dmi_scan.c 23.0 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4
#include <linux/types.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/module.h>
5
#include <linux/ctype.h>
L
Linus Torvalds 已提交
6
#include <linux/dmi.h>
M
Matt Domsch 已提交
7
#include <linux/efi.h>
L
Linus Torvalds 已提交
8
#include <linux/bootmem.h>
9
#include <linux/random.h>
10
#include <asm/dmi.h>
11
#include <asm/unaligned.h>
L
Linus Torvalds 已提交
12

13 14 15 16 17
/*
 * DMI stands for "Desktop Management Interface".  It is part
 * of and an antecedent to, SMBIOS, which stands for System
 * Management BIOS.  See further: http://www.dmtf.org/standards
 */
18
static const char dmi_empty_string[] = "        ";
19

20
static u16 __initdata dmi_ver;
21 22 23 24 25
/*
 * Catch too early calls to dmi_check_system():
 */
static int dmi_initialized;

26 27 28
/* DMI system identification string used during boot */
static char dmi_ids_string[128] __initdata;

29 30 31 32 33 34 35
static struct dmi_memdev_info {
	const char *device;
	const char *bank;
	u16 handle;
} *dmi_memdev;
static int dmi_memdev_nr;

36
static const char * __init dmi_string_nosave(const struct dmi_header *dm, u8 s)
L
Linus Torvalds 已提交
37
{
38
	const u8 *bp = ((u8 *) dm) + dm->length;
A
Andrey Panin 已提交
39

40
	if (s) {
L
Linus Torvalds 已提交
41
		s--;
42 43 44 45 46 47
		while (s > 0 && *bp) {
			bp += strlen(bp) + 1;
			s--;
		}

		if (*bp != 0) {
48 49 50 51 52
			size_t len = strlen(bp)+1;
			size_t cmp_len = len > 8 ? 8 : len;

			if (!memcmp(bp, dmi_empty_string, cmp_len))
				return dmi_empty_string;
53
			return bp;
54
		}
55
	}
56

57 58 59
	return "";
}

60
static const char * __init dmi_string(const struct dmi_header *dm, u8 s)
61 62 63 64 65 66 67 68 69 70 71 72 73
{
	const char *bp = dmi_string_nosave(dm, s);
	char *str;
	size_t len;

	if (bp == dmi_empty_string)
		return dmi_empty_string;

	len = strlen(bp) + 1;
	str = dmi_alloc(len);
	if (str != NULL)
		strcpy(str, bp);

74
	return str;
L
Linus Torvalds 已提交
75 76 77 78 79 80
}

/*
 *	We have to be cautious here. We have seen BIOSes with DMI pointers
 *	pointing to completely the wrong place for example
 */
81
static void dmi_table(u8 *buf, u32 len, int num,
82 83
		      void (*decode)(const struct dmi_header *, void *),
		      void *private_data)
L
Linus Torvalds 已提交
84
{
85
	u8 *data = buf;
A
Andrey Panin 已提交
86
	int i = 0;
87

L
Linus Torvalds 已提交
88
	/*
89 90 91
	 *	Stop when we see all the items the table claimed to have
	 *	OR we run off the end of the table (also happens)
	 */
A
Andrey Panin 已提交
92
	while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) {
93 94
		const struct dmi_header *dm = (const struct dmi_header *)data;

L
Linus Torvalds 已提交
95
		/*
A
Alan Cox 已提交
96 97 98
		 *  We want to know the total length (formatted area and
		 *  strings) before decoding to make sure we won't run off the
		 *  table in dmi_decode or dmi_string
L
Linus Torvalds 已提交
99
		 */
A
Andrey Panin 已提交
100 101
		data += dm->length;
		while ((data - buf < len - 1) && (data[0] || data[1]))
L
Linus Torvalds 已提交
102
			data++;
A
Andrey Panin 已提交
103
		if (data - buf < len - 1)
104
			decode(dm, private_data);
105 106 107 108 109 110 111

		/*
		 * 7.45 End-of-Table (Type 127) [SMBIOS reference spec v3.0.0]
		 */
		if (dm->type == DMI_ENTRY_END_OF_TABLE)
			break;

A
Andrey Panin 已提交
112
		data += 2;
L
Linus Torvalds 已提交
113 114
		i++;
	}
115 116
}

117
static phys_addr_t dmi_base;
118
static u32 dmi_len;
119 120
static u16 dmi_num;

