Index: trunk/i386/libsaio/smbios_patcher.c =================================================================== --- trunk/i386/libsaio/smbios_patcher.c (revision 781) +++ trunk/i386/libsaio/smbios_patcher.c (revision 782) @@ -1,1067 +0,0 @@ -/* - * Copyright 2008 mackerintel - */ - -#include "libsaio.h" -#include "boot.h" -#include "bootstruct.h" -#include "acpi.h" -#include "efi_tables.h" -#include "fake_efi.h" -#include "platform.h" -#include "smbios_patcher.h" -#include "pci.h" - -#ifndef DEBUG_SMBIOS -#define DEBUG_SMBIOS 0 -#endif - -#if DEBUG_SMBIOS -#define DBG(x...) printf(x) -#else -#define DBG(x...) -#endif - -typedef struct { - const char* key; - const char* value; -} SMStrEntryPair; - -// defaults for a MacBook -static const SMStrEntryPair const sm_macbook_defaults[]={ - {"SMbiosvendor", "Apple Inc." }, - {"SMbiosversion", "MB41.88Z.0073.B00.0809221748" }, - {"SMbiosdate", "04/01/2008" }, - {"SMmanufacter", "Apple Inc." }, - {"SMproductname", "MacBook4,1" }, - {"SMsystemversion", "1.0" }, - {"SMserial", "SOMESRLNMBR" }, - {"SMfamily", "MacBook" }, - {"SMboardmanufacter", "Apple Inc." }, - {"SMboardproduct", "Mac-F42D89C8" }, - { "","" } -}; - -// defaults for a MacBook Pro -static const SMStrEntryPair const sm_macbookpro_defaults[]={ - {"SMbiosvendor", "Apple Inc." }, - {"SMbiosversion", "MBP41.88Z.0073.B00.0809221748" }, - {"SMbiosdate", "04/01/2008" }, - {"SMmanufacter", "Apple Inc." }, - {"SMproductname", "MacBookPro4,1" }, - {"SMsystemversion", "1.0" }, - {"SMserial", "SOMESRLNMBR" }, - {"SMfamily", "MacBookPro" }, - {"SMboardmanufacter", "Apple Inc." }, - {"SMboardproduct", "Mac-F42D89C8" }, - { "","" } -}; - -// defaults for a Mac mini -static const SMStrEntryPair const sm_macmini_defaults[]={ - {"SMbiosvendor", "Apple Inc." }, - {"SMbiosversion", "MM21.88Z.009A.B00.0706281359" }, - {"SMbiosdate", "04/01/2008" }, - {"SMmanufacter", "Apple Inc." }, - {"SMproductname", "Macmini2,1" }, - {"SMsystemversion", "1.0" }, - {"SMserial", "SOMESRLNMBR" }, - {"SMfamily", "Napa Mac" }, - {"SMboardmanufacter", "Apple Inc." }, - {"SMboardproduct", "Mac-F4208EAA" }, - { "","" } -}; - -// defaults for an iMac -static const SMStrEntryPair const sm_imac_defaults[]={ - {"SMbiosvendor", "Apple Inc." }, - {"SMbiosversion", "IM81.88Z.00C1.B00.0802091538" }, - {"SMbiosdate", "04/01/2008" }, - {"SMmanufacter", "Apple Inc." }, - {"SMproductname", "iMac8,1" }, - {"SMsystemversion", "1.0" }, - {"SMserial", "SOMESRLNMBR" }, - {"SMfamily", "Mac" }, - {"SMboardmanufacter", "Apple Inc." }, - {"SMboardproduct", "Mac-F227BEC8" }, - { "","" } -}; - -// defaults for a Mac Pro -static const SMStrEntryPair const sm_macpro_defaults[]={ - {"SMbiosvendor", "Apple Computer, Inc." }, - {"SMbiosversion", "MP31.88Z.006C.B05.0802291410" }, - {"SMbiosdate", "04/01/2008" }, - {"SMmanufacter", "Apple Computer, Inc." }, - {"SMproductname", "MacPro3,1" }, - {"SMsystemversion", "1.0" }, - {"SMserial", "SOMESRLNMBR" }, - {"SMfamily", "MacPro" }, - {"SMboardmanufacter", "Apple Computer, Inc." }, - {"SMboardproduct", "Mac-F4208DC8" }, - { "","" } -}; - -// defaults for an iMac11,1 core i3/i5/i7 -static const SMStrEntryPair const sm_imac_core_defaults[]={ - {"SMbiosvendor", "Apple Inc." }, - {"SMbiosversion", "IM111.88Z.0034.B00.0802091538" }, - {"SMbiosdate", "06/01/2009" }, - {"SMmanufacter", "Apple Inc." }, - {"SMproductname", "iMac11,1" }, - {"SMsystemversion", "1.0" }, - {"SMserial", "SOMESRLNMBR" }, - {"SMfamily", "iMac" }, - {"SMboardmanufacter", "Apple Computer, Inc." }, - {"SMboardproduct", "Mac-F2268DAE" }, - { "","" } -}; - -// defaults for a Mac Pro 4,1 core i7/Xeon -static const SMStrEntryPair const sm_macpro_core_defaults[]={ - {"SMbiosvendor", "Apple Computer, Inc." }, - {"SMbiosversion", "MP41.88Z.0081.B04.0903051113" }, - {"SMbiosdate", "11/06/2009" }, - {"SMmanufacter", "Apple Computer, Inc." }, - {"SMproductname", "MacPro4,1" }, - {"SMsystemversion", "1.0" }, - {"SMserial", "SOMESRLNMBR" }, - {"SMfamily", "MacPro" }, - {"SMboardmanufacter", "Apple Computer, Inc." }, - {"SMboardproduct", "Mac-F4208DC8" }, - { "","" } -}; - -static const char* sm_get_defstr(const char * key, int table_num) -{ - int i; - const SMStrEntryPair* sm_defaults; - - if (platformCPUFeature(CPU_FEATURE_MOBILE)) { - if (Platform.CPU.NoCores > 1) { - sm_defaults=sm_macbookpro_defaults; - } else { - sm_defaults=sm_macbook_defaults; - } - } else { - switch (Platform.CPU.NoCores) - { - case 1: - sm_defaults=sm_macmini_defaults; - break; - case 2: - sm_defaults=sm_imac_defaults; - break; - default: - { - switch (Platform.CPU.Family) - { - case 0x06: - { - switch (Platform.CPU.Model) - { - case CPU_MODEL_FIELDS: // Intel Core i5, i7 LGA1156 (45nm) - case CPU_MODEL_DALES: // Intel Core i5, i7 LGA1156 (45nm) ??? - case CPU_MODEL_DALES_32NM: // Intel Core i3, i5, i7 LGA1156 (32nm) (Clarkdale, Arrandale) - case 0x19: // Intel Core i5 650 @3.20 Ghz - sm_defaults=sm_imac_core_defaults; - break; - case CPU_MODEL_NEHALEM: - case CPU_MODEL_NEHALEM_EX: - case CPU_MODEL_WESTMERE: - case CPU_MODEL_WESTMERE_EX: - sm_defaults=sm_macpro_core_defaults; - break; - default: - sm_defaults=sm_macpro_defaults; - break; - } - break; - } - default: - sm_defaults=sm_macpro_defaults; - break; - } - break; - } - } - } - - for (i=0; sm_defaults[i].key[0]; i++) { - if (!strcmp (sm_defaults[i].key, key)) { - return sm_defaults[i].value; - } - } - - // Shouldn't happen - printf ("Error: no default for '%s' known\n", key); - sleep (2); - return ""; -} - -static int sm_get_fsb(const char *name, int table_num) -{ - return Platform.CPU.FSBFrequency/1000000; -} - -static int sm_get_cpu (const char *name, int table_num) -{ - return Platform.CPU.CPUFrequency/1000000; -} - -static int sm_get_bus_speed (const char *name, int table_num) -{ - if (Platform.CPU.Vendor == 0x756E6547) // Intel - { - switch (Platform.CPU.Family) - { - case 0x06: - { - switch (Platform.CPU.Model) - { - case 0x0D: // ? - case CPU_MODEL_YONAH: // Yonah 0x0E - case CPU_MODEL_MEROM: // Merom 0x0F - case CPU_MODEL_PENRYN: // Penryn 0x17 - case CPU_MODEL_ATOM: // Atom 45nm 0x1C - return 0; // TODO: populate bus speed for these processors - -// case CPU_MODEL_FIELDS: // Intel Core i5, i7 LGA1156 (45nm) -// if (strstr(Platform.CPU.BrandString, "Core(TM) i5")) -// return 2500; // Core i5 -// return 4800; // Core i7 - -// case CPU_MODEL_NEHALEM: // Intel Core i7 LGA1366 (45nm) -// case CPU_MODEL_NEHALEM_EX: -// case CPU_MODEL_DALES: // Intel Core i5, i7 LGA1156 (45nm) ??? -// return 4800; // GT/s / 1000 -// - case CPU_MODEL_WESTMERE_EX: // Intel Core i7 LGA1366 (45nm) 6 Core ??? - return 0; // TODO: populate bus speed for these processors - -// case 0x19: // Intel Core i5 650 @3.20 Ghz -// return 2500; // why? Intel spec says 2.5GT/s - - case 0x19: // Intel Core i5 650 @3.20 Ghz - case CPU_MODEL_NEHALEM: // Intel Core i7 LGA1366 (45nm) - case CPU_MODEL_FIELDS: // Intel Core i5, i7 LGA1156 (45nm) - case CPU_MODEL_DALES: // Intel Core i5, i7 LGA1156 (45nm) ??? - case CPU_MODEL_DALES_32NM: // Intel Core i3, i5, i7 LGA1156 (32nm) - case CPU_MODEL_WESTMERE: // Intel Core i7 LGA1366 (32nm) 6 Core - case CPU_MODEL_NEHALEM_EX: // Intel Core i7 LGA1366 (45nm) 6 Core ??? - { // thanks to dgobe for i3/i5/i7 bus speed detection - int nhm_bus = 0x3F; - static long possible_nhm_bus[] = {0xFF, 0x7F, 0x3F}; - unsigned long did, vid; - int i; - - // Nehalem supports Scrubbing - // First, locate the PCI bus where the MCH is located - for(i = 0; i < sizeof(possible_nhm_bus); i++) - { - vid = pci_config_read16(PCIADDR(possible_nhm_bus[i], 3, 4), 0x00); - did = pci_config_read16(PCIADDR(possible_nhm_bus[i], 3, 4), 0x02); - vid &= 0xFFFF; - did &= 0xFF00; - - if(vid == 0x8086 && did >= 0x2C00) - nhm_bus = possible_nhm_bus[i]; - } - - unsigned long qpimult, qpibusspeed; - qpimult = pci_config_read32(PCIADDR(nhm_bus, 2, 1), 0x50); - qpimult &= 0x7F; - DBG("qpimult %d\n", qpimult); - qpibusspeed = (qpimult * 2 * (Platform.CPU.FSBFrequency/1000000)); - // Rek: rounding decimals to match original mac profile info - if (qpibusspeed%100 != 0)qpibusspeed = ((qpibusspeed+50)/100)*100; - DBG("qpibusspeed %d\n", qpibusspeed); - return qpibusspeed; - } - } - } - } - } - return 0; -} - -static int sm_get_simplecputype() -{ - if (Platform.CPU.NoCores >= 4) - { - return 0x0501; // Quad-Core Xeon - } - else if (Platform.CPU.NoCores == 1) - { - return 0x0201; // Core Solo - }; - - return 0x0301; // Core 2 Duo -} - -static int sm_get_cputype (const char *name, int table_num) -{ - static bool done = false; - - if (Platform.CPU.Vendor == 0x756E6547) // Intel - { - if (!done) { - verbose("CPU is %s, family 0x%x, model 0x%x\n", Platform.CPU.BrandString, Platform.CPU.Family, Platform.CPU.Model); - done = true; - } - - switch (Platform.CPU.Family) - { - case 0x06: - { - switch (Platform.CPU.Model) - { - case 0x0D: // ? - case CPU_MODEL_YONAH: // Yonah - case CPU_MODEL_MEROM: // Merom - case CPU_MODEL_PENRYN: // Penryn - case CPU_MODEL_ATOM: // Intel Atom (45nm) - return sm_get_simplecputype(); - - case CPU_MODEL_NEHALEM: // Intel Core i7 LGA1366 (45nm) - return 0x0701; // Core i7 - - case CPU_MODEL_FIELDS: // Lynnfield, Clarksfield, Jasper - if (strstr(Platform.CPU.BrandString, "Core(TM) i5")) - return 0x601; // Core i5 - return 0x701; // Core i7 - - case CPU_MODEL_DALES: // Intel Core i5, i7 LGA1156 (45nm) (Havendale, Auburndale) - if (strstr(Platform.CPU.BrandString, "Core(TM) i5")) - return 0x601; // Core i5 - return 0x0701; // Core i7 - - case CPU_MODEL_DALES_32NM: // Intel Core i3, i5, i7 LGA1156 (32nm) (Clarkdale, Arrandale) - if (strstr(Platform.CPU.BrandString, "Core(TM) i3")) - return 0x901; // Core i3 - if (strstr(Platform.CPU.BrandString, "Core(TM) i5")) - return 0x601; // Core i5 - return 0x0701; // Core i7 - - case CPU_MODEL_WESTMERE: // Intel Core i7 LGA1366 (32nm) 6 Core (Gulftown, Westmere-EP, Westmere-WS) - case CPU_MODEL_WESTMERE_EX: // Intel Core i7 LGA1366 (45nm) 6 Core ??? - return 0x0701; // Core i7 - - case 0x19: // Intel Core i5 650 @3.20 Ghz - return 0x601; // Core i5 - } - } - } - } - - return sm_get_simplecputype(); -} - -static int sm_get_memtype (const char *name, int table_num) -{ - int map; - - if (table_num < MAX_RAM_SLOTS) { - map = Platform.DMI.DIMM[table_num]; - if (Platform.RAM.DIMM[map].InUse && Platform.RAM.DIMM[map].Type != 0) { - DBG("RAM Detected Type = %d\n", Platform.RAM.DIMM[map].Type); - return Platform.RAM.DIMM[map].Type; - } - } - - return SMB_MEM_TYPE_DDR2; -} - -static int sm_get_memspeed (const char *name, int table_num) -{ - int map; - - if (table_num < MAX_RAM_SLOTS) { - map = Platform.DMI.DIMM[table_num]; - if (Platform.RAM.DIMM[map].InUse && Platform.RAM.DIMM[map].Frequency != 0) { - DBG("RAM Detected Freq = %d Mhz\n", Platform.RAM.DIMM[map].Frequency); - return Platform.RAM.DIMM[map].Frequency; - } - } - - return 800; -} - -static const char *sm_get_memvendor (const char *name, int table_num) -{ - int map; - - if (table_num < MAX_RAM_SLOTS) { - map = Platform.DMI.DIMM[table_num]; - if (Platform.RAM.DIMM[map].InUse && strlen(Platform.RAM.DIMM[map].Vendor) > 0) { - DBG("RAM Detected Vendor[%d]='%s'\n", table_num, Platform.RAM.DIMM[map].Vendor); - return Platform.RAM.DIMM[map].Vendor; - } - } - return "N/A"; -} - -static const char *sm_get_memserial (const char *name, int table_num) -{ - int map; - - if (table_num < MAX_RAM_SLOTS) { - map = Platform.DMI.DIMM[table_num]; - if (Platform.RAM.DIMM[map].InUse && strlen(Platform.RAM.DIMM[map].SerialNo) > 0) { - DBG("name = %s, map=%d, RAM Detected SerialNo[%d]='%s'\n", name ? name : "", - map, table_num, Platform.RAM.DIMM[map].SerialNo); - return Platform.RAM.DIMM[map].SerialNo; - } - } - return "N/A"; -} - -static const char *sm_get_mempartno (const char *name, int table_num) -{ - int map; - - if (table_num < MAX_RAM_SLOTS) { - map = Platform.DMI.DIMM[table_num]; - if (Platform.RAM.DIMM[map].InUse && strlen(Platform.RAM.DIMM[map].PartNo) > 0) { - DBG("Ram Detected PartNo[%d]='%s'\n", table_num, Platform.RAM.DIMM[map].PartNo); - return Platform.RAM.DIMM[map].PartNo; - } - } - return "N/A"; -} - -static int sm_one (int tablen) -{ - return 1; -} - -struct smbios_property smbios_properties[]= -{ - {.name="SMbiosvendor", .table_type= 0, .value_type=SMSTRING, .offset=0x04, .auto_str=sm_get_defstr }, - {.name="SMbiosversion", .table_type= 0, .value_type=SMSTRING, .offset=0x05, .auto_str=sm_get_defstr }, - {.name="SMbiosdate", .table_type= 0, .value_type=SMSTRING, .offset=0x08, .auto_str=sm_get_defstr }, - {.name="SMmanufacter", .table_type= 1, .value_type=SMSTRING, .offset=0x04, .auto_str=sm_get_defstr }, - {.name="SMproductname", .table_type= 1, .value_type=SMSTRING, .offset=0x05, .auto_str=sm_get_defstr }, - {.name="SMsystemversion", .table_type= 1, .value_type=SMSTRING, .offset=0x06, .auto_str=sm_get_defstr }, - {.name="SMserial", .table_type= 1, .value_type=SMSTRING, .offset=0x07, .auto_str=sm_get_defstr }, - {.name="SMUUID", .table_type= 1, .value_type=SMOWORD, .offset=0x08, .auto_oword=0 }, - {.name="SMfamily", .table_type= 1, .value_type=SMSTRING, .offset=0x1a, .auto_str=sm_get_defstr }, - {.name="SMboardmanufacter", .table_type= 2, .value_type=SMSTRING, .offset=0x04, .auto_str=sm_get_defstr }, - {.name="SMboardproduct", .table_type= 2, .value_type=SMSTRING, .offset=0x05, .auto_str=sm_get_defstr }, - {.name="SMexternalclock", .table_type= 4, .value_type=SMWORD, .offset=0x12, .auto_int=sm_get_fsb }, - {.name="SMmaximalclock", .table_type= 4, .value_type=SMWORD, .offset=0x14, .auto_int=sm_get_cpu }, - {.name="SMmemdevloc", .table_type=17, .value_type=SMSTRING, .offset=0x10, .auto_str=0 }, - {.name="SMmembankloc", .table_type=17, .value_type=SMSTRING, .offset=0x11, .auto_str=0 }, - {.name="SMmemtype", .table_type=17, .value_type=SMBYTE, .offset=0x12, .auto_int=sm_get_memtype}, - {.name="SMmemspeed", .table_type=17, .value_type=SMWORD, .offset=0x15, .auto_int=sm_get_memspeed}, - {.name="SMmemmanufacter", .table_type=17, .value_type=SMSTRING, .offset=0x17, .auto_str=sm_get_memvendor}, - {.name="SMmemserial", .table_type=17, .value_type=SMSTRING, .offset=0x18, .auto_str=sm_get_memserial}, - {.name="SMmempart", .table_type=17, .value_type=SMSTRING, .offset=0x1A, .auto_str=sm_get_mempartno}, - {.name="SMcputype", .table_type=131,.value_type=SMWORD, .offset=0x04, .auto_int=sm_get_cputype}, - {.name="SMbusspeed", .table_type=132,.value_type=SMWORD, .offset=0x04, .auto_int=sm_get_bus_speed} -}; - -struct smbios_table_description smbios_table_descriptions[]= -{ - {.type=0, .len=0x18, .numfunc=sm_one}, - {.type=1, .len=0x1b, .numfunc=sm_one}, - {.type=2, .len=0x0f, .numfunc=sm_one}, - {.type=4, .len=0x2a, .numfunc=sm_one}, - {.type=17, .len=0x1c, .numfunc=0}, - {.type=131, .len=0x06, .numfunc=sm_one}, - {.type=132, .len=0x06, .numfunc=sm_one} -}; - -// getting smbios addr with fast compare ops, late checksum testing ... -#define COMPARE_DWORD(a,b) ( *((u_int32_t *) a) == *((u_int32_t *) b) ) -static const char * const SMTAG = "_SM_"; -static const char* const DMITAG= "_DMI_"; - -static struct SMBEntryPoint *getAddressOfSmbiosTable(void) -{ - struct SMBEntryPoint *smbios; - /* - * The logic is to start at 0xf0000 and end at 0xfffff iterating 16 bytes at a time looking - * for the SMBIOS entry-point structure anchor (literal ASCII "_SM_"). - */ - smbios = (struct SMBEntryPoint*) SMBIOS_RANGE_START; - while (smbios <= (struct SMBEntryPoint *)SMBIOS_RANGE_END) { - if (COMPARE_DWORD(smbios->anchor, SMTAG) && - COMPARE_DWORD(smbios->dmi.anchor, DMITAG) && - smbios->dmi.anchor[4]==DMITAG[4] && - checksum8(smbios, sizeof(struct SMBEntryPoint)) == 0) - { - return smbios; - } - smbios = (struct SMBEntryPoint*) ( ((char*) smbios) + 16 ); - } - printf("ERROR: Unable to find SMBIOS!\n"); - pause(); - return NULL; -} - -/** Compute necessary space requirements for new smbios */ -static struct SMBEntryPoint *smbios_dry_run(struct SMBEntryPoint *origsmbios) -{ - struct SMBEntryPoint *ret; - char *smbiostables; - char *tablesptr; - int origsmbiosnum; - int i, j; - int tablespresent[256]; - bool do_auto=true; - - bzero(tablespresent, sizeof(tablespresent)); - - getBoolForKey(kSMBIOSdefaults, &do_auto, &bootInfo->bootConfig); - - ret = (struct SMBEntryPoint *)AllocateKernelMemory(sizeof(struct SMBEntryPoint)); - if (origsmbios) { - smbiostables = (char *)origsmbios->dmi.tableAddress; - origsmbiosnum = origsmbios->dmi.structureCount; - } else { - smbiostables = NULL; - origsmbiosnum = 0; - } - - // _SM_ - ret->anchor[0] = 0x5f; - ret->anchor[1] = 0x53; - ret->anchor[2] = 0x4d; - ret->anchor[3] = 0x5f; - ret->entryPointLength = sizeof(*ret); - ret->majorVersion = 2; - ret->minorVersion = 1; - ret->maxStructureSize = 0; // will be calculated later in this function - ret->entryPointRevision = 0; - for (i=0;i<5;i++) { - ret->formattedArea[i] = 0; - } - //_DMI_ - ret->dmi.anchor[0] = 0x5f; - ret->dmi.anchor[1] = 0x44; - ret->dmi.anchor[2] = 0x4d; - ret->dmi.anchor[3] = 0x49; - ret->dmi.anchor[4] = 0x5f; - ret->dmi.tableLength = 0; // will be calculated later in this function - ret->dmi.tableAddress = 0; // will be initialized in smbios_real_run() - ret->dmi.structureCount = 0; // will be calculated later in this function - ret->dmi.bcdRevision = 0x21; - tablesptr = smbiostables; - - // add stringlen of overrides to original stringlen, update maxStructure size adequately, - // update structure count and tablepresent[type] with count of type. - if (smbiostables) { - for (i=0; ilength; - stringsptr = tablesptr; - for (; tablesptr[0]!=0 || tablesptr[1]!=0; tablesptr++); - tablesptr += 2; - stringlen = tablesptr - stringsptr - 1; - if (stringlen == 1) { - stringlen = 0; - } - for (j=0; jtype] + 1); - if (smbios_properties[j].table_type == cur->type && - smbios_properties[j].value_type == SMSTRING && - (getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig) || - getValueForKey(altname,&str, &size, &bootInfo->smbiosConfig))) - { - stringlen += size + 1; - } else if (smbios_properties[j].table_type == cur->type && - smbios_properties[j].value_type == SMSTRING && - do_auto && smbios_properties[j].auto_str) - { - stringlen += strlen(smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[cur->type])) + 1; - } - } - if (stringlen == 0) { - stringlen = 1; - } - stringlen++; - if (ret->maxStructureSize < cur->length+stringlen) { - ret->maxStructureSize=cur->length+stringlen; - } - ret->dmi.tableLength += cur->length+stringlen; - ret->dmi.structureCount++; - tablespresent[cur->type]++; - } - } - // Add eventually table types whose detected count would be < required count, and update ret header with: - // new stringlen addons, structure count, and tablepresent[type] count adequately - for (i=0; ismbiosConfig)) { - numnec = -1; - } - if (numnec==-1 && do_auto && smbios_table_descriptions[i].numfunc) { - numnec = smbios_table_descriptions[i].numfunc(smbios_table_descriptions[i].type); - } - while (tablespresent[smbios_table_descriptions[i].type] < numnec) { - int stringlen = 0; - for (j=0; jsmbiosConfig) || - getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig))) - { - stringlen += size + 1; - } else if (smbios_properties[j].table_type == smbios_table_descriptions[i].type && - smbios_properties[j].value_type==SMSTRING && - do_auto && smbios_properties[j].auto_str) - { - stringlen += strlen(smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[smbios_table_descriptions[i].type])) + 1; - } - } - if (stringlen == 0) { - stringlen = 1; - } - stringlen++; - if (ret->maxStructureSize < smbios_table_descriptions[i].len+stringlen) { - ret->maxStructureSize = smbios_table_descriptions[i].len + stringlen; - } - ret->dmi.tableLength += smbios_table_descriptions[i].len + stringlen; - ret->dmi.structureCount++; - tablespresent[smbios_table_descriptions[i].type]++; - } - } - return ret; -} - -/** From the origsmbios detected by getAddressOfSmbiosTable() to newsmbios whose entrypoint - * struct has been created by smbios_dry_run, update each table struct content of new smbios - * int the new allocated table address of size newsmbios->tablelength. - */ -static void smbios_real_run(struct SMBEntryPoint * origsmbios, struct SMBEntryPoint * newsmbios) -{ - char *smbiostables; - char *tablesptr, *newtablesptr; - int origsmbiosnum; - // bitmask of used handles - uint8_t handles[8192]; - uint16_t nexthandle=0; - int i, j; - int tablespresent[256]; - bool do_auto=true; - - static bool done = false; // IMPROVEME: called twice via getSmbios(), but only the second call can get all necessary info ! - - extern void dumpPhysAddr(const char * title, void * a, int len); - - bzero(tablespresent, sizeof(tablespresent)); - bzero(handles, sizeof(handles)); - - getBoolForKey(kSMBIOSdefaults, &do_auto, &bootInfo->bootConfig); - - newsmbios->dmi.tableAddress = (uint32_t)AllocateKernelMemory(newsmbios->dmi.tableLength); - if (origsmbios) { - smbiostables = (char *)origsmbios->dmi.tableAddress; - origsmbiosnum = origsmbios->dmi.structureCount; - } else { - smbiostables = NULL; - origsmbiosnum = 0; - } - tablesptr = smbiostables; - newtablesptr = (char *)newsmbios->dmi.tableAddress; - - // if old smbios exists then update new smbios with old smbios original content first - if (smbiostables) { - for (i=0; ihandle) / 8] |= 1 << ((oldcur->handle) % 8); - - // copy table length from old table to new table but not the old strings - memcpy(newcur,oldcur, oldcur->length); - - tablesptr += oldcur->length; - stringsptr = tablesptr; - newtablesptr += oldcur->length; - - // calculate the number of strings in the old content - for (;tablesptr[0]!=0 || tablesptr[1]!=0; tablesptr++) { - if (tablesptr[0] == 0) { - nstrings++; - } - } - if (tablesptr != stringsptr) { - nstrings++; - } - tablesptr += 2; - - // copy the old strings to new table - memcpy(newtablesptr, stringsptr, tablesptr-stringsptr); - - // point to next possible space for a string (deducting the second 0 char at the end) - newtablesptr += tablesptr - stringsptr - 1; - if (nstrings == 0) { // if no string was found rewind to the first 0 char of the 0,0 terminator - newtablesptr--; - } - - // now for each property in the table update the overrides if any (auto or user) - for (j=0; jtype] + 1); - if (smbios_properties[j].table_type == newcur->type) { - switch (smbios_properties[j].value_type) { - case SMSTRING: - if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) || - getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig)) - { - memcpy(newtablesptr, str, size); - newtablesptr[size] = 0; - newtablesptr += size + 1; - *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings; - } else if (do_auto && smbios_properties[j].auto_str) { - str = smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]); - size = strlen(str); - memcpy(newtablesptr, str, size); - newtablesptr[size] = 0; - newtablesptr += size + 1; - *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings; - } - break; - - case SMOWORD: - if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) || - getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig)) - { - int k=0, t=0, kk=0; - const char *ptr = str; - memset(((char*)newcur) + smbios_properties[j].offset, 0, 16); - while (ptr-str=2 && ptr[0]=='0' && (ptr[1]=='x' || ptr[1]=='X')) { - ptr += 2; - } - for (;ptr-str='0' && *ptr<='9') { - (t=(t<<4)|(*ptr-'0')),kk++; - } - if (*ptr>='a' && *ptr<='f') { - (t=(t<<4)|(*ptr-'a'+10)),kk++; - } - if (*ptr>='A' && *ptr<='F') { - (t=(t<<4)|(*ptr-'A'+10)),kk++; - } - if (kk == 2) { - *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset + k)) = t; - k++; - kk = 0; - t = 0; - } - } - } - break; - - case SMBYTE: - if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) || - getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig)) - { - *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = num; - } else if (do_auto && smbios_properties[j].auto_int) { - *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]); - } - break; - - case SMWORD: - if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) || - getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig)) - { - *((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = num; - } else if (do_auto && smbios_properties[j].auto_int) { - *((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]); - } - break; - } - } - } - if (nstrings == 0) { - newtablesptr[0] = 0; - newtablesptr++; - } - newtablesptr[0] = 0; - newtablesptr++; - tablespresent[newcur->type]++; - } - } - - // for each eventual complementary table not present in the original smbios, do the overrides - for (i=0; ismbiosConfig)) { - numnec = -1; - } - if (numnec == -1 && do_auto && smbios_table_descriptions[i].numfunc) { - numnec = smbios_table_descriptions[i].numfunc(smbios_table_descriptions[i].type); - } - while (tablespresent[smbios_table_descriptions[i].type] < numnec) { - struct smbios_table_header *newcur = (struct smbios_table_header *) newtablesptr; - int nstrings = 0; - - memset(newcur,0, smbios_table_descriptions[i].len); - while (handles[(nexthandle)/8] & (1 << ((nexthandle) % 8))) { - nexthandle++; - } - newcur->handle = nexthandle; - handles[nexthandle / 8] |= 1 << (nexthandle % 8); - newcur->type = smbios_table_descriptions[i].type; - newcur->length = smbios_table_descriptions[i].len; - newtablesptr += smbios_table_descriptions[i].len; - for (j=0; jtype] + 1); - if (smbios_properties[j].table_type == newcur->type) { - switch (smbios_properties[j].value_type) { - case SMSTRING: - if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) || - getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig)) - { - memcpy(newtablesptr, str, size); - newtablesptr[size] = 0; - newtablesptr += size + 1; - *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings; - } else if (do_auto && smbios_properties[j].auto_str) { - str = smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]); - size = strlen(str); - memcpy(newtablesptr, str, size); - newtablesptr[size] = 0; - newtablesptr += size + 1; - *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings; - } - break; - - case SMOWORD: - if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) || - getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig)) - { - int k=0, t=0, kk=0; - const char *ptr = str; - - memset(((char*)newcur) + smbios_properties[j].offset, 0, 16); - while (ptr-str=2 && ptr[0]=='0' && (ptr[1]=='x' || ptr[1]=='X')) { - ptr += 2; - } - for (;ptr-str='0' && *ptr<='9') { - (t=(t<<4)|(*ptr-'0')),kk++; - } - if (*ptr>='a' && *ptr<='f') { - (t=(t<<4)|(*ptr-'a'+10)),kk++; - } - if (*ptr>='A' && *ptr<='F') { - (t=(t<<4)|(*ptr-'A'+10)),kk++; - } - if (kk == 2) { - *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset + k)) = t; - k++; - kk = 0; - t = 0; - } - } - } - break; - - case SMBYTE: - if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) || - getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig)) - { - *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = num; - } else if (do_auto && smbios_properties[j].auto_int) { - *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]); - } - break; - - case SMWORD: - if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) || - getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig)) - { - *((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = num; - } else if (do_auto && smbios_properties[j].auto_int) { - *((uint16_t*)(((char*)newcur)+smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]); - } - break; - } - } - } - if (nstrings == 0) { - newtablesptr[0] = 0; - newtablesptr++; - } - newtablesptr[0] = 0; - newtablesptr++; - tablespresent[smbios_table_descriptions[i].type]++; - } - } - - // calculate new checksums - newsmbios->dmi.checksum = 0; - newsmbios->dmi.checksum = 256 - checksum8(&newsmbios->dmi, sizeof(newsmbios->dmi)); - newsmbios->checksum = 0; - newsmbios->checksum = 256 - checksum8(newsmbios, sizeof(*newsmbios)); - - if (!done) { - verbose("Patched DMI Table\n"); - done=true; - } -} - -#define MAX_DMI_TABLES 96 -typedef struct DmiNumAssocTag { - struct DMIHeader * dmi; - uint8_t type; -} DmiNumAssoc; - -static DmiNumAssoc DmiTablePair[MAX_DMI_TABLES]; -static int DmiTablePairCount = 0; -static int current_pos=0; -static bool ftTablePairInit = true; - -/** - * Get a table structure entry from a type specification and a smbios address - * return NULL if table is not found - */ -static void getSmbiosTableStructure(struct SMBEntryPoint *smbios) -{ - struct DMIHeader * dmihdr=NULL; - SMBByte* p; - int i; - - if (ftTablePairInit && smbios!=NULL) { - ftTablePairInit = false; -#if DEBUG_SMBIOS - printf(">>> SMBIOSAddr=0x%08x\n", smbios); - printf(">>> DMI: addr=0x%08x, len=%d, count=%d\n", smbios->dmi.tableAddress, - smbios->dmi.tableLength, smbios->dmi.structureCount); -#endif - p = (SMBByte *) smbios->dmi.tableAddress; - for (i=0; - i < smbios->dmi.structureCount && - p + 4 <= (SMBByte *)smbios->dmi.tableAddress + smbios->dmi.tableLength; - i++) { - dmihdr = (struct DMIHeader *) p; - -#if DEBUG_SMBIOS - // verbose(">>>>>> DMI(%d): type=0x%02x, len=0x%d\n",i,dmihdr->type,dmihdr->length); -#endif - if (dmihdr->length < 4 || dmihdr->type == 127 /* EOT */) break; - if (DmiTablePairCount < MAX_DMI_TABLES) { - DmiTablePair[DmiTablePairCount].dmi = dmihdr; - DmiTablePair[DmiTablePairCount].type = dmihdr->type; - DmiTablePairCount++; - } - else { - printf("DMI table entries list is full! Next entries won't be stored.\n"); - } -#if DEBUG_SMBIOS - printf("DMI header found for table type %d, length = %d\n", dmihdr->type, dmihdr->length); -#endif - p = p + dmihdr->length; - while ((p - (SMBByte *)smbios->dmi.tableAddress + 1 < smbios->dmi.tableLength) && (p[0] != 0x00 || p[1] != 0x00)) { - p++; - } - p += 2; - } - - } -} - -/** Get original or new smbios entry point, if sucessful, the adresses are cached for next time */ -struct SMBEntryPoint *getSmbios(int which) -{ - static struct SMBEntryPoint *orig = NULL; // cached - static struct SMBEntryPoint *patched = NULL; // cached - - // whatever we are called with orig or new flag, initialize asap both structures - switch (which) { - case SMBIOS_ORIGINAL: - if (orig==NULL) { - orig = getAddressOfSmbiosTable(); - getSmbiosTableStructure(orig); // generate tables entry list for fast table finding - } - return orig; - case SMBIOS_PATCHED: - if (orig==NULL && (orig = getAddressOfSmbiosTable())==NULL ) { - printf("Could not find original SMBIOS !!\n"); - pause(); - } else { - patched = smbios_dry_run(orig); - if(patched==NULL) { - printf("Could not create new SMBIOS !!\n"); - pause(); - } - else { - smbios_real_run(orig, patched); - } - } - - return patched; - default: - printf("ERROR: invalid option for getSmbios() !!\n"); - break; - } - - return NULL; -} - -/** Find first original dmi Table with a particular type */ -struct DMIHeader* FindFirstDmiTableOfType(int type, int minlength) -{ - current_pos = 0; - - return FindNextDmiTableOfType(type, minlength); -}; - -/** Find next original dmi Table with a particular type */ -struct DMIHeader* FindNextDmiTableOfType(int type, int minlength) -{ - int i; - - if (ftTablePairInit) getSmbios(SMBIOS_ORIGINAL); - - for (i=current_pos; i < DmiTablePairCount; i++) { - if (type == DmiTablePair[i].type && - DmiTablePair[i].dmi && - DmiTablePair[i].dmi->length >= minlength ) { - current_pos = i+1; - return DmiTablePair[i].dmi; - } - } - return NULL; // not found -}; - Index: trunk/i386/libsaio/smbios_patcher.h =================================================================== --- trunk/i386/libsaio/smbios_patcher.h (revision 781) +++ trunk/i386/libsaio/smbios_patcher.h (revision 782) @@ -1,56 +0,0 @@ -/* - * Copyright 2008 mackerintel - */ -/* - * AsereBLN: cleanup - */ - -#ifndef __LIBSAIO_SMBIOS_PATCHER_H -#define __LIBSAIO_SMBIOS_PATCHER_H - -#include "libsaio.h" -#include "SMBIOS.h" - -/* From Foundation/Efi/Guid/Smbios/SmBios.h */ -/* Modified to wrap Data4 array init with {} */ -#define EFI_SMBIOS_TABLE_GUID {0xeb9d2d31, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d}} - -#define SMBIOS_RANGE_START 0x000F0000 -#define SMBIOS_RANGE_END 0x000FFFFF - -#define SMBIOS_ORIGINAL 0 -#define SMBIOS_PATCHED 1 - -struct smbios_table_header -{ - uint8_t type; - uint8_t length; - uint16_t handle; -} __attribute__ ((packed)); - -struct smbios_property -{ - const char *name; - uint8_t table_type; - enum {SMSTRING, SMWORD, SMBYTE, SMOWORD} value_type; - int offset; - int (*auto_int) (const char *name, int table_num); - const char *(*auto_str) (const char *name, int table_num); - const char *(*auto_oword) (const char *name, int table_num); -}; - -struct smbios_table_description -{ - uint8_t type; - int len; - int (*numfunc)(int tablen); -}; - -/** call with flag SMBIOS_ORIGINAL to get orig. entrypoint - or call with flag SMBIOS_PATCHED to get patched smbios entrypoint -*/ -extern struct SMBEntryPoint *getSmbios(int); -extern struct DMIHeader* FindNextDmiTableOfType(int type, int minlen); -extern struct DMIHeader* FindFirstDmiTableOfType(int type, int minlen); - -#endif /* !__LIBSAIO_SMBIOS_PATCHER_H */ Index: trunk/i386/libsaio/smbios_getters.h =================================================================== --- trunk/i386/libsaio/smbios_getters.h (revision 0) +++ trunk/i386/libsaio/smbios_getters.h (revision 782) @@ -0,0 +1,41 @@ + +#include "libsaio.h" +#include "smbios.h" +#include "platform.h" +#include "pci.h" + +#ifndef __LIBSAIO_SMBIOS_GETTERS_H +#define __LIBSAIO_SMBIOS_GETTERS_H + +#define SMBIOS_RANGE_START 0x000F0000 +#define SMBIOS_RANGE_END 0x000FFFFF + +typedef enum { + kSMBString, + kSMBByte, + kSMBWord, + kSMBDWord +// kSMBQWord +} SMBValueType; + +typedef union { + const char *string; + uint8_t byte; + uint16_t word; + uint32_t dword; +// uint64_t qword; +} returnType; + +extern bool getProcessorInformationExternalClock(returnType *value); +extern bool getProcessorInformationMaximumClock(returnType *value); +extern bool getSMBOemProcessorBusSpeed(returnType *value); +extern bool getSMBOemProcessorType(returnType *value); +extern bool getSMBMemoryDeviceMemoryType(returnType *value); +extern bool getSMBMemoryDeviceMemorySpeed(returnType *value); +extern bool getSMBMemoryDeviceManufacturer(returnType *value); +extern bool getSMBMemoryDeviceSerialNumber(returnType *value); +extern bool getSMBMemoryDevicePartNumber(returnType *value); + +SMBEntryPoint *getAddressOfSmbiosTable(void); + +#endif /* !__LIBSAIO_SMBIOS_GETTERS_H */ Index: trunk/i386/libsaio/smbios.c =================================================================== --- trunk/i386/libsaio/smbios.c (revision 0) +++ trunk/i386/libsaio/smbios.c (revision 782) @@ -0,0 +1,774 @@ +/* + * SMBIOS Table Patcher, part of the Chameleon Boot Loader Project + * + * Copyright 2010 by Islam M. Ahmed Zaid. All rights reserved. + * + */ + + +#include "boot.h" +#include "bootstruct.h" +#include "smbios_getters.h" + +#ifndef DEBUG_SMBIOS +#define DEBUG_SMBIOS 0 +#endif + +#if DEBUG_SMBIOS +#define DBG(x...) printf(x) +#else +#define DBG(x...) msglog(x) +#endif + +#define SMBPlist &bootInfo->smbiosConfig +/* ASSUMPTION: 16KB should be enough for the whole thing */ +#define SMB_ALLOC_SIZE 16384 + + +//------------------------------------------------------------------------------------------------------------------------- +// SMBIOS Plist Keys +//------------------------------------------------------------------------------------------------------------------------- +/* BIOS Information */ +#define kSMBBIOSInformationVendorKey "SMbiosvendor" +#define kSMBBIOSInformationVersionKey "SMbiosversion" +#define kSMBBIOSInformationReleaseDateKey "SMbiosdate" + +/* System Information */ +#define kSMBSystemInformationManufacturerKey "SMmanufacturer" +#define kSMBSystemInformationProductNameKey "SMproductname" +#define kSMBSystemInformationVersionKey "SMsystemversion" +#define kSMBSystemInformationSerialNumberKey "SMserial" +#define kSMBSystemInformationFamilyKey "SMfamily" + +/* Base Board */ +#define kSMBBaseBoardManufacturerKey "SMboardmanufacturer" +#define kSMBBaseBoardProductKey "SMboardproduct" + +/* Processor Information */ +#define kSMBProcessorInformationExternalClockKey "SMexternalclock" +#define kSMBProcessorInformationMaximumClockKey "SMmaximalclock" + +/* Memory Device */ +#define kSMBMemoryDeviceDeviceLocatorKey "SMmemdevloc" +#define kSMBMemoryDeviceBankLocatorKey "SMmembankloc" +#define kSMBMemoryDeviceMemoryTypeKey "SMmemtype" +#define kSMBMemoryDeviceMemorySpeedKey "SMmemspeed" +#define kSMBMemoryDeviceManufacturerKey "SMmemmanufacturer" +#define kSMBMemoryDeviceSerialNumberKey "SMmemserial" +#define kSMBMemoryDevicePartNumberKey "SMmempart" + +/* Apple Specific */ +#define kSMBOemProcessorTypeKey "SMcputype" +#define kSMBOemProcessorBusSpeedKey "SMbusspeed" + +//------------------------------------------------------------------------------------------------------------------------- +// Default SMBIOS Data +//------------------------------------------------------------------------------------------------------------------------- +/* Rewrite: use a struct */ + +#define kDefaultVendorManufacturer "Apple Inc." +#define kDefaultBIOSReleaseDate "11/06/2009" +#define kDefaultSerialNumber "SOMESRLNMBR" +#define kDefaultBoardProduct "Mac-F4208DC8" +#define kDefaultSystemVersion "1.0" + +// defaults for a Mac mini +#define kDefaultMacminiFamily "Macmini" +#define kDefaultMacmini "Macmini2,1" +#define kDefaultMacminiBIOSVersion " MM21.88Z.009A.B00.0903051113" + +// defaults for a MacBook +#define kDefaultMacBookFamily "MacBook" +#define kDefaultMacBook "MacBook4,1" +#define kDefaultMacBookBIOSVersion " MB41.88Z.0073.B00.0903051113" + +// defaults for a MacBook Pro +#define kDefaultMacBookProFamily "MacBookPro" +#define kDefaultMacBookPro "MacBookPro4,1" +#define kDefaultMacBookProBIOSVersion " MBP41.88Z.0073.B00.0903051113" + +// defaults for an iMac +#define kDefaultiMacFamily "iMac" +#define kDefaultiMac "iMac8,1" +#define kDefaultiMacBIOSVersion " IM81.88Z.00C1.B00.0903051113" +// defaults for an iMac11,1 core i3/i5/i7 +#define kDefaultiMacNehalem "iMac11,1" +#define kDefaultiMacNehalemBIOSVersion " IM111.88Z.0034.B00.0903051113" + +// defaults for a Mac Pro +#define kDefaultMacProFamily "MacPro" +#define kDefaultMacPro "MacPro3,1" +#define kDefaultMacProBIOSVersion " MP31.88Z.006C.B05.0903051113" +// defaults for a Mac Pro 4,1 core i7/Xeon +#define kDefaultMacProNehalem "MacPro4,1" +#define kDefaultMacProNehalemBIOSVersion " MP41.88Z.0081.B04.0903051113" +// defaults for a Mac Pro 5,1 core i7/Xeon +#define kDefaultMacProWestmere "MacPro5,1" +#define kDefaultMacProWestmereBIOSVersion " MP51.88Z.007F.B00.1008031144" +#define kDefaulMacProWestmereBIOSReleaseDate "08/03/10" +//------------------------------------------------------------------------------------------------------------------------- + + +#define getFieldOffset(struct, field) ((uint8_t)(uint32_t)&(((struct *)0)->field)) + +typedef struct { + SMBStructHeader *orig; + SMBStructHeader *new; +} SMBStructPtrs; + +struct { + char *vendor; + char *version; + char *releaseDate; +} defaultBIOSInfo; + +struct { + char *manufacturer; + char *productName; + char *version; + char *serialNumber; + char *family; +} defaultSystemInfo; + +struct { + char *manufacturer; + char *product; +} defaultBaseBoard; + + +typedef struct { + uint8_t type; + SMBValueType valueType; + uint8_t fieldOffset; + char *keyString; + bool (*getSMBValue)(returnType *); + char **defaultValue; +} SMBValueSetter; + +SMBValueSetter SMBSetters[] = +{ + //------------------------------------------------------------------------------------------------------------------------- + // BIOSInformation + //------------------------------------------------------------------------------------------------------------------------- + {kSMBTypeBIOSInformation, kSMBString, getFieldOffset(SMBBIOSInformation, vendor), kSMBBIOSInformationVendorKey, + NULL, &defaultBIOSInfo.vendor }, + + {kSMBTypeBIOSInformation, kSMBString, getFieldOffset(SMBBIOSInformation, version), kSMBBIOSInformationVersionKey, + NULL, &defaultBIOSInfo.version }, + + {kSMBTypeBIOSInformation, kSMBString, getFieldOffset(SMBBIOSInformation, releaseDate), kSMBBIOSInformationReleaseDateKey, + NULL, &defaultBIOSInfo.releaseDate }, + + //------------------------------------------------------------------------------------------------------------------------- + // SystemInformation + //------------------------------------------------------------------------------------------------------------------------- + {kSMBTypeSystemInformation, kSMBString, getFieldOffset(SMBSystemInformation, manufacturer), kSMBSystemInformationManufacturerKey, + NULL, &defaultSystemInfo.manufacturer }, + + {kSMBTypeSystemInformation, kSMBString, getFieldOffset(SMBSystemInformation, productName), kSMBSystemInformationProductNameKey, + NULL, &defaultSystemInfo.productName }, + + {kSMBTypeSystemInformation, kSMBString, getFieldOffset(SMBSystemInformation, version), kSMBSystemInformationVersionKey, + NULL, &defaultSystemInfo.version }, + + {kSMBTypeSystemInformation, kSMBString, getFieldOffset(SMBSystemInformation, serialNumber), kSMBSystemInformationSerialNumberKey, + NULL, &defaultSystemInfo.serialNumber }, + + {kSMBTypeSystemInformation, kSMBString, getFieldOffset(SMBSystemInformation, skuNumber), NULL, + NULL, NULL }, + + {kSMBTypeSystemInformation, kSMBString, getFieldOffset(SMBSystemInformation, family), kSMBSystemInformationFamilyKey, + NULL, &defaultSystemInfo.family }, + + + //------------------------------------------------------------------------------------------------------------------------- + // BaseBoard + //------------------------------------------------------------------------------------------------------------------------- + {kSMBTypeBaseBoard, kSMBString, getFieldOffset(SMBBaseBoard, manufacturer), kSMBBaseBoardManufacturerKey, + NULL, &defaultBaseBoard.manufacturer }, + + {kSMBTypeBaseBoard, kSMBString, getFieldOffset(SMBBaseBoard, product), kSMBBaseBoardProductKey, + NULL, &defaultBaseBoard.product }, + + {kSMBTypeBaseBoard, kSMBString, getFieldOffset(SMBBaseBoard, version), NULL, NULL, NULL}, + + {kSMBTypeBaseBoard, kSMBString, getFieldOffset(SMBBaseBoard, serialNumber), NULL, NULL, NULL}, + + {kSMBTypeBaseBoard, kSMBString, getFieldOffset(SMBBaseBoard, assetTagNumber), NULL, NULL, NULL}, + + {kSMBTypeBaseBoard, kSMBString, getFieldOffset(SMBBaseBoard, locationInChassis), NULL, NULL, NULL}, + + + //------------------------------------------------------------------------------------------------------------------------- + // ProcessorInformation + //------------------------------------------------------------------------------------------------------------------------- + {kSMBTypeProcessorInformation, kSMBString, getFieldOffset(SMBProcessorInformation, socketDesignation), NULL, NULL, NULL}, + + {kSMBTypeProcessorInformation, kSMBString, getFieldOffset(SMBProcessorInformation, manufacturer), NULL, NULL, NULL}, + + {kSMBTypeProcessorInformation, kSMBString, getFieldOffset(SMBProcessorInformation, processorVersion), NULL, NULL, NULL}, + + {kSMBTypeProcessorInformation, kSMBWord, getFieldOffset(SMBProcessorInformation, externalClock), kSMBProcessorInformationExternalClockKey, + getProcessorInformationExternalClock, NULL}, + + {kSMBTypeProcessorInformation, kSMBWord, getFieldOffset(SMBProcessorInformation, maximumClock), kSMBProcessorInformationMaximumClockKey, + getProcessorInformationMaximumClock, NULL}, + + {kSMBTypeProcessorInformation, kSMBString, getFieldOffset(SMBProcessorInformation, serialNumber), NULL, NULL, NULL}, + + {kSMBTypeProcessorInformation, kSMBString, getFieldOffset(SMBProcessorInformation, assetTag), NULL, NULL, NULL}, + + {kSMBTypeProcessorInformation, kSMBString, getFieldOffset(SMBProcessorInformation, partNumber), NULL, NULL, NULL}, + + //------------------------------------------------------------------------------------------------------------------------- + // Memory Device + //------------------------------------------------------------------------------------------------------------------------- + {kSMBTypeMemoryDevice, kSMBString, getFieldOffset(SMBMemoryDevice, deviceLocator), kSMBMemoryDeviceDeviceLocatorKey, + NULL, NULL}, + + {kSMBTypeMemoryDevice, kSMBString, getFieldOffset(SMBMemoryDevice, bankLocator), kSMBMemoryDeviceBankLocatorKey, + NULL, NULL}, + + {kSMBTypeMemoryDevice, kSMBByte, getFieldOffset(SMBMemoryDevice, memoryType), kSMBMemoryDeviceMemoryTypeKey, + getSMBMemoryDeviceMemoryType, NULL}, + + {kSMBTypeMemoryDevice, kSMBWord, getFieldOffset(SMBMemoryDevice, memorySpeed), kSMBMemoryDeviceMemorySpeedKey, + getSMBMemoryDeviceMemorySpeed, NULL}, + + {kSMBTypeMemoryDevice, kSMBString, getFieldOffset(SMBMemoryDevice, manufacturer), kSMBMemoryDeviceManufacturerKey, + getSMBMemoryDeviceManufacturer, NULL}, + + {kSMBTypeMemoryDevice, kSMBString, getFieldOffset(SMBMemoryDevice, serialNumber), kSMBMemoryDeviceSerialNumberKey, + getSMBMemoryDeviceSerialNumber, NULL}, + + {kSMBTypeMemoryDevice, kSMBString, getFieldOffset(SMBMemoryDevice, assetTag), NULL, NULL, NULL}, + + {kSMBTypeMemoryDevice, kSMBString, getFieldOffset(SMBMemoryDevice, partNumber), kSMBMemoryDevicePartNumberKey, + getSMBMemoryDevicePartNumber, NULL}, + + + //------------------------------------------------------------------------------------------------------------------------- + // Apple Specific + //------------------------------------------------------------------------------------------------------------------------- + {kSMBTypeOemProcessorType, kSMBWord, getFieldOffset(SMBOemProcessorType, ProcessorType), kSMBOemProcessorTypeKey, + getSMBOemProcessorType, NULL}, + + {kSMBTypeOemProcessorBusSpeed, kSMBWord, getFieldOffset(SMBOemProcessorBusSpeed, ProcessorBusSpeed), kSMBOemProcessorBusSpeedKey, + getSMBOemProcessorBusSpeed, NULL} +}; + +int numOfSetters = sizeof(SMBSetters) / sizeof(SMBValueSetter); + + +SMBEntryPoint *origeps = 0; +SMBEntryPoint *neweps = 0; + +static uint8_t stringIndex; // increament when a string is added and set the field value accordingly +static uint8_t stringsSize; // add string size + +static SMBWord tableLength = 0; +static SMBWord handle = 0; +static SMBWord maxStructSize = 0; +static SMBWord structureCount = 0; + +/* Rewrite this function */ +void setDefaultSMBData(void) +{ + defaultBIOSInfo.vendor = kDefaultVendorManufacturer; + defaultBIOSInfo.releaseDate = kDefaultBIOSReleaseDate; + + defaultSystemInfo.manufacturer = kDefaultVendorManufacturer; + defaultSystemInfo.version = kDefaultSystemVersion; + defaultSystemInfo.serialNumber = kDefaultSerialNumber; + + defaultBaseBoard.manufacturer = kDefaultVendorManufacturer; + defaultBaseBoard.product = kDefaultBoardProduct; + + if (platformCPUFeature(CPU_FEATURE_MOBILE)) + { + if (Platform.CPU.NoCores > 1) + { + defaultBIOSInfo.version = kDefaultMacBookProBIOSVersion; + defaultSystemInfo.productName = kDefaultMacBookPro; + defaultSystemInfo.family = kDefaultMacBookProFamily; + } + else + { + defaultBIOSInfo.version = kDefaultMacBookBIOSVersion; + defaultSystemInfo.productName = kDefaultMacBook; + defaultSystemInfo.family = kDefaultMacBookFamily; + } + } + else + { + switch (Platform.CPU.NoCores) + { + case 1: + defaultBIOSInfo.version = kDefaultMacminiBIOSVersion; + defaultSystemInfo.productName = kDefaultMacmini; + defaultSystemInfo.family = kDefaultMacminiFamily; + break; + + case 2: + defaultBIOSInfo.version = kDefaultiMacBIOSVersion; + defaultSystemInfo.productName = kDefaultiMac; + defaultSystemInfo.family = kDefaultiMacFamily; + break; + default: + { + switch (Platform.CPU.Family) + { + case 0x06: + { + switch (Platform.CPU.Model) + { + case CPU_MODEL_FIELDS: // Intel Core i5, i7 LGA1156 (45nm) + case CPU_MODEL_DALES: // Intel Core i5, i7 LGA1156 (45nm) ??? + case CPU_MODEL_DALES_32NM: // Intel Core i3, i5, i7 LGA1156 (32nm) (Clarkdale, Arrandale) + case 0x19: // Intel Core i5 650 @3.20 Ghz + defaultBIOSInfo.version = kDefaultiMacNehalemBIOSVersion; + defaultSystemInfo.productName = kDefaultiMacNehalem; + defaultSystemInfo.family = kDefaultiMacFamily; + break; + + case CPU_MODEL_NEHALEM: + case CPU_MODEL_NEHALEM_EX: + defaultBIOSInfo.version = kDefaultMacProNehalemBIOSVersion; + defaultSystemInfo.productName = kDefaultMacProNehalem; + defaultSystemInfo.family = kDefaultMacProFamily; + break; + + case CPU_MODEL_WESTMERE: + case CPU_MODEL_WESTMERE_EX: + defaultBIOSInfo.version = kDefaultMacProWestmereBIOSVersion; + defaultBIOSInfo.releaseDate = kDefaulMacProWestmereBIOSReleaseDate; + defaultSystemInfo.productName = kDefaultMacProWestmere; + defaultSystemInfo.family = kDefaultMacProFamily; + break; + + default: + defaultBIOSInfo.version = kDefaultMacProBIOSVersion; + defaultSystemInfo.productName = kDefaultMacPro; + defaultSystemInfo.family = kDefaultMacProFamily; + break; + } + break; + } + default: + defaultBIOSInfo.version = kDefaultMacProBIOSVersion; + defaultSystemInfo.productName = kDefaultMacPro; + defaultSystemInfo.family = kDefaultMacProFamily; + break; + } + break; + } + } + } +} + +/* Used for SM*_N smbios.plist keys */ +bool getSMBValueForKey(SMBStructHeader *structHeader, const char *keyString, const char **string, returnType *value) +{ + static int idx = -1; + static int current = -1; + int len; + char key[24]; + + if (current != structHeader->handle) + { + idx++; + current = structHeader->handle; + } + + sprintf(key, "%s%d", keyString, idx); + + if (value) + if (getIntForKey(key, (int *)&(value->dword), SMBPlist)) + return true; + else + if (getValueForKey(key, string, &len, SMBPlist)) + return true; + return false; +} + +char *getSMBStringForField(SMBStructHeader *structHeader, uint8_t field) +{ + uint8_t *stringPtr = (uint8_t *)structHeader + structHeader->length; + + if (!field) + return (char *)0; + + for (field--; field != 0 && strlen((char *)stringPtr) > 0; + field--, stringPtr = (uint8_t *)((uint32_t)stringPtr + strlen((char *)stringPtr) + 1)); + + return (char *)stringPtr; +} + +void setSMBStringForField(SMBStructHeader *structHeader, const char *string, uint8_t *field) +{ + int strSize; + + if (!field) + return; + if (!string) + { + *field = 0; + return; + } + + strSize = strlen(string); + + // remove any spaces found at the end + while (string[strSize - 1] == ' ') + strSize--; + + memcpy((uint8_t *)structHeader + structHeader->length + stringsSize, string, strSize); + *field = stringIndex; + + stringIndex++; + stringsSize += strSize + 1; +} + +bool setSMBValue(SMBStructPtrs *structPtr, int idx, returnType *value) +{ + const char *string = 0; + int len; + + if (numOfSetters <= idx) + return false; + + switch (SMBSetters[idx].valueType) + { + case kSMBString: + if (SMBSetters[idx].keyString) + { + if (getValueForKey(SMBSetters[idx].keyString, &string, &len, SMBPlist)) + break; + else + if (structPtr->orig->type == kSMBTypeMemoryDevice) // MemoryDevice only + if (getSMBValueForKey(structPtr->orig, SMBSetters[idx].keyString, &string, NULL)) + break; + } + if (SMBSetters[idx].getSMBValue) + if (SMBSetters[idx].getSMBValue((returnType *)&string)) + break; + if ((SMBSetters[idx].defaultValue) && *(SMBSetters[idx].defaultValue)) + { + string = *(SMBSetters[idx].defaultValue); + break; + } + string = getSMBStringForField(structPtr->orig, *(uint8_t *)value); + break; + + case kSMBByte: + case kSMBWord: + case kSMBDWord: + //case kSMBQWord: + if (SMBSetters[idx].keyString) + { + if (getIntForKey(SMBSetters[idx].keyString, (int *)&(value->dword), SMBPlist)) + return true; + else + if (structPtr->orig->type == kSMBTypeMemoryDevice) // MemoryDevice only + if (getSMBValueForKey(structPtr->orig, SMBSetters[idx].keyString, NULL, value)) + return true; + } + if (SMBSetters[idx].getSMBValue) + if (SMBSetters[idx].getSMBValue(value)) + return true; +#if 0 + if (*(SMBSetters[idx].defaultValue)) + { + value->dword = *(uint32_t *)(SMBSetters[idx].defaultValue); + return true; + } +#endif + break; + } + + if (SMBSetters[idx].valueType == kSMBString && string) + setSMBStringForField(structPtr->new, string, &value->byte); + + return true; +} + +//------------------------------------------------------------------------------------------------------------------------- +// Apple Specific +//------------------------------------------------------------------------------------------------------------------------- +void addSMBFirmwareVolume(SMBStructPtrs *structPtr) +{ + return; +} + +void addSMBMemorySPD(SMBStructPtrs *structPtr) +{ + /* SPD data from Platform.RAM.spd */ + return; +} + +void addSMBOemProcessorType(SMBStructPtrs *structPtr) +{ + SMBOemProcessorType *p = (SMBOemProcessorType *)structPtr->new; + + p->header.type = kSMBTypeOemProcessorType; + p->header.length = sizeof(SMBOemProcessorType); + p->header.handle = handle++; + + setSMBValue(structPtr, numOfSetters - 2 , (returnType *)&(p->ProcessorType)); + + structPtr->new = (SMBStructHeader *)((uint8_t *)structPtr->new + sizeof(SMBOemProcessorType) + 2); + tableLength += sizeof(SMBOemProcessorType) + 2; + structureCount++; +} + +void addSMBOemProcessorBusSpeed(SMBStructPtrs *structPtr) +{ + SMBOemProcessorBusSpeed *p = (SMBOemProcessorBusSpeed *)structPtr->new; + + p->header.type = kSMBTypeOemProcessorBusSpeed; + p->header.length = sizeof(SMBOemProcessorBusSpeed); + p->header.handle = handle++; + + setSMBValue(structPtr, numOfSetters -1, (returnType *)&(p->ProcessorBusSpeed)); + + structPtr->new = (SMBStructHeader *)((uint8_t *)structPtr->new + sizeof(SMBOemProcessorBusSpeed) + 2); + tableLength += sizeof(SMBOemProcessorBusSpeed) + 2; + structureCount++; +} + +//------------------------------------------------------------------------------------------------------------------------- +// EndOfTable +//------------------------------------------------------------------------------------------------------------------------- +void addSMBEndOfTable(SMBStructPtrs *structPtr) +{ + structPtr->new->type = kSMBTypeEndOfTable; + structPtr->new->length = sizeof(SMBStructHeader); + structPtr->new->handle = handle++; + + structPtr->new = (SMBStructHeader *)((uint8_t *)structPtr->new + sizeof(SMBStructHeader) + 2); + tableLength += sizeof(SMBStructHeader) + 2; + structureCount++; +} + +void setSMBStruct(SMBStructPtrs *structPtr) +{ + bool setterFound = false; + + uint8_t *ptr; + SMBWord structSize; + int i; + + stringIndex = 1; + stringsSize = 0; + + if (handle < structPtr->orig->handle) + handle = structPtr->orig->handle; + + memcpy((void *)structPtr->new, structPtr->orig, structPtr->orig->length); + + for (i = 0; i < numOfSetters; i++) + if (structPtr->orig->type == SMBSetters[i].type) + { + setterFound = true; + setSMBValue(structPtr, i, (returnType *)((uint8_t *)structPtr->new + SMBSetters[i].fieldOffset)); + } + + if (setterFound) + { + ptr = (uint8_t *)structPtr->new + structPtr->orig->length; + for (; ((uint16_t *)ptr)[0] != 0; ptr++); + + if (((uint16_t *)ptr)[0] == 0) + ptr += 2; + + structSize = ptr - (uint8_t *)structPtr->new; + } + else + { + ptr = (uint8_t *)structPtr->orig + structPtr->orig->length; + for (; ((uint16_t *)ptr)[0] != 0; ptr++); + + if (((uint16_t *)ptr)[0] == 0) + ptr += 2; + + structSize = ptr - (uint8_t *)structPtr->orig; + memcpy((void *)structPtr->new, structPtr->orig, structSize); + } + + structPtr->new = (SMBStructHeader *)((uint8_t *)structPtr->new + structSize); + + tableLength += structSize; + + if (structSize > maxStructSize) + maxStructSize = structSize; + + structureCount++; +} + +void setupNewSMBIOSTable(SMBEntryPoint *eps, SMBStructPtrs *structPtr) +{ + uint8_t *ptr = (uint8_t *)eps->dmi.tableAddress; + structPtr->orig = (SMBStructHeader *)ptr; + + for (;((eps->dmi.tableAddress + eps->dmi.tableLength) > ((uint32_t)(uint8_t *)structPtr->orig + sizeof(SMBStructHeader)));) + { + switch (structPtr->orig->type) + { + /* Skip all Apple Specific Structures */ + case kSMBTypeFirmwareVolume: + case kSMBTypeMemorySPD: + case kSMBTypeOemProcessorType: + case kSMBTypeOemProcessorBusSpeed: + /* And this one too, to be added at the end */ + case kSMBTypeEndOfTable: + break; + + default: + /* Add */ + setSMBStruct(structPtr); + break; + } + + ptr = (uint8_t *)((uint32_t)structPtr->orig + structPtr->orig->length); + for (; ((uint16_t *)ptr)[0] != 0; ptr++); + + if (((uint16_t *)ptr)[0] == 0) + ptr += 2; + + structPtr->orig = (SMBStructHeader *)ptr; + } + + addSMBFirmwareVolume(structPtr); + addSMBMemorySPD(structPtr); + addSMBOemProcessorType(structPtr); + addSMBOemProcessorBusSpeed(structPtr); + + addSMBEndOfTable(structPtr); +} + +void setupSMBIOSTable(void) +{ + SMBStructPtrs *structPtr; + uint8_t *buffer; + bool setSMB = true; + + if (!origeps) + return; + + neweps = origeps; + + structPtr = (SMBStructPtrs *)malloc(sizeof(SMBStructPtrs)); + if (!structPtr) + return; + + buffer = malloc(SMB_ALLOC_SIZE); + if (!buffer) + return; + + bzero(buffer, SMB_ALLOC_SIZE); + structPtr->new = (SMBStructHeader *)buffer; + + getBoolForKey(kSMBIOSdefaults, &setSMB, &bootInfo->bootConfig); + if (setSMB) + setDefaultSMBData(); + + setupNewSMBIOSTable(origeps, structPtr); + + neweps = (SMBEntryPoint *)AllocateKernelMemory(sizeof(SMBEntryPoint)); + if (!neweps) + return; + bzero(neweps, sizeof(SMBEntryPoint)); + + neweps->anchor[0] = '_'; + neweps->anchor[1] = 'S'; + neweps->anchor[2] = 'M'; + neweps->anchor[3] = '_'; + neweps->entryPointLength = sizeof(SMBEntryPoint); + neweps->majorVersion = 2; + neweps->minorVersion = 4; + neweps->maxStructureSize = maxStructSize; + neweps->entryPointRevision = 0; + + neweps->dmi.anchor[0] = '_'; + neweps->dmi.anchor[1] = 'D'; + neweps->dmi.anchor[2] = 'M'; + neweps->dmi.anchor[3] = 'I'; + neweps->dmi.anchor[4] = '_'; + neweps->dmi.tableLength = tableLength; + neweps->dmi.tableAddress = AllocateKernelMemory(tableLength); + neweps->dmi.structureCount = structureCount; + neweps->dmi.bcdRevision = 0x24; + + if (!neweps->dmi.tableAddress) + return; + + memcpy((void *)neweps->dmi.tableAddress, buffer, tableLength); + + neweps->dmi.checksum = 0; + neweps->dmi.checksum = 0x100 - checksum8(&neweps->dmi, sizeof(DMIEntryPoint)); + + neweps->checksum = 0; + neweps->checksum = 0x100 - checksum8(neweps, sizeof(SMBEntryPoint)); + + free(buffer); + decodeSMBIOSTable(neweps); +} + +void *getSmbios(int which) +{ + switch (which) + { + case SMBIOS_ORIGINAL: + if (!origeps) + origeps = getAddressOfSmbiosTable(); + return origeps; + case SMBIOS_PATCHED: + return neweps; + } + + return 0; +} + +/* Collect any information needed later */ +void readSMBIOSInfo(SMBEntryPoint *eps) +{ + uint8_t *structPtr = (uint8_t *)eps->dmi.tableAddress; + SMBStructHeader *structHeader = (SMBStructHeader *)structPtr; + + int dimmnbr = 0; + Platform.DMI.MaxMemorySlots = 0; + Platform.DMI.CntMemorySlots = 0; + Platform.DMI.MemoryModules = 0; + + for (;((eps->dmi.tableAddress + eps->dmi.tableLength) > ((uint32_t)(uint8_t *)structHeader + sizeof(SMBStructHeader)));) + { + switch (structHeader->type) + { + case kSMBTypeSystemInformation: + Platform.UUID = ((SMBSystemInformation *)structHeader)->uuid; + break; + + case kSMBTypePhysicalMemoryArray: + Platform.DMI.MaxMemorySlots += ((SMBPhysicalMemoryArray *)structHeader)->numMemoryDevices; + break; + + case kSMBTypeMemoryDevice: + Platform.DMI.CntMemorySlots++; + if (((SMBMemoryDevice *)structHeader)->memorySize != 0) + Platform.DMI.MemoryModules++; + if (((SMBMemoryDevice *)structHeader)->memorySpeed > 0) + Platform.RAM.DIMM[dimmnbr].Frequency = ((SMBMemoryDevice *)structHeader)->memorySpeed; + dimmnbr++; + break; + } + + structPtr = (uint8_t *)((uint32_t)structHeader + structHeader->length); + for (; ((uint16_t *)structPtr)[0] != 0; structPtr++); + + if (((uint16_t *)structPtr)[0] == 0) + structPtr += 2; + + structHeader = (SMBStructHeader *)structPtr; + } +} + Index: trunk/i386/libsaio/smbios_decode.c =================================================================== --- trunk/i386/libsaio/smbios_decode.c (revision 0) +++ trunk/i386/libsaio/smbios_decode.c (revision 782) @@ -0,0 +1,232 @@ +/* + * A very simple SMBIOS Table decoder, part of the Chameleon Boot Loader Project + * + * Copyright 2010 by Islam M. Ahmed Zaid. All rights reserved. + * + */ + +#include "libsaio.h" +#include "smbios.h" + +#ifndef DEBUG_SMBIOS +#define DEBUG_SMBIOS 0 +#endif + +#if DEBUG_SMBIOS +#define DBG(x...) printf(x) +#else +#define DBG(x...) msglog(x) +#endif + + +static SMBWord minorVersion; + +extern char *getSMBStringForField(SMBStructHeader *structHeader, uint8_t field); + +//------------------------------------------------------------------------------------------------------------------------- +// BIOSInformation +//------------------------------------------------------------------------------------------------------------------------- +void decodeBIOSInformation(SMBBIOSInformation *structHeader) +{ + DBG("BIOSInformation:\n"); + DBG("\tvendor: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->vendor)); + DBG("\tversion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->version)); + DBG("\treleaseDate: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->releaseDate)); + DBG("\n"); +} + +//------------------------------------------------------------------------------------------------------------------------- +// SystemInformation +//------------------------------------------------------------------------------------------------------------------------- +void decodeSystemInformation(SMBSystemInformation *structHeader) +{ + DBG("SystemInformation:\n"); + DBG("\tmanufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer)); + DBG("\tproductName: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->productName)); + DBG("\tversion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->version)); + DBG("\tserialNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber)); + + if (minorVersion < 1 || structHeader->header.length < 25) + return; + uint8_t *uuid = structHeader->uuid; + DBG("\tuuid: %02X%02X%02X%02X-%02X%02X-%02X%02X-%02x%02X-%02X%02X%02X%02X%02X%02X\n", + uuid[0], uuid[1], uuid[2], uuid[3], + uuid[4], uuid[5], + uuid[6], uuid[7], + uuid[8], uuid[9], + uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]); + DBG("\twakeupReason: 0x%x\n", structHeader->wakeupReason); + + if (minorVersion < 4 || structHeader->header.length < 27) + return; + DBG("\tskuNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->skuNumber)); + DBG("\tfamily: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->family)); + DBG("\n"); +} + +//------------------------------------------------------------------------------------------------------------------------- +// BaseBoard +//------------------------------------------------------------------------------------------------------------------------- +void decodeBaseBoard(SMBBaseBoard *structHeader) +{ + DBG("BaseBoard:\n"); + DBG("\tmanufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer)); + DBG("\tproduct: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->product)); + DBG("\tversion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->version)); + DBG("\tserialNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber)); + DBG("\tassetTagNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->assetTagNumber)); + DBG("\tlocationInChassis: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->locationInChassis)); + DBG("\tboardType: 0x%X\n", structHeader->boardType); + DBG("\n"); +} + +//------------------------------------------------------------------------------------------------------------------------- +// SystemEnclosure +//------------------------------------------------------------------------------------------------------------------------- +void decodeSystemEnclosure(SMBSystemEnclosure *structHeader) +{ + DBG("SystemEnclosure:\n"); + DBG("\tmanufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer)); + DBG("\ttype: %d\n", structHeader->type); + DBG("\tversion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->version)); + DBG("\tserialNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber)); + DBG("\tassetTagNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->assetTagNumber)); + DBG("\n"); +} + +//------------------------------------------------------------------------------------------------------------------------- +// ProcessorInformation +//------------------------------------------------------------------------------------------------------------------------- +void decodeProcessorInformation(SMBProcessorInformation *structHeader) +{ + DBG("ProcessorInformation:\n"); + DBG("\tsocketDesignation: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->socketDesignation)); + DBG("\tprocessorType: %d\n", structHeader->processorType); + DBG("\tprocessorFamily: 0x%X\n", structHeader->processorFamily); + DBG("\tmanufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer)); + DBG("\tprocessorID: 0x%llX\n", structHeader->processorID); + DBG("\tprocessorVersion: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->processorVersion)); + DBG("\texternalClock: %dMHz\n", structHeader->externalClock); + DBG("\tmaximumClock: %dMHz\n", structHeader->maximumClock); + DBG("\tcurrentClock: %dMHz\n", structHeader->currentClock); + + if (minorVersion < 3 || structHeader->header.length < 35) + return; + DBG("\tserialNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber)); + DBG("\tassetTag: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->assetTag)); + DBG("\tpartNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->partNumber)); + DBG("\n"); +} + +//------------------------------------------------------------------------------------------------------------------------- +// MemoryDevice +//------------------------------------------------------------------------------------------------------------------------- +void decodeMemoryDevice(SMBMemoryDevice *structHeader) +{ + DBG("MemoryDevice:\n"); + DBG("\tdeviceLocator: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->deviceLocator)); + DBG("\tbankLocator: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->bankLocator)); + DBG("\tmemoryType: %s\n", SMBMemoryDeviceTypes[structHeader->memoryType]); + + if (minorVersion < 3 || structHeader->header.length < 27) + return; + DBG("\tmemorySpeed: %dMHz\n", structHeader->memorySpeed); + DBG("\tmanufacturer: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->manufacturer)); + DBG("\tserialNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->serialNumber)); + DBG("\tassetTag: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->assetTag)); + DBG("\tpartNumber: %s\n", getSMBStringForField((SMBStructHeader *)structHeader, structHeader->partNumber)); + DBG("\n"); +} + +//------------------------------------------------------------------------------------------------------------------------- +// Apple Specific +//------------------------------------------------------------------------------------------------------------------------- +void decodeOemProcessorType(SMBOemProcessorType *structHeader) +{ + DBG("AppleProcessorType:\n"); + DBG("\tProcessorType: 0x%x\n", ((SMBOemProcessorType *)structHeader)->ProcessorType); + DBG("\n"); +} + +void decodeOemProcessorBusSpeed(SMBOemProcessorBusSpeed *structHeader) +{ + DBG("AppleProcessorBusSpeed:\n"); + DBG("\tProcessorBusSpeed (QPI): %d.%dGT/s\n", + ((SMBOemProcessorBusSpeed *)structHeader)->ProcessorBusSpeed / 1000, + (((SMBOemProcessorBusSpeed *)structHeader)->ProcessorBusSpeed / 100) % 10); + DBG("\n"); +} +//------------------------------------------------------------------------------------------------------------------------- + + +void decodeSMBIOSTable(SMBEntryPoint *eps) +{ + uint8_t *ptr = (uint8_t *)eps->dmi.tableAddress; + SMBStructHeader *structHeader = (SMBStructHeader *)ptr; + + minorVersion = eps->minorVersion; + + DBG("\n"); + for (;((eps->dmi.tableAddress + eps->dmi.tableLength) > ((uint32_t)(uint8_t *)structHeader + sizeof(SMBStructHeader)));) + { + DBG("Type: %d, Length: %d, Handle: 0x%x\n", + structHeader->type, structHeader->length, structHeader->handle); + + switch (structHeader->type) + { + case kSMBTypeBIOSInformation: + decodeBIOSInformation((SMBBIOSInformation *)structHeader); + break; + + case kSMBTypeSystemInformation: + decodeSystemInformation((SMBSystemInformation *)structHeader); + break; + + case kSMBTypeBaseBoard: + decodeBaseBoard((SMBBaseBoard *)structHeader); + break; + + case kSMBTypeSystemEnclosure: + decodeSystemEnclosure((SMBSystemEnclosure *)structHeader); + break; + + case kSMBTypeProcessorInformation: + decodeProcessorInformation((SMBProcessorInformation *)structHeader); + break; + + case kSMBTypeMemoryDevice: + decodeMemoryDevice((SMBMemoryDevice *)structHeader); + break; + + /* Skip all Apple Specific Structures */ + case kSMBTypeFirmwareVolume: + case kSMBTypeMemorySPD: + break; + + case kSMBTypeOemProcessorType: + decodeOemProcessorType((SMBOemProcessorType *)structHeader); + break; + + case kSMBTypeOemProcessorBusSpeed: + decodeOemProcessorBusSpeed((SMBOemProcessorBusSpeed *)structHeader); + break; + + case kSMBTypeEndOfTable: + /* Skip, to be added at the end */ + break; + + default: + break; + } + + ptr = (uint8_t *)((uint32_t)structHeader + structHeader->length); + for (; ((uint16_t *)ptr)[0] != 0; ptr++); + + if (((uint16_t *)ptr)[0] == 0) + ptr += 2; + + structHeader = (SMBStructHeader *)ptr; + } + DBG("\n"); +} + Index: trunk/i386/libsaio/smbios_getters.c =================================================================== --- trunk/i386/libsaio/smbios_getters.c (revision 0) +++ trunk/i386/libsaio/smbios_getters.c (revision 782) @@ -0,0 +1,320 @@ +/* + * Add (c) here + * + * Copyright .... All rights reserved. + * + */ + +#include "smbios_getters.h" + +#ifndef DEBUG_SMBIOS +#define DEBUG_SMBIOS 0 +#endif + +#if DEBUG_SMBIOS +#define DBG(x...) printf(x) +#else +#define DBG(x...) +#endif + + +bool getProcessorInformationExternalClock(returnType *value) +{ + value->word = Platform.CPU.FSBFrequency/1000000; + return true; +} + +bool getProcessorInformationMaximumClock(returnType *value) +{ + value->word = Platform.CPU.CPUFrequency/1000000; + return true; +} + +bool getSMBOemProcessorBusSpeed(returnType *value) +{ + if (Platform.CPU.Vendor == 0x756E6547) // Intel + { + switch (Platform.CPU.Family) + { + case 0x06: + { + switch (Platform.CPU.Model) + { + case 0x0D: // ? + case CPU_MODEL_YONAH: // Yonah 0x0E + case CPU_MODEL_MEROM: // Merom 0x0F + case CPU_MODEL_PENRYN: // Penryn 0x17 + case CPU_MODEL_ATOM: // Atom 45nm 0x1C + return false; + + case 0x19: // Intel Core i5 650 @3.20 Ghz + case CPU_MODEL_NEHALEM: // Intel Core i7 LGA1366 (45nm) + case CPU_MODEL_FIELDS: // Intel Core i5, i7 LGA1156 (45nm) + case CPU_MODEL_DALES: // Intel Core i5, i7 LGA1156 (45nm) ??? + case CPU_MODEL_DALES_32NM: // Intel Core i3, i5, i7 LGA1156 (32nm) + case CPU_MODEL_WESTMERE: // Intel Core i7 LGA1366 (32nm) 6 Core + case CPU_MODEL_NEHALEM_EX: // Intel Core i7 LGA1366 (45nm) 6 Core ??? + case CPU_MODEL_WESTMERE_EX: // Intel Core i7 LGA1366 (45nm) 6 Core ??? + { + // thanks to dgobe for i3/i5/i7 bus speed detection + int nhm_bus = 0x3F; + static long possible_nhm_bus[] = {0xFF, 0x7F, 0x3F}; + unsigned long did, vid; + int i; + + // Nehalem supports Scrubbing + // First, locate the PCI bus where the MCH is located + for(i = 0; i < sizeof(possible_nhm_bus); i++) + { + vid = pci_config_read16(PCIADDR(possible_nhm_bus[i], 3, 4), 0x00); + did = pci_config_read16(PCIADDR(possible_nhm_bus[i], 3, 4), 0x02); + vid &= 0xFFFF; + did &= 0xFF00; + + if(vid == 0x8086 && did >= 0x2C00) + nhm_bus = possible_nhm_bus[i]; + } + + unsigned long qpimult, qpibusspeed; + qpimult = pci_config_read32(PCIADDR(nhm_bus, 2, 1), 0x50); + qpimult &= 0x7F; + DBG("qpimult %d\n", qpimult); + qpibusspeed = (qpimult * 2 * (Platform.CPU.FSBFrequency/1000000)); + // Rek: rounding decimals to match original mac profile info + if (qpibusspeed%100 != 0)qpibusspeed = ((qpibusspeed+50)/100)*100; + DBG("qpibusspeed %d\n", qpibusspeed); + value->word = qpibusspeed; + return true; + } + } + } + } + } + return false; +} + +uint16_t simpleGetSMBOemProcessorType(void) +{ + if (Platform.CPU.NoCores >= 4) + { + return 0x0501; // Quad-Core Xeon + } + else if (Platform.CPU.NoCores == 1) + { + return 0x0201; // Core Solo + }; + + return 0x0301; // Core 2 Duo +} + +bool getSMBOemProcessorType(returnType *value) +{ + static bool done = false; + + value->word = simpleGetSMBOemProcessorType(); + + if (Platform.CPU.Vendor == 0x756E6547) // Intel + { + if (!done) + { + verbose("CPU is %s, family 0x%x, model 0x%x\n", Platform.CPU.BrandString, Platform.CPU.Family, Platform.CPU.Model); + done = true; + } + + switch (Platform.CPU.Family) + { + case 0x06: + { + switch (Platform.CPU.Model) + { + case 0x0D: // ? + case CPU_MODEL_YONAH: // Yonah + case CPU_MODEL_MEROM: // Merom + case CPU_MODEL_PENRYN: // Penryn + case CPU_MODEL_ATOM: // Intel Atom (45nm) + return true; + + case CPU_MODEL_NEHALEM: // Intel Core i7 LGA1366 (45nm) + value->word = 0x0701; // Core i7 + return true; + + case CPU_MODEL_FIELDS: // Lynnfield, Clarksfield, Jasper + if (strstr(Platform.CPU.BrandString, "Core(TM) i5")) + value->word = 0x601; // Core i5 + else + value->word = 0x701; // Core i7 + return true; + + case CPU_MODEL_DALES: // Intel Core i5, i7 LGA1156 (45nm) (Havendale, Auburndale) + if (strstr(Platform.CPU.BrandString, "Core(TM) i5")) + value->word = 0x601; // Core i5 + else + value->word = 0x0701; // Core i7 + return true; + + case CPU_MODEL_DALES_32NM: // Intel Core i3, i5, i7 LGA1156 (32nm) (Clarkdale, Arrandale) + if (strstr(Platform.CPU.BrandString, "Core(TM) i3")) + value->word = 0x901; // Core i3 + else + if (strstr(Platform.CPU.BrandString, "Core(TM) i5")) + value->word = 0x601; // Core i5 + else + value->word = 0x0701; // Core i7 + return true; + + case CPU_MODEL_WESTMERE: // Intel Core i7 LGA1366 (32nm) 6 Core (Gulftown, Westmere-EP, Westmere-WS) + case CPU_MODEL_WESTMERE_EX: // Intel Core i7 LGA1366 (45nm) 6 Core ??? + value->word = 0x0701; // Core i7 + return true; + + case 0x19: // Intel Core i5 650 @3.20 Ghz + value->word = 0x601; // Core i5 + return true; + } + } + } + } + + return false; +} + +bool getSMBMemoryDeviceMemoryType(returnType *value) +{ + static int idx = -1; + int map; + + idx++; + if (idx < MAX_RAM_SLOTS) + { + map = Platform.DMI.DIMM[idx]; + if (Platform.RAM.DIMM[map].InUse && Platform.RAM.DIMM[map].Type != 0) + { + DBG("RAM Detected Type = %d\n", Platform.RAM.DIMM[map].Type); + value->byte = Platform.RAM.DIMM[map].Type; + return true; + } + } + + return false; +// value->byte = SMB_MEM_TYPE_DDR2; +// return true; +} + +bool getSMBMemoryDeviceMemorySpeed(returnType *value) +{ + static int idx = -1; + int map; + + idx++; + if (idx < MAX_RAM_SLOTS) + { + map = Platform.DMI.DIMM[idx]; + if (Platform.RAM.DIMM[map].InUse && Platform.RAM.DIMM[map].Frequency != 0) + { + DBG("RAM Detected Freq = %d Mhz\n", Platform.RAM.DIMM[map].Frequency); + value->dword = Platform.RAM.DIMM[map].Frequency; + return true; + } + } + + return false; +// value->dword = 800; +// return true; +} + +bool getSMBMemoryDeviceManufacturer(returnType *value) +{ + static int idx = -1; + int map; + + idx++; + if (idx < MAX_RAM_SLOTS) + { + map = Platform.DMI.DIMM[idx]; + if (Platform.RAM.DIMM[map].InUse && strlen(Platform.RAM.DIMM[map].Vendor) > 0) + { + DBG("RAM Detected Vendor[%d]='%s'\n", idx, Platform.RAM.DIMM[map].Vendor); + value->string = Platform.RAM.DIMM[map].Vendor; + return true; + } + } + + return false; +// value->string = "N/A"; +// return true; +} + +bool getSMBMemoryDeviceSerialNumber(returnType *value) +{ + static int idx = -1; + int map; + + idx++; + if (idx < MAX_RAM_SLOTS) + { + map = Platform.DMI.DIMM[idx]; + if (Platform.RAM.DIMM[map].InUse && strlen(Platform.RAM.DIMM[map].SerialNo) > 0) + { + DBG("name = %s, map=%d, RAM Detected SerialNo[%d]='%s'\n", name ? name : "", + map, idx, Platform.RAM.DIMM[map].SerialNo); + value->string = Platform.RAM.DIMM[map].SerialNo; + return true; + } + } + + return false; +// value->string = "N/A"; +// return true; +} + +bool getSMBMemoryDevicePartNumber(returnType *value) +{ + static int idx = -1; + int map; + + idx++; + if (idx < MAX_RAM_SLOTS) + { + map = Platform.DMI.DIMM[idx]; + if (Platform.RAM.DIMM[map].InUse && strlen(Platform.RAM.DIMM[map].PartNo) > 0) + { + DBG("Ram Detected PartNo[%d]='%s'\n", idx, Platform.RAM.DIMM[map].PartNo); + value->string = Platform.RAM.DIMM[map].PartNo; + return true; + } + } + + return false; +// value->string = "N/A"; +// return true; +} + + +// getting smbios addr with fast compare ops, late checksum testing ... +#define COMPARE_DWORD(a,b) ( *((uint32_t *) a) == *((uint32_t *) b) ) +static const char * const SMTAG = "_SM_"; +static const char* const DMITAG = "_DMI_"; + +SMBEntryPoint *getAddressOfSmbiosTable(void) +{ + SMBEntryPoint *smbios; + /* + * The logic is to start at 0xf0000 and end at 0xfffff iterating 16 bytes at a time looking + * for the SMBIOS entry-point structure anchor (literal ASCII "_SM_"). + */ + smbios = (SMBEntryPoint*)SMBIOS_RANGE_START; + while (smbios <= (SMBEntryPoint *)SMBIOS_RANGE_END) { + if (COMPARE_DWORD(smbios->anchor, SMTAG) && + COMPARE_DWORD(smbios->dmi.anchor, DMITAG) && + smbios->dmi.anchor[4] == DMITAG[4] && + checksum8(smbios, sizeof(SMBEntryPoint)) == 0) + { + return smbios; + } + smbios = (SMBEntryPoint*)(((char*)smbios) + 16); + } + printf("ERROR: Unable to find SMBIOS!\n"); + pause(); + return NULL; +} +