summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErwan Velu <erwan.velu@free.fr>2009-10-30 22:00:09 +0100
committerErwan Velu <erwan.velu@free.fr>2009-10-30 22:00:09 +0100
commita1d88954b2913bb6b992077accad6b23c6767abe (patch)
tree3a061d45f702c9c2c3f65c9e7ca99e696053efa7
parentcf14910be4b9941247f5aebb8d901455532553dc (diff)
downloadsyslinux-a1d88954b2913bb6b992077accad6b23c6767abe.tar.gz
dmi: Adding smbios detection
Impact: Avoid misdetection of dmi version On some hosts, the legacy DMI version is reported as 0.0. We can use SMBIOS to get the real version. Solves HDT's ticket #8
-rw-r--r--com32/gplinclude/dmi/dmi.h3
-rw-r--r--com32/gpllib/dmi/dmi.c87
-rw-r--r--com32/hdt/hdt-cli-dmi.c2
-rw-r--r--com32/modules/dmitest.c2
4 files changed, 58 insertions, 36 deletions
diff --git a/com32/gplinclude/dmi/dmi.h b/com32/gplinclude/dmi/dmi.h
index def0a8ea..72bc8dc4 100644
--- a/com32/gplinclude/dmi/dmi.h
+++ b/com32/gplinclude/dmi/dmi.h
@@ -13,6 +13,7 @@
#ifndef DMI_H
#define DMI_H
#include <inttypes.h>
+#define DMI_BUFFER_SIZE 16
#define MAX_DMI_MEMORY_ITEMS 32
#define MAX_DMI_CACHE_ITEMS 32
#define OEM_STRINGS_SIZE 512
@@ -86,7 +87,7 @@ typedef struct {
void to_dmi_header(struct dmi_header *h, uint8_t * data);
void dmi_bios_runtime_size(uint32_t code, s_dmi * dmi);
const char *dmi_string(struct dmi_header *dm, uint8_t s);
-int dmi_checksum(uint8_t * buf);
+int dmi_checksum(uint8_t * buf, int len);
void parse_dmitable(s_dmi * dmi);
void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi * dmi);
int dmi_iterate(s_dmi * dmi);
diff --git a/com32/gpllib/dmi/dmi.c b/com32/gpllib/dmi/dmi.c
index ebf3c527..a72ef2ed 100644
--- a/com32/gpllib/dmi/dmi.c
+++ b/com32/gpllib/dmi/dmi.c
@@ -406,7 +406,6 @@ static void dmi_processor_id(uint8_t type, uint8_t * p, const char *version,
for (i = 0; i <= 31; i++)
if (cpu_flags_strings[i] != NULL && edx & (1 << i))
((bool *) (&dmi->processor.cpu_flags))[i] = true;
- //printf("%s\t%s\n", prefix, flags[i]);
}
}
@@ -445,19 +444,65 @@ const char *dmi_string(struct dmi_header *dm, uint8_t s)
return bp;
}
-int dmi_checksum(uint8_t * buf)
+int dmi_checksum(uint8_t * buf, int len)
{
uint8_t sum = 0;
int a;
- for (a = 0; a < 15; a++)
+ for (a = 0; a < len; a++)
sum += buf[a];
return (sum == 0);
}
+static int smbios_decode(s_dmi *dmi, uint8_t *buf)
+{
+
+ dmi->dmitable.ver = (buf[0x06] << 8) + buf[0x07];
+ /* Some BIOS report weird SMBIOS version, fix that up */
+ switch (dmi->dmitable.ver) {
+ case 0x021F:
+ dmi->dmitable.ver = 0x0203;
+ break;
+ case 0x0233:
+ dmi->dmitable.ver = 0x0206;
+ break;
+ }
+ dmi->dmitable.major_version=dmi->dmitable.ver >> 8;
+ dmi->dmitable.minor_version=dmi->dmitable.ver & 0xFF;
+
+ return DMI_TABLE_PRESENT;
+}
+
+
+static int legacy_decode(s_dmi *dmi, uint8_t *buf)
+{
+ dmi->dmitable.num = buf[13] << 8 | buf[12];
+ dmi->dmitable.len = buf[7] << 8 | buf[6];
+ dmi->dmitable.base =
+ buf[11] << 24 | buf[10] << 16 | buf[9] << 8 | buf[8];
+
+ if (dmi->dmitable.ver>0) return DMI_TABLE_PRESENT;
+
+ dmi->dmitable.ver = (buf[0x06] << 8) + buf[0x07];
+
+ /*
+ * DMI version 0.0 means that the real version is taken from
+ * the SMBIOS version, which we don't know at this point.
+ */
+ if (buf[14] != 0) {
+ dmi->dmitable.major_version = buf[14] >> 4;
+ dmi->dmitable.minor_version = buf[14] & 0x0F;
+ } else {
+ dmi->dmitable.major_version = 0;
+ dmi->dmitable.minor_version = 0;
+ }
+ return DMI_TABLE_PRESENT;
+}
+
+
int dmi_iterate(s_dmi * dmi)
{
- uint8_t buf[16];
+ uint8_t buf[DMI_BUFFER_SIZE];
char *p, *q;
/* Cleaning structures */
@@ -483,29 +528,11 @@ int dmi_iterate(s_dmi * dmi)
p = (char *)0xF0000; /* The start address to look at the dmi table */
for (q = p; q < p + 0x10000; q += 16) {
memcpy(buf, q, 15);
- if (memcmp(buf, "_DMI_", 5) == 0 && dmi_checksum(buf)) {
- dmi->dmitable.num = buf[13] << 8 | buf[12];
- dmi->dmitable.len = buf[7] << 8 | buf[6];
- dmi->dmitable.base =
- buf[11] << 24 | buf[10] << 16 | buf[9] << 8 | buf[8];
- dmi->dmitable.ver = (buf[0x06] << 8) + buf[0x07];
-
- /*
- * DMI version 0.0 means that the real version is taken from
- * the SMBIOS version, which we don't know at this point.
- */
- if (buf[14] != 0) {
- dmi->dmitable.major_version = buf[14] >> 4;
- dmi->dmitable.minor_version = buf[14] & 0x0F;
- } else {
- dmi->dmitable.major_version = 0;
- dmi->dmitable.minor_version = 0;
-
- }
-/* printf("DMI present (version %d.%d)\n", dmitable.major_version,dmitable.minor_version);
- printf("%d structures occupying %d bytes.\n",dmitable.num, dmitable.len);
- printf("DMI table at 0x%08X.\n",dmitable.base);*/
- return DMI_TABLE_PRESENT;
+ if (memcmp(buf, "_SM_", 4) == 0) {
+ smbios_decode(dmi,buf);
+ }
+ if (memcmp(buf, "_DMI_", 5) == 0 && dmi_checksum(buf,sizeof(buf))) {
+ return legacy_decode(dmi,buf);
}
}
dmi->dmitable.base = 0;
@@ -524,7 +551,6 @@ void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi * dmi)
*/
switch (h->type) {
case 0: /* 3.3.1 BIOS Information */
-// printf("BIOS Information\n");
if (h->length < 0x12)
break;
dmi->bios.filled = true;
@@ -552,7 +578,6 @@ void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi * dmi)
data[0x16], data[0x17]);
break;
case 1: /* 3.3.2 System Information */
-// printf("System Information\n");
if (h->length < 0x08)
break;
dmi->system.filled = true;
@@ -571,7 +596,6 @@ void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi * dmi)
break;
case 2: /* 3.3.3 Base Board Information */
-// printf("Base Board Information\n");
if (h->length < 0x08)
break;
dmi->base_board.filled = true;
@@ -589,7 +613,6 @@ void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi * dmi)
break;
break;
case 3: /* 3.3.4 Chassis Information */
-// printf("Chassis Information\n");
if(h->length<0x09) break;
dmi->chassis.filled=true;
strcpy(dmi->chassis.manufacturer,dmi_string(h,data[0x04]));
@@ -611,7 +634,6 @@ void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi * dmi)
break;
case 4: /* 3.3.5 Processor Information */
-// printf("Processor Information\n");
if(h->length<0x1A) break;
dmi->processor.filled=true;
strcpy(dmi->processor.socket_designation,dmi_string(h, data[0x04]));
@@ -843,7 +865,6 @@ void parse_dmitable(s_dmi * dmi)
(unsigned int)h.length);
break;
}
-// printf("Handle 0x%04X, DMI type %d, %d bytes\n", h.handle, h.type, h.length);
/* loo for the next handle */
next = data + h.length;
diff --git a/com32/hdt/hdt-cli-dmi.c b/com32/hdt/hdt-cli-dmi.c
index fca94cdc..111fe56e 100644
--- a/com32/hdt/hdt-cli-dmi.c
+++ b/com32/hdt/hdt-cli-dmi.c
@@ -505,7 +505,7 @@ void main_show_dmi(int argc __unused, char **argv __unused,
printf("No valid DMI table found, exiting.\n");
return;
}
- printf("DMI Table version %d.%d found\n",
+ printf("DMI Table version %u.%u found\n",
hardware->dmi.dmitable.major_version,
hardware->dmi.dmitable.minor_version);
diff --git a/com32/modules/dmitest.c b/com32/modules/dmitest.c
index d85b3127..212e82af 100644
--- a/com32/modules/dmitest.c
+++ b/com32/modules/dmitest.c
@@ -179,7 +179,7 @@ int main(void)
printf("No DMI Structure found\n");
return -1;
} else {
- printf("DMI %d.%d present.\n", dmi.dmitable.major_version,
+ printf("DMI %u.%u present.\n", dmi.dmitable.major_version,
dmi.dmitable.minor_version);
printf("%d structures occupying %d bytes.\n", dmi.dmitable.num,
dmi.dmitable.len);