121 122
static int __init dmi_walk_early(void (*decode)(const struct dmi_header *,
		void *))
123 124 125
{
	u8 *buf;

126
	buf = dmi_early_remap(dmi_base, dmi_len);
127 128 129
	if (buf == NULL)
		return -1;

130
	dmi_table(buf, dmi_len, dmi_num, decode, NULL);
131

132 133
	add_device_randomness(buf, dmi_len);

134
	dmi_early_unmap(buf, dmi_len);
L
Linus Torvalds 已提交
135 136 137
	return 0;
}

138
static int __init dmi_checksum(const u8 *buf, u8 len)
L
Linus Torvalds 已提交
139
{
A
Andrey Panin 已提交
140
	u8 sum = 0;
L
Linus Torvalds 已提交
141
	int a;
142

143
	for (a = 0; a < len; a++)
A
Andrey Panin 已提交
144 145 146
		sum += buf[a];

	return sum == 0;
L
Linus Torvalds 已提交
147 148
}

149
static const char *dmi_ident[DMI_STRING_MAX];
150
static LIST_HEAD(dmi_devices);
151
int dmi_available;
L
Linus Torvalds 已提交
152 153 154 155

/*
 *	Save a DMI string
 */
156 157
static void __init dmi_save_ident(const struct dmi_header *dm, int slot,
		int string)
L
Linus Torvalds 已提交
158
{
159
	const char *d = (const char *) dm;
160
	const char *p;
A
Andrey Panin 已提交
161

L
Linus Torvalds 已提交
162 163
	if (dmi_ident[slot])
		return;
A
Andrey Panin 已提交
164

165 166 167 168 169
	p = dmi_string(dm, d[string]);
	if (p == NULL)
		return;

	dmi_ident[slot] = p;
L
Linus Torvalds 已提交
170 171
}

172 173
static void __init dmi_save_uuid(const struct dmi_header *dm, int slot,
		int index)
174
{
175
	const u8 *d = (u8 *) dm + index;
176 177 178 179 180 181 182
	char *s;
	int is_ff = 1, is_00 = 1, i;

	if (dmi_ident[slot])
		return;

	for (i = 0; i < 16 && (is_ff || is_00); i++) {
183 184 185 186
		if (d[i] != 0x00)
			is_00 = 0;
		if (d[i] != 0xFF)
			is_ff = 0;
187 188 189 190 191 192 193 194 195
	}

	if (is_ff || is_00)
		return;

	s = dmi_alloc(16*2+4+1);
	if (!s)
		return;

196 197 198 199 200 201 202 203 204
	/*
	 * As of version 2.6 of the SMBIOS specification, the first 3 fields of
	 * the UUID are supposed to be little-endian encoded.  The specification
	 * says that this is the defacto standard.
	 */
	if (dmi_ver >= 0x0206)
		sprintf(s, "%pUL", d);
	else
		sprintf(s, "%pUB", d);
205

206
	dmi_ident[slot] = s;
207 208
}

209 210
static void __init dmi_save_type(const struct dmi_header *dm, int slot,
		int index)
211
{
212
	const u8 *d = (u8 *) dm + index;
213 214 215 216 217 218 219 220 221 222 223 224 225
	char *s;

	if (dmi_ident[slot])
		return;

	s = dmi_alloc(4);
	if (!s)
		return;

	sprintf(s, "%u", *d & 0x7F);
	dmi_ident[slot] = s;
}

226 227 228 229 230 231 232 233 234
static void __init dmi_save_one_device(int type, const char *name)
{
	struct dmi_device *dev;

	/* No duplicate device */
	if (dmi_find_device(type, name, NULL))
		return;

	dev = dmi_alloc(sizeof(*dev) + strlen(name) + 1);
235
	if (!dev)
236 237 238 239 240 241 242 243 244
		return;

	dev->type = type;
	strcpy((char *)(dev + 1), name);
	dev->name = (char *)(dev + 1);
	dev->device_data = NULL;
	list_add(&dev->list, &dmi_devices);
}

245
static void __init dmi_save_devices(const struct dmi_header *dm)
246 247 248 249
{
	int i, count = (dm->length - sizeof(struct dmi_header)) / 2;

	for (i = 0; i < count; i++) {
250
		const char *d = (char *)(dm + 1) + (i * 2);
251 252 253 254 255

		/* Skip disabled device */
		if ((*d & 0x80) == 0)
			continue;

256
		dmi_save_one_device(*d & 0x7f, dmi_string_nosave(dm, *(d + 1)));
257 258 259
	}
}

