dmi_scan.c 20.7 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>
L
Linus Torvalds 已提交
11

12 13 14 15 16
/*
 * 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
 */
17
static const char dmi_empty_string[] = "        ";
18

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

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

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

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

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

		if (*bp != 0) {
47 48 49 50 51
			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;
52
			return bp;
53
		}
54
	}
55

56 57 58
	return "";
}

59
static const char * __init dmi_string(const struct dmi_header *dm, u8 s)
60 61 62 63 64 65 66 67 68 69 70 71 72
{
	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);

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

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

L
Linus Torvalds 已提交
87
	/*
88 89 90
	 *	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 已提交
91
	while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) {
92 93
		const struct dmi_header *dm = (const struct dmi_header *)data;

L
Linus Torvalds 已提交
94
		/*
A
Alan Cox 已提交
95 96 97
		 *  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 已提交
98
		 */
A
Andrey Panin 已提交
99 100
		data += dm->length;
		while ((data - buf < len - 1) && (data[0] || data[1]))
L
Linus Torvalds 已提交
101
			data++;
A
Andrey Panin 已提交
102
		if (data - buf < len - 1)
103
			decode(dm, private_data);
A
Andrey Panin 已提交
104
		data += 2;
L
Linus Torvalds 已提交
105 106
		i++;
	}
107 108 109 110 111 112
}

static u32 dmi_base;
static u16 dmi_len;
static u16 dmi_num;

113 114
static int __init dmi_walk_early(void (*decode)(const struct dmi_header *,
		void *))
115 116 117 118 119 120 121
{
	u8 *buf;

	buf = dmi_ioremap(dmi_base, dmi_len);
	if (buf == NULL)
		return -1;

122
	dmi_table(buf, dmi_len, dmi_num, decode, NULL);
123

124 125
	add_device_randomness(buf, dmi_len);

126
	dmi_iounmap(buf, dmi_len);
L
Linus Torvalds 已提交
127 128 129
	return 0;
}

130
static int __init dmi_checksum(const u8 *buf, u8 len)
L
Linus Torvalds 已提交
131
{
A
Andrey Panin 已提交
132
	u8 sum = 0;
L
Linus Torvalds 已提交
133
	int a;
134

135
	for (a = 0; a < len; a++)
A
Andrey Panin 已提交
136 137 138
		sum += buf[a];

	return sum == 0;
L
Linus Torvalds 已提交
139 140
}

141
static const char *dmi_ident[DMI_STRING_MAX];
142
static LIST_HEAD(dmi_devices);
143
int dmi_available;
L
Linus Torvalds 已提交
144 145 146 147

/*
 *	Save a DMI string
 */
148 149
static void __init dmi_save_ident(const struct dmi_header *dm, int slot,
		int string)
L
Linus Torvalds 已提交
150
{
151
	const char *d = (const char *) dm;
152
	const char *p;
A
Andrey Panin 已提交
153

L
Linus Torvalds 已提交
154 155
	if (dmi_ident[slot])
		return;
A
Andrey Panin 已提交
156

157 158 159 160 161
	p = dmi_string(dm, d[string]);
	if (p == NULL)
		return;

	dmi_ident[slot] = p;
L
Linus Torvalds 已提交
162 163
}

164 165
static void __init dmi_save_uuid(const struct dmi_header *dm, int slot,
		int index)
166
{
167
	const u8 *d = (u8 *) dm + index;
168 169 170 171 172 173 174
	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++) {
175 176 177 178
		if (d[i] != 0x00)
			is_00 = 0;
		if (d[i] != 0xFF)
			is_ff = 0;
179 180 181 182 183 184 185 186 187
	}

	if (is_ff || is_00)
		return;

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

