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

Archive Download this file

Revision: 2839