forked from mirrors/linux
		
	dmi_scan: refactor dmi_scan_machine(), {smbios,dmi}_present()
Move the calls to memcpy_fromio() up into the loop in dmi_scan_machine(), and move the signature checks back down into dmi_decode(). We need to check at 16-byte intervals but keep a 32-byte buffer for an SMBIOS entry, so shift the buffer after each iteration. Merge smbios_present() into dmi_present(), so we look for an SMBIOS signature at the beginning of the given buffer and then for a DMI signature at an offset of 16 bytes. [artem.savkov@gmail.com: use proper buf type in dmi_present()] Signed-off-by: Ben Hutchings <ben@decadent.org.uk> Reported-by: Tim McGrath <tmhikaru@gmail.com> Tested-by: Tim Mcgrath <tmhikaru@gmail.com> Cc: Zhenzhong Duan <zhenzhong.duan@oracle.com> Signed-off-by: Artem Savkov <artem.savkov@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									c1d025e22e
								
							
						
					
					
						commit
						79bae42d51
					
				
					 1 changed files with 37 additions and 43 deletions
				
			
		| 
						 | 
					@ -419,22 +419,45 @@ static void __init dmi_format_ids(char *buf, size_t len)
 | 
				
			||||||
			    dmi_get_system_info(DMI_BIOS_DATE));
 | 
								    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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memcpy_fromio(buf, p, 15);
 | 
						if (memcmp(buf, "_SM_", 4) == 0 &&
 | 
				
			||||||
	if (dmi_checksum(buf, 15)) {
 | 
						    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)) {
 | 
				
			||||||
		dmi_num = (buf[13] << 8) | buf[12];
 | 
							dmi_num = (buf[13] << 8) | buf[12];
 | 
				
			||||||
		dmi_len = (buf[7] << 8) | buf[6];
 | 
							dmi_len = (buf[7] << 8) | buf[6];
 | 
				
			||||||
		dmi_base = (buf[11] << 24) | (buf[10] << 16) |
 | 
							dmi_base = (buf[11] << 24) | (buf[10] << 16) |
 | 
				
			||||||
			(buf[9] << 8) | buf[8];
 | 
								(buf[9] << 8) | buf[8];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (dmi_walk_early(dmi_decode) == 0) {
 | 
							if (dmi_walk_early(dmi_decode) == 0) {
 | 
				
			||||||
			if (dmi_ver)
 | 
								if (smbios_ver) {
 | 
				
			||||||
 | 
									dmi_ver = smbios_ver;
 | 
				
			||||||
				pr_info("SMBIOS %d.%d present.\n",
 | 
									pr_info("SMBIOS %d.%d present.\n",
 | 
				
			||||||
				       dmi_ver >> 8, dmi_ver & 0xFF);
 | 
									       dmi_ver >> 8, dmi_ver & 0xFF);
 | 
				
			||||||
			else {
 | 
								} else {
 | 
				
			||||||
				dmi_ver = (buf[14] & 0xF0) << 4 |
 | 
									dmi_ver = (buf[14] & 0xF0) << 4 |
 | 
				
			||||||
					   (buf[14] & 0x0F);
 | 
										   (buf[14] & 0x0F);
 | 
				
			||||||
				pr_info("Legacy DMI %d.%d present.\n",
 | 
									pr_info("Legacy DMI %d.%d present.\n",
 | 
				
			||||||
| 
						 | 
					@ -445,40 +468,14 @@ static int __init dmi_present(const char __iomem *p)
 | 
				
			||||||
			return 0;
 | 
								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;
 | 
						return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void __init dmi_scan_machine(void)
 | 
					void __init dmi_scan_machine(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char __iomem *p, *q;
 | 
						char __iomem *p, *q;
 | 
				
			||||||
	int rc;
 | 
						char buf[32];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (efi_enabled(EFI_CONFIG_TABLES)) {
 | 
						if (efi_enabled(EFI_CONFIG_TABLES)) {
 | 
				
			||||||
		if (efi.smbios == EFI_INVALID_TABLE_ADDR)
 | 
							if (efi.smbios == EFI_INVALID_TABLE_ADDR)
 | 
				
			||||||
| 
						 | 
					@ -491,10 +488,10 @@ void __init dmi_scan_machine(void)
 | 
				
			||||||
		p = dmi_ioremap(efi.smbios, 32);
 | 
							p = dmi_ioremap(efi.smbios, 32);
 | 
				
			||||||
		if (p == NULL)
 | 
							if (p == NULL)
 | 
				
			||||||
			goto error;
 | 
								goto error;
 | 
				
			||||||
 | 
							memcpy_fromio(buf, p, 32);
 | 
				
			||||||
		rc = smbios_present(p);
 | 
					 | 
				
			||||||
		dmi_iounmap(p, 32);
 | 
							dmi_iounmap(p, 32);
 | 
				
			||||||
		if (!rc) {
 | 
					
 | 
				
			||||||
 | 
							if (!dmi_present(buf)) {
 | 
				
			||||||
			dmi_available = 1;
 | 
								dmi_available = 1;
 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -509,18 +506,15 @@ void __init dmi_scan_machine(void)
 | 
				
			||||||
		if (p == NULL)
 | 
							if (p == NULL)
 | 
				
			||||||
			goto error;
 | 
								goto error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							memset(buf, 0, 16);
 | 
				
			||||||
		for (q = p; q < p + 0x10000; q += 16) {
 | 
							for (q = p; q < p + 0x10000; q += 16) {
 | 
				
			||||||
			if (memcmp(q, "_SM_", 4) == 0 && q - p <= 0xFFE0)
 | 
								memcpy_fromio(buf + 16, q, 16);
 | 
				
			||||||
				rc = smbios_present(q);
 | 
								if (!dmi_present(buf)) {
 | 
				
			||||||
			else if (memcmp(q, "_DMI_", 5) == 0)
 | 
					 | 
				
			||||||
				rc = dmi_present(q);
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
				continue;
 | 
					 | 
				
			||||||
			if (!rc) {
 | 
					 | 
				
			||||||
				dmi_available = 1;
 | 
									dmi_available = 1;
 | 
				
			||||||
				dmi_iounmap(p, 0x10000);
 | 
									dmi_iounmap(p, 0x10000);
 | 
				
			||||||
				goto out;
 | 
									goto out;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								memcpy(buf, buf + 16, 16);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		dmi_iounmap(p, 0x10000);
 | 
							dmi_iounmap(p, 0x10000);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue