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

1.1       root        1: // smbios table generation (on emulators)
                      2: //
                      3: // Copyright (C) 2008,2009  Kevin O'Connor <[email protected]>
                      4: // Copyright (C) 2006 Fabrice Bellard
                      5: //
                      6: // This file may be distributed under the terms of the GNU LGPLv3 license.
                      7: 
                      8: #include "util.h" // dprintf
                      9: #include "biosvar.h" // GET_EBDA
                     10: #include "paravirt.h" // qemu_cfg_smbios_load_field
                     11: #include "smbios.h" // struct smbios_entry_point
                     12: 
                     13: static void
                     14: smbios_entry_point_init(u16 max_structure_size,
                     15:                         u16 structure_table_length,
                     16:                         void *structure_table_address,
                     17:                         u16 number_of_structures)
                     18: {
                     19:     struct smbios_entry_point *ep = malloc_fseg(sizeof(*ep));
                     20:     if (! ep) {
                     21:         dprintf(1, "No space for smbios entry table!\n");
                     22:         return;
                     23:     }
                     24: 
                     25:     memcpy(ep->anchor_string, "_SM_", 4);
                     26:     ep->length = 0x1f;
                     27:     ep->smbios_major_version = 2;
                     28:     ep->smbios_minor_version = 4;
                     29:     ep->max_structure_size = max_structure_size;
                     30:     ep->entry_point_revision = 0;
                     31:     memset(ep->formatted_area, 0, 5);
                     32:     memcpy(ep->intermediate_anchor_string, "_DMI_", 5);
                     33: 
                     34:     ep->structure_table_length = structure_table_length;
                     35:     ep->structure_table_address = (u32)structure_table_address;
                     36:     ep->number_of_structures = number_of_structures;
                     37:     ep->smbios_bcd_revision = 0x24;
                     38: 
                     39:     ep->checksum -= checksum(ep, 0x10);
                     40: 
                     41:     ep->intermediate_checksum -= checksum((void*)ep + 0x10, ep->length - 0x10);
                     42: 
                     43:     dprintf(1, "SMBIOS ptr=%p table=%p\n", ep, structure_table_address);
                     44: }
                     45: 
                     46: #define load_str_field_with_default(type, field, def)                   \
                     47:     do {                                                                \
                     48:         size = qemu_cfg_smbios_load_field(type,                         \
                     49:                                  offsetof(struct smbios_type_##type,    \
                     50:                                           field), end);                 \
                     51:         if (size > 0) {                                                 \
                     52:             end += size;                                                \
                     53:         } else {                                                        \
                     54:             memcpy(end, def, sizeof(def));                              \
                     55:             end += sizeof(def);                                         \
                     56:         }                                                               \
                     57:         p->field = ++str_index;                                         \
                     58:     } while (0)
                     59: 
                     60: #define load_str_field_or_skip(type, field) \
                     61:     do {                                                                \
                     62:         size = qemu_cfg_smbios_load_field(type,                         \
                     63:                                  offsetof(struct smbios_type_##type,    \
                     64:                                           field), end);                 \
                     65:         if (size > 0) {                                                 \
                     66:             end += size;                                                \
                     67:             p->field = ++str_index;                                     \
                     68:         } else {                                                        \
                     69:             p->field = 0;                                               \
                     70:         }                                                               \
                     71:     } while (0)
                     72: 
                     73: /* Type 0 -- BIOS Information */
                     74: #define RELEASE_DATE_STR "01/01/2007"
                     75: static void *
                     76: smbios_init_type_0(void *start)
                     77: {
                     78:     struct smbios_type_0 *p = (struct smbios_type_0 *)start;
                     79:     char *end = (char *)start + sizeof(struct smbios_type_0);
                     80:     size_t size;
                     81:     int str_index = 0;
                     82: 
                     83:     p->header.type = 0;
                     84:     p->header.length = sizeof(struct smbios_type_0);
                     85:     p->header.handle = 0;
                     86: 
                     87:     load_str_field_with_default(0, vendor_str, CONFIG_APPNAME);
                     88:     load_str_field_with_default(0, bios_version_str, CONFIG_APPNAME);
                     89: 
                     90:     p->bios_starting_address_segment = 0xe800;
                     91: 
                     92:     load_str_field_with_default(0, bios_release_date_str, RELEASE_DATE_STR);
                     93: 
                     94:     p->bios_rom_size = 0; /* FIXME */
                     95: 
                     96:     memset(p->bios_characteristics, 0, 8);
                     97:     p->bios_characteristics[0] = 0x08; /* BIOS characteristics not supported */
                     98:     p->bios_characteristics_extension_bytes[0] = 0;
                     99:     /* Enable targeted content distribution. Needed for SVVP */
                    100:     p->bios_characteristics_extension_bytes[1] = 4;
                    101: 
                    102:     if (!qemu_cfg_smbios_load_field(0, offsetof(struct smbios_type_0,
                    103:                                                 system_bios_major_release),
                    104:                                     &p->system_bios_major_release))
                    105:         p->system_bios_major_release = 1;
                    106: 
                    107:     if (!qemu_cfg_smbios_load_field(0, offsetof(struct smbios_type_0,
                    108:                                                 system_bios_minor_release),
                    109:                                     &p->system_bios_minor_release))
                    110:         p->system_bios_minor_release = 0;
                    111: 
                    112:     p->embedded_controller_major_release = 0xff;
                    113:     p->embedded_controller_minor_release = 0xff;
                    114: 
                    115:     *end = 0;
                    116:     end++;
                    117: 
                    118:     return end;
                    119: }
                    120: 
                    121: /* Type 1 -- System Information */
                    122: static void *
                    123: smbios_init_type_1(void *start)
                    124: {
                    125:     struct smbios_type_1 *p = (struct smbios_type_1 *)start;
                    126:     char *end = (char *)start + sizeof(struct smbios_type_1);
                    127:     size_t size;
                    128:     int str_index = 0;
                    129: 
                    130:     p->header.type = 1;
                    131:     p->header.length = sizeof(struct smbios_type_1);
                    132:     p->header.handle = 0x100;
                    133: 
                    134:     load_str_field_with_default(1, manufacturer_str, CONFIG_APPNAME);
                    135:     load_str_field_with_default(1, product_name_str, CONFIG_APPNAME);
                    136:     load_str_field_or_skip(1, version_str);
                    137:     load_str_field_or_skip(1, serial_number_str);
                    138: 
                    139:     size = qemu_cfg_smbios_load_field(1, offsetof(struct smbios_type_1,
                    140:                                                   uuid), &p->uuid);
                    141:     if (size == 0)
                    142:         memset(p->uuid, 0, 16);
                    143: 
                    144:     p->wake_up_type = 0x06; /* power switch */
                    145: 
                    146:     load_str_field_or_skip(1, sku_number_str);
                    147:     load_str_field_or_skip(1, family_str);
                    148: 
                    149:     *end = 0;
                    150:     end++;
                    151:     if (!str_index) {
                    152:         *end = 0;
                    153:         end++;
                    154:     }
                    155: 
                    156:     return end;
                    157: }
                    158: 
                    159: /* Type 3 -- System Enclosure */
                    160: static void *
                    161: smbios_init_type_3(void *start)
                    162: {
                    163:     struct smbios_type_3 *p = (struct smbios_type_3 *)start;
                    164: 
                    165:     p->header.type = 3;
                    166:     p->header.length = sizeof(struct smbios_type_3);
                    167:     p->header.handle = 0x300;
                    168: 
                    169:     p->manufacturer_str = 1;
                    170:     p->type = 0x01; /* other */
                    171:     p->version_str = 0;
                    172:     p->serial_number_str = 0;
                    173:     p->asset_tag_number_str = 0;
                    174:     p->boot_up_state = 0x03; /* safe */
                    175:     p->power_supply_state = 0x03; /* safe */
                    176:     p->thermal_state = 0x03; /* safe */
                    177:     p->security_status = 0x02; /* unknown */
                    178:     p->oem_defined = 0;
                    179:     p->height = 0;
                    180:     p->number_of_power_cords = 0;
                    181:     p->contained_element_count = 0;
                    182: 
                    183:     start += sizeof(struct smbios_type_3);
                    184:     memcpy((char *)start, CONFIG_APPNAME"\0\0", sizeof(CONFIG_APPNAME) + 1);
                    185: 
                    186:     return start + sizeof(CONFIG_APPNAME) + 1;
                    187: }
                    188: 
                    189: /* Type 4 -- Processor Information */
                    190: static void *
                    191: smbios_init_type_4(void *start, unsigned int cpu_number)
                    192: {
                    193:     struct smbios_type_4 *p = (struct smbios_type_4 *)start;
                    194: 
                    195:     p->header.type = 4;
                    196:     p->header.length = sizeof(struct smbios_type_4);
                    197:     p->header.handle = 0x400 + cpu_number;
                    198: 
                    199:     p->socket_designation_str = 1;
                    200:     p->processor_type = 0x03; /* CPU */
                    201:     p->processor_family = 0x01; /* other */
                    202:     p->processor_manufacturer_str = 2;
                    203: 
                    204:     u32 cpuid_signature, ebx, ecx, cpuid_features;
                    205:     cpuid(1, &cpuid_signature, &ebx, &ecx, &cpuid_features);
                    206:     p->processor_id[0] = cpuid_signature;
                    207:     p->processor_id[1] = cpuid_features;
                    208: 
                    209:     p->processor_version_str = 0;
                    210:     p->voltage = 0;
                    211:     p->external_clock = 0;
                    212: 
                    213:     p->max_speed = 2000;
                    214:     p->current_speed = 2000;
                    215: 
                    216:     p->status = 0x41; /* socket populated, CPU enabled */
                    217:     p->processor_upgrade = 0x01; /* other */
                    218: 
                    219:     p->l1_cache_handle = 0xffff; /* cache information structure not provided */
                    220:     p->l2_cache_handle = 0xffff;
                    221:     p->l3_cache_handle = 0xffff;
                    222: 
                    223:     start += sizeof(struct smbios_type_4);
                    224: 
                    225:     snprintf((char*)start, 6, "CPU%2x", cpu_number);
                    226:     start += 6;
                    227:     memcpy((char *)start, CONFIG_APPNAME"\0\0", sizeof(CONFIG_APPNAME) + 1);
                    228: 
                    229:     return start + sizeof(CONFIG_APPNAME) + 1;
                    230: }
                    231: 
                    232: /* Type 16 -- Physical Memory Array */
                    233: static void *
                    234: smbios_init_type_16(void *start, u32 memory_size_mb, int nr_mem_devs)
                    235: {
                    236:     struct smbios_type_16 *p = (struct smbios_type_16*)start;
                    237: 
                    238:     p->header.type = 16;
                    239:     p->header.length = sizeof(struct smbios_type_16);
                    240:     p->header.handle = 0x1000;
                    241: 
                    242:     p->location = 0x01; /* other */
                    243:     p->use = 0x03; /* system memory */
                    244:     p->error_correction = 0x06; /* Multi-bit ECC to make Microsoft happy */
                    245:     p->maximum_capacity = memory_size_mb * 1024;
                    246:     p->memory_error_information_handle = 0xfffe; /* none provided */
                    247:     p->number_of_memory_devices = nr_mem_devs;
                    248: 
                    249:     start += sizeof(struct smbios_type_16);
                    250:     *((u16 *)start) = 0;
                    251: 
                    252:     return start + 2;
                    253: }
                    254: 
                    255: /* Type 17 -- Memory Device */
                    256: static void *
                    257: smbios_init_type_17(void *start, u32 memory_size_mb, int instance)
                    258: {
                    259:     struct smbios_type_17 *p = (struct smbios_type_17 *)start;
                    260: 
                    261:     p->header.type = 17;
                    262:     p->header.length = sizeof(struct smbios_type_17);
                    263:     p->header.handle = 0x1100 + instance;
                    264: 
                    265:     p->physical_memory_array_handle = 0x1000;
                    266:     p->total_width = 64;
                    267:     p->data_width = 64;
                    268: /* TODO: should assert in case something is wrong   ASSERT((memory_size_mb & ~0x7fff) == 0); */
                    269:     p->size = memory_size_mb;
                    270:     p->form_factor = 0x09; /* DIMM */
                    271:     p->device_set = 0;
                    272:     p->device_locator_str = 1;
                    273:     p->bank_locator_str = 0;
                    274:     p->memory_type = 0x07; /* RAM */
                    275:     p->type_detail = 0;
                    276: 
                    277:     start += sizeof(struct smbios_type_17);
                    278:     memcpy((char *)start, "DIMM 0", 7);
                    279:     ((char*)start)[5] += instance;
                    280:     start += 7;
                    281:     *((u8 *)start) = 0;
                    282: 
                    283:     return start+1;
                    284: }
                    285: 
                    286: /* Type 19 -- Memory Array Mapped Address */
                    287: static void *
                    288: smbios_init_type_19(void *start, u32 memory_size_mb, int instance)
                    289: {
                    290:     struct smbios_type_19 *p = (struct smbios_type_19 *)start;
                    291: 
                    292:     p->header.type = 19;
                    293:     p->header.length = sizeof(struct smbios_type_19);
                    294:     p->header.handle = 0x1300 + instance;
                    295: 
                    296:     p->starting_address = instance << 24;
                    297:     p->ending_address = p->starting_address + (memory_size_mb << 10) - 1;
                    298:     p->memory_array_handle = 0x1000;
                    299:     p->partition_width = 1;
                    300: 
                    301:     start += sizeof(struct smbios_type_19);
                    302:     *((u16 *)start) = 0;
                    303: 
                    304:     return start + 2;
                    305: }
                    306: 
                    307: /* Type 20 -- Memory Device Mapped Address */
                    308: static void *
                    309: smbios_init_type_20(void *start, u32 memory_size_mb, int instance)
                    310: {
                    311:     struct smbios_type_20 *p = (struct smbios_type_20 *)start;
                    312: 
                    313:     p->header.type = 20;
                    314:     p->header.length = sizeof(struct smbios_type_20);
                    315:     p->header.handle = 0x1400 + instance;
                    316: 
                    317:     p->starting_address = instance << 24;
                    318:     p->ending_address = p->starting_address + (memory_size_mb << 10) - 1;
                    319:     p->memory_device_handle = 0x1100 + instance;
                    320:     p->memory_array_mapped_address_handle = 0x1300 + instance;
                    321:     p->partition_row_position = 1;
                    322:     p->interleave_position = 0;
                    323:     p->interleaved_data_depth = 0;
                    324: 
                    325:     start += sizeof(struct smbios_type_20);
                    326: 
                    327:     *((u16 *)start) = 0;
                    328:     return start+2;
                    329: }
                    330: 
                    331: /* Type 32 -- System Boot Information */
                    332: static void *
                    333: smbios_init_type_32(void *start)
                    334: {
                    335:     struct smbios_type_32 *p = (struct smbios_type_32 *)start;
                    336: 
                    337:     p->header.type = 32;
                    338:     p->header.length = sizeof(struct smbios_type_32);
                    339:     p->header.handle = 0x2000;
                    340:     memset(p->reserved, 0, 6);
                    341:     p->boot_status = 0; /* no errors detected */
                    342: 
                    343:     start += sizeof(struct smbios_type_32);
                    344:     *((u16 *)start) = 0;
                    345: 
                    346:     return start+2;
                    347: }
                    348: 
                    349: /* Type 127 -- End of Table */
                    350: static void *
                    351: smbios_init_type_127(void *start)
                    352: {
                    353:     struct smbios_type_127 *p = (struct smbios_type_127 *)start;
                    354: 
                    355:     p->header.type = 127;
                    356:     p->header.length = sizeof(struct smbios_type_127);
                    357:     p->header.handle = 0x7f00;
                    358: 
                    359:     start += sizeof(struct smbios_type_127);
                    360:     *((u16 *)start) = 0;
                    361: 
                    362:     return start + 2;
                    363: }
                    364: 
                    365: void
                    366: smbios_init(void)
                    367: {
                    368:     if (! CONFIG_SMBIOS)
                    369:         return;
                    370: 
                    371:     dprintf(3, "init SMBIOS tables\n");
                    372: 
                    373:     char *start = malloc_high(2048); // XXX - determine real size
                    374:     if (! start) {
                    375:         dprintf(1, "No memory for smbios tables\n");
                    376:         return;
                    377:     }
                    378: 
                    379:     u32 nr_structs = 0, max_struct_size = 0;
                    380:     char *q, *p = start, *end = start + 2048 - sizeof(struct smbios_type_127);
                    381: 
                    382: #define add_struct(type, args...)                                       \
                    383:     do {                                                                \
                    384:         if (!qemu_cfg_smbios_load_external(type, &p, &nr_structs,       \
                    385:                                            &max_struct_size, end)) {    \
                    386:             q = smbios_init_type_##type(args);                          \
                    387:             nr_structs++;                                               \
                    388:             if ((q - p) > max_struct_size)                              \
                    389:                 max_struct_size = q - p;                                \
                    390:             p = q;                                                      \
                    391:         }                                                               \
                    392:     } while (0)
                    393: 
                    394:     add_struct(0, p);
                    395:     add_struct(1, p);
                    396:     add_struct(3, p);
                    397: 
                    398:     int cpu_num;
                    399:     for (cpu_num = 1; cpu_num <= MaxCountCPUs; cpu_num++)
                    400:         add_struct(4, p, cpu_num);
                    401:     u64 memsize = RamSizeOver4G;
                    402:     if (memsize)
                    403:         memsize += 0x100000000ull;
                    404:     else
                    405:         memsize = RamSize;
                    406:     memsize = memsize / (1024 * 1024);
                    407:     int nr_mem_devs = (memsize + 0x3fff) >> 14;
                    408:     add_struct(16, p, memsize, nr_mem_devs);
                    409:     int i;
                    410:     for (i = 0; i < nr_mem_devs; i++) {
                    411:         u32 dev_memsize = ((i == (nr_mem_devs - 1))
                    412:                            ? (((memsize-1) & 0x3fff)+1) : 0x4000);
                    413:         add_struct(17, p, dev_memsize, i);
                    414:         add_struct(19, p, dev_memsize, i);
                    415:         add_struct(20, p, dev_memsize, i);
                    416:     }
                    417: 
                    418:     add_struct(32, p);
                    419:     /* Add any remaining provided entries before the end marker */
                    420:     for (i = 0; i < 256; i++)
                    421:         qemu_cfg_smbios_load_external(i, &p, &nr_structs, &max_struct_size,
                    422:                                       end);
                    423:     add_struct(127, p);
                    424: 
                    425: #undef add_struct
                    426: 
                    427:     smbios_entry_point_init(max_struct_size, p - start, start, nr_structs);
                    428: }

unix.superglobalmegacorp.com

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