188 189 190 191 192 193 194 195 196
	/*
	 * 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);
197

198
	dmi_ident[slot] = s;
199 200
}

201 202
static void __init dmi_save_type(const struct dmi_header *dm, int slot,
		int index)
203
{
204
	const u8 *d = (u8 *) dm + index;
205 206 207 208 209 210 211 212 213 214 215 216 217
	char *s;

	if (dmi_ident[slot])
		return;

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

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

218 219 220 221 222 223 224 225 226
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);
227
	if (!dev)
228 229 230 231 232 233 234 235 236
		return;

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

237
static void __init dmi_save_devices(const struct dmi_header *dm)
238 239 240 241
{
	int i, count = (dm->length - sizeof(struct dmi_header)) / 2;

	for (i = 0; i < count; i++) {
242
		const char *d = (char *)(dm + 1) + (i * 2);
243 244 245 246 247

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

248
		dmi_save_one_device(*d & 0x7f, dmi_string_nosave(dm, *(d + 1)));
249 250 251
	}
}

252
static void __init dmi_save_oem_strings_devices(const struct dmi_header *dm)
253 254 255 256 257
{
	int i, count = *(u8 *)(dm + 1);
	struct dmi_device *dev;

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

260
		if (devname == dmi_empty_string)
261 262
			continue;

263
		dev = dmi_alloc(sizeof(*dev));
264
		if (!dev)
265 266 267
			break;

		dev->type = DMI_DEV_TYPE_OEM_STRING;
268
		dev->name = devname;
269
		dev->device_data = NULL;
270 271 272 273 274

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

275
static void __init dmi_save_ipmi_device(const struct dmi_header *dm)
276 277
{
	struct dmi_device *dev;
278
	void *data;
279

280
	data = dmi_alloc(dm->length);
281
	if (data == NULL)
282 283 284 285
		return;

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

286
	dev = dmi_alloc(sizeof(*dev));
287
	if (!dev)
288 289 290 291 292 293
		return;

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

294
	list_add_tail(&dev->list, &dmi_devices);
295 296
}

297 298 299 300 301 302
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);
303
	if (!onboard_dev)
304
		return;
305

306 307 308 309 310 311 312 313 314 315 316 317 318
	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);
}

319 320
static void __init dmi_save_extended_devices(const struct dmi_header *dm)
{
321
	const u8 *d = (u8 *) dm + 5;
322 323 324 325 326

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

327 328
	dmi_save_dev_onboard(*(d+1), *(u16 *)(d+2), *(d+4), *(d+5),
			     dmi_string_nosave(dm, *(d-1)));
329
	dmi_save_one_device(*d & 0x7f, dmi_string_nosave(dm, *(d - 1)));
330 331
}

332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
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;
	}
	dmi_memdev[nr].handle = dm->handle;
	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 已提交
368 369 370 371 372
/*
 *	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.
 */
373
static void __init dmi_decode(const struct dmi_header *dm, void *dummy)
L
Linus Torvalds 已提交
374
{
375
	switch (dm->type) {
376
	case 0:		/* BIOS Information */
A
Andrey Panin 已提交
377 378 379 380
		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;
381
	case 1:		/* System Information */
A
Andrey Panin 已提交
382 383 384 385
		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);
386
		dmi_save_uuid(dm, DMI_PRODUCT_UUID, 8);
A
Andrey Panin 已提交
387
		break;
388
	case 2:		/* Base Board Information */
A
Andrey Panin 已提交
389 390 391
		dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
		dmi_save_ident(dm, DMI_BOARD_NAME, 5);
		dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
392 393 394 395 396 397 398 399 400
		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 已提交
401
		break;
402 403 404
	case 10:	/* Onboard Devices Information */
		dmi_save_devices(dm);
		break;
405 406 407
	case 11:	/* OEM Strings */
		dmi_save_oem_strings_devices(dm);
		break;
408 409
	case 38:	/* IPMI Device Information */
		dmi_save_ipmi_device(dm);
410 411 412
		break;
	case 41:	/* Onboard Devices Extended Information */
		dmi_save_extended_devices(dm);
L
Linus Torvalds 已提交
413 414 415
	}
}

416
static int __init print_filtered(char *buf, size_t len, const char *info)
417
{
418
	int c = 0;
419 420 421
	const char *p;

	if (!info)
422
		return c;
423 424 425

	for (p = info; *p; p++)
		if (isprint(*p))
426
			c += scnprintf(buf + c, len - c, "%c", *p);
427
		else
428 429
			c += scnprintf(buf + c, len - c, "\\x%02x", *p & 0xff);
	return c;
430 431
}

432
static void __init dmi_format_ids(char *buf, size_t len)
433
{
434
	int c = 0;
435 436
	const char *board;	/* Board Name is optional */

437 438 439 440 441 442
	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));

