From 53bafb796b654d1f7206196fd97cf8ba0b08ad7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Mon, 28 Sep 2015 12:29:58 +0200 Subject: Imported Upstream version 3.0 --- dmioem.c | 197 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 179 insertions(+), 18 deletions(-) (limited to 'dmioem.c') diff --git a/dmioem.c b/dmioem.c index a2b5a68..034ad9f 100644 --- a/dmioem.c +++ b/dmioem.c @@ -2,7 +2,7 @@ * Decoding of OEM-specific entries * This file is part of the dmidecode project. * - * Copyright (C) 2007-2008 Jean Delvare + * Copyright (C) 2007-2008 Jean Delvare * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,7 +30,12 @@ * Globals for vendor-specific decodes */ -enum DMI_VENDORS { VENDOR_UNKNOWN, VENDOR_HP }; +enum DMI_VENDORS +{ + VENDOR_UNKNOWN, + VENDOR_HP, + VENDOR_ACER, +}; static enum DMI_VENDORS dmi_vendor = VENDOR_UNKNOWN; @@ -41,20 +46,58 @@ static enum DMI_VENDORS dmi_vendor = VENDOR_UNKNOWN; */ void dmi_set_vendor(const char *s) { - if (strcmp(s, "HP") == 0 || strcmp(s, "Hewlett-Packard") == 0) + int len; + + /* + * Often DMI strings have trailing spaces. Ignore these + * when checking for known vendor names. + */ + len = strlen(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) + dmi_vendor = VENDOR_ACER; } /* * HP-specific data structures are decoded here. * - * Code contributed by John Cagle. + * Code contributed by John Cagle and Tyler Bell. */ +static void dmi_print_hp_net_iface_rec(u8 id, u8 bus, u8 dev, const u8 *mac) +{ + /* Some systems do not provide an id. nic_ctr provides an artificial + * id, and assumes the records will be provided "in order". Also, + * using 0xFF marker is not future proof. 256 NICs is a lot, but + * 640K ought to be enough for anybody(said no one, ever). + * */ + static u8 nic_ctr; + + if (id == 0xFF) + id = ++nic_ctr; + + if (dev == 0x00 && bus == 0x00) + printf("\tNIC %d: Disabled\n", id); + else if (dev == 0xFF && bus == 0xFF) + printf("\tNIC %d: Not Installed\n", id); + else + { + printf("\tNIC %d: PCI device %02x:%02x.%x, " + "MAC address %02X:%02X:%02X:%02X:%02X:%02X\n", + id, bus, dev >> 3, dev & 7, + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + } +} + static int dmi_decode_hp(const struct dmi_header *h) { u8 *data = h->data; int nic, ptr; + u32 feat; switch (h->type) { @@ -80,6 +123,19 @@ static int dmi_decode_hp(const struct dmi_header *h) * * This prints the BIOS NIC number, * PCI bus/device/function, and MAC address + * + * Type 209: + * Offset | Name | Width | Description + * ------------------------------------- + * 0x00 | Type | BYTE | 0xD1, MAC Info + * 0x01 | Length | BYTE | Length of structure + * 0x02 | Handle | WORD | Unique handle + * 0x04 | Dev No | BYTE | PCI Device/Function No + * 0x05 | Bus No | BYTE | PCI Bus + * 0x06 | MAC | 6B | MAC addr + * 0x0C | NIC #2 | 8B | Repeat 0x04-0x0B + * + * Type 221: is deprecated in the latest docs */ printf(h->type == 221 ? "HP BIOS iSCSI NIC PCI and MAC Information\n" : @@ -88,25 +144,128 @@ static int dmi_decode_hp(const struct dmi_header *h) ptr = 4; while (h->length >= ptr + 8) { - if (data[ptr] == 0x00 && data[ptr + 1] == 0x00) - printf("\tNIC %d: Disabled\n", nic); - else if (data[ptr] == 0xFF && data[ptr + 1] == 0xFF) - printf("\tNIC %d: Not Installed\n", nic); - else - { - printf("\tNIC %d: PCI device %02x:%02x.%x, " - "MAC address %02X:%02X:%02X:%02X:%02X:%02X\n", - nic, data[ptr + 1], - data[ptr] >> 3, data[ptr] & 7, - data[ptr + 2], data[ptr + 3], - data[ptr + 4], data[ptr + 5], - data[ptr + 6], data[ptr + 7]); - } + dmi_print_hp_net_iface_rec(nic, + data[ptr + 0x01], + data[ptr], + &data[ptr + 0x02]); nic++; ptr += 8; } break; + case 233: + /* + * Vendor Specific: HP ProLiant NIC MAC Information + * + * This prints the BIOS NIC number, + * PCI bus/device/function, and MAC address + * + * Offset | Name | Width | Description + * ------------------------------------- + * 0x00 | Type | BYTE | 0xE9, NIC structure + * 0x01 | Length | BYTE | Length of structure + * 0x02 | Handle | WORD | Unique handle + * 0x04 | Grp No | WORD | 0 for single segment + * 0x06 | Bus No | BYTE | PCI Bus + * 0x07 | Dev No | BYTE | PCI Device/Function No + * 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"); + 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. + * */ + nic = h->length > 0x28 ? data[0x28] : 0xFF; + dmi_print_hp_net_iface_rec(nic, data[0x06], data[0x07], + &data[0x08]); + break; + + case 212: + /* + * Vendor Specific: HP 64-bit CRU Information + * + * Source: hpwdt kernel driver + */ + printf("HP 64-bit CRU Information\n"); + if (h->length < 0x18) break; + printf("\tSignature: 0x%08x", DWORD(data + 0x04)); + if (is_printable(data + 0x04, 4)) + printf(" (%c%c%c%c)", data[0x04], data[0x05], + data[0x06], data[0x07]); + printf("\n"); + if (DWORD(data + 0x04) == 0x55524324) + { + u64 paddr = QWORD(data + 0x08); + paddr.l += DWORD(data + 0x14); + if (paddr.l < DWORD(data + 0x14)) + paddr.h++; + printf("\tPhysical Address: 0x%08x%08x\n", + paddr.h, paddr.l); + printf("\tLength: 0x%08x\n", DWORD(data + 0x10)); + } + break; + + case 219: + /* + * Vendor Specific: HP ProLiant Information + * + * Source: hpwdt kernel driver + */ + printf("HP ProLiant Information\n"); + if (h->length < 0x08) break; + printf("\tPower Features: 0x%08x\n", DWORD(data + 0x04)); + if (h->length < 0x0C) break; + printf("\tOmega Features: 0x%08x\n", DWORD(data + 0x08)); + if (h->length < 0x14) break; + 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"); + break; + + default: + return 0; + } + return 1; +} + +/* + * 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; } @@ -123,6 +282,8 @@ int dmi_decode_oem(const struct dmi_header *h) { case VENDOR_HP: return dmi_decode_hp(h); + case VENDOR_ACER: + return dmi_decode_acer(h); default: return 0; } -- cgit v1.2.3