260
static void __init dmi_save_oem_strings_devices(const struct dmi_header *dm)
261 262 263 264 265
{
	int i, count = *(u8 *)(dm + 1);
	struct dmi_device *dev;

	for (i = 1; i <= count; i++) {
266
		const char *devname = dmi_string(dm, i);
267

268
		if (devname == dmi_empty_string)
269 270
			continue;

271
		dev = dmi_alloc(sizeof(*dev));
272
		if (!dev)
273 274 275
			break;

		dev->type = DMI_DEV_TYPE_OEM_STRING;
276
		dev->name = devname;
277
		dev->device_data = NULL;
278 279 280 281 282

		list_add(&dev->list, &dmi_devices);
	}
}

283
static void __init dmi_save_ipmi_device(const struct dmi_header *dm)
284 285
{
	struct dmi_device *dev;
286
	void *data;
287

288
	data = dmi_alloc(dm->length);
289
	if (data == NULL)
290 291 292 293
		return;

	memcpy(data, dm, dm->length);

294
	dev = dmi_alloc(sizeof(*dev));
295
	if (!dev)
296 297 298 299 300 301
		return;

	dev->type = DMI_DEV_TYPE_IPMI;
	dev->name = "IPMI controller";
	dev->device_data = data;

302
	list_add_tail(&dev->list, &dmi_devices);
303 304
}

305 306 307 308 309 310
static void __init dmi_save_dev_onboard(int instance, int segment, int bus,
					int devfn, const char *name)
{
	struct dmi_dev_onboard *onboard_dev;

	onboard_dev = dmi_alloc(sizeof(*onboard_dev) + strlen(name) + 1);
311
	if (!onboard_dev)
312
		return;
313

314 315 316 317 318 319 320 321 322 323 324 325 326
	onboard_dev->instance = instance;
	onboard_dev->segment = segment;
	onboard_dev->bus = bus;
	onboard_dev->devfn = devfn;

	strcpy((char *)&onboard_dev[1], name);
	onboard_dev->dev.type = DMI_DEV_TYPE_DEV_ONBOARD;
	onboard_dev->dev.name = (char *)&onboard_dev[1];
	onboard_dev->dev.device_data = onboard_dev;

	list_add(&onboard_dev->dev.list, &dmi_devices);
}

327 328
static void __init dmi_save_extended_devices(const struct dmi_header *dm)
{
329
	const u8 *d = (u8 *) dm + 5;
330 331 332 333 334

	/* Skip disabled device */
	if ((*d & 0x80) == 0)
		return;

335 336
	dmi_save_dev_onboard(*(d+1), *(u16 *)(d+2), *(d+4), *(d+5),
			     dmi_string_nosave(dm, *(d-1)));
337
	dmi_save_one_device(*d & 0x7f, dmi_string_nosave(dm, *(d - 1)));
338 339
}

340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
static void __init count_mem_devices(const struct dmi_header *dm, void *v)
{
	if (dm->type != DMI_ENTRY_MEM_DEVICE)
		return;
	dmi_memdev_nr++;
}

static void __init save_mem_devices(const struct dmi_header *dm, void *v)
{
	const char *d = (const char *)dm;
	static int nr;

	if (dm->type != DMI_ENTRY_MEM_DEVICE)
		return;
	if (nr >= dmi_memdev_nr) {
		pr_warn(FW_BUG "Too many DIMM entries in SMBIOS table\n");
		return;
	}
358
	dmi_memdev[nr].handle = get_unaligned(&dm->handle);
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
	dmi_memdev[nr].device = dmi_string(dm, d[0x10]);
	dmi_memdev[nr].bank = dmi_string(dm, d[0x11]);
	nr++;
}

void __init dmi_memdev_walk(void)
{
	if (!dmi_available)
		return;

	if (dmi_walk_early(count_mem_devices) == 0 && dmi_memdev_nr) {
		dmi_memdev = dmi_alloc(sizeof(*dmi_memdev) * dmi_memdev_nr);
		if (dmi_memdev)
			dmi_walk_early(save_mem_devices);
	}
}

L
Linus Torvalds 已提交
376 377 378 379 380
/*
 *	Process a DMI table entry. Right now all we care about are the BIOS
 *	and machine entries. For 2.5 we should pull the smbus controller info
 *	out of here.
 */
