Chameleon

Chameleon Commit Details

Date:2010-01-17 14:27:30 (14 years 3 months ago)
Author:JrCs
Commit:15
Parents: 14
Message:New cpu and mem modules. Update fake_efi, platform and smbios_patcher. Delete freq_detect module.
Changes:
D/branches/JrCs/i386/libsaio/freq_detect.h
R/branches/JrCs/i386/libsaio/freq_detect.c → /branches/JrCs/i386/libsaio/cpu.c
A/branches/JrCs/i386/libsaio/mem.c
A/branches/JrCs/i386/libsaio/mem.h
A/branches/JrCs/i386/libsaio/cpu.h
M/branches/JrCs/i386/libsaio/smbios_patcher.c
M/branches/JrCs/i386/libsaio/dsdt_patcher.c
M/branches/JrCs/i386/libsaio/platform.c
M/branches/JrCs/i386/libsaio/spd.c
M/branches/JrCs/i386/libsaio/smbios_patcher.h
M/branches/JrCs/i386/libsaio/fake_efi.c
M/branches/JrCs/i386/libsaio/platform.h
M/branches/JrCs/i386/libsaio/spd.h
M/branches/JrCs/i386/libsaio/Makefile

File differences

branches/JrCs/i386/libsaio/freq_detect.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
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
/*
* Copyright 2008 Islam Ahmed Zaid. All rights reserved. <azismed@gmail.com>
*/
#include "libsaio.h"
#include "freq_detect.h"
// DFE: enable_PIT2 and disable_PIT2 come from older xnu
/*
* Enable or disable timer 2.
* Port 0x61 controls timer 2:
* bit 0 gates the clock,
* bit 1 gates output to speaker.
*/
inline static void
enable_PIT2(void)
{
/* Enable gate, disable speaker */
__asm__ volatile(
" inb $0x61,%%al \n\t"
" and $0xFC,%%al \n\t" /* & ~0x03 */
" or $1,%%al \n\t"
" outb %%al,$0x61 \n\t"
: : : "%al" );
}
inline static void
disable_PIT2(void)
{
/* Disable gate and output to speaker */
__asm__ volatile(
" inb $0x61,%%al \n\t"
" and $0xFC,%%al \n\t"/* & ~0x03 */
" outb %%al,$0x61 \n\t"
: : : "%al" );
}
// DFE: set_PIT2_mode0, poll_PIT2_gate, and measure_tsc_frequency are
// roughly based on Linux code
/* Set the 8254 channel 2 to mode 0 with the specified value.
In mode 0, the counter will initially set its gate low when the
timer expires. For this to be useful, you ought to set it high
before calling this function. The enable_PIT2 function does this.
*/
static inline void set_PIT2_mode0(uint16_t value)
{
__asm__ volatile(
" movb $0xB0,%%al \n\t"
" outb%%al,$0x43\n\t"
" movb%%dl,%%al\n\t"
" outb%%al,$0x42\n\t"
" movb%%dh,%%al\n\t"
" outb%%al,$0x42"
: : "d"(value) /*: no clobber */ );
}
/* Returns the number of times the loop ran before the PIT2 signaled */
static inline unsigned long poll_PIT2_gate(void)
{
unsigned long count = 0;
unsigned char nmi_sc_val;
do {
++count;
__asm__ volatile(
"inb$0x61,%0"
: "=q"(nmi_sc_val) /*:*/ /* no input */ /*:*/ /* no clobber */);
} while( (nmi_sc_val & 0x20) == 0);
return count;
}
/*
* DFE: Measures the TSC frequency in Hz (64-bit) using the ACPI PM timer
*/
uint64_t measure_tsc_frequency(void)
{
uint64_t tscStart;
uint64_t tscEnd;
uint64_t tscDelta = 0xffffffffffffffffULL;
unsigned long pollCount;
uint64_t retval = 0;
int i;
/* Time how many TSC ticks elapse in 30 msec using the 8254 PIT
* counter 2. We run this loop 3 times to make sure the cache
* is hot and we take the minimum delta from all of the runs.
* That is to say that we're biased towards measuring the minimum
* number of TSC ticks that occur while waiting for the timer to
* expire. That theoretically helps avoid inconsistencies when
* running under a VM if the TSC is not virtualized and the host
* steals time. The TSC is normally virtualized for VMware.
*/
for(i = 0; i < 3; ++i)
{
enable_PIT2();
set_PIT2_mode0(CALIBRATE_LATCH);
tscStart = rdtsc64();
pollCount = poll_PIT2_gate();
tscEnd = rdtsc64();
/* The poll loop must have run at least a few times for accuracy */
if(pollCount <= 1)
continue;
/* The TSC must increment at LEAST once every millisecond. We
* should have waited exactly 30 msec so the TSC delta should
* be >= 30. Anything less and the processor is way too slow.
*/
if((tscEnd - tscStart) <= CALIBRATE_TIME_MSEC)
continue;
// tscDelta = min(tscDelta, (tscEnd - tscStart))
if( (tscEnd - tscStart) < tscDelta )
tscDelta = tscEnd - tscStart;
}
/* tscDelta is now the least number of TSC ticks the processor made in
* a timespan of 0.03 s (e.g. 30 milliseconds)
* Linux thus divides by 30 which gives the answer in kiloHertz because
* 1 / ms = kHz. But we're xnu and most of the rest of the code uses
* Hz so we need to convert our milliseconds to seconds. Since we're
* dividing by the milliseconds, we simply multiply by 1000.
*/
/* Unlike linux, we're not limited to 32-bit, but we do need to take care
* that we're going to multiply by 1000 first so we do need at least some
* arithmetic headroom. For now, 32-bit should be enough.
* Also unlike Linux, our compiler can do 64-bit integer arithmetic.
*/
if(tscDelta > (1ULL<<32))
retval = 0;
else
{
retval = tscDelta * 1000 / 30;
}
disable_PIT2();
return retval;
}
uint64_t tscFrequency = 0;
uint64_t fsbFrequency = 0;
uint64_t cpuFrequency = 0;
/*
* Calculates the FSB and CPU frequencies using specific MSRs for each CPU
* - multi. is read from a specific MSR. In the case of Intel, there is:
* a max multi. (used to calculate the FSB freq.),
* and a current multi. (used to calculate the CPU freq.)
* - fsbFrequency = tscFrequency / multi
* - cpuFrequency = fsbFrequency * multi
*/
void calculate_freq(void)
{
uint32_tcpuid_reg[4], cpu_vendor;
uint8_tcpu_family, cpu_model, cpu_extfamily, cpu_extmodel;
uint64_tmsr, flex_ratio;
uint8_tmaxcoef, maxdiv, currcoef, currdiv;
do_cpuid(0, cpuid_reg);
cpu_vendor = cpuid_reg[1];
do_cpuid(1, cpuid_reg);
cpu_model = bitfield(cpuid_reg[0], 7, 4);
cpu_family = bitfield(cpuid_reg[0], 11, 8);
cpu_extmodel = bitfield(cpuid_reg[0], 19, 16);
cpu_extfamily = bitfield(cpuid_reg[0], 27, 20);
cpu_model += (cpu_extmodel << 4);
DBG("\nCPU Model: %d - CPU Family: %d - CPU Ext. Family: %d\n", cpu_model, cpu_family, cpu_extfamily);
DBG("The booter will now attempt to read the CPU Multiplier (using RDMSR).\n");
DBG("Press any key to continue..\n\n");
#if DEBUG_FREQ
getc();
#endif
tscFrequency = measure_tsc_frequency();
DBG("CPU Multiplier: ");
if((cpu_vendor == 0x756E6547 /* Intel */) && ((cpu_family == 0x06) || (cpu_family == 0x0f)))
{
if ((cpu_family == 0x06 && cpu_model >= 0x0c) ||
(cpu_family == 0x0f && cpu_model >= 0x03))
{
/* Nehalem CPU model */
if (cpu_family == 0x06 && (cpu_model == 0x1a || cpu_model == 0x1e))
{
msr = rdmsr64(MSR_PLATFORM_INFO);
currcoef = (msr >> 8) & 0xff;
msr = rdmsr64(MSR_FLEX_RATIO);
if ((msr >> 16) & 0x01)
{
flex_ratio = (msr >> 8) & 0xff;
if (currcoef > flex_ratio)
currcoef = flex_ratio;
}
if (currcoef)
{
DBG("%d\n", currcoef);
fsbFrequency = (tscFrequency / currcoef);
}
cpuFrequency = tscFrequency;
}
else
{
msr = rdmsr64(IA32_PERF_STATUS);
currcoef = (msr >> 8) & 0x1f;
/* Non-integer bus ratio for the max-multi*/
maxdiv = (msr >> 46) & 0x01;
/* Non-integer bus ratio for the current-multi (undocumented)*/
currdiv = (msr >> 14) & 0x01;
if ((cpu_family == 0x06 && cpu_model >= 0x0e) ||
(cpu_family == 0x0f)) // This will always be model >= 3
{
/* On these models, maxcoef defines TSC freq */
maxcoef = (msr >> 40) & 0x1f;
}
else
{
/* On lower models, currcoef defines TSC freq */
/* XXX */
maxcoef = currcoef;
}
if (maxcoef)
{
if (maxdiv)
fsbFrequency = ((tscFrequency * 2) / ((maxcoef * 2) + 1));
else
fsbFrequency = (tscFrequency / maxcoef);
if (currdiv)
cpuFrequency = (fsbFrequency * ((currcoef * 2) + 1) / 2);
else
cpuFrequency = (fsbFrequency * currcoef);
DBG("max: %d%s current: %d%s\n", maxcoef, maxdiv ? ".5" : "",currcoef, currdiv ? ".5" : "");
}
}
}
}
else if((cpu_vendor == 0x68747541 /* AMD */) && (cpu_family == 0x0f))
{
if(cpu_extfamily == 0x00 /* K8 */)
{
msr = rdmsr64(K8_FIDVID_STATUS);
currcoef = (msr & 0x3f) / 2 + 4;
currdiv = (msr & 0x01) * 2;
}
else if(cpu_extfamily >= 0x01 /* K10+ */)
{
msr = rdmsr64(K10_COFVID_STATUS);
if(cpu_extfamily == 0x01 /* K10 */)
currcoef = (msr & 0x3f) + 0x10;
else /* K11+ */
currcoef = (msr & 0x3f) + 0x08;
currdiv = (2 << ((msr >> 6) & 0x07));
}
if (currcoef)
{
if (currdiv)
{
fsbFrequency = ((tscFrequency * currdiv) / currcoef);
DBG("%d.%d\n", currcoef / currdiv, ((currcoef % currdiv) * 100) / currdiv);
}
else
{
fsbFrequency = (tscFrequency / currcoef);
DBG("%d\n", currcoef);
}
fsbFrequency = (tscFrequency / currcoef);
cpuFrequency = tscFrequency;
}
}
if (!fsbFrequency)
{
fsbFrequency = (DEFAULT_FSB * 1000);
cpuFrequency = tscFrequency;
DBG("0 ! using the default value for FSB !\n");
}
DBG("TSC Frequency: %dMHz\n", tscFrequency / 1000000);
DBG("CPU Frequency: %dMHz\n", cpuFrequency / 1000000);
DBG("FSB Frequency: %dMHz\n", fsbFrequency / 1000000);
DBG("Press [Enter] to continue..\n");
#if DEBUG_FREQ
while (getc() != 0x0d) ;
#endif
}
branches/JrCs/i386/libsaio/freq_detect.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
/*
* Copyright 2008 Islam Ahmed Zaid. All rights reserved. <azismed@gmail.com>
*/
#ifndef __LIBSAIO_FREQ_DETECT_H
#define __LIBSAIO_FREQ_DETECT_H
#include "libsaio.h"
#ifndef DEBUG_FREQ
#define DEBUG_FREQ 0
#endif
#if DEBUG_FREQ
#define DBG(x...)printf(x)
#else
#define DBG(x...)
#endif
/* Decimal powers: */
#define kilo (1000ULL)
#define Mega (kilo * kilo)
#define Giga (kilo * Mega)
#define Tera (kilo * Giga)
#define Peta (kilo * Tera)
#define bit(n)(1ULL << (n))
#define bitmask(h,l)((bit(h)|(bit(h)-1)) & ~(bit(l)-1))
#define bitfield(x,h,l)(((x) & bitmask(h,l)) >> l)
#defineIA32_PERF_STATUS0x198
#define MSR_FLEX_RATIO0x194
#defineMSR_PLATFORM_INFO0xCE
#define K8_FIDVID_STATUS0xC0010042
#define K10_COFVID_STATUS0xC0010071
#define DEFAULT_FSB100000 /* for now, hardcoding 100MHz for old CPUs */
// DFE: This constant comes from older xnu:
#define CLKNUM1193182/* formerly 1193167 */
// DFE: These two constants come from Linux except CLOCK_TICK_RATE replaced with CLKNUM
#define CALIBRATE_TIME_MSEC 30 /* 30 msecs */
#define CALIBRATE_LATCH\
((CLKNUM * CALIBRATE_TIME_MSEC + 1000/2)/1000)
extern uint64_t tscFrequency;
extern uint64_t fsbFrequency;
extern uint64_t cpuFrequency;
void calculate_freq(void);
static inline uint64_t rdtsc64(void)
{
uint64_t ret;
__asm__ volatile("rdtsc" : "=A" (ret));
return ret;
}
static inline uint64_t rdmsr64(uint32_t msr)
{
uint64_t ret;
__asm__ volatile("rdmsr" : "=A" (ret) : "c" (msr));
return ret;
}
static inline void do_cpuid(uint32_t selector, uint32_t *data)
{
asm volatile ("cpuid"
: "=a" (data[0]),
"=b" (data[1]),
"=c" (data[2]),
"=d" (data[3])
: "a" (selector)
);
}
#endif /* !__LIBSAIO_FREQ_DETECT_H */
branches/JrCs/i386/libsaio/spd.c
1818
1919
2020
21
22
23
24
25
26
2127
2228
2329
......
3440
3541
3642
37
38
43
44
3945
4046
4147
......
163169
164170
165171
166
172
#define DBG(x...)
#endif
void scan_spd(PlatformInfo_t *p)
{
/* NYI */
}
#if 0 // Old structures and functions
static const char *spd_memory_types[] =
{
"RAM", /* 00h Undefined */
"DDR3 SDRAM", /* 0Bh SDRAM DDR 3 */
};
#define rdtsc(low,high) \
__asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
#define rdtsc(low,high)\
__asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
#define SMBHSTSTS 0
#define SMBHSTCNT 2
}
}
#endif
branches/JrCs/i386/libsaio/spd.h
66
77
88
9
10
11
12
13
14
915
1016
1117
......
153159
154160
155161
162
163
156164
#ifndef __LIBSAIO_SPD_H
#define __LIBSAIO_SPD_H
#include "platform.h"
extern void scan_spd(PlatformInfo_t *p);
#if 0 // Old structures and functions
#include "libsaio.h"
void scan_smbus_controller(pci_dt_t *smbus_dev);
#define MODULE_BUFFERED1
#define MODULE_REGISTERED2
#endif
#endif /* !__LIBSAIO_SPD_H */
branches/JrCs/i386/libsaio/Makefile
44
55
66
7
78
89
910
......
1819
1920
2021
21
22
2223
2324
2425
......
3738
3839
3940
40
41
4142
4243
43
44
4445
4546
4647
UTILDIR = ../util
LIBSADIR = ../libsa
BOOT2DIR = ../boot2
INSTALLDIR = $(DSTROOT)/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders/standalone
#SYMROOT=
DEFINES=
CONFIG = hd
INC = -I. -I$(SYMROOT) -I$(UTILDIR) -I$(LIBSADIR)
INC = -I. -I$(SYMROOT) -I$(UTILDIR) -I$(LIBSADIR) -I$(BOOT2DIR)
ifneq "" "$(wildcard /bin/mkdirs)"
MKDIRS = /bin/mkdirs
else
ufs.o ufs_byteorder.o \
vbe.o nbp.o hfs.o hfs_compare.o \
xml.o ntfs.o msdos.o md5c.o device_tree.o \
freq_detect.o platform.o dsdt_patcher.o \
cpu.o platform.o dsdt_patcher.o \
smbios_patcher.o fake_efi.o ext2fs.o \
hpet.o spd.o usb.o pci_setup.o \
device_inject.o nvidia.o ati.o
device_inject.o nvidia.o ati.o mem.o
SAIO_EXTERN_OBJS = console.o
branches/JrCs/i386/libsaio/smbios_patcher.c
33
44
55
6
67
78
89
......
102103
103104
104105
105
106
107
106
107
108108
109109
110110
111111
112
112
113113
114114
115115
116116
117117
118118
119
119120
120121
121122
......
156157
157158
158159
159
160
161
160
161
162
163
164
165
162166
163167
164168
165169
166170
167
168
169
171
172
173
170174
171175
172176
173177
174178
179
180
181
182
183
184
185
175186
176187
177188
178189
179190
191
192
193
194
195
196
197
180198
181199
182200
183201
184202
203
204
205
206
207
208
209
185210
186211
187212
......
227252
228253
229254
230
255
231256
232257
233258
......
283308
284309
285310
311
312
313
286314
315
287316
288317
289318
......
422451
423452
424453
454
455
456
425457
426458
427459
428460
429461
430462
431
432
433
463
464
434465
435466
436467
*/
#include "libsaio.h"
#include "boot.h"
#include "acpi.h"
#include "bootstruct.h"
#include "efi_tables.h"
int i;
char (*sm_defaults)[2][40];
if (Platform.CPU.Mobile)
if (Platform.CPU.NoCores > 1)
{
if (platformCPUFeature(CPU_FEATURE_MOBILE)) {
if (Platform.CPU.NoCores > 1) {
sm_defaults=sm_macbookpro_defaults;
} else {
sm_defaults=sm_macbook_defaults;
}
else
} else {
switch (Platform.CPU.NoCores)
{
case 1: sm_defaults=sm_macmini_defaults; break;
case 2: sm_defaults=sm_imac_defaults; break;
default: sm_defaults=sm_macpro_defaults; break;
}
}
for (i=0;sm_defaults[i][0][0];i++)
if (!strcmp (sm_defaults[i][0],name))
static int sm_get_memtype (char *name, int table_num)
{
if(Platform.RAM.Type)
return Platform.RAM.Type;
else
if (table_num < MAX_RAM_SLOTS &&
Platform.RAM.DIMM[table_num].InUse &&
Platform.RAM.DIMM[table_num].Type != 0)
{
return Platform.RAM.DIMM[table_num].Type;
}
return SMB_MEM_TYPE_DDR2;
}
static int sm_get_memspeed (char *name, int table_num)
{
if(Platform.RAM.Type)
return round2( Platform.RAM.Frequency / 500000, 2);
else
if (Platform.RAM.Frequency != 0) {
return Platform.RAM.Frequency/1000000;
}
return 667;
}
static char *sm_get_memvendor (char *name, int table_num)
{
if (table_num < MAX_RAM_SLOTS &&
Platform.RAM.DIMM[table_num].InUse &&
strlen(Platform.RAM.DIMM[table_num].Vendor) > 0)
{
DBG("Vendor[%d]='%s'\n", table_num, Platform.RAM.DIMM[table_num].Vendor);
return Platform.RAM.DIMM[table_num].Vendor;
}
return "N/A";
}
static char *sm_get_memserial (char *name, int table_num)
{
if (table_num < MAX_RAM_SLOTS &&
Platform.RAM.DIMM[table_num].InUse &&
strlen(Platform.RAM.DIMM[table_num].SerialNo) > 0)
{
DBG("SerialNo[%d]='%s'\n", table_num, Platform.RAM.DIMM[table_num].SerialNo);
return Platform.RAM.DIMM[table_num].SerialNo;
}
return "N/A";
}
static char *sm_get_mempartno (char *name, int table_num)
{
if (table_num < MAX_RAM_SLOTS &&
Platform.RAM.DIMM[table_num].InUse &&
strlen(Platform.RAM.DIMM[table_num].PartNo) > 0)
{
DBG("PartNo[%d]='%s'\n", table_num, Platform.RAM.DIMM[table_num].PartNo);
return Platform.RAM.DIMM[table_num].PartNo;
}
return "N/A";
}
{.type=132,.len=0x06,.numfunc=sm_one}
};
static inline struct SMBEntryPoint * getAddressOfSmbiosTable()
struct SMBEntryPoint * getAddressOfSmbiosTable()
{
/* First see if we can even find the damn SMBIOS table
* The logic here is to start at 0xf0000 and end at 0xfffff iterating 16 bytes at a time looking
{
smbiostables=(char *)origsmbios->dmi.tableAddress;
origsmbiosnum=origsmbios->dmi.structureCount;
} else {
smbiostables = NULL;
origsmbiosnum = 0;
}
// _SM_
ret->anchor[0]=0x5f;
ret->anchor[1]=0x53;
{
smbiostables=(char *) origsmbios->dmi.tableAddress;
origsmbiosnum=origsmbios->dmi.structureCount;
} else {
smbiostables = NULL;
origsmbiosnum = 0;
}
tablesptr=smbiostables;
newtablesptr=(char *) newsmbios->dmi.tableAddress;
if (smbiostables)
for (i=0;i<origsmbiosnum;i++)
{
struct smbios_table_header *oldcur
=(struct smbios_table_header *) tablesptr,
*newcur=(struct smbios_table_header *) newtablesptr;
struct smbios_table_header*oldcur = (struct smbios_table_header *) tablesptr;
struct smbios_table_header*newcur = (struct smbios_table_header *) newtablesptr;
char *stringsptr;
int nstrings=0;
branches/JrCs/i386/libsaio/smbios_patcher.h
66
77
88
9
910
1011
1112
......
5455
5556
5657
58
59
5760
#define __LIBSAIO_SMBIOS_PATCHER_H
#include "libsaio.h"
#include "SMBIOS.h"
extern EFI_GUID gEfiAcpiTableGuid;
extern EFI_GUID gEfiAcpi20TableGuid;
};
extern struct SMBEntryPoint *getAddressOfSmbiosTable(void);
extern struct SMBEntryPoint *getSmbios(void);
#endif /* !__LIBSAIO_SMBIOS_PATCHER_H */
branches/JrCs/i386/libsaio/mem.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/*
* Copyright 2010 AsereBLN. All rights reserved. <aserebln@googlemail.com>
* Released under version 2 of the Gnu Public License (GPLv2).
*
* mem.c - obtain system memory information
*/
#include "libsaio.h"
#include "pci.h"
#include "platform.h"
#include "cpu.h"
#include "mem.h"
#ifndef DEBUG_MEM
#define DEBUG_MEM 0
#endif
#if DEBUG_MEM
#define DBG(x...)printf(x)
#else
#define DBG(x...)
#endif
void scan_memory(PlatformInfo_t *p)
{
/* NYI */
}
branches/JrCs/i386/libsaio/mem.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*
* Copyright 2010 AsereBLN. All rights reserved. <aserebln@googlemail.com>
* Released under version 2 of the Gnu Public License (GPLv2).
*
* mem.h
*/
#ifndef __LIBSAIO_MEM_H
#define __LIBSAIO_MEM_H
#include "platform.h"
extern void scan_memory(PlatformInfo_t *);
#endif/* __LIBSAIO_MEM_H */
branches/JrCs/i386/libsaio/dsdt_patcher.c
33
44
55
6
67
78
89
......
240241
241242
242243
243
244
244245
245246
246247
247248
248
249
249250
250251
251252
......
356357
357358
358359
359
360
360361
361362
362363
......
365366
366367
367368
368
369
369370
370371
371372
......
387388
388389
389390
391
390392
391393
392394
*/
#include "libsaio.h"
#include "boot.h"
#include "bootstruct.h"
#include "acpi.h"
#include "efi_tables.h"
// Correct the checksum of RSDT
rsdt_mod->Length-=4*dropoffset;
DBG("RSDT Original checksum %d\n", rsdt_mod->Checksum);
DBG("RSDT: Original checksum %d, ", rsdt_mod->Checksum);
rsdt_mod->Checksum=0;
rsdt_mod->Checksum=256-checksum8(rsdt_mod,rsdt_mod->Length);
DBG("RSDT New checksum %d at %x\n", rsdt_mod->Checksum,rsdt_mod);
DBG("New checksum %d at %x\n", rsdt_mod->Checksum,rsdt_mod);
}
else
{
// Correct the checksum of RSDP
DBG("Original checksum %d\n", rsdp_mod->Checksum);
DBG("RSDP: Original checksum %d, ", rsdp_mod->Checksum);
rsdp_mod->Checksum=0;
rsdp_mod->Checksum=256-checksum8(rsdp_mod,20);
if (version)
{
DBG("Original extended checksum %d\n", rsdp_mod->ExtendedChecksum);
DBG("RSDP: Original extended checksum %d", rsdp_mod->ExtendedChecksum);
rsdp_mod->ExtendedChecksum=0;
rsdp_mod->ExtendedChecksum=256-checksum8(rsdp_mod,rsdp_mod->Length);
}
}
#if DEBUG_DSDT
printf("Press a key to continue... (DEBUG_DSDT)\n");
getc();
#endif
return 1;
branches/JrCs/i386/libsaio/platform.c
66
77
88
9
10
11
129
10
11
12
1313
1414
1515
......
2323
2424
2525
26
26
2727
28
29
30
31
32
33
28
29
30
31
32
3433
3534
36
35
3736
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
37
6838
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
39
40
41
9142
92
93
#include "libsaio.h"
#include "bootstruct.h"
#include "pci.h"
#include "freq_detect.h"
#include "nvidia.h"
#include "spd.h"
#include "platform.h"
#include "cpu.h"
#include "mem.h"
#include "spd.h"
#ifndef DEBUG_PLATFORM
#define DEBUG_PLATFORM 0
PlatformInfo_t Platform;
void scan_cpu_amd()
bool platformCPUFeature(uint32_t feature)
{
// AMD
// TODO: Retrieve cpu brand string
// TODO: Retrieve cpu core count
// TODO: Retrieve cpu mobile info
if (Platform.CPU.Features & feature) {
return true;
} else {
return false;
}
}
void scan_cpu_intel()
void scan_platform(void)
{
uint32_tcpuid_reg[4];
// Get Number of cores per package
/*
Initially set the EAX register to 4 and the ECX register to 0 prior to executing the CPUID instruction.
After executing the CPUID instruction, (EAX[31:26] + 1) contains the number of cores.
*/
cpuid_reg[2]=1;
do_cpuid(4, cpuid_reg);
do_cpuid(4, cpuid_reg); // FIXME: why does this only work the 2nd time ?
Platform.CPU.NoCores = bitfield(cpuid_reg[0], 31, 26) + 1;
// Find Number of Concurrent Threads Processed (HyperThreading)
do_cpuid(1,cpuid_reg);
if(bitfield(cpuid_reg[1], 23, 16) > 1)
Platform.CPU.NoThreads=Platform.CPU.NoCores;
else
Platform.CPU.NoThreads=Platform.CPU.NoCores * 2;
// Mobile CPU ?
if (rdmsr64(0x17) & (1<<28))
Platform.CPU.Mobile = 1;
else
Platform.CPU.Mobile = 0;
}
void scan_platform()
{
uint32_tcpuid_reg[4];
memset(&Platform, 0, sizeof(Platform));
build_pci_dt();
calculate_freq();
// Copy the values from calculate_freq()
Platform.CPU.TSCFrequency = tscFrequency;
Platform.CPU.FSBFrequency = fsbFrequency;
Platform.CPU.CPUFrequency = cpuFrequency;
do_cpuid(0, cpuid_reg);
Platform.CPU.Vendor = cpuid_reg[1];
do_cpuid(1, cpuid_reg);
Platform.CPU.Model = bitfield(cpuid_reg[0], 7, 4);
Platform.CPU.Family = bitfield(cpuid_reg[0], 11, 8);
Platform.CPU.ExtModel = bitfield(cpuid_reg[0], 19, 16);
Platform.CPU.ExtFamily = bitfield(cpuid_reg[0], 27, 20);
// Get vendor specific cpu data
if((Platform.CPU.Vendor == 0x756E6547 /* Intel */) && ((Platform.CPU.Family == 0x06) || (Platform.CPU.Family == 0x0f)))
scan_cpu_intel();
else if((Platform.CPU.Vendor == 0x68747541 /* AMD */) && (Platform.CPU.Family == 0x0f))
scan_cpu_amd();
scan_cpu(&Platform);
scan_memory(&Platform);
scan_spd(&Platform);
}
branches/JrCs/i386/libsaio/cpu.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
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
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
/*
* Copyright 2008 Islam Ahmed Zaid. All rights reserved. <azismed@gmail.com>
* AsereBLN: 2009: cleanup and bugfix
*/
#include "libsaio.h"
#include "platform.h"
#include "cpu.h"
#ifndef DEBUG_CPU
#define DEBUG_CPU 0
#endif
#if DEBUG_CPU
#define DBG(x...)printf(x)
#else
#define DBG(x...)
#endif
static inline uint64_t rdtsc64(void)
{
uint64_t ret;
__asm__ volatile("rdtsc" : "=A" (ret));
return ret;
}
static inline uint64_t rdmsr64(uint32_t msr)
{
uint64_t ret;
__asm__ volatile("rdmsr" : "=A" (ret) : "c" (msr));
return ret;
}
static inline void do_cpuid(uint32_t selector, uint32_t *data)
{
asm volatile ("cpuid"
: "=a" (data[0]),
"=b" (data[1]),
"=c" (data[2]),
"=d" (data[3])
: "a" (selector));
}
static inline void do_cpuid2(uint32_t selector, uint32_t selector2, uint32_t *data)
{
asm volatile ("cpuid"
: "=a" (data[0]),
"=b" (data[1]),
"=c" (data[2]),
"=d" (data[3])
: "a" (selector), "c" (selector2));
}
// DFE: enable_PIT2 and disable_PIT2 come from older xnu
/*
* Enable or disable timer 2.
* Port 0x61 controls timer 2:
* bit 0 gates the clock,
* bit 1 gates output to speaker.
*/
static inline void enable_PIT2(void)
{
/* Enable gate, disable speaker */
__asm__ volatile(
" inb $0x61,%%al \n\t"
" and $0xFC,%%al \n\t" /* & ~0x03 */
" or $1,%%al \n\t"
" outb %%al,$0x61 \n\t"
: : : "%al" );
}
static inline void disable_PIT2(void)
{
/* Disable gate and output to speaker */
__asm__ volatile(
" inb $0x61,%%al \n\t"
" and $0xFC,%%al \n\t"/* & ~0x03 */
" outb %%al,$0x61 \n\t"
: : : "%al" );
}
// DFE: set_PIT2_mode0, poll_PIT2_gate, and measure_tsc_frequency are
// roughly based on Linux code
/* Set the 8254 channel 2 to mode 0 with the specified value.
In mode 0, the counter will initially set its gate low when the
timer expires. For this to be useful, you ought to set it high
before calling this function. The enable_PIT2 function does this.
*/
static inline void set_PIT2_mode0(uint16_t value)
{
__asm__ volatile(
" movb $0xB0,%%al \n\t"
" outb%%al,$0x43\n\t"
" movb%%dl,%%al\n\t"
" outb%%al,$0x42\n\t"
" movb%%dh,%%al\n\t"
" outb%%al,$0x42"
: : "d"(value) /*: no clobber */ );
}
/* Returns the number of times the loop ran before the PIT2 signaled */
static inline unsigned long poll_PIT2_gate(void)
{
unsigned long count = 0;
unsigned char nmi_sc_val;
do {
++count;
__asm__ volatile(
"inb$0x61,%0"
: "=q"(nmi_sc_val) /*:*/ /* no input */ /*:*/ /* no clobber */);
} while( (nmi_sc_val & 0x20) == 0);
return count;
}
/*
* DFE: Measures the TSC frequency in Hz (64-bit) using the ACPI PM timer
*/
static uint64_t measure_tsc_frequency(void)
{
uint64_t tscStart;
uint64_t tscEnd;
uint64_t tscDelta = 0xffffffffffffffffULL;
unsigned long pollCount;
uint64_t retval = 0;
int i;
/* Time how many TSC ticks elapse in 30 msec using the 8254 PIT
* counter 2. We run this loop 3 times to make sure the cache
* is hot and we take the minimum delta from all of the runs.
* That is to say that we're biased towards measuring the minimum
* number of TSC ticks that occur while waiting for the timer to
* expire. That theoretically helps avoid inconsistencies when
* running under a VM if the TSC is not virtualized and the host
* steals time. The TSC is normally virtualized for VMware.
*/
for(i = 0; i < 10; ++i)
{
enable_PIT2();
set_PIT2_mode0(CALIBRATE_LATCH);
tscStart = rdtsc64();
pollCount = poll_PIT2_gate();
tscEnd = rdtsc64();
/* The poll loop must have run at least a few times for accuracy */
if(pollCount <= 1)
continue;
/* The TSC must increment at LEAST once every millisecond. We
* should have waited exactly 30 msec so the TSC delta should
* be >= 30. Anything less and the processor is way too slow.
*/
if((tscEnd - tscStart) <= CALIBRATE_TIME_MSEC)
continue;
// tscDelta = min(tscDelta, (tscEnd - tscStart))
if( (tscEnd - tscStart) < tscDelta )
tscDelta = tscEnd - tscStart;
}
/* tscDelta is now the least number of TSC ticks the processor made in
* a timespan of 0.03 s (e.g. 30 milliseconds)
* Linux thus divides by 30 which gives the answer in kiloHertz because
* 1 / ms = kHz. But we're xnu and most of the rest of the code uses
* Hz so we need to convert our milliseconds to seconds. Since we're
* dividing by the milliseconds, we simply multiply by 1000.
*/
/* Unlike linux, we're not limited to 32-bit, but we do need to take care
* that we're going to multiply by 1000 first so we do need at least some
* arithmetic headroom. For now, 32-bit should be enough.
* Also unlike Linux, our compiler can do 64-bit integer arithmetic.
*/
if(tscDelta > (1ULL<<32))
retval = 0;
else
{
retval = tscDelta * 1000 / 30;
}
disable_PIT2();
return retval;
}
/*
* Calculates the FSB and CPU frequencies using specific MSRs for each CPU
* - multi. is read from a specific MSR. In the case of Intel, there is:
* a max multi. (used to calculate the FSB freq.),
* and a current multi. (used to calculate the CPU freq.)
* - fsbFrequency = tscFrequency / multi
* - cpuFrequency = fsbFrequency * multi
*/
void scan_cpu(PlatformInfo_t *p)
{
uint64_ttscFrequency, fsbFrequency, cpuFrequency;
uint64_tmsr, flex_ratio;
uint8_tmaxcoef, maxdiv, currcoef, currdiv;
maxcoef = maxdiv = currcoef = currdiv = 0;
/* get cpuid values */
do_cpuid(0x00000000, p->CPU.CPUID[CPUID_0]);
do_cpuid(0x00000001, p->CPU.CPUID[CPUID_1]);
do_cpuid(0x00000002, p->CPU.CPUID[CPUID_2]);
do_cpuid(0x00000003, p->CPU.CPUID[CPUID_3]);
do_cpuid2(0x00000004, 0, p->CPU.CPUID[CPUID_4]);
do_cpuid(0x80000000, p->CPU.CPUID[CPUID_80]);
if ((p->CPU.CPUID[CPUID_80][0] & 0x0000000f) >= 1) {
do_cpuid(0x80000001, p->CPU.CPUID[CPUID_81]);
}
#if DEBUG_CPU
{
inti;
printf("CPUID Raw Values:\n");
for (i=0; i<CPUID_MAX; i++) {
printf("%02d: %08x-%08x-%08x-%08x\n", i,
p->CPU.CPUID[i][0], p->CPU.CPUID[i][1],
p->CPU.CPUID[i][2], p->CPU.CPUID[i][3]);
}
}
#endif
p->CPU.Vendor= p->CPU.CPUID[CPUID_0][1];
p->CPU.Model= bitfield(p->CPU.CPUID[CPUID_1][0], 7, 4);
p->CPU.Family= bitfield(p->CPU.CPUID[CPUID_1][0], 11, 8);
p->CPU.ExtModel= bitfield(p->CPU.CPUID[CPUID_1][0], 19, 16);
p->CPU.ExtFamily= bitfield(p->CPU.CPUID[CPUID_1][0], 27, 20);
p->CPU.NoThreads= bitfield(p->CPU.CPUID[CPUID_1][1], 23, 16);
p->CPU.NoCores= bitfield(p->CPU.CPUID[CPUID_4][0], 31, 26) + 1;
p->CPU.Model += (p->CPU.ExtModel << 4);
/* setup features */
if ((bit(23) & p->CPU.CPUID[CPUID_1][3]) != 0) {
p->CPU.Features |= CPU_FEATURE_MMX;
}
if ((bit(25) & p->CPU.CPUID[CPUID_1][3]) != 0) {
p->CPU.Features |= CPU_FEATURE_SSE;
}
if ((bit(26) & p->CPU.CPUID[CPUID_1][3]) != 0) {
p->CPU.Features |= CPU_FEATURE_SSE2;
}
if ((bit(0) & p->CPU.CPUID[CPUID_1][2]) != 0) {
p->CPU.Features |= CPU_FEATURE_SSE3;
}
if ((bit(19) & p->CPU.CPUID[CPUID_1][2]) != 0) {
p->CPU.Features |= CPU_FEATURE_SSE41;
}
if ((bit(20) & p->CPU.CPUID[CPUID_1][2]) != 0) {
p->CPU.Features |= CPU_FEATURE_SSE42;
}
if ((bit(29) & p->CPU.CPUID[CPUID_81][3]) != 0) {
p->CPU.Features |= CPU_FEATURE_EM64T;
}
//if ((bit(28) & p->CPU.CPUID[CPUID_1][3]) != 0) {
if (p->CPU.NoThreads > p->CPU.NoCores) {
p->CPU.Features |= CPU_FEATURE_HTT;
}
tscFrequency = measure_tsc_frequency();
fsbFrequency = 0;
cpuFrequency = 0;
if ((p->CPU.Vendor == 0x756E6547 /* Intel */) && ((p->CPU.Family == 0x06) || (p->CPU.Family == 0x0f))) {
if ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0c) || (p->CPU.Family == 0x0f && p->CPU.Model >= 0x03)) {
/* Nehalem CPU model */
if (p->CPU.Family == 0x06 && (p->CPU.Model == 0x1a || p->CPU.Model == 0x1e)) {
msr = rdmsr64(MSR_PLATFORM_INFO);
DBG("msr(%d): platform_info %08x\n", __LINE__, msr & 0xffffffff);
currcoef = (msr >> 8) & 0xff;
msr = rdmsr64(MSR_FLEX_RATIO);
DBG("msr(%d): flex_ratio %08x\n", __LINE__, msr & 0xffffffff);
if ((msr >> 16) & 0x01) {
flex_ratio = (msr >> 8) & 0xff;
if (currcoef > flex_ratio) {
currcoef = flex_ratio;
}
}
if (currcoef) {
fsbFrequency = (tscFrequency / currcoef);
}
cpuFrequency = tscFrequency;
} else {
msr = rdmsr64(IA32_PERF_STATUS);
DBG("msr(%d): ia32_perf_stat 0x%08x\n", __LINE__, msr & 0xffffffff);
currcoef = (msr >> 8) & 0x1f;
/* Non-integer bus ratio for the max-multi*/
maxdiv = (msr >> 46) & 0x01;
/* Non-integer bus ratio for the current-multi (undocumented)*/
currdiv = (msr >> 14) & 0x01;
if ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0e) || (p->CPU.Family == 0x0f)) // This will always be model >= 3
{
/* On these models, maxcoef defines TSC freq */
maxcoef = (msr >> 40) & 0x1f;
} else {
/* On lower models, currcoef defines TSC freq */
/* XXX */
maxcoef = currcoef;
}
if (maxcoef) {
if (maxdiv) {
fsbFrequency = ((tscFrequency * 2) / ((maxcoef * 2) + 1));
} else {
fsbFrequency = (tscFrequency / maxcoef);
}
if (currdiv) {
cpuFrequency = (fsbFrequency * ((currcoef * 2) + 1) / 2);
} else {
cpuFrequency = (fsbFrequency * currcoef);
}
DBG("max: %d%s current: %d%s\n", maxcoef, maxdiv ? ".5" : "",currcoef, currdiv ? ".5" : "");
}
}
}
/* Mobile CPU ? */
if (rdmsr64(0x17) & (1<<28)) {
p->CPU.Features |= CPU_FEATURE_MOBILE;
}
}
#if 0
else if((p->CPU.Vendor == 0x68747541 /* AMD */) && (p->CPU.Family == 0x0f)) {
if(p->CPU.ExtFamily == 0x00 /* K8 */) {
msr = rdmsr64(K8_FIDVID_STATUS);
currcoef = (msr & 0x3f) / 2 + 4;
currdiv = (msr & 0x01) * 2;
} else if(p->CPU.ExtFamily >= 0x01 /* K10+ */) {
msr = rdmsr64(K10_COFVID_STATUS);
if(p->CPU.ExtFamily == 0x01 /* K10 */)
currcoef = (msr & 0x3f) + 0x10;
else /* K11+ */
currcoef = (msr & 0x3f) + 0x08;
currdiv = (2 << ((msr >> 6) & 0x07));
}
if (currcoef) {
if (currdiv) {
fsbFrequency = ((tscFrequency * currdiv) / currcoef);
DBG("%d.%d\n", currcoef / currdiv, ((currcoef % currdiv) * 100) / currdiv);
} else {
fsbFrequency = (tscFrequency / currcoef);
DBG("%d\n", currcoef);
}
fsbFrequency = (tscFrequency / currcoef);
cpuFrequency = tscFrequency;
}
}
if (!fsbFrequency) {
fsbFrequency = (DEFAULT_FSB * 1000);
cpuFrequency = tscFrequency;
DBG("0 ! using the default value for FSB !\n");
}
#endif
p->CPU.MaxCoef = maxcoef;
p->CPU.MaxDiv = maxdiv;
p->CPU.CurrCoef = currcoef;
p->CPU.CurrDiv = currdiv;
p->CPU.TSCFrequency = tscFrequency;
p->CPU.FSBFrequency = fsbFrequency;
p->CPU.CPUFrequency = cpuFrequency;
#if DEBUG_CPU
DBG("CPU: Vendor/Model/ExtModel: 0x%x/0x%x/0x%x\n", p->CPU.Vendor, p->CPU.Model, p->CPU.ExtModel);
DBG("CPU: Family/ExtFamily: 0x%x/0x%x\n", p->CPU.Family, p->CPU.ExtFamily);
DBG("CPU: MaxCoef/CurrCoef: 0x%x/0x%x\n", p->CPU.MaxCoef, p->CPU.CurrCoef);
DBG("CPU: MaxDiv/CurrDiv: 0x%x/0x%x\n", p->CPU.MaxDiv, p->CPU.CurrDiv);
DBG("CPU: TSCFreq: %dMHz\n", p->CPU.TSCFrequency / 1000000);
DBG("CPU: FSBFreq: %dMHz\n", p->CPU.FSBFrequency / 1000000);
DBG("CPU: CPUFreq: %dMHz\n", p->CPU.CPUFrequency / 1000000);
DBG("CPU: NoCores/NoThreads: %d/%d\n", p->CPU.NoCores, p->CPU.NoThreads);
DBG("CPU: Features: 0x%08x\n", p->CPU.Features);
printf("Press a key to continue... (DEBUG_CPU)\n");
getc();
#endif
}
branches/JrCs/i386/libsaio/platform.h
88
99
1010
11
12
13
11
12
1413
15
14
15
16
17
18
19
20
21
22
1623
24
25
26
27
28
29
30
31
32
33
34
1735
1836
1937
......
4563
4664
4765
48
66
4967
68
69
70
5071
51
52
53
72
73
74
75
76
77
78
5479
5580
5681
57
58
59
60
61
6282
63
64
65
66
67
68
69
70
83
84
85
86
87
88
89
90
91
7192
7293
7394
74
75
76
77
78
79
80
95
96
97
98
99
81100
82101
83
84
85
86
87
88
89
90
91
92
93
102
103
104
94105
95106
96107
#include "libsaio.h"
#define bit(n)(1ULL << (n))
#define bitmask(h,l)((bit(h)|(bit(h)-1)) & ~(bit(l)-1))
#define bitfield(x,h,l)(((x) & bitmask(h,l)) >> l)
extern bool platformCPUFeature(uint32_t);
extern void scan_platform(void);
extern void scan_platform();
/* CPUID index into cpuid_raw */
#define CPUID_00
#define CPUID_11
#define CPUID_22
#define CPUID_33
#define CPUID_44
#define CPUID_805
#define CPUID_816
#define CPUID_MAX7
/* CPU Features */
#define CPU_FEATURE_MMX0x00000001// MMX Instruction Set
#define CPU_FEATURE_SSE0x00000002// SSE Instruction Set
#define CPU_FEATURE_SSE20x00000004// SSE2 Instruction Set
#define CPU_FEATURE_SSE30x00000008// SSE3 Instruction Set
#define CPU_FEATURE_SSE410x00000010// SSE41 Instruction Set
#define CPU_FEATURE_SSE420x00000020// SSE42 Instruction Set
#define CPU_FEATURE_EM64T0x00000040// 64Bit Support
#define CPU_FEATURE_HTT0x00000080// HyperThreading
#define CPU_FEATURE_MOBILE0x00000100// Mobile CPU
/* SMBIOS Memory Types */
#define SMB_MEM_TYPE_UNDEFINED0
#define SMB_MEM_TYPE_OTHER1
#define SMB_MEM_CHANNEL_TRIPLE3
/* Maximum number of ram slots */
#defineMAX_RAM_SLOTS16
#define MAX_RAM_SLOTS8
/* Maximum number of SPD bytes */
#define MAX_SPD_SIZE256
typedef struct _RamSlotInfo_t {
boolInUse;// Module Present
uint32_tModuleSize;// Size of Module in MB
char*spd;// SPD Dump
boolInUse;
uint32_tModuleSize;// Size of Module in MB
uint8_tType;
charVendor[64];
charPartNo[64];
charSerialNo[16];
uint8_tspd[MAX_SPD_SIZE];
} RamSlotInfo_t;
typedef struct _PlatformInfo_t {
boolMobile;// Mobile Platform
boolx86_64;// 64 Bit Capable
struct PCI {
uint8_tNoDevices;// No of PCI devices
} PCI;
struct CPU {
uint32_tVendor;// Vendor
uint32_tModel;// Model
uint32_tExtModel;// Extended Model
uint32_tFamily;// Family
uint32_tExtFamily;// Extended Family
uint8_tNoCores;// No Cores per Package
uint8_tNoThreads;// Threads per Package
uint8_tMaxCoef;// Max Multiplier
uint32_tFeatures;// CPU Features like MMX, SSE2, VT, MobileCPU
uint32_tVendor;// Vendor
uint32_tModel;// Model
uint32_tExtModel;// Extended Model
uint32_tFamily;// Family
uint32_tExtFamily;// Extended Family
uint32_tNoCores;// No Cores per Package
uint32_tNoThreads;// Threads per Package
uint8_tMaxCoef;// Max Multiplier
uint8_tMaxDiv;
uint8_tCurrCoef;// Current Multiplier
uint8_tCurrDiv;
floatMaxRatio;
floatCurrRatio;
uint64_tTSCFrequency;// TSC Frequency Hz
uint64_tFSBFrequency;// FSB Frequency Hz
uint64_tCPUFrequency;// CPU Frequency Hz
boolMobile;// Mobile CPU
uint32_tBrandString[16];// 48 Byte Branding String
uint64_tTSCFrequency;// TSC Frequency Hz
uint64_tFSBFrequency;// FSB Frequency Hz
uint64_tCPUFrequency;// CPU Frequency Hz
uint32_tBrandString[16];// 48 Byte Branding String
uint32_tCPUID[CPUID_MAX][4];// CPUID 0..4, 80..81 Raw Values
} CPU;
struct RAM {
uint64_tFrequency;// Ram Frequency
uint32_tDivider;// Memory divider
floatCAS;// CAS 1/2/2.5/3/4/5/6/7
uint8_tTRC;
uint8_tTRP;
uint8_tRAS;
uint8_tChannels;// Channel Configuration Single,Dual or Triple
uint8_tNoSlots;// Maximum no of slots available
uint8_tType;// Standard SMBIOS v2.5 Memory Type
char*BrandString;// Branding String Memory Controller
RamSlotInfo_tDIMM[MAX_RAM_SLOTS];// Information about each slot
RamSlotInfo_tDIMM[MAX_RAM_SLOTS];// Information about each slot
uint64_tFrequency;// Ram Frequency
//uint8_tType;// Standard SMBIOS v2.5 Memory Type
} RAM;
} PlatformInfo_t;
branches/JrCs/i386/libsaio/cpu.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/*
* Copyright 2008 Islam Ahmed Zaid. All rights reserved. <azismed@gmail.com>
* AsereBLN: 2009: cleanup and bugfix
*/
#ifndef __LIBSAIO_CPU_H
#define __LIBSAIO_CPU_H
#include "libsaio.h"
extern void scan_cpu(PlatformInfo_t *);
#define bit(n)(1UL << (n))
#define bitmask(h,l)((bit(h)|(bit(h)-1)) & ~(bit(l)-1))
#define bitfield(x,h,l)(((x) & bitmask(h,l)) >> l)
#defineIA32_PERF_STATUS0x198
#define MSR_FLEX_RATIO0x194
#defineMSR_PLATFORM_INFO0xCE
#define K8_FIDVID_STATUS0xC0010042
#define K10_COFVID_STATUS0xC0010071
#define DEFAULT_FSB100000 /* for now, hardcoding 100MHz for old CPUs */
// DFE: This constant comes from older xnu:
#define CLKNUM1193182/* formerly 1193167 */
// DFE: These two constants come from Linux except CLOCK_TICK_RATE replaced with CLKNUM
#define CALIBRATE_TIME_MSEC30/* 30 msecs */
#define CALIBRATE_LATCH((CLKNUM * CALIBRATE_TIME_MSEC + 1000/2)/1000)
#endif /* !__LIBSAIO_CPU_H */
branches/JrCs/i386/libsaio/fake_efi.c
33
44
55
6
67
78
89
910
1011
11
12
1213
1314
1415
1516
1617
1718
18
1919
2020
2121
......
320320
321321
322322
323
324323
325324
326325
......
366365
367366
368367
369
370
368
369
371370
372
373
374
375371
376372
377
378
379
380
373
374
375
376
381377
382378
383379
*/
#include "libsaio.h"
#include "boot.h"
#include "bootstruct.h" /* for bootArgs */
#include "efi.h"
#include "acpi.h"
#include "fake_efi.h"
#include "efi_tables.h"
#include "freq_detect.h"
#include "platform.h"
#include "dsdt_patcher.h"
#include "smbios_patcher.h"
#include "device_inject.h"
#include "pci.h"
#include "sl.h"
extern struct SMBEntryPoint * getSmbios();
extern void setup_pci_devs(pci_dt_t *pci_dt);
/*
static char FIRMWARE_ABI_PROP[] = "firmware-abi";
static char FIRMWARE_VENDOR_PROP[] = "firmware-vendor";
static char FIRMWARE_ABI_PROP_VALUE[] = "EFI64";
static char SYSTEM_ID_PROP[] = "system-id";
void
setupEfiDeviceTree(void)
* the value in the fsbFrequency global and not an malloc'd pointer
* because the DT_AddProperty function does not copy its args.
*/
if(fsbFrequency != 0)
DT__AddProperty(efiPlatformNode, FSB_Frequency_prop, sizeof(uint64_t), &fsbFrequency);
if(Platform.CPU.FSBFrequency != 0)
DT__AddProperty(efiPlatformNode, FSB_Frequency_prop, sizeof(uint64_t), &Platform.CPU.FSBFrequency);
// unable to determine UUID for host. Error: 35 fix
DT__AddProperty(efiPlatformNode, SYSTEM_ID_PROP, sizeof(SYSTEM_ID), (EFI_UINT32*)&SYSTEM_ID);
/* Export TSC and CPU frequencies for use by the kernel or KEXTs
*/
if(tscFrequency != 0)
DT__AddProperty(efiPlatformNode, TSC_Frequency_prop, sizeof(uint64_t), &tscFrequency);
if(cpuFrequency != 0)
DT__AddProperty(efiPlatformNode, CPU_Frequency_prop, sizeof(uint64_t), &cpuFrequency);
if(Platform.CPU.TSCFrequency != 0)
DT__AddProperty(efiPlatformNode, TSC_Frequency_prop, sizeof(uint64_t), &Platform.CPU.TSCFrequency);
if(Platform.CPU.CPUFrequency != 0)
DT__AddProperty(efiPlatformNode, CPU_Frequency_prop, sizeof(uint64_t), &Platform.CPU.CPUFrequency);
/* Fill /efi/device-properties node.
*/

Archive Download the corresponding diff file

Revision: 15