Annotation of qemu/roms/ipxe/src/interface/smbios/smbios.c, revision 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.