qemu/hw/smbios/smbios.c
<<
>>
Prefs
   1/*
   2 * SMBIOS Support
   3 *
   4 * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
   5 * Copyright (C) 2013 Red Hat, Inc.
   6 *
   7 * Authors:
   8 *  Alex Williamson <alex.williamson@hp.com>
   9 *  Markus Armbruster <armbru@redhat.com>
  10 *
  11 * This work is licensed under the terms of the GNU GPL, version 2.  See
  12 * the COPYING file in the top-level directory.
  13 *
  14 * Contributions after 2012-01-13 are licensed under the terms of the
  15 * GNU GPL, version 2 or (at your option) any later version.
  16 */
  17
  18#include "qemu/osdep.h"
  19#include "qemu/units.h"
  20#include "qapi/error.h"
  21#include "qemu/config-file.h"
  22#include "qemu/error-report.h"
  23#include "qemu/module.h"
  24#include "qemu/option.h"
  25#include "sysemu/sysemu.h"
  26#include "qemu/uuid.h"
  27#include "sysemu/cpus.h"
  28#include "hw/firmware/smbios.h"
  29#include "hw/loader.h"
  30#include "hw/boards.h"
  31#include "exec/cpu-common.h"
  32#include "smbios_build.h"
  33
  34/* legacy structures and constants for <= 2.0 machines */
  35struct smbios_header {
  36    uint16_t length;
  37    uint8_t type;
  38} QEMU_PACKED;
  39
  40struct smbios_field {
  41    struct smbios_header header;
  42    uint8_t type;
  43    uint16_t offset;
  44    uint8_t data[];
  45} QEMU_PACKED;
  46
  47struct smbios_table {
  48    struct smbios_header header;
  49    uint8_t data[];
  50} QEMU_PACKED;
  51
  52#define SMBIOS_FIELD_ENTRY 0
  53#define SMBIOS_TABLE_ENTRY 1
  54
  55static uint8_t *smbios_entries;
  56static size_t smbios_entries_len;
  57static bool smbios_legacy = true;
  58static bool smbios_uuid_encoded = true;
  59/* end: legacy structures & constants for <= 2.0 machines */
  60
  61
  62uint8_t *smbios_tables;
  63size_t smbios_tables_len;
  64unsigned smbios_table_max;
  65unsigned smbios_table_cnt;
  66static SmbiosEntryPointType smbios_ep_type = SMBIOS_ENTRY_POINT_21;
  67
  68static SmbiosEntryPoint ep;
  69
  70static int smbios_type4_count = 0;
  71static bool smbios_immutable;
  72static bool smbios_have_defaults;
  73static uint32_t smbios_cpuid_version, smbios_cpuid_features, smbios_smp_sockets;
  74
  75static DECLARE_BITMAP(have_binfile_bitmap, SMBIOS_MAX_TYPE+1);
  76static DECLARE_BITMAP(have_fields_bitmap, SMBIOS_MAX_TYPE+1);
  77
  78static struct {
  79    const char *vendor, *version, *date;
  80    bool have_major_minor, uefi;
  81    uint8_t major, minor;
  82} type0;
  83
  84static struct {
  85    const char *manufacturer, *product, *version, *serial, *sku, *family;
  86    /* uuid is in qemu_uuid */
  87} type1;
  88
  89static struct {
  90    const char *manufacturer, *product, *version, *serial, *asset, *location;
  91} type2;
  92
  93static struct {
  94    const char *manufacturer, *version, *serial, *asset, *sku;
  95} type3;
  96
  97static struct {
  98    const char *sock_pfx, *manufacturer, *version, *serial, *asset, *part;
  99} type4;
 100
 101static struct {
 102    size_t nvalues;
 103    const char **values;
 104} type11;
 105
 106static struct {
 107    const char *loc_pfx, *bank, *manufacturer, *serial, *asset, *part;
 108    uint16_t speed;
 109} type17;
 110
 111static QemuOptsList qemu_smbios_opts = {
 112    .name = "smbios",
 113    .head = QTAILQ_HEAD_INITIALIZER(qemu_smbios_opts.head),
 114    .desc = {
 115        /*
 116         * no elements => accept any params
 117         * validation will happen later
 118         */
 119        { /* end of list */ }
 120    }
 121};
 122
 123static const QemuOptDesc qemu_smbios_file_opts[] = {
 124    {
 125        .name = "file",
 126        .type = QEMU_OPT_STRING,
 127        .help = "binary file containing an SMBIOS element",
 128    },
 129    { /* end of list */ }
 130};
 131
 132static const QemuOptDesc qemu_smbios_type0_opts[] = {
 133    {
 134        .name = "type",
 135        .type = QEMU_OPT_NUMBER,
 136        .help = "SMBIOS element type",
 137    },{
 138        .name = "vendor",
 139        .type = QEMU_OPT_STRING,
 140        .help = "vendor name",
 141    },{
 142        .name = "version",
 143        .type = QEMU_OPT_STRING,
 144        .help = "version number",
 145    },{
 146        .name = "date",
 147        .type = QEMU_OPT_STRING,
 148        .help = "release date",
 149    },{
 150        .name = "release",
 151        .type = QEMU_OPT_STRING,
 152        .help = "revision number",
 153    },{
 154        .name = "uefi",
 155        .type = QEMU_OPT_BOOL,
 156        .help = "uefi support",
 157    },
 158    { /* end of list */ }
 159};
 160
 161static const QemuOptDesc qemu_smbios_type1_opts[] = {
 162    {
 163        .name = "type",
 164        .type = QEMU_OPT_NUMBER,
 165        .help = "SMBIOS element type",
 166    },{
 167        .name = "manufacturer",
 168        .type = QEMU_OPT_STRING,
 169        .help = "manufacturer name",
 170    },{
 171        .name = "product",
 172        .type = QEMU_OPT_STRING,
 173        .help = "product name",
 174    },{
 175        .name = "version",
 176        .type = QEMU_OPT_STRING,
 177        .help = "version number",
 178    },{
 179        .name = "serial",
 180        .type = QEMU_OPT_STRING,
 181        .help = "serial number",
 182    },{
 183        .name = "uuid",
 184        .type = QEMU_OPT_STRING,
 185        .help = "UUID",
 186    },{
 187        .name = "sku",
 188        .type = QEMU_OPT_STRING,
 189        .help = "SKU number",
 190    },{
 191        .name = "family",
 192        .type = QEMU_OPT_STRING,
 193        .help = "family name",
 194    },
 195    { /* end of list */ }
 196};
 197
 198static const QemuOptDesc qemu_smbios_type2_opts[] = {
 199    {
 200        .name = "type",
 201        .type = QEMU_OPT_NUMBER,
 202        .help = "SMBIOS element type",
 203    },{
 204        .name = "manufacturer",
 205        .type = QEMU_OPT_STRING,
 206        .help = "manufacturer name",
 207    },{
 208        .name = "product",
 209        .type = QEMU_OPT_STRING,
 210        .help = "product name",
 211    },{
 212        .name = "version",
 213        .type = QEMU_OPT_STRING,
 214        .help = "version number",
 215    },{
 216        .name = "serial",
 217        .type = QEMU_OPT_STRING,
 218        .help = "serial number",
 219    },{
 220        .name = "asset",
 221        .type = QEMU_OPT_STRING,
 222        .help = "asset tag number",
 223    },{
 224        .name = "location",
 225        .type = QEMU_OPT_STRING,
 226        .help = "location in chassis",
 227    },
 228    { /* end of list */ }
 229};
 230
 231static const QemuOptDesc qemu_smbios_type3_opts[] = {
 232    {
 233        .name = "type",
 234        .type = QEMU_OPT_NUMBER,
 235        .help = "SMBIOS element type",
 236    },{
 237        .name = "manufacturer",
 238        .type = QEMU_OPT_STRING,
 239        .help = "manufacturer name",
 240    },{
 241        .name = "version",
 242        .type = QEMU_OPT_STRING,
 243        .help = "version number",
 244    },{
 245        .name = "serial",
 246        .type = QEMU_OPT_STRING,
 247        .help = "serial number",
 248    },{
 249        .name = "asset",
 250        .type = QEMU_OPT_STRING,
 251        .help = "asset tag number",
 252    },{
 253        .name = "sku",
 254        .type = QEMU_OPT_STRING,
 255        .help = "SKU number",
 256    },
 257    { /* end of list */ }
 258};
 259
 260static const QemuOptDesc qemu_smbios_type4_opts[] = {
 261    {
 262        .name = "type",
 263        .type = QEMU_OPT_NUMBER,
 264        .help = "SMBIOS element type",
 265    },{
 266        .name = "sock_pfx",
 267        .type = QEMU_OPT_STRING,
 268        .help = "socket designation string prefix",
 269    },{
 270        .name = "manufacturer",
 271        .type = QEMU_OPT_STRING,
 272        .help = "manufacturer name",
 273    },{
 274        .name = "version",
 275        .type = QEMU_OPT_STRING,
 276        .help = "version number",
 277    },{
 278        .name = "serial",
 279        .type = QEMU_OPT_STRING,
 280        .help = "serial number",
 281    },{
 282        .name = "asset",
 283        .type = QEMU_OPT_STRING,
 284        .help = "asset tag number",
 285    },{
 286        .name = "part",
 287        .type = QEMU_OPT_STRING,
 288        .help = "part number",
 289    },
 290    { /* end of list */ }
 291};
 292
 293static const QemuOptDesc qemu_smbios_type11_opts[] = {
 294    {
 295        .name = "value",
 296        .type = QEMU_OPT_STRING,
 297        .help = "OEM string data",
 298    },
 299};
 300
 301static const QemuOptDesc qemu_smbios_type17_opts[] = {
 302    {
 303        .name = "type",
 304        .type = QEMU_OPT_NUMBER,
 305        .help = "SMBIOS element type",
 306    },{
 307        .name = "loc_pfx",
 308        .type = QEMU_OPT_STRING,
 309        .help = "device locator string prefix",
 310    },{
 311        .name = "bank",
 312        .type = QEMU_OPT_STRING,
 313        .help = "bank locator string",
 314    },{
 315        .name = "manufacturer",
 316        .type = QEMU_OPT_STRING,
 317        .help = "manufacturer name",
 318    },{
 319        .name = "serial",
 320        .type = QEMU_OPT_STRING,
 321        .help = "serial number",
 322    },{
 323        .name = "asset",
 324        .type = QEMU_OPT_STRING,
 325        .help = "asset tag number",
 326    },{
 327        .name = "part",
 328        .type = QEMU_OPT_STRING,
 329        .help = "part number",
 330    },{
 331        .name = "speed",
 332        .type = QEMU_OPT_NUMBER,
 333        .help = "maximum capable speed",
 334    },
 335    { /* end of list */ }
 336};
 337
 338static void smbios_register_config(void)
 339{
 340    qemu_add_opts(&qemu_smbios_opts);
 341}
 342
 343opts_init(smbios_register_config);
 344
 345static void smbios_validate_table(MachineState *ms)
 346{
 347    uint32_t expect_t4_count = smbios_legacy ?
 348                                        ms->smp.cpus : smbios_smp_sockets;
 349
 350    if (smbios_type4_count && smbios_type4_count != expect_t4_count) {
 351        error_report("Expected %d SMBIOS Type 4 tables, got %d instead",
 352                     expect_t4_count, smbios_type4_count);
 353        exit(1);
 354    }
 355}
 356
 357
 358/* legacy setup functions for <= 2.0 machines */
 359static void smbios_add_field(int type, int offset, const void *data, size_t len)
 360{
 361    struct smbios_field *field;
 362
 363    if (!smbios_entries) {
 364        smbios_entries_len = sizeof(uint16_t);
 365        smbios_entries = g_malloc0(smbios_entries_len);
 366    }
 367    smbios_entries = g_realloc(smbios_entries, smbios_entries_len +
 368                                                  sizeof(*field) + len);
 369    field = (struct smbios_field *)(smbios_entries + smbios_entries_len);
 370    field->header.type = SMBIOS_FIELD_ENTRY;
 371    field->header.length = cpu_to_le16(sizeof(*field) + len);
 372
 373    field->type = type;
 374    field->offset = cpu_to_le16(offset);
 375    memcpy(field->data, data, len);
 376
 377    smbios_entries_len += sizeof(*field) + len;
 378    (*(uint16_t *)smbios_entries) =
 379            cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1);
 380}
 381
 382static void smbios_maybe_add_str(int type, int offset, const char *data)
 383{
 384    if (data) {
 385        smbios_add_field(type, offset, data, strlen(data) + 1);
 386    }
 387}
 388
 389static void smbios_build_type_0_fields(void)
 390{
 391    smbios_maybe_add_str(0, offsetof(struct smbios_type_0, vendor_str),
 392                         type0.vendor);
 393    smbios_maybe_add_str(0, offsetof(struct smbios_type_0, bios_version_str),
 394                         type0.version);
 395    smbios_maybe_add_str(0, offsetof(struct smbios_type_0,
 396                                     bios_release_date_str),
 397                         type0.date);
 398    if (type0.have_major_minor) {
 399        smbios_add_field(0, offsetof(struct smbios_type_0,
 400                                     system_bios_major_release),
 401                         &type0.major, 1);
 402        smbios_add_field(0, offsetof(struct smbios_type_0,
 403                                     system_bios_minor_release),
 404                         &type0.minor, 1);
 405    }
 406}
 407
 408static void smbios_build_type_1_fields(void)
 409{
 410    smbios_maybe_add_str(1, offsetof(struct smbios_type_1, manufacturer_str),
 411                         type1.manufacturer);
 412    smbios_maybe_add_str(1, offsetof(struct smbios_type_1, product_name_str),
 413                         type1.product);
 414    smbios_maybe_add_str(1, offsetof(struct smbios_type_1, version_str),
 415                         type1.version);
 416    smbios_maybe_add_str(1, offsetof(struct smbios_type_1, serial_number_str),
 417                         type1.serial);
 418    smbios_maybe_add_str(1, offsetof(struct smbios_type_1, sku_number_str),
 419                         type1.sku);
 420    smbios_maybe_add_str(1, offsetof(struct smbios_type_1, family_str),
 421                         type1.family);
 422    if (qemu_uuid_set) {
 423        /* We don't encode the UUID in the "wire format" here because this
 424         * function is for legacy mode and needs to keep the guest ABI, and
 425         * because we don't know what's the SMBIOS version advertised by the
 426         * BIOS.
 427         */
 428        smbios_add_field(1, offsetof(struct smbios_type_1, uuid),
 429                         &qemu_uuid, 16);
 430    }
 431}
 432
 433uint8_t *smbios_get_table_legacy(MachineState *ms, size_t *length)
 434{
 435    if (!smbios_legacy) {
 436        *length = 0;
 437        return NULL;
 438    }
 439
 440    if (!smbios_immutable) {
 441        smbios_build_type_0_fields();
 442        smbios_build_type_1_fields();
 443        smbios_validate_table(ms);
 444        smbios_immutable = true;
 445    }
 446    *length = smbios_entries_len;
 447    return smbios_entries;
 448}
 449/* end: legacy setup functions for <= 2.0 machines */
 450
 451
 452bool smbios_skip_table(uint8_t type, bool required_table)
 453{
 454    if (test_bit(type, have_binfile_bitmap)) {
 455        return true; /* user provided their own binary blob(s) */
 456    }
 457    if (test_bit(type, have_fields_bitmap)) {
 458        return false; /* user provided fields via command line */
 459    }
 460    if (smbios_have_defaults && required_table) {
 461        return false; /* we're building tables, and this one's required */
 462    }
 463    return true;
 464}
 465
 466static void smbios_build_type_0_table(void)
 467{
 468    SMBIOS_BUILD_TABLE_PRE(0, 0x000, false); /* optional, leave up to BIOS */
 469
 470    SMBIOS_TABLE_SET_STR(0, vendor_str, type0.vendor);
 471    SMBIOS_TABLE_SET_STR(0, bios_version_str, type0.version);
 472
 473    t->bios_starting_address_segment = cpu_to_le16(0xE800); /* from SeaBIOS */
 474
 475    SMBIOS_TABLE_SET_STR(0, bios_release_date_str, type0.date);
 476
 477    t->bios_rom_size = 0; /* hardcoded in SeaBIOS with FIXME comment */
 478
 479    t->bios_characteristics = cpu_to_le64(0x08); /* Not supported */
 480    t->bios_characteristics_extension_bytes[0] = 0;
 481    t->bios_characteristics_extension_bytes[1] = 0x14; /* TCD/SVVP | VM */
 482    if (type0.uefi) {
 483        t->bios_characteristics_extension_bytes[1] |= 0x08; /* |= UEFI */
 484    }
 485
 486    if (type0.have_major_minor) {
 487        t->system_bios_major_release = type0.major;
 488        t->system_bios_minor_release = type0.minor;
 489    } else {
 490        t->system_bios_major_release = 0;
 491        t->system_bios_minor_release = 0;
 492    }
 493
 494    /* hardcoded in SeaBIOS */
 495    t->embedded_controller_major_release = 0xFF;
 496    t->embedded_controller_minor_release = 0xFF;
 497
 498    SMBIOS_BUILD_TABLE_POST;
 499}
 500
 501/* Encode UUID from the big endian encoding described on RFC4122 to the wire
 502 * format specified by SMBIOS version 2.6.
 503 */
 504static void smbios_encode_uuid(struct smbios_uuid *uuid, QemuUUID *in)
 505{
 506    memcpy(uuid, in, 16);
 507    if (smbios_uuid_encoded) {
 508        uuid->time_low = bswap32(uuid->time_low);
 509        uuid->time_mid = bswap16(uuid->time_mid);
 510        uuid->time_hi_and_version = bswap16(uuid->time_hi_and_version);
 511    }
 512}
 513
 514static void smbios_build_type_1_table(void)
 515{
 516    SMBIOS_BUILD_TABLE_PRE(1, 0x100, true); /* required */
 517
 518    SMBIOS_TABLE_SET_STR(1, manufacturer_str, type1.manufacturer);
 519    SMBIOS_TABLE_SET_STR(1, product_name_str, type1.product);
 520    SMBIOS_TABLE_SET_STR(1, version_str, type1.version);
 521    SMBIOS_TABLE_SET_STR(1, serial_number_str, type1.serial);
 522    if (qemu_uuid_set) {
 523        smbios_encode_uuid(&t->uuid, &qemu_uuid);
 524    } else {
 525        memset(&t->uuid, 0, 16);
 526    }
 527    t->wake_up_type = 0x06; /* power switch */
 528    SMBIOS_TABLE_SET_STR(1, sku_number_str, type1.sku);
 529    SMBIOS_TABLE_SET_STR(1, family_str, type1.family);
 530
 531    SMBIOS_BUILD_TABLE_POST;
 532}
 533
 534static void smbios_build_type_2_table(void)
 535{
 536    SMBIOS_BUILD_TABLE_PRE(2, 0x200, false); /* optional */
 537
 538    SMBIOS_TABLE_SET_STR(2, manufacturer_str, type2.manufacturer);
 539    SMBIOS_TABLE_SET_STR(2, product_str, type2.product);
 540    SMBIOS_TABLE_SET_STR(2, version_str, type2.version);
 541    SMBIOS_TABLE_SET_STR(2, serial_number_str, type2.serial);
 542    SMBIOS_TABLE_SET_STR(2, asset_tag_number_str, type2.asset);
 543    t->feature_flags = 0x01; /* Motherboard */
 544    SMBIOS_TABLE_SET_STR(2, location_str, type2.location);
 545    t->chassis_handle = cpu_to_le16(0x300); /* Type 3 (System enclosure) */
 546    t->board_type = 0x0A; /* Motherboard */
 547    t->contained_element_count = 0;
 548
 549    SMBIOS_BUILD_TABLE_POST;
 550}
 551
 552static void smbios_build_type_3_table(void)
 553{
 554    SMBIOS_BUILD_TABLE_PRE(3, 0x300, true); /* required */
 555
 556    SMBIOS_TABLE_SET_STR(3, manufacturer_str, type3.manufacturer);
 557    t->type = 0x01; /* Other */
 558    SMBIOS_TABLE_SET_STR(3, version_str, type3.version);
 559    SMBIOS_TABLE_SET_STR(3, serial_number_str, type3.serial);
 560    SMBIOS_TABLE_SET_STR(3, asset_tag_number_str, type3.asset);
 561    t->boot_up_state = 0x03; /* Safe */
 562    t->power_supply_state = 0x03; /* Safe */
 563    t->thermal_state = 0x03; /* Safe */
 564    t->security_status = 0x02; /* Unknown */
 565    t->oem_defined = cpu_to_le32(0);
 566    t->height = 0;
 567    t->number_of_power_cords = 0;
 568    t->contained_element_count = 0;
 569    t->contained_element_record_length = 0;
 570    SMBIOS_TABLE_SET_STR(3, sku_number_str, type3.sku);
 571
 572    SMBIOS_BUILD_TABLE_POST;
 573}
 574
 575static void smbios_build_type_4_table(MachineState *ms, unsigned instance)
 576{
 577    char sock_str[128];
 578
 579    SMBIOS_BUILD_TABLE_PRE(4, 0x400 + instance, true); /* required */
 580
 581    snprintf(sock_str, sizeof(sock_str), "%s%2x", type4.sock_pfx, instance);
 582    SMBIOS_TABLE_SET_STR(4, socket_designation_str, sock_str);
 583    t->processor_type = 0x03; /* CPU */
 584    t->processor_family = 0x01; /* Other */
 585    SMBIOS_TABLE_SET_STR(4, processor_manufacturer_str, type4.manufacturer);
 586    t->processor_id[0] = cpu_to_le32(smbios_cpuid_version);
 587    t->processor_id[1] = cpu_to_le32(smbios_cpuid_features);
 588    SMBIOS_TABLE_SET_STR(4, processor_version_str, type4.version);
 589    t->voltage = 0;
 590    t->external_clock = cpu_to_le16(0); /* Unknown */
 591    /* SVVP requires max_speed and current_speed to not be unknown. */
 592    t->max_speed = cpu_to_le16(2000); /* 2000 MHz */
 593    t->current_speed = cpu_to_le16(2000); /* 2000 MHz */
 594    t->status = 0x41; /* Socket populated, CPU enabled */
 595    t->processor_upgrade = 0x01; /* Other */
 596    t->l1_cache_handle = cpu_to_le16(0xFFFF); /* N/A */
 597    t->l2_cache_handle = cpu_to_le16(0xFFFF); /* N/A */
 598    t->l3_cache_handle = cpu_to_le16(0xFFFF); /* N/A */
 599    SMBIOS_TABLE_SET_STR(4, serial_number_str, type4.serial);
 600    SMBIOS_TABLE_SET_STR(4, asset_tag_number_str, type4.asset);
 601    SMBIOS_TABLE_SET_STR(4, part_number_str, type4.part);
 602    t->core_count = t->core_enabled = ms->smp.cores;
 603    t->thread_count = ms->smp.threads;
 604    t->processor_characteristics = cpu_to_le16(0x02); /* Unknown */
 605    t->processor_family2 = cpu_to_le16(0x01); /* Other */
 606
 607    SMBIOS_BUILD_TABLE_POST;
 608    smbios_type4_count++;
 609}
 610
 611static void smbios_build_type_11_table(void)
 612{
 613    char count_str[128];
 614    size_t i;
 615
 616    if (type11.nvalues == 0) {
 617        return;
 618    }
 619
 620    SMBIOS_BUILD_TABLE_PRE(11, 0xe00, true); /* required */
 621
 622    snprintf(count_str, sizeof(count_str), "%zu", type11.nvalues);
 623    t->count = type11.nvalues;
 624
 625    for (i = 0; i < type11.nvalues; i++) {
 626        SMBIOS_TABLE_SET_STR_LIST(11, type11.values[i]);
 627    }
 628
 629    SMBIOS_BUILD_TABLE_POST;
 630}
 631
 632#define MAX_T16_STD_SZ 0x80000000 /* 2T in Kilobytes */
 633
 634static void smbios_build_type_16_table(unsigned dimm_cnt)
 635{
 636    uint64_t size_kb;
 637
 638    SMBIOS_BUILD_TABLE_PRE(16, 0x1000, true); /* required */
 639
 640    t->location = 0x01; /* Other */
 641    t->use = 0x03; /* System memory */
 642    t->error_correction = 0x06; /* Multi-bit ECC (for Microsoft, per SeaBIOS) */
 643    size_kb = QEMU_ALIGN_UP(ram_size, KiB) / KiB;
 644    if (size_kb < MAX_T16_STD_SZ) {
 645        t->maximum_capacity = cpu_to_le32(size_kb);
 646        t->extended_maximum_capacity = cpu_to_le64(0);
 647    } else {
 648        t->maximum_capacity = cpu_to_le32(MAX_T16_STD_SZ);
 649        t->extended_maximum_capacity = cpu_to_le64(ram_size);
 650    }
 651    t->memory_error_information_handle = cpu_to_le16(0xFFFE); /* Not provided */
 652    t->number_of_memory_devices = cpu_to_le16(dimm_cnt);
 653
 654    SMBIOS_BUILD_TABLE_POST;
 655}
 656
 657#define MAX_T17_STD_SZ 0x7FFF /* (32G - 1M), in Megabytes */
 658#define MAX_T17_EXT_SZ 0x80000000 /* 2P, in Megabytes */
 659
 660static void smbios_build_type_17_table(unsigned instance, uint64_t size)
 661{
 662    char loc_str[128];
 663    uint64_t size_mb;
 664
 665    SMBIOS_BUILD_TABLE_PRE(17, 0x1100 + instance, true); /* required */
 666
 667    t->physical_memory_array_handle = cpu_to_le16(0x1000); /* Type 16 above */
 668    t->memory_error_information_handle = cpu_to_le16(0xFFFE); /* Not provided */
 669    t->total_width = cpu_to_le16(0xFFFF); /* Unknown */
 670    t->data_width = cpu_to_le16(0xFFFF); /* Unknown */
 671    size_mb = QEMU_ALIGN_UP(size, MiB) / MiB;
 672    if (size_mb < MAX_T17_STD_SZ) {
 673        t->size = cpu_to_le16(size_mb);
 674        t->extended_size = cpu_to_le32(0);
 675    } else {
 676        assert(size_mb < MAX_T17_EXT_SZ);
 677        t->size = cpu_to_le16(MAX_T17_STD_SZ);
 678        t->extended_size = cpu_to_le32(size_mb);
 679    }
 680    t->form_factor = 0x09; /* DIMM */
 681    t->device_set = 0; /* Not in a set */
 682    snprintf(loc_str, sizeof(loc_str), "%s %d", type17.loc_pfx, instance);
 683    SMBIOS_TABLE_SET_STR(17, device_locator_str, loc_str);
 684    SMBIOS_TABLE_SET_STR(17, bank_locator_str, type17.bank);
 685    t->memory_type = 0x07; /* RAM */
 686    t->type_detail = cpu_to_le16(0x02); /* Other */
 687    t->speed = cpu_to_le16(type17.speed);
 688    SMBIOS_TABLE_SET_STR(17, manufacturer_str, type17.manufacturer);
 689    SMBIOS_TABLE_SET_STR(17, serial_number_str, type17.serial);
 690    SMBIOS_TABLE_SET_STR(17, asset_tag_number_str, type17.asset);
 691    SMBIOS_TABLE_SET_STR(17, part_number_str, type17.part);
 692    t->attributes = 0; /* Unknown */
 693    t->configured_clock_speed = t->speed; /* reuse value for max speed */
 694    t->minimum_voltage = cpu_to_le16(0); /* Unknown */
 695    t->maximum_voltage = cpu_to_le16(0); /* Unknown */
 696    t->configured_voltage = cpu_to_le16(0); /* Unknown */
 697
 698    SMBIOS_BUILD_TABLE_POST;
 699}
 700
 701static void smbios_build_type_19_table(unsigned instance,
 702                                       uint64_t start, uint64_t size)
 703{
 704    uint64_t end, start_kb, end_kb;
 705
 706    SMBIOS_BUILD_TABLE_PRE(19, 0x1300 + instance, true); /* required */
 707
 708    end = start + size - 1;
 709    assert(end > start);
 710    start_kb = start / KiB;
 711    end_kb = end / KiB;
 712    if (start_kb < UINT32_MAX && end_kb < UINT32_MAX) {
 713        t->starting_address = cpu_to_le32(start_kb);
 714        t->ending_address = cpu_to_le32(end_kb);
 715        t->extended_starting_address =
 716            t->extended_ending_address = cpu_to_le64(0);
 717    } else {
 718        t->starting_address = t->ending_address = cpu_to_le32(UINT32_MAX);
 719        t->extended_starting_address = cpu_to_le64(start);
 720        t->extended_ending_address = cpu_to_le64(end);
 721    }
 722    t->memory_array_handle = cpu_to_le16(0x1000); /* Type 16 above */
 723    t->partition_width = 1; /* One device per row */
 724
 725    SMBIOS_BUILD_TABLE_POST;
 726}
 727
 728static void smbios_build_type_32_table(void)
 729{
 730    SMBIOS_BUILD_TABLE_PRE(32, 0x2000, true); /* required */
 731
 732    memset(t->reserved, 0, 6);
 733    t->boot_status = 0; /* No errors detected */
 734
 735    SMBIOS_BUILD_TABLE_POST;
 736}
 737
 738static void smbios_build_type_127_table(void)
 739{
 740    SMBIOS_BUILD_TABLE_PRE(127, 0x7F00, true); /* required */
 741    SMBIOS_BUILD_TABLE_POST;
 742}
 743
 744void smbios_set_cpuid(uint32_t version, uint32_t features)
 745{
 746    smbios_cpuid_version = version;
 747    smbios_cpuid_features = features;
 748}
 749
 750#define SMBIOS_SET_DEFAULT(field, value)                                  \
 751    if (!field) {                                                         \
 752        field = value;                                                    \
 753    }
 754
 755void smbios_set_defaults(const char *manufacturer, const char *product,
 756                         const char *version, bool legacy_mode,
 757                         bool uuid_encoded, SmbiosEntryPointType ep_type)
 758{
 759    smbios_have_defaults = true;
 760    smbios_legacy = legacy_mode;
 761    smbios_uuid_encoded = uuid_encoded;
 762    smbios_ep_type = ep_type;
 763
 764    /* drop unwanted version of command-line file blob(s) */
 765    if (smbios_legacy) {
 766        g_free(smbios_tables);
 767        /* in legacy mode, also complain if fields were given for types > 1 */
 768        if (find_next_bit(have_fields_bitmap,
 769                          SMBIOS_MAX_TYPE+1, 2) < SMBIOS_MAX_TYPE+1) {
 770            error_report("can't process fields for smbios "
 771                         "types > 1 on machine versions < 2.1!");
 772            exit(1);
 773        }
 774    } else {
 775        g_free(smbios_entries);
 776    }
 777
 778    SMBIOS_SET_DEFAULT(type1.manufacturer, manufacturer);
 779    SMBIOS_SET_DEFAULT(type1.product, product);
 780    SMBIOS_SET_DEFAULT(type1.version, version);
 781    SMBIOS_SET_DEFAULT(type2.manufacturer, manufacturer);
 782    SMBIOS_SET_DEFAULT(type2.product, product);
 783    SMBIOS_SET_DEFAULT(type2.version, version);
 784    SMBIOS_SET_DEFAULT(type3.manufacturer, manufacturer);
 785    SMBIOS_SET_DEFAULT(type3.version, version);
 786    SMBIOS_SET_DEFAULT(type4.sock_pfx, "CPU");
 787    SMBIOS_SET_DEFAULT(type4.manufacturer, manufacturer);
 788    SMBIOS_SET_DEFAULT(type4.version, version);
 789    SMBIOS_SET_DEFAULT(type17.loc_pfx, "DIMM");
 790    SMBIOS_SET_DEFAULT(type17.manufacturer, manufacturer);
 791}
 792
 793static void smbios_entry_point_setup(void)
 794{
 795    switch (smbios_ep_type) {
 796    case SMBIOS_ENTRY_POINT_21:
 797        memcpy(ep.ep21.anchor_string, "_SM_", 4);
 798        memcpy(ep.ep21.intermediate_anchor_string, "_DMI_", 5);
 799        ep.ep21.length = sizeof(struct smbios_21_entry_point);
 800        ep.ep21.entry_point_revision = 0; /* formatted_area reserved */
 801        memset(ep.ep21.formatted_area, 0, 5);
 802
 803        /* compliant with smbios spec v2.8 */
 804        ep.ep21.smbios_major_version = 2;
 805        ep.ep21.smbios_minor_version = 8;
 806        ep.ep21.smbios_bcd_revision = 0x28;
 807
 808        /* set during table construction, but BIOS may override: */
 809        ep.ep21.structure_table_length = cpu_to_le16(smbios_tables_len);
 810        ep.ep21.max_structure_size = cpu_to_le16(smbios_table_max);
 811        ep.ep21.number_of_structures = cpu_to_le16(smbios_table_cnt);
 812
 813        /* BIOS must recalculate */
 814        ep.ep21.checksum = 0;
 815        ep.ep21.intermediate_checksum = 0;
 816        ep.ep21.structure_table_address = cpu_to_le32(0);
 817
 818        break;
 819    case SMBIOS_ENTRY_POINT_30:
 820        memcpy(ep.ep30.anchor_string, "_SM3_", 5);
 821        ep.ep30.length = sizeof(struct smbios_30_entry_point);
 822        ep.ep30.entry_point_revision = 1;
 823        ep.ep30.reserved = 0;
 824
 825        /* compliant with smbios spec 3.0 */
 826        ep.ep30.smbios_major_version = 3;
 827        ep.ep30.smbios_minor_version = 0;
 828        ep.ep30.smbios_doc_rev = 0;
 829
 830        /* set during table construct, but BIOS might override */
 831        ep.ep30.structure_table_max_size = cpu_to_le32(smbios_tables_len);
 832
 833        /* BIOS must recalculate */
 834        ep.ep30.checksum = 0;
 835        ep.ep30.structure_table_address = cpu_to_le64(0);
 836
 837        break;
 838    default:
 839        abort();
 840        break;
 841    }
 842}
 843
 844void smbios_get_tables(MachineState *ms,
 845                       const struct smbios_phys_mem_area *mem_array,
 846                       const unsigned int mem_array_size,
 847                       uint8_t **tables, size_t *tables_len,
 848                       uint8_t **anchor, size_t *anchor_len)
 849{
 850    unsigned i, dimm_cnt;
 851
 852    if (smbios_legacy) {
 853        *tables = *anchor = NULL;
 854        *tables_len = *anchor_len = 0;
 855        return;
 856    }
 857
 858    if (!smbios_immutable) {
 859        smbios_build_type_0_table();
 860        smbios_build_type_1_table();
 861        smbios_build_type_2_table();
 862        smbios_build_type_3_table();
 863
 864        smbios_smp_sockets = DIV_ROUND_UP(ms->smp.cpus,
 865                                          ms->smp.cores * ms->smp.threads);
 866        assert(smbios_smp_sockets >= 1);
 867
 868        for (i = 0; i < smbios_smp_sockets; i++) {
 869            smbios_build_type_4_table(ms, i);
 870        }
 871
 872        smbios_build_type_11_table();
 873
 874#define MAX_DIMM_SZ (16 * GiB)
 875#define GET_DIMM_SZ ((i < dimm_cnt - 1) ? MAX_DIMM_SZ \
 876                                        : ((ram_size - 1) % MAX_DIMM_SZ) + 1)
 877
 878        dimm_cnt = QEMU_ALIGN_UP(ram_size, MAX_DIMM_SZ) / MAX_DIMM_SZ;
 879
 880        smbios_build_type_16_table(dimm_cnt);
 881
 882        for (i = 0; i < dimm_cnt; i++) {
 883            smbios_build_type_17_table(i, GET_DIMM_SZ);
 884        }
 885
 886        for (i = 0; i < mem_array_size; i++) {
 887            smbios_build_type_19_table(i, mem_array[i].address,
 888                                       mem_array[i].length);
 889        }
 890
 891        smbios_build_type_32_table();
 892        smbios_build_type_38_table();
 893        smbios_build_type_127_table();
 894
 895        smbios_validate_table(ms);
 896        smbios_entry_point_setup();
 897        smbios_immutable = true;
 898    }
 899
 900    /* return tables blob and entry point (anchor), and their sizes */
 901    *tables = smbios_tables;
 902    *tables_len = smbios_tables_len;
 903    *anchor = (uint8_t *)&ep;
 904
 905    /* calculate length based on anchor string */
 906    if (!strncmp((char *)&ep, "_SM_", 4)) {
 907        *anchor_len = sizeof(struct smbios_21_entry_point);
 908    } else if (!strncmp((char *)&ep, "_SM3_", 5)) {
 909        *anchor_len = sizeof(struct smbios_30_entry_point);
 910    } else {
 911        abort();
 912    }
 913}
 914
 915static void save_opt(const char **dest, QemuOpts *opts, const char *name)
 916{
 917    const char *val = qemu_opt_get(opts, name);
 918
 919    if (val) {
 920        *dest = val;
 921    }
 922}
 923
 924
 925struct opt_list {
 926    const char *name;
 927    size_t *ndest;
 928    const char ***dest;
 929};
 930
 931static int save_opt_one(void *opaque,
 932                        const char *name, const char *value,
 933                        Error **errp)
 934{
 935    struct opt_list *opt = opaque;
 936
 937    if (!g_str_equal(name, opt->name)) {
 938        return 0;
 939    }
 940
 941    *opt->dest = g_renew(const char *, *opt->dest, (*opt->ndest) + 1);
 942    (*opt->dest)[*opt->ndest] = value;
 943    (*opt->ndest)++;
 944    return 0;
 945}
 946
 947static void save_opt_list(size_t *ndest, const char ***dest,
 948                          QemuOpts *opts, const char *name)
 949{
 950    struct opt_list opt = {
 951        name, ndest, dest,
 952    };
 953    qemu_opt_foreach(opts, save_opt_one, &opt, NULL);
 954}
 955
 956void smbios_entry_add(QemuOpts *opts, Error **errp)
 957{
 958    Error *err = NULL;
 959    const char *val;
 960
 961    assert(!smbios_immutable);
 962
 963    val = qemu_opt_get(opts, "file");
 964    if (val) {
 965        struct smbios_structure_header *header;
 966        int size;
 967        struct smbios_table *table; /* legacy mode only */
 968
 969        qemu_opts_validate(opts, qemu_smbios_file_opts, &err);
 970        if (err) {
 971            error_propagate(errp, err);
 972            return;
 973        }
 974
 975        size = get_image_size(val);
 976        if (size == -1 || size < sizeof(struct smbios_structure_header)) {
 977            error_setg(errp, "Cannot read SMBIOS file %s", val);
 978            return;
 979        }
 980
 981        /*
 982         * NOTE: standard double '\0' terminator expected, per smbios spec.
 983         * (except in legacy mode, where the second '\0' is implicit and
 984         *  will be inserted by the BIOS).
 985         */
 986        smbios_tables = g_realloc(smbios_tables, smbios_tables_len + size);
 987        header = (struct smbios_structure_header *)(smbios_tables +
 988                                                    smbios_tables_len);
 989
 990        if (load_image_size(val, (uint8_t *)header, size) != size) {
 991            error_setg(errp, "Failed to load SMBIOS file %s", val);
 992            return;
 993        }
 994
 995        if (test_bit(header->type, have_fields_bitmap)) {
 996            error_setg(errp,
 997                       "can't load type %d struct, fields already specified!",
 998                       header->type);
 999            return;
1000        }
1001        set_bit(header->type, have_binfile_bitmap);
1002
1003        if (header->type == 4) {
1004            smbios_type4_count++;
1005        }
1006
1007        smbios_tables_len += size;
1008        if (size > smbios_table_max) {
1009            smbios_table_max = size;
1010        }
1011        smbios_table_cnt++;
1012
1013        /* add a copy of the newly loaded blob to legacy smbios_entries */
1014        /* NOTE: This code runs before smbios_set_defaults(), so we don't
1015         *       yet know which mode (legacy vs. aggregate-table) will be
1016         *       required. We therefore add the binary blob to both legacy
1017         *       (smbios_entries) and aggregate (smbios_tables) tables, and
1018         *       delete the one we don't need from smbios_set_defaults(),
1019         *       once we know which machine version has been requested.
1020         */
1021        if (!smbios_entries) {
1022            smbios_entries_len = sizeof(uint16_t);
1023            smbios_entries = g_malloc0(smbios_entries_len);
1024        }
1025        smbios_entries = g_realloc(smbios_entries, smbios_entries_len +
1026                                                   size + sizeof(*table));
1027        table = (struct smbios_table *)(smbios_entries + smbios_entries_len);
1028        table->header.type = SMBIOS_TABLE_ENTRY;
1029        table->header.length = cpu_to_le16(sizeof(*table) + size);
1030        memcpy(table->data, header, size);
1031        smbios_entries_len += sizeof(*table) + size;
1032        (*(uint16_t *)smbios_entries) =
1033                cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1);
1034        /* end: add a copy of the newly loaded blob to legacy smbios_entries */
1035
1036        return;
1037    }
1038
1039    val = qemu_opt_get(opts, "type");
1040    if (val) {
1041        unsigned long type = strtoul(val, NULL, 0);
1042
1043        if (type > SMBIOS_MAX_TYPE) {
1044            error_setg(errp, "out of range!");
1045            return;
1046        }
1047
1048        if (test_bit(type, have_binfile_bitmap)) {
1049            error_setg(errp, "can't add fields, binary file already loaded!");
1050            return;
1051        }
1052        set_bit(type, have_fields_bitmap);
1053
1054        switch (type) {
1055        case 0:
1056            qemu_opts_validate(opts, qemu_smbios_type0_opts, &err);
1057            if (err) {
1058                error_propagate(errp, err);
1059                return;
1060            }
1061            save_opt(&type0.vendor, opts, "vendor");
1062            save_opt(&type0.version, opts, "version");
1063            save_opt(&type0.date, opts, "date");
1064            type0.uefi = qemu_opt_get_bool(opts, "uefi", false);
1065
1066            val = qemu_opt_get(opts, "release");
1067            if (val) {
1068                if (sscanf(val, "%hhu.%hhu", &type0.major, &type0.minor) != 2) {
1069                    error_setg(errp, "Invalid release");
1070                    return;
1071                }
1072                type0.have_major_minor = true;
1073            }
1074            return;
1075        case 1:
1076            qemu_opts_validate(opts, qemu_smbios_type1_opts, &err);
1077            if (err) {
1078                error_propagate(errp, err);
1079                return;
1080            }
1081            save_opt(&type1.manufacturer, opts, "manufacturer");
1082            save_opt(&type1.product, opts, "product");
1083            save_opt(&type1.version, opts, "version");
1084            save_opt(&type1.serial, opts, "serial");
1085            save_opt(&type1.sku, opts, "sku");
1086            save_opt(&type1.family, opts, "family");
1087
1088            val = qemu_opt_get(opts, "uuid");
1089            if (val) {
1090                if (qemu_uuid_parse(val, &qemu_uuid) != 0) {
1091                    error_setg(errp, "Invalid UUID");
1092                    return;
1093                }
1094                qemu_uuid_set = true;
1095            }
1096            return;
1097        case 2:
1098            qemu_opts_validate(opts, qemu_smbios_type2_opts, &err);
1099            if (err) {
1100                error_propagate(errp, err);
1101                return;
1102            }
1103            save_opt(&type2.manufacturer, opts, "manufacturer");
1104            save_opt(&type2.product, opts, "product");
1105            save_opt(&type2.version, opts, "version");
1106            save_opt(&type2.serial, opts, "serial");
1107            save_opt(&type2.asset, opts, "asset");
1108            save_opt(&type2.location, opts, "location");
1109            return;
1110        case 3:
1111            qemu_opts_validate(opts, qemu_smbios_type3_opts, &err);
1112            if (err) {
1113                error_propagate(errp, err);
1114                return;
1115            }
1116            save_opt(&type3.manufacturer, opts, "manufacturer");
1117            save_opt(&type3.version, opts, "version");
1118            save_opt(&type3.serial, opts, "serial");
1119            save_opt(&type3.asset, opts, "asset");
1120            save_opt(&type3.sku, opts, "sku");
1121            return;
1122        case 4:
1123            qemu_opts_validate(opts, qemu_smbios_type4_opts, &err);
1124            if (err) {
1125                error_propagate(errp, err);
1126                return;
1127            }
1128            save_opt(&type4.sock_pfx, opts, "sock_pfx");
1129            save_opt(&type4.manufacturer, opts, "manufacturer");
1130            save_opt(&type4.version, opts, "version");
1131            save_opt(&type4.serial, opts, "serial");
1132            save_opt(&type4.asset, opts, "asset");
1133            save_opt(&type4.part, opts, "part");
1134            return;
1135        case 11:
1136            qemu_opts_validate(opts, qemu_smbios_type11_opts, &err);
1137            if (err) {
1138                error_propagate(errp, err);
1139                return;
1140            }
1141            save_opt_list(&type11.nvalues, &type11.values, opts, "value");
1142            return;
1143        case 17:
1144            qemu_opts_validate(opts, qemu_smbios_type17_opts, &err);
1145            if (err) {
1146                error_propagate(errp, err);
1147                return;
1148            }
1149            save_opt(&type17.loc_pfx, opts, "loc_pfx");
1150            save_opt(&type17.bank, opts, "bank");
1151            save_opt(&type17.manufacturer, opts, "manufacturer");
1152            save_opt(&type17.serial, opts, "serial");
1153            save_opt(&type17.asset, opts, "asset");
1154            save_opt(&type17.part, opts, "part");
1155            type17.speed = qemu_opt_get_number(opts, "speed", 0);
1156            return;
1157        default:
1158            error_setg(errp,
1159                       "Don't know how to build fields for SMBIOS type %ld",
1160                       type);
1161            return;
1162        }
1163    }
1164
1165    error_setg(errp, "Must specify type= or file=");
1166}
1167