Chameleon

Chameleon Svn Source Tree

Root/trunk/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// Slice: New signature compare function
31boolean_t tableSign(char *table, const char *sgn)
32{
33int i;
34for (i = 0; i < 4; i++)
35{
36if ((table[i] &~0x20) != (sgn[i] &~0x20))
37{
38return false;
39}
40}
41return true;
42}
43
44/* Gets the ACPI 1.0 RSDP address */
45static struct acpi_2_rsdp *getAddressOfAcpiTable()
46{
47/* TODO: Before searching the BIOS space we are supposed to search the first 1K of the EBDA */
48
49void *acpi_addr = (void*)ACPI_RANGE_START;
50
51for(; acpi_addr <= (void*)ACPI_RANGE_END; acpi_addr += 16)
52{
53if(*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE)
54{
55uint8_t csum = checksum8(acpi_addr, 20);
56if(csum == 0)
57{
58// Only return the table if it is a true version 1.0 table (Revision 0)
59if(((struct acpi_2_rsdp*)acpi_addr)->Revision == 0)
60return acpi_addr;
61}
62}
63}
64return NULL;
65}
66
67/* Gets the ACPI 2.0 RSDP address */
68static struct acpi_2_rsdp *getAddressOfAcpi20Table()
69{
70/* TODO: Before searching the BIOS space we are supposed to search the first 1K of the EBDA */
71
72void *acpi_addr = (void *)ACPI_RANGE_START;
73
74for(; acpi_addr <= (void *)ACPI_RANGE_END; acpi_addr += 16)
75{
76if(*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE)
77{
78uint8_t csum = checksum8(acpi_addr, 20);
79
80/* Only assume this is a 2.0 or better table if the revision is greater than 0
81 * NOTE: ACPI 3.0 spec only seems to say that 1.0 tables have revision 1
82 * and that the current revision is 2.. I am going to assume that rev > 0 is 2.0.
83 */
84
85if(csum == 0 && (((struct acpi_2_rsdp*)acpi_addr)->Revision > 0))
86{
87uint8_t csum2 = checksum8(acpi_addr, sizeof(struct acpi_2_rsdp));
88if(csum2 == 0)
89{
90return acpi_addr;
91}
92}
93}
94}
95return NULL;
96}
97
98/* The folowing ACPI Table search algo. should be reused anywhere needed:*/
99/* WARNING: outDirspec string will be overwritten by subsequent calls! */
100int search_and_get_acpi_fd(const char *filename, const char **outDirspec)
101{
102int fd = 0;
103static char dirSpec[512];
104
105// Try finding 'filename' in the usual places
106// Start searching any potential location for ACPI Table
107strncpy(dirSpec, filename, sizeof(dirSpec) );
108fd = open(dirSpec, 0);
109if (fd < 0)
110{
111snprintf(dirSpec, sizeof(dirSpec), "/Extra/%s", filename);
112fd = open(dirSpec, 0);
113if (fd < 0)
114{
115snprintf(dirSpec, sizeof(dirSpec), "bt(0,0)/Extra/%s", filename);
116fd = open(dirSpec, 0);
117if (fd < 0)
118{
119// NOT FOUND:
120DBG("ACPI Table not found: %s\n", filename);
121*dirSpec = '\0';
122}
123}
124}
125
126if (outDirspec) *outDirspec = dirSpec;
127return fd;
128}
129
130void *loadACPITable (const char *filename)
131{
132const char *dirspec = NULL;
133
134int fd = search_and_get_acpi_fd(filename, &dirspec);
135
136if (fd >= 0)
137{
138void *tableAddr = (void*)AllocateKernelMemory(file_size(fd));
139if (tableAddr)
140{
141if (read(fd, tableAddr, file_size(fd)) != file_size(fd))
142{
143DBG("Couldn't read table %s\n",dirspec);
144free(tableAddr);
145close(fd);
146return NULL;
147}
148
149DBG("Table %s read and stored at: %x\n", dirspec, tableAddr);
150close(fd);
151return tableAddr;
152}
153close(fd);
154DBG("Couldn't allocate memory for table \n", dirspec);
155}
156//printf("Couldn't find table %s\n", filename);
157return NULL;
158}
159
160uint8_t acpi_cpu_count= 0;
161uint32_t acpi_cpu_p_blk= 0;
162char *acpi_cpu_name[32];
163
164void get_acpi_cpu_names(unsigned char *dsdt, uint32_t length)
165{
166uint32_t i;
167
168DBG("ACPIpatcher: start finding cpu names. Length %d\n", length);
169
170for (i=0; i<length-7; i++)
171{
172if (dsdt[i] == 0x5B && dsdt[i+1] == 0x83) // ProcessorOP
173{
174DBG("ACPIpatcher: DSDT[%X%X]\n", dsdt[i], dsdt[i+1]);
175
176uint32_t offset = i + 3 + (dsdt[i+2] >> 6);
177
178bool add_name = true;
179
180uint8_t j;
181
182for (j=0; j<4; j++)
183{
184char c = dsdt[offset+j];
185
186if (!aml_isvalidchar(c))
187{
188add_name = false;
189DBG("ACPIpatcher: invalid character found in ProcessorOP '0x%X'!\n", c);
190break;
191}
192}
193
194if (add_name)
195{
196acpi_cpu_name[acpi_cpu_count] = malloc(4);
197memcpy(acpi_cpu_name[acpi_cpu_count], dsdt+offset, 4);
198i = offset + 5;
199
200if (acpi_cpu_count == 0)
201{
202acpi_cpu_p_blk = dsdt[i] | (dsdt[i+1] << 8);
203}
204
205DBG("ACPIpatcher: found ACPI CPU [%c%c%c%c]\n", acpi_cpu_name[acpi_cpu_count][0], acpi_cpu_name[acpi_cpu_count][1], acpi_cpu_name[acpi_cpu_count][2], acpi_cpu_name[acpi_cpu_count][3]);
206
207if (++acpi_cpu_count == 32)
208{
209return;
210}
211}
212}
213}
214
215DBG("ACPIpatcher: finished finding cpu names. Found: %d.\n", acpi_cpu_count);
216}
217
218struct acpi_2_fadt *patch_fadt(struct acpi_2_fadt *fadt, struct acpi_2_dsdt *new_dsdt)
219{
220extern void setupSystemType();
221
222struct acpi_2_fadt *fadt_mod = NULL;
223bool fadt_rev2_needed = false;
224bool fix_restart;
225bool fix_restart_ps2;
226const char * value;
227
228// Restart Fix
229if (Platform.CPU.Vendor == 0x756E6547)
230{/* Intel */
231fix_restart = true;
232fix_restart_ps2 = false;
233if ( getBoolForKey(kPS2RestartFix, &fix_restart_ps2, &bootInfo->chameleonConfig) && fix_restart_ps2)
234{
235fix_restart = true;
236}
237else
238{
239getBoolForKey(kRestartFix, &fix_restart, &bootInfo->chameleonConfig);
240}
241}
242else
243{
244DBG("Not an Intel platform: Restart Fix not applied !!!\n");
245fix_restart = false;
246}
247
248if (fix_restart)
249{
250fadt_rev2_needed = true;
251}
252
253// Allocate new fadt table
254if (fadt->Length < 0x84 && fadt_rev2_needed)
255{
256fadt_mod = (struct acpi_2_fadt *)AllocateKernelMemory(0x84);
257memcpy(fadt_mod, fadt, fadt->Length);
258fadt_mod->Length = 0x84;
259fadt_mod->Revision = 0x02; // FADT rev 2 (ACPI 1.0B MS extensions)
260}
261else
262{
263fadt_mod = (struct acpi_2_fadt *)AllocateKernelMemory(fadt->Length);
264memcpy(fadt_mod, fadt, fadt->Length);
265}
266// Determine system type / PM_Model
267if ( (value=getStringForKey(kSystemType, &bootInfo->chameleonConfig))!=NULL)
268{
269if (Platform.Type > 6)
270{
271if(fadt_mod->PM_Profile<=6)
272{
273Platform.Type = fadt_mod->PM_Profile; // get the fadt if correct
274}
275else
276{
277Platform.Type = 1;/* Set a fixed value (Desktop) */
278}
279DBG("Error: system-type must be 0..6. Defaulting to %d !\n", Platform.Type);
280}
281else
282{
283Platform.Type = (unsigned char) strtoul(value, NULL, 10);
284}
285}
286// Set PM_Profile from System-type if only user wanted this value to be forced
287if (fadt_mod->PM_Profile != Platform.Type)
288{
289if (value)
290{
291// user has overriden the SystemType so take care of it in FACP
292DBG("FADT: changing PM_Profile from 0x%02x to 0x%02x\n", fadt_mod->PM_Profile, Platform.Type);
293fadt_mod->PM_Profile = Platform.Type;
294}
295else
296{
297// PM_Profile has a different value and no override has been set, so reflect the user value to ioregs
298Platform.Type = fadt_mod->PM_Profile <= 6 ? fadt_mod->PM_Profile : 1;
299}
300}
301// We now have to write the systemm-type in ioregs: we cannot do it before in setupDeviceTree()
302// because we need to take care of FACP original content, if it is correct.
303setupSystemType();
304
305// Patch FADT to fix restart
306if (fix_restart)
307{
308if (fix_restart_ps2)
309{
310fadt_mod->Flags|= 0x400;
311fadt_mod->Reset_SpaceID= 0x01; // System I/O
312fadt_mod->Reset_BitWidth= 0x08; // 1 byte
313fadt_mod->Reset_BitOffset= 0x00; // Offset 0
314fadt_mod->Reset_AccessWidth= 0x01; // Byte access
315fadt_mod->Reset_Address= 0x64; // Address of the register
316fadt_mod->Reset_Value= 0xfe; // Value to write to reset the system
317DBG("FADT: PS2 Restart Fix applied!\n");
318}
319else
320{
321fadt_mod->Flags|= 0x400;
322fadt_mod->Reset_SpaceID= 0x01; // System I/O
323fadt_mod->Reset_BitWidth= 0x08; // 1 byte
324fadt_mod->Reset_BitOffset= 0x00; // Offset 0
325fadt_mod->Reset_AccessWidth= 0x01; // Byte access
326fadt_mod->Reset_Address= 0x0cf9; // Address of the register
327fadt_mod->Reset_Value= 0x06; // Value to write to reset the system
328DBG("FADT: ACPI Restart Fix applied!\n");
329}
330
331}
332
333// Bungo: Save Hardware Signature (machine-signature)
334if ((fadt_mod->FIRMWARE_CTRL > 0) && (fadt_mod->FIRMWARE_CTRL < 0xFFFFFFFF) && (((struct acpi_2_facs *)fadt_mod->FIRMWARE_CTRL)->Length >= 64))
335{
336Platform.HWSignature = ((struct acpi_2_facs *)fadt_mod->FIRMWARE_CTRL)->HWSignature;
337DBG("\tHardware Signature=0x%08X: using.\n", Platform.HWSignature);
338}
339else
340{
341Platform.HWSignature = 0;
342DBG("\tFixing Hardware Signature=0x%08X.\n", Platform.HWSignature);
343}
344
345// Patch DSDT address if we have loaded DSDT.aml
346if (new_dsdt)
347{
348DBG("DSDT: Old @%x,%x, ",fadt_mod->DSDT,fadt_mod->X_DSDT);
349
350fadt_mod->DSDT = (uint32_t)new_dsdt;
351if ((uint32_t)(&(fadt_mod->X_DSDT)) - (uint32_t)fadt_mod + 8<=fadt_mod->Length)
352{
353fadt_mod->X_DSDT = (uint32_t)new_dsdt;
354}
355
356DBG("New @%x,%x\n",fadt_mod->DSDT,fadt_mod->X_DSDT);
357
358DBG("FADT: Using custom DSDT!\n");
359}
360
361// Correct the checksum
362fadt_mod->Checksum=0;
363fadt_mod->Checksum=256-checksum8(fadt_mod,fadt_mod->Length);
364
365return fadt_mod;
366}
367
368/* Setup ACPI without replacing DSDT. */
369int setupAcpiNoMod()
370{
371//addConfigurationTable(&gEfiAcpiTableGuid, getAddressOfAcpiTable(), "ACPI");
372//addConfigurationTable(&gEfiAcpi20TableGuid, getAddressOfAcpi20Table(), "ACPI_20");
373/* XXX aserebln why uint32 cast if pointer is uint64 ? */
374acpi10_p = (uint64_t)(uint32_t)getAddressOfAcpiTable();
375acpi20_p = (uint64_t)(uint32_t)getAddressOfAcpi20Table();
376addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
377if(acpi20_p)
378{
379addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
380}
381else
382{
383DBG("No ACPI 2.\n");
384}
385return 1;
386}
387
388/* Setup ACPI. Replace DSDT if DSDT.aml is found */
389int setupAcpi(void)
390{
391int version;
392void *new_dsdt = NULL;
393
394
395const char *filename;
396char dirSpec[128];
397int len = 0;
398
399// always reset cpu count to 0 when injecting new acpi
400acpi_cpu_count = 0;
401
402/* Try using the file specified with the DSDT option */
403if (getValueForKey(kDSDT, &filename, &len, &bootInfo->chameleonConfig))
404{
405strncpy(dirSpec, filename, sizeof(dirSpec) );
406}
407else
408{
409strcpy(dirSpec, "DSDT.aml");
410//verbose("dirSpec, DSDT.aml");
411}
412
413// Load replacement DSDT
414new_dsdt = loadACPITable(dirSpec);
415
416// Mozodojo: going to patch FACP and load SSDT's even if DSDT.aml is not present
417/*if (!new_dsdt)
418 {
419 return setupAcpiNoMod();
420 }*/
421
422// Mozodojo: Load additional SSDTs
423struct acpi_2_ssdt *new_ssdt[32]; // 30 + 2 additional tables for pss & cst
424int ssdt_count=0;
425
426// SSDT Options
427bool drop_ssdt = false, generate_pstates = false, generate_cstates = false;
428
429getBoolForKey(kDropSSDT, &drop_ssdt, &bootInfo->chameleonConfig);
430getBoolForKey(kGeneratePStates, &generate_pstates, &bootInfo->chameleonConfig);
431getBoolForKey(kGenerateCStates, &generate_cstates, &bootInfo->chameleonConfig);
432
433DBG("Generating P-States config: %s\n", generate_pstates ? "YES" : "NO");
434DBG("Generating C-States config: %s\n", generate_cstates ? "YES" : "NO");
435
436{
437int i;
438
439for (i = 0; i < 30; i++)
440{
441char filename[512];
442
443if (i > 0)
444{
445sprintf(filename, "SSDT-%d.aml", i);
446}
447else
448{
449strcpy(filename, "SSDT.aml");
450}
451
452if ( (new_ssdt[ssdt_count] = loadACPITable(filename)) )
453{
454ssdt_count++;
455}
456else
457{
458break;
459}
460}
461}
462
463// Do the same procedure for both versions of ACPI
464for (version = 0; version < 2; version++)
465{
466struct acpi_2_rsdp *rsdp, *rsdp_mod;
467struct acpi_2_rsdt *rsdt, *rsdt_mod;
468int rsdplength;
469
470// Find original rsdp
471rsdp = (struct acpi_2_rsdp *)(version ? getAddressOfAcpi20Table() : getAddressOfAcpiTable());
472if (!rsdp)
473{
474DBG("No ACPI version %d found. Ignoring\n", version+1);
475if (version)
476{
477addConfigurationTable(&gEfiAcpi20TableGuid, NULL, "ACPI_20");
478}
479else
480{
481addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI");
482}
483continue;
484}
485rsdplength = version ? rsdp->Length : 20;
486
487DBG("RSDP version %d found @%x. Length=%d\n",version+1,rsdp,rsdplength);
488
489/* FIXME: no check that memory allocation succeeded
490 * Copy and patch RSDP,RSDT, XSDT and FADT
491 * For more info see ACPI Specification pages 110 and following
492 */
493
494rsdp_mod = (struct acpi_2_rsdp *) AllocateKernelMemory(rsdplength);
495memcpy(rsdp_mod, rsdp, rsdplength);
496
497rsdt = (struct acpi_2_rsdt *)rsdp->RsdtAddress;
498
499DBG("RSDT @%x, Length %d\n",rsdt, rsdt ? rsdt->Length : 0);
500
501if (rsdt && (uint32_t)rsdt !=0xffffffff && rsdt->Length < 0x10000)
502{
503uint32_t *rsdt_entries;
504int rsdt_entries_num;
505int dropoffset=0, i;
506
507// mozo: using malloc cos I didn't found how to free already allocated kernel memory
508rsdt_mod = (struct acpi_2_rsdt *)malloc(rsdt->Length);
509memcpy(rsdt_mod, rsdt, rsdt->Length);
510rsdp_mod->RsdtAddress = (uint32_t)rsdt_mod;
511rsdt_entries_num = (rsdt_mod->Length - sizeof(struct acpi_2_rsdt)) / 4;
512rsdt_entries = (uint32_t *)(rsdt_mod + 1);
513for (i = 0;i < rsdt_entries_num;i++)
514{
515char *table=(char *)(rsdt_entries[i]);
516if (!table)
517{
518continue;
519}
520
521DBG("TABLE %c%c%c%c,",table[0],table[1],table[2],table[3]);
522
523rsdt_entries[i-dropoffset]=rsdt_entries[i];
524
525if (drop_ssdt && tableSign(table, "SSDT"))
526{
527DBG("OEM SSDT tables was dropped\n");
528dropoffset++;
529continue;
530}
531
532if (tableSign(table, "DSDT"))
533{
534DBG("DSDT found\n");
535DBG("Custom DSDT table was found\n");
536if(new_dsdt)
537{
538rsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;
539}
540
541continue;
542}
543
544if (tableSign(table, "FACP"))
545{
546struct acpi_2_fadt *fadt, *fadt_mod;
547fadt=(struct acpi_2_fadt *)rsdt_entries[i];
548
549DBG("FADT found @%x, Length %d\n",fadt, fadt->Length);
550
551if (!fadt || (uint32_t)fadt == 0xffffffff || fadt->Length>0x10000)
552{
553DBG("FADT incorrect. Not modified\n");
554continue;
555}
556
557fadt_mod = patch_fadt(fadt, new_dsdt);
558rsdt_entries[i-dropoffset] = (uint32_t)fadt_mod;
559
560// Generate _CST SSDT
561if (generate_cstates && (new_ssdt[ssdt_count] = generate_cst_ssdt(fadt_mod)))
562{
563DBG("C-States generated\n");
564generate_cstates = false; // Generate SSDT only once!
565ssdt_count++;
566}
567
568// Generating _PSS SSDT
569if (generate_pstates && (new_ssdt[ssdt_count] = generate_pss_ssdt((void*)fadt_mod->DSDT)))
570{
571DBG("P-States generated\n");
572generate_pstates = false; // Generate SSDT only once!
573ssdt_count++;
574}
575continue;
576}
577}
578DBG("\n");
579
580// Allocate rsdt in Kernel memory area
581rsdt_mod->Length += 4*ssdt_count - 4*dropoffset;
582struct acpi_2_rsdt *rsdt_copy = (struct acpi_2_rsdt *)AllocateKernelMemory(rsdt_mod->Length);
583memcpy(rsdt_copy, rsdt_mod, rsdt_mod->Length);
584free(rsdt_mod);
585rsdt_mod = rsdt_copy;
586rsdp_mod->RsdtAddress = (uint32_t)rsdt_mod;
587rsdt_entries_num = (rsdt_mod->Length-sizeof(struct acpi_2_rsdt)) / 4;
588rsdt_entries = (uint32_t *)(rsdt_mod + 1);
589
590// Mozodojo: Insert additional SSDTs into RSDT
591if(ssdt_count > 0)
592{
593int j;
594
595for (j=0; j<ssdt_count; j++)
596{
597rsdt_entries[i-dropoffset+j]=(uint32_t)new_ssdt[j];
598}
599
600DBG("RSDT: Added %d SSDT table(s)\n", ssdt_count);
601
602}
603
604// Correct the checksum of RSDT
605DBG("RSDT: Original checksum %d, ", rsdt_mod->Checksum);
606
607rsdt_mod->Checksum=0;
608rsdt_mod->Checksum=256-checksum8(rsdt_mod,rsdt_mod->Length);
609
610DBG("New checksum %d at %x\n", rsdt_mod->Checksum,rsdt_mod);
611}
612else
613{
614rsdp_mod->RsdtAddress=0;
615DBG("RSDT not found or RSDT incorrect\n");
616}
617DBG("\n");
618
619if (version)
620{
621struct acpi_2_xsdt *xsdt, *xsdt_mod;
622
623// FIXME: handle 64-bit address correctly
624
625xsdt=(struct acpi_2_xsdt*) ((uint32_t)rsdp->XsdtAddress);
626DBG("XSDT @%x;%x, Length=%d\n", (uint32_t)(rsdp->XsdtAddress>>32),(uint32_t)rsdp->XsdtAddress, xsdt->Length);
627
628if (xsdt && (uint64_t)rsdp->XsdtAddress<0xffffffff && xsdt->Length<0x10000)
629{
630uint64_t *xsdt_entries;
631int xsdt_entries_num, i;
632int dropoffset=0;
633
634// mozo: using malloc cos I didn't found how to free already allocated kernel memory
635xsdt_mod=(struct acpi_2_xsdt*)malloc(xsdt->Length);
636memcpy(xsdt_mod, xsdt, xsdt->Length);
637
638rsdp_mod->XsdtAddress = (uint32_t)xsdt_mod;
639xsdt_entries_num = (xsdt_mod->Length - sizeof(struct acpi_2_xsdt)) / 8;
640xsdt_entries = (uint64_t *)(xsdt_mod + 1);
641for (i = 0;i < xsdt_entries_num;i++)
642{
643char *table = (char *)((uint32_t)(xsdt_entries[i]));
644if (!table)
645{
646continue;
647}
648xsdt_entries[i - dropoffset] = xsdt_entries[i];
649
650if (drop_ssdt && tableSign(table, "SSDT"))
651{
652DBG("OEM SSDT tables was dropped\n");
653dropoffset++;
654continue;
655}
656if (tableSign(table, "DSDT"))
657{
658DBG("DSDT found\n");
659
660if (new_dsdt)
661{
662xsdt_entries[i-dropoffset] = (uint32_t)new_dsdt;
663DBG("custom table added\n");
664}
665
666DBG("TABLE %c%c%c%c@%x \n", table[0],table[1],table[2],table[3],xsdt_entries[i]);
667
668continue;
669}
670if (tableSign(table, "FACP"))
671{
672struct acpi_2_fadt *fadt, *fadt_mod;
673fadt=(struct acpi_2_fadt *)(uint32_t)xsdt_entries[i];
674
675DBG("FADT found @%x%x, Length %d\n",(uint32_t)(xsdt_entries[i]>>32),fadt,
676fadt->Length);
677
678if (!fadt || (uint64_t)xsdt_entries[i] >= 0xffffffff || fadt->Length>0x10000)
679{
680DBG("FADT incorrect or after 4GB. Dropping XSDT\n");
681goto drop_xsdt;
682}
683
684fadt_mod = patch_fadt(fadt, new_dsdt);
685xsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;
686
687// DBG("TABLE %c%c%c%c@%x \n", table[0],table[1],table[2],table[3],xsdt_entries[i]);
688
689// Generate _CST SSDT
690if (generate_cstates && (new_ssdt[ssdt_count] = generate_cst_ssdt(fadt_mod)))
691{
692DBG("C-States generated\n");
693generate_cstates = false; // Generate SSDT only once!
694ssdt_count++;
695}
696
697// Generating _PSS SSDT
698if (generate_pstates && (new_ssdt[ssdt_count] = generate_pss_ssdt((void*)fadt_mod->DSDT)))
699{
700DBG("P-States generated\n");
701generate_pstates = false; // Generate SSDT only once!
702ssdt_count++;
703}
704
705continue;
706}
707DBG("copied (OEM)\n");
708// DBG("TABLE %c%c%c%c@%x \n", table[0],table[1],table[2],table[3],xsdt_entries[i]);
709}
710
711// Allocate xsdt in Kernel memory area
712xsdt_mod->Length += 8*ssdt_count - 8*dropoffset;
713struct acpi_2_xsdt *xsdt_copy = (struct acpi_2_xsdt *)AllocateKernelMemory(xsdt_mod->Length);
714memcpy(xsdt_copy, xsdt_mod, xsdt_mod->Length);
715free(xsdt_mod);
716xsdt_mod = xsdt_copy;
717rsdp_mod->XsdtAddress = (uint32_t)xsdt_mod;
718xsdt_entries_num = (xsdt_mod->Length - sizeof(struct acpi_2_xsdt)) / 8;
719xsdt_entries = (uint64_t *)(xsdt_mod + 1);
720
721// Mozodojo: Insert additional SSDTs into XSDT
722if(ssdt_count > 0)
723{
724int j;
725
726for (j=0; j<ssdt_count; j++)
727{
728xsdt_entries[i-dropoffset+j]=(uint32_t)new_ssdt[j];
729}
730
731verbose("Added %d SSDT table(s) into XSDT\n", ssdt_count);
732
733}
734
735// Correct the checksum of XSDT
736xsdt_mod->Checksum=0;
737xsdt_mod->Checksum=256-checksum8(xsdt_mod,xsdt_mod->Length);
738}
739else
740{
741drop_xsdt:
742
743DBG("About to drop XSDT\n");
744
745/*FIXME: Now we just hope that if MacOS doesn't find XSDT it reverts to RSDT.
746 * A Better strategy would be to generate
747 */
748
749rsdp_mod->XsdtAddress=0xffffffffffffffffLL;
750verbose("XSDT not found or XSDT incorrect\n");
751}
752}
753DBG("\n");
754
755// Correct the checksum of RSDP
756
757DBG("RSDP: Original checksum %d, ", rsdp_mod->Checksum);
758
759rsdp_mod->Checksum=0;
760rsdp_mod->Checksum=256-checksum8(rsdp_mod,20);
761
762DBG("New checksum %d\n", rsdp_mod->Checksum);
763
764if (version)
765{
766DBG("RSDP: Original extended checksum %d, ", rsdp_mod->ExtendedChecksum);
767
768rsdp_mod->ExtendedChecksum=0;
769rsdp_mod->ExtendedChecksum=256-checksum8(rsdp_mod,rsdp_mod->Length);
770
771DBG("New extended checksum %d\n", rsdp_mod->ExtendedChecksum);
772
773}
774
775if (version)
776{
777/* XXX aserebln why uint32 cast if pointer is uint64 ? */
778acpi20_p = (uint64_t)(uint32_t)rsdp_mod;
779addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
780}
781else
782{
783/* XXX aserebln why uint32 cast if pointer is uint64 ? */
784acpi10_p = (uint64_t)(uint32_t)rsdp_mod;
785addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
786}
787DBG("ACPI version %d patching finished\n\n", version+1);
788}
789#if DEBUG_ACPI
790printf("Press a key to continue... (DEBUG_ACPI)\n");
791getchar();
792#endif
793return 1;
794}
795

Archive Download this file

Revision: 2639