|
@@ -144,7 +144,7 @@ static int __init dmi_walk_early(void (*decode)(const struct dmi_header *,
|
|
|
|
|
|
buf = dmi_early_remap(dmi_base, orig_dmi_len);
|
|
buf = dmi_early_remap(dmi_base, orig_dmi_len);
|
|
if (buf == NULL)
|
|
if (buf == NULL)
|
|
- return -1;
|
|
|
|
|
|
+ return -ENOMEM;
|
|
|
|
|
|
dmi_decode_table(buf, decode, NULL);
|
|
dmi_decode_table(buf, decode, NULL);
|
|
|
|
|
|
@@ -178,7 +178,7 @@ static void __init dmi_save_ident(const struct dmi_header *dm, int slot,
|
|
const char *d = (const char *) dm;
|
|
const char *d = (const char *) dm;
|
|
const char *p;
|
|
const char *p;
|
|
|
|
|
|
- if (dmi_ident[slot])
|
|
|
|
|
|
+ if (dmi_ident[slot] || dm->length <= string)
|
|
return;
|
|
return;
|
|
|
|
|
|
p = dmi_string(dm, d[string]);
|
|
p = dmi_string(dm, d[string]);
|
|
@@ -191,13 +191,14 @@ static void __init dmi_save_ident(const struct dmi_header *dm, int slot,
|
|
static void __init dmi_save_uuid(const struct dmi_header *dm, int slot,
|
|
static void __init dmi_save_uuid(const struct dmi_header *dm, int slot,
|
|
int index)
|
|
int index)
|
|
{
|
|
{
|
|
- const u8 *d = (u8 *) dm + index;
|
|
|
|
|
|
+ const u8 *d;
|
|
char *s;
|
|
char *s;
|
|
int is_ff = 1, is_00 = 1, i;
|
|
int is_ff = 1, is_00 = 1, i;
|
|
|
|
|
|
- if (dmi_ident[slot])
|
|
|
|
|
|
+ if (dmi_ident[slot] || dm->length <= index + 16)
|
|
return;
|
|
return;
|
|
|
|
|
|
|
|
+ d = (u8 *) dm + index;
|
|
for (i = 0; i < 16 && (is_ff || is_00); i++) {
|
|
for (i = 0; i < 16 && (is_ff || is_00); i++) {
|
|
if (d[i] != 0x00)
|
|
if (d[i] != 0x00)
|
|
is_00 = 0;
|
|
is_00 = 0;
|
|
@@ -228,16 +229,17 @@ static void __init dmi_save_uuid(const struct dmi_header *dm, int slot,
|
|
static void __init dmi_save_type(const struct dmi_header *dm, int slot,
|
|
static void __init dmi_save_type(const struct dmi_header *dm, int slot,
|
|
int index)
|
|
int index)
|
|
{
|
|
{
|
|
- const u8 *d = (u8 *) dm + index;
|
|
|
|
|
|
+ const u8 *d;
|
|
char *s;
|
|
char *s;
|
|
|
|
|
|
- if (dmi_ident[slot])
|
|
|
|
|
|
+ if (dmi_ident[slot] || dm->length <= index)
|
|
return;
|
|
return;
|
|
|
|
|
|
s = dmi_alloc(4);
|
|
s = dmi_alloc(4);
|
|
if (!s)
|
|
if (!s)
|
|
return;
|
|
return;
|
|
|
|
|
|
|
|
+ d = (u8 *) dm + index;
|
|
sprintf(s, "%u", *d & 0x7F);
|
|
sprintf(s, "%u", *d & 0x7F);
|
|
dmi_ident[slot] = s;
|
|
dmi_ident[slot] = s;
|
|
}
|
|
}
|
|
@@ -278,9 +280,13 @@ static void __init dmi_save_devices(const struct dmi_header *dm)
|
|
|
|
|
|
static void __init dmi_save_oem_strings_devices(const struct dmi_header *dm)
|
|
static void __init dmi_save_oem_strings_devices(const struct dmi_header *dm)
|
|
{
|
|
{
|
|
- int i, count = *(u8 *)(dm + 1);
|
|
|
|
|
|
+ int i, count;
|
|
struct dmi_device *dev;
|
|
struct dmi_device *dev;
|
|
|
|
|
|
|
|
+ if (dm->length < 0x05)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ count = *(u8 *)(dm + 1);
|
|
for (i = 1; i <= count; i++) {
|
|
for (i = 1; i <= count; i++) {
|
|
const char *devname = dmi_string(dm, i);
|
|
const char *devname = dmi_string(dm, i);
|
|
|
|
|
|
@@ -353,6 +359,9 @@ static void __init dmi_save_extended_devices(const struct dmi_header *dm)
|
|
const char *name;
|
|
const char *name;
|
|
const u8 *d = (u8 *)dm;
|
|
const u8 *d = (u8 *)dm;
|
|
|
|
|
|
|
|
+ if (dm->length < 0x0B)
|
|
|
|
+ return;
|
|
|
|
+
|
|
/* Skip disabled device */
|
|
/* Skip disabled device */
|
|
if ((d[0x5] & 0x80) == 0)
|
|
if ((d[0x5] & 0x80) == 0)
|
|
return;
|
|
return;
|
|
@@ -387,7 +396,7 @@ static void __init save_mem_devices(const struct dmi_header *dm, void *v)
|
|
const char *d = (const char *)dm;
|
|
const char *d = (const char *)dm;
|
|
static int nr;
|
|
static int nr;
|
|
|
|
|
|
- if (dm->type != DMI_ENTRY_MEM_DEVICE)
|
|
|
|
|
|
+ if (dm->type != DMI_ENTRY_MEM_DEVICE || dm->length < 0x12)
|
|
return;
|
|
return;
|
|
if (nr >= dmi_memdev_nr) {
|
|
if (nr >= dmi_memdev_nr) {
|
|
pr_warn(FW_BUG "Too many DIMM entries in SMBIOS table\n");
|
|
pr_warn(FW_BUG "Too many DIMM entries in SMBIOS table\n");
|
|
@@ -649,6 +658,21 @@ void __init dmi_scan_machine(void)
|
|
if (p == NULL)
|
|
if (p == NULL)
|
|
goto error;
|
|
goto error;
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Same logic as above, look for a 64-bit entry point
|
|
|
|
+ * first, and if not found, fall back to 32-bit entry point.
|
|
|
|
+ */
|
|
|
|
+ memcpy_fromio(buf, p, 16);
|
|
|
|
+ for (q = p + 16; q < p + 0x10000; q += 16) {
|
|
|
|
+ memcpy_fromio(buf + 16, q, 16);
|
|
|
|
+ if (!dmi_smbios3_present(buf)) {
|
|
|
|
+ dmi_available = 1;
|
|
|
|
+ dmi_early_unmap(p, 0x10000);
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ memcpy(buf, buf + 16, 16);
|
|
|
|
+ }
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Iterate over all possible DMI header addresses q.
|
|
* Iterate over all possible DMI header addresses q.
|
|
* Maintain the 32 bytes around q in buf. On the
|
|
* Maintain the 32 bytes around q in buf. On the
|
|
@@ -659,7 +683,7 @@ void __init dmi_scan_machine(void)
|
|
memset(buf, 0, 16);
|
|
memset(buf, 0, 16);
|
|
for (q = p; q < p + 0x10000; q += 16) {
|
|
for (q = p; q < p + 0x10000; q += 16) {
|
|
memcpy_fromio(buf + 16, q, 16);
|
|
memcpy_fromio(buf + 16, q, 16);
|
|
- if (!dmi_smbios3_present(buf) || !dmi_present(buf)) {
|
|
|
|
|
|
+ if (!dmi_present(buf)) {
|
|
dmi_available = 1;
|
|
dmi_available = 1;
|
|
dmi_early_unmap(p, 0x10000);
|
|
dmi_early_unmap(p, 0x10000);
|
|
goto out;
|
|
goto out;
|
|
@@ -993,7 +1017,8 @@ EXPORT_SYMBOL(dmi_get_date);
|
|
* @decode: Callback function
|
|
* @decode: Callback function
|
|
* @private_data: Private data to be passed to the callback function
|
|
* @private_data: Private data to be passed to the callback function
|
|
*
|
|
*
|
|
- * Returns -1 when the DMI table can't be reached, 0 on success.
|
|
|
|
|
|
+ * Returns 0 on success, -ENXIO if DMI is not selected or not present,
|
|
|
|
+ * or a different negative error code if DMI walking fails.
|
|
*/
|
|
*/
|
|
int dmi_walk(void (*decode)(const struct dmi_header *, void *),
|
|
int dmi_walk(void (*decode)(const struct dmi_header *, void *),
|
|
void *private_data)
|
|
void *private_data)
|
|
@@ -1001,11 +1026,11 @@ int dmi_walk(void (*decode)(const struct dmi_header *, void *),
|
|
u8 *buf;
|
|
u8 *buf;
|
|
|
|
|
|
if (!dmi_available)
|
|
if (!dmi_available)
|
|
- return -1;
|
|
|
|
|
|
+ return -ENXIO;
|
|
|
|
|
|
buf = dmi_remap(dmi_base, dmi_len);
|
|
buf = dmi_remap(dmi_base, dmi_len);
|
|
if (buf == NULL)
|
|
if (buf == NULL)
|
|
- return -1;
|
|
|
|
|
|
+ return -ENOMEM;
|
|
|
|
|
|
dmi_decode_table(buf, decode, private_data);
|
|
dmi_decode_table(buf, decode, private_data);
|
|
|
|
|