From b3bb4ed21e8802cb38eb693952da058f52cf76b0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 24 Aug 2020 14:41:54 +0200 Subject: [PATCH] Read DMI entries from /sys/firmware/dmi/tables/DMI A kernel with Secure Boot lockdown may prohibit reading the contents of /dev/mem, hence biosdevname fails. The recent kernel provides the DMI byte contents in /sys/firmware/dmi/tables/*, and we can use this instead of poking /dev/mem. Signed-off-by: Takashi Iwai CC: Thomas Renninger CC: Michal Suchanek --- src/dmidecode/dmidecode.c | 54 +++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 13 deletions(-) diff --git a/src/dmidecode/dmidecode.c b/src/dmidecode/dmidecode.c index a01a6ce..f4c1269 100644 --- a/src/dmidecode/dmidecode.c +++ b/src/dmidecode/dmidecode.c @@ -229,7 +229,7 @@ static int isvalidsmbios(int mjr, int mnr) return 0; } -static void dmi_table(u32 base, u16 len, u16 num, u16 ver, const char *devmem, const struct libbiosdevname_state *state) +static int dmi_table(u32 base, u16 len, u16 num, u16 ver, const char *devmem, const struct libbiosdevname_state *state, int sysfs) { u8 *buf; u8 *data; @@ -237,14 +237,19 @@ static void dmi_table(u32 base, u16 len, u16 num, u16 ver, const char *devmem, c /* Verify SMBIOS version */ if (!isvalidsmbios(ver >> 8, ver & 0xFF)) { - return; + return 0; } - if((buf=mem_chunk(base, len, devmem))==NULL) + + if (sysfs) + buf = __mem_chunk(0, len, devmem, 0); + else + buf = mem_chunk(base, len, devmem); + if(buf == NULL) { #ifndef USE_MMAP printf("Table is unreachable, sorry. Try compiling dmidecode with -DUSE_MMAP.\n"); #endif - return; + return 0; } data=buf; @@ -280,18 +285,18 @@ static void dmi_table(u32 base, u16 len, u16 num, u16 ver, const char *devmem, c i++; } free(buf); + return 1; } - -static int smbios_decode(u8 *buf, const char *devmem, const struct libbiosdevname_state *state) +static int smbios_decode(u8 *buf, const char *devmem, const struct libbiosdevname_state *state, int sysfs) { if(checksum(buf, buf[0x05]) && memcmp(buf+0x10, "_DMI_", 5)==0 && checksum(buf+0x10, 0x0F)) { - dmi_table(DWORD(buf+0x18), WORD(buf+0x16), WORD(buf+0x1C), - (buf[0x06]<<8)+buf[0x07], devmem, state); - return 1; + return dmi_table(DWORD(buf+0x18), WORD(buf+0x16), WORD(buf+0x1C), + (buf[0x06]<<8)+buf[0x07], devmem, state, + sysfs); } return 0; @@ -302,13 +307,32 @@ static int legacy_decode(u8 *buf, const char *devmem, const struct libbiosdevnam if(checksum(buf, 0x0F)) { dmi_table(DWORD(buf+0x08), WORD(buf+0x06), WORD(buf+0x0C), - ((buf[0x0E]&0xF0)<<4)+(buf[0x0E]&0x0F), devmem, state); + ((buf[0x0E]&0xF0)<<4)+(buf[0x0E]&0x0F), devmem, state, 0); return 1; } return 0; } +#define SYSFS_TABLE_SMBIOS "/sys/firmware/dmi/tables/smbios_entry_point" +#define SYSFS_TABLE_DMI "/sys/firmware/dmi/tables/DMI" + +static int smibios_decode_from_sysfs(const struct libbiosdevname_state *state) +{ + FILE *fp; + u8 buf[0x1f]; + int len; + + fp = fopen(SYSFS_TABLE_SMBIOS, "r"); + if (!fp) + return 0; + len = fread(buf, 1, sizeof(buf), fp); + fclose(fp); + if (len == 0x1f && memcmp(buf, "_SM_", 4) == 0) + return smbios_decode(buf, SYSFS_TABLE_DMI, state, 1); + return 0; +} + /* * Probe for EFI interface */ @@ -417,7 +441,11 @@ int dmidecode_main(const struct libbiosdevname_state *state) if (dmidecode_read_file(state)) return 0; - /* First try EFI (ia64, Intel-based Mac) */ + /* First try sysfs entries */ + if (smibios_decode_from_sysfs(state)) + return 0; + + /* Next try EFI (ia64, Intel-based Mac) */ efi=address_from_efi(&fp); switch(efi) { @@ -434,7 +462,7 @@ int dmidecode_main(const struct libbiosdevname_state *state) goto exit_free; } - if(smbios_decode(buf, devmem, state)) + if(smbios_decode(buf, devmem, state, 0)) found++; goto done; @@ -450,7 +478,7 @@ memory_scan: { if(memcmp(buf+fp, "_SM_", 4)==0 && fp<=0xFFE0) { - if(smbios_decode(buf+fp, devmem, state)) + if(smbios_decode(buf+fp, devmem, state, 0)) { found++; fp+=16; -- 2.44.0