381
static void __init dmi_decode(const struct dmi_header *dm, void *dummy)
L
Linus Torvalds 已提交
382
{
383
	switch (dm->type) {
384
	case 0:		/* BIOS Information */
A
Andrey Panin 已提交
385 386 387 388
		dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
		dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
		dmi_save_ident(dm, DMI_BIOS_DATE, 8);
		break;
389
	case 1:		/* System Information */
A
Andrey Panin 已提交
390 391 392 393
		dmi_save_ident(dm, DMI_SYS_VENDOR, 4);
		dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
		dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
		dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7);
394
		dmi_save_uuid(dm, DMI_PRODUCT_UUID, 8);
A
Andrey Panin 已提交
395
		break;
396
	case 2:		/* Base Board Information */
A
Andrey Panin 已提交
397 398 399
		dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
		dmi_save_ident(dm, DMI_BOARD_NAME, 5);
		dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
400 401 402 403 404 405 406 407 408
		dmi_save_ident(dm, DMI_BOARD_SERIAL, 7);
		dmi_save_ident(dm, DMI_BOARD_ASSET_TAG, 8);
		break;
	case 3:		/* Chassis Information */
		dmi_save_ident(dm, DMI_CHASSIS_VENDOR, 4);
		dmi_save_type(dm, DMI_CHASSIS_TYPE, 5);
		dmi_save_ident(dm, DMI_CHASSIS_VERSION, 6);
		dmi_save_ident(dm, DMI_CHASSIS_SERIAL, 7);
		dmi_save_ident(dm, DMI_CHASSIS_ASSET_TAG, 8);
A
Andrey Panin 已提交
409
		break;
410 411 412
	case 10:	/* Onboard Devices Information */
		dmi_save_devices(dm);
		break;
413 414 415
	case 11:	/* OEM Strings */
		dmi_save_oem_strings_devices(dm);
		break;
416 417
	case 38:	/* IPMI Device Information */
		dmi_save_ipmi_device(dm);
418 419 420
		break;
	case 41:	/* Onboard Devices Extended Information */
		dmi_save_extended_devices(dm);
L
Linus Torvalds 已提交
421 422 423
	}
}

424
static int __init print_filtered(char *buf, size_t len, const char *info)
425
{
426
	int c = 0;
427 428 429
	const char *p;

	if (!info)
430
		return c;
431 432 433

	for (p = info; *p; p++)
		if (isprint(*p))
434
			c += scnprintf(buf + c, len - c, "%c", *p);
435
		else
436 437
			c += scnprintf(buf + c, len - c, "\\x%02x", *p & 0xff);
	return c;
438 439
}

440
static void __init dmi_format_ids(char *buf, size_t len)
441
{
442
	int c = 0;
443 444
	const char *board;	/* Board Name is optional */

445 446 447 448 449 450
	c += print_filtered(buf + c, len - c,
			    dmi_get_system_info(DMI_SYS_VENDOR));
	c += scnprintf(buf + c, len - c, " ");
	c += print_filtered(buf + c, len - c,
			    dmi_get_system_info(DMI_PRODUCT_NAME));

451 452
	board = dmi_get_system_info(DMI_BOARD_NAME);
	if (board) {
453 454
		c += scnprintf(buf + c, len - c, "/");
		c += print_filtered(buf + c, len - c, board);
455
	}
456 457 458 459 460 461
	c += scnprintf(buf + c, len - c, ", BIOS ");
	c += print_filtered(buf + c, len - c,
			    dmi_get_system_info(DMI_BIOS_VERSION));
	c += scnprintf(buf + c, len - c, " ");
	c += print_filtered(buf + c, len - c,
			    dmi_get_system_info(DMI_BIOS_DATE));
462 463
}

464 465 466 467 468 469 470
/*
 * Check for DMI/SMBIOS headers in the system firmware image.  Any
 * SMBIOS header must start 16 bytes before the DMI header, so take a
 * 32 byte buffer and check for DMI at offset 16 and SMBIOS at offset
 * 0.  If the DMI header is present, set dmi_ver accordingly (SMBIOS
 * takes precedence) and return 0.  Otherwise return 1.
 */
