diff options
Diffstat (limited to 'drivers/firmware/dmi_scan.c')
| -rw-r--r-- | drivers/firmware/dmi_scan.c | 137 | 
1 files changed, 77 insertions, 60 deletions
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 4cd392dbf11..b95159b33c3 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -22,6 +22,9 @@ static u16 __initdata dmi_ver;   */  static int dmi_initialized; +/* DMI system identification string used during boot */ +static char dmi_ids_string[128] __initdata; +  static const char * __init dmi_string_nosave(const struct dmi_header *dm, u8 s)  {  	const u8 *bp = ((u8 *) dm) + dm->length; @@ -376,99 +379,103 @@ static void __init dmi_decode(const struct dmi_header *dm, void *dummy)  	}  } -static void __init print_filtered(const char *info) +static int __init print_filtered(char *buf, size_t len, const char *info)  { +	int c = 0;  	const char *p;  	if (!info) -		return; +		return c;  	for (p = info; *p; p++)  		if (isprint(*p)) -			printk(KERN_CONT "%c", *p); +			c += scnprintf(buf + c, len - c, "%c", *p);  		else -			printk(KERN_CONT "\\x%02x", *p & 0xff); +			c += scnprintf(buf + c, len - c, "\\x%02x", *p & 0xff); +	return c;  } -static void __init dmi_dump_ids(void) +static void __init dmi_format_ids(char *buf, size_t len)  { +	int c = 0;  	const char *board;	/* Board Name is optional */ -	printk(KERN_DEBUG "DMI: "); -	print_filtered(dmi_get_system_info(DMI_SYS_VENDOR)); -	printk(KERN_CONT " "); -	print_filtered(dmi_get_system_info(DMI_PRODUCT_NAME)); +	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)); +  	board = dmi_get_system_info(DMI_BOARD_NAME);  	if (board) { -		printk(KERN_CONT "/"); -		print_filtered(board); +		c += scnprintf(buf + c, len - c, "/"); +		c += print_filtered(buf + c, len - c, board);  	} -	printk(KERN_CONT ", BIOS "); -	print_filtered(dmi_get_system_info(DMI_BIOS_VERSION)); -	printk(KERN_CONT " "); -	print_filtered(dmi_get_system_info(DMI_BIOS_DATE)); -	printk(KERN_CONT "\n"); +	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));  } -static int __init dmi_present(const char __iomem *p) +static int __init dmi_present(const u8 *buf)  { -	u8 buf[15]; +	int smbios_ver; + +	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; +	} -	memcpy_fromio(buf, p, 15); -	if (dmi_checksum(buf, 15)) { +	buf += 16; + +	if (memcmp(buf, "_DMI_", 5) == 0 && dmi_checksum(buf, 15)) {  		dmi_num = (buf[13] << 8) | buf[12];  		dmi_len = (buf[7] << 8) | buf[6];  		dmi_base = (buf[11] << 24) | (buf[10] << 16) |  			(buf[9] << 8) | buf[8];  		if (dmi_walk_early(dmi_decode) == 0) { -			if (dmi_ver) +			if (smbios_ver) { +				dmi_ver = smbios_ver;  				pr_info("SMBIOS %d.%d present.\n",  				       dmi_ver >> 8, dmi_ver & 0xFF); -			else { +			} else {  				dmi_ver = (buf[14] & 0xF0) << 4 |  					   (buf[14] & 0x0F);  				pr_info("Legacy DMI %d.%d present.\n",  				       dmi_ver >> 8, dmi_ver & 0xFF);  			} -			dmi_dump_ids(); +			dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string)); +			printk(KERN_DEBUG "DMI: %s\n", dmi_ids_string);  			return 0;  		}  	} -	dmi_ver = 0; -	return 1; -} - -static int __init smbios_present(const char __iomem *p) -{ -	u8 buf[32]; -	memcpy_fromio(buf, p, 32); -	if ((buf[5] < 32) && dmi_checksum(buf, buf[5])) { -		dmi_ver = (buf[6] << 8) + buf[7]; - -		/* Some BIOS report weird SMBIOS version, fix that up */ -		switch (dmi_ver) { -		case 0x021F: -		case 0x0221: -			pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", -			       dmi_ver & 0xFF, 3); -			dmi_ver = 0x0203; -			break; -		case 0x0233: -			pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", 51, 6); -			dmi_ver = 0x0206; -			break; -		} -		return memcmp(p + 16, "_DMI_", 5) || dmi_present(p + 16); -	}  	return 1;  }  void __init dmi_scan_machine(void)  {  	char __iomem *p, *q; -	int rc; +	char buf[32];  	if (efi_enabled(EFI_CONFIG_TABLES)) {  		if (efi.smbios == EFI_INVALID_TABLE_ADDR) @@ -481,10 +488,10 @@ void __init dmi_scan_machine(void)  		p = dmi_ioremap(efi.smbios, 32);  		if (p == NULL)  			goto error; - -		rc = smbios_present(p); +		memcpy_fromio(buf, p, 32);  		dmi_iounmap(p, 32); -		if (!rc) { + +		if (!dmi_present(buf)) {  			dmi_available = 1;  			goto out;  		} @@ -499,18 +506,15 @@ void __init dmi_scan_machine(void)  		if (p == NULL)  			goto error; +		memset(buf, 0, 16);  		for (q = p; q < p + 0x10000; q += 16) { -			if (memcmp(q, "_SM_", 4) == 0 && q - p <= 0xFFE0) -				rc = smbios_present(q); -			else if (memcmp(q, "_DMI_", 5) == 0) -				rc = dmi_present(q); -			else -				continue; -			if (!rc) { +			memcpy_fromio(buf + 16, q, 16); +			if (!dmi_present(buf)) {  				dmi_available = 1;  				dmi_iounmap(p, 0x10000);  				goto out;  			} +			memcpy(buf, buf + 16, 16);  		}  		dmi_iounmap(p, 0x10000);  	} @@ -521,6 +525,19 @@ void __init dmi_scan_machine(void)  }  /** + * 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); +} + +/**   *	dmi_matches - check if dmi_system_id structure matches system DMI data   *	@dmi: pointer to the dmi_system_id structure to check   */  |