Skip to the content.

smbios

https://gist.github.com/smoser/290f74c256c89cb3f3bd434a27b9f64c

seabios

在 seabios 的那一侧:

#define QEMU_CFG_SMBIOS_ENTRIES         (QEMU_CFG_ARCH_LOCAL + 1)
  1. qemu_cfg_init : smbios 是其中的一个文件
    • qemu_cfg_read_entry(&count, QEMU_CFG_FILE_DIR, sizeof(count));

日志:

Add romfile: etc/smbios/smbios-anchor (size=31)
Add romfile: etc/smbios/smbios-tables (size=354)
  1. smbios_setup
    • smbios_romfile_setup
    • f_anchor->copy(f_anchor, &ep, f_anchor->size); : 从 QEMU 中将制作的表格读取出来
    • f_tables->copy(f_tables, qtables, f_tables->size);
    • smbios_new_type_0 : 填充 type 0 的表格
    • copy_smbios : 从 stack 上拷贝到一个确定的区域 - smbios_legacy_setup : 并不会 fallback 到这里

qemu

表格的创建 : /hw/smbios/smbios.c

存在两种格式的 smbios:

/* SMBIOS Entry Point
 * There are two types of entry points defined in the SMBIOS specification
 * (see below). BIOS must place the entry point(s) at a 16-byte-aligned
 * address between 0xf0000 and 0xfffff. Note that either entry point type
 * can be used in a 64-bit target system, except that SMBIOS 2.1 entry point
 * only allows the SMBIOS struct table to reside below 4GB address space.
 */

/* SMBIOS 2.1 (32-bit) Entry Point
 *  - introduced since SMBIOS 2.1
 *  - supports structure table below 4GB only
 */
struct smbios_21_entry_point {
    uint8_t anchor_string[4];
    uint8_t checksum;
    uint8_t length;
    uint8_t smbios_major_version;
    uint8_t smbios_minor_version;
    uint16_t max_structure_size;
    uint8_t entry_point_revision;
    uint8_t formatted_area[5];
    uint8_t intermediate_anchor_string[5];
    uint8_t intermediate_checksum;
    uint16_t structure_table_length;
    uint32_t structure_table_address;
    uint16_t number_of_structures;
    uint8_t smbios_bcd_revision;
} QEMU_PACKED;

/* SMBIOS 3.0 (64-bit) Entry Point
 *  - introduced since SMBIOS 3.0
 *  - supports structure table at 64-bit address space
 */
struct smbios_30_entry_point {
    uint8_t anchor_string[5];
    uint8_t checksum;
    uint8_t length;
    uint8_t smbios_major_version;
    uint8_t smbios_minor_version;
    uint8_t smbios_doc_rev;
    uint8_t entry_point_revision;
    uint8_t reserved;
    uint32_t structure_table_max_size;
    uint64_t structure_table_address;
} QEMU_PACKED;

kernel

问题

在 pc_init1 中

    if (pcmc->smbios_defaults) {
        MachineClass *mc = MACHINE_GET_CLASS(machine);
        /* These values are guest ABI, do not change */
        smbios_set_defaults("QEMU", "Standard PC (i440FX + PIIX, 1996)",
                            mc->name, pcmc->smbios_legacy_mode,
                            pcmc->smbios_uuid_encoded,
                            SMBIOS_ENTRY_POINT_21);
    }

其最后体现出来的效果是什么啊?

dmidecode(8)

dmidecode is a tool for dumping a computer’s DMI (some say SMBIOS ) table contents in a human-readable format. This table contains a description of the system’s hardware components, as well as other useful pieces of information such as serial numbers and BIOS revision.

这个工具的 backtrace 是什么样子的,从 Host QEMU 到 guest 的输出。

SMBIOS 可以用来汇报 Guest 的 CPU topo ?

guest 内核中: socket 应该是通过这个数值获取的:

for((i=0; i < 8; i++)); do
    cat /sys/devices/system/cpu/cpu$i/topology/physical_package_id
done

最后检查,是出现这个位置来设置,通过 cpuid