443 444
	board = dmi_get_system_info(DMI_BOARD_NAME);
	if (board) {
445 446
		c += scnprintf(buf + c, len - c, "/");
		c += print_filtered(buf + c, len - c, board);
447
	}
448 449 450 451 452 453
	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));
454 455
}

456 457 458 459 460 461 462
/*
 * 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.
 */
463
static int __init dmi_present(const u8 *buf)
L
Linus Torvalds 已提交
464
{
465
	int smbios_ver;
466

467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490
	if (memcmp(buf, "_SM_", 4) == 0 &&
	    buf[5] < 32 && dmi_checksum(buf, buf[5])) {
		smbios_ver = (buf[6] << 8) + buf[7];

		/* 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)) {
491 492 493
		dmi_num = (buf[13] << 8) | buf[12];
		dmi_len = (buf[7] << 8) | buf[6];
		dmi_base = (buf[11] << 24) | (buf[10] << 16) |
M
Matt Domsch 已提交
494
			(buf[9] << 8) | buf[8];
495

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

513
	return 1;
514 515
}

M
Matt Domsch 已提交
516 517 518
void __init dmi_scan_machine(void)
{
	char __iomem *p, *q;
519
	char buf[32];
M
Matt Domsch 已提交
520

521
	if (efi_enabled(EFI_CONFIG_TABLES)) {
522
		if (efi.smbios == EFI_INVALID_TABLE_ADDR)
523
			goto error;
M
Matt Domsch 已提交
524

525 526 527 528
		/* 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.
		 */
529
		p = dmi_ioremap(efi.smbios, 32);
M
Matt Domsch 已提交
530
		if (p == NULL)
531
			goto error;
532
		memcpy_fromio(buf, p, 32);
T
Tolentino, Matthew E 已提交
533
		dmi_iounmap(p, 32);
534 535

		if (!dmi_present(buf)) {
536
			dmi_available = 1;
537
			goto out;
538
		}
539
	} else {
M
Matt Domsch 已提交
540 541
		p = dmi_ioremap(0xF0000, 0x10000);
		if (p == NULL)
542
			goto error;
M
Matt Domsch 已提交
543

544 545 546 547 548 549 550
		/*
		 * 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.
		 */
551
		memset(buf, 0, 16);
M
Matt Domsch 已提交
552
		for (q = p; q < p + 0x10000; q += 16) {
553 554
			memcpy_fromio(buf + 16, q, 16);
			if (!dmi_present(buf)) {
555
				dmi_available = 1;
I
Ingo Molnar 已提交
556
				dmi_iounmap(p, 0x10000);
557
				goto out;
558
			}
559
			memcpy(buf, buf + 16, 16);
560
		}
561
		dmi_iounmap(p, 0x10000);
562
	}
563
 error:
564
	pr_info("DMI not present or invalid.\n");
565 566
 out:
	dmi_initialized = 1;
L
Linus Torvalds 已提交
567 568
}

569 570 571 572 573 574 575 576 577 578 579 580 581
/**
 * 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);
}

582 583 584 585 586 587 588 589 590 591 592 593 594
/**
 *	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)
595
			break;
596 597 598 599 600 601 602 603 604
		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;
		}

605 606 607 608 609 610
		/* No match */
		return false;
	}
	return true;
}

611 612 613 614 615 616 617 618 619
/**
 *	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 已提交
620 621 622
/**
 *	dmi_check_system - check system DMI data
 *	@list: array of dmi_system_id structures to match against
623 624 625 626 627
 *		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 已提交
628 629 630
 *
 *	Walk the blacklist table running matching functions until someone
 *	returns non zero or we hit the end. Callback function is called for
631
 *	each successful match. Returns the number of matches.
L
Linus Torvalds 已提交
632
 */
633
int dmi_check_system(const struct dmi_system_id *list)
L
Linus Torvalds 已提交
634
{
635 636 637
	int count = 0;
	const struct dmi_system_id *d;

638
	for (d = list; !dmi_is_end_of_table(d); d++)
639 640 641 642
		if (dmi_matches(d)) {
			count++;
			if (d->callback && d->callback(d))
				break;
L
Linus Torvalds 已提交
643 644 645 646 647 648
		}

	return count;
}
EXPORT_SYMBOL(dmi_check_system);

