Index: trunk/i386/libsaio/spd.c =================================================================== --- trunk/i386/libsaio/spd.c (revision 102) +++ trunk/i386/libsaio/spd.c (revision 103) @@ -64,7 +64,8 @@ #define SMBHSTADD 4 #define SMBHSTDAT 5 -/** Get Vendor Name from spd, 2 cases handled DDR3 and DDR2, have different formats.*/ +/** Get Vendor Name from spd, 2 cases handled DDR3 and DDR2, + have different formats, always return a valid ptr.*/ const char * getVendorName(RamSlotInfo_t* slot) { uint8_t bank = 0; @@ -131,33 +132,71 @@ #define UIS(a) ((uint32_t)spd[a]) -/** Get DDR3 or DDR2 serial number, 0 most of the times */ -uint32_t getDDRSerial(const char* spd) +/** Get DDR3 or DDR2 serial number, 0 most of the times, always return a valid ptr */ +const char *getDDRSerial(const char* spd) { - uint32_t ret=0; + static char asciiSerial[16]; + static uint8_t serialnum=0; + uint32_t ret=0,i; - if (spd[2]==0x0b) // DDR3 - // assume it is lsb to msb - ret = UIS(122) | (UIS(123)<<8) | (UIS(124)<<16) | (UIS(125)<<24); - else if (spd[2]==0x08 || spd[2]==0x07) // DDR2 or DDR - ret = UIS(95) | (UIS(96)<<8) | (UIS(97)<<16) | (UIS(98)<<24); - return ret; + if (spd[2]==0x0b) {// DDR3 + if ( isascii(spd[122]) && isascii(spd[123]) && + isascii(spd[124]) && isascii(spd[125]) ) { + for(i=0; i<4; i++) asciiSerial[i] = spd[122+i]; + asciiSerial[4] = 0; + return asciiSerial; + } + else // assume it is lsb to msb + ret = UIS(122) | (UIS(123)<<8) | (UIS(124)<<16) | ((UIS(125)&0x7f)<<24); + } + else if (spd[2]==0x08 || spd[2]==0x07) { // DDR2 or DDR + if ( isascii(spd[95]) && isascii(spd[96]) && + isascii(spd[97]) && isascii(spd[98]) ) { + for (i=0; i<4; i++) asciiSerial[i] = spd[95+i]; + asciiSerial[4] = 0; + return asciiSerial; + } + else + ret = UIS(95) | (UIS(96)<<8) | (UIS(97)<<16) | ((UIS(98)&0x7f)<<24); + } + + if (!ret) sprintf(asciiSerial, "10000000%d", serialnum++); + else sprintf(asciiSerial, "%d", ret); + + return asciiSerial; } -/** Get DDR3 or DDR2 Part Number */ +/** Get DDR3 or DDR2 Part Number, always return a valid ptr */ const char * getDDRPartNum(const char* spd) { + const char * sPart = NULL; + int i; + bool bZero = false; + if (spd[2]==0x0b) // DDR3 - return &spd[128]; + sPart = &spd[128]; else if (spd[2]==0x08 || spd[2]==0x07) // DDR2 or DDR - return &spd[73]; - return "N/A"; + sPart = &spd[73]; + if (sPart) { // Check that the spd part name is zero terminated and that it is ascii: + for (i=0; i<32; i++) { + if (sPart[i]==0) { + bZero = true; + break; + } + else if ( !isascii(sPart[i]) ) { + sPart = NULL; + break; + } + } + } + return ( sPart==NULL || !(*sPart) || !bZero ) ? + "N/A" : sPart; } /** Read one byte from the intel i2c, used for reading SPD on intel chipsets only. */ unsigned char smb_read_byte_intel(uint32_t base, uint8_t adr, uint8_t cmd) { - int l1, h1, l2, h2; + int l1, h1, l2, h2; unsigned long long t; outb(base + SMBHSTSTS, 0x1f); // reset SMBus Controller @@ -186,8 +225,7 @@ /** Read from smbus the SPD content and interpret it for detecting memory attributes */ static void read_smb_intel(pci_dt_t *smbus_dev) { - static int serialnum=0; - int i, x, ser, speed; + int i, x, speed; uint8_t spd_size, spd_type; uint32_t base; bool dump = false; @@ -205,46 +243,40 @@ spd_size = smb_read_byte_intel(base, 0x50 + i, 0); // Check spd is present - if (spd_size && spd_size != 0xff) { + if (spd_size && (spd_size != 0xff) ) { + slot->spd = malloc(spd_size); + if (slot->spd == NULL) continue; + slot->InUse = true; + + bzero(slot->spd, spd_size); - slot->spd = malloc(spd_size); - if (slot->spd) { - bzero(slot->spd, spd_size); + // Copy spd data into buffer + for (x = 0; x < spd_size; x++) + slot->spd[x] = smb_read_byte_intel(base, 0x50 + i, x); + + switch (slot->spd[SPD_MEMORY_TYPE]) { + case SPD_MEMORY_TYPE_SDRAM_DDR2: - // Copy spd data into buffer - for (x = 0; x < spd_size; x++) - slot->spd[x] = smb_read_byte_intel(base, 0x50 + i, x); + slot->ModuleSize = ((1 << (slot->spd[SPD_NUM_ROWS] & 0x0f) + (slot->spd[SPD_NUM_COLUMNS] & 0x0f) - 17) * + ((slot->spd[SPD_NUM_DIMM_BANKS] & 0x7) + 1) * slot->spd[SPD_NUM_BANKS_PER_SDRAM]); + break; - switch (slot->spd[SPD_MEMORY_TYPE]) { - case SPD_MEMORY_TYPE_SDRAM_DDR2: - - slot->ModuleSize = ((1 << (slot->spd[SPD_NUM_ROWS] & 0x0f) + (slot->spd[SPD_NUM_COLUMNS] & 0x0f) - 17) * - ((slot->spd[SPD_NUM_DIMM_BANKS] & 0x7) + 1) * slot->spd[SPD_NUM_BANKS_PER_SDRAM]); - break; - - case SPD_MEMORY_TYPE_SDRAM_DDR3: - - slot->ModuleSize = ((slot->spd[4] & 0x0f) + 28 ) + ((slot->spd[8] & 0x7) + 3 ); - slot->ModuleSize -= (slot->spd[7] & 0x7) + 25; - slot->ModuleSize = ((1 << slot->ModuleSize) * (((slot->spd[7] >> 3) & 0x1f) + 1)); - - break; - } + case SPD_MEMORY_TYPE_SDRAM_DDR3: + + slot->ModuleSize = ((slot->spd[4] & 0x0f) + 28 ) + ((slot->spd[8] & 0x7) + 3 ); + slot->ModuleSize -= (slot->spd[7] & 0x7) + 25; + slot->ModuleSize = ((1 << slot->ModuleSize) * (((slot->spd[7] >> 3) & 0x1f) + 1)); + + break; } spd_type = (slot->spd[SPD_MEMORY_TYPE] < ((char) 12) ? slot->spd[SPD_MEMORY_TYPE] : 0); slot->Type = spd_mem_to_smbios[spd_type]; - strncpy(slot->PartNo, getDDRPartNum(slot->spd), 64); - strncpy(slot->Vendor, getVendorName(slot), 64); - - ser = getDDRSerial(slot->spd); - if (ser==0) { - sprintf(slot->SerialNo, "10000000%d", serialnum); - serialnum++; - } - else - sprintf(slot->SerialNo, "%d", ser); + slot->PartNo = strdup(getDDRPartNum(slot->spd) ); + slot->Vendor = strdup(getVendorName(slot) ); + slot->SerialNo = strdup(getDDRSerial(slot->spd)); + // determine spd speed speed = getDDRspeedMhz(slot->spd); if (speed > slot->Frequency) slot->Frequency = speed; // just in case dmi wins on spd @@ -262,11 +294,18 @@ getc(); } } + // laptops sometimes show slot 0 and 2 with slot 1 empty when only 2 slots are presents so: Platform.DMI.DIMM[i]= i>0 && Platform.RAM.DIMM[1].InUse==false && fullBanks && Platform.DMI.MaxMemorySlots==2 ? mapping[i] : i; // for laptops case, mapping setup would need to be more generic than this - } + + if (slot->spd) { + free(slot->spd); + slot->spd = NULL; + } + + } // for } static struct smbus_controllers_t smbus_controllers[] = { @@ -286,26 +325,6 @@ }; -void scan_smbus_controller(pci_dt_t *smbus_dev) -{ - int i; - - for( i = 1; i < sizeof(smbus_controllers) / sizeof(smbus_controllers[0]); i++ ) - if (( smbus_controllers[i].vendor == smbus_dev->vendor_id) - && ( smbus_controllers[i].device == smbus_dev->device_id)) - { - verbose("%s%s SMBus Controller [%4x:%4x] at %02x:%02x.%x\n", - (smbus_dev->vendor_id == 0x8086) ? "Intel(R) " : "", - smbus_controllers[i].name, - smbus_dev->vendor_id, smbus_dev->device_id, - smbus_dev->dev.bits.bus, smbus_dev->dev.bits.dev, smbus_dev->dev.bits.func); - - smbus_controllers[i].read_smb(smbus_dev); - - } - -} - // initial call : pci_dt = root_pci_dev; // find_and_read_smbus_controller(root_pci_dev); bool find_and_read_smbus_controller(pci_dt_t* pci_dt) Index: trunk/i386/libsaio/spd.h =================================================================== --- trunk/i386/libsaio/spd.h (revision 102) +++ trunk/i386/libsaio/spd.h (revision 103) @@ -10,7 +10,6 @@ #include "platform.h" #include "libsaio.h" -void scan_smbus_controller(pci_dt_t *smbus_dev); void scan_spd(PlatformInfo_t *p); struct smbus_controllers_t { Index: trunk/i386/libsaio/smbios_patcher.c =================================================================== --- trunk/i386/libsaio/smbios_patcher.c (revision 102) +++ trunk/i386/libsaio/smbios_patcher.c (revision 103) @@ -21,9 +21,13 @@ #define DBG(x...) #endif +typedef struct { + const char* key; + const char* value; +} SMStrEntryPair; // defaults for a MacBook -static char sm_macbook_defaults[][2][40]={ +static const SMStrEntryPair const sm_macbook_defaults[]={ {"SMbiosvendor", "Apple Inc." }, {"SMbiosversion", "MB41.88Z.0073.B00.0809221748" }, {"SMbiosdate", "04/01/2008" }, @@ -38,7 +42,7 @@ }; // defaults for a MacBook Pro -static char sm_macbookpro_defaults[][2][40]={ +static const SMStrEntryPair const sm_macbookpro_defaults[]={ {"SMbiosvendor", "Apple Inc." }, {"SMbiosversion", "MBP41.88Z.0073.B00.0809221748" }, {"SMbiosdate", "04/01/2008" }, @@ -53,7 +57,7 @@ }; // defaults for a Mac mini -static char sm_macmini_defaults[][2][40]={ +static const SMStrEntryPair const sm_macmini_defaults[]={ {"SMbiosvendor", "Apple Inc." }, {"SMbiosversion", "MM21.88Z.009A.B00.0706281359" }, {"SMbiosdate", "04/01/2008" }, @@ -68,7 +72,7 @@ }; // defaults for an iMac -static char sm_imac_defaults[][2][40]={ +static const SMStrEntryPair const sm_imac_defaults[]={ {"SMbiosvendor", "Apple Inc." }, {"SMbiosversion", "IM81.88Z.00C1.B00.0802091538" }, {"SMbiosdate", "04/01/2008" }, @@ -83,7 +87,7 @@ }; // defaults for a Mac Pro -static char sm_macpro_defaults[][2][40]={ +static const SMStrEntryPair const sm_macpro_defaults[]={ {"SMbiosvendor", "Apple Computer, Inc." }, {"SMbiosversion", "MP31.88Z.006C.B05.0802291410" }, {"SMbiosdate", "04/01/2008" }, @@ -97,10 +101,10 @@ { "","" } }; -static char *sm_get_defstr(char *name, int table_num) +static const char* sm_get_defstr(const char * key, int table_num) { int i; - char (*sm_defaults)[2][40]; + const SMStrEntryPair* sm_defaults; if (platformCPUFeature(CPU_FEATURE_MOBILE)) { if (Platform.CPU.NoCores > 1) { @@ -116,29 +120,29 @@ } } - for (i=0;sm_defaults[i][0][0];i++) { - if (!strcmp (sm_defaults[i][0],name)) { - return sm_defaults[i][1]; + 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", name); + printf ("Error: no default for '%s' known\n", key); sleep (2); return ""; } -static int sm_get_fsb(char *name, int table_num) +static int sm_get_fsb(const char *name, int table_num) { return Platform.CPU.FSBFrequency/1000000; } -static int sm_get_cpu (char *name, int table_num) +static int sm_get_cpu (const char *name, int table_num) { return Platform.CPU.CPUFrequency/1000000; } -static int sm_get_cputype (char *name, int table_num) +static int sm_get_cputype (const char *name, int table_num) { if (Platform.CPU.NoCores == 1) { return 0x0101; // <01 01> Intel Core Solo? @@ -151,7 +155,7 @@ } } -static int sm_get_memtype (char *name, int table_num) +static int sm_get_memtype (const char *name, int table_num) { int map; @@ -165,7 +169,7 @@ return SMB_MEM_TYPE_DDR2; } -static int sm_get_memspeed (char *name, int table_num) +static int sm_get_memspeed (const char *name, int table_num) { int map; @@ -180,7 +184,7 @@ return 800; } -static char *sm_get_memvendor (char *name, int table_num) +static const char *sm_get_memvendor (const char *name, int table_num) { int map; @@ -194,7 +198,7 @@ return "N/A"; } -static char *sm_get_memserial (char *name, int table_num) +static const char *sm_get_memserial (const char *name, int table_num) { int map; @@ -209,7 +213,7 @@ return "N/A"; } -static char *sm_get_mempartno (char *name, int table_num) +static const char *sm_get_mempartno (const char *name, int table_num) { int map; Index: trunk/i386/libsaio/smbios_patcher.h =================================================================== --- trunk/i386/libsaio/smbios_patcher.h (revision 102) +++ trunk/i386/libsaio/smbios_patcher.h (revision 103) @@ -30,13 +30,13 @@ struct smbios_property { - char *name; + const char *name; uint8_t table_type; enum {SMSTRING, SMWORD, SMBYTE, SMOWORD} value_type; int offset; - int (*auto_int) (char *name, int table_num); - char *(*auto_str) (char *name, int table_num); - char *(*auto_oword) (char *name, int table_num); + 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 Index: trunk/i386/libsaio/platform.h =================================================================== --- trunk/i386/libsaio/platform.h (revision 102) +++ trunk/i386/libsaio/platform.h (revision 103) @@ -75,16 +75,16 @@ #define UUID_LEN 16 typedef struct _RamSlotInfo_t { + uint32_t ModuleSize; // Size of Module in MB + uint32_t Frequency; // in Mhz + const char* Vendor; + const char* PartNo; + const char* SerialNo; + char* spd; // SPD Dump bool InUse; uint8_t Type; uint8_t BankConnections; // table type 6, see (3.3.7) uint8_t BankConnCnt; - uint32_t ModuleSize; // Size of Module in MB - uint32_t Frequency; // in Mhz - char Vendor[64]; - char PartNo[64]; - char SerialNo[16]; - char *spd; // SPD Dump } RamSlotInfo_t; Index: trunk/i386/libsa/libsa.h =================================================================== --- trunk/i386/libsa/libsa.h (revision 102) +++ trunk/i386/libsa/libsa.h (revision 103) @@ -50,6 +50,11 @@ return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')); } +static inline int isascii(char c) +{ + return ( (c >= 0x20) && (c < 0x7f) ); +} + static inline int isspace(char c) { return (c == ' ' || c == '\t' || c == '\n' || c == '\12');