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