Annotation of qemu/roms/ipxe/src/drivers/nvs/nvsvpd.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (C) 2010 Michael Brown <[email protected]>.
                      3:  *
                      4:  * This program is free software; you can redistribute it and/or
                      5:  * modify it under the terms of the GNU General Public License as
                      6:  * published by the Free Software Foundation; either version 2 of the
                      7:  * License, or any later version.
                      8:  *
                      9:  * This program is distributed in the hope that it will be useful, but
                     10:  * WITHOUT ANY WARRANTY; without even the implied warranty of
                     11:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     12:  * General Public License for more details.
                     13:  *
                     14:  * You should have received a copy of the GNU General Public License
                     15:  * along with this program; if not, write to the Free Software
                     16:  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
                     17:  */
                     18: 
                     19: FILE_LICENCE ( GPL2_OR_LATER );
                     20: 
                     21: #include <stdio.h>
                     22: #include <errno.h>
                     23: #include <ipxe/nvs.h>
                     24: #include <ipxe/pci.h>
                     25: #include <ipxe/pcivpd.h>
                     26: #include <ipxe/nvo.h>
                     27: #include <ipxe/nvsvpd.h>
                     28: 
                     29: /** @file
                     30:  *
                     31:  * Non-Volatile Storage using Vital Product Data
                     32:  *
                     33:  */
                     34: 
                     35: /**
                     36:  * Read from VPD field
                     37:  *
                     38:  * @v nvs              NVS device
                     39:  * @v field            VPD field descriptor
                     40:  * @v data             Data buffer
                     41:  * @v len              Length of data buffer
                     42:  * @ret rc             Return status code
                     43:  */
                     44: static int nvs_vpd_read ( struct nvs_device *nvs, unsigned int field,
                     45:                          void *data, size_t len ) {
                     46:        struct nvs_vpd_device *nvsvpd =
                     47:                container_of ( nvs, struct nvs_vpd_device, nvs );
                     48:        struct pci_device *pci = nvsvpd->vpd.pci;
                     49:        unsigned int address;
                     50:        size_t max_len;
                     51:        int rc;
                     52: 
                     53:        /* Allow reading non-existent field */
                     54:        if ( len == 0 )
                     55:                return 0;
                     56: 
                     57:        /* Locate VPD field */
                     58:        if ( ( rc = pci_vpd_find ( &nvsvpd->vpd, field, &address,
                     59:                                   &max_len ) ) != 0 ) {
                     60:                DBGC ( pci, PCI_FMT " NVS VPD could not locate field "
                     61:                       PCI_VPD_FIELD_FMT ": %s\n", PCI_ARGS ( pci ),
                     62:                       PCI_VPD_FIELD_ARGS ( field ), strerror ( rc ) );
                     63:                return rc;
                     64:        }
                     65: 
                     66:        /* Sanity check */
                     67:        if ( len > max_len ) {
                     68:                DBGC ( pci, PCI_FMT " NVS VPD cannot read %#02zx bytes "
                     69:                       "beyond field " PCI_VPD_FIELD_FMT " at [%04x,%04zx)\n",
                     70:                       PCI_ARGS ( pci ), len, PCI_VPD_FIELD_ARGS ( field ),
                     71:                       address, ( address + max_len ) );
                     72:                return -ENXIO;
                     73:        }
                     74: 
                     75:        /* Read from VPD field */
                     76:        if ( ( rc = pci_vpd_read ( &nvsvpd->vpd, address, data, len ) ) != 0 ) {
                     77:                DBGC ( pci, PCI_FMT " NVS VPD could not read field "
                     78:                       PCI_VPD_FIELD_FMT " at [%04x,%04zx): %s\n",
                     79:                       PCI_ARGS ( pci ), PCI_VPD_FIELD_ARGS ( field ),
                     80:                       address, ( address + len ), strerror ( rc ) );
                     81:                return rc;
                     82:        }
                     83: 
                     84:        return 0;
                     85: }
                     86: 
                     87: /**
                     88:  * Write to VPD field
                     89:  *
                     90:  * @v nvs              NVS device
                     91:  * @v field            VPD field descriptor
                     92:  * @v data             Data buffer
                     93:  * @v len              Length of data buffer
                     94:  * @ret rc             Return status code
                     95:  */
                     96: static int nvs_vpd_write ( struct nvs_device *nvs, unsigned int field,
                     97:                           const void *data, size_t len ) {
                     98:        struct nvs_vpd_device *nvsvpd =
                     99:                container_of ( nvs, struct nvs_vpd_device, nvs );
                    100:        struct pci_device *pci = nvsvpd->vpd.pci;
                    101:        unsigned int address;
                    102:        size_t max_len;
                    103:        int rc;
                    104: 
                    105:        /* Locate VPD field */
                    106:        if ( ( rc = pci_vpd_find ( &nvsvpd->vpd, field, &address,
                    107:                                   &max_len ) ) != 0 ) {
                    108:                DBGC ( pci, PCI_FMT " NVS VPD could not locate field "
                    109:                       PCI_VPD_FIELD_FMT ": %s\n", PCI_ARGS ( pci ),
                    110:                       PCI_VPD_FIELD_ARGS ( field ), strerror ( rc ) );
                    111:                return rc;
                    112:        }
                    113: 
                    114:        /* Sanity check */
                    115:        if ( len > max_len ) {
                    116:                DBGC ( pci, PCI_FMT " NVS VPD cannot write %#02zx bytes "
                    117:                       "beyond field " PCI_VPD_FIELD_FMT " at [%04x,%04zx)\n",
                    118:                       PCI_ARGS ( pci ), len, PCI_VPD_FIELD_ARGS ( field ),
                    119:                       address, ( address + max_len ) );
                    120:                return -ENXIO;
                    121:        }
                    122: 
                    123:        /* Write field */
                    124:        if ( ( rc = pci_vpd_write ( &nvsvpd->vpd, address, data,
                    125:                                    len ) ) != 0 ) {
                    126:                DBGC ( pci, PCI_FMT " NVS VPD could not write field "
                    127:                       PCI_VPD_FIELD_FMT " at [%04x,%04zx): %s\n",
                    128:                       PCI_ARGS ( pci ), PCI_VPD_FIELD_ARGS ( field ),
                    129:                       address, ( address + len ), strerror ( rc ) );
                    130:                return rc;
                    131:        }
                    132: 
                    133:        return 0;
                    134: }
                    135: 
                    136: /**
                    137:  * Resize VPD field
                    138:  *
                    139:  * @v nvs              NVS device
                    140:  * @v field            VPD field descriptor
                    141:  * @v data             Data buffer
                    142:  * @v len              Length of data buffer
                    143:  * @ret rc             Return status code
                    144:  */
                    145: static int nvs_vpd_resize ( struct nvs_device *nvs, unsigned int field,
                    146:                            size_t len ) {
                    147:        struct nvs_vpd_device *nvsvpd =
                    148:                container_of ( nvs, struct nvs_vpd_device, nvs );
                    149:        struct pci_device *pci = nvsvpd->vpd.pci;
                    150:        unsigned int address;
                    151:        int rc;
                    152: 
                    153:        /* Resize field */
                    154:        if ( ( rc = pci_vpd_resize ( &nvsvpd->vpd, field, len,
                    155:                                     &address ) ) != 0 ) {
                    156:                DBGC ( pci, PCI_FMT " NVS VPD could not resize field "
                    157:                       PCI_VPD_FIELD_FMT " to %#02zx bytes: %s\n",
                    158:                       PCI_ARGS ( pci ), PCI_VPD_FIELD_ARGS ( field ),
                    159:                       len, strerror ( rc ) );
                    160:                return rc;
                    161:        }
                    162: 
                    163:        return 0;
                    164: }
                    165: 
                    166: /**
                    167:  * Initialise NVS VPD device
                    168:  *
                    169:  * @v nvsvpd           NVS VPD device
                    170:  * @v pci              PCI device
                    171:  * @ret rc             Return status code
                    172:  */
                    173: int nvs_vpd_init ( struct nvs_vpd_device *nvsvpd, struct pci_device *pci ) {
                    174:        int rc;
                    175: 
                    176:        /* Initialise VPD device */
                    177:        if ( ( rc = pci_vpd_init ( &nvsvpd->vpd, pci ) ) != 0 ) {
                    178:                DBGC ( pci, PCI_FMT " NVS could not initialise "
                    179:                       "VPD: %s\n", PCI_ARGS ( pci ), strerror ( rc ) );
                    180:                return rc;
                    181:        }
                    182: 
                    183:        /* Initialise NVS device */
                    184:        nvsvpd->nvs.read = nvs_vpd_read;
                    185:        nvsvpd->nvs.write = nvs_vpd_write;
                    186: 
                    187:        return 0;
                    188: }
                    189: 
                    190: /**
                    191:  * Resize non-volatile option storage within NVS VPD device
                    192:  *
                    193:  * @v nvo              Non-volatile options block
                    194:  * @v len              New length
                    195:  * @ret rc             Return status code
                    196:  */
                    197: static int nvs_vpd_nvo_resize ( struct nvo_block *nvo, size_t len ) {
                    198:        int rc;
                    199: 
                    200:        /* Resize VPD field */
                    201:        if ( ( rc = nvs_vpd_resize ( nvo->nvs, nvo->address, len ) ) != 0 )
                    202:                return rc;
                    203: 
                    204:        return 0;
                    205: }
                    206: 
                    207: /**
                    208:  * Initialise non-volatile option storage within NVS VPD device
                    209:  *
                    210:  * @v nvsvpd           NVS VPD device
                    211:  * @v field            VPD field descriptor
                    212:  * @v nvo              Non-volatile options block
                    213:  * @v refcnt           Containing object reference counter, or NULL
                    214:  */
                    215: void nvs_vpd_nvo_init ( struct nvs_vpd_device *nvsvpd, unsigned int field,
                    216:                        struct nvo_block *nvo, struct refcnt *refcnt ) {
                    217:        struct pci_device *pci = nvsvpd->vpd.pci;
                    218:        unsigned int address;
                    219:        size_t len;
                    220:        int rc;
                    221: 
                    222:        /* Locate VPD field, if present */
                    223:        if ( ( rc = pci_vpd_find ( &nvsvpd->vpd, field, &address,
                    224:                                   &len ) ) != 0 ) {
                    225:                DBGC ( pci, PCI_FMT " NVS VPD field " PCI_VPD_FIELD_FMT
                    226:                       " not present; assuming empty\n",
                    227:                       PCI_ARGS ( pci ), PCI_VPD_FIELD_ARGS ( field ) );
                    228:                len = 0;
                    229:        }
                    230: 
                    231:        /* Initialise non-volatile options block */
                    232:        nvo_init ( nvo, &nvsvpd->nvs, field, len, nvs_vpd_nvo_resize, refcnt );
                    233: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.