Chameleon

Chameleon Commit Details

Date:2010-02-19 05:50:32 (14 years 2 months ago)
Author:Rekursor
Commit:90
Parents: 89
Message:Implementation of dynamic memory detection, works great here with 2 modules of ddr3.
Changes:
M/trunk/i386/libsaio/smbios_patcher.c
M/trunk/i386/libsaio/spd.c
M/trunk/i386/libsaio/platform.h
M/trunk/version
M/trunk/i386/libsaio/spd.h
M/trunk/CHANGES
M/trunk/i386/libsaio/mem.c

File differences

trunk/version
1
1
2.0-RC5pre9
2.0-RC5pre10
trunk/CHANGES
1
12
23
34
- Implemented SPD memory automatic detection and injection,seems to work really great ...
- Factorized code to prepare a dynamic memory detection algorithm ...
- Optimized smbios table address search
- Optimized cursor spinout in textmode if no verbose mode is set
trunk/i386/libsaio/spd.c
11
2
3
4
2
3
54
65
76
87
98
109
10
11
1112
1213
1314
......
1920
2021
2122
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
22314
23315
24
316
25317
/*
* Copyright 2010 AsereBLN. All rights reserved. <aserebln@googlemail.com>
*
* spd.c - obtain serial presene detect memory information
* spd.c - serial presence detect memory information
* (restored from pcefi10.5)
*/
#include "libsaio.h"
#include "pci.h"
#include "platform.h"
#include "spd.h"
#include "saio_internal.h"
#include "bootstruct.h"
#ifndef DEBUG_SPD
#define DEBUG_SPD 0
#define DBG(x...)
#endif
static const char *spd_memory_types[] =
{
"RAM", /* 00h Undefined */
"FPM", /* 01h FPM */
"EDO", /* 02h EDO */
"",/* 03h PIPELINE NIBBLE */
"SDRAM", /* 04h SDRAM */
"",/* 05h MULTIPLEXED ROM */
"DDR SGRAM",/* 06h SGRAM DDR */
"DDR SDRAM",/* 07h SDRAM DDR */
"DDR2 SDRAM", /* 08h SDRAM DDR 2 */
"",/* 09h Undefined */
"",/* 0Ah Undefined */
"DDR3 SDRAM" /* 0Bh SDRAM DDR 3 */
};
#define UNKNOWN_MEM_TYPE 2
static uint8_t spd_mem_to_smbios[] =
{
UNKNOWN_MEM_TYPE, /* 00h Undefined */
UNKNOWN_MEM_TYPE, /* 01h FPM */
UNKNOWN_MEM_TYPE, /* 02h EDO */
UNKNOWN_MEM_TYPE, /* 03h PIPELINE NIBBLE */
SMB_MEM_TYPE_SDRAM, /* 04h SDRAM */
SMB_MEM_TYPE_ROM, /* 05h MULTIPLEXED ROM */
SMB_MEM_TYPE_SGRAM, /* 06h SGRAM DDR */
SMB_MEM_TYPE_DDR, /* 07h SDRAM DDR */
SMB_MEM_TYPE_DDR2, /* 08h SDRAM DDR 2 */
UNKNOWN_MEM_TYPE, /* 09h Undefined */
UNKNOWN_MEM_TYPE, /* 0Ah Undefined */
SMB_MEM_TYPE_DDR3 /* 0Bh SDRAM DDR 3 */
};
#define SPD_TO_SMBIOS_SIZE (sizeof(spd_mem_to_smbios)/sizeof(uint8_t))
typedef struct _vidTag {
uint16_t code;
const char* name;
} VenIdName;
VenIdName vendorMap[] = {
{0xCD04, "G Skill Intl"}, // id=CD Bank=5
{0xB004, "OCZ"}, // id=B0 Bank=5
{0x9801, "Kingston"}, // id=98 Bank=2
{0x9E02, "Corsair"}, // id=9E Bank=3
{0x0205, "Patriot Memory"}, // id=02 Bank=6
{0x9B05, "Crucial Technology"}, // id=9B Bank=6
{0xBA01, "PNY Electronics"}, // id=BA Bank=2
{0x4F01, "Transcend Information"}, // id=4F Bank=2
{0x1903, "Centon Electronics"}, // id=19 Bank=4
{0x4001, "Viking Components"} // id=40 Bank=2
};
#define VEN_MAP_SIZE (sizeof(vendorMap)/sizeof(VenIdName))
#define rdtsc(low,high) \
__asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
#define SMBHSTSTS 0
#define SMBHSTCNT 2
#define SMBHSTCMD 3
#define SMBHSTADD 4
#define SMBHSTDAT 5
const char * getVendorName(const char * spd)
{
uint16_t code = *((uint16_t*) &spd[0x75]);
int i;
for (i=0; i < VEN_MAP_SIZE; i++)
if (code==vendorMap[i].code)
return vendorMap[i].name;
return "No Name";
}
int getDDRspeedMhz(const char * spd)
{
if (spd[2]==0x0b) { // DDR3
switch(spd[12]) {
case 0x0f:
return 1066;
case 0x0c:
return 1333;
case 0x0a:
return 1600;
case 0x14:
default:
return 800;
}
}
else if (spd[2]==0x08) { // DDR2
switch(spd[9]) {
case 0x50:
return 400;
case 0x3d:
return 533;
case 0x30:
return 667;
case 0x25:
default:
return 800;
}
}
return 800; // default freq for unknown types
}
#define UIS(a) ((uint32_t)spd[a])
uint32_t getDDRSerial(const char* spd)
{
uint32_t ret=0;
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;
}
unsigned char smb_read_byte_intel(uint32_t base, uint8_t adr, uint8_t cmd)
{
int l1, h1, l2, h2;
unsigned long long t;
outb(base + SMBHSTSTS, 0x1f);// reset SMBus Controller
outb(base + SMBHSTDAT, 0xff);
while( inb(base + SMBHSTSTS) & 0x01);// wait until ready
outb(base + SMBHSTCMD, cmd);
outb(base + SMBHSTADD, (adr << 1) | 0x01 );
outb(base + SMBHSTCNT, 0x48 );
rdtsc(l1, h1);
while (!( inb(base + SMBHSTSTS) & 0x02))// wait til command finished
{
rdtsc(l2, h2);
t = ((h2 - h1) * 0xffffffff + (l2 - l1)) / (Platform.CPU.TSCFrequency / 40);
if (t > 10)
break;// break after 10ms
}
return inb(base + SMBHSTDAT);
}
int mapping []={0,1,2,3,4,5}; // linear mapping for now, check me
static void read_smb_intel(pci_dt_t *smbus_dev)
{
static int serialnum=0;
int i, x, ser;
uint8_tspd_size, spd_type;
uint32_tbase;
bool dump = false;
RamSlotInfo_t* slot;
base = pci_config_read16(smbus_dev->dev.addr, 0x20) & 0xFFFE;
DBG("Scanning smbus_dev <%04x, %04x> ...\n",smbus_dev->vendor_id, smbus_dev->device_id);
getBoolForKey("DumpSPD", &dump, &bootInfo->bootConfig);
// Search MAX_RAM_SLOTS slots
for (i = 0; i < 6; i++){
slot = &Platform.RAM.DIMM[i];
Platform.DMI.DIMM[i]=mapping[i]; // for now no special mapping
spd_size = smb_read_byte_intel(base, 0x50 + i, 0);
// Check spd is present
if (spd_size != 0xff)
{
slot->InUse = true;
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:
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;
}
}
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, &slot->spd[0x80], 64);
strncpy(slot->Vendor, getVendorName(slot->spd), 64);
ser = getDDRSerial(slot->spd);
if (ser==0) {
sprintf(slot->SerialNo, "10000000%d", serialnum);
serialnum++;
}
else
sprintf(slot->SerialNo, "%d", ser);
// determine speed
slot->Frequency = getDDRspeedMhz(slot->spd);
verbose("Slot %d Type %d %dMB (%s) %dMHz Vendor=%s, PartNo=%s SerialNo=%s\n",
i,
(int)slot->Type,
slot->ModuleSize,
spd_memory_types[spd_type],
slot->Frequency,
slot->Vendor,
slot->PartNo,
slot->SerialNo);
if(dump) {
dumpPhysAddr("spd content: ",slot->spd, spd_size);
getc();
}
}
}
}
static struct smbus_controllers_t smbus_controllers[] = {
{0x8086, 0x5032, "EP80579", read_smb_intel },
{0x8086, 0x269B, "ESB2", read_smb_intel },
{0x8086, 0x25A4, "6300ESB", read_smb_intel },
{0x8086, 0x24C3, "ICH4", read_smb_intel },
{0x8086, 0x24D3, "ICH5", read_smb_intel },
{0x8086, 0x266A, "ICH6", read_smb_intel },
{0x8086, 0x27DA, "ICH7", read_smb_intel },
{0x8086, 0x283E, "ICH8", read_smb_intel },
{0x8086, 0x2930, "ICH9", read_smb_intel },
{0x8086, 0x3A30, "ICH10R", read_smb_intel },
{0x8086, 0x3A60, "ICH10B", read_smb_intel },
{0x8086, 0x3B30, "P55", read_smb_intel }
};
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)
{
pci_dt_t*current = pci_dt;
int i;
while (current) {
#if DEBUG_SPD
printf("%02x:%02x.%x [%04x] [%04x:%04x] :: %s\n",
current->dev.bits.bus, current->dev.bits.dev, current->dev.bits.func,
current->class_id, current->vendor_id, current->device_id,
get_pci_dev_path(current));
#endif
for ( i = 0; i < sizeof(smbus_controllers) / sizeof(smbus_controllers[0]); i++ )
{
if (current->vendor_id == smbus_controllers[i].vendor &&
current->device_id == smbus_controllers[i].device)
{
smbus_controllers[i].read_smb(current); // read smb
return true;
}
}
find_and_read_smbus_controller(current->children);
current = current->next;
}
return false; // not found
}
void scan_spd(PlatformInfo_t *p)
{
/* NYI */
find_and_read_smbus_controller(root_pci_dev);
}
trunk/i386/libsaio/spd.h
88
99
1010
11
1112
12
13
14
1315
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
14159
#define __LIBSAIO_SPD_H
#include "platform.h"
#include "libsaio.h"
extern void scan_spd(PlatformInfo_t *p);
void scan_smbus_controller(pci_dt_t *smbus_dev);
void scan_spd(PlatformInfo_t *p);
struct smbus_controllers_t {
uint32_tvendor;
uint32_tdevice;
char*name;
void (*read_smb)(pci_dt_t *smbus_dev);
};
/*
* Serial Presence Detect (SPD) data stored on SDRAM modules.
*
* Datasheet:
* - Name: PC SDRAM Serial Presence Detect (SPD) Specification
* Revision 1.2A, December, 1997
* - PDF: http://www.intel.com/design/chipsets/memory/spdsd12a.pdf
*
* Datasheet (alternative):
* - Name: SERIAL PRESENCE DETECT STANDARD, General Standard
* JEDEC Standard No. 21-C
* - PDF: http://www.jedec.org/download/search/4_01_02_00R9.PDF
*/
/* Byte numbers. */
#define SPD_NUM_MANUFACTURER_BYTES 0 /* Number of bytes used by module manufacturer */
#define SPD_TOTAL_SPD_MEMORY_SIZE 1 /* Total SPD memory size */
#define SPD_MEMORY_TYPE 2 /* (Fundamental) memory type */
#define SPD_NUM_ROWS 3 /* Number of row address bits */
#define SPD_NUM_COLUMNS 4 /* Number of column address bits */
#define SPD_NUM_DIMM_BANKS 5 /* Number of module rows (banks) */
#define SPD_MODULE_DATA_WIDTH_LSB 6 /* Module data width (LSB) */
#define SPD_MODULE_DATA_WIDTH_MSB 7 /* Module data width (MSB) */
#define SPD_MODULE_VOLTAGE 8 /* Module interface signal levels */
#define SPD_MIN_CYCLE_TIME_AT_CAS_MAX 9 /* SDRAM cycle time (highest CAS latency), RAS access time (tRAC) */
#define SPD_ACCESS_TIME_FROM_CLOCK 10 /* SDRAM access time from clock (highest CAS latency), CAS access time (Tac, tCAC) */
#define SPD_DIMM_CONFIG_TYPE 11 /* Module configuration type */
#define SPD_REFRESH 12 /* Refresh rate/type */
#define SPD_PRIMARY_SDRAM_WIDTH 13 /* SDRAM width (primary SDRAM) */
#define SPD_ERROR_CHECKING_SDRAM_WIDTH 14 /* Error checking SDRAM (data) width */
#define SPD_MIN_CLOCK_DELAY_B2B_RAND_COLUMN 15 /* SDRAM device attributes, minimum clock delay for back to back random column */
#define SPD_SUPPORTED_BURST_LENGTHS 16 /* SDRAM device attributes, burst lengths supported */
#define SPD_NUM_BANKS_PER_SDRAM 17 /* SDRAM device attributes, number of banks on SDRAM device */
#define SPD_ACCEPTABLE_CAS_LATENCIES 18 /* SDRAM device attributes, CAS latency */
#define SPD_CS_LATENCY 19 /* SDRAM device attributes, CS latency */
#define SPD_WE_LATENCY 20 /* SDRAM device attributes, WE latency */
#define SPD_MODULE_ATTRIBUTES 21 /* SDRAM module attributes */
#define SPD_DEVICE_ATTRIBUTES_GENERAL 22 /* SDRAM device attributes, general */
#define SPD_SDRAM_CYCLE_TIME_2ND 23 /* SDRAM cycle time (2nd highest CAS latency) */
#define SPD_ACCESS_TIME_FROM_CLOCK_2ND 24 /* SDRAM access from clock (2nd highest CAS latency) */
#define SPD_SDRAM_CYCLE_TIME_3RD 25 /* SDRAM cycle time (3rd highest CAS latency) */
#define SPD_ACCESS_TIME_FROM_CLOCK_3RD 26 /* SDRAM access from clock (3rd highest CAS latency) */
#define SPD_MIN_ROW_PRECHARGE_TIME 27 /* Minimum row precharge time (Trp) */
#define SPD_MIN_ROWACTIVE_TO_ROWACTIVE 28 /* Minimum row active to row active (Trrd) */
#define SPD_MIN_RAS_TO_CAS_DELAY 29 /* Minimum RAS to CAS delay (Trcd) */
#define SPD_MIN_ACTIVE_TO_PRECHARGE_DELAY 30 /* Minimum RAS pulse width (Tras) */
#define SPD_DENSITY_OF_EACH_ROW_ON_MODULE 31 /* Density of each row on module */
#define SPD_CMD_SIGNAL_INPUT_SETUP_TIME 32 /* Command and address signal input setup time */
#define SPD_CMD_SIGNAL_INPUT_HOLD_TIME 33 /* Command and address signal input hold time */
#define SPD_DATA_SIGNAL_INPUT_SETUP_TIME 34 /* Data signal input setup time */
#define SPD_DATA_SIGNAL_INPUT_HOLD_TIME 35 /* Data signal input hold time */
#define SPD_WRITE_RECOVERY_TIME 36 /* Write recovery time (tWR) */
#define SPD_INT_WRITE_TO_READ_DELAY 37 /* Internal write to read command delay (tWTR) */
#define SPD_INT_READ_TO_PRECHARGE_DELAY 38 /* Internal read to precharge command delay (tRTP) */
#define SPD_MEM_ANALYSIS_PROBE_PARAMS 39 /* Memory analysis probe characteristics */
#define SPD_BYTE_41_42_EXTENSION 40 /* Extension of byte 41 (tRC) and byte 42 (tRFC) */
#define SPD_MIN_ACT_TO_ACT_AUTO_REFRESH 41 /* Minimum active to active auto refresh (tRCmin) */
#define SPD_MIN_AUTO_REFRESH_TO_ACT 42 /* Minimum auto refresh to active/auto refresh (tRFC) */
#define SPD_MAX_DEVICE_CYCLE_TIME 43 /* Maximum device cycle time (tCKmax) */
#define SPD_MAX_DQS_DQ_SKEW 44 /* Maximum skew between DQS and DQ (tDQSQ) */
#define SPD_MAX_READ_DATAHOLD_SKEW 45 /* Maximum read data-hold skew factor (tQHS) */
#define SPD_PLL_RELOCK_TIME 46 /* PLL relock time */
#define SPD_SPD_DATA_REVISION_CODE 62 /* SPD data revision code */
#define SPD_CHECKSUM_FOR_BYTES_0_TO_62 63 /* Checksum for bytes 0-62 */
#define SPD_MANUFACTURER_JEDEC_ID_CODE 64 /* Manufacturer's JEDEC ID code, per EIA/JEP106 (bytes 64-71) */
#define SPD_MANUFACTURING_LOCATION 72 /* Manufacturing location */
#define SPD_MANUFACTURER_PART_NUMBER 73 /* Manufacturer's part number, in 6-bit ASCII (bytes 73-90) */
#define SPD_REVISION_CODE 91 /* Revision code (bytes 91-92) */
#define SPD_MANUFACTURING_DATE 93 /* Manufacturing date (byte 93: year, byte 94: week) */
#define SPD_ASSEMBLY_SERIAL_NUMBER 95 /* Assembly serial number (bytes 95-98) */
#define SPD_MANUFACTURER_SPECIFIC_DATA 99 /* Manufacturer specific data (bytes 99-125) */
#define SPD_INTEL_SPEC_FOR_FREQUENCY 126 /* Intel specification for frequency */
#define SPD_INTEL_SPEC_100_MHZ 127 /* Intel specification details for 100MHz support */
/* DRAM specifications use the following naming conventions for SPD locations */
#define SPD_tRP SPD_MIN_ROW_PRECHARGE_TIME
#define SPD_tRRD SPD_MIN_ROWACTIVE_TO_ROWACTIVE
#define SPD_tRCD SPD_MIN_RAS_TO_CAS_DELAY
#define SPD_tRAS SPD_MIN_ACTIVE_TO_PRECHARGE_DELAY
#define SPD_BANK_DENSITY SPD_DENSITY_OF_EACH_ROW_ON_MODULE
#define SPD_ADDRESS_CMD_HOLD SPD_CMD_SIGNAL_INPUT_HOLD_TIME
#define SPD_tRC41/* SDRAM Device Minimum Active to Active/Auto Refresh Time (tRC) */
#define SPD_tRFC42/* SDRAM Device Minimum Auto Refresh to Active/Auto Refresh (tRFC) */
/* SPD_MEMORY_TYPE values. */
#define SPD_MEMORY_TYPE_FPM_DRAM1
#define SPD_MEMORY_TYPE_EDO2
#define SPD_MEMORY_TYPE_PIPELINED_NIBBLE3
#define SPD_MEMORY_TYPE_SDRAM4
#define SPD_MEMORY_TYPE_MULTIPLEXED_ROM5
#define SPD_MEMORY_TYPE_SGRAM_DDR6
#define SPD_MEMORY_TYPE_SDRAM_DDR7
#define SPD_MEMORY_TYPE_SDRAM_DDR28
#define SPD_MEMORY_TYPE_SDRAM_DDR30xb
/* SPD_MODULE_VOLTAGE values. */
#define SPD_VOLTAGE_TTL0 /* 5.0 Volt/TTL */
#define SPD_VOLTAGE_LVTTL1 /* LVTTL */
#define SPD_VOLTAGE_HSTL2 /* HSTL 1.5 */
#define SPD_VOLTAGE_SSTL33 /* SSTL 3.3 */
#define SPD_VOLTAGE_SSTL24 /* SSTL 2.5 */
/* SPD_DIMM_CONFIG_TYPE values. */
#define ERROR_SCHEME_NONE0
#define ERROR_SCHEME_PARITY1
#define ERROR_SCHEME_ECC2
/* SPD_ACCEPTABLE_CAS_LATENCIES values. */
// TODO: Check values.
#define SPD_CAS_LATENCY_1_00x01
#define SPD_CAS_LATENCY_1_50x02
#define SPD_CAS_LATENCY_2_00x04
#define SPD_CAS_LATENCY_2_50x08
#define SPD_CAS_LATENCY_3_00x10
#define SPD_CAS_LATENCY_3_50x20
#define SPD_CAS_LATENCY_4_00x40
#define SPD_CAS_LATENCY_DDR2_3(1 << 3)
#define SPD_CAS_LATENCY_DDR2_4(1 << 4)
#define SPD_CAS_LATENCY_DDR2_5(1 << 5)
#define SPD_CAS_LATENCY_DDR2_6(1 << 6)
/* SPD_SUPPORTED_BURST_LENGTHS values. */
#define SPD_BURST_LENGTH_11
#define SPD_BURST_LENGTH_22
#define SPD_BURST_LENGTH_44
#define SPD_BURST_LENGTH_88
#define SPD_BURST_LENGTH_PAGE(1 << 7)
/* SPD_MODULE_ATTRIBUTES values. */
#define MODULE_BUFFERED1
#define MODULE_REGISTERED2
#endif /* !__LIBSAIO_SPD_H */
trunk/i386/libsaio/smbios_patcher.c
1010
1111
1212
13
1413
1514
16
15
1716
1817
1918
......
168167
169168
170169
171
172
173
170
171
172
173
174
175
176
177
174178
179
175180
176181
177182
......
196201
197202
198203
199
200
204
205
206
201207
202208
203209
......
276282
277283
278284
279
280
281
285
286
287
282288
283289
284290
......
286292
287293
288294
289
295
290296
291297
292298
......
318324
319325
320326
321
327
322328
323329
324330
......
329335
330336
331337
332
333
334
338
339
340
335341
336342
343
344
345
337346
338347
339348
......
379388
380389
381390
391
392
382393
383394
384395
......
426437
427438
428439
440
441
442
443
429444
430445
431446
......
437452
438453
439454
440
455
456
457
441458
442459
443460
......
453470
454471
455472
473
474
456475
457476
458477
......
461480
462481
463482
483
484
464485
465486
466487
467488
468489
490
491
469492
470493
471494
......
475498
476499
477500
501
502
478503
479
504
505
506
507
508
509
510
511
512
513
480514
481
515
482516
483517
518
519
484520
485521
486522
......
572608
573609
574610
611
612
575613
576614
577615
......
688726
689727
690728
729
730
691731
692732
693733
......
707747
708748
709749
750
710751
711752
712753
......
730771
731772
732773
733
734
735
774
775
776
736777
737
738
778
779
739780
740781
741782
742
783
743784
744785
745786
746
747
748
749
787
788
789
790
750791
751792
752
793
753794
754
795
755796
756797
757798
#include "fake_efi.h"
#include "platform.h"
#include "smbios_patcher.h"
#include "SMBIOS.h"
#ifndef DEBUG_SMBIOS
#define DEBUG_SMBIOS 1
#define DEBUG_SMBIOS 0
#endif
#if DEBUG_SMBIOS
static int sm_get_memspeed (char *name, int table_num)
{
if (Platform.RAM.Frequency != 0) {
DBG("RAM Detected Freq = %d\n", Platform.RAM.Frequency/1000000);
return Platform.RAM.Frequency/1000000;
intmap;
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 Freq = %d Mhz\n", Platform.RAM.DIMM[map].Frequency);
return Platform.RAM.DIMM[map].Frequency;
}
}
return 800;
}
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("RAM Detected SerialNo[%d]='%s'\n", table_num, Platform.RAM.DIMM[map].SerialNo);
return Platform.RAM.DIMM[map].SerialNo;
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";
while (smbios <= (struct SMBEntryPoint *)SMBIOS_RANGE_END) {
if (COMPARE_DWORD(smbios->anchor, SMTAG) && COMPARE_DWORD(smbios->dmi.anchor, DMITAG) &&
checksum8(smbios, sizeof(struct SMBEntryPoint)) == 0)
{
return smbios;
}
{
return smbios;
}
smbios = (((void*) smbios) + 16);
}
printf("ERROR: Unable to find SMBIOS!\n");
return NULL;
}
/* Compute necessary space requirements for new smbios */
/** Compute necessary space requirements for new smbios */
struct SMBEntryPoint *smbios_dry_run(struct SMBEntryPoint *origsmbios)
{
struct SMBEntryPoint*ret;
ret->entryPointLength = sizeof(*ret);
ret->majorVersion = 2;
ret->minorVersion = 1;
ret->maxStructureSize = 0;
ret->maxStructureSize = 0; // will be calculated later in this function
ret->entryPointRevision = 0;
for (i=0;i<5;i++) {
ret->formattedArea[i] = 0;
ret->dmi.anchor[2] = 0x4d;
ret->dmi.anchor[3] = 0x49;
ret->dmi.anchor[4] = 0x5f;
ret->dmi.tableLength = 0;
ret->dmi.tableAddress = 0;
ret->dmi.structureCount = 0;
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; i<origsmbiosnum; i++) {
struct smbios_table_header*cur = (struct smbios_table_header *)tablesptr;
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; i<sizeof(smbios_table_descriptions)/sizeof(smbios_table_descriptions[0]); i++) {
intnumnec=-1;
charbuffer[40];
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.
*/
void smbios_real_run(struct SMBEntryPoint * origsmbios, struct SMBEntryPoint * newsmbios)
{
char *smbiostables;
int i, j;
int tablespresent[256];
bool do_auto=true;
extern void dumpPhysAddr(const char * title, void * a, int len);
bzero(tablespresent, sizeof(tablespresent));
bzero(handles, sizeof(handles));
}
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; i<origsmbiosnum; i++) {
struct smbios_table_header*oldcur = (struct smbios_table_header *) tablesptr;
intnstrings = 0;
handles[(oldcur->handle) / 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++;
nstrings++;
}
tablesptr += 2;
// copy the old strings to new table
memcpy(newtablesptr, stringsptr, tablesptr-stringsptr);
//point to next possible space for a string
#if 0
// DEBUG: display this original table 17
if (oldcur->type==6 || oldcur->type==17)
{
dumpPhysAddr("orig table:", oldcur, oldcur->length + ( tablesptr-stringsptr));
}
#endif
// point to next possible space for a string (deducting the second 0 char at the end)
newtablesptr += tablesptr - stringsptr - 1;
if (nstrings == 0) {
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; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {
const char*str;
intsize;
tablespresent[newcur->type]++;
}
}
// for each eventual complementary table not present in the original smbios, do the overrides
for (i=0; i<sizeof(smbios_table_descriptions)/sizeof(smbios_table_descriptions[0]); i++) {
intnumnec = -1;
charbuffer[40];
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;
return orig;
case SMBIOS_PATCHED:
if (patched == NULL) {
if (orig==NULL) orig = getAddressOfSmbiosTable();
patched = smbios_dry_run(orig);
smbios_real_run(orig, patched);
}
if (smbios == NULL || type < 0 ) return NULL;
#if DEBUG_SMBIOS
printf(">>> SMBIOSAddr=0x%08x\n", smbios);
printf(">>> DMI: addr=0x%08x, len=0x%d, count=%d\n", smbios->dmi.tableAddress,
smbios->dmi.tableLength, smbios->dmi.structureCount);
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++)
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);
// 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 (dmihdr->type == type) /* 3.3.2 System Information */
{
if (dmihdr->length >= min_length) found = true;
break;
}
{
if (dmihdr->length >= min_length) found = true;
break;
}
p = p + dmihdr->length;
while ((p - (SMBByte *)smbios->dmi.tableAddress + 1 < smbios->dmi.tableLength) && (p[0] != 0x00 || p[1] != 0x00))
{
{
p++;
}
}
p += 2;
}
trunk/i386/libsaio/mem.c
99
1010
1111
12
1213
1314
1415
......
2021
2122
2223
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
2366
2467
25
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
2691
#include "platform.h"
#include "cpu.h"
#include "mem.h"
#include "smbios_patcher.h"
#ifndef DEBUG_MEM
#define DEBUG_MEM 0
#define DBG(x...)
#endif
#define DC(c) (c >= 0x20 && c < 0x7f ? (char) c : '.')
#define STEP 16
void dumpPhysAddr(const char * title, void * a, int len)
{
int i,j;
u_int8_t* ad = (u_int8_t*) a;
char buffer[80];
char str[16];
if(ad==NULL) return;
printf("%s addr=0x%08x len=%04d\n",title ? title : "Dump of ", a, len);
i = (len/STEP)*STEP;
for (j=0; j < i; j+=STEP)
{
printf("%02x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
j,
ad[j], ad[j+1], ad[j+2], ad[j+3] , ad[j+4], ad[j+5], ad[j+6], ad[j+7],
ad[j+8], ad[j+9], ad[j+10], ad[j+11] , ad[j+12], ad[j+13], ad[j+14], ad[j+15],
DC(ad[j]), DC(ad[j+1]), DC(ad[j+2]), DC(ad[j+3]) , DC(ad[j+4]), DC(ad[j+5]), DC(ad[j+6]), DC(ad[j+7]),
DC(ad[j+8]), DC(ad[j+9]), DC(ad[j+10]), DC(ad[j+11]) , DC(ad[j+12]), DC(ad[j+13]), DC(ad[j+14]), DC(ad[j+15])
);
}
if (len%STEP==0) return;
sprintf(buffer,"%02x:", i);
for (j=0; j < STEP; j++) {
if (j<(len%STEP))
sprintf(str, " %02x", ad[i+j]);
else
strcpy(str, " " );
strncat(buffer, str, sizeof(buffer));
}
strncat(buffer," ", sizeof(buffer));
for (j=0; j < (len%STEP); j++) {
sprintf(str, "%c", DC(ad[i+j]));
strncat(buffer, str, sizeof(buffer));
}
printf("%s\n",buffer);
}
void scan_memory(PlatformInfo_t *p)
{
/* NYI */
#if 0
struct SMBEntryPoint*smbios;
//struct DMIHeader * dmihdr;
struct DMIMemoryControllerInfo* ctrlInfo;
struct DMIMemoryModuleInfo* memInfo;
struct DMIPhysicalMemoryArray* physMemArray;
struct DMIMemoryDevice* memDev;
smbios = getSmbios(SMBIOS_ORIGINAL);/* checks for _SM_ anchor and table header checksum */
if (smbios==NULL) return ; // getSmbios() return a non null value if smbios is found
ctrlInfo = (struct DMIMemoryControllerInfo*) getSmbiosTableStructure(smbios, 5, 0x1);
memInfo = (struct DMIMemoryModuleInfo*) getSmbiosTableStructure(smbios, 6, 0x1);
physMemArray = (struct DMIPhysicalMemoryArray*) getSmbiosTableStructure(smbios, 16, 0x1);
memDev = (struct DMIMemoryDevice*) getSmbiosTableStructure(smbios, 17, 0x1);
dumpPhysAddr("Memory Controller Info (05):", ctrlInfo, ctrlInfo->dmiHeader.length);
dumpPhysAddr("Memory Module Info (06):",memInfo, memInfo->dmiHeader.length);
dumpPhysAddr("Physical Memory Array (16):",physMemArray, physMemArray->dmiHeader.length);
dumpPhysAddr("Memory Device (17):",memDev, memDev->dmiHeader.length);
getc();
#endif
}
trunk/i386/libsaio/platform.h
1111
1212
1313
14
1415
1516
1617
......
7475
7576
7677
77
78
79
80
81
78
79
80
81
82
83
84
85
86
87
8288
8389
8490
......
104110
105111
106112
107
108113
109114
110115
extern bool platformCPUFeature(uint32_t);
extern void scan_platform(void);
extern void dumpPhysAddr(const char * title, void * a, int len);
/* CPUID index into cpuid_raw */
#define CPUID_00
#define UUID_LEN16
typedef struct _RamSlotInfo_t {
boolInUse;
uint8_tType;
charVendor[64];
charPartNo[64];
charSerialNo[16];
boolInUse;
uint8_tType;
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;
typedef struct _PlatformInfo_t {
struct RAM {
RamSlotInfo_tDIMM[MAX_RAM_SLOTS];// Information about each slot
uint64_tFrequency;// Ram Frequency
} RAM;
struct DMI {

Archive Download the corresponding diff file

Revision: 90