首页 > 学院 > 开发设计 > 正文

dmi

2019-11-09 17:17:18
字体:
来源:转载
供稿:网友
在arch/arm64/kernel/efi.c 中会对dmi初始化,dmi的全程是Desktop Management Interface.属于smbios的一部分.static int __init arm64_dmi_init(void){    /*     * On arm64, DMI depends on UEFI, and dmi_scan_machine() needs to     * be called early because dmi_id_init(), which is an arch_initcall     * itself, depends on dmi_scan_machine() having been called already.     */    dmi_scan_machine();    if (dmi_available)        dmi_set_dump_stack_arch_desc();    return 0;}core_initcall(arm64_dmi_init);可见是通过core_initcall(arm64_dmi_init);在kernel 初始化阶段自动运行的.void __init dmi_scan_machine(void){    char __iomem *p, *q;    char buf[32];    if (efi_enabled(EFI_CONFIG_TABLES)) {            if (efi.smbios3 != EFI_INVALID_TABLE_ADDR) {        }        if (efi.smbios == EFI_INVALID_TABLE_ADDR)            goto error;        if (!dmi_PResent(buf)) {            dmi_available = 1;            goto out;        }    } else if (IS_ENABLED(CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK)) {    } error:    pr_info("DMI not present or invalid./n"); out:    dmi_initialized = 1;}在dmi_scan_machine 中首先判断 efi.smbios3 != EFI_INVALID_TABLE_ADDR 或者 efi.smbios == EFI_INVALID_TABLE_ADDR,可见dmi是smbios的一部分,且smbios有两个标准smbios 和 smbios3如果条件成立的话就通过memcpy_fromio(buf, p, 32);将32 byte copy到buf中。在dmi_scan_machine 中如果条件不成立,且定义了CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK,就会在0xF0000, 0x10000 这个范围内找dmi的信息。我们之关注efi.smbios3 != EFI_INVALID_TABLE_ADDR 或者 efi.smbios == EFI_INVALID_TABLE_ADDR 成立的情况。然后调用dmi_presentstatic int __init dmi_present(const u8 *buf){    u32 smbios_ver;    if (memcmp(buf, "_SM_", 4) == 0 &&        buf[5] < 32 && dmi_checksum(buf, buf[5])) {        smbios_ver = get_unaligned_be16(buf + 6);        smbios_entry_point_size = buf[5];        memcpy(smbios_entry_point, buf, smbios_entry_point_size);        /* Some BIOS report weird SMBIOS version, fix that up */        switch (smbios_ver) {        case 0x021F:        case 0x0221:            pr_debug("SMBIOS version fixup (2.%d->2.%d)/n",                 smbios_ver & 0xFF, 3);            smbios_ver = 0x0203;            break;        case 0x0233:            pr_debug("SMBIOS version fixup (2.%d->2.%d)/n", 51, 6);            smbios_ver = 0x0206;            break;        }    } else {        smbios_ver = 0;    }    buf += 16;    if (memcmp(buf, "_DMI_", 5) == 0 && dmi_checksum(buf, 15)) {        if (smbios_ver)            dmi_ver = smbios_ver;        else            dmi_ver = (buf[14] & 0xF0) << 4 | (buf[14] & 0x0F);        dmi_ver <<= 8;        dmi_num = get_unaligned_le16(buf + 12);        dmi_len = get_unaligned_le16(buf + 6);        dmi_base = get_unaligned_le32(buf + 8);        if (dmi_walk_early(dmi_decode) == 0) {            if (smbios_ver) {                pr_info("SMBIOS %d.%d present./n",                    dmi_ver >> 16, (dmi_ver >> 8) & 0xFF);            } else {                smbios_entry_point_size = 15;                memcpy(smbios_entry_point, buf,                       smbios_entry_point_size);                pr_info("Legacy DMI %d.%d present./n",                    dmi_ver >> 16, (dmi_ver >> 8) & 0xFF);            }            dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string));            printk(KERN_DEBUG "DMI: %s/n", dmi_ids_string);            return 0;        }    }    return 1;}在dmi_present 中首先得到smbios_ver ,如果smbios_ver 不是NULL,则dmi_ver就等于smbios_ver。否则dmi_ver 重新计算.        if (smbios_ver)            dmi_ver = smbios_ver;        else            dmi_ver = (buf[14] & 0xF0) << 4 | (buf[14] & 0x0F);最后后调用        if (dmi_walk_early(dmi_decode) == 0) {来将dmi中的信息存到kernel中方面其他程序查询.static void __init dmi_decode(const struct dmi_header *dm, void *dummy){    switch (dm->type) {    case 0:        /* BIOS Information */        dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);        dmi_save_ident(dm, DMI_BIOS_VERSION, 5);        dmi_save_ident(dm, DMI_BIOS_DATE, 8);        break;    case 1:        /* System Information */        dmi_save_ident(dm, DMI_SYS_VENDOR, 4);        dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);        dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);        dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7);        dmi_save_uuid(dm, DMI_PRODUCT_UUID, 8);        break;    case 2:        /* Base Board Information */        dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);        dmi_save_ident(dm, DMI_BOARD_NAME, 5);        dmi_save_ident(dm, DMI_BOARD_VERSION, 6);        dmi_save_ident(dm, DMI_BOARD_SERIAL, 7);        dmi_save_ident(dm, DMI_BOARD_ASSET_TAG, 8);        break;    case 3:        /* Chassis Information */        dmi_save_ident(dm, DMI_CHASSIS_VENDOR, 4);        dmi_save_type(dm, DMI_CHASSIS_TYPE, 5);        dmi_save_ident(dm, DMI_CHASSIS_VERSION, 6);        dmi_save_ident(dm, DMI_CHASSIS_SERIAL, 7);        dmi_save_ident(dm, DMI_CHASSIS_ASSET_TAG, 8);        break;    case 9:        /* System Slots */        dmi_save_system_slot(dm);        break;    case 10:    /* Onboard Devices Information */        dmi_save_devices(dm);        break;    case 11:    /* OEM Strings */        dmi_save_oem_strings_devices(dm);        break;    case 38:    /* ipMI Device Information */        dmi_save_ipmi_device(dm);        break;    case 41:    /* Onboard Devices Extended Information */        dmi_save_extended_devices(dm);    }}可见dmi的信息大概分成0/1/2/3/9/10/11/38/41.根据不同的type将信息存到不同的数组中。我们以System Information为例dmi_save_ident(dm, DMI_SYS_VENDOR, 4);static void __init dmi_save_ident(const struct dmi_header *dm, int slot,        int string){    const char *d = (const char *) dm;    const char *p;    if (dmi_ident[slot])        return;    p = dmi_string(dm, d[string]);    if (p == NULL)        return;    dmi_ident[slot] = p;}可见是存在dmi_ident这个数组中。这样我们就可以通过dmi_get_system_info 函数从dmi_ident 数组中拿到System Informationconst char *dmi_get_system_info(int field){    return dmi_ident[field];}EXPORT_SYMBOL(dmi_get_system_info);
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表