Annotation of qemu/roms/ipxe/src/interface/smbios/smbios.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (C) 2007 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 <stdint.h>
                     22: #include <string.h>
                     23: #include <errno.h>
                     24: #include <assert.h>
                     25: #include <ipxe/uaccess.h>
                     26: #include <ipxe/smbios.h>
                     27: 
                     28: /** @file
                     29:  *
                     30:  * System Management BIOS
                     31:  *
                     32:  */
                     33: 
                     34: /** SMBIOS entry point descriptor */
                     35: static struct smbios smbios = {
                     36:        .address = UNULL,
                     37: };
                     38: 
                     39: /**
                     40:  * Find SMBIOS strings terminator
                     41:  *
                     42:  * @v offset           Offset to start of strings
                     43:  * @ret offset         Offset to strings terminator, or 0 if not found
                     44:  */
                     45: static size_t find_strings_terminator ( size_t offset ) {
                     46:        size_t max_offset = ( smbios.len - 2 );
                     47:        uint16_t nulnul;
                     48: 
                     49:        for ( ; offset <= max_offset ; offset++ ) {
                     50:                copy_from_user ( &nulnul, smbios.address, offset, 2 );
                     51:                if ( nulnul == 0 )
                     52:                        return ( offset + 1 );
                     53:        }
                     54:        return 0;
                     55: }
                     56: 
                     57: /**
                     58:  * Find specific structure type within SMBIOS
                     59:  *
                     60:  * @v type             Structure type to search for
                     61:  * @v structure                SMBIOS structure descriptor to fill in
                     62:  * @ret rc             Return status code
                     63:  */
                     64: int find_smbios_structure ( unsigned int type,
                     65:                            struct smbios_structure *structure ) {
                     66:        unsigned int count = 0;
                     67:        size_t offset = 0;
                     68:        size_t strings_offset;
                     69:        size_t terminator_offset;
                     70:        int rc;
                     71: 
                     72:        /* Find SMBIOS */
                     73:        if ( ( smbios.address == UNULL ) &&
                     74:             ( ( rc = find_smbios ( &smbios ) ) != 0 ) )
                     75:                return rc;
                     76:        assert ( smbios.address != UNULL );
                     77: 
                     78:        /* Scan through list of structures */
                     79:        while ( ( ( offset + sizeof ( structure->header ) ) < smbios.len )
                     80:                && ( count < smbios.count ) ) {
                     81: 
                     82:                /* Read next SMBIOS structure header */
                     83:                copy_from_user ( &structure->header, smbios.address, offset,
                     84:                                 sizeof ( structure->header ) );
                     85: 
                     86:                /* Determine start and extent of strings block */
                     87:                strings_offset = ( offset + structure->header.len );
                     88:                if ( strings_offset > smbios.len ) {
                     89:                        DBG ( "SMBIOS structure at offset %zx with length "
                     90:                              "%x extends beyond SMBIOS\n", offset,
                     91:                              structure->header.len );
                     92:                        return -ENOENT;
                     93:                }
                     94:                terminator_offset = find_strings_terminator ( strings_offset );
                     95:                if ( ! terminator_offset ) {
                     96:                        DBG ( "SMBIOS structure at offset %zx has "
                     97:                              "unterminated strings section\n", offset );
                     98:                        return -ENOENT;
                     99:                }
                    100:                structure->strings_len = ( terminator_offset - strings_offset);
                    101: 
                    102:                DBG ( "SMBIOS structure at offset %zx has type %d, length %x, "
                    103:                      "strings length %zx\n", offset, structure->header.type,
                    104:                      structure->header.len, structure->strings_len );
                    105: 
                    106:                /* If this is the structure we want, return */
                    107:                if ( structure->header.type == type ) {
                    108:                        structure->offset = offset;
                    109:                        return 0;
                    110:                }
                    111: 
                    112:                /* Move to next SMBIOS structure */
                    113:                offset = ( terminator_offset + 1 );
                    114:                count++;
                    115:        }
                    116: 
                    117:        DBG ( "SMBIOS structure type %d not found\n", type );
                    118:        return -ENOENT;
                    119: }
                    120: 
                    121: /**
                    122:  * Copy SMBIOS structure
                    123:  *
                    124:  * @v structure                SMBIOS structure descriptor
                    125:  * @v data             Buffer to hold SMBIOS structure
                    126:  * @v len              Length of buffer
                    127:  * @ret rc             Return status code
                    128:  */
                    129: int read_smbios_structure ( struct smbios_structure *structure,
                    130:                            void *data, size_t len ) {
                    131: 
                    132:        assert ( smbios.address != UNULL );
                    133: 
                    134:        if ( len > structure->header.len )
                    135:                len = structure->header.len;
                    136:        copy_from_user ( data, smbios.address, structure->offset, len );
                    137:        return 0;
                    138: }
                    139: 
                    140: /**
                    141:  * Find indexed string within SMBIOS structure
                    142:  *
                    143:  * @v structure                SMBIOS structure descriptor
                    144:  * @v index            String index
                    145:  * @v data             Buffer for string
                    146:  * @v len              Length of string buffer
                    147:  * @ret rc             Length of string, or negative error
                    148:  */
                    149: int read_smbios_string ( struct smbios_structure *structure,
                    150:                         unsigned int index, void *data, size_t len ) {
                    151:        size_t strings_start = ( structure->offset + structure->header.len );
                    152:        size_t strings_end = ( strings_start + structure->strings_len );
                    153:        size_t offset;
                    154:        size_t string_len;
                    155: 
                    156:        assert ( smbios.address != UNULL );
                    157: 
                    158:        /* String numbers start at 1 (0 is used to indicate "no string") */
                    159:        if ( ! index )
                    160:                return -ENOENT;
                    161: 
                    162:        for ( offset = strings_start ; offset < strings_end ;
                    163:              offset += ( string_len + 1 ) ) {
                    164:                /* Get string length.  This is known safe, since the
                    165:                 * smbios_strings struct is constructed so as to
                    166:                 * always end on a string boundary.
                    167:                 */
                    168:                string_len = strlen_user ( smbios.address, offset );
                    169:                if ( --index == 0 ) {
                    170:                        /* Copy string, truncating as necessary. */
                    171:                        if ( len > string_len )
                    172:                                len = string_len;
                    173:                        copy_from_user ( data, smbios.address, offset, len );
                    174:                        return string_len;
                    175:                }
                    176:        }
                    177: 
                    178:        DBG ( "SMBIOS string index %d not found\n", index );
                    179:        return -ENOENT;
                    180: }

unix.superglobalmegacorp.com

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