All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2/2] Fetch dmi version from SMBIOS if it exist
@ 2012-07-25 11:05 zhenzhong.duan
  2012-07-25 19:55 ` Andrew Morton
  0 siblings, 1 reply; 3+ messages in thread
From: zhenzhong.duan @ 2012-07-25 11:05 UTC (permalink / raw)
  To: akpm, khali; +Cc: linux-kernel, Feng Jin

The right dmi version is in SMBIOS if it's zero in DMI region

Signed-off-by: Zhenzhong Duan <zhenzhong.duan@oracle.com>
---
 drivers/firmware/dmi_scan.c |   63 ++++++++++++++++++++++++++++++++----------
 1 files changed, 48 insertions(+), 15 deletions(-)

diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index d8c804d..bedefbf 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -116,12 +116,12 @@ static int __init dmi_walk_early(void (*decode)(const struct dmi_header *,
 	return 0;
 }
 
-static int __init dmi_checksum(const u8 *buf)
+static int __init dmi_checksum(const u8 *buf, u8 len)
 {
 	u8 sum = 0;
 	int a;
 
-	for (a = 0; a < 15; a++)
+	for (a = 0; a < len; a++)
 		sum += buf[a];
 
 	return sum == 0;
@@ -413,30 +413,58 @@ static int __init dmi_present(const char __iomem *p)
 	u8 buf[15];
 
 	memcpy_fromio(buf, p, 15);
-	if ((memcmp(buf, "_DMI_", 5) == 0) && dmi_checksum(buf)) {
+	if (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];
 
-		/*
-		 * DMI version 0.0 means that the real version is taken from
-		 * the SMBIOS version, which we don't know at this point.
-		 */
-		dmi_ver = (buf[14] & 0xf0) << 4 | (buf[14] & 0x0f);
-		if (buf[14] != 0)
-			printk(KERN_INFO "DMI %d.%d present.\n",
-			       buf[14] >> 4, buf[14] & 0xF);
-		else
-			printk(KERN_INFO "DMI present.\n");
 		if (dmi_walk_early(dmi_decode) == 0) {
+			if (dmi_ver)
+				printk(KERN_INFO "SMBIOS %d.%d present.\n",
+				       dmi_ver >> 8, dmi_ver & 0xFF);
+			else {
+				dmi_ver = (buf[14] & 0xF0) << 4 |
+					   (buf[14] & 0x0F);
+				printk(KERN_INFO "Legacy DMI %d.%d present.\n",
+				       dmi_ver >> 8, dmi_ver & 0xFF);
+			}
 			dmi_dump_ids();
 			return 0;
 		}
 	}
+	dmi_ver = 0;
 	return 1;
 }
 
+static int __init smbios_present(const char __iomem *p)
+{
+	u8 buf[32];
+	int offset = 0;
+
+	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:
+			printk(KERN_DEBUG "SMBIOS version fixup(2.%d->2.%d)\n",
+			       dmi_ver & 0xFF, 3);
+			dmi_ver = 0x0203;
+			break;
+		case 0x0233:
+			printk(KERN_DEBUG "SMBIOS version fixup(2.%d->2.%d)\n",
+			       51, 6);
+			dmi_ver = 0x0206;
+			break;
+		}
+		offset = 16;
+	}
+	return dmi_present(buf + offset);
+}
+
 void __init dmi_scan_machine(void)
 {
 	char __iomem *p, *q;
@@ -454,7 +482,7 @@ void __init dmi_scan_machine(void)
 		if (p == NULL)
 			goto error;
 
-		rc = dmi_present(p + 0x10); /* offset of _DMI_ string */
+		rc = smbios_present(p);
 		dmi_iounmap(p, 32);
 		if (!rc) {
 			dmi_available = 1;
@@ -472,7 +500,12 @@ void __init dmi_scan_machine(void)
 			goto error;
 
 		for (q = p; q < p + 0x10000; q += 16) {
-			rc = dmi_present(q);
+			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) {
 				dmi_available = 1;
 				dmi_iounmap(p, 0x10000);
-- 
1.7.3


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH 2/2] Fetch dmi version from SMBIOS if it exist
  2012-07-25 11:05 [PATCH 2/2] Fetch dmi version from SMBIOS if it exist zhenzhong.duan
@ 2012-07-25 19:55 ` Andrew Morton
  2012-07-26  1:41   ` zhenzhong.duan
  0 siblings, 1 reply; 3+ messages in thread
From: Andrew Morton @ 2012-07-25 19:55 UTC (permalink / raw)
  To: zhenzhong.duan; +Cc: khali, linux-kernel, Feng Jin

On Wed, 25 Jul 2012 19:05:09 +0800
"zhenzhong.duan" <zhenzhong.duan@oracle.com> wrote:

> The right dmi version is in SMBIOS if it's zero in DMI region
> 

This description is too brief to permit me to understand the patch. 
Can you please provide a more detailed explanation?


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH 2/2] Fetch dmi version from SMBIOS if it exist
  2012-07-25 19:55 ` Andrew Morton
@ 2012-07-26  1:41   ` zhenzhong.duan
  0 siblings, 0 replies; 3+ messages in thread
From: zhenzhong.duan @ 2012-07-26  1:41 UTC (permalink / raw)
  To: Andrew Morton; +Cc: khali, linux-kernel, Feng Jin



于 2012-07-26 03:55, Andrew Morton 写道:
> On Wed, 25 Jul 2012 19:05:09 +0800
> "zhenzhong.duan"<zhenzhong.duan@oracle.com>  wrote:
>
>> The right dmi version is in SMBIOS if it's zero in DMI region
>>
> This description is too brief to permit me to understand the patch.
> Can you please provide a more detailed explanation?
>
This issue was originally found from an oracle bug.
One customer noticed system UUID doesn't match between dmidecode & uek2.
HP ProLiant BL460c G6 :
# cat /sys/devices/virtual/dmi/id/product_uuid
00000000-0000-4C48-3031-4D5030333531
# dmidecode | grep -i uuid
UUID: 00000000-0000-484C-3031-4D5030333531
 From SMBIOS 2.6 on, spec use little-endian encoding for UUID other than 
network byte order.
So we need to get dmi version to distinguish. If version is 0.0, the 
real version is taken from the SMBIOS version. This is part of original 
kernel comment in code.

thanks
zduan

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2012-07-26  1:41 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-25 11:05 [PATCH 2/2] Fetch dmi version from SMBIOS if it exist zhenzhong.duan
2012-07-25 19:55 ` Andrew Morton
2012-07-26  1:41   ` zhenzhong.duan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.