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

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

unix.superglobalmegacorp.com

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