471
static int __init dmi_present(const u8 *buf)
L
Linus Torvalds 已提交
472
{
473
	int smbios_ver;
474

475 476
	if (memcmp(buf, "_SM_", 4) == 0 &&
	    buf[5] < 32 && dmi_checksum(buf, buf[5])) {
477
		smbios_ver = get_unaligned_be16(buf + 6);
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498

		/* Some BIOS report weird SMBIOS version, fix that up */
		switch (smbios_ver) {
		case 0x021F:
		case 0x0221:
			pr_debug("SMBIOS version fixup(2.%d->2.%d)\n",
				 smbios_ver & 0xFF, 3);
			smbios_ver = 0x0203;
			break;
		case 0x0233:
			pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", 51, 6);
			smbios_ver = 0x0206;
			break;
		}
	} else {
		smbios_ver = 0;
	}

	buf += 16;

	if (memcmp(buf, "_DMI_", 5) == 0 && dmi_checksum(buf, 15)) {
499 500 501
		dmi_num = get_unaligned_le16(buf + 12);
		dmi_len = get_unaligned_le16(buf + 6);
		dmi_base = get_unaligned_le32(buf + 8);
502

503
		if (dmi_walk_early(dmi_decode) == 0) {
504 505
			if (smbios_ver) {
				dmi_ver = smbios_ver;
506 507
				pr_info("SMBIOS %d.%d present.\n",
				       dmi_ver >> 8, dmi_ver & 0xFF);
508
			} else {
509 510 511 512 513
				dmi_ver = (buf[14] & 0xF0) << 4 |
					   (buf[14] & 0x0F);
				pr_info("Legacy DMI %d.%d present.\n",
				       dmi_ver >> 8, dmi_ver & 0xFF);
			}
514 515
			dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string));
			printk(KERN_DEBUG "DMI: %s\n", dmi_ids_string);
M
Matt Domsch 已提交
516
			return 0;
517
		}
M
Matt Domsch 已提交
518
	}
519

520
	return 1;
521 522
}

523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557
/*
 * Check for the SMBIOS 3.0 64-bit entry point signature. Unlike the legacy
 * 32-bit entry point, there is no embedded DMI header (_DMI_) in here.
 */
static int __init dmi_smbios3_present(const u8 *buf)
{
	if (memcmp(buf, "_SM3_", 5) == 0 &&
	    buf[6] < 32 && dmi_checksum(buf, buf[6])) {
		dmi_ver = get_unaligned_be16(buf + 7);
		dmi_len = get_unaligned_le32(buf + 12);
		dmi_base = get_unaligned_le64(buf + 16);

		/*
		 * The 64-bit SMBIOS 3.0 entry point no longer has a field
		 * containing the number of structures present in the table.
		 * Instead, it defines the table size as a maximum size, and
		 * relies on the end-of-table structure type (#127) to be used
		 * to signal the end of the table.
		 * So let's define dmi_num as an upper bound as well: each
		 * structure has a 4 byte header, so dmi_len / 4 is an upper
		 * bound for the number of structures in the table.
		 */
		dmi_num = dmi_len / 4;

		if (dmi_walk_early(dmi_decode) == 0) {
			pr_info("SMBIOS %d.%d present.\n",
				dmi_ver >> 8, dmi_ver & 0xFF);
			dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string));
			pr_debug("DMI: %s\n", dmi_ids_string);
			return 0;
		}
	}
	return 1;
}

