aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware/dmi_scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firmware/dmi_scan.c')
-rw-r--r--drivers/firmware/dmi_scan.c47
1 files changed, 43 insertions, 4 deletions
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index e35c5e04c46a..54e66adef252 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -32,6 +32,7 @@ static char dmi_ids_string[128] __initdata;
static struct dmi_memdev_info {
const char *device;
const char *bank;
+ u64 size; /* bytes */
u16 handle;
} *dmi_memdev;
static int dmi_memdev_nr;
@@ -186,7 +187,7 @@ static void __init dmi_save_uuid(const struct dmi_header *dm, int slot,
char *s;
int is_ff = 1, is_00 = 1, i;
- if (dmi_ident[slot] || dm->length <= index + 16)
+ if (dmi_ident[slot] || dm->length < index + 16)
return;
d = (u8 *) dm + index;
@@ -210,9 +211,9 @@ static void __init dmi_save_uuid(const struct dmi_header *dm, int slot,
* says that this is the defacto standard.
*/
if (dmi_ver >= 0x020600)
- sprintf(s, "%pUL", d);
+ sprintf(s, "%pUl", d);
else
- sprintf(s, "%pUB", d);
+ sprintf(s, "%pUb", d);
dmi_ident[slot] = s;
}
@@ -386,6 +387,8 @@ static void __init save_mem_devices(const struct dmi_header *dm, void *v)
{
const char *d = (const char *)dm;
static int nr;
+ u64 bytes;
+ u16 size;
if (dm->type != DMI_ENTRY_MEM_DEVICE || dm->length < 0x12)
return;
@@ -396,6 +399,20 @@ static void __init save_mem_devices(const struct dmi_header *dm, void *v)
dmi_memdev[nr].handle = get_unaligned(&dm->handle);
dmi_memdev[nr].device = dmi_string(dm, d[0x10]);
dmi_memdev[nr].bank = dmi_string(dm, d[0x11]);
+
+ size = get_unaligned((u16 *)&d[0xC]);
+ if (size == 0)
+ bytes = 0;
+ else if (size == 0xffff)
+ bytes = ~0ull;
+ else if (size & 0x8000)
+ bytes = (u64)(size & 0x7fff) << 10;
+ else if (size != 0x7fff)
+ bytes = (u64)size << 20;
+ else
+ bytes = (u64)get_unaligned((u32 *)&d[0x1C]) << 20;
+
+ dmi_memdev[nr].size = bytes;
nr++;
}
@@ -775,7 +792,15 @@ static bool dmi_matches(const struct dmi_system_id *dmi)
int s = dmi->matches[i].slot;
if (s == DMI_NONE)
break;
- if (dmi_ident[s]) {
+ if (s == DMI_OEM_STRING) {
+ /* DMI_OEM_STRING must be exact match */
+ const struct dmi_device *valid;
+
+ valid = dmi_find_device(DMI_DEV_TYPE_OEM_STRING,
+ dmi->matches[i].substr, NULL);
+ if (valid)
+ continue;
+ } else if (dmi_ident[s]) {
if (dmi->matches[i].exact_match) {
if (!strcmp(dmi_ident[s],
dmi->matches[i].substr))
@@ -1085,3 +1110,17 @@ void dmi_memdev_name(u16 handle, const char **bank, const char **device)
}
}
EXPORT_SYMBOL_GPL(dmi_memdev_name);
+
+u64 dmi_memdev_size(u16 handle)
+{
+ int n;
+
+ if (dmi_memdev) {
+ for (n = 0; n < dmi_memdev_nr; n++) {
+ if (handle == dmi_memdev[n].handle)
+ return dmi_memdev[n].size;
+ }
+ }
+ return ~0ull;
+}
+EXPORT_SYMBOL_GPL(dmi_memdev_size);