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

Archive Download this file

Revision: HEAD