/* * Trimmed from DMI Decode http://savannah.nongnu.org/projects/dmidecode * * (C) 2000-2002 Alan Cox * (C) 2002-2007 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 * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For the avoidance of doubt the "preferred form" of this code is one which * is in an open unpatent encumbered format. Where cryptographic key signing * forms part of the process of creating an executable the information * including keys needed to generate an equivalently functional executable * are deemed to be part of the source code. */ #include #include #include #include #include "config.h" #include "types.h" #include "util.h" #include "dmidecode.h" #include "dmioem.h" #include "../state.h" #include "../pci.h" static const char *out_of_spec = ""; static const char *bad_index = ""; /* * Type-independant Stuff */ const char *dmi_string(struct dmi_header *dm, u8 s) { char *bp=(char *)dm->data; size_t i, len; if(s==0) return "Not Specified"; bp+=dm->length; while(s>1 && *bp) { bp+=strlen(bp); bp++; s--; } if(!*bp) return bad_index; /* ASCII filtering */ len=strlen(bp); for(i=0; i=0x01 && code<=0x04) return usage[code-0x01]; return out_of_spec; } static void dmi_slot_segment_bus_func(u16 code1, u8 code2, u8 code3, u8 type, const char *prefix) { /* 3.3.10.8 */ if (!(code1==0xFFFF && code2==0xFF && code3==0xFF)) printf("%sSegment Group %u, Bus %u, Device %u, Function %u ", prefix, code1, code2, (code3>>3)&0x1F, (code3&0x7)); switch(type) { case 0x06: /* PCI */ case 0x0E: /* PCI */ case 0x0F: /* AGP */ case 0x10: /* AGP */ case 0x11: /* AGP */ case 0x12: /* PCI-X */ case 0x13: /* AGP */ case 0xA5: /* PCI Express */ printf("\n"); break; default: if (code1 != 0xFF || code2 != 0xFF || code3 != 0xFF) printf("%s\n", out_of_spec); break; } } static u8 onboard_device_type(u8 code, const char *prefix) { /* 3.3.x.2 */ u8 e = (code & 0x80)>>7; static const char *type[]={ "Other", /* 1 */ "Unknown", "Video", "SCSI Controller", "Ethernet", "Token Ring", "Sound", "PATA Controller", "SATA Controller", "SAS Controller" /* 0x0A */ }; code = code & 0x7F; if(code>=0x01 && code<=0x0A) { printf("%sStatus: %s\n", prefix, e?"Enabled":"Disabled"); printf("%sDevice Type: %s\n", prefix, type[code-0x01]); } else printf("%sDevice Type: %s\n", prefix, out_of_spec); } /* * Main */ #define MIN(a,b) (((a)<(b))?(a):(b)) static void dmi_decode(struct dmi_header *h, u16 ver, const struct libbiosdevname_state *state) { u8 *data=h->data; int domain, bus, device, function; struct pci_device *pdev; switch(h->type) { case 9: /* 3.3.10 System Slots */ if (h->length >= 0x0E && h->length >=0x11) { domain = WORD(data+0x0D); bus = data[0x0F]; device = (data[0x10]>>3)&0x1F; function = data[0x10] & 7; if (! (domain == 0xFFFF && bus == 0xFF && data[0x10] == 0xFF)) { device = (data[0x10]>>3)&0x1F; function = data[0x10] & 7; pdev = find_pci_dev_by_pci_addr(state, domain, bus, device, function); if (pdev) { pdev->physical_slot = WORD(data+0x09); pdev->smbios_type = 0; pdev->smbios_instance = 0; } } } break; case 41: /* 3.3.xx Onboard Device Information */ domain = WORD(data+0x07); bus = data[0x09]; device = (data[0xa]>>3) & 0x1F; function = data[0xa] & 0x7; pdev = find_pci_dev_by_pci_addr(state, domain, bus, device, function); if (pdev) { pdev->physical_slot = 0; pdev->smbios_enabled = !!(data[0x05] & 0x80); pdev->smbios_type = data[0x05] & 0x7F; pdev->smbios_instance = data[0x06]; } break; default: if(dmi_decode_oem(h, state)) break; } } static void to_dmi_header(struct dmi_header *h, u8 *data) { h->type=data[0]; h->length=data[1]; h->handle=WORD(data+2); h->data=data; } static void dmi_table(u32 base, u16 len, u16 num, u16 ver, const char *devmem, const struct libbiosdevname_state *state) { u8 *buf; u8 *data; int i=0; if((buf=mem_chunk(base, len, devmem))==NULL) { #ifndef USE_MMAP printf("Table is unreachable, sorry. Try compiling dmidecode with -DUSE_MMAP.\n"); #endif return; } data=buf; while(i=5) dmi_set_vendor(dmi_string(&h, data[0x04])); /* look for the next handle */ next=data+h.length; while(next-buf+1