Chameleon

Chameleon Svn Source Tree

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

1/*
2 * Copyright 2008 mackerintel
3 * 2010 mojodojo, 2012 slice
4 */
5
6#include "libsaio.h"
7#include "boot.h"
8#include "bootstruct.h"
9#include "acpi.h"
10#include "efi_tables.h"
11#include "fake_efi.h"
12#include "acpi_patcher.h"
13#include "platform.h"
14#include "cpu.h"
15#include "aml_generator.h"
16#include "state_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// Bungo:
31void *new_dsdt = NULL,
32 *new_ecdt = NULL;
33
34// Slice: New signature compare function
35boolean_t tableSign(void *table, const char *sgn)
36{
37int i;
38for (i = 0; i < 4; i++)
39{
40if ((((char *)table)[i] & ~0x20) != (sgn[i] & ~0x20))
41{
42return false;
43}
44}
45return true;
46}
47
48uint32_t EBDA_RANGE_START = EBDA_RANGE_MIN;
49
50uint64_t acpi10_p = 0;
51uint64_t acpi20_p = 0;
52
53/* Gets the ACPI 1.0 RSDP address */
54static struct acpi_2_rsdp *getAddressOfAcpiTable()
55{
56 /* Before searching the BIOS space we are supposed to search the first 1K of the EBDA */
57 EBDA_RANGE_START = /* (uint32_t)swapUint16(*(uint16_t *)BDA_EBDA_START) << 4 */ EBDA_RANGE_MIN;
58 verbose("ACPIpatcher: scanning EBDA [%08X-%08X] for RSDP 1.0... ", EBDA_RANGE_START, EBDA_RANGE_END);
59 void *acpi_addr = (void*)EBDA_RANGE_START;
60for (; acpi_addr < (void*)EBDA_RANGE_END; acpi_addr++)
61{
62if (*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE)
63{
64 break;
65}
66}
67
68if (acpi_addr >= (void*)EBDA_RANGE_END)
69{
70 verbose("Nothing found.\n");
71 verbose("ACPIpatcher: scanning BIOS area [%08X-%08X] for RSDP 1.0...\n", ACPI_RANGE_START, ACPI_RANGE_END);
72 acpi_addr = (void*)ACPI_RANGE_START;
73for (; acpi_addr < (void*)ACPI_RANGE_END; acpi_addr += 16)
74{
75if (*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE)
76{
77 break;
78 }
79 }
80}
81else
82{
83 verbose("\n");
84 }
85
86 uint8_t csum = checksum8(acpi_addr, 20);
87
88if (csum == 0)
89{
90 // Only return the table if it is a true version 1.0 table (Revision 0)
91if(((struct acpi_2_rsdp*)acpi_addr)->Revision == 0)
92{
93 return acpi_addr;
94 }
95 }
96
97return NULL;
98}
99
100/* Gets the ACPI 2.0 RSDP address */
101static struct acpi_2_rsdp *getAddressOfAcpi20Table()
102{
103 /* Before searching the BIOS space we are supposed to search the first 1K of the EBDA */
104EBDA_RANGE_START = /* (uint32_t)swapUint16(*(uint16_t *)BDA_EBDA_START) << 4 */ EBDA_RANGE_MIN;
105 verbose("ACPIpatcher: scanning EBDA [%08X-%08X] for RSDP 2.0 or newer... ", EBDA_RANGE_START, EBDA_RANGE_END);
106 void *acpi_addr = (void *)EBDA_RANGE_START;
107for (; acpi_addr < (void *)EBDA_RANGE_END; acpi_addr++)
108{
109if (*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE)
110{
111 break;
112}
113}
114
115if (acpi_addr >= (void *)EBDA_RANGE_END)
116{
117 verbose("Nothing found.\n");
118 verbose("ACPIpatcher: scanning BIOS area [%08X-%08X] for RSDP 2.0 or newer...\n", ACPI_RANGE_START, ACPI_RANGE_END);
119 acpi_addr = (void *)ACPI_RANGE_START;
120for (; acpi_addr <= (void *)ACPI_RANGE_END; acpi_addr += 16)
121{
122if(*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE)
123{
124 break;
125 }
126 }
127}
128else
129{
130 verbose("\n");
131 }
132
133 uint8_t csum = checksum8(acpi_addr, 20);
134
135 /* Only assume this is a 2.0 or better table if the revision is greater than 0
136 * NOTE: ACPI 3.0 spec only seems to say that 1.0 tables have revision 1
137 * and that the current revision is 2.. I am going to assume that rev > 0 is 2.0.
138 */
139
140 if(csum == 0 && (((struct acpi_2_rsdp*)acpi_addr)->Revision > 0)) {
141 uint8_t csum2 = checksum8(acpi_addr, sizeof(struct acpi_2_rsdp));
142if(csum2 == 0)
143{
144 return acpi_addr;
145 }
146 }
147
148return NULL;
149}
150
151/* The folowing ACPI Table search algo. should be reused anywhere needed:*/
152/* WARNING: outDirspec string will be overwritten by subsequent calls! */
153int search_and_get_acpi_fd(const char *filename, const char **outDirspec)
154{
155int fd = 0;
156static char dirSpec[512];
157
158// Try finding 'filename' in the usual places
159// Start searching any potential location for ACPI Table
160 snprintf(dirSpec, sizeof(dirSpec), "%s", filename);
161 fd = open(dirSpec, 0);
162if (fd < 0)
163{
164snprintf(dirSpec, sizeof(dirSpec), "/Extra/%s", filename);
165fd = open(dirSpec, 0);
166if (fd < 0)
167{
168 snprintf(dirSpec, sizeof(dirSpec), "/Extra/Acpi/%s", filename);
169 fd = open(dirSpec, 0);
170if (fd < 0)
171{
172 snprintf(dirSpec, sizeof(dirSpec), "bt(0,0)/Extra/%s", filename);
173 fd = open(dirSpec, 0);
174if (fd < 0)
175{
176 snprintf(dirSpec, sizeof(dirSpec), "bt(0,0)/Extra/Acpi/%s", filename);
177 fd = open(dirSpec, 0);
178if (fd < 0)
179{
180 // NOT FOUND:
181 dirSpec[0] = 0;
182 }
183 }
184}
185}
186}
187
188if (outDirspec) *outDirspec = dirSpec;
189return fd;
190}
191
192void *loadACPITable (const char *filename)
193{
194void *tableAddr;
195const char *dirspec = NULL;
196
197int fd = search_and_get_acpi_fd(filename, &dirspec);
198
199if (fd >= 0)
200{
201tableAddr = (void *)AllocateKernelMemory(file_size(fd));
202if (tableAddr)
203{
204if (read(fd, tableAddr, file_size(fd)) != file_size(fd))
205{
206verbose("loadACPITable: Couldn't read table from: %s.\n", dirspec);
207free(tableAddr);
208close(fd);
209return NULL;
210}
211//verbose("ACPIpatcher: Table %s read and stored at: 0x%08X\n", dirspec, tableAddr);
212close(fd);
213return tableAddr;
214}
215close(fd);
216verbose("loadACPITable: Couldn't allocate memory for table: %s.\n", dirspec);
217 }
218
219return NULL;
220}
221
222struct acpi_2_fadt *patch_fadt(struct acpi_2_fadt *fadt, struct acpi_2_dsdt *new_dsdt)
223{
224// extern void setupSystemType();
225
226struct acpi_2_fadt *fadt_mod = NULL;
227bool fadt_rev2_needed = false;
228bool fix_restart = false;
229bool fix_restart_ps2 = false;
230int value = 1;
231 static bool ver_20 = false;
232
233// Restart Fix
234if (Platform.CPU.Vendor == CPUID_VENDOR_INTEL) { // Intel=0x756E6547
235fix_restart = true;
236fix_restart_ps2 = false;
237if ( getBoolForKey(kPS2RestartFix, &fix_restart_ps2, &bootInfo->chameleonConfig) && fix_restart_ps2)
238{
239fix_restart = true;
240}
241else
242{
243getBoolForKey(kRestartFix, &fix_restart, &bootInfo->chameleonConfig);
244}
245}
246else
247{
248verbose("\tNot an Intel platform, FACP Restart Fix will not be applied!\n");
249fix_restart = false;
250}
251
252if (fix_restart)
253{
254fadt_rev2_needed = true;
255}
256
257// Allocate new fadt table
258if ((fadt->Length < 0x84) && fadt_rev2_needed)
259{
260fadt_mod = (struct acpi_2_fadt *)AllocateKernelMemory(0x84);
261memcpy(fadt_mod, fadt, fadt->Length);
262fadt_mod->Length = 0x84;
263fadt_mod->Revision = 0x02; // FACP rev 2 (ACPI 1.0B MS extensions)
264}
265else
266{
267fadt_mod = (struct acpi_2_fadt *)AllocateKernelMemory(fadt->Length);
268memcpy(fadt_mod, fadt, fadt->Length);
269}
270 verbose("\tNew FACP loaded @%08X, length=%d\n", (uint32_t)fadt_mod, fadt_mod->Length);
271
272// Bungo: Determine PM Profile
273verbose("\tPM Profile=0x%02X", fadt_mod->PM_Profile);
274if (getIntForKey(kSystemType, &value, &bootInfo->chameleonConfig))
275{
276verbose(", overriding with: 0x%02X.\n", (uint8_t)value);
277fadt_mod->PM_Profile = (uint8_t)value; // user has overriden the PM Profile so take care of it in FACP
278}
279else
280{
281 switch (fadt_mod->PM_Profile) { // check if PM Profile is correct (1..3)
282 case 1:
283 case 2:
284 case 3:
285 verbose(": using.\n");
286 break;
287 default:
288 // use SMBIOS chassisType to determine PM Profile (saved previously for us)
289 verbose(", expected value: 1, 2 or 3, setting to 0x%02X.\n", Platform.Type);
290 fadt_mod->PM_Profile = Platform.Type; // take care of modified FACP's PM Profile entry
291 break;
292 }
293 }
294Platform.Type = fadt_mod->PM_Profile; // Save fixed PM Profile (system-type)
295
296/* Bungo: Moved into fake_efi.c
297 // Setup system-type: We now have to write the systemm-type in ioregs: we cannot do it before in setupDeviceTree()
298// because we need to take care of FACP original content, if it is correct.
299setupSystemType();
300*/
301// Patch FACP to fix restart
302if (fix_restart) {
303if (fix_restart_ps2) {
304fadt_mod->Flags|= 0x400; // Reset register supported
305fadt_mod->Reset_SpaceID= 0x01; // System I/O
306fadt_mod->Reset_BitWidth= 0x08; // 1 byte
307fadt_mod->Reset_BitOffset= 0x00; // Offset 0
308fadt_mod->Reset_AccessWidth= 0x01; // Byte access
309fadt_mod->Reset_Address= 0x64; // Address of the register
310fadt_mod->Reset_Value= 0xfe; // Value to write to reset the system
311verbose("\tFACP PS2 Restart Fix applied!\n");
312}
313else
314{
315fadt_mod->Flags|= 0x400; // Reset register supported
316fadt_mod->Reset_SpaceID= 0x01; // System I/O
317fadt_mod->Reset_BitWidth= 0x08; // 1 byte
318fadt_mod->Reset_BitOffset= 0x00; // Offset 0
319fadt_mod->Reset_AccessWidth= 0x01; // Byte access
320fadt_mod->Reset_Address= 0x0cf9; // Address of the register
321fadt_mod->Reset_Value= 0x06; // Value to write to reset the system
322verbose("\tFACP Restart Fix applied!\n");
323}
324}
325else
326{
327 //verbose("\tRestart Fix: No.\n");
328 }
329
330 // Bungo: FACS table fix and load
331 verbose("\tOEM table FACS@%08X, length=%d: ", fadt_mod->FACS, ((struct acpi_2_facs *)fadt_mod->FACS)->Length);
332if ((fadt_mod->FACS > 0) && (fadt_mod->FACS < 0xFFFFFFFF) && (((struct acpi_2_facs *)fadt_mod->FACS)->Length >= 64))
333{
334 verbose("using.\n");
335}
336else
337{
338 verbose(" incorrect!\n");
339 }
340if (ver_20 && (((uint32_t)(&(fadt_mod->X_FACS)) - (uint32_t)fadt_mod + 8) <= fadt_mod->Length))
341{
342 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);
343if (fadt_mod->FACS != fadt_mod->X_FACS)
344{
345 verbose("differes from FACS - fixing");
346if ((fadt_mod->X_FACS > 0) && (fadt_mod->X_FACS < 0xFFFFFFFF) && (((struct acpi_2_facs *)(uint32_t)fadt_mod->X_FACS)->Length >= 64))
347{
348 // Bungo: in my case only from X_FACS loading correct table (64 bytes) into IOReg
349 fadt_mod->FACS = (uint32_t)fadt_mod->X_FACS;
350}
351else
352{
353 fadt_mod->X_FACS = (uint64_t)fadt_mod->FACS;
354 }
355 verbose(" \tUsing FACS@%08X = X_FACS@%08X\n", fadt_mod->FACS, (uint32_t)fadt_mod->X_FACS);
356}
357else
358{
359 verbose("using.\n");
360 }
361 }
362
363 // Bungo: Save Hardware Signature (machine-signature)
364 if ((fadt_mod->FACS > 0) && (fadt_mod->FACS < 0xFFFFFFFF) && (((struct acpi_2_facs *)fadt_mod->FACS)->Length >= 64)) {
365 Platform.HWSignature = ((struct acpi_2_facs *)fadt_mod->FACS)->HWSignature;
366 verbose("\tHardware Signature=0x%08X: using.\n", Platform.HWSignature);
367 } else {
368 Platform.HWSignature = 0;
369 verbose("\tFixing Hardware Signature=0x%08X.\n", Platform.HWSignature);
370 }
371
372 verbose("\tOEM table DSDT@%08X, length=%d: %susing.\n", fadt_mod->DSDT, ((struct acpi_2_dsdt *)fadt_mod->DSDT)->Length, new_dsdt ? "not " : "");
373 if (ver_20 && (((uint32_t)(&(fadt_mod->X_DSDT)) - (uint32_t)fadt_mod + 8) <= fadt_mod->Length)) {
374 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 " : "");
375 }
376// Patch DSDT address if we have loaded DSDT.aml
377if (new_dsdt) {
378 fadt_mod->DSDT = (uint32_t)new_dsdt;
379 verbose("\tFACP uses custom DSDT@%08X", fadt_mod->DSDT);
380if (ver_20 && (((uint32_t)(&(fadt_mod->X_DSDT)) - (uint32_t)fadt_mod + 8) <= fadt_mod->Length)) {
381fadt_mod->X_DSDT = (uint64_t)new_dsdt;
382 verbose(" / X_DSDT@%08X%08X", (uint32_t)(fadt_mod->X_DSDT >> 32), (uint32_t)(fadt_mod->X_DSDT & 0xFFFFFFFF));
383}
384 verbose(", length=%d\n", ((struct acpi_2_dsdt *)fadt_mod->DSDT)->Length);
385}
386
387// Correct the checksum
388fadt_mod->Checksum=0;
389fadt_mod->Checksum=256-checksum8(fadt_mod, fadt_mod->Length);
390
391 ver_20 = TRUE;
392return fadt_mod;
393}
394// Bung: Unused
395/* Setup ACPI without replacing DSDT.
396int setupAcpiNoMod()
397{
398//addConfigurationTable(&gEfiAcpiTableGuid, getAddressOfAcpiTable(), "ACPI");
399//addConfigurationTable(&gEfiAcpi20TableGuid, getAddressOfAcpi20Table(), "ACPI_20");
400// XXX aserebln why uint32 cast if pointer is uint64 ?
401acpi10_p = (uint64_t)(uint32_t)getAddressOfAcpiTable();
402acpi20_p = (uint64_t)(uint32_t)getAddressOfAcpi20Table();
403// addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
404if(acpi20_p)
405{
406// addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
407}
408else
409{
410DBG("ACPIpatcher: version 2.0 not found.\n");
411}
412return 1;
413}
414*/
415/* Setup ACPI. Replace DSDT if DSDT.aml is found */
416int setupAcpi(void)
417{
418int version;
419const char *filename;
420char dirSpec[128];
421int len = 0;
422
423// always reset cpu count to 0 when injecting new acpi
424acpi_cpu_count = 0;
425
426 verbose("\nACPIpatcher: Start patching...\n");
427
428 if (new_dsdt != NULL) {
429 verbose("ACPIpatcher: custom table DSDT already loaded @%08X, length=%d: using.\n", new_dsdt, ((struct acpi_2_header *)new_dsdt)->Length);
430 } else {
431 // Try using the file specified with the DSDT option
432 if (getValueForKey(kDSDT, &filename, &len, &bootInfo->chameleonConfig) && len) {
433 snprintf(dirSpec, sizeof(dirSpec), filename);
434 } else {
435 sprintf(dirSpec, "DSDT.aml");
436 }
437
438 verbose("ACPIpatcher: attempting to load custom table DSDT...\n", dirSpec);
439 if ((new_dsdt = loadACPITable(dirSpec))) {
440 verbose("ACPIpatcher: custom table DSDT loaded @%08X, length=%d.\n", new_dsdt, ((struct acpi_2_header *)new_dsdt)->Length);
441 } else {
442 //verbose("ACPIpatcher: custom DSDT not found!.\n");
443 }
444 }
445
446/* Try using the file specified with the DSDT option
447if (getValueForKey(kDSDT, &filename, &len, &bootInfo->chameleonConfig)) {
448snprintf(dirSpec, sizeof(dirSpec), filename);
449} else {
450sprintf(dirSpec, "DSDT.aml");
451//DBG("dirSpec, DSDT.aml");
452}
453
454// Load replacement DSDT
455new_dsdt = loadACPITable(dirSpec);
456*/
457
458 // Load ECDT table
459 if (new_ecdt != NULL) {
460 verbose("ACPIpatcher: custom table ECDT already loaded @%08X, length=%d: using.\n", new_ecdt, ((struct acpi_2_header *)new_ecdt)->Length);
461 } else {
462 sprintf(dirSpec, "ECDT.aml");
463 filename = "ECDT.aml";
464 verbose("ACPIpatcher: attempting to load custom table ECDT...\n");
465 if ((new_ecdt = loadACPITable(filename))) {
466 verbose("ACPIpatcher: custom table ECDT loaded @%08X, length=%d.\n", new_ecdt, ((struct acpi_2_header *)new_ecdt)->Length);
467 } else {
468 //verbose("ACPIpatcher: custom ECDT not found!.\n");
469 }
470 }
471
472 // Mozodojo: Load additional SSDTs
473struct acpi_2_ssdt *new_ssdt[32]; // 26 custom + 4 subssdt + 2 for pss & cst
474int ssdtotal_number = 0;
475{
476int i;
477for (i = 0; i < 26; i++) {
478//char filename[512];
479
480sprintf(dirSpec, (i > 0)? "SSDT-%d.aml":"SSDT.aml", i);
481
482if ((new_ssdt[ssdtotal_number] = loadACPITable(dirSpec))) {
483 verbose("ACPIpatcher: custom table %s loaded @%08X, length=%d\n", dirSpec, new_ssdt[ssdtotal_number], new_ssdt[ssdtotal_number]->Length);
484 ssdtotal_number++;
485} else {
486 //verbose("ACPIpatcher: custom table '%s' not found.\n", filename);
487 // Bungo: load up to 26 custom tables enabled now
488//break;
489}
490}
491}
492
493// Mozodojo: going to patch FACP and load SSDTs even if DSDT.aml is not present
494/*if (!new_dsdt)
495 {
496 return setupAcpiNoMod();
497 }*/
498
499// SSDT options
500bool drop_ssdt = false, generate_pstates = false, generate_cstates = false;
501
502getBoolForKey(kDropSSDT, &drop_ssdt, &bootInfo->chameleonConfig);
503getBoolForKey(kGeneratePStates, &generate_pstates, &bootInfo->chameleonConfig);
504getBoolForKey(kGenerateCStates, &generate_cstates, &bootInfo->chameleonConfig);
505 verbose("ACPIpatcher: drop SSDT tables: %s.\n", drop_ssdt ? "Yes" : "No");
506verbose("ACPIpatcher: generate P-States: %s.\n", generate_pstates ? "Yes" : "No");
507verbose("ACPIpatcher: generate C-States: %s.\n", generate_cstates ? "Yes" : "No");
508
509 bool getSubSSDT = !generate_pstates && !generate_cstates;
510
511// Do the same procedure for both versions of ACPI
512for (version = 0; version < 2; version++)
513{
514struct acpi_2_rsdp *rsdp, *rsdp_mod;
515struct acpi_2_rsdt *rsdt, *rsdt_mod;
516 struct acpi_2_xsdt *xsdt, *xsdt_mod;
517 struct acpi_2_fadt *fadt_mod;
518 uint32_t *rsdt_entries;
519 uint64_t *xsdt_entries;
520
521// Find original rsdp
522rsdp = (struct acpi_2_rsdp *)(version ? getAddressOfAcpi20Table() : getAddressOfAcpiTable());
523if (!rsdp) {
524 /*
525if (version) {
526addConfigurationTable(&gEfiAcpi20TableGuid, NULL, "ACPI_20");
527} else {
528addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI");
529}
530 */
531 verbose("ACPIpatcher: ACPI version %d.0 not found. Not patching.\n", version + 1);
532continue;
533}
534
535 int rsdplength = version ? rsdp->Length : 20;
536int l = version ? 20 : 0;
537verbose("ACPIpatcher: OEM table RSDP@%08X, length=%d. ACPI version %d.0: patching.\n", rsdp, rsdplength, version + 1);
538
539/* FIXME: no check that memory allocation succeeded
540 * Copy and patch RSDP, RSDT, XSDT and FADT
541 * For more info see ACPI Specification pages 110 and following
542 */
543
544rsdp_mod = (struct acpi_2_rsdp *)(l + AllocateKernelMemory(l + rsdplength));
545memcpy(rsdp_mod, rsdp, rsdplength);
546
547rsdt = (struct acpi_2_rsdt *)rsdp->RsdtAddress;
548verbose("ACPIpatcher: OEM table RSDT@%08X, length=%d: ", rsdp->RsdtAddress, rsdt->Length);
549
550if ((rsdp->RsdtAddress > 0) && (rsdp->RsdtAddress < 0xFFFFFFFF) && (rsdt->Length < 0x10000)) {
551 verbose("using.\n");
552int rsdt_entries_num;
553int dropoffset = 0, i, j;
554
555// mozo: using malloc cos I didn't found how to free already allocated kernel memory
556rsdt_mod = (struct acpi_2_rsdt *)malloc(rsdt->Length);
557memcpy(rsdt_mod, rsdt, rsdt->Length);
558rsdp_mod->RsdtAddress = (uint32_t)rsdt_mod;
559rsdt_entries_num = (rsdt_mod->Length - sizeof(struct acpi_2_rsdt)) / 4;
560rsdt_entries = (uint32_t *)(rsdt_mod + 1);
561
562for (i = 0; i < rsdt_entries_num; i++) {
563 struct acpi_2_header *oemTable = (struct acpi_2_header *)rsdt_entries[i];
564 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);
565
566if (!(rsdt_entries[i] > 0) || !(rsdt_entries[i] < 0xFFFFFFFF)) {
567 verbose("incorrect! Dropping.\n");
568 dropoffset++;
569 continue;
570}
571
572if (tableSign(oemTable, "SSDT")) {
573 if (drop_ssdt) {
574 verbose("dropping.\n");
575 dropoffset++;
576 } else {
577 verbose("using.\n");
578 rsdt_entries[i-dropoffset] = rsdt_entries[i];
579 // get rest of ssdt tables from inside ssdt_pmref
580 if (getSubSSDT) { // prevent from extracting originals if user choosed generatind PSS and/or CSS tables
581 struct ssdt_pmref *subSSDT = (struct ssdt_pmref *)(rsdt_entries[i] + sizeof(struct acpi_2_header) + 15);
582 uint8_t tabNum = *((uint8_t *)subSSDT - 2) / 3; // e.g Name (SSDT, Package (0x0C) -> 0x0C / 3 = number of sub SSDTs
583 for (j = 0; (j < tabNum) && (ssdtotal_number < 30); j++) {
584 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);
585 if (!(subSSDT[j].addr > 0) || !(subSSDT[j].addr < 0xFFFFFFFF)) {
586 verbose("incorrect! Dropping.\n");
587 continue;
588 }
589 verbose("using.\n");
590 new_ssdt[ssdtotal_number] = (struct acpi_2_ssdt *)subSSDT[j].addr;
591 ssdtotal_number++;
592 }
593 }
594 }
595 continue;
596}
597
598 /* Bungo: According to ACPI Spec. no DSDT in RSDT, so what this for?
599
600 if (tableSign(oemTable, "DSDT")) {
601if (new_dsdt) {
602rsdt_entries[i-dropoffset] = (uint32_t)new_dsdt;
603verbose("custom table added.\n");
604}
605continue;
606}
607
608 So, suggest to drop, it should be in FACP */
609
610 if (tableSign(oemTable, "DSDT")) {
611 verbose("dropping.\n");
612 dropoffset++;
613 continue;
614}
615
616 if (tableSign(oemTable, "ECDT") && new_ecdt) {
617 verbose("dropping.\n");
618 dropoffset++;
619 continue;
620}
621
622if (tableSign(oemTable, "FACP")) {
623if (oemTable->Length > 0x10000) {
624verbose("incorrect. Not modifying.\n");
625continue;
626}
627
628verbose("patching.\n");
629fadt_mod = patch_fadt((struct acpi_2_fadt *)oemTable, new_dsdt);
630rsdt_entries[i-dropoffset] = (uint32_t)fadt_mod;
631
632// Generate _CST SSDT
633if (generate_cstates && (new_ssdt[ssdtotal_number] = generate_cst_ssdt(fadt_mod))) {
634verbose("\tC-States generated.\n");
635generate_cstates = false; // Generate SSDT only once!
636ssdtotal_number++;
637}
638
639// Generating _PSS SSDT
640if (generate_pstates && (new_ssdt[ssdtotal_number] = generate_pss_ssdt((void*)fadt_mod->DSDT))) {
641verbose("\tP-States generated.\n");
642generate_pstates = false; // Generate SSDT only once!
643ssdtotal_number++;
644}
645continue;
646}
647
648 verbose("using.\n");
649 rsdt_entries[i-dropoffset] = rsdt_entries[i];
650}
651
652 // For moded rsdt calculate new lenght
653 if (new_ecdt)
654 rsdt_mod->Length += 4*ssdtotal_number - 4*dropoffset + 4; // custom - dropped + ECDT
655else
656 rsdt_mod->Length += 4*ssdtotal_number - 4*dropoffset;
657 // Allocate moded rsdt in Kernel memory area
658struct acpi_2_rsdt *rsdt_copy = (struct acpi_2_rsdt *)AllocateKernelMemory(rsdt_mod->Length);
659 memcpy(rsdt_copy, rsdt_mod, rsdt_mod->Length); // should be rsdt_mod->Length - 4*ssdtotal_number - 4 but don't care
660free(rsdt_mod);
661rsdt_mod = rsdt_copy;
662rsdp_mod->RsdtAddress = (uint32_t)rsdt_mod;
663rsdt_entries_num = (rsdt_mod->Length-sizeof(struct acpi_2_rsdt)) / 4;
664rsdt_entries = (uint32_t *)(rsdt_mod + 1);
665
666// Mozodojo: Insert additional SSDTs into RSDT
667 for (j = 0; j < ssdtotal_number; j++) {
668 rsdt_entries[i-dropoffset+j] = (uint32_t)new_ssdt[j];
669 }
670 verbose("ACPIpatcher: added %d custom SSDT table%s into RSDT.\n", ssdtotal_number, (ssdtotal_number != 1) ? "s" : "");
671
672if (new_ecdt) {
673rsdt_entries[i - dropoffset + j] = (uint32_t)new_ecdt;
674verbose("ACPIpatcher: added custom table %s @%08X into RSDT.\n", "ECDT", new_ecdt);
675}
676
677// Correct the checksum of RSDT
678verbose("ACPIpatcher: modified RSDT@%08X, length=%d. Checksum: old=%d, ", rsdt_mod, rsdt_mod->Length, rsdt_mod->Checksum);
679rsdt_mod->Checksum=0;
680rsdt_mod->Checksum=256-checksum8(rsdt_mod,rsdt_mod->Length);
681verbose("new=%d.\n", rsdt_mod->Checksum);
682} else {
683rsdp_mod->RsdtAddress = 0;
684verbose("not found or incorrect!\n");
685}
686verbose("\n");
687
688 if (gVerboseMode) pause("");
689
690if (version) {
691// FIXME: handle 64-bit address correctly
692xsdt = (struct acpi_2_xsdt *)(uint32_t)rsdp->XsdtAddress;
693 verbose("ACPIpatcher: OEM table XSDT@%08X%08X, length=%d: ", (uint32_t)(rsdp->XsdtAddress >> 32), (uint32_t)(rsdp->XsdtAddress & 0xFFFFFFFF), xsdt->Length);
694
695if ((rsdp->XsdtAddress > 0) && (rsdp->XsdtAddress < 0xFFFFFFFF) && (xsdt->Length < 0x10000)) {
696 verbose("using.\n");
697int xsdt_entries_num, i, j;
698int dropoffset = 0;
699
700// mozo: using malloc cos I didn't found how to free already allocated kernel memory
701xsdt_mod = (struct acpi_2_xsdt *)malloc(xsdt->Length);
702memcpy(xsdt_mod, xsdt, xsdt->Length);
703 rsdp_mod->XsdtAddress = (uint64_t)xsdt_mod;
704xsdt_entries_num = (xsdt_mod->Length - sizeof(struct acpi_2_xsdt)) / 8;
705xsdt_entries = (uint64_t *)(xsdt_mod + 1);
706
707for (i = 0; i < xsdt_entries_num; i++) {
708 struct acpi_2_header *oemTable = (struct acpi_2_header *)(uint32_t)xsdt_entries[i];
709 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);
710
711if (!(xsdt_entries[i] > 0) || !(xsdt_entries[i] < 0xFFFFFFFF)) {
712 verbose(": incorrect! Dropping.\n");
713 dropoffset++;
714continue;
715}
716
717 bool inRSDT = (uint32_t)oemTable == ((uint32_t *)(rsdt + 1))[i]; // check if already in RSDT
718 if (inRSDT) {
719 verbose(" (already in RSDT)");
720 }
721
722 if (tableSign(oemTable, "SSDT") && !inRSDT) {
723 if (drop_ssdt) {
724 verbose(": dropping.\n");
725 dropoffset++;
726 } else {
727 verbose(": using.\n");
728 xsdt_entries[i - dropoffset] = xsdt_entries[i];
729 // Get rest of ssdts from ssdt_pmref
730 if (getSubSSDT) {
731 struct ssdt_pmref *subSSDT = (struct ssdt_pmref *)((uint32_t)xsdt_entries[i - dropoffset] + sizeof(struct acpi_2_header) + 15);
732 uint8_t tabNum = *((uint8_t *)subSSDT - 2) / 3; // e.g: Name (SSDT, Package (0x0C) -> 0x0C / 3 = 4 is number of sub SSDTs
733 for (j = 0; (j < tabNum) && (ssdtotal_number < 30); j++) {
734 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);
735 if (!(subSSDT[j].addr > 0) || !(subSSDT[j].addr < 0xFFFFFFFF)) {
736 verbose(": incorrect! Dropping.\n");
737 continue;
738 }
739 new_ssdt[ssdtotal_number] = (struct acpi_2_ssdt *)subSSDT[j].addr;
740 ssdtotal_number++;
741 verbose(": using.\n");
742 }
743 }
744 }
745 continue;
746 }
747
748 // Bungo: According to ACPI Spec. no DSDT in RSDT, so what this for?
749 /*
750 if (tableSign(oemTable, "DSDT")) {
751 if (new_dsdt) {
752 xsdt_entries[i-dropoffset] = (uint64_t)new_dsdt;
753 verbose("custom table added.\n");
754 }
755 continue;
756 }
757 */
758 // Suggest to drop, it should be in FACP
759 if (tableSign(oemTable, "DSDT") && !inRSDT) {
760 verbose(": dropping.\n");
761 dropoffset++;
762 continue;
763 }
764
765if (tableSign(oemTable, "FACP") && !inRSDT) {
766if (oemTable->Length > 0x10000) {
767goto drop_xsdt;
768}
769
770 verbose(": patching.\n");
771fadt_mod = patch_fadt((struct acpi_2_fadt *)oemTable, new_dsdt);
772xsdt_entries[i - dropoffset] = (uint64_t)fadt_mod;
773
774// Generate _CST SSDT
775if (generate_cstates && (new_ssdt[ssdtotal_number] = generate_cst_ssdt(fadt_mod))) {
776verbose("\tC-States generated\n");
777generate_cstates = false; // Generate SSDT only once!
778ssdtotal_number++;
779}
780
781// Generating _PSS SSDT
782if (generate_pstates && (new_ssdt[ssdtotal_number] = generate_pss_ssdt((void *)fadt_mod->DSDT))) {
783verbose("\tP-States generated\n");
784generate_pstates = false; // Generate SSDT only once!
785ssdtotal_number++;
786}
787continue;
788}
789
790 verbose(": using.\n");
791 xsdt_entries[i - dropoffset] = xsdt_entries[i];
792}
793
794 // For moded xsdt calculate new lenght
795 if (new_ecdt)
796 xsdt_mod->Length += 8*ssdtotal_number - 8*dropoffset + 8; // custom - dropped + ECDT
797 else
798 xsdt_mod->Length += 8*ssdtotal_number - 8*dropoffset;
799 // Allocate xsdt in Kernel memory area
800struct acpi_2_xsdt *xsdt_copy = (struct acpi_2_xsdt *)AllocateKernelMemory(xsdt_mod->Length);
801memcpy(xsdt_copy, xsdt_mod, xsdt_mod->Length); // should be: rsdt_mod->Length - 8*ssdtotal_number - 8 but don't care
802free(xsdt_mod);
803 xsdt_mod = xsdt_copy;
804rsdp_mod->XsdtAddress = (uint64_t)xsdt_mod;
805xsdt_entries_num = (xsdt_mod->Length - sizeof(struct acpi_2_xsdt)) / 8;
806xsdt_entries = (uint64_t *)(xsdt_mod + 1);
807
808// Mozodojo: Insert additional SSDTs into XSDT
809 for (j = 0; j < ssdtotal_number; j++) {
810 xsdt_entries[i-dropoffset+j] = (uint64_t)new_ssdt[j];
811 }
812 verbose("ACPIpatcher: added %d custom SSDT table%s into XSDT.\n", ssdtotal_number, (ssdtotal_number != 1) ? "s" : "");
813
814if (new_ecdt) {
815xsdt_entries[i - dropoffset + j] = (uint64_t)new_ecdt;
816verbose("ACPIpatcher: added custom table %s@%016X into XSDT.\n", "ECDT", new_ecdt);
817}
818
819// Correct the checksum of XSDT
820verbose("ACPIpatcher: modified XSDT@%016X, length=%d. Checksum: old=%d, ", xsdt_mod, xsdt_mod->Length, xsdt_mod->Checksum);
821 xsdt_mod->Checksum=0;
822 xsdt_mod->Checksum=256-checksum8(xsdt_mod, xsdt_mod->Length);
823 verbose("new=%d.\n", xsdt_mod->Checksum);
824} else {
825drop_xsdt:
826/*FIXME: Now we just hope that if MacOS doesn't find XSDT it reverts to RSDT.
827 * A Better strategy would be to generate
828 */
829 verbose("not found or incorrect!\n");
830rsdp_mod->XsdtAddress=0xffffffffffffffffLL;
831}
832
833 if (gVerboseMode) pause("");
834}
835
836// Correct the checksum of RSDP
837verbose("ACPIpatcher: modified RSDP@%08X, checksum: old=%d, ", rsdp_mod, rsdp_mod->Checksum);
838rsdp_mod->Checksum=0;
839rsdp_mod->Checksum=256-checksum8(rsdp_mod, 20);
840verbose("new=%d", rsdp_mod->Checksum);
841
842if (version) {
843verbose("; extended checksum: old=%d, ", rsdp_mod->ExtendedChecksum);
844rsdp_mod->ExtendedChecksum=0;
845rsdp_mod->ExtendedChecksum=256-checksum8(rsdp_mod,rsdp_mod->Length);
846verbose("new=%d.\n", rsdp_mod->ExtendedChecksum);
847} else {
848 verbose(".\n");
849 }
850
851if (version) {
852acpi20_p = (uint64_t)(uint32_t)rsdp_mod; // efi configuration table pointer to ACPI_20 RSDP
853 acpi10_p = acpi20_p - 20; // efi configuration table pointer to ACPI RSDP
854 memcpy((struct acpi_2_rsdp *)(uint32_t)acpi10_p, (struct acpi_2_rsdp *)(uint32_t)acpi20_p, 20);
855//addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
856} else {
857acpi10_p = (uint64_t)(uint32_t)rsdp_mod; // efi configuration table pointer to ACPI RSDP
858//addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
859}
860
861 verbose("ACPIpatcher: acpi version %d.0 patching finished.\n", version + 1);
862}
863
864#if DEBUG_ACPI
865 pause("[DEBUG ACPI] ");
866#else
867 if (gVerboseMode) pause("");
868#endif
869
870return 1;
871}
872
873struct acpi_2_rsdp *getRSDPaddress()
874{
875 bool found = false;
876 /* Before searching the BIOS space we are supposed to search the first 1K of the EBDA */
877EBDA_RANGE_START = (uint32_t)swapUint16(*(uint16_t *)BDA_EBDA_START) << 4;
878 verbose("getRSDPaddress: scanning EBDA [%08X:%08X] for RSDP... ", EBDA_RANGE_START, EBDA_RANGE_END);
879 void *rsdp_addr = (void*)EBDA_RANGE_START;
880for (; rsdp_addr <= (void*)EBDA_RANGE_END; rsdp_addr += 1) {
881if (*(uint64_t *)rsdp_addr == ACPI_SIGNATURE_UINT64_LE) {
882 found = true;
883 break;
884}
885}
886
887 if (!found) {
888 verbose("Nothing found.\n");
889 verbose("getRSDPaddress: scanning BIOS area [%08X:%08X] for RSDP... ", ACPI_RANGE_START, ACPI_RANGE_END);
890 rsdp_addr = (void*)ACPI_RANGE_START;
891 for (; rsdp_addr <= (void*)ACPI_RANGE_END; rsdp_addr += 16) {
892 if (*(uint64_t *)rsdp_addr == ACPI_SIGNATURE_UINT64_LE) {
893 found = true;
894 break;
895 }
896 }
897 }
898
899 if (found) {
900 verbose("Found @0%08X, Rev.: %d.0).\n", rsdp_addr, ((struct acpi_2_rsdp *)rsdp_addr)->Revision + 1);
901 uint8_t csum = checksum8(rsdp_addr, 20);
902 if (csum == 0) {
903 if (((struct acpi_2_rsdp *)rsdp_addr)->Revision == 0) return rsdp_addr;
904 csum = checksum8(rsdp_addr, sizeof(struct acpi_2_rsdp));
905 if (csum == 0) return rsdp_addr;
906 else verbose("getRSDPaddress: RSDP extended checksum incorrect: %d.\n", csum);
907 } else verbose("getRSDPaddress: RSDP checksum incorrect: %d.\n", csum);
908 } else verbose("Nothing found.\n");
909
910return NULL;
911}
912

Archive Download this file

Revision: 2537