summaryrefslogtreecommitdiff
path: root/dmioem.c
diff options
context:
space:
mode:
authorJörg Frings-Fürst <debian@jff-webhosting.net>2018-10-03 08:05:58 +0200
committerJörg Frings-Fürst <debian@jff-webhosting.net>2018-10-03 08:05:58 +0200
commit7c994b7f6bda56308e5f1d50651d5951de92198f (patch)
tree2311835538d830ee1518d95059a0a425582dc14a /dmioem.c
parenta1e93482d9cc9ace5fc1494677b45d965f1ddcb7 (diff)
New upstream version 3.2upstream/3.2
Diffstat (limited to 'dmioem.c')
-rw-r--r--dmioem.c219
1 files changed, 176 insertions, 43 deletions
diff --git a/dmioem.c b/dmioem.c
index 034ad9f..1a9bd82 100644
--- a/dmioem.c
+++ b/dmioem.c
@@ -33,8 +33,11 @@
enum DMI_VENDORS
{
VENDOR_UNKNOWN,
- VENDOR_HP,
VENDOR_ACER,
+ VENDOR_HP,
+ VENDOR_HPE,
+ VENDOR_IBM,
+ VENDOR_LENOVO,
};
static enum DMI_VENDORS dmi_vendor = VENDOR_UNKNOWN;
@@ -56,14 +59,62 @@ void dmi_set_vendor(const char *s)
while (len && s[len - 1] == ' ')
len--;
- if (strncmp(s, "HP", len) == 0 || strncmp(s, "Hewlett-Packard", len) == 0)
- dmi_vendor = VENDOR_HP;
- else if (strncmp(s, "Acer", len) == 0)
+ if (strncmp(s, "Acer", len) == 0)
dmi_vendor = VENDOR_ACER;
+ else if (strncmp(s, "HP", len) == 0 || strncmp(s, "Hewlett-Packard", len) == 0)
+ dmi_vendor = VENDOR_HP;
+ else if (strncmp(s, "HPE", len) == 0 || strncmp(s, "Hewlett Packard Enterprise", len) == 0)
+ dmi_vendor = VENDOR_HPE;
+ else if (strncmp(s, "IBM", len) == 0)
+ dmi_vendor = VENDOR_IBM;
+ else if (strncmp(s, "LENOVO", len) == 0)
+ dmi_vendor = VENDOR_LENOVO;
}
/*
- * HP-specific data structures are decoded here.
+ * Acer-specific data structures are decoded here.
+ */
+
+static int dmi_decode_acer(const struct dmi_header *h)
+{
+ u8 *data = h->data;
+ u16 cap;
+
+ switch (h->type)
+ {
+ case 170:
+ /*
+ * Vendor Specific: Acer Hotkey Function
+ *
+ * Source: acer-wmi kernel driver
+ *
+ * Probably applies to some laptop models of other
+ * brands, including Fujitsu-Siemens, Medion, Lenovo,
+ * and eMachines.
+ */
+ printf("Acer Hotkey Function\n");
+ if (h->length < 0x0F) break;
+ cap = WORD(data + 0x04);
+ printf("\tFunction bitmap for Communication Button: 0x%04hx\n", cap);
+ printf("\t\tWiFi: %s\n", cap & 0x0001 ? "Yes" : "No");
+ printf("\t\t3G: %s\n", cap & 0x0040 ? "Yes" : "No");
+ printf("\t\tWiMAX: %s\n", cap & 0x0080 ? "Yes" : "No");
+ printf("\t\tBluetooth: %s\n", cap & 0x0800 ? "Yes" : "No");
+ printf("\tFunction bitmap for Application Button: 0x%04hx\n", WORD(data + 0x06));
+ printf("\tFunction bitmap for Media Button: 0x%04hx\n", WORD(data + 0x08));
+ printf("\tFunction bitmap for Display Button: 0x%04hx\n", WORD(data + 0x0A));
+ printf("\tFunction bitmap for Others Button: 0x%04hx\n", WORD(data + 0x0C));
+ printf("\tCommunication Function Key Number: %d\n", data[0x0E]);
+ break;
+
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * HPE-specific data structures are decoded here.
*
* Code contributed by John Cagle and Tyler Bell.
*/
@@ -98,14 +149,15 @@ static int dmi_decode_hp(const struct dmi_header *h)
u8 *data = h->data;
int nic, ptr;
u32 feat;
+ const char *company = (dmi_vendor == VENDOR_HP) ? "HP" : "HPE";
switch (h->type)
{
case 204:
/*
- * Vendor Specific: HP ProLiant System/Rack Locator
+ * Vendor Specific: HPE ProLiant System/Rack Locator
*/
- printf("HP ProLiant System/Rack Locator\n");
+ printf("%s ProLiant System/Rack Locator\n", company);
if (h->length < 0x0B) break;
printf("\tRack Name: %s\n", dmi_string(h, data[0x04]));
printf("\tEnclosure Name: %s\n", dmi_string(h, data[0x05]));
@@ -119,7 +171,7 @@ static int dmi_decode_hp(const struct dmi_header *h)
case 209:
case 221:
/*
- * Vendor Specific: HP ProLiant NIC MAC Information
+ * Vendor Specific: HPE ProLiant NIC MAC Information
*
* This prints the BIOS NIC number,
* PCI bus/device/function, and MAC address
@@ -137,9 +189,10 @@ static int dmi_decode_hp(const struct dmi_header *h)
*
* Type 221: is deprecated in the latest docs
*/
- printf(h->type == 221 ?
- "HP BIOS iSCSI NIC PCI and MAC Information\n" :
- "HP BIOS PXE NIC PCI and MAC Information\n");
+ printf("%s %s\n", company,
+ h->type == 221 ?
+ "BIOS iSCSI NIC PCI and MAC Information" :
+ "BIOS PXE NIC PCI and MAC Information");
nic = 1;
ptr = 4;
while (h->length >= ptr + 8)
@@ -155,7 +208,7 @@ static int dmi_decode_hp(const struct dmi_header *h)
case 233:
/*
- * Vendor Specific: HP ProLiant NIC MAC Information
+ * Vendor Specific: HPE ProLiant NIC MAC Information
*
* This prints the BIOS NIC number,
* PCI bus/device/function, and MAC address
@@ -171,7 +224,7 @@ static int dmi_decode_hp(const struct dmi_header *h)
* 0x08 | MAC | 32B | MAC addr padded w/ 0s
* 0x28 | Port No| BYTE | Each NIC maps to a Port
*/
- printf("HP BIOS PXE NIC PCI and MAC Information\n");
+ printf("%s BIOS PXE NIC PCI and MAC Information\n", company);
if (h->length < 0x0E) break;
/* If the record isn't long enough, we don't have an ID
* use 0xFF to use the internal counter.
@@ -183,11 +236,11 @@ static int dmi_decode_hp(const struct dmi_header *h)
case 212:
/*
- * Vendor Specific: HP 64-bit CRU Information
+ * Vendor Specific: HPE 64-bit CRU Information
*
* Source: hpwdt kernel driver
*/
- printf("HP 64-bit CRU Information\n");
+ printf("%s 64-bit CRU Information\n", company);
if (h->length < 0x18) break;
printf("\tSignature: 0x%08x", DWORD(data + 0x04));
if (is_printable(data + 0x04, 4))
@@ -208,11 +261,11 @@ static int dmi_decode_hp(const struct dmi_header *h)
case 219:
/*
- * Vendor Specific: HP ProLiant Information
+ * Vendor Specific: HPE ProLiant Information
*
* Source: hpwdt kernel driver
*/
- printf("HP ProLiant Information\n");
+ printf("%s ProLiant Information\n", company);
if (h->length < 0x08) break;
printf("\tPower Features: 0x%08x\n", DWORD(data + 0x04));
if (h->length < 0x0C) break;
@@ -221,7 +274,7 @@ static int dmi_decode_hp(const struct dmi_header *h)
feat = DWORD(data + 0x10);
printf("\tMisc. Features: 0x%08x\n", feat);
printf("\t\tiCRU: %s\n", feat & 0x0001 ? "Yes" : "No");
- printf("\t\tUEFI: %s\n", feat & 0x0408 ? "Yes" : "No");
+ printf("\t\tUEFI: %s\n", feat & 0x1400 ? "Yes" : "No");
break;
default:
@@ -230,40 +283,116 @@ static int dmi_decode_hp(const struct dmi_header *h)
return 1;
}
-/*
- * Acer-specific data structures are decoded here.
- */
-
-static int dmi_decode_acer(const struct dmi_header *h)
+static int dmi_decode_ibm_lenovo(const struct dmi_header *h)
{
u8 *data = h->data;
- u16 cap;
switch (h->type)
{
- case 170:
+ case 131:
/*
- * Vendor Specific: Acer Hotkey Function
+ * Vendor Specific: ThinkVantage Technologies feature bits
*
- * Source: acer-wmi kernel driver
+ * Source: Compal hel81 Service Manual Software Specification,
+ * documented under "System Management BIOS(SM BIOS)
+ * version 2.4 or greater"
*
- * Probably applies to some laptop models of other
- * brands, including Fujitsu-Siemens, Medion, Lenovo,
- * and eMachines.
+ * Offset | Name | Width | Description
+ * ----------------------------------------------
+ * 0x00 | Type | BYTE | 0x83
+ * 0x01 | Length | BYTE | 0x16
+ * 0x02 | Handle | WORD | Varies
+ * 0x04 | Version | BYTE | 0x01
+ * 0x05 | TVT Structure | BYTEx16 | Each of the 128 bits represents a TVT feature:
+ * | | | - bit 127 means diagnostics (PC Doctor) is available
+ * | | | (http://www.pc-doctor.com/company/pr-articles/45-lenovo-introduces-thinkvantage-toolbox)
+ * | | | - the rest (126-0) are reserved/unknown
+ *
+ * It must also be followed by a string containing
+ * "TVT-Enablement". There exist other type 131 records
+ * with different length and a different string, for
+ * other purposes.
*/
- printf("Acer Hotkey Function\n");
- if (h->length < 0x0F) break;
- cap = WORD(data + 0x04);
- printf("\tFunction bitmap for Communication Button: 0x%04hx\n", cap);
- printf("\t\tWiFi: %s\n", cap & 0x0001 ? "Yes" : "No");
- printf("\t\t3G: %s\n", cap & 0x0040 ? "Yes" : "No");
- printf("\t\tWiMAX: %s\n", cap & 0x0080 ? "Yes" : "No");
- printf("\t\tBluetooth: %s\n", cap & 0x0800 ? "Yes" : "No");
- printf("\tFunction bitmap for Application Button: 0x%04hx\n", WORD(data + 0x06));
- printf("\tFunction bitmap for Media Button: 0x%04hx\n", WORD(data + 0x08));
- printf("\tFunction bitmap for Display Button: 0x%04hx\n", WORD(data + 0x0A));
- printf("\tFunction bitmap for Others Button: 0x%04hx\n", WORD(data + 0x0C));
- printf("\tCommunication Function Key Number: %d\n", data[0x0E]);
+
+ if (h->length != 0x16
+ || strcmp(dmi_string(h, 1), "TVT-Enablement") != 0)
+ return 0;
+
+ printf("ThinkVantage Technologies\n");
+ printf("\tVersion: %u\n", data[0x04]);
+ printf("\tDiagnostics: %s\n",
+ data[0x14] & 0x80 ? "Available" : "No");
+ break;
+
+ case 135:
+ /*
+ * Vendor Specific: Device Presence Detection bits
+ *
+ * Source: Compal hel81 Service Manual Software Specification,
+ * documented as "SMBIOS Type 135: Bulk for Lenovo
+ * Mobile PC Unique OEM Data" under appendix D.
+ *
+ * Offset | Name | Width | Description
+ * ---------------------------------------------------
+ * 0x00 | Type | BYTE | 0x87
+ * 0x01 | Length | BYTE | 0x0A
+ * 0x02 | Handle | WORD | Varies
+ * 0x04 | Signature | WORD | 0x5054 (ASCII for "TP")
+ * 0x06 | OEM struct offset | BYTE | 0x07
+ * 0x07 | OEM struct number | BYTE | 0x03, for this structure
+ * 0x08 | OEM struct revision | BYTE | 0x01, for this format
+ * 0x09 | Device presence bits | BYTE | Each of the 8 bits indicates device presence:
+ * | | | - bit 0 indicates the presence of a fingerprint reader
+ * | | | - the rest (7-1) are reserved/unknown
+ *
+ * Other OEM struct number+rev combinations have been
+ * seen in the wild but we don't know how to decode
+ * them.
+ */
+
+ if (h->length < 0x0A || data[0x04] != 'T' || data[0x05] != 'P')
+ return 0;
+
+ /* Bail out if not the expected format */
+ if (data[0x06] != 0x07 || data[0x07] != 0x03 || data[0x08] != 0x01)
+ return 0;
+
+ printf("ThinkPad Device Presence Detection\n");
+ printf("\tFingerprint Reader: %s\n",
+ data[0x09] & 0x01 ? "Present" : "No");
+ break;
+
+ case 140:
+ /*
+ * Vendor Specific: ThinkPad Embedded Controller Program
+ *
+ * Source: some guesswork, and publicly available information;
+ * Lenovo's BIOS update READMEs often contain the ECP IDs
+ * which match the first string in this type.
+ *
+ * Offset | Name | Width | Description
+ * ----------------------------------------------------
+ * 0x00 | Type | BYTE | 0x8C
+ * 0x01 | Length | BYTE |
+ * 0x02 | Handle | WORD | Varies
+ * 0x04 | Signature | BYTEx6 | ASCII for "LENOVO"
+ * 0x0A | OEM struct offset | BYTE | 0x0B
+ * 0x0B | OEM struct number | BYTE | 0x07, for this structure
+ * 0x0C | OEM struct revision | BYTE | 0x01, for this format
+ * 0x0D | ECP version ID | STRING |
+ * 0x0E | ECP release date | STRING |
+ */
+
+ if (h->length < 0x0F || memcmp(data + 4, "LENOVO", 6) != 0)
+ return 0;
+
+ /* Bail out if not the expected format */
+ if (data[0x0A] != 0x0B || data[0x0B] != 0x07 || data[0x0C] != 0x01)
+ return 0;
+
+ printf("ThinkPad Embedded Controller Program\n");
+ printf("\tVersion ID: %s\n", dmi_string(h, 1));
+ printf("\tRelease Date: %s\n", dmi_string(h, 2));
break;
default:
@@ -281,9 +410,13 @@ int dmi_decode_oem(const struct dmi_header *h)
switch (dmi_vendor)
{
case VENDOR_HP:
+ case VENDOR_HPE:
return dmi_decode_hp(h);
case VENDOR_ACER:
return dmi_decode_acer(h);
+ case VENDOR_IBM:
+ case VENDOR_LENOVO:
+ return dmi_decode_ibm_lenovo(h);
default:
return 0;
}