diff options
author | Erwan Velu <erwan.velu@free.fr> | 2009-10-30 22:00:09 +0100 |
---|---|---|
committer | Erwan Velu <erwan.velu@free.fr> | 2009-10-30 22:00:09 +0100 |
commit | a1d88954b2913bb6b992077accad6b23c6767abe (patch) | |
tree | 3a061d45f702c9c2c3f65c9e7ca99e696053efa7 | |
parent | cf14910be4b9941247f5aebb8d901455532553dc (diff) | |
download | syslinux-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.h | 3 | ||||
-rw-r--r-- | com32/gpllib/dmi/dmi.c | 87 | ||||
-rw-r--r-- | com32/hdt/hdt-cli-dmi.c | 2 | ||||
-rw-r--r-- | com32/modules/dmitest.c | 2 |
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); |