M
Matt Domsch 已提交
558 559 560
void __init dmi_scan_machine(void)
{
	char __iomem *p, *q;
561
	char buf[32];
M
Matt Domsch 已提交
562

563
	if (efi_enabled(EFI_CONFIG_TABLES)) {
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588
		/*
		 * According to the DMTF SMBIOS reference spec v3.0.0, it is
		 * allowed to define both the 64-bit entry point (smbios3) and
		 * the 32-bit entry point (smbios), in which case they should
		 * either both point to the same SMBIOS structure table, or the
		 * table pointed to by the 64-bit entry point should contain a
		 * superset of the table contents pointed to by the 32-bit entry
		 * point (section 5.2)
		 * This implies that the 64-bit entry point should have
		 * precedence if it is defined and supported by the OS. If we
		 * have the 64-bit entry point, but fail to decode it, fall
		 * back to the legacy one (if available)
		 */
		if (efi.smbios3 != EFI_INVALID_TABLE_ADDR) {
			p = dmi_early_remap(efi.smbios3, 32);
			if (p == NULL)
				goto error;
			memcpy_fromio(buf, p, 32);
			dmi_early_unmap(p, 32);

			if (!dmi_smbios3_present(buf)) {
				dmi_available = 1;
				goto out;
			}
		}
589
		if (efi.smbios == EFI_INVALID_TABLE_ADDR)
590
			goto error;
M
Matt Domsch 已提交
591

592 593 594 595
		/* This is called as a core_initcall() because it isn't
		 * needed during early boot.  This also means we can
		 * iounmap the space when we're done with it.
		 */
596
		p = dmi_early_remap(efi.smbios, 32);
M
Matt Domsch 已提交
597
		if (p == NULL)
598
			goto error;
599
		memcpy_fromio(buf, p, 32);
600
		dmi_early_unmap(p, 32);
601 602

		if (!dmi_present(buf)) {
603
			dmi_available = 1;
604
			goto out;
605
		}
606 607
	} else if (IS_ENABLED(CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK)) {
		p = dmi_early_remap(0xF0000, 0x10000);
M
Matt Domsch 已提交
608
		if (p == NULL)
609
			goto error;
M
Matt Domsch 已提交
610

611 612 613 614 615 616 617
		/*
		 * Iterate over all possible DMI header addresses q.
		 * Maintain the 32 bytes around q in buf.  On the
		 * first iteration, substitute zero for the
		 * out-of-range bytes so there is no chance of falsely
		 * detecting an SMBIOS header.
		 */
618
		memset(buf, 0, 16);
M
Matt Domsch 已提交
619
		for (q = p; q < p + 0x10000; q += 16) {
620
			memcpy_fromio(buf + 16, q, 16);
621
			if (!dmi_smbios3_present(buf) || !dmi_present(buf)) {
622
				dmi_available = 1;
623
				dmi_early_unmap(p, 0x10000);
624
				goto out;
625
			}
626
			memcpy(buf, buf + 16, 16);
627
		}
628
		dmi_early_unmap(p, 0x10000);
629
	}
630
 error:
631
	pr_info("DMI not present or invalid.\n");
632 633
 out:
	dmi_initialized = 1;
L
Linus Torvalds 已提交
634 635
}

636 637 638 639 640 641 642 643 644 645 646 647 648
/**
 * dmi_set_dump_stack_arch_desc - set arch description for dump_stack()
 *
 * Invoke dump_stack_set_arch_desc() with DMI system information so that
 * DMI identifiers are printed out on task dumps.  Arch boot code should
 * call this function after dmi_scan_machine() if it wants to print out DMI
 * identifiers on task dumps.
 */
void __init dmi_set_dump_stack_arch_desc(void)
{
	dump_stack_set_arch_desc("%s", dmi_ids_string);
}

649 650 651 652 653 654 655 656 657 658 659 660 661
/**
 *	dmi_matches - check if dmi_system_id structure matches system DMI data
 *	@dmi: pointer to the dmi_system_id structure to check
 */
static bool dmi_matches(const struct dmi_system_id *dmi)
{
	int i;

	WARN(!dmi_initialized, KERN_ERR "dmi check: not initialized yet.\n");

	for (i = 0; i < ARRAY_SIZE(dmi->matches); i++) {
		int s = dmi->matches[i].slot;
		if (s == DMI_NONE)
662
			break;
663 664 665 666 667 668 669 670 671
		if (dmi_ident[s]) {
			if (!dmi->matches[i].exact_match &&
			    strstr(dmi_ident[s], dmi->matches[i].substr))
				continue;
			else if (dmi->matches[i].exact_match &&
				 !strcmp(dmi_ident[s], dmi->matches[i].substr))
				continue;
		}

672 673 674 675 676 677
		/* No match */
		return false;
	}
	return true;
}

678 679 680 681 682 683 684 685 686
/**
 *	dmi_is_end_of_table - check for end-of-table marker
 *	@dmi: pointer to the dmi_system_id structure to check
 */
static bool dmi_is_end_of_table(const struct dmi_system_id *dmi)
{
	return dmi->matches[0].slot == DMI_NONE;
}

L
Linus Torvalds 已提交
687 688 689
/**
 *	dmi_check_system - check system DMI data
 *	@list: array of dmi_system_id structures to match against
690 691 692 693 694
 *		All non-null elements of the list must match
 *		their slot's (field index's) data (i.e., each
 *		list string must be a substring of the specified
 *		DMI slot's string data) to be considered a
 *		successful match.
L
Linus Torvalds 已提交
695 696 697
 *
 *	Walk the blacklist table running matching functions until someone
 *	returns non zero or we hit the end. Callback function is called for
698
 *	each successful match. Returns the number of matches.
L
Linus Torvalds 已提交
699
 */