而 QEMU 中,对应的生成位置是: cpu_x86_cpuid

            if (*eax & 31) {
                int host_vcpus_per_cache = 1 + ((*eax & 0x3FFC000) >> 14);
                int vcpus_per_socket = env->nr_dies * cs->nr_cores *
                                       cs->nr_threads;
                if (cs->nr_cores > 1) {
                    *eax &= ~0xFC000000;
                    *eax |= (pow2ceil(cs->nr_cores) - 1) << 26;
                }
                if (host_vcpus_per_cache > vcpus_per_socket) {
                    *eax &= ~0x3FFC000;
                    *eax |= (pow2ceil(vcpus_per_socket) - 1) << 14;
                }
            }

物理上的实现

16:46:41 openat(AT_FDCWD, "/sys/firmware/dmi/tables/smbios_entry_point", O_RDONLY) = 3
16:46:41 newfstatat(3, "", {st_mode=S_IFREG|0400, st_size=24, ...}, AT_EMPTY_PATH) = 0
16:46:41 openat(AT_FDCWD, "/sys/firmware/dmi/tables/DMI", O_RDONLY) = 3
└── id
    ├── bios_date
    ├── bios_release
    ├── bios_vendor
    ├── bios_version
    ├── board_asset_tag
    ├── board_name
    ├── board_serial
    ├── board_vendor
    ├── board_version
    ├── chassis_asset_tag
    ├── chassis_serial
    ├── chassis_type
    ├── chassis_vendor
    ├── chassis_version
    ├── modalias
    ├── power
    │   ├── async
    │   ├── autosuspend_delay_ms
    │   ├── control
    │   ├── runtime_active_kids
    │   ├── runtime_active_time
    │   ├── runtime_enabled
    │   ├── runtime_status
    │   ├── runtime_suspended_time
    │   └── runtime_usage
    ├── product_family
    ├── product_name
    ├── product_serial
    ├── product_sku
    ├── product_uuid
    ├── product_version
    ├── subsystem -> ../../../../class/dmi
    ├── sys_vendor
    └── uevent

操作系统的实现: linux/drivers/firmware/dmi_scan.c

smbios 基础

DMI/SMBIOS SUPPORT
M:	Jean Delvare <jdelvare@suse.com>
S:	Maintained
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging.git dmi-for-next
F:	Documentation/ABI/testing/sysfs-firmware-dmi-tables
F:	drivers/firmware/dmi-id.c
F:	drivers/firmware/dmi_scan.c
F:	include/linux/dmi.h

此外,还有这些东西:

找到 dmi_scan_machine 中,其具体的逻辑为:

[!NOTE] 参考神奇海螺的意见,有待验证

Method 1: EFI Configuration Tables

Method 2: Memory Scanning (Non-EFI fallback)

那么如何获取的 efi.smbios3 ,大致过程因为是

  1. GUID Definition: SMBIOS 3.0 has a specific GUID defined as:

#define SMBIOS3_TABLE_GUID EFI_GUID(0xf2fd1544, 0x9794, 0x4a2c, 0x99, 0x2e, 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94)

  1. Table Mapping: The system defines a mapping between the SMBIOS3 GUID and the efi.smbios3 field:
   1    static const efi_config_table_type_t common_tables[] __initconst = {
   2        // ...
   3        {SMBIOS3_TABLE_GUID, &efi.smbios3, "SMBIOS 3.0"},
   4        // ...
   5    };
  1. Runtime Assignment: During early boot, the efi_config_parse_tables() function:
    • Iterates through the EFI configuration tables provided by the firmware
    • For each table, it calls match_config_table() to check if the table’s GUID matches any of the expected GUIDs in the common_tables array
    • When it finds a match between a firmware table’s GUID and SMBIOS3_TABLE_GUID, it assigns the table’s physical address to efi.smbios3 via *(table_types[i].ptr) = table;

DMI 和 SMBIOS 是什么关系?

DMI(Desktop Management Interface)

docs/uefi/dmi.md

似乎 dmidecode 解析的是 qemu 填充的 bmbios 的内容?

本站所有文章转发 CSDN 将按侵权追究法律责任,其它情况随意。