11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 58881cdceb25b4fcebfb17a9548ed80c22cf8b066Bjorn Helgaas#include <linux/ctype.h> 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/dmi.h> 73ed3bce846abc7ef460104b461cac793e41afe5eMatt Domsch#include <linux/efi.h> 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bootmem.h> 9d114a33387472555188f142ed8e98acdb8181c6dTony Luck#include <linux/random.h> 10f2d3efedbecc04dc348d723e4c90b46731b3bb48Andi Kleen#include <asm/dmi.h> 110841c04d65937ad2808f59c43cb54a92473c8f0eTony Luck#include <asm/unaligned.h> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13cb5dd7c104c64d7ba8ff4dd3eec3d9b92c378937Paul Jackson/* 14cb5dd7c104c64d7ba8ff4dd3eec3d9b92c378937Paul Jackson * DMI stands for "Desktop Management Interface". It is part 15cb5dd7c104c64d7ba8ff4dd3eec3d9b92c378937Paul Jackson * of and an antecedent to, SMBIOS, which stands for System 16cb5dd7c104c64d7ba8ff4dd3eec3d9b92c378937Paul Jackson * Management BIOS. See further: http://www.dmtf.org/standards 17cb5dd7c104c64d7ba8ff4dd3eec3d9b92c378937Paul Jackson */ 18ffbbb96dd7570b9aafd426cd77a7ee03d224cabfJean Delvarestatic const char dmi_empty_string[] = " "; 1979da4721117fcf188b4b007b775738a530f574daParag Warudkar 20f1d8e614d74b09531b9a85e812485340f3df7b1cZhenzhong Duanstatic u16 __initdata dmi_ver; 219a22b6e76ba75fa0f3963cdec7829156d00a7173Ingo Molnar/* 229a22b6e76ba75fa0f3963cdec7829156d00a7173Ingo Molnar * Catch too early calls to dmi_check_system(): 239a22b6e76ba75fa0f3963cdec7829156d00a7173Ingo Molnar */ 249a22b6e76ba75fa0f3963cdec7829156d00a7173Ingo Molnarstatic int dmi_initialized; 259a22b6e76ba75fa0f3963cdec7829156d00a7173Ingo Molnar 26c90fe6bc0343f7c26b30c9f503b1d061636ac8eeTejun Heo/* DMI system identification string used during boot */ 27c90fe6bc0343f7c26b30c9f503b1d061636ac8eeTejun Heostatic char dmi_ids_string[128] __initdata; 28c90fe6bc0343f7c26b30c9f503b1d061636ac8eeTejun Heo 29dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gongstatic struct dmi_memdev_info { 30dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong const char *device; 31dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong const char *bank; 32dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong u16 handle; 33dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong} *dmi_memdev; 34dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gongstatic int dmi_memdev_nr; 35dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong 36f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvarestatic const char * __init dmi_string_nosave(const struct dmi_header *dm, u8 s) 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 381855256c497ecfefc730df6032243f26855ce52cJeff Garzik const u8 *bp = ((u8 *) dm) + dm->length; 391249c5138f573890eae0c01f13d627094edcd55cAndrey Panin 40c3c7120d552989be94c9137989be5abb6da8954fAndrey Panin if (s) { 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s--; 42c3c7120d552989be94c9137989be5abb6da8954fAndrey Panin while (s > 0 && *bp) { 43c3c7120d552989be94c9137989be5abb6da8954fAndrey Panin bp += strlen(bp) + 1; 44c3c7120d552989be94c9137989be5abb6da8954fAndrey Panin s--; 45c3c7120d552989be94c9137989be5abb6da8954fAndrey Panin } 46c3c7120d552989be94c9137989be5abb6da8954fAndrey Panin 47c3c7120d552989be94c9137989be5abb6da8954fAndrey Panin if (*bp != 0) { 4879da4721117fcf188b4b007b775738a530f574daParag Warudkar size_t len = strlen(bp)+1; 4979da4721117fcf188b4b007b775738a530f574daParag Warudkar size_t cmp_len = len > 8 ? 8 : len; 5079da4721117fcf188b4b007b775738a530f574daParag Warudkar 5179da4721117fcf188b4b007b775738a530f574daParag Warudkar if (!memcmp(bp, dmi_empty_string, cmp_len)) 5279da4721117fcf188b4b007b775738a530f574daParag Warudkar return dmi_empty_string; 53f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare return bp; 54c3c7120d552989be94c9137989be5abb6da8954fAndrey Panin } 554f705ae3e94ffaafe8d35f71ff4d5c499bb06814Bjorn Helgaas } 56c3c7120d552989be94c9137989be5abb6da8954fAndrey Panin 57f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare return ""; 58f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare} 59f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare 60ffbbb96dd7570b9aafd426cd77a7ee03d224cabfJean Delvarestatic const char * __init dmi_string(const struct dmi_header *dm, u8 s) 61f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare{ 62f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare const char *bp = dmi_string_nosave(dm, s); 63f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare char *str; 64f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare size_t len; 65f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare 66f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare if (bp == dmi_empty_string) 67f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare return dmi_empty_string; 68f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare 69f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare len = strlen(bp) + 1; 70f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare str = dmi_alloc(len); 71f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare if (str != NULL) 72f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare strcpy(str, bp); 73f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare 74c3c7120d552989be94c9137989be5abb6da8954fAndrey Panin return str; 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We have to be cautious here. We have seen BIOSes with DMI pointers 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pointing to completely the wrong place for example 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 817fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvarestatic void dmi_table(u8 *buf, int len, int num, 82e7a19c5624c66afa8118b10cd59f87ee407646bcJean Delvare void (*decode)(const struct dmi_header *, void *), 83e7a19c5624c66afa8118b10cd59f87ee407646bcJean Delvare void *private_data) 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 857fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare u8 *data = buf; 861249c5138f573890eae0c01f13d627094edcd55cAndrey Panin int i = 0; 874f705ae3e94ffaafe8d35f71ff4d5c499bb06814Bjorn Helgaas 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 894f705ae3e94ffaafe8d35f71ff4d5c499bb06814Bjorn Helgaas * Stop when we see all the items the table claimed to have 904f705ae3e94ffaafe8d35f71ff4d5c499bb06814Bjorn Helgaas * OR we run off the end of the table (also happens) 914f705ae3e94ffaafe8d35f71ff4d5c499bb06814Bjorn Helgaas */ 921249c5138f573890eae0c01f13d627094edcd55cAndrey Panin while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) { 931855256c497ecfefc730df6032243f26855ce52cJeff Garzik const struct dmi_header *dm = (const struct dmi_header *)data; 941855256c497ecfefc730df6032243f26855ce52cJeff Garzik 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 969390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel * 7.45 End-of-Table (Type 127) [SMBIOS reference spec v3.0.0] 979390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel */ 989390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel if (dm->type == DMI_ENTRY_END_OF_TABLE) 999390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel break; 1009390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel 1019390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel /* 1028638545c3668231675dcf8f46afa7ed5930a6b02Alan Cox * We want to know the total length (formatted area and 1038638545c3668231675dcf8f46afa7ed5930a6b02Alan Cox * strings) before decoding to make sure we won't run off the 1048638545c3668231675dcf8f46afa7ed5930a6b02Alan Cox * table in dmi_decode or dmi_string 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1061249c5138f573890eae0c01f13d627094edcd55cAndrey Panin data += dm->length; 1071249c5138f573890eae0c01f13d627094edcd55cAndrey Panin while ((data - buf < len - 1) && (data[0] || data[1])) 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data++; 1091249c5138f573890eae0c01f13d627094edcd55cAndrey Panin if (data - buf < len - 1) 110e7a19c5624c66afa8118b10cd59f87ee407646bcJean Delvare decode(dm, private_data); 1111249c5138f573890eae0c01f13d627094edcd55cAndrey Panin data += 2; 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i++; 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1147fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare} 1157fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare 1169390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvelstatic phys_addr_t dmi_base; 1177fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvarestatic u16 dmi_len; 1187fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvarestatic u16 dmi_num; 1197fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare 120e7a19c5624c66afa8118b10cd59f87ee407646bcJean Delvarestatic int __init dmi_walk_early(void (*decode)(const struct dmi_header *, 121e7a19c5624c66afa8118b10cd59f87ee407646bcJean Delvare void *)) 1227fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare{ 1237fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare u8 *buf; 1247fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare 125cf0744021c5d5de54d2c66e2020c6de2fe800264Ard Biesheuvel buf = dmi_early_remap(dmi_base, dmi_len); 1267fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare if (buf == NULL) 1277fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare return -1; 1287fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare 129e7a19c5624c66afa8118b10cd59f87ee407646bcJean Delvare dmi_table(buf, dmi_len, dmi_num, decode, NULL); 1307fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare 131d114a33387472555188f142ed8e98acdb8181c6dTony Luck add_device_randomness(buf, dmi_len); 132d114a33387472555188f142ed8e98acdb8181c6dTony Luck 133cf0744021c5d5de54d2c66e2020c6de2fe800264Ard Biesheuvel dmi_early_unmap(buf, dmi_len); 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1379f9c9cbb60576a1518d0bf93fb8e499cffccf377Zhenzhong Duanstatic int __init dmi_checksum(const u8 *buf, u8 len) 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1391249c5138f573890eae0c01f13d627094edcd55cAndrey Panin u8 sum = 0; 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int a; 1414f705ae3e94ffaafe8d35f71ff4d5c499bb06814Bjorn Helgaas 1429f9c9cbb60576a1518d0bf93fb8e499cffccf377Zhenzhong Duan for (a = 0; a < len; a++) 1431249c5138f573890eae0c01f13d627094edcd55cAndrey Panin sum += buf[a]; 1441249c5138f573890eae0c01f13d627094edcd55cAndrey Panin 1451249c5138f573890eae0c01f13d627094edcd55cAndrey Panin return sum == 0; 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 148ffbbb96dd7570b9aafd426cd77a7ee03d224cabfJean Delvarestatic const char *dmi_ident[DMI_STRING_MAX]; 149ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Paninstatic LIST_HEAD(dmi_devices); 1504f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poetteringint dmi_available; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Save a DMI string 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 15502d9c47f1bf2304d6482e1e69e00c06791d86908Jean Delvarestatic void __init dmi_save_ident(const struct dmi_header *dm, int slot, 15602d9c47f1bf2304d6482e1e69e00c06791d86908Jean Delvare int string) 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 15802d9c47f1bf2304d6482e1e69e00c06791d86908Jean Delvare const char *d = (const char *) dm; 159ffbbb96dd7570b9aafd426cd77a7ee03d224cabfJean Delvare const char *p; 1601249c5138f573890eae0c01f13d627094edcd55cAndrey Panin 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dmi_ident[slot]) 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1631249c5138f573890eae0c01f13d627094edcd55cAndrey Panin 164c3c7120d552989be94c9137989be5abb6da8954fAndrey Panin p = dmi_string(dm, d[string]); 165c3c7120d552989be94c9137989be5abb6da8954fAndrey Panin if (p == NULL) 166c3c7120d552989be94c9137989be5abb6da8954fAndrey Panin return; 167c3c7120d552989be94c9137989be5abb6da8954fAndrey Panin 168c3c7120d552989be94c9137989be5abb6da8954fAndrey Panin dmi_ident[slot] = p; 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17102d9c47f1bf2304d6482e1e69e00c06791d86908Jean Delvarestatic void __init dmi_save_uuid(const struct dmi_header *dm, int slot, 17202d9c47f1bf2304d6482e1e69e00c06791d86908Jean Delvare int index) 1734f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering{ 17402d9c47f1bf2304d6482e1e69e00c06791d86908Jean Delvare const u8 *d = (u8 *) dm + index; 1754f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering char *s; 1764f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering int is_ff = 1, is_00 = 1, i; 1774f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering 1784f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering if (dmi_ident[slot]) 1794f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering return; 1804f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering 1814f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering for (i = 0; i < 16 && (is_ff || is_00); i++) { 182f1d8e614d74b09531b9a85e812485340f3df7b1cZhenzhong Duan if (d[i] != 0x00) 183f1d8e614d74b09531b9a85e812485340f3df7b1cZhenzhong Duan is_00 = 0; 184f1d8e614d74b09531b9a85e812485340f3df7b1cZhenzhong Duan if (d[i] != 0xFF) 185f1d8e614d74b09531b9a85e812485340f3df7b1cZhenzhong Duan is_ff = 0; 1864f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering } 1874f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering 1884f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering if (is_ff || is_00) 1894f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering return; 1904f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering 1914f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering s = dmi_alloc(16*2+4+1); 1924f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering if (!s) 1934f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering return; 1944f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering 195f1d8e614d74b09531b9a85e812485340f3df7b1cZhenzhong Duan /* 196f1d8e614d74b09531b9a85e812485340f3df7b1cZhenzhong Duan * As of version 2.6 of the SMBIOS specification, the first 3 fields of 197f1d8e614d74b09531b9a85e812485340f3df7b1cZhenzhong Duan * the UUID are supposed to be little-endian encoded. The specification 198f1d8e614d74b09531b9a85e812485340f3df7b1cZhenzhong Duan * says that this is the defacto standard. 199f1d8e614d74b09531b9a85e812485340f3df7b1cZhenzhong Duan */ 200f1d8e614d74b09531b9a85e812485340f3df7b1cZhenzhong Duan if (dmi_ver >= 0x0206) 201f1d8e614d74b09531b9a85e812485340f3df7b1cZhenzhong Duan sprintf(s, "%pUL", d); 202f1d8e614d74b09531b9a85e812485340f3df7b1cZhenzhong Duan else 203f1d8e614d74b09531b9a85e812485340f3df7b1cZhenzhong Duan sprintf(s, "%pUB", d); 2044f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering 20502d9c47f1bf2304d6482e1e69e00c06791d86908Jean Delvare dmi_ident[slot] = s; 2064f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering} 2074f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering 20802d9c47f1bf2304d6482e1e69e00c06791d86908Jean Delvarestatic void __init dmi_save_type(const struct dmi_header *dm, int slot, 20902d9c47f1bf2304d6482e1e69e00c06791d86908Jean Delvare int index) 2104f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering{ 21102d9c47f1bf2304d6482e1e69e00c06791d86908Jean Delvare const u8 *d = (u8 *) dm + index; 2124f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering char *s; 2134f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering 2144f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering if (dmi_ident[slot]) 2154f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering return; 2164f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering 2174f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering s = dmi_alloc(4); 2184f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering if (!s) 2194f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering return; 2204f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering 2214f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering sprintf(s, "%u", *d & 0x7F); 2224f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering dmi_ident[slot] = s; 2234f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering} 2244f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering 225f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvarestatic void __init dmi_save_one_device(int type, const char *name) 226f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare{ 227f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare struct dmi_device *dev; 228f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare 229f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare /* No duplicate device */ 230f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare if (dmi_find_device(type, name, NULL)) 231f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare return; 232f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare 233f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare dev = dmi_alloc(sizeof(*dev) + strlen(name) + 1); 234ae79744975cb0b3b9c469fe1a05db37d2943c863Jean Delvare if (!dev) 235f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare return; 236f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare 237f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare dev->type = type; 238f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare strcpy((char *)(dev + 1), name); 239f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare dev->name = (char *)(dev + 1); 240f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare dev->device_data = NULL; 241f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare list_add(&dev->list, &dmi_devices); 242f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare} 243f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare 2441855256c497ecfefc730df6032243f26855ce52cJeff Garzikstatic void __init dmi_save_devices(const struct dmi_header *dm) 245ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin{ 246ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin int i, count = (dm->length - sizeof(struct dmi_header)) / 2; 247ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin 248ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin for (i = 0; i < count; i++) { 2491855256c497ecfefc730df6032243f26855ce52cJeff Garzik const char *d = (char *)(dm + 1) + (i * 2); 250ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin 251ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin /* Skip disabled device */ 252ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin if ((*d & 0x80) == 0) 253ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin continue; 254ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin 255f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare dmi_save_one_device(*d & 0x7f, dmi_string_nosave(dm, *(d + 1))); 2562e0c1f6ce7b816f63fea2af3e5e2cb20c66430e9Shem Multinymous } 2572e0c1f6ce7b816f63fea2af3e5e2cb20c66430e9Shem Multinymous} 2582e0c1f6ce7b816f63fea2af3e5e2cb20c66430e9Shem Multinymous 2591855256c497ecfefc730df6032243f26855ce52cJeff Garzikstatic void __init dmi_save_oem_strings_devices(const struct dmi_header *dm) 2602e0c1f6ce7b816f63fea2af3e5e2cb20c66430e9Shem Multinymous{ 2612e0c1f6ce7b816f63fea2af3e5e2cb20c66430e9Shem Multinymous int i, count = *(u8 *)(dm + 1); 2622e0c1f6ce7b816f63fea2af3e5e2cb20c66430e9Shem Multinymous struct dmi_device *dev; 2632e0c1f6ce7b816f63fea2af3e5e2cb20c66430e9Shem Multinymous 2642e0c1f6ce7b816f63fea2af3e5e2cb20c66430e9Shem Multinymous for (i = 1; i <= count; i++) { 265ffbbb96dd7570b9aafd426cd77a7ee03d224cabfJean Delvare const char *devname = dmi_string(dm, i); 26679da4721117fcf188b4b007b775738a530f574daParag Warudkar 26743fe105a5c91b2f00ea7f900ed307fe980410612Jean Delvare if (devname == dmi_empty_string) 26879da4721117fcf188b4b007b775738a530f574daParag Warudkar continue; 26979da4721117fcf188b4b007b775738a530f574daParag Warudkar 2702e0c1f6ce7b816f63fea2af3e5e2cb20c66430e9Shem Multinymous dev = dmi_alloc(sizeof(*dev)); 271ae79744975cb0b3b9c469fe1a05db37d2943c863Jean Delvare if (!dev) 2722e0c1f6ce7b816f63fea2af3e5e2cb20c66430e9Shem Multinymous break; 2732e0c1f6ce7b816f63fea2af3e5e2cb20c66430e9Shem Multinymous 2742e0c1f6ce7b816f63fea2af3e5e2cb20c66430e9Shem Multinymous dev->type = DMI_DEV_TYPE_OEM_STRING; 27579da4721117fcf188b4b007b775738a530f574daParag Warudkar dev->name = devname; 2762e0c1f6ce7b816f63fea2af3e5e2cb20c66430e9Shem Multinymous dev->device_data = NULL; 277ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin 278ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin list_add(&dev->list, &dmi_devices); 279ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin } 280ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin} 281ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin 2821855256c497ecfefc730df6032243f26855ce52cJeff Garzikstatic void __init dmi_save_ipmi_device(const struct dmi_header *dm) 283ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin{ 284ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin struct dmi_device *dev; 28502d9c47f1bf2304d6482e1e69e00c06791d86908Jean Delvare void *data; 286ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin 287e99286744599a66195de4cd975d7ef4d643c2789Andi Kleen data = dmi_alloc(dm->length); 288ae79744975cb0b3b9c469fe1a05db37d2943c863Jean Delvare if (data == NULL) 289ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin return; 290ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin 291ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin memcpy(data, dm, dm->length); 292ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin 293e99286744599a66195de4cd975d7ef4d643c2789Andi Kleen dev = dmi_alloc(sizeof(*dev)); 294ae79744975cb0b3b9c469fe1a05db37d2943c863Jean Delvare if (!dev) 295ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin return; 296ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin 297ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin dev->type = DMI_DEV_TYPE_IPMI; 298ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin dev->name = "IPMI controller"; 299ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin dev->device_data = data; 300ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin 301abd24df828f1a72971db29d1b74fefae104ea9e2Carol Hebert list_add_tail(&dev->list, &dmi_devices); 302ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin} 303ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin 304911e1c9b05a8e3559a7aa89083930700a0b9e7eeNarendra Kstatic void __init dmi_save_dev_onboard(int instance, int segment, int bus, 305911e1c9b05a8e3559a7aa89083930700a0b9e7eeNarendra K int devfn, const char *name) 306911e1c9b05a8e3559a7aa89083930700a0b9e7eeNarendra K{ 307911e1c9b05a8e3559a7aa89083930700a0b9e7eeNarendra K struct dmi_dev_onboard *onboard_dev; 308911e1c9b05a8e3559a7aa89083930700a0b9e7eeNarendra K 309911e1c9b05a8e3559a7aa89083930700a0b9e7eeNarendra K onboard_dev = dmi_alloc(sizeof(*onboard_dev) + strlen(name) + 1); 310ae79744975cb0b3b9c469fe1a05db37d2943c863Jean Delvare if (!onboard_dev) 311911e1c9b05a8e3559a7aa89083930700a0b9e7eeNarendra K return; 312ae79744975cb0b3b9c469fe1a05db37d2943c863Jean Delvare 313911e1c9b05a8e3559a7aa89083930700a0b9e7eeNarendra K onboard_dev->instance = instance; 314911e1c9b05a8e3559a7aa89083930700a0b9e7eeNarendra K onboard_dev->segment = segment; 315911e1c9b05a8e3559a7aa89083930700a0b9e7eeNarendra K onboard_dev->bus = bus; 316911e1c9b05a8e3559a7aa89083930700a0b9e7eeNarendra K onboard_dev->devfn = devfn; 317911e1c9b05a8e3559a7aa89083930700a0b9e7eeNarendra K 318911e1c9b05a8e3559a7aa89083930700a0b9e7eeNarendra K strcpy((char *)&onboard_dev[1], name); 319911e1c9b05a8e3559a7aa89083930700a0b9e7eeNarendra K onboard_dev->dev.type = DMI_DEV_TYPE_DEV_ONBOARD; 320911e1c9b05a8e3559a7aa89083930700a0b9e7eeNarendra K onboard_dev->dev.name = (char *)&onboard_dev[1]; 321911e1c9b05a8e3559a7aa89083930700a0b9e7eeNarendra K onboard_dev->dev.device_data = onboard_dev; 322911e1c9b05a8e3559a7aa89083930700a0b9e7eeNarendra K 323911e1c9b05a8e3559a7aa89083930700a0b9e7eeNarendra K list_add(&onboard_dev->dev.list, &dmi_devices); 324911e1c9b05a8e3559a7aa89083930700a0b9e7eeNarendra K} 325911e1c9b05a8e3559a7aa89083930700a0b9e7eeNarendra K 326b4bd7d59451960d4e1d994c01581b31b08fe3720Wim Van Sebroeckstatic void __init dmi_save_extended_devices(const struct dmi_header *dm) 327b4bd7d59451960d4e1d994c01581b31b08fe3720Wim Van Sebroeck{ 32802d9c47f1bf2304d6482e1e69e00c06791d86908Jean Delvare const u8 *d = (u8 *) dm + 5; 329b4bd7d59451960d4e1d994c01581b31b08fe3720Wim Van Sebroeck 330b4bd7d59451960d4e1d994c01581b31b08fe3720Wim Van Sebroeck /* Skip disabled device */ 331b4bd7d59451960d4e1d994c01581b31b08fe3720Wim Van Sebroeck if ((*d & 0x80) == 0) 332b4bd7d59451960d4e1d994c01581b31b08fe3720Wim Van Sebroeck return; 333b4bd7d59451960d4e1d994c01581b31b08fe3720Wim Van Sebroeck 334911e1c9b05a8e3559a7aa89083930700a0b9e7eeNarendra K dmi_save_dev_onboard(*(d+1), *(u16 *)(d+2), *(d+4), *(d+5), 335911e1c9b05a8e3559a7aa89083930700a0b9e7eeNarendra K dmi_string_nosave(dm, *(d-1))); 336f3069ae9d76901d021362bb63d9ad6c5900dfc76Jean Delvare dmi_save_one_device(*d & 0x7f, dmi_string_nosave(dm, *(d - 1))); 337b4bd7d59451960d4e1d994c01581b31b08fe3720Wim Van Sebroeck} 338b4bd7d59451960d4e1d994c01581b31b08fe3720Wim Van Sebroeck 339dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gongstatic void __init count_mem_devices(const struct dmi_header *dm, void *v) 340dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong{ 341dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong if (dm->type != DMI_ENTRY_MEM_DEVICE) 342dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong return; 343dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong dmi_memdev_nr++; 344dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong} 345dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong 346dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gongstatic void __init save_mem_devices(const struct dmi_header *dm, void *v) 347dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong{ 348dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong const char *d = (const char *)dm; 349dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong static int nr; 350dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong 351dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong if (dm->type != DMI_ENTRY_MEM_DEVICE) 352dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong return; 353dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong if (nr >= dmi_memdev_nr) { 354dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong pr_warn(FW_BUG "Too many DIMM entries in SMBIOS table\n"); 355dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong return; 356dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong } 3570841c04d65937ad2808f59c43cb54a92473c8f0eTony Luck dmi_memdev[nr].handle = get_unaligned(&dm->handle); 358dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong dmi_memdev[nr].device = dmi_string(dm, d[0x10]); 359dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong dmi_memdev[nr].bank = dmi_string(dm, d[0x11]); 360dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong nr++; 361dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong} 362dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong 363dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gongvoid __init dmi_memdev_walk(void) 364dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong{ 365dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong if (!dmi_available) 366dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong return; 367dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong 368dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong if (dmi_walk_early(count_mem_devices) == 0 && dmi_memdev_nr) { 369dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong dmi_memdev = dmi_alloc(sizeof(*dmi_memdev) * dmi_memdev_nr); 370dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong if (dmi_memdev) 371dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong dmi_walk_early(save_mem_devices); 372dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong } 373dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong} 374dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Process a DMI table entry. Right now all we care about are the BIOS 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and machine entries. For 2.5 we should pull the smbus controller info 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * out of here. 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 380e7a19c5624c66afa8118b10cd59f87ee407646bcJean Delvarestatic void __init dmi_decode(const struct dmi_header *dm, void *dummy) 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 38202d9c47f1bf2304d6482e1e69e00c06791d86908Jean Delvare switch (dm->type) { 383ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin case 0: /* BIOS Information */ 3841249c5138f573890eae0c01f13d627094edcd55cAndrey Panin dmi_save_ident(dm, DMI_BIOS_VENDOR, 4); 3851249c5138f573890eae0c01f13d627094edcd55cAndrey Panin dmi_save_ident(dm, DMI_BIOS_VERSION, 5); 3861249c5138f573890eae0c01f13d627094edcd55cAndrey Panin dmi_save_ident(dm, DMI_BIOS_DATE, 8); 3871249c5138f573890eae0c01f13d627094edcd55cAndrey Panin break; 388ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin case 1: /* System Information */ 3891249c5138f573890eae0c01f13d627094edcd55cAndrey Panin dmi_save_ident(dm, DMI_SYS_VENDOR, 4); 3901249c5138f573890eae0c01f13d627094edcd55cAndrey Panin dmi_save_ident(dm, DMI_PRODUCT_NAME, 5); 3911249c5138f573890eae0c01f13d627094edcd55cAndrey Panin dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6); 3921249c5138f573890eae0c01f13d627094edcd55cAndrey Panin dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7); 3934f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering dmi_save_uuid(dm, DMI_PRODUCT_UUID, 8); 3941249c5138f573890eae0c01f13d627094edcd55cAndrey Panin break; 395ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin case 2: /* Base Board Information */ 3961249c5138f573890eae0c01f13d627094edcd55cAndrey Panin dmi_save_ident(dm, DMI_BOARD_VENDOR, 4); 3971249c5138f573890eae0c01f13d627094edcd55cAndrey Panin dmi_save_ident(dm, DMI_BOARD_NAME, 5); 3981249c5138f573890eae0c01f13d627094edcd55cAndrey Panin dmi_save_ident(dm, DMI_BOARD_VERSION, 6); 3994f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering dmi_save_ident(dm, DMI_BOARD_SERIAL, 7); 4004f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering dmi_save_ident(dm, DMI_BOARD_ASSET_TAG, 8); 4014f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering break; 4024f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering case 3: /* Chassis Information */ 4034f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering dmi_save_ident(dm, DMI_CHASSIS_VENDOR, 4); 4044f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering dmi_save_type(dm, DMI_CHASSIS_TYPE, 5); 4054f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering dmi_save_ident(dm, DMI_CHASSIS_VERSION, 6); 4064f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering dmi_save_ident(dm, DMI_CHASSIS_SERIAL, 7); 4074f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering dmi_save_ident(dm, DMI_CHASSIS_ASSET_TAG, 8); 4081249c5138f573890eae0c01f13d627094edcd55cAndrey Panin break; 409ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin case 10: /* Onboard Devices Information */ 410ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin dmi_save_devices(dm); 411ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin break; 4122e0c1f6ce7b816f63fea2af3e5e2cb20c66430e9Shem Multinymous case 11: /* OEM Strings */ 4132e0c1f6ce7b816f63fea2af3e5e2cb20c66430e9Shem Multinymous dmi_save_oem_strings_devices(dm); 4142e0c1f6ce7b816f63fea2af3e5e2cb20c66430e9Shem Multinymous break; 415ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin case 38: /* IPMI Device Information */ 416ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin dmi_save_ipmi_device(dm); 417b4bd7d59451960d4e1d994c01581b31b08fe3720Wim Van Sebroeck break; 418b4bd7d59451960d4e1d994c01581b31b08fe3720Wim Van Sebroeck case 41: /* Onboard Devices Extended Information */ 419b4bd7d59451960d4e1d994c01581b31b08fe3720Wim Van Sebroeck dmi_save_extended_devices(dm); 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 423c90fe6bc0343f7c26b30c9f503b1d061636ac8eeTejun Heostatic int __init print_filtered(char *buf, size_t len, const char *info) 4248881cdceb25b4fcebfb17a9548ed80c22cf8b066Bjorn Helgaas{ 425c90fe6bc0343f7c26b30c9f503b1d061636ac8eeTejun Heo int c = 0; 4268881cdceb25b4fcebfb17a9548ed80c22cf8b066Bjorn Helgaas const char *p; 4278881cdceb25b4fcebfb17a9548ed80c22cf8b066Bjorn Helgaas 4288881cdceb25b4fcebfb17a9548ed80c22cf8b066Bjorn Helgaas if (!info) 429c90fe6bc0343f7c26b30c9f503b1d061636ac8eeTejun Heo return c; 4308881cdceb25b4fcebfb17a9548ed80c22cf8b066Bjorn Helgaas 4318881cdceb25b4fcebfb17a9548ed80c22cf8b066Bjorn Helgaas for (p = info; *p; p++) 4328881cdceb25b4fcebfb17a9548ed80c22cf8b066Bjorn Helgaas if (isprint(*p)) 433c90fe6bc0343f7c26b30c9f503b1d061636ac8eeTejun Heo c += scnprintf(buf + c, len - c, "%c", *p); 4348881cdceb25b4fcebfb17a9548ed80c22cf8b066Bjorn Helgaas else 435c90fe6bc0343f7c26b30c9f503b1d061636ac8eeTejun Heo c += scnprintf(buf + c, len - c, "\\x%02x", *p & 0xff); 436c90fe6bc0343f7c26b30c9f503b1d061636ac8eeTejun Heo return c; 4378881cdceb25b4fcebfb17a9548ed80c22cf8b066Bjorn Helgaas} 4388881cdceb25b4fcebfb17a9548ed80c22cf8b066Bjorn Helgaas 439c90fe6bc0343f7c26b30c9f503b1d061636ac8eeTejun Heostatic void __init dmi_format_ids(char *buf, size_t len) 4408881cdceb25b4fcebfb17a9548ed80c22cf8b066Bjorn Helgaas{ 441c90fe6bc0343f7c26b30c9f503b1d061636ac8eeTejun Heo int c = 0; 44284e383b322e5348db03be54ff64cc6da87003717Naga Chumbalkar const char *board; /* Board Name is optional */ 44384e383b322e5348db03be54ff64cc6da87003717Naga Chumbalkar 444c90fe6bc0343f7c26b30c9f503b1d061636ac8eeTejun Heo c += print_filtered(buf + c, len - c, 445c90fe6bc0343f7c26b30c9f503b1d061636ac8eeTejun Heo dmi_get_system_info(DMI_SYS_VENDOR)); 446c90fe6bc0343f7c26b30c9f503b1d061636ac8eeTejun Heo c += scnprintf(buf + c, len - c, " "); 447c90fe6bc0343f7c26b30c9f503b1d061636ac8eeTejun Heo c += print_filtered(buf + c, len - c, 448c90fe6bc0343f7c26b30c9f503b1d061636ac8eeTejun Heo dmi_get_system_info(DMI_PRODUCT_NAME)); 449c90fe6bc0343f7c26b30c9f503b1d061636ac8eeTejun Heo 45084e383b322e5348db03be54ff64cc6da87003717Naga Chumbalkar board = dmi_get_system_info(DMI_BOARD_NAME); 45184e383b322e5348db03be54ff64cc6da87003717Naga Chumbalkar if (board) { 452c90fe6bc0343f7c26b30c9f503b1d061636ac8eeTejun Heo c += scnprintf(buf + c, len - c, "/"); 453c90fe6bc0343f7c26b30c9f503b1d061636ac8eeTejun Heo c += print_filtered(buf + c, len - c, board); 45484e383b322e5348db03be54ff64cc6da87003717Naga Chumbalkar } 455c90fe6bc0343f7c26b30c9f503b1d061636ac8eeTejun Heo c += scnprintf(buf + c, len - c, ", BIOS "); 456c90fe6bc0343f7c26b30c9f503b1d061636ac8eeTejun Heo c += print_filtered(buf + c, len - c, 457c90fe6bc0343f7c26b30c9f503b1d061636ac8eeTejun Heo dmi_get_system_info(DMI_BIOS_VERSION)); 458c90fe6bc0343f7c26b30c9f503b1d061636ac8eeTejun Heo c += scnprintf(buf + c, len - c, " "); 459c90fe6bc0343f7c26b30c9f503b1d061636ac8eeTejun Heo c += print_filtered(buf + c, len - c, 460c90fe6bc0343f7c26b30c9f503b1d061636ac8eeTejun Heo dmi_get_system_info(DMI_BIOS_DATE)); 4618881cdceb25b4fcebfb17a9548ed80c22cf8b066Bjorn Helgaas} 4628881cdceb25b4fcebfb17a9548ed80c22cf8b066Bjorn Helgaas 463d39de28c95876f8becb559d242eefe718ea1f747Ben Hutchings/* 464d39de28c95876f8becb559d242eefe718ea1f747Ben Hutchings * Check for DMI/SMBIOS headers in the system firmware image. Any 465d39de28c95876f8becb559d242eefe718ea1f747Ben Hutchings * SMBIOS header must start 16 bytes before the DMI header, so take a 466d39de28c95876f8becb559d242eefe718ea1f747Ben Hutchings * 32 byte buffer and check for DMI at offset 16 and SMBIOS at offset 467d39de28c95876f8becb559d242eefe718ea1f747Ben Hutchings * 0. If the DMI header is present, set dmi_ver accordingly (SMBIOS 468d39de28c95876f8becb559d242eefe718ea1f747Ben Hutchings * takes precedence) and return 0. Otherwise return 1. 469d39de28c95876f8becb559d242eefe718ea1f747Ben Hutchings */ 47079bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchingsstatic int __init dmi_present(const u8 *buf) 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 47279bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings int smbios_ver; 4731855256c497ecfefc730df6032243f26855ce52cJeff Garzik 47479bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings if (memcmp(buf, "_SM_", 4) == 0 && 47579bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings buf[5] < 32 && dmi_checksum(buf, buf[5])) { 4769390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel smbios_ver = get_unaligned_be16(buf + 6); 47779bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings 47879bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings /* Some BIOS report weird SMBIOS version, fix that up */ 47979bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings switch (smbios_ver) { 48079bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings case 0x021F: 48179bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings case 0x0221: 48279bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", 48379bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings smbios_ver & 0xFF, 3); 48479bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings smbios_ver = 0x0203; 48579bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings break; 48679bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings case 0x0233: 48779bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", 51, 6); 48879bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings smbios_ver = 0x0206; 48979bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings break; 49079bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings } 49179bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings } else { 49279bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings smbios_ver = 0; 49379bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings } 49479bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings 49579bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings buf += 16; 49679bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings 49779bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings if (memcmp(buf, "_DMI_", 5) == 0 && dmi_checksum(buf, 15)) { 4989390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel dmi_num = get_unaligned_le16(buf + 12); 4999390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel dmi_len = get_unaligned_le16(buf + 6); 5009390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel dmi_base = get_unaligned_le32(buf + 8); 50161e032fa2f659fada02ede5087b46963a1c7de34Andrey Panin 5028881cdceb25b4fcebfb17a9548ed80c22cf8b066Bjorn Helgaas if (dmi_walk_early(dmi_decode) == 0) { 50379bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings if (smbios_ver) { 50479bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings dmi_ver = smbios_ver; 5059f9c9cbb60576a1518d0bf93fb8e499cffccf377Zhenzhong Duan pr_info("SMBIOS %d.%d present.\n", 5069f9c9cbb60576a1518d0bf93fb8e499cffccf377Zhenzhong Duan dmi_ver >> 8, dmi_ver & 0xFF); 50779bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings } else { 5089f9c9cbb60576a1518d0bf93fb8e499cffccf377Zhenzhong Duan dmi_ver = (buf[14] & 0xF0) << 4 | 5099f9c9cbb60576a1518d0bf93fb8e499cffccf377Zhenzhong Duan (buf[14] & 0x0F); 5109f9c9cbb60576a1518d0bf93fb8e499cffccf377Zhenzhong Duan pr_info("Legacy DMI %d.%d present.\n", 5119f9c9cbb60576a1518d0bf93fb8e499cffccf377Zhenzhong Duan dmi_ver >> 8, dmi_ver & 0xFF); 5129f9c9cbb60576a1518d0bf93fb8e499cffccf377Zhenzhong Duan } 513c90fe6bc0343f7c26b30c9f503b1d061636ac8eeTejun Heo dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string)); 514c90fe6bc0343f7c26b30c9f503b1d061636ac8eeTejun Heo printk(KERN_DEBUG "DMI: %s\n", dmi_ids_string); 5153ed3bce846abc7ef460104b461cac793e41afe5eMatt Domsch return 0; 5168881cdceb25b4fcebfb17a9548ed80c22cf8b066Bjorn Helgaas } 5173ed3bce846abc7ef460104b461cac793e41afe5eMatt Domsch } 51861e032fa2f659fada02ede5087b46963a1c7de34Andrey Panin 519a40e7cf8f06b4e322ba902e4e9f6a6b0c2daa907Ben Hutchings return 1; 5209f9c9cbb60576a1518d0bf93fb8e499cffccf377Zhenzhong Duan} 5219f9c9cbb60576a1518d0bf93fb8e499cffccf377Zhenzhong Duan 5229390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel/* 5239390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel * Check for the SMBIOS 3.0 64-bit entry point signature. Unlike the legacy 5249390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel * 32-bit entry point, there is no embedded DMI header (_DMI_) in here. 5259390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel */ 5269390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvelstatic int __init dmi_smbios3_present(const u8 *buf) 5279390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel{ 5289390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel if (memcmp(buf, "_SM3_", 5) == 0 && 5299390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel buf[6] < 32 && dmi_checksum(buf, buf[6])) { 5309390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel dmi_ver = get_unaligned_be16(buf + 7); 5319390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel dmi_len = get_unaligned_le32(buf + 12); 5329390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel dmi_base = get_unaligned_le64(buf + 16); 5339390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel 5349390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel /* 5359390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel * The 64-bit SMBIOS 3.0 entry point no longer has a field 5369390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel * containing the number of structures present in the table. 5379390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel * Instead, it defines the table size as a maximum size, and 5389390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel * relies on the end-of-table structure type (#127) to be used 5399390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel * to signal the end of the table. 5409390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel * So let's define dmi_num as an upper bound as well: each 5419390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel * structure has a 4 byte header, so dmi_len / 4 is an upper 5429390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel * bound for the number of structures in the table. 5439390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel */ 5449390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel dmi_num = dmi_len / 4; 5459390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel 5469390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel if (dmi_walk_early(dmi_decode) == 0) { 5479390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel pr_info("SMBIOS %d.%d present.\n", 5489390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel dmi_ver >> 8, dmi_ver & 0xFF); 5499390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string)); 5509390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel pr_debug("DMI: %s\n", dmi_ids_string); 5519390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel return 0; 5529390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel } 5539390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel } 5549390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel return 1; 5559390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel} 5569390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel 5573ed3bce846abc7ef460104b461cac793e41afe5eMatt Domschvoid __init dmi_scan_machine(void) 5583ed3bce846abc7ef460104b461cac793e41afe5eMatt Domsch{ 5593ed3bce846abc7ef460104b461cac793e41afe5eMatt Domsch char __iomem *p, *q; 56079bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings char buf[32]; 5613ed3bce846abc7ef460104b461cac793e41afe5eMatt Domsch 56283e68189745ad931c2afd45d8ee3303929233e7fMatt Fleming if (efi_enabled(EFI_CONFIG_TABLES)) { 5639390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel /* 5649390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel * According to the DMTF SMBIOS reference spec v3.0.0, it is 5659390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel * allowed to define both the 64-bit entry point (smbios3) and 5669390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel * the 32-bit entry point (smbios), in which case they should 5679390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel * either both point to the same SMBIOS structure table, or the 5689390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel * table pointed to by the 64-bit entry point should contain a 5699390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel * superset of the table contents pointed to by the 32-bit entry 5709390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel * point (section 5.2) 5719390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel * This implies that the 64-bit entry point should have 5729390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel * precedence if it is defined and supported by the OS. If we 5739390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel * have the 64-bit entry point, but fail to decode it, fall 5749390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel * back to the legacy one (if available) 5759390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel */ 5769390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel if (efi.smbios3 != EFI_INVALID_TABLE_ADDR) { 5779390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel p = dmi_early_remap(efi.smbios3, 32); 5789390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel if (p == NULL) 5799390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel goto error; 5809390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel memcpy_fromio(buf, p, 32); 5819390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel dmi_early_unmap(p, 32); 5829390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel 5839390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel if (!dmi_smbios3_present(buf)) { 5849390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel dmi_available = 1; 5859390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel goto out; 5869390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel } 5879390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel } 588b2c99e3c70d77fb194df5aa1642030080d28ea48Bjorn Helgaas if (efi.smbios == EFI_INVALID_TABLE_ADDR) 5899a22b6e76ba75fa0f3963cdec7829156d00a7173Ingo Molnar goto error; 5903ed3bce846abc7ef460104b461cac793e41afe5eMatt Domsch 5914f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering /* This is called as a core_initcall() because it isn't 5924f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering * needed during early boot. This also means we can 5934f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering * iounmap the space when we're done with it. 5944f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering */ 595cf0744021c5d5de54d2c66e2020c6de2fe800264Ard Biesheuvel p = dmi_early_remap(efi.smbios, 32); 5963ed3bce846abc7ef460104b461cac793e41afe5eMatt Domsch if (p == NULL) 5979a22b6e76ba75fa0f3963cdec7829156d00a7173Ingo Molnar goto error; 59879bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings memcpy_fromio(buf, p, 32); 599cf0744021c5d5de54d2c66e2020c6de2fe800264Ard Biesheuvel dmi_early_unmap(p, 32); 60079bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings 60179bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings if (!dmi_present(buf)) { 6024f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering dmi_available = 1; 6039a22b6e76ba75fa0f3963cdec7829156d00a7173Ingo Molnar goto out; 6044f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering } 605cf0744021c5d5de54d2c66e2020c6de2fe800264Ard Biesheuvel } else if (IS_ENABLED(CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK)) { 606cf0744021c5d5de54d2c66e2020c6de2fe800264Ard Biesheuvel p = dmi_early_remap(0xF0000, 0x10000); 6073ed3bce846abc7ef460104b461cac793e41afe5eMatt Domsch if (p == NULL) 6089a22b6e76ba75fa0f3963cdec7829156d00a7173Ingo Molnar goto error; 6093ed3bce846abc7ef460104b461cac793e41afe5eMatt Domsch 610d39de28c95876f8becb559d242eefe718ea1f747Ben Hutchings /* 611d39de28c95876f8becb559d242eefe718ea1f747Ben Hutchings * Iterate over all possible DMI header addresses q. 612d39de28c95876f8becb559d242eefe718ea1f747Ben Hutchings * Maintain the 32 bytes around q in buf. On the 613d39de28c95876f8becb559d242eefe718ea1f747Ben Hutchings * first iteration, substitute zero for the 614d39de28c95876f8becb559d242eefe718ea1f747Ben Hutchings * out-of-range bytes so there is no chance of falsely 615d39de28c95876f8becb559d242eefe718ea1f747Ben Hutchings * detecting an SMBIOS header. 616d39de28c95876f8becb559d242eefe718ea1f747Ben Hutchings */ 61779bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings memset(buf, 0, 16); 6183ed3bce846abc7ef460104b461cac793e41afe5eMatt Domsch for (q = p; q < p + 0x10000; q += 16) { 61979bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings memcpy_fromio(buf + 16, q, 16); 6209390abcdbc7cb720109a63e7157d3561b22631bfArd Biesheuvel if (!dmi_smbios3_present(buf) || !dmi_present(buf)) { 6214f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering dmi_available = 1; 622cf0744021c5d5de54d2c66e2020c6de2fe800264Ard Biesheuvel dmi_early_unmap(p, 0x10000); 6239a22b6e76ba75fa0f3963cdec7829156d00a7173Ingo Molnar goto out; 6244f5c791a850e5305a5b1b48d0e4b4de248dc96f9Lennart Poettering } 62579bae42d51a5d498500c890c19ef76df41d2bf59Ben Hutchings memcpy(buf, buf + 16, 16); 62661e032fa2f659fada02ede5087b46963a1c7de34Andrey Panin } 627cf0744021c5d5de54d2c66e2020c6de2fe800264Ard Biesheuvel dmi_early_unmap(p, 0x10000); 62861e032fa2f659fada02ede5087b46963a1c7de34Andrey Panin } 6299a22b6e76ba75fa0f3963cdec7829156d00a7173Ingo Molnar error: 63002d9c47f1bf2304d6482e1e69e00c06791d86908Jean Delvare pr_info("DMI not present or invalid.\n"); 6319a22b6e76ba75fa0f3963cdec7829156d00a7173Ingo Molnar out: 6329a22b6e76ba75fa0f3963cdec7829156d00a7173Ingo Molnar dmi_initialized = 1; 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 63698e5e1bf722c4f976a860aed06dd365a56a34ee0Tejun Heo * dmi_set_dump_stack_arch_desc - set arch description for dump_stack() 63798e5e1bf722c4f976a860aed06dd365a56a34ee0Tejun Heo * 63898e5e1bf722c4f976a860aed06dd365a56a34ee0Tejun Heo * Invoke dump_stack_set_arch_desc() with DMI system information so that 63998e5e1bf722c4f976a860aed06dd365a56a34ee0Tejun Heo * DMI identifiers are printed out on task dumps. Arch boot code should 64098e5e1bf722c4f976a860aed06dd365a56a34ee0Tejun Heo * call this function after dmi_scan_machine() if it wants to print out DMI 64198e5e1bf722c4f976a860aed06dd365a56a34ee0Tejun Heo * identifiers on task dumps. 64298e5e1bf722c4f976a860aed06dd365a56a34ee0Tejun Heo */ 64398e5e1bf722c4f976a860aed06dd365a56a34ee0Tejun Heovoid __init dmi_set_dump_stack_arch_desc(void) 64498e5e1bf722c4f976a860aed06dd365a56a34ee0Tejun Heo{ 64598e5e1bf722c4f976a860aed06dd365a56a34ee0Tejun Heo dump_stack_set_arch_desc("%s", dmi_ids_string); 64698e5e1bf722c4f976a860aed06dd365a56a34ee0Tejun Heo} 64798e5e1bf722c4f976a860aed06dd365a56a34ee0Tejun Heo 64898e5e1bf722c4f976a860aed06dd365a56a34ee0Tejun Heo/** 649d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki * dmi_matches - check if dmi_system_id structure matches system DMI data 650d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki * @dmi: pointer to the dmi_system_id structure to check 651d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki */ 652d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysockistatic bool dmi_matches(const struct dmi_system_id *dmi) 653d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki{ 654d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki int i; 655d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki 656d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki WARN(!dmi_initialized, KERN_ERR "dmi check: not initialized yet.\n"); 657d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki 658d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki for (i = 0; i < ARRAY_SIZE(dmi->matches); i++) { 659d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki int s = dmi->matches[i].slot; 660d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki if (s == DMI_NONE) 66175757507e014fa074d25d2883c4ab604999584bdDmitry Torokhov break; 6625017b2851373ee15c7035151853bb1448800cae2Jani Nikula if (dmi_ident[s]) { 6635017b2851373ee15c7035151853bb1448800cae2Jani Nikula if (!dmi->matches[i].exact_match && 6645017b2851373ee15c7035151853bb1448800cae2Jani Nikula strstr(dmi_ident[s], dmi->matches[i].substr)) 6655017b2851373ee15c7035151853bb1448800cae2Jani Nikula continue; 6665017b2851373ee15c7035151853bb1448800cae2Jani Nikula else if (dmi->matches[i].exact_match && 6675017b2851373ee15c7035151853bb1448800cae2Jani Nikula !strcmp(dmi_ident[s], dmi->matches[i].substr)) 6685017b2851373ee15c7035151853bb1448800cae2Jani Nikula continue; 6695017b2851373ee15c7035151853bb1448800cae2Jani Nikula } 6705017b2851373ee15c7035151853bb1448800cae2Jani Nikula 671d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki /* No match */ 672d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki return false; 673d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki } 674d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki return true; 675d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki} 676d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki 677d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki/** 67875757507e014fa074d25d2883c4ab604999584bdDmitry Torokhov * dmi_is_end_of_table - check for end-of-table marker 67975757507e014fa074d25d2883c4ab604999584bdDmitry Torokhov * @dmi: pointer to the dmi_system_id structure to check 68075757507e014fa074d25d2883c4ab604999584bdDmitry Torokhov */ 68175757507e014fa074d25d2883c4ab604999584bdDmitry Torokhovstatic bool dmi_is_end_of_table(const struct dmi_system_id *dmi) 68275757507e014fa074d25d2883c4ab604999584bdDmitry Torokhov{ 68375757507e014fa074d25d2883c4ab604999584bdDmitry Torokhov return dmi->matches[0].slot == DMI_NONE; 68475757507e014fa074d25d2883c4ab604999584bdDmitry Torokhov} 68575757507e014fa074d25d2883c4ab604999584bdDmitry Torokhov 68675757507e014fa074d25d2883c4ab604999584bdDmitry Torokhov/** 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * dmi_check_system - check system DMI data 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @list: array of dmi_system_id structures to match against 689b0ef371e3f9fa3b2571058be366a6780827ec0bfRandy Dunlap * All non-null elements of the list must match 690b0ef371e3f9fa3b2571058be366a6780827ec0bfRandy Dunlap * their slot's (field index's) data (i.e., each 691b0ef371e3f9fa3b2571058be366a6780827ec0bfRandy Dunlap * list string must be a substring of the specified 692b0ef371e3f9fa3b2571058be366a6780827ec0bfRandy Dunlap * DMI slot's string data) to be considered a 693b0ef371e3f9fa3b2571058be366a6780827ec0bfRandy Dunlap * successful match. 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Walk the blacklist table running matching functions until someone 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * returns non zero or we hit the end. Callback function is called for 697b0ef371e3f9fa3b2571058be366a6780827ec0bfRandy Dunlap * each successful match. Returns the number of matches. 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6991855256c497ecfefc730df6032243f26855ce52cJeff Garzikint dmi_check_system(const struct dmi_system_id *list) 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 701d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki int count = 0; 702d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki const struct dmi_system_id *d; 703d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki 70475757507e014fa074d25d2883c4ab604999584bdDmitry Torokhov for (d = list; !dmi_is_end_of_table(d); d++) 705d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki if (dmi_matches(d)) { 706d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki count++; 707d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki if (d->callback && d->callback(d)) 708d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki break; 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(dmi_check_system); 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 716d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki * dmi_first_match - find dmi_system_id structure matching system DMI data 717d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki * @list: array of dmi_system_id structures to match against 718d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki * All non-null elements of the list must match 719d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki * their slot's (field index's) data (i.e., each 720d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki * list string must be a substring of the specified 721d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki * DMI slot's string data) to be considered a 722d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki * successful match. 723d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki * 724d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki * Walk the blacklist table until the first match is found. Return the 725d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki * pointer to the matching entry or NULL if there's no match. 726d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki */ 727d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysockiconst struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list) 728d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki{ 729d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki const struct dmi_system_id *d; 730d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki 73175757507e014fa074d25d2883c4ab604999584bdDmitry Torokhov for (d = list; !dmi_is_end_of_table(d); d++) 732d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki if (dmi_matches(d)) 733d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki return d; 734d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki 735d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki return NULL; 736d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki} 737d7b1956fed33d30c4815e848fd7a143722916868Rafael J. WysockiEXPORT_SYMBOL(dmi_first_match); 738d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki 739d7b1956fed33d30c4815e848fd7a143722916868Rafael J. Wysocki/** 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * dmi_get_system_info - return DMI data value 741b0ef371e3f9fa3b2571058be366a6780827ec0bfRandy Dunlap * @field: data index (see enum dmi_field) 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns one DMI data value, can be used to perform 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * complex DMI data checks. 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7461855256c497ecfefc730df6032243f26855ce52cJeff Garzikconst char *dmi_get_system_info(int field) 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return dmi_ident[field]; 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 750e70c9d5e61c6cb2272c866fc1303e62975006752Dmitry TorokhovEXPORT_SYMBOL(dmi_get_system_info); 751ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin 752fd8cd7e1919fc1c27fe2fdccd2a1cd32f791ef0fAlok Kataria/** 753c2bacfc44f4b8d03dbaad5d2dca2fb4161e81975Randy Dunlap * dmi_name_in_serial - Check if string is in the DMI product serial information 754c2bacfc44f4b8d03dbaad5d2dca2fb4161e81975Randy Dunlap * @str: string to check for 755fd8cd7e1919fc1c27fe2fdccd2a1cd32f791ef0fAlok Kataria */ 756fd8cd7e1919fc1c27fe2fdccd2a1cd32f791ef0fAlok Katariaint dmi_name_in_serial(const char *str) 757fd8cd7e1919fc1c27fe2fdccd2a1cd32f791ef0fAlok Kataria{ 758fd8cd7e1919fc1c27fe2fdccd2a1cd32f791ef0fAlok Kataria int f = DMI_PRODUCT_SERIAL; 759fd8cd7e1919fc1c27fe2fdccd2a1cd32f791ef0fAlok Kataria if (dmi_ident[f] && strstr(dmi_ident[f], str)) 760fd8cd7e1919fc1c27fe2fdccd2a1cd32f791ef0fAlok Kataria return 1; 761fd8cd7e1919fc1c27fe2fdccd2a1cd32f791ef0fAlok Kataria return 0; 762fd8cd7e1919fc1c27fe2fdccd2a1cd32f791ef0fAlok Kataria} 763a1bae67243512ca30ceda48e3e24e25b543f8ab7Andi Kleen 764a1bae67243512ca30ceda48e3e24e25b543f8ab7Andi Kleen/** 76566e13e66b6c4e5b2ecd6225e1f8437640cfb6498Jean Delvare * dmi_name_in_vendors - Check if string is in the DMI system or board vendor name 76602d9c47f1bf2304d6482e1e69e00c06791d86908Jean Delvare * @str: Case sensitive Name 767a1bae67243512ca30ceda48e3e24e25b543f8ab7Andi Kleen */ 7681855256c497ecfefc730df6032243f26855ce52cJeff Garzikint dmi_name_in_vendors(const char *str) 769a1bae67243512ca30ceda48e3e24e25b543f8ab7Andi Kleen{ 77066e13e66b6c4e5b2ecd6225e1f8437640cfb6498Jean Delvare static int fields[] = { DMI_SYS_VENDOR, DMI_BOARD_VENDOR, DMI_NONE }; 771a1bae67243512ca30ceda48e3e24e25b543f8ab7Andi Kleen int i; 772a1bae67243512ca30ceda48e3e24e25b543f8ab7Andi Kleen for (i = 0; fields[i] != DMI_NONE; i++) { 773a1bae67243512ca30ceda48e3e24e25b543f8ab7Andi Kleen int f = fields[i]; 774a1bae67243512ca30ceda48e3e24e25b543f8ab7Andi Kleen if (dmi_ident[f] && strstr(dmi_ident[f], str)) 775a1bae67243512ca30ceda48e3e24e25b543f8ab7Andi Kleen return 1; 776a1bae67243512ca30ceda48e3e24e25b543f8ab7Andi Kleen } 777a1bae67243512ca30ceda48e3e24e25b543f8ab7Andi Kleen return 0; 778a1bae67243512ca30ceda48e3e24e25b543f8ab7Andi Kleen} 779a1bae67243512ca30ceda48e3e24e25b543f8ab7Andi KleenEXPORT_SYMBOL(dmi_name_in_vendors); 780a1bae67243512ca30ceda48e3e24e25b543f8ab7Andi Kleen 781ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin/** 782ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin * dmi_find_device - find onboard device by type/name 783ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin * @type: device type or %DMI_DEV_TYPE_ANY to match all device types 784b0ef371e3f9fa3b2571058be366a6780827ec0bfRandy Dunlap * @name: device name string or %NULL to match all 785ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin * @from: previous device found in search, or %NULL for new search. 786ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin * 787ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin * Iterates through the list of known onboard devices. If a device is 788ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin * found with a matching @vendor and @device, a pointer to its device 789ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin * structure is returned. Otherwise, %NULL is returned. 790b0ef371e3f9fa3b2571058be366a6780827ec0bfRandy Dunlap * A new search is initiated by passing %NULL as the @from argument. 791ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin * If @from is not %NULL, searches continue from next device. 792ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin */ 79302d9c47f1bf2304d6482e1e69e00c06791d86908Jean Delvareconst struct dmi_device *dmi_find_device(int type, const char *name, 7941855256c497ecfefc730df6032243f26855ce52cJeff Garzik const struct dmi_device *from) 795ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin{ 7961855256c497ecfefc730df6032243f26855ce52cJeff Garzik const struct list_head *head = from ? &from->list : &dmi_devices; 7971855256c497ecfefc730df6032243f26855ce52cJeff Garzik struct list_head *d; 798ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin 79902d9c47f1bf2304d6482e1e69e00c06791d86908Jean Delvare for (d = head->next; d != &dmi_devices; d = d->next) { 8001855256c497ecfefc730df6032243f26855ce52cJeff Garzik const struct dmi_device *dev = 8011855256c497ecfefc730df6032243f26855ce52cJeff Garzik list_entry(d, struct dmi_device, list); 802ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin 803ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin if (((type == DMI_DEV_TYPE_ANY) || (dev->type == type)) && 804ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin ((name == NULL) || (strcmp(dev->name, name) == 0))) 805ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin return dev; 806ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin } 807ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin 808ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin return NULL; 809ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey Panin} 810ebad6a4230bdb5927495e28bc7837f515bf667a7Andrey PaninEXPORT_SYMBOL(dmi_find_device); 811f083a329e63d471a5e9238e837772b1b76c218dbAndi Kleen 812f083a329e63d471a5e9238e837772b1b76c218dbAndi Kleen/** 8133e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo * dmi_get_date - parse a DMI date 8143e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo * @field: data index (see enum dmi_field) 8153e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo * @yearp: optional out parameter for the year 8163e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo * @monthp: optional out parameter for the month 8173e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo * @dayp: optional out parameter for the day 818f083a329e63d471a5e9238e837772b1b76c218dbAndi Kleen * 8193e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo * The date field is assumed to be in the form resembling 8203e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo * [mm[/dd]]/yy[yy] and the result is stored in the out 8213e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo * parameters any or all of which can be omitted. 8223e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo * 8233e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo * If the field doesn't exist, all out parameters are set to zero 8243e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo * and false is returned. Otherwise, true is returned with any 8253e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo * invalid part of date set to zero. 8263e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo * 8273e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo * On return, year, month and day are guaranteed to be in the 8283e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo * range of [0,9999], [0,12] and [0,31] respectively. 829f083a329e63d471a5e9238e837772b1b76c218dbAndi Kleen */ 8303e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heobool dmi_get_date(int field, int *yearp, int *monthp, int *dayp) 831f083a329e63d471a5e9238e837772b1b76c218dbAndi Kleen{ 8323e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo int year = 0, month = 0, day = 0; 8333e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo bool exists; 8343e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo const char *s, *y; 83502c24fa87724bb3af969463cd74dc3b3feb24740Tejun Heo char *e; 836f083a329e63d471a5e9238e837772b1b76c218dbAndi Kleen 8373e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo s = dmi_get_system_info(field); 8383e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo exists = s; 8393e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo if (!exists) 8403e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo goto out; 841f083a329e63d471a5e9238e837772b1b76c218dbAndi Kleen 8423e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo /* 8433e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo * Determine year first. We assume the date string resembles 8443e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo * mm/dd/yy[yy] but the original code extracted only the year 8453e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo * from the end. Keep the behavior in the spirit of no 8463e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo * surprises. 8473e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo */ 8483e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo y = strrchr(s, '/'); 8493e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo if (!y) 8503e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo goto out; 8513e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo 8523e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo y++; 8533e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo year = simple_strtoul(y, &e, 10); 8543e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo if (y != e && year < 100) { /* 2-digit year */ 855f083a329e63d471a5e9238e837772b1b76c218dbAndi Kleen year += 1900; 856f083a329e63d471a5e9238e837772b1b76c218dbAndi Kleen if (year < 1996) /* no dates < spec 1.0 */ 857f083a329e63d471a5e9238e837772b1b76c218dbAndi Kleen year += 100; 858f083a329e63d471a5e9238e837772b1b76c218dbAndi Kleen } 8593e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo if (year > 9999) /* year should fit in %04d */ 8603e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo year = 0; 8613e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo 8623e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo /* parse the mm and dd */ 8633e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo month = simple_strtoul(s, &e, 10); 8643e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo if (s == e || *e != '/' || !month || month > 12) { 8653e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo month = 0; 8663e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo goto out; 8673e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo } 868f083a329e63d471a5e9238e837772b1b76c218dbAndi Kleen 8693e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo s = e + 1; 8703e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo day = simple_strtoul(s, &e, 10); 8713e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo if (s == y || s == e || *e != '/' || day > 31) 8723e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo day = 0; 8733e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heoout: 8743e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo if (yearp) 8753e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo *yearp = year; 8763e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo if (monthp) 8773e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo *monthp = month; 8783e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo if (dayp) 8793e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo *dayp = day; 8803e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun Heo return exists; 881f083a329e63d471a5e9238e837772b1b76c218dbAndi Kleen} 8823e5cd1f2576c720f1d0705fdd7ba64f27e8836b7Tejun HeoEXPORT_SYMBOL(dmi_get_date); 8837fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare 8847fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare/** 8857fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare * dmi_walk - Walk the DMI table and get called back for every record 8867fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare * @decode: Callback function 887e7a19c5624c66afa8118b10cd59f87ee407646bcJean Delvare * @private_data: Private data to be passed to the callback function 8887fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare * 8897fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare * Returns -1 when the DMI table can't be reached, 0 on success. 8907fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare */ 891e7a19c5624c66afa8118b10cd59f87ee407646bcJean Delvareint dmi_walk(void (*decode)(const struct dmi_header *, void *), 892e7a19c5624c66afa8118b10cd59f87ee407646bcJean Delvare void *private_data) 8937fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare{ 8947fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare u8 *buf; 8957fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare 8967fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare if (!dmi_available) 8977fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare return -1; 8987fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare 899cf0744021c5d5de54d2c66e2020c6de2fe800264Ard Biesheuvel buf = dmi_remap(dmi_base, dmi_len); 9007fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare if (buf == NULL) 9017fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare return -1; 9027fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare 903e7a19c5624c66afa8118b10cd59f87ee407646bcJean Delvare dmi_table(buf, dmi_len, dmi_num, decode, private_data); 9047fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare 905cf0744021c5d5de54d2c66e2020c6de2fe800264Ard Biesheuvel dmi_unmap(buf); 9067fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare return 0; 9077fce084a0b3e2bb8caef919f8f36065953655bb5Jean Delvare} 9087fce084a0b3e2bb8caef919f8f36065953655bb5Jean DelvareEXPORT_SYMBOL_GPL(dmi_walk); 909d61c72e52b98411d1cfef1fdb3f5a8bb070f8966Jiri Slaby 910d61c72e52b98411d1cfef1fdb3f5a8bb070f8966Jiri Slaby/** 911d61c72e52b98411d1cfef1fdb3f5a8bb070f8966Jiri Slaby * dmi_match - compare a string to the dmi field (if exists) 912c2bacfc44f4b8d03dbaad5d2dca2fb4161e81975Randy Dunlap * @f: DMI field identifier 913c2bacfc44f4b8d03dbaad5d2dca2fb4161e81975Randy Dunlap * @str: string to compare the DMI field to 914d61c72e52b98411d1cfef1fdb3f5a8bb070f8966Jiri Slaby * 915d61c72e52b98411d1cfef1fdb3f5a8bb070f8966Jiri Slaby * Returns true if the requested field equals to the str (including NULL). 916d61c72e52b98411d1cfef1fdb3f5a8bb070f8966Jiri Slaby */ 917d61c72e52b98411d1cfef1fdb3f5a8bb070f8966Jiri Slabybool dmi_match(enum dmi_field f, const char *str) 918d61c72e52b98411d1cfef1fdb3f5a8bb070f8966Jiri Slaby{ 919d61c72e52b98411d1cfef1fdb3f5a8bb070f8966Jiri Slaby const char *info = dmi_get_system_info(f); 920d61c72e52b98411d1cfef1fdb3f5a8bb070f8966Jiri Slaby 921d61c72e52b98411d1cfef1fdb3f5a8bb070f8966Jiri Slaby if (info == NULL || str == NULL) 922d61c72e52b98411d1cfef1fdb3f5a8bb070f8966Jiri Slaby return info == str; 923d61c72e52b98411d1cfef1fdb3f5a8bb070f8966Jiri Slaby 924d61c72e52b98411d1cfef1fdb3f5a8bb070f8966Jiri Slaby return !strcmp(info, str); 925d61c72e52b98411d1cfef1fdb3f5a8bb070f8966Jiri Slaby} 926d61c72e52b98411d1cfef1fdb3f5a8bb070f8966Jiri SlabyEXPORT_SYMBOL_GPL(dmi_match); 927dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong 928dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gongvoid dmi_memdev_name(u16 handle, const char **bank, const char **device) 929dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong{ 930dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong int n; 931dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong 932dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong if (dmi_memdev == NULL) 933dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong return; 934dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong 935dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong for (n = 0; n < dmi_memdev_nr; n++) { 936dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong if (handle == dmi_memdev[n].handle) { 937dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong *bank = dmi_memdev[n].bank; 938dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong *device = dmi_memdev[n].device; 939dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong break; 940dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong } 941dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong } 942dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, Gong} 943dd6dad4288cb93e79bd7abfa6c6a338c47454d1aChen, GongEXPORT_SYMBOL_GPL(dmi_memdev_name); 944