Chameleon

Chameleon Commit Details

Date:2010-02-21 19:06:31 (10 years 1 day ago)
Author:Rekursor
Commit:103
Parents: 102
Message:Cleanup the spd code, added missing free() after spd malloc, cleanup char* string that are in fact const char*, added more constrained var typing (see smbios key,value parsing now). Added a new isacii() inline function that check if a char is between 0x20 and 0x7e.
Changes:
M/trunk/i386/libsaio/smbios_patcher.c
M/trunk/i386/libsaio/spd.c
M/trunk/i386/libsa/libsa.h
M/trunk/i386/libsaio/smbios_patcher.h
M/trunk/i386/libsaio/platform.h
M/trunk/i386/libsaio/spd.h

File differences

trunk/i386/libsaio/spd.c
6464
6565
6666
67
67
68
6869
6970
7071
......
131132
132133
133134
134
135
135
136
136137
137
138
139
140
138141
139
140
141
142
143
144
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
145167
146168
147
169
148170
149171
172
173
174
175
150176
151
177
152178
153
154
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
155194
156195
157196
158197
159198
160
199
161200
162201
163202
......
186225
187226
188227
189
190
228
191229
192230
193231
......
205243
206244
207245
208
246
247
248
249
209250
251
252
210253
211
212
213
254
255
256
257
258
259
214260
215
216
217
261
262
263
218264
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
265
266
267
268
269
270
271
234272
235273
236274
237275
238
239
240
241
242
243
244
245
246
247
276
277
278
279
248280
249281
250282
......
262294
263295
264296
297
265298
266299
267300
268301
269
302
303
304
305
306
307
308
270309
271310
272311
......
286325
287326
288327
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309328
310329
311330
#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;
#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
/** 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;
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
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[] = {
};
void scan_smbus_controller(pci_dt_t *smbus_dev)
{
inti;
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)
trunk/i386/libsaio/spd.h
1010
1111
1212
13
1413
1514
1615
#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 {
trunk/i386/libsaio/smbios_patcher.c
2121
2222
2323
24
25
26
27
2428
2529
26
30
2731
2832
2933
......
3842
3943
4044
41
45
4246
4347
4448
......
5357
5458
5559
56
60
5761
5862
5963
......
6872
6973
7074
71
75
7276
7377
7478
......
8387
8488
8589
86
90
8791
8892
8993
......
97101
98102
99103
100
104
101105
102106
103
107
104108
105109
106110
......
116120
117121
118122
119
120
121
123
124
125
122126
123127
124128
125129
126
130
127131
128132
129133
130134
131
135
132136
133137
134138
135139
136
140
137141
138142
139143
140144
141
145
142146
143147
144148
......
151155
152156
153157
154
158
155159
156160
157161
......
165169
166170
167171
168
172
169173
170174
171175
......
180184
181185
182186
183
187
184188
185189
186190
......
194198
195199
196200
197
201
198202
199203
200204
......
209213
210214
211215
212
216
213217
214218
215219
#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"},
};
// 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"},
};
// 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"},
};
// 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"},
};
// 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"},
{ "",""}
};
static char *sm_get_defstr(char *name, int table_num)
static const char* sm_get_defstr(const char * key, int table_num)
{
inti;
char(*sm_defaults)[2][40];
const SMStrEntryPair*sm_defaults;
if (platformCPUFeature(CPU_FEATURE_MOBILE)) {
if (Platform.CPU.NoCores > 1) {
}
}
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?
}
}
static int sm_get_memtype (char *name, int table_num)
static int sm_get_memtype (const char *name, int table_num)
{
intmap;
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)
{
intmap;
return 800;
}
static char *sm_get_memvendor (char *name, int table_num)
static const char *sm_get_memvendor (const char *name, int table_num)
{
intmap;
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)
{
intmap;
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)
{
intmap;
trunk/i386/libsaio/smbios_patcher.h
3030
3131
3232
33
33
3434
3535
3636
37
38
39
37
38
39
4040
4141
4242
struct smbios_property
{
char*name;
const char*name;
uint8_ttable_type;
enum {SMSTRING, SMWORD, SMBYTE, SMOWORD} value_type;
intoffset;
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
trunk/i386/libsaio/platform.h
7575
7676
7777
78
79
80
81
82
83
7884
7985
8086
8187
82
83
84
85
86
87
8888
8989
9090
#define UUID_LEN16
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
boolInUse;
uint8_tType;
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
charVendor[64];
charPartNo[64];
charSerialNo[16];
char*spd;// SPD Dump
} RamSlotInfo_t;
trunk/i386/libsa/libsa.h
5050
5151
5252
53
54
55
56
57
5358
5459
5560
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');

Archive Download the corresponding diff file

Revision: 103