700
int dmi_check_system(const struct dmi_system_id *list)
L
Linus Torvalds 已提交
701
{
702 703 704
	int count = 0;
	const struct dmi_system_id *d;

705
	for (d = list; !dmi_is_end_of_table(d); d++)
706 707 708 709
		if (dmi_matches(d)) {
			count++;
			if (d->callback && d->callback(d))
				break;
L
Linus Torvalds 已提交
710 711 712 713 714 715
		}

	return count;
}
EXPORT_SYMBOL(dmi_check_system);

716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731
/**
 *	dmi_first_match - find dmi_system_id structure matching system DMI data
 *	@list: array of dmi_system_id structures to match against
 *		All non-null elements of the list must match
 *		their slot's (field index's) data (i.e., each
 *		list string must be a substring of the specified
 *		DMI slot's string data) to be considered a
 *		successful match.
 *
 *	Walk the blacklist table until the first match is found.  Return the
 *	pointer to the matching entry or NULL if there's no match.
 */
const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list)
{
	const struct dmi_system_id *d;

732
	for (d = list; !dmi_is_end_of_table(d); d++)
733 734 735 736 737 738 739
		if (dmi_matches(d))
			return d;

	return NULL;
}
EXPORT_SYMBOL(dmi_first_match);

L
Linus Torvalds 已提交
740 741
/**
 *	dmi_get_system_info - return DMI data value
742
 *	@field: data index (see enum dmi_field)
L
Linus Torvalds 已提交
743 744 745 746
 *
 *	Returns one DMI data value, can be used to perform
 *	complex DMI data checks.
 */
747
const char *dmi_get_system_info(int field)
L
Linus Torvalds 已提交
748 749 750
{
	return dmi_ident[field];
}
751
EXPORT_SYMBOL(dmi_get_system_info);
752

753
/**
R
Randy Dunlap 已提交
754 755
 * dmi_name_in_serial - Check if string is in the DMI product serial information
 * @str: string to check for
756 757 758 759 760 761 762 763
 */
int dmi_name_in_serial(const char *str)
{
	int f = DMI_PRODUCT_SERIAL;
	if (dmi_ident[f] && strstr(dmi_ident[f], str))
		return 1;
	return 0;
}
764 765

/**
766
 *	dmi_name_in_vendors - Check if string is in the DMI system or board vendor name
767
 *	@str: Case sensitive Name
768
 */
769
int dmi_name_in_vendors(const char *str)
770
{
771
	static int fields[] = { DMI_SYS_VENDOR, DMI_BOARD_VENDOR, DMI_NONE };
772 773 774 775 776 777 778 779 780 781
	int i;
	for (i = 0; fields[i] != DMI_NONE; i++) {
		int f = fields[i];
		if (dmi_ident[f] && strstr(dmi_ident[f], str))
			return 1;
	}
	return 0;
}
EXPORT_SYMBOL(dmi_name_in_vendors);

782 783 784
/**
 *	dmi_find_device - find onboard device by type/name
 *	@type: device type or %DMI_DEV_TYPE_ANY to match all device types
785
 *	@name: device name string or %NULL to match all
786 787 788 789 790
 *	@from: previous device found in search, or %NULL for new search.
 *
 *	Iterates through the list of known onboard devices. If a device is
 *	found with a matching @vendor and @device, a pointer to its device
 *	structure is returned.  Otherwise, %NULL is returned.
791
 *	A new search is initiated by passing %NULL as the @from argument.
792 793
 *	If @from is not %NULL, searches continue from next device.
 */
794
const struct dmi_device *dmi_find_device(int type, const char *name,
795
				    const struct dmi_device *from)
796
{
797 798
	const struct list_head *head = from ? &from->list : &dmi_devices;
	struct list_head *d;
799

800
	for (d = head->next; d != &dmi_devices; d = d->next) {
801 802
		const struct dmi_device *dev =
			list_entry(d, struct dmi_device, list);
803 804 805 806 807 808 809 810 811

		if (((type == DMI_DEV_TYPE_ANY) || (dev->type == type)) &&
		    ((name == NULL) || (strcmp(dev->name, name) == 0)))
			return dev;
	}

	return NULL;
}
EXPORT_SYMBOL(dmi_find_device);
812 813

