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

Archive Download this file

Revision: 2531