649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664
/**
 *	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;

665
	for (d = list; !dmi_is_end_of_table(d); d++)
666 667 668 669 670 671 672
		if (dmi_matches(d))
			return d;

	return NULL;
}
EXPORT_SYMBOL(dmi_first_match);

L
Linus Torvalds 已提交
673 674
/**
 *	dmi_get_system_info - return DMI data value
675
 *	@field: data index (see enum dmi_field)
L
Linus Torvalds 已提交
676 677 678 679
 *
 *	Returns one DMI data value, can be used to perform
 *	complex DMI data checks.
 */
680
const char *dmi_get_system_info(int field)
L
Linus Torvalds 已提交
681 682 683
{
	return dmi_ident[field];
}
684
EXPORT_SYMBOL(dmi_get_system_info);
685

686
/**
R
Randy Dunlap 已提交
687 688
 * dmi_name_in_serial - Check if string is in the DMI product serial information
 * @str: string to check for
689 690 691 692 693 694 695 696
 */
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;
}
697 698

/**
699
 *	dmi_name_in_vendors - Check if string is in the DMI system or board vendor name
700
 *	@str: Case sensitive Name
701
 */
702
int dmi_name_in_vendors(const char *str)
703
{
704
	static int fields[] = { DMI_SYS_VENDOR, DMI_BOARD_VENDOR, DMI_NONE };
705 706 707 708 709 710 711 712 713 714
	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);

715 716 717
/**
 *	dmi_find_device - find onboard device by type/name
 *	@type: device type or %DMI_DEV_TYPE_ANY to match all device types
718
 *	@name: device name string or %NULL to match all
719 720 721 722 723
 *	@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.
724
 *	A new search is initiated by passing %NULL as the @from argument.
725 726
 *	If @from is not %NULL, searches continue from next device.
 */
727
const struct dmi_device *dmi_find_device(int type, const char *name,
728
				    const struct dmi_device *from)
729
{
730 731
	const struct list_head *head = from ? &from->list : &dmi_devices;
	struct list_head *d;
732

733
	for (d = head->next; d != &dmi_devices; d = d->next) {
734 735
		const struct dmi_device *dev =
			list_entry(d, struct dmi_device, list);
736 737 738 739 740 741 742 743 744

		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);
745 746

/**
747 748 749 750 751
 *	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
752
 *
753 754 755 756 757 758 759 760 761 762
 *	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.
763
 */
764
bool dmi_get_date(int field, int *yearp, int *monthp, int *dayp)
765
{
766 767 768
	int year = 0, month = 0, day = 0;
	bool exists;
	const char *s, *y;
769
	char *e;
770

771 772 773 774
	s = dmi_get_system_info(field);
	exists = s;
	if (!exists)
		goto out;
775

776 777 778 779 780 781 782 783 784 785 786 787 788
	/*
	 * 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 */
789 790 791 792
		year += 1900;
		if (year < 1996)	/* no dates < spec 1.0 */
			year += 100;
	}
793 794 795 796 797 798 799 800 801
	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;
	}
802

803 804 805 806 807 808 809 810 811 812 813 814
	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;
815
}
816
EXPORT_SYMBOL(dmi_get_date);
817 818 819 820

/**
 *	dmi_walk - Walk the DMI table and get called back for every record
 *	@decode: Callback function
821
 *	@private_data: Private data to be passed to the callback function
822 823 824
 *
 *	Returns -1 when the DMI table can't be reached, 0 on success.
 */
825 826
int dmi_walk(void (*decode)(const struct dmi_header *, void *),
	     void *private_data)
827 828 829 830 831 832 833 834 835 836
{
	u8 *buf;

	if (!dmi_available)
		return -1;

	buf = ioremap(dmi_base, dmi_len);
	if (buf == NULL)
		return -1;

837
	dmi_table(buf, dmi_len, dmi_num, decode, private_data);
838 839 840 841 842

	iounmap(buf);
	return 0;
}
EXPORT_SYMBOL_GPL(dmi_walk);
J
Jiri Slaby 已提交
843 844 845

/**
 * dmi_match - compare a string to the dmi field (if exists)
R
Randy Dunlap 已提交
846 847
 * @f: DMI field identifier
 * @str: string to compare the DMI field to
J
Jiri Slaby 已提交
848 849 850 851 852 853 854 855 856 857 858 859 860
 *
 * 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);
861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877

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);