/**
814 815 816 817 818
 *	dmi_get_date - parse a DMI date
 *	@field:	data index (see enum dmi_field)
 *	@yearp: optional out parameter for the year
 *	@monthp: optional out parameter for the month
 *	@dayp: optional out parameter for the day
819
 *
820 821 822 823 824 825 826 827 828 829
 *	The date field is assumed to be in the form resembling
 *	[mm[/dd]]/yy[yy] and the result is stored in the out
 *	parameters any or all of which can be omitted.
 *
 *	If the field doesn't exist, all out parameters are set to zero
 *	and false is returned.  Otherwise, true is returned with any
 *	invalid part of date set to zero.
 *
 *	On return, year, month and day are guaranteed to be in the
 *	range of [0,9999], [0,12] and [0,31] respectively.
830
 */
831
bool dmi_get_date(int field, int *yearp, int *monthp, int *dayp)
832
{
833 834 835
	int year = 0, month = 0, day = 0;
	bool exists;
	const char *s, *y;
836
	char *e;
837

838 839 840 841
	s = dmi_get_system_info(field);
	exists = s;
	if (!exists)
		goto out;
842

843 844 845 846 847 848 849 850 851 852 853 854 855
	/*
	 * Determine year first.  We assume the date string resembles
	 * mm/dd/yy[yy] but the original code extracted only the year
	 * from the end.  Keep the behavior in the spirit of no
	 * surprises.
	 */
	y = strrchr(s, '/');
	if (!y)
		goto out;

	y++;
	year = simple_strtoul(y, &e, 10);
	if (y != e && year < 100) {	/* 2-digit year */
856 857 858 859
		year += 1900;
		if (year < 1996)	/* no dates < spec 1.0 */
			year += 100;
	}
860 861 862 863 864 865 866 867 868
	if (year > 9999)		/* year should fit in %04d */
		year = 0;

	/* parse the mm and dd */
	month = simple_strtoul(s, &e, 10);
	if (s == e || *e != '/' || !month || month > 12) {
		month = 0;
		goto out;
	}
869

870 871 872 873 874 875 876 877 878 879 880 881
	s = e + 1;
	day = simple_strtoul(s, &e, 10);
	if (s == y || s == e || *e != '/' || day > 31)
		day = 0;
out:
	if (yearp)
		*yearp = year;
	if (monthp)
		*monthp = month;
	if (dayp)
		*dayp = day;
	return exists;
882
}
883
EXPORT_SYMBOL(dmi_get_date);
884 885 886 887

/**
 *	dmi_walk - Walk the DMI table and get called back for every record
 *	@decode: Callback function
888
 *	@private_data: Private data to be passed to the callback function
889 890 891
 *
 *	Returns -1 when the DMI table can't be reached, 0 on success.
 */
892 893
int dmi_walk(void (*decode)(const struct dmi_header *, void *),
	     void *private_data)
894 895 896 897 898 899
{
	u8 *buf;

	if (!dmi_available)
		return -1;

900
	buf = dmi_remap(dmi_base, dmi_len);
901 902 903
	if (buf == NULL)
		return -1;

904
	dmi_table(buf, dmi_len, dmi_num, decode, private_data);
905

906
	dmi_unmap(buf);
907 908 909
	return 0;
}
EXPORT_SYMBOL_GPL(dmi_walk);
J
Jiri Slaby 已提交
910 911 912

/**
 * dmi_match - compare a string to the dmi field (if exists)
R
Randy Dunlap 已提交
913 914
 * @f: DMI field identifier
 * @str: string to compare the DMI field to
J
Jiri Slaby 已提交
915 916 917 918 919 920 921 922 923 924 925 926 927
 *
 * Returns true if the requested field equals to the str (including NULL).
 */
bool dmi_match(enum dmi_field f, const char *str)
{
	const char *info = dmi_get_system_info(f);

	if (info == NULL || str == NULL)
		return info == str;

	return !strcmp(info, str);
}
EXPORT_SYMBOL_GPL(dmi_match);
928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944

void dmi_memdev_name(u16 handle, const char **bank, const char **device)
{
	int n;

	if (dmi_memdev == NULL)
		return;

	for (n = 0; n < dmi_memdev_nr; n++) {
		if (handle == dmi_memdev[n].handle) {
			*bank = dmi_memdev[n].bank;
			*device = dmi_memdev[n].device;
			break;
		}
	}
}
EXPORT_SYMBOL_GPL(dmi_memdev_name);