[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[dmidecode] [PATCH 3/4] Add support for SMBIOS 2.7.0: memory
From: |
Jean Delvare |
Subject: |
[dmidecode] [PATCH 3/4] Add support for SMBIOS 2.7.0: memory |
Date: |
Sat, 13 Nov 2010 20:49:23 +0100 |
Add support for memory arrays of 2 TB and more (DMI types 16, 19 and
20).
Add support for memory devices of 32 GB and more (DMI type 17).
---
dmidecode.c | 180 ++++++++++++++++++++++++++++++++++++++++++++++-------------
util.c | 16 +++++
util.h | 1
3 files changed, 160 insertions(+), 37 deletions(-)
--- dmidecode.orig/dmidecode.c 2010-11-11 16:29:54.000000000 +0100
+++ dmidecode/dmidecode.c 2010-11-11 21:34:48.000000000 +0100
@@ -214,6 +214,51 @@ static void dmi_dump(const struct dmi_he
}
}
+/* shift is 0 if the value is in bytes, 1 if it is in kilobytes */
+static void dmi_print_memory_size(u64 code, int shift)
+{
+ unsigned long capacity;
+ u16 split[7];
+ static const char *unit[8] =
+ {
+ "bytes", "kB", "MB", "GB", "TB", "PB", "EB", "ZB"
+ };
+ int i;
+
+ /*
+ * We split the overall size in powers of thousand: EB, PB, TB, GB,
+ * MB, kB and B. In practice, it is expected that only one or two
+ * (consecutive) of these will be non-zero.
+ */
+ split[0] = code.l & 0x3FFUL;
+ split[1] = (code.l >> 10) & 0x3FFUL;
+ split[2] = (code.l >> 20) & 0x3FFUL;
+ split[3] = ((code.h << 2) & 0x3FCUL) | (code.l >> 30);
+ split[4] = (code.h >> 8) & 0x3FFUL;
+ split[5] = (code.h >> 18) & 0x3FFUL;
+ split[6] = code.h >> 28;
+
+ /*
+ * Now we find the highest unit with a non-zero value. If the following
+ * is also non-zero, we use that as our base. If the following is zero,
+ * we simply display the highest unit.
+ */
+ for (i = 6; i > 0; i--)
+ {
+ if (split[i])
+ break;
+ }
+ if (i > 0 && split[i - 1])
+ {
+ i--;
+ capacity = split[i] + (split[i + 1] << 10);
+ }
+ else
+ capacity = split[i];
+
+ printf(" %lu %s", capacity, unit[i + shift]);
+}
+
/*
* 7.1 BIOS Information (Type 0)
*/
@@ -2060,21 +2105,6 @@ static const char *dmi_memory_array_ec_t
return out_of_spec;
}
-static void dmi_memory_array_capacity(u32 code)
-{
- if (code == 0x80000000)
- printf(" Unknown");
- else
- {
- if ((code & 0x000FFFFF) == 0)
- printf(" %u GB", code >> 20);
- else if ((code & 0x000003FF) == 0)
- printf(" %u MB", code >> 10);
- else
- printf(" %u kB", code);
- }
-}
-
static void dmi_memory_array_error_handle(u16 code)
{
if (code == 0xFFFE)
@@ -2115,6 +2145,11 @@ static void dmi_memory_device_size(u16 c
}
}
+static void dmi_memory_device_extended_size(u32 code)
+{
+ printf(" %lu MB", code & 0x7FFFFFFFUL);
+}
+
static const char *dmi_memory_device_form_factor(u8 code)
{
/* 7.18.1 */
@@ -2202,16 +2237,18 @@ static void dmi_memory_device_type_detai
"EDO",
"Window DRAM",
"Cache DRAM",
- "Non-Volatile" /* 12 */
+ "Non-Volatile",
+ "Registered (Buffered)",
+ "Unbuffered (Unregistered)" /* 14 */
};
- if ((code & 0x1FFE) == 0)
+ if ((code & 0x7FFE) == 0)
printf(" None");
else
{
int i;
- for (i = 1; i <= 12; i++)
+ for (i = 1; i <= 14; i++)
if (code & (1 << i))
printf(" %s", detail[i - 1]);
}
@@ -2309,12 +2346,22 @@ static void dmi_mapped_address_size(u32
{
if (code == 0)
printf(" Invalid");
- else if ((code & 0x000FFFFF) == 0)
- printf(" %u GB", code >> 20);
- else if ((code & 0x000003FF) == 0)
- printf(" %u MB", code >> 10);
else
- printf(" %u kB", code);
+ {
+ u64 size;
+
+ size.h = 0;
+ size.l = code;
+ dmi_print_memory_size(size, 1);
+ }
+}
+
+static void dmi_mapped_address_extended_size(u64 start, u64 end)
+{
+ if (start.h == end.h && start.l == end.l)
+ printf(" Invalid");
+ else
+ dmi_print_memory_size(u64_range(start, end), 0);
}
/*
@@ -3402,7 +3449,21 @@ static void dmi_decode(const struct dmi_
printf("\tError Correction Type: %s\n",
dmi_memory_array_ec_type(data[0x06]));
printf("\tMaximum Capacity:");
- dmi_memory_array_capacity(DWORD(data + 0x07));
+ if (DWORD(data + 0x07) == 0x80000000)
+ {
+ if (h->length < 0x17)
+ printf(" Unknown");
+ else
+ dmi_print_memory_size(QWORD(data +
0x0F), 0);
+ }
+ else
+ {
+ u64 capacity;
+
+ capacity.h = 0;
+ capacity.l = DWORD(data + 0x07);
+ dmi_print_memory_size(capacity, 1);
+ }
printf("\n");
if (!(opt.flags & FLAG_QUIET))
{
@@ -3432,7 +3493,10 @@ static void dmi_decode(const struct dmi_
dmi_memory_device_width(WORD(data + 0x0A));
printf("\n");
printf("\tSize:");
- dmi_memory_device_size(WORD(data + 0x0C));
+ if (h->length >= 0x20 && WORD(data + 0x0C) == 0x7FFF)
+ dmi_memory_device_extended_size(DWORD(data +
0x1C));
+ else
+ dmi_memory_device_size(WORD(data + 0x0C));
printf("\n");
printf("\tForm Factor: %s\n",
dmi_memory_device_form_factor(data[0x0E]));
@@ -3468,6 +3532,10 @@ static void dmi_decode(const struct dmi_
else
printf("%u", data[0x1B] & 0x0F);
printf("\n");
+ if (h->length < 0x22) break;
+ printf("\tConfigured Clock Speed:");
+ dmi_memory_device_speed(WORD(data + 0x20));
+ printf("\n");
break;
case 18: /* 7.19 32-bit Memory Error Information */
@@ -3496,12 +3564,31 @@ static void dmi_decode(const struct dmi_
case 19: /* 7.20 Memory Array Mapped Address */
printf("Memory Array Mapped Address\n");
if (h->length < 0x0F) break;
- printf("\tStarting Address: 0x%08X%03X\n",
- DWORD(data + 0x04) >> 2, (DWORD(data + 0x04) &
0x3) << 10);
- printf("\tEnding Address: 0x%08X%03X\n",
- DWORD(data + 0x08) >> 2, ((DWORD(data + 0x08) &
0x3) << 10) + 0x3FF);
- printf("\tRange Size:");
- dmi_mapped_address_size(DWORD(data + 0x08) - DWORD(data
+ 0x04) + 1);
+ if (h->length >= 0x1F && DWORD(data + 0x04) ==
0xFFFFFFFF)
+ {
+ u64 start, end;
+
+ start = QWORD(data + 0x0F);
+ end = QWORD(data + 0x17);
+
+ printf("\tStarting Address: 0x%08X%08Xk\n",
+ start.h, start.l);
+ printf("\tEnding Address: 0x%08X%08Xk\n",
+ end.h, end.l);
+ printf("\tRange Size:");
+ dmi_mapped_address_extended_size(start, end);
+ }
+ else
+ {
+ printf("\tStarting Address: 0x%08X%03X\n",
+ DWORD(data + 0x04) >> 2,
+ (DWORD(data + 0x04) & 0x3) << 10);
+ printf("\tEnding Address: 0x%08X%03X\n",
+ DWORD(data + 0x08) >> 2,
+ ((DWORD(data + 0x08) & 0x3) << 10) +
0x3FF);
+ printf("\tRange Size:");
+ dmi_mapped_address_size(DWORD(data + 0x08) -
DWORD(data + 0x04) + 1);
+ }
printf("\n");
if (!(opt.flags & FLAG_QUIET))
printf("\tPhysical Array Handle: 0x%04X\n",
@@ -3513,12 +3600,31 @@ static void dmi_decode(const struct dmi_
case 20: /* 7.21 Memory Device Mapped Address */
printf("Memory Device Mapped Address\n");
if (h->length < 0x13) break;
- printf("\tStarting Address: 0x%08X%03X\n",
- DWORD(data + 0x04) >> 2, (DWORD(data + 0x04) &
0x3) << 10);
- printf("\tEnding Address: 0x%08X%03X\n",
- DWORD(data + 0x08) >> 2, ((DWORD(data + 0x08) &
0x3) << 10) + 0x3FF);
- printf("\tRange Size:");
- dmi_mapped_address_size(DWORD(data + 0x08) - DWORD(data
+ 0x04) + 1);
+ if (h->length >= 0x23 && DWORD(data + 0x04) ==
0xFFFFFFFF)
+ {
+ u64 start, end;
+
+ start = QWORD(data + 0x13);
+ end = QWORD(data + 0x1B);
+
+ printf("\tStarting Address: 0x%08X%08Xk\n",
+ start.h, start.l);
+ printf("\tEnding Address: 0x%08X%08Xk\n",
+ end.h, end.l);
+ printf("\tRange Size:");
+ dmi_mapped_address_extended_size(start, end);
+ }
+ else
+ {
+ printf("\tStarting Address: 0x%08X%03X\n",
+ DWORD(data + 0x04) >> 2,
+ (DWORD(data + 0x04) & 0x3) << 10);
+ printf("\tEnding Address: 0x%08X%03X\n",
+ DWORD(data + 0x08) >> 2,
+ ((DWORD(data + 0x08) & 0x3) << 10) +
0x3FF);
+ printf("\tRange Size:");
+ dmi_mapped_address_size(DWORD(data + 0x08) -
DWORD(data + 0x04) + 1);
+ }
printf("\n");
if (!(opt.flags & FLAG_QUIET))
{
--- dmidecode.orig/util.c 2010-09-29 13:59:31.000000000 +0200
+++ dmidecode/util.c 2010-11-11 18:27:33.000000000 +0100
@@ -201,3 +201,19 @@ err_close:
fclose(f);
return -1;
}
+
+/* Returns end - start + 1, assuming start < end */
+u64 u64_range(u64 start, u64 end)
+{
+ u64 res;
+
+ res.h = end.h - start.h;
+ res.l = end.l - start.l;
+
+ if (end.l < start.l)
+ res.h--;
+ if (++res.l == 0)
+ res.h++;
+
+ return res;
+}
--- dmidecode.orig/util.h 2008-10-28 11:12:19.000000000 +0100
+++ dmidecode/util.h 2010-11-11 16:53:32.000000000 +0100
@@ -27,3 +27,4 @@
int checksum(const u8 *buf, size_t len);
void *mem_chunk(size_t base, size_t len, const char *devmem);
int write_dump(size_t base, size_t len, const void *data, const char
*dumpfile, int add);
+u64 u64_range(u64 start, u64 end);
--
Jean Delvare
- [dmidecode] [PATCH 0/4] SMBIOS 2.7.0 support, Jean Delvare, 2010/11/13
- [dmidecode] [PATCH 1/4] Update references to match SMBIOS 2.7.0, Jean Delvare, 2010/11/13
- [dmidecode] [PATCH 2/4] Add support SMBIOS 2.7.0: BIOS, chassis and processor, Jean Delvare, 2010/11/13
- [dmidecode] [PATCH 3/4] Add support for SMBIOS 2.7.0: memory,
Jean Delvare <=
- [dmidecode] [PATCH 4/4] Add support for SMBIOS 2.7.0: cooling device, IPMI, Jean Delvare, 2010/11/13
- [dmidecode] Re: [PATCH 0/4] SMBIOS 2.7.0 support, Jean Delvare, 2010/11/24