Chameleon

Chameleon Svn Source Tree

Root/branches/Bungo/i386/libsaio/acpi_patcher.c

1/*
2 * Copyright 2008 mackerintel
3 * 2010 mojodojo,
4 * 2012 slice
5 */
6
7#include "libsaio.h"
8#include "boot.h"
9#include "bootstruct.h"
10#include "acpi.h"
11#include "efi_tables.h"
12#include "fake_efi.h"
13#include "acpi_patcher.h"
14#include "platform.h"
15#include "cpu.h"
16#include "aml_generator.h"
17
18#ifndef DEBUG_ACPI
19#define DEBUG_ACPI 0
20#endif
21
22#if DEBUG_ACPI==2
23#define DBG(x...) {printf(x); sleep(1);}
24#elif DEBUG_ACPI==1
25#define DBG(x...) printf(x)
26#else
27#define DBG(x...) msglog(x)
28#endif
29
30// Slice: New signature compare function
31boolean_t tableSign(void *table, const char *sgn)
32{
33int i;
34for (i = 0; i < 4; i++)
35{
36if ((((char *)table)[i] & ~0x20) != (sgn[i] & ~0x20))
37{
38return false;
39}
40}
41return true;
42}
43
44uint32_t EBDA_RANGE_START = EBDA_RANGE_MIN;
45
46uint64_t acpi10_p = 0;
47uint64_t acpi20_p = 0;
48
49/* Gets the ACPI 1.0 RSDP address */
50static struct acpi_2_rsdp* getAddressOfAcpiTable()
51{
52 /* Before searching the BIOS space we are supposed to search the first 1K of the EBDA */
53 EBDA_RANGE_START = /* (uint32_t)swapUint16(*(uint16_t *)BDA_EBDA_START) << 4 */ EBDA_RANGE_MIN;
54 DBG("ACPI: scanning EBDA [%08X-%08X] for RSDP 1.0... ", EBDA_RANGE_START, EBDA_RANGE_END);
55 void *acpi_addr = (void*)EBDA_RANGE_START;
56for (; acpi_addr < (void*)EBDA_RANGE_END; acpi_addr++) {
57if (*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE) {
58 break;
59}
60}
61
62 if (acpi_addr >= (void*)EBDA_RANGE_END) {
63 DBG("Nothing found.\n");
64 DBG("ACPI: scanning BIOS area [%08X-%08X] for RSDP 1.0...\n", ACPI_RANGE_START, ACPI_RANGE_END);
65 acpi_addr = (void*)ACPI_RANGE_START;
66 for (; acpi_addr < (void*)ACPI_RANGE_END; acpi_addr += 16) {
67 if (*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE) {
68 break;
69 }
70 }
71 } else {
72 DBG("\n");
73 }
74
75 uint8_t csum = checksum8(acpi_addr, 20);
76
77 if (csum == 0) {
78 // Only return the table if it is a true version 1.0 table (Revision 0)
79 if(((struct acpi_2_rsdp*)acpi_addr)->Revision == 0) {
80 return acpi_addr;
81 }
82 }
83
84return NULL;
85}
86
87/* Gets the ACPI 2.0 RSDP address */
88static struct acpi_2_rsdp* getAddressOfAcpi20Table()
89{
90 /* Before searching the BIOS space we are supposed to search the first 1K of the EBDA */
91EBDA_RANGE_START = /* (uint32_t)swapUint16(*(uint16_t *)BDA_EBDA_START) << 4 */ EBDA_RANGE_MIN;
92 DBG("ACPI: scanning EBDA [%08X-%08X] for RSDP 2.0... ", EBDA_RANGE_START, EBDA_RANGE_END);
93 void *acpi_addr = (void *)EBDA_RANGE_START;
94for (; acpi_addr < (void *)EBDA_RANGE_END; acpi_addr++) {
95if (*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE) {
96 break;
97}
98}
99
100 if (acpi_addr >= (void *)EBDA_RANGE_END) {
101 DBG("Nothing found.\n");
102 DBG("ACPI: scanning BIOS area [%08X-%08X] for RSDP 2.0...\n", ACPI_RANGE_START, ACPI_RANGE_END);
103 acpi_addr = (void *)ACPI_RANGE_START;
104 for (; acpi_addr <= (void *)ACPI_RANGE_END; acpi_addr += 16) {
105 if(*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE) {
106 break;
107 }
108 }
109 } else {
110 DBG("\n");
111 }
112
113 uint8_t csum = checksum8(acpi_addr, 20);
114
115 /* Only assume this is a 2.0 or better table if the revision is greater than 0
116 * NOTE: ACPI 3.0 spec only seems to say that 1.0 tables have revision 1
117 * and that the current revision is 2.. I am going to assume that rev > 0 is 2.0.
118 */
119
120 if(csum == 0 && (((struct acpi_2_rsdp*)acpi_addr)->Revision > 0)) {
121 uint8_t csum2 = checksum8(acpi_addr, sizeof(struct acpi_2_rsdp));
122 if(csum2 == 0) {
123 return acpi_addr;
124 }
125 }
126
127return NULL;
128}
129
130/* The folowing ACPI Table search algo. should be reused anywhere needed:*/
131/* WARNING: outDirspec string will be overwritten by subsequent calls! */
132int search_and_get_acpi_fd(const char * filename, const char ** outDirspec)
133{
134int fd = 0;
135static char dirSpec[512];
136
137// Try finding 'filename' in the usual places
138// Start searching any potential location for ACPI Table
139 snprintf(dirSpec, sizeof(dirSpec), "%s", filename);
140 fd = open(dirSpec, 0);
141if (fd < 0) {
142snprintf(dirSpec, sizeof(dirSpec), "/Extra/%s", filename);
143fd = open(dirSpec, 0);
144if (fd < 0) {
145 snprintf(dirSpec, sizeof(dirSpec), "/Extra/ACPI/%s", filename);
146 fd = open(dirSpec, 0);
147 if (fd < 0) {
148 snprintf(dirSpec, sizeof(dirSpec), "bt(0,0)/Extra/%s", filename);
149 fd = open(dirSpec, 0);
150 if (fd < 0) {
151 snprintf(dirSpec, sizeof(dirSpec), "bt(0,0)/Extra/ACPI/%s", filename);
152 fd = open(dirSpec, 0);
153 if (fd < 0) {
154 // NOT FOUND:
155 dirSpec[0] = 0;
156 }
157 }
158}
159}
160}
161
162if (outDirspec) *outDirspec = dirSpec;
163return fd;
164}
165
166void *loadACPITable (const char * filename)
167{
168void *tableAddr;
169const char * dirspec=NULL;
170
171int fd = search_and_get_acpi_fd(filename, &dirspec);
172
173if (fd>=0)
174{
175tableAddr=(void*)AllocateKernelMemory(file_size (fd));
176if (tableAddr)
177{
178if (read (fd, tableAddr, file_size (fd))!=file_size (fd))
179{
180DBG("ACPI: Couldn't read table from '%s'\n", dirspec);
181free (tableAddr);
182close (fd);
183return NULL;
184}
185DBG("ACPI: Table %s read and stored at: 0x%x\n", dirspec, tableAddr);
186close (fd);
187return tableAddr;
188}
189close (fd);
190DBG("ACPI: Couldn't allocate memory for table '%s'\n", dirspec);
191 }
192
193return NULL;
194}
195
196uint8_tacpi_cpu_count = 0;
197char* acpi_cpu_name[32];
198uint32_t acpi_cpu_p_blk = 0;
199
200void get_acpi_cpu_names(unsigned char* dsdt, uint32_t length)
201{
202uint32_t i;
203
204DBG("ACPI: start finding cpu names. Length %d\n", length);
205
206for (i=0; i<length-7; i++)
207{
208if (dsdt[i] == 0x5B && dsdt[i+1] == 0x83) // ProcessorOP
209{
210DBG("ACPI: DSDT[%x%x]\n", dsdt[i], dsdt[i+1]);
211
212uint32_t offset = i + 3 + (dsdt[i+2] >> 6);
213
214bool add_name = true;
215
216uint8_t j;
217
218for (j=0; j<4; j++)
219{
220char c = dsdt[offset+j];
221
222if (!aml_isvalidchar(c))
223{
224add_name = false;
225DBG("ACPI: invalid character found in ProcessorOP 0x%x!\n", c);
226break;
227}
228}
229
230if (add_name)
231{
232acpi_cpu_name[acpi_cpu_count] = malloc(4);
233memcpy(acpi_cpu_name[acpi_cpu_count], dsdt+offset, 4);
234i = offset + 5;
235
236if (acpi_cpu_count == 0)
237acpi_cpu_p_blk = dsdt[i] | (dsdt[i+1] << 8);
238
239DBG("ACPI: found ACPI CPU [%c%c%c%c]\n", acpi_cpu_name[acpi_cpu_count][0], acpi_cpu_name[acpi_cpu_count][1], acpi_cpu_name[acpi_cpu_count][2], acpi_cpu_name[acpi_cpu_count][3]);
240
241if (++acpi_cpu_count == 32) {
242return;
243}
244}
245}
246}
247
248DBG("ACPI: finished finding cpu names. Found: %d.\n", acpi_cpu_count);
249}
250
251struct acpi_2_ssdt *generate_cst_ssdt(struct acpi_2_fadt* fadt)
252{
253char ssdt_header[] = // cst_ssdt_header
254{
2550x53, 0x53, 0x44, 0x54, 0xE7, 0x00, 0x00, 0x00, /* SSDT.... */
2560x01, 0x17, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x41, /* ..PmRefA */
2570x43, 0x70, 0x75, 0x43, 0x73, 0x74, 0x00, 0x00, /* CpuCst.. */
2580x00, 0x10, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* ....INTL */
2590x31, 0x03, 0x10, 0x20/* 1.._*/
260};
261
262char resource_template_register_fixedhw[] =
263{
2640x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00, 0x7F,
2650x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2660x00, 0x00, 0x01, 0x79, 0x00
267};
268
269char resource_template_register_systemio[] =
270{
2710x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00, 0x01,
2720x08, 0x00, 0x00, 0x15, 0x04, 0x00, 0x00, 0x00,
2730x00, 0x00, 0x00, 0x79, 0x00,
274};
275
276if (Platform.CPU.Vendor != 0x756E6547) {
277DBG("ACPI: not an Intel platform, C-States will not be generated!\n");
278return NULL;
279}
280
281if (fadt == NULL) {
282DBG("ACPI: FACP not exists, C-States will not be generated!\n");
283return NULL;
284}
285
286struct acpi_2_dsdt* dsdt = (void*)fadt->DSDT;
287
288if (dsdt == NULL) {
289DBG("ACPI: DSDT not found, C-States will not be generated!\n");
290return NULL;
291}
292
293if (acpi_cpu_count == 0)
294get_acpi_cpu_names((void*)dsdt, dsdt->Length);
295
296if (acpi_cpu_count > 0)
297{
298bool c2_enabled = false;
299bool c3_enabled = false;
300bool c4_enabled = false;
301bool cst_using_systemio = false;
302
303getBoolForKey(kEnableC2State, &c2_enabled, &bootInfo->chameleonConfig);
304getBoolForKey(kEnableC3State, &c3_enabled, &bootInfo->chameleonConfig);
305getBoolForKey(kEnableC4State, &c4_enabled, &bootInfo->chameleonConfig);
306getBoolForKey(kCSTUsingSystemIO, &cst_using_systemio, &bootInfo->chameleonConfig);
307
308c2_enabled = c2_enabled | (fadt->C2_Latency < 100);
309c3_enabled = c3_enabled | (fadt->C3_Latency < 1000);
310
311unsigned char cstates_count = 1 + (c2_enabled ? 1 : 0) + (c3_enabled ? 1 : 0);
312
313AML_CHUNK* root = aml_create_node(NULL);
314aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header
315AML_CHUNK* scop = aml_add_scope(root, "\\_PR_");
316AML_CHUNK* name = aml_add_name(scop, "CST_");
317AML_CHUNK* pack = aml_add_package(name);
318aml_add_byte(pack, cstates_count);
319
320AML_CHUNK* tmpl = aml_add_package(pack);
321if (cst_using_systemio) {
322// C1
323resource_template_register_fixedhw[8] = 0x00;
324resource_template_register_fixedhw[9] = 0x00;
325resource_template_register_fixedhw[18] = 0x00;
326aml_add_buffer(tmpl, resource_template_register_fixedhw, sizeof(resource_template_register_fixedhw));
327aml_add_byte(tmpl, 0x01);// C1
328aml_add_word(tmpl, 0x0001);// Latency
329aml_add_dword(tmpl, 0x000003e8);// Power
330
331uint8_t p_blk_lo, p_blk_hi;
332
333if (c2_enabled) // C2
334{
335p_blk_lo = acpi_cpu_p_blk + 4;
336p_blk_hi = (acpi_cpu_p_blk + 4) >> 8;
337
338tmpl = aml_add_package(pack);
339resource_template_register_systemio[11] = p_blk_lo; // C2
340resource_template_register_systemio[12] = p_blk_hi; // C2
341aml_add_buffer(tmpl, resource_template_register_systemio, sizeof(resource_template_register_systemio));
342aml_add_byte(tmpl, 0x02);// C2
343aml_add_word(tmpl, 0x0040);// Latency
344aml_add_dword(tmpl, 0x000001f4);// Power
345}
346
347if (c4_enabled) // C4
348{
349p_blk_lo = acpi_cpu_p_blk + 5;
350p_blk_hi = (acpi_cpu_p_blk + 5) >> 8;
351
352tmpl = aml_add_package(pack);
353resource_template_register_systemio[11] = p_blk_lo; // C4
354resource_template_register_systemio[12] = p_blk_hi; // C4
355aml_add_buffer(tmpl, resource_template_register_systemio, sizeof(resource_template_register_systemio));
356aml_add_byte(tmpl, 0x04);// C4
357aml_add_word(tmpl, 0x0080);// Latency
358aml_add_dword(tmpl, 0x000000C8);// Power
359}
360else if (c3_enabled) // C3
361{
362p_blk_lo = acpi_cpu_p_blk + 5;
363p_blk_hi = (acpi_cpu_p_blk + 5) >> 8;
364
365tmpl = aml_add_package(pack);
366resource_template_register_systemio[11] = p_blk_lo; // C3
367resource_template_register_systemio[12] = p_blk_hi; // C3
368aml_add_buffer(tmpl, resource_template_register_systemio, sizeof(resource_template_register_systemio));
369aml_add_byte(tmpl, 0x03);// C3
370aml_add_word(tmpl, 0x0060);// Latency
371aml_add_dword(tmpl, 0x0000015e);// Power
372}
373}
374else
375{
376// C1
377resource_template_register_fixedhw[11] = 0x00; // C1
378aml_add_buffer(tmpl, resource_template_register_fixedhw, sizeof(resource_template_register_fixedhw));
379aml_add_byte(tmpl, 0x01);// C1
380aml_add_word(tmpl, 0x0001);// Latency
381aml_add_dword(tmpl, 0x000003e8);// Power
382
383resource_template_register_fixedhw[18] = 0x03;
384
385if (c2_enabled) // C2
386{
387tmpl = aml_add_package(pack);
388resource_template_register_fixedhw[11] = 0x10; // C2
389aml_add_buffer(tmpl, resource_template_register_fixedhw, sizeof(resource_template_register_fixedhw));
390aml_add_byte(tmpl, 0x02);// C2
391aml_add_word(tmpl, 0x0040);// Latency
392aml_add_dword(tmpl, 0x000001f4);// Power
393}
394
395if (c4_enabled) // C4
396{
397tmpl = aml_add_package(pack);
398resource_template_register_fixedhw[11] = 0x30; // C4
399aml_add_buffer(tmpl, resource_template_register_fixedhw, sizeof(resource_template_register_fixedhw));
400aml_add_byte(tmpl, 0x04);// C4
401aml_add_word(tmpl, 0x0080);// Latency
402aml_add_dword(tmpl, 0x000000C8);// Power
403}
404else if (c3_enabled)
405{
406tmpl = aml_add_package(pack);
407resource_template_register_fixedhw[11] = 0x20; // C3
408aml_add_buffer(tmpl, resource_template_register_fixedhw, sizeof(resource_template_register_fixedhw));
409aml_add_byte(tmpl, 0x03);// C3
410aml_add_word(tmpl, 0x0060);// Latency
411aml_add_dword(tmpl, 0x0000015e);// Power
412}
413}
414
415// Aliaces
416int i;
417for (i = 0; i < acpi_cpu_count; i++)
418{
419char name[9];
420sprintf(name, "_PR_%c%c%c%c", acpi_cpu_name[i][0], acpi_cpu_name[i][1], acpi_cpu_name[i][2], acpi_cpu_name[i][3]);
421
422scop = aml_add_scope(root, name);
423aml_add_alias(scop, "CST_", "_CST");
424}
425
426aml_calculate_size(root);
427
428struct acpi_2_ssdt *ssdt = (struct acpi_2_ssdt *)AllocateKernelMemory(root->Size);
429
430aml_write_node(root, (void*)ssdt, 0);
431
432ssdt->Length = root->Size;
433ssdt->Checksum = 0;
434ssdt->Checksum = 256 - checksum8(ssdt, ssdt->Length);
435
436aml_destroy_node(root);
437
438// dumpPhysAddr("C-States SSDT content: ", ssdt, ssdt->Length);
439
440DBG("ACPI: SSDT with CPU C-States generated successfully.\n");
441
442return ssdt;
443} else {
444DBG("ACPI: ACPI CPUs not found: C-States not generated!\n");
445}
446
447return NULL;
448}
449
450struct acpi_2_ssdt *generate_pss_ssdt(struct acpi_2_dsdt* dsdt)
451{
452char ssdt_header[] = // pss_ssdt_header
453{
4540x53, 0x53, 0x44, 0x54, 0x7E, 0x00, 0x00, 0x00, /* SSDT.... */
4550x01, 0x6A, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x00, /* ..PmRef. */
4560x43, 0x70, 0x75, 0x50, 0x6D, 0x00, 0x00, 0x00, /* CpuPm... */
4570x00, 0x30, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* .0..INTL */
4580x31, 0x03, 0x10, 0x20,/* 1.._*/
459};
460
461if (Platform.CPU.Vendor != 0x756E6547) {
462DBG("ACPI: not an Intel platform: P-States will not be generated!\n");
463return NULL;
464}
465
466if (!(Platform.CPU.Features & CPU_FEATURE_MSR)) {
467DBG("ACPI: unsupported CPU: P-States will not be generated! No MSR support.\n");
468return NULL;
469}
470
471if (acpi_cpu_count == 0)
472get_acpi_cpu_names((void*)dsdt, dsdt->Length);
473
474if (acpi_cpu_count > 0)
475{
476struct p_state initial, maximum, minimum, p_states[32];
477uint8_t p_states_count = 0;
478
479// Retrieving P-States, ported from code by superhai (c)
480switch (Platform.CPU.Family) {
481case 0x06:
482{
483switch (Platform.CPU.Model)
484{
485case CPU_MODEL_DOTHAN:// Intel Pentium M
486case CPU_MODEL_YONAH:// Intel Mobile Core Solo, Duo
487case CPU_MODEL_MEROM:// Intel Mobile Core 2 Solo, Duo, Xeon 30xx, Xeon 51xx, Xeon X53xx, Xeon E53xx, Xeon X32xx
488case CPU_MODEL_PENRYN:// Intel Core 2 Solo, Duo, Quad, Extreme, Xeon X54xx, Xeon X33xx
489case CPU_MODEL_ATOM:// Intel Atom (45nm)
490{
491bool cpu_dynamic_fsb = false;
492
493if (rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 27))
494{
495wrmsr64(MSR_IA32_EXT_CONFIG, (rdmsr64(MSR_IA32_EXT_CONFIG) | (1 << 28)));
496delay(1);
497cpu_dynamic_fsb = rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 28);
498}
499
500bool cpu_noninteger_bus_ratio = (rdmsr64(MSR_IA32_PERF_STATUS) & (1ULL << 46));
501
502initial.Control = rdmsr64(MSR_IA32_PERF_STATUS);
503
504maximum.Control = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 32) & 0x1F3F) | (0x4000 * cpu_noninteger_bus_ratio);
505maximum.CID = ((maximum.FID & 0x1F) << 1) | cpu_noninteger_bus_ratio;
506
507minimum.FID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 24) & 0x1F) | (0x80 * cpu_dynamic_fsb);
508minimum.VID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 48) & 0x3F);
509
510if (minimum.FID == 0)
511{
512uint64_t msr;
513uint8_t i;
514// Probe for lowest fid
515for (i = maximum.FID; i >= 0x6; i--)
516{
517msr = rdmsr64(MSR_IA32_PERF_CONTROL);
518wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (i << 8) | minimum.VID);
519intel_waitforsts();
520minimum.FID = (rdmsr64(MSR_IA32_PERF_STATUS) >> 8) & 0x1F;
521delay(1);
522}
523
524msr = rdmsr64(MSR_IA32_PERF_CONTROL);
525wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
526intel_waitforsts();
527}
528
529if (minimum.VID == maximum.VID)
530{
531uint64_t msr;
532uint8_t i;
533// Probe for lowest vid
534for (i = maximum.VID; i > 0xA; i--)
535{
536msr = rdmsr64(MSR_IA32_PERF_CONTROL);
537wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (minimum.FID << 8) | i);
538intel_waitforsts();
539minimum.VID = rdmsr64(MSR_IA32_PERF_STATUS) & 0x3F;
540delay(1);
541}
542
543msr = rdmsr64(MSR_IA32_PERF_CONTROL);
544wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
545intel_waitforsts();
546}
547
548minimum.CID = ((minimum.FID & 0x1F) << 1) >> cpu_dynamic_fsb;
549
550// Sanity check
551if (maximum.CID < minimum.CID) {
552DBG("P-States: Insane FID values!");
553p_states_count = 0;
554} else {
555uint8_t vidstep;
556uint8_t i = 0, u, invalid = 0;
557// Finalize P-States
558// Find how many P-States machine supports
559p_states_count = (uint8_t)(maximum.CID - minimum.CID + 1);
560
561if (p_states_count > 32) {
562p_states_count = 32;
563}
564
565vidstep = ((maximum.VID << 2) - (minimum.VID << 2)) / (p_states_count - 1);
566
567for (u = 0; u < p_states_count; u++) {
568i = u - invalid;
569
570p_states[i].CID = maximum.CID - u;
571p_states[i].FID = (uint8_t)(p_states[i].CID >> 1);
572
573if (p_states[i].FID < 0x6) {
574if (cpu_dynamic_fsb) {
575p_states[i].FID = (p_states[i].FID << 1) | 0x80;
576}
577} else if (cpu_noninteger_bus_ratio) {
578p_states[i].FID = p_states[i].FID | (0x40 * (p_states[i].CID & 0x1));
579}
580
581if (i && p_states[i].FID == p_states[i-1].FID) {
582invalid++;
583}
584p_states[i].VID = ((maximum.VID << 2) - (vidstep * u)) >> 2;
585uint32_t multiplier = p_states[i].FID & 0x1f;// = 0x08
586bool half = p_states[i].FID & 0x40;// = 0x01
587bool dfsb = p_states[i].FID & 0x80;// = 0x00
588uint32_t fsb = (uint32_t)(Platform.CPU.FSBFrequency / 1000000); // = 400
589uint32_t halffsb = (fsb + 1) >> 1;// = 200
590uint32_t frequency = (multiplier * fsb);// = 3200
591
592p_states[i].Frequency = (uint32_t)(frequency + (half * halffsb)) >> dfsb;// = 3200 + 200 = 3400
593}
594
595p_states_count -= invalid;
596}
597
598break;
599}
600case CPU_MODEL_FIELDS:// Intel Core i5, i7, Xeon X34xx LGA1156 (45nm)
601case CPU_MODEL_DALES:
602case CPU_MODEL_DALES_32NM:// Intel Core i3, i5 LGA1156 (32nm)
603case CPU_MODEL_NEHALEM:// Intel Core i7, Xeon W35xx, Xeon X55xx, Xeon E55xx LGA1366 (45nm)
604case CPU_MODEL_NEHALEM_EX:// Intel Xeon X75xx, Xeon X65xx, Xeon E75xx, Xeon E65xx
605case CPU_MODEL_WESTMERE:// Intel Core i7, Xeon X56xx, Xeon E56xx, Xeon W36xx LGA1366 (32nm) 6 Core
606case CPU_MODEL_WESTMERE_EX:// Intel Xeon E7
607case CPU_MODEL_SANDYBRIDGE:// Intel Core i3, i5, i7 LGA1155 (32nm)
608case CPU_MODEL_JAKETOWN:// Intel Core i7, Xeon E5 LGA2011 (32nm)
609case CPU_MODEL_IVYBRIDGE:// Intel Core i3, i5, i7 LGA1155 (22nm)
610case CPU_MODEL_HASWELL://
611case CPU_MODEL_IVYBRIDGE_XEON: //
612//case CPU_MODEL_HASWELL_H://
613case CPU_MODEL_HASWELL_SVR://
614case CPU_MODEL_HASWELL_ULT://
615case CPU_MODEL_CRYSTALWELL://
616
617{
618if ((Platform.CPU.Model == CPU_MODEL_SANDYBRIDGE) || (Platform.CPU.Model == CPU_MODEL_JAKETOWN) ||
619(Platform.CPU.Model == CPU_MODEL_IVYBRIDGE) || (Platform.CPU.Model == CPU_MODEL_HASWELL) ||
620(Platform.CPU.Model == CPU_MODEL_IVYBRIDGE_XEON) || (Platform.CPU.Model == CPU_MODEL_HASWELL_SVR) ||
621(Platform.CPU.Model == CPU_MODEL_HASWELL_ULT) || (Platform.CPU.Model == CPU_MODEL_CRYSTALWELL))
622{
623maximum.Control = (rdmsr64(MSR_IA32_PERF_STATUS) >> 8) & 0xff;
624} else {
625maximum.Control = rdmsr64(MSR_IA32_PERF_STATUS) & 0xff;
626}
627
628minimum.Control = (rdmsr64(MSR_PLATFORM_INFO) >> 40) & 0xff;
629
630DBG("ACPI: P-States: min=0x%x, max=0x%x.", minimum.Control, maximum.Control);
631
632// Sanity check
633if (maximum.Control < minimum.Control) {
634DBG(" Insane control values!\n");
635p_states_count = 0;
636} else {
637uint8_t i;
638p_states_count = 0;
639
640for (i = maximum.Control; i >= minimum.Control; i--) {
641p_states[p_states_count].Control = i;
642p_states[p_states_count].CID = p_states[p_states_count].Control << 1;
643p_states[p_states_count].Frequency = (Platform.CPU.FSBFrequency / 1000000) * i;
644p_states_count++;
645}
646 DBG("\n");
647}
648
649break;
650}
651default:
652DBG("ACPI: unsupported CPU (0x%X): P-States not generated !!!\n", Platform.CPU.Family);
653break;
654}
655}
656}
657
658// Generating SSDT
659if (p_states_count > 0) {
660int i;
661
662AML_CHUNK* root = aml_create_node(NULL);
663aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header
664AML_CHUNK* scop = aml_add_scope(root, "\\_PR_");
665AML_CHUNK* name = aml_add_name(scop, "PSS_");
666AML_CHUNK* pack = aml_add_package(name);
667
668for (i = 0; i < p_states_count; i++) {
669AML_CHUNK* pstt = aml_add_package(pack);
670
671aml_add_dword(pstt, p_states[i].Frequency);
672aml_add_dword(pstt, 0x00000000); // Power
673aml_add_dword(pstt, 0x0000000A); // Latency
674aml_add_dword(pstt, 0x0000000A); // Latency
675aml_add_dword(pstt, p_states[i].Control);
676aml_add_dword(pstt, i+1); // Status
677}
678
679// Add aliaces
680for (i = 0; i < acpi_cpu_count; i++) {
681char name[9];
682sprintf(name, "_PR_%c%c%c%c", acpi_cpu_name[i][0], acpi_cpu_name[i][1], acpi_cpu_name[i][2], acpi_cpu_name[i][3]);
683
684scop = aml_add_scope(root, name);
685aml_add_alias(scop, "PSS_", "_PSS");
686}
687
688aml_calculate_size(root);
689
690struct acpi_2_ssdt *ssdt = (struct acpi_2_ssdt *)AllocateKernelMemory(root->Size);
691
692aml_write_node(root, (void*)ssdt, 0);
693
694ssdt->Length = root->Size;
695ssdt->Checksum = 0;
696ssdt->Checksum = 256 - (uint8_t)(checksum8(ssdt, ssdt->Length));
697
698aml_destroy_node(root);
699
700//dumpPhysAddr("P-States SSDT content: ", ssdt, ssdt->Length);
701
702DBG("ACPI: SSDT with CPU P-States generated successfully\n");
703
704return ssdt;
705}
706} else {
707DBG("ACPI: ACPI CPUs not found: P-States not generated!\n");
708}
709
710return NULL;
711}
712
713struct acpi_2_fadt *patch_fadt(struct acpi_2_fadt *fadt, struct acpi_2_dsdt *new_dsdt)
714{
715// extern void setupSystemType();
716
717struct acpi_2_fadt *fadt_mod = NULL;
718bool fadt_rev2_needed = false;
719bool fix_restart = false;
720bool fix_restart_ps2 = false;
721int value = 1;
722
723// Restart Fix
724if (Platform.CPU.Vendor == 0x756E6547) { /* Intel */
725fix_restart = true;
726fix_restart_ps2 = false;
727if ( getBoolForKey(kPS2RestartFix, &fix_restart_ps2, &bootInfo->chameleonConfig) && fix_restart_ps2) {
728fix_restart = true;
729} else {
730getBoolForKey(kRestartFix, &fix_restart, &bootInfo->chameleonConfig);
731}
732} else {
733DBG("\tnot an Intel platform, FACP Restart Fix not applied!\n");
734fix_restart = false;
735}
736
737if (fix_restart) {
738fadt_rev2_needed = true;
739}
740
741// Allocate new fadt table
742if (fadt->Length < 0x84 && fadt_rev2_needed)
743{
744fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(0x84);
745memcpy(fadt_mod, fadt, fadt->Length);
746fadt_mod->Length = 0x84;
747fadt_mod->Revision = 0x02; // FACP rev 2 (ACPI 1.0B MS extensions)
748} else {
749fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(fadt->Length);
750memcpy(fadt_mod, fadt, fadt->Length);
751}
752
753// Bungo: Determine PM Profile
754DBG("\tPM Profile=0x%02X", fadt->PM_Profile);
755if (getIntForKey(kSystemType, &value, &bootInfo->chameleonConfig)) {
756DBG(", overriding with: 0x%02X.\n", (uint8_t)value);
757fadt_mod->PM_Profile = (uint8_t)value; // user has overriden the PM Profile so take care of it in FACP
758} else {
759 switch (fadt->PM_Profile) { // check if PM Profile is correct (1..3)
760 case 1:
761 case 2:
762 case 3:
763 DBG(": using.\n");
764 break;
765 default:
766 // use SMBIOS chassisType to determine PM Profile (saved previously for us)
767 DBG(", expected value: 1, 2 or 3, setting to 0x%02X.\n", Platform.Type);
768 fadt_mod->PM_Profile = Platform.Type; // take care of modified FACP's PM Profile entry
769 break;
770 }
771 }
772Platform.Type = fadt_mod->PM_Profile; // Save fixed PM Profile (-> system-type)
773
774/* Bungo: Moved into fake_efi.c
775 // Setup system-type: We now have to write the systemm-type in ioregs: we cannot do it before in setupDeviceTree()
776// because we need to take care of FACP original content, if it is correct.
777setupSystemType();
778*/
779// Patch FACP to fix restart
780if (fix_restart) {
781if (fix_restart_ps2) {
782fadt_mod->Flags|= 0x400;
783fadt_mod->Reset_SpaceID= 0x01; // System I/O
784fadt_mod->Reset_BitWidth= 0x08; // 1 byte
785fadt_mod->Reset_BitOffset= 0x00; // Offset 0
786fadt_mod->Reset_AccessWidth= 0x01; // Byte access
787fadt_mod->Reset_Address= 0x64; // Address of the register
788fadt_mod->Reset_Value= 0xfe; // Value to write to reset the system
789DBG("\tFACP PS2 Restart Fix applied!\n");
790} else {
791fadt_mod->Flags|= 0x400;
792fadt_mod->Reset_SpaceID= 0x01; // System I/O
793fadt_mod->Reset_BitWidth= 0x08; // 1 byte
794fadt_mod->Reset_BitOffset= 0x00; // Offset 0
795fadt_mod->Reset_AccessWidth= 0x01; // Byte access
796fadt_mod->Reset_Address= 0x0cf9; // Address of the register
797fadt_mod->Reset_Value= 0x06; // Value to write to reset the system
798DBG("\tFACP Restart Fix applied!\n");
799}
800} else {
801 DBG("\tRestart Fix: No.\n");
802 }
803
804 // Bungo: Allocate new FACS table
805 DBG("\tOEM table FACS@%08X found, length=%d", fadt->FACS, ((struct acpi_2_facs *)(fadt->FACS))->Length);
806 if ((uint32_t)(&(fadt->X_FACS))-(uint32_t)fadt+8<=fadt->Length) {
807 DBG(".\n");
808 DBG("\tOEM table X_FACS@%08X%08X found, length=%d", (uint32_t)(fadt->X_FACS >> 32), (uint32_t)(fadt->X_FACS), ((struct acpi_2_facs *)(fadt->X_FACS))->Length);
809 if (fadt->FACS != (uint32_t)(fadt->X_FACS)) {
810 DBG(". Differs from FACS: fixing.\n");
811 fadt_mod->FACS = (uint32_t)(fadt->X_FACS); // in my case only from X_FACS loaded 64 bytes (see ACPI spec.)
812 } else {
813 DBG(": using.\n");
814 }
815 } else {
816 DBG(": using.\n");
817 }
818 struct acpi_2_facs *oemfacs = (struct acpi_2_facs *)(fadt_mod->FACS);
819 fadt_mod->FACS = AllocateKernelMemory(oemfacs->Length);
820 memcpy((struct acpi_2_facs *)(fadt_mod->FACS), oemfacs, oemfacs->Length);
821 ((struct acpi_2_facs *)(fadt_mod->FACS))->Version = 1;
822 if ((uint32_t)(&(fadt->X_FACS))-(uint32_t)fadt+8<=fadt->Length) {
823 fadt_mod->X_FACS = (uint64_t)(fadt_mod->FACS);
824 }
825
826 // Bungo: Save Hardware Signature (-> machine-signature)
827Platform.HWSignature = ((struct acpi_2_facs *)fadt_mod->FACS)->HWSignature;
828 DBG("\tHardware Signature=0x%08X: using.\n", Platform.HWSignature);
829
830 DBG("\tOEM table DSDT@%08X found: %susing.\n", fadt->DSDT, new_dsdt ? "not " : "");
831 if ((uint32_t)(&(fadt->X_DSDT))-(uint32_t)fadt+8<=fadt->Length) {
832 DBG("\tOEM table X_DSDT@%08X%08X found: %susing.\n", (uint32_t)(fadt->X_DSDT >> 32), (uint32_t)(fadt->X_DSDT), new_dsdt ? "not " : "");
833 }
834// Patch DSDT address if we have loaded DSDT.aml
835if (new_dsdt) {
836 fadt_mod->DSDT = (uint32_t)new_dsdt;
837 DBG("\tFACP uses custom DSDT@%08X", fadt_mod->DSDT);
838if ((uint32_t)(&(fadt_mod->X_DSDT))-(uint32_t)fadt_mod+8<=fadt_mod->Length) {
839fadt_mod->X_DSDT = (uint64_t)(fadt_mod->DSDT);
840 DBG("/X_DSDT@%08X%08X", (uint32_t)(fadt_mod->X_DSDT >> 32), (uint32_t)(fadt_mod->X_DSDT));
841}
842 DBG(".\n");
843}
844
845// Correct the checksum
846fadt_mod->Checksum=0;
847fadt_mod->Checksum=256-checksum8(fadt_mod,fadt_mod->Length);
848
849return fadt_mod;
850}
851// Bung: Unused
852/* Setup ACPI without replacing DSDT.
853int setupAcpiNoMod()
854{
855//addConfigurationTable(&gEfiAcpiTableGuid, getAddressOfAcpiTable(), "ACPI");
856//addConfigurationTable(&gEfiAcpi20TableGuid, getAddressOfAcpi20Table(), "ACPI_20");
857// XXX aserebln why uint32 cast if pointer is uint64 ?
858acpi10_p = (uint64_t)(uint32_t)getAddressOfAcpiTable();
859acpi20_p = (uint64_t)(uint32_t)getAddressOfAcpi20Table();
860// addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
861if(acpi20_p) {
862// addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
863} else {
864DBG("ACPI: version 2.0 not found.\n");
865}
866return 1;
867}
868*/
869/* Setup ACPI. Replace DSDT if DSDT.aml is found */
870int setupAcpi()
871{
872int version;
873void *new_dsdt = NULL, *new_table = NULL;
874const char *filename = "";
875char dirSpec[128];
876int len = 0;
877
878// always reset cpu count to 0 when injecting new acpi
879acpi_cpu_count = 0;
880
881/* Try using the file specified with the DSDT option */
882if (getValueForKey(kDSDT, &filename, &len, &bootInfo->chameleonConfig)) {
883snprintf(dirSpec, sizeof(dirSpec), filename);
884} else {
885sprintf(dirSpec, "DSDT.aml");
886//verbose("dirSpec, DSDT.aml");
887}
888
889// Load replacement DSDT
890new_dsdt = loadACPITable(dirSpec);
891
892// Mozodojo: going to patch FACP and load SSDT's even if DSDT.aml is not present
893/*if (!new_dsdt)
894 {
895 return setupAcpiNoMod();
896 }*/
897
898// SSDT options
899bool drop_ssdt=false, generate_pstates=false, generate_cstates=false;
900
901getBoolForKey(kDropSSDT, &drop_ssdt, &bootInfo->chameleonConfig);
902getBoolForKey(kGeneratePStates, &generate_pstates, &bootInfo->chameleonConfig);
903getBoolForKey(kGenerateCStates, &generate_cstates, &bootInfo->chameleonConfig);
904 DBG("ACPI: drop SSDT tables: %s.\n", drop_ssdt ? "Yes" : "No");
905DBG("ACPI: generate P-States: %s.\n", generate_pstates ? "Yes" : "No");
906DBG("ACPI: generate C-States: %s.\n", generate_cstates ? "Yes" : "No");
907
908 // Mozodojo: Load additional SSDTs
909struct acpi_2_ssdt *new_ssdt[32]; // 30 + 2 additional tables for pss & cst
910int ssdtotal_number=0;
911{
912int i;
913for (i = 0; i < 30; i++) {
914char filename[512];
915
916sprintf(filename, i > 0 ? "SSDT-%d.aml" : "SSDT.aml", i);
917
918if ( (new_ssdt[ssdtotal_number] = loadACPITable(filename)) ) {
919ssdtotal_number++;
920} else {
921 // DBG("ACPI: table not found: '%s'\n", filename);
922//break;
923}
924}
925}
926
927// Load ECDT table
928sprintf(dirSpec, "ECDT.aml");
929new_table = loadACPITable(dirSpec);
930
931// Do the same procedure for both versions of ACPI
932for (version = 0; version < 2; version++) {
933struct acpi_2_rsdp *rsdp, *rsdp_mod;
934struct acpi_2_rsdt *rsdt, *rsdt_mod;
935 struct acpi_2_xsdt *xsdt, *xsdt_mod;
936 uint32_t *rsdt_entries;
937 uint64_t *xsdt_entries;
938
939// Find original rsdp
940rsdp=(struct acpi_2_rsdp *)(version ? getAddressOfAcpi20Table() : getAddressOfAcpiTable());
941if (!rsdp) {
942if (version) {
943//addConfigurationTable(&gEfiAcpi20TableGuid, NULL, "ACPI_20");
944} else {
945//addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI");
946}
947 DBG("ACPI: version %d.0 not found. Not patching.\n", version+1);
948continue;
949}
950
951 int rsdplength = version ? rsdp->Length : 20;
952int l = version ? 20 : 0;
953DBG("ACPI: OEM table RSDP found @%08X, length=%d. ACPI version %d.0: patching.\n", rsdp, rsdplength, version + 1);
954
955/* FIXME: no check that memory allocation succeeded
956 * Copy and patch RSDP, RSDT, XSDT and FADT
957 * For more info see ACPI Specification pages 110 and following
958 */
959
960rsdp_mod = (struct acpi_2_rsdp *)(l + AllocateKernelMemory(l + rsdplength));
961memcpy(rsdp_mod, rsdp, rsdplength);
962
963rsdt=(struct acpi_2_rsdt *)(rsdp->RsdtAddress);
964
965DBG("ACPI: OEM table RSDT found @%08X, length=%d.\n",rsdt, rsdt->Length);
966
967if (rsdt && (uint32_t)rsdt !=0xffffffff && rsdt->Length<0x10000) {
968//uint32_t *rsdt_entries;
969int rsdt_entries_num;
970int dropoffset=0, i, j;
971
972// mozo: using malloc cos I didn't found how to free already allocated kernel memory
973rsdt_mod = (struct acpi_2_rsdt *)malloc(rsdt->Length);
974memcpy(rsdt_mod, rsdt, rsdt->Length);
975rsdp_mod->RsdtAddress = (uint32_t)rsdt_mod;
976rsdt_entries_num = (rsdt_mod->Length-sizeof(struct acpi_2_rsdt))/4;
977rsdt_entries = (uint32_t *)(rsdt_mod + 1);
978
979for (i = 0; i < rsdt_entries_num; i++) {
980 // rsdt_entries[i-dropoffset] = rsdt_entries[i]; // dropping
981
982struct acpi_2_header *oemTable = (struct acpi_2_header *)rsdt_entries[i];
983if (!oemTable) {
984dropoffset++;
985 continue;
986}
987
988//DBG("TABLE %c%c%c%c,",table[0],table[1],table[2],table[3]);
989DBG("ACPI: OEM table %c%c%c%c found @%08X, length=%d: ", oemTable->Signature[0], oemTable->Signature[1], oemTable->Signature[2], oemTable->Signature[3], oemTable, oemTable->Length);
990
991if (tableSign(oemTable, "SSDT")) {
992 if (drop_ssdt) {
993 DBG("dropping.\n");
994 dropoffset++;
995 continue;
996 } else {
997 DBG("using.\n");
998 rsdt_entries[i-dropoffset] = (uint64_t)AllocateKernelMemory(oemTable->Length);
999 memcpy((struct acpi_2_header *)(uint32_t)rsdt_entries[i-dropoffset], oemTable, oemTable->Length);
1000
1001 // get rest of ssdt tables from inside ssdt_pmref
1002 struct ssdt_pmref *subSSDT = (struct ssdt_pmref *)((uint32_t)rsdt_entries[i-dropoffset] + sizeof(struct acpi_2_header) + 15);
1003 uint8_t tabNum = *((uint8_t *)subSSDT - 2) / 3; // e.g Name (SSDT, Package (0x0C) -> 0x0C / 3 = number of sub SSDTs
1004 for (j = 0; j < tabNum; j++) {
1005 if (!subSSDT[j].addr) continue;
1006 oemTable = (struct acpi_2_header *)subSSDT[j].addr;
1007 DBG("ACPI: OEM table SSDT_%s found @%08X, length=%d: using.\n", oemTable->OEMTableId, oemTable, oemTable->Length);
1008 subSSDT[j].addr = AllocateKernelMemory(oemTable->Length);
1009 memcpy((struct acpi_2_header *)subSSDT[j].addr, oemTable, oemTable->Length);
1010 new_ssdt[ssdtotal_number] = (struct acpi_2_ssdt *)subSSDT[j].addr;
1011 ssdtotal_number++;
1012 }
1013 continue;
1014 }
1015}
1016
1017if (tableSign(oemTable, "DSDT") && new_dsdt) {
1018 rsdt_entries[i-dropoffset] = (uint32_t)new_dsdt;
1019 DBG("using custom table.\n");
1020 continue;
1021}
1022
1023if (tableSign(oemTable, "FACP")) {
1024struct acpi_2_fadt /* *fadt, */ *fadt_mod;
1025// fadt = (struct acpi_2_fadt *)rsdt_entries[i];
1026
1027if ((uint32_t)oemTable == 0xffffffff || oemTable->Length>0x10000) {
1028DBG("INCORRECT! Not modifying.\n");
1029continue;
1030}
1031
1032DBG("patching.\n");
1033fadt_mod = patch_fadt((struct acpi_2_fadt *)oemTable, new_dsdt);
1034rsdt_entries[i-dropoffset] = (uint32_t)fadt_mod;
1035
1036// Generate _CST SSDT
1037if (generate_cstates && (new_ssdt[ssdtotal_number] = generate_cst_ssdt(fadt_mod))) {
1038DBG("\tC-States generated.\n");
1039generate_cstates = false; // Generate SSDT only once!
1040ssdtotal_number++;
1041}
1042
1043// Generating _PSS SSDT
1044if (generate_pstates && (new_ssdt[ssdtotal_number] = generate_pss_ssdt((void*)fadt_mod->DSDT))) {
1045DBG("\tP-States generated.\n");
1046generate_pstates = false; // Generate SSDT only once!
1047ssdtotal_number++;
1048}
1049continue;
1050}
1051 DBG("using.\n");
1052 // allocating oem table
1053 rsdt_entries[i-dropoffset] = (uint32_t)AllocateKernelMemory(oemTable->Length);
1054 memcpy((struct acpi_2_header *)rsdt_entries[i-dropoffset], oemTable, oemTable->Length);
1055}
1056
1057// Mozodojo: Insert additional SSDTs into RSDT
1058if (ssdtotal_number > 0) {
1059for (j=0; j<ssdtotal_number; j++) {
1060rsdt_entries[i-dropoffset+j]=(uint32_t)new_ssdt[j];
1061}
1062DBG("ACPI: added %d custom SSDT table%s into RSDT.\n", ssdtotal_number, (ssdtotal_number != 1) ? "s" : "");
1063}
1064
1065if (new_table) {
1066rsdt_entries[i-dropoffset+j]=(uint32_t)new_table;
1067DBG("ACPI: added custom table '%s' @%08X into RSDT.\n", "ECDT", new_table);
1068}
1069
1070// Allocate rsdt in Kernel memory area
1071rsdt_mod->Length += 4*ssdtotal_number + 4 - 4*dropoffset;
1072struct acpi_2_rsdt *rsdt_copy = (struct acpi_2_rsdt *)AllocateKernelMemory(rsdt_mod->Length);
1073memcpy (rsdt_copy, rsdt_mod, rsdt_mod->Length);
1074free(rsdt_mod);
1075rsdt_mod = rsdt_copy;
1076rsdp_mod->RsdtAddress=(uint32_t)rsdt_mod;
1077rsdt_entries_num=(rsdt_mod->Length-sizeof(struct acpi_2_rsdt))/4;
1078rsdt_entries=(uint32_t *)(rsdt_mod+1);
1079
1080// Correct the checksum of RSDT
1081DBG("ACPI: modified RSDT@%08X, length=%d. Checksum: old=%d, ", rsdt_mod, rsdt_mod->Length, rsdt_mod->Checksum);
1082rsdt_mod->Checksum=0;
1083rsdt_mod->Checksum=256-checksum8(rsdt_mod,rsdt_mod->Length);
1084DBG("new=%d.\n", rsdt_mod->Checksum);
1085} else {
1086rsdp_mod->RsdtAddress=0;
1087DBG("ACPI: RSDT table not found or incorrect.\n");
1088}
1089DBG("\n");
1090
1091if (version) {
1092// struct acpi_2_xsdt *xsdt, *xsdt_mod;
1093
1094// FIXME: handle 64-bit address correctly
1095xsdt = (struct acpi_2_xsdt *)(uint32_t)rsdp->XsdtAddress;
1096DBG("ACPI: OEM table XSDT found @%08X%08X, length=%d.\n", (uint32_t)(rsdp->XsdtAddress >> 32),(uint32_t)rsdp->XsdtAddress, xsdt->Length);
1097
1098if (xsdt && rsdp->XsdtAddress<0xffffffff && xsdt->Length<0x10000) {
1099// uint64_t *xsdt_entries;
1100int xsdt_entries_num, i, j;
1101int dropoffset=0;
1102
1103// mozo: using malloc cos I didn't found how to free already allocated kernel memory
1104xsdt_mod=(struct acpi_2_xsdt*)malloc(xsdt->Length);
1105memcpy(xsdt_mod, xsdt, xsdt->Length);
1106
1107rsdp_mod->XsdtAddress=(uint64_t)xsdt_mod;
1108xsdt_entries_num = (xsdt_mod->Length-sizeof(struct acpi_2_xsdt))/8;
1109xsdt_entries = (uint64_t *)(xsdt_mod+1);
1110
1111 struct acpi_2_header *oemTable;
1112for (i = 0; i < xsdt_entries_num; i++) {
1113 // xsdt_entries[i-dropoffset] = xsdt_entries[i]; // dropping
1114
1115 oemTable = (struct acpi_2_header *)(uint32_t)xsdt_entries[i];
1116if (!oemTable) {
1117 dropoffset++;
1118continue;
1119}
1120
1121 DBG("ACPI: OEM table %c%c%c%c found @%08X%08X, length=%d: ", oemTable->Signature[0], oemTable->Signature[1], oemTable->Signature[2], oemTable->Signature[3], (uint32_t)(xsdt_entries[i] >> 32), (uint32_t)(xsdt_entries[i]), oemTable->Length);
1122
1123 if (((uint64_t *)(xsdt + 1))[i] == (uint64_t)((uint32_t *)(rsdt + 1))[i]) {
1124 DBG("it's the same as in RSDT, using\n");
1125 xsdt_entries[i-dropoffset] = (uint64_t)rsdt_entries[i];
1126 continue;
1127 }
1128
1129 if (tableSign(oemTable, "SSDT")) {
1130 if (drop_ssdt) {
1131 DBG("dropping.\n");
1132 dropoffset++;
1133 continue;
1134 } else {
1135 DBG("using.\n");
1136 xsdt_entries[i-dropoffset] = (uint64_t)AllocateKernelMemory(oemTable->Length);
1137 memcpy((struct acpi_2_header *)(uint32_t)xsdt_entries[i-dropoffset], oemTable, oemTable->Length);
1138
1139 // get rest of ssdt tables from inside ssdt_pmref
1140 struct ssdt_pmref *subSSDT = (struct ssdt_pmref *)((uint32_t)xsdt_entries[i-dropoffset] + sizeof(struct acpi_2_header) + 15);
1141 uint8_t tabNum = *((uint8_t *)subSSDT - 2) / 3; // e.g Name (SSDT, Package (0x0C) -> 0x0C / 3 = number of sub SSDTs
1142 for (j = 0; j < tabNum; j++) {
1143 if (!subSSDT[j].addr) continue;
1144 oemTable = (struct acpi_2_header *)subSSDT[j].addr;
1145 DBG("ACPI: OEM table SSDT_%s found @%08X, length=%d: using.\n", oemTable->OEMTableId, oemTable, oemTable->Length);
1146 subSSDT[j].addr = AllocateKernelMemory(oemTable->Length);
1147 memcpy((struct acpi_2_header *)subSSDT[j].addr, oemTable, oemTable->Length);
1148 new_ssdt[ssdtotal_number] = (struct acpi_2_ssdt *)subSSDT[j].addr;
1149 ssdtotal_number++;
1150 }
1151 continue;
1152 }
1153 }
1154
1155if (tableSign(oemTable, "DSDT") && new_dsdt) {
1156 xsdt_entries[i-dropoffset] = (uint64_t)new_dsdt;
1157 DBG("using custom table.\n");
1158 continue;
1159}
1160
1161if (tableSign(oemTable, "FACP")) {
1162struct acpi_2_fadt /* *fadt, */ *fadt_mod;
1163//fadt = (struct acpi_2_fadt *)(uint32_t)xsdt_entries[i];
1164
1165if (xsdt_entries[i] >= 0xffffffff || oemTable->Length>0x10000) {
1166goto drop_xsdt;
1167}
1168
1169 DBG("patching.\n");
1170fadt_mod = patch_fadt((struct acpi_2_fadt *)oemTable, new_dsdt);
1171xsdt_entries[i-dropoffset] = (uint64_t)fadt_mod;
1172
1173// Generate _CST SSDT
1174if (generate_cstates && (new_ssdt[ssdtotal_number] = generate_cst_ssdt(fadt_mod))) {
1175DBG("ACPI: C-States generated\n");
1176generate_cstates = false; // Generate SSDT only once!
1177ssdtotal_number++;
1178}
1179
1180// Generating _PSS SSDT
1181if (generate_pstates && (new_ssdt[ssdtotal_number] = generate_pss_ssdt((void *)fadt_mod->DSDT))) {
1182DBG("ACPI: P-States generated\n");
1183generate_pstates = false; // Generate SSDT only once!
1184ssdtotal_number++;
1185}
1186continue;
1187}
1188
1189 DBG("using.\n");
1190 // allocating oem table
1191 xsdt_entries[i-dropoffset] = (uint64_t)AllocateKernelMemory(oemTable->Length);
1192 memcpy((struct acpi_2_header *)(uint32_t)xsdt_entries[i-dropoffset], oemTable, oemTable->Length);
1193}
1194
1195// Mozodojo: Insert additional SSDTs into XSDT
1196if (ssdtotal_number > 0) {
1197for (j=0; j<ssdtotal_number; j++) {
1198xsdt_entries[i-dropoffset+j]=(uint64_t)new_ssdt[j];
1199}
1200DBG("ACPI: added %d custom SSDT table%s into XSDT.\n", ssdtotal_number, (ssdtotal_number != 1) ? "s" : "");
1201}
1202
1203if (new_table) {
1204xsdt_entries[i-dropoffset+j]=(uint64_t)new_table;
1205DBG("ACPI: added custom table '%s' @00000000%08X into XSDT.\n", "ECDT", new_table);
1206}
1207
1208// Allocate xsdt in Kernel memory area
1209xsdt_mod->Length += 8*ssdtotal_number + 8 - 8*dropoffset;
1210struct acpi_2_xsdt *xsdt_copy = (struct acpi_2_xsdt *)AllocateKernelMemory(xsdt_mod->Length);
1211memcpy(xsdt_copy, xsdt_mod, xsdt_mod->Length);
1212free(xsdt_mod);
1213 xsdt_mod = xsdt_copy;
1214rsdp_mod->XsdtAddress=(uint64_t)xsdt_mod;
1215xsdt_entries_num=(xsdt_mod->Length-sizeof(struct acpi_2_xsdt))/8;
1216xsdt_entries=(uint64_t *)(xsdt_mod+1);
1217
1218// Correct the checksum of XSDT
1219DBG("ACPI: modified XSDT@00000000%08X, length=%d. Checksum: old=%d, ", xsdt_mod, xsdt_mod->Length, xsdt_mod->Checksum);
1220 xsdt_mod->Checksum=0;
1221 xsdt_mod->Checksum=256-checksum8(xsdt_mod, xsdt_mod->Length);
1222 DBG("new=%d.\n", xsdt_mod->Checksum);
1223} else {
1224drop_xsdt:
1225/*FIXME: Now we just hope that if MacOS doesn't find XSDT it reverts to RSDT.
1226 * A Better strategy would be to generate
1227 */
1228rsdp_mod->XsdtAddress=0xffffffffffffffffLL;
1229DBG("ACPI: XSDT table not found (>4GB) or incorrect. Dropping.\n");
1230}
1231}
1232
1233// Correct the checksum of RSDP
1234DBG("ACPI: modified RSDP@%08X, checksum: old=%d, ", rsdp_mod, rsdp_mod->Checksum);
1235rsdp_mod->Checksum=0;
1236rsdp_mod->Checksum=256-checksum8(rsdp_mod, 20);
1237DBG("new=%d", rsdp_mod->Checksum);
1238
1239if (version) {
1240DBG("; extended checksum: old=%d, ", rsdp_mod->ExtendedChecksum);
1241rsdp_mod->ExtendedChecksum=0;
1242rsdp_mod->ExtendedChecksum=256-checksum8(rsdp_mod,rsdp_mod->Length);
1243DBG("new=%d.\n", rsdp_mod->ExtendedChecksum);
1244} else {
1245 DBG(".\n");
1246 }
1247
1248if (version) {
1249/* XXX aserebln why uint32 cast if pointer is uint64 ? */
1250 acpi10_p = (uint64_t)((uint32_t)rsdp_mod - 20);
1251acpi20_p = (uint64_t)(uint32_t)rsdp_mod;
1252 memcpy((struct acpi_2_rsdp *)acpi10_p, (struct acpi_2_rsdp *)acpi20_p, 20);
1253//addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
1254} else {
1255/* XXX aserebln why uint32 cast if pointer is uint64 ? */
1256acpi10_p = (uint64_t)(uint32_t)rsdp_mod;
1257//addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
1258}
1259
1260DBG("ACPI: acpi version %d.0 patching finished\n\n", version+1);
1261}
1262#if DEBUG_ACPI
1263printf("ACPI: Press a key to continue... (DEBUG_ACPI)\n");
1264getchar();
1265#endif
1266return 1;
1267}
1268
1269struct acpi_2_rsdp *getRSDPaddress()
1270{
1271 bool found = false;
1272 /* Before searching the BIOS space we are supposed to search the first 1K of the EBDA */
1273EBDA_RANGE_START = (uint32_t)swapUint16(*(uint16_t *)BDA_EBDA_START) << 4;
1274 DBG("getRSDPaddress: scanning EBDA [%08X:%08X] for RSDP... ", EBDA_RANGE_START, EBDA_RANGE_END);
1275 void *rsdp_addr = (void*)EBDA_RANGE_START;
1276for (; rsdp_addr <= (void*)EBDA_RANGE_END; rsdp_addr += 1) {
1277if (*(uint64_t *)rsdp_addr == ACPI_SIGNATURE_UINT64_LE) {
1278 found = true;
1279 break;
1280}
1281}
1282
1283 if (!found) {
1284 DBG("Nothing found.\n");
1285 DBG("getRSDPaddress: scanning BIOS area [%08X:%08X] for RSDP... ", ACPI_RANGE_START, ACPI_RANGE_END);
1286 rsdp_addr = (void*)ACPI_RANGE_START;
1287 for (; rsdp_addr <= (void*)ACPI_RANGE_END; rsdp_addr += 16) {
1288 if (*(uint64_t *)rsdp_addr == ACPI_SIGNATURE_UINT64_LE) {
1289 found = true;
1290 break;
1291 }
1292 }
1293 }
1294
1295 if (found) {
1296 DBG("Found @0%08X, Rev.: %s (0x%02X).\n", rsdp_addr, ((struct acpi_2_rsdp *)rsdp_addr)->Revision ? "2.0" : "1.0", ((struct acpi_2_rsdp *)rsdp_addr)->Revision);
1297 uint8_t csum = checksum8(rsdp_addr, 20);
1298 if (csum == 0) {
1299 if (((struct acpi_2_rsdp *)rsdp_addr)->Revision == 0) return rsdp_addr;
1300 csum = checksum8(rsdp_addr, sizeof(struct acpi_2_rsdp));
1301 if (csum == 0) return rsdp_addr;
1302 else DBG("getRSDPaddress: RSDP extended checksum incorrect: %d.\n", csum);
1303 } else DBG("getRSDPaddress: RSDP checksum incorrect: %d.\n", csum);
1304 } else DBG("Nothing found.\n");
1305
1306return NULL;
1307}
1308

Archive Download this file

Revision: 2469