Chameleon

Chameleon Svn Source Tree

Root/branches/ErmaC/Enoch/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
107snprintf(dirSpec, sizeof(dirSpec), "%s", filename);
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_tacpi_cpu_count = 0;
161char* acpi_cpu_name[32];
162uint32_t acpi_cpu_p_blk = 0;
163
164void get_acpi_cpu_names(unsigned char* dsdt, uint32_t length)
165{
166uint32_t i;
167
168DBG("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("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("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("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("End finding cpu names: 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// Patch DSDT Address if we have loaded DSDT.aml
334if(new_dsdt)
335{
336DBG("DSDT: Old @%x,%x, ",fadt_mod->DSDT,fadt_mod->X_DSDT);
337
338fadt_mod->DSDT=(uint32_t)new_dsdt;
339if ((uint32_t)(&(fadt_mod->X_DSDT))-(uint32_t)fadt_mod+8<=fadt_mod->Length)
340{
341fadt_mod->X_DSDT=(uint32_t)new_dsdt;
342}
343
344DBG("New @%x,%x\n",fadt_mod->DSDT,fadt_mod->X_DSDT);
345
346DBG("FADT: Using custom DSDT!\n");
347}
348
349// Correct the checksum
350fadt_mod->Checksum=0;
351fadt_mod->Checksum=256-checksum8(fadt_mod,fadt_mod->Length);
352
353return fadt_mod;
354}
355
356/* Setup ACPI without replacing DSDT. */
357int setupAcpiNoMod()
358{
359//addConfigurationTable(&gEfiAcpiTableGuid, getAddressOfAcpiTable(), "ACPI");
360//addConfigurationTable(&gEfiAcpi20TableGuid, getAddressOfAcpi20Table(), "ACPI_20");
361/* XXX aserebln why uint32 cast if pointer is uint64 ? */
362acpi10_p = (uint64_t)(uint32_t)getAddressOfAcpiTable();
363acpi20_p = (uint64_t)(uint32_t)getAddressOfAcpi20Table();
364addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
365if(acpi20_p)
366{
367addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
368}
369else
370{
371DBG("No ACPI 2.\n");
372}
373return 1;
374}
375
376/* Setup ACPI. Replace DSDT if DSDT.aml is found */
377int setupAcpi(void)
378{
379int version;
380
381// ACPI Tables
382bool drop_dmar = getBoolForKey(kDropDMAR, &drop_dmar, &bootInfo->chameleonConfig);
383bool drop_hpet = getBoolForKey(kDropHPET, &drop_hpet, &bootInfo->chameleonConfig);
384bool drop_slic = getBoolForKey(kDropSLIC, &drop_slic, &bootInfo->chameleonConfig);
385bool drop_sbst = getBoolForKey(kDropSBST, &drop_sbst, &bootInfo->chameleonConfig);
386bool drop_ecdt = getBoolForKey(kDropECDT, &drop_ecdt, &bootInfo->chameleonConfig);
387bool drop_asft = getBoolForKey(kDropASFT, &drop_asft, &bootInfo->chameleonConfig);
388
389void *new_dsdt = NULL; // DSDT.aml DSDT
390void *new_hpet = NULL; // HPET.aml HPET
391void *new_sbst = NULL; // SBST.aml SBST
392void *new_ecdt = NULL; // ECDT.aml ECDT
393void *new_asft = NULL; // ASFT.aml ASF!
394void *new_dmar = NULL; // DMAR.aml DMAR
395void *new_apic = NULL; // APIC.aml APIC
396void *new_mcfg = NULL; // MCFG.aml MCFG
397
398const char *filename;
399char dirSpec[128];
400int len = 0;
401
402// always reset cpu count to 0 when injecting new acpi
403acpi_cpu_count = 0;
404
405/* Try using the file specified with the DSDT option */
406if (getValueForKey(kDSDT, &filename, &len, &bootInfo->chameleonConfig))
407{
408snprintf(dirSpec, sizeof(dirSpec), filename);
409}
410else
411{
412sprintf(dirSpec, "DSDT.aml");
413//verbose("dirSpec, DSDT.aml");
414}
415
416// Load replacement DSDT
417new_dsdt = loadACPITable(dirSpec);
418
419/* Try using the file specified with the HPET option */
420if (getValueForKey(kHPET, &filename, &len, &bootInfo->chameleonConfig))
421{
422snprintf(dirSpec, sizeof(dirSpec), filename);
423}
424else
425{
426sprintf(dirSpec, "HPET.aml");
427}
428// Load replacement HPET
429new_hpet = loadACPITable(dirSpec);
430
431/* Try using the file specified with the SBST option */
432if (getValueForKey(kSBST, &filename, &len, &bootInfo->chameleonConfig))
433{
434snprintf(dirSpec, sizeof(dirSpec), filename);
435}
436else
437{
438sprintf(dirSpec, "SBST.aml");
439}
440// Load replacement SBST
441new_sbst = loadACPITable(dirSpec);
442
443/* Try using the file specified with the ECDT option */
444if (getValueForKey(kECDT, &filename, &len, &bootInfo->chameleonConfig))
445{
446snprintf(dirSpec, sizeof(dirSpec), filename);
447}
448else
449{
450sprintf(dirSpec, "ECDT.aml");
451}
452// Load replacement ECDT
453new_ecdt = loadACPITable(dirSpec);
454
455/* Try using the file specified with the ASF! option */
456if (getValueForKey(kASFT, &filename, &len, &bootInfo->chameleonConfig))
457{
458snprintf(dirSpec, sizeof(dirSpec), filename);
459}
460else
461{
462sprintf(dirSpec, "ASFT.aml");
463}
464// Load replacement ASF!
465new_asft = loadACPITable(dirSpec);
466
467/* Try using the file specified with the DMAR option */
468if (getValueForKey(kDMAR, &filename, &len, &bootInfo->chameleonConfig))
469{
470snprintf(dirSpec, sizeof(dirSpec), filename);
471}
472else
473{
474sprintf(dirSpec, "DMAR.aml");
475}
476// Load replacement DMAR
477new_dmar = loadACPITable(dirSpec);
478
479/* Try using the file specified with the APIC option */
480if (getValueForKey(kAPIC, &filename, &len, &bootInfo->chameleonConfig))
481{
482snprintf(dirSpec, sizeof(dirSpec), filename);
483}
484else
485{
486sprintf(dirSpec, "APIC.aml");
487}
488// Load replacement APIC
489new_apic = loadACPITable(dirSpec);
490
491// Try using the file specified with the MCFG option */
492if (getValueForKey(kMCFG, &filename, &len, &bootInfo->chameleonConfig))
493{
494snprintf(dirSpec, sizeof(dirSpec), filename);
495}
496else
497{
498sprintf(dirSpec, "MCFG.aml");
499}
500// Load replacement MCFG
501new_mcfg = loadACPITable(dirSpec);
502
503// Mozodojo: going to patch FACP and load SSDT's even if DSDT.aml is not present
504/*if (!new_dsdt)
505 {
506 return setupAcpiNoMod();
507 }*/
508
509// Mozodojo: Load additional SSDTs
510struct acpi_2_ssdt *new_ssdt[32]; // 30 + 2 additional tables for pss & cst
511int ssdt_count=0;
512
513// SSDT Options
514bool drop_ssdt=false, generate_pstates=false, generate_cstates=false;
515
516getBoolForKey(kDropSSDT, &drop_ssdt, &bootInfo->chameleonConfig);
517getBoolForKey(kGeneratePStates, &generate_pstates, &bootInfo->chameleonConfig);
518getBoolForKey(kGenerateCStates, &generate_cstates, &bootInfo->chameleonConfig);
519//getBoolForKey(kGenerateTStates, &generate_tstates, &bootInfo->chameleonConfig);
520
521DBG("Generating P-States config: %s\n", generate_pstates ? "YES" : "NO");
522DBG("Generating C-States config: %s\n", generate_cstates ? "YES" : "NO");
523//DBG("Generating T-States config: %s\n", generate_tstates ? "YES" : "NO");
524
525{
526int i;
527
528for (i = 0; i < 30; i++)
529{
530char filename[512];
531
532sprintf(filename, i > 0 ? "SSDT-%d.aml" : "SSDT.aml", i);
533
534if ( (new_ssdt[ssdt_count] = loadACPITable(filename)) )
535{
536ssdt_count++;
537}
538else
539{
540break;
541}
542}
543}
544
545// Do the same procedure for both versions of ACPI
546for (version = 0; version < 2; version++)
547{
548struct acpi_2_rsdp *rsdp, *rsdp_mod;
549struct acpi_2_rsdt *rsdt, *rsdt_mod;
550int rsdplength;
551
552// Find original rsdp
553rsdp=(struct acpi_2_rsdp *)(version ? getAddressOfAcpi20Table() : getAddressOfAcpiTable());
554if (!rsdp)
555{
556DBG("No ACPI version %d found. Ignoring\n", version+1);
557if (version)
558{
559addConfigurationTable(&gEfiAcpi20TableGuid, NULL, "ACPI_20");
560}
561else
562{
563addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI");
564}
565continue;
566}
567rsdplength=version ? rsdp->Length : 20;
568
569DBG("RSDP version %d found @%x. Length=%d\n",version+1,rsdp,rsdplength);
570
571/* FIXME: no check that memory allocation succeeded
572 * Copy and patch RSDP,RSDT, XSDT and FADT
573 * For more info see ACPI Specification pages 110 and following
574 */
575
576rsdp_mod=(struct acpi_2_rsdp *) AllocateKernelMemory(rsdplength);
577memcpy(rsdp_mod, rsdp, rsdplength);
578
579rsdt=(struct acpi_2_rsdt *)(rsdp->RsdtAddress);
580
581DBG("RSDT @%x, Length %d\n",rsdt, rsdt ? rsdt->Length : 0);
582
583if (rsdt && (uint32_t)rsdt !=0xffffffff && rsdt->Length<0x10000)
584{
585uint32_t *rsdt_entries;
586int rsdt_entries_num;
587int dropoffset=0, i;
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);
595for (i=0;i<rsdt_entries_num;i++)
596{
597char *table=(char *)(rsdt_entries[i]);
598if (!table)
599{
600continue;
601}
602
603DBG("TABLE %c%c%c%c,",table[0],table[1],table[2],table[3]);
604
605rsdt_entries[i-dropoffset]=rsdt_entries[i];
606
607if (drop_ssdt && tableSign(table, "SSDT"))
608{
609DBG("OEM SSDT tables was dropped\n");
610dropoffset++;
611continue;
612}
613
614if (drop_hpet && tableSign(table, "HPET"))
615{
616DBG("OEM HPET table was dropped\n");
617dropoffset++;
618continue;
619}
620
621if (drop_slic && tableSign(table, "SLIC"))
622{
623DBG("OEM SLIC table was dropped\n");
624dropoffset++;
625continue;
626}
627
628if (drop_sbst && tableSign(table, "SBST"))
629{
630DBG("OEM SBST table was dropped\n");
631dropoffset++;
632continue;
633}
634
635if (drop_ecdt && tableSign(table, "ECDT"))
636{
637DBG("OEM ECDT table was dropped\n");
638dropoffset++;
639continue;
640}
641
642if (drop_asft && tableSign(table, "ASF!"))
643{
644DBG("OEM ASF! table was dropped\n");
645dropoffset++;
646continue;
647}
648
649if (drop_dmar && tableSign(table, "DMAR"))
650{
651DBG("OEM DMAR table was dropped\n");
652dropoffset++;
653continue;
654}
655
656if (tableSign(table, "HPET"))
657{
658DBG("HPET found\n");
659DBG("Custom HPET table was found\n");
660if(new_hpet)
661{
662rsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
663}
664continue;
665}
666
667if (tableSign(table, "SBST"))
668{
669DBG("SBST found\n");
670DBG("Custom SBST table was found\n");
671if(new_sbst)
672{
673rsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
674}
675continue;
676}
677
678if (tableSign(table, "ECDT"))
679{
680DBG("ECDT found\n");
681DBG("Custom ECDT table was found\n");
682if(new_ecdt)
683{
684rsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
685}
686continue;
687}
688
689if (tableSign(table, "ASF!"))
690{
691DBG("ASF! found\n");
692DBG("Custom ASF! table was found\n");
693if(new_asft)
694{
695rsdt_entries[i-dropoffset]=(uint32_t)new_asft;
696}
697continue;
698}
699
700if (tableSign(table, "DMAR"))
701{
702DBG("DMAR found\n");
703DBG("Custom DMAR table was found\n");
704if(new_dmar)
705{
706rsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
707}
708continue;
709}
710
711if (tableSign(table, "APIC"))
712{
713DBG("APIC found\n");
714DBG("Custom APIC table was found\n");
715if(new_apic)
716{
717rsdt_entries[i-dropoffset]=(uint32_t)new_apic;
718}
719continue;
720}
721
722if (tableSign(table, "MCFG"))
723{
724DBG("MCFG found\n");
725DBG("Custom MCFG table was found\n");
726if(new_mcfg)
727{
728rsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
729}
730
731continue;
732}
733if (tableSign(table, "DSDT"))
734{
735DBG("DSDT found\n");
736DBG("Custom DSDT table was found\n");
737if(new_dsdt)
738{
739rsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;
740}
741
742continue;
743}
744
745if (tableSign(table, "FACP"))
746{
747struct acpi_2_fadt *fadt, *fadt_mod;
748fadt=(struct acpi_2_fadt *)rsdt_entries[i];
749
750DBG("FADT found @%x, Length %d\n",fadt, fadt->Length);
751
752if (!fadt || (uint32_t)fadt == 0xffffffff || fadt->Length>0x10000)
753{
754DBG("FADT incorrect. Not modified\n");
755continue;
756}
757
758fadt_mod = patch_fadt(fadt, new_dsdt);
759rsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;
760
761// Generate _CST SSDT
762if (generate_cstates && (new_ssdt[ssdt_count] = generate_cst_ssdt(fadt_mod)))
763{
764DBG("C-States generated\n");
765generate_cstates = false; // Generate SSDT only once!
766ssdt_count++;
767}
768
769// Generating _PSS SSDT
770if (generate_pstates && (new_ssdt[ssdt_count] = generate_pss_ssdt((void*)fadt_mod->DSDT)))
771{
772DBG("P-States generated\n");
773generate_pstates = false; // Generate SSDT only once!
774ssdt_count++;
775}
776continue;
777}
778}
779DBG("\n");
780
781// Allocate rsdt in Kernel memory area
782rsdt_mod->Length += 4*ssdt_count - 4*dropoffset;
783struct acpi_2_rsdt *rsdt_copy = (struct acpi_2_rsdt *)AllocateKernelMemory(rsdt_mod->Length);
784memcpy (rsdt_copy, rsdt_mod, rsdt_mod->Length);
785free(rsdt_mod); rsdt_mod = rsdt_copy;
786rsdp_mod->RsdtAddress=(uint32_t)rsdt_mod;
787rsdt_entries_num=(rsdt_mod->Length-sizeof(struct acpi_2_rsdt))/4;
788rsdt_entries=(uint32_t *)(rsdt_mod+1);
789
790// Mozodojo: Insert additional SSDTs into RSDT
791if(ssdt_count > 0)
792{
793int j;
794
795for (j=0; j<ssdt_count; j++)
796{
797rsdt_entries[i-dropoffset+j]=(uint32_t)new_ssdt[j];
798}
799
800DBG("RSDT: Added %d SSDT table(s)\n", ssdt_count);
801
802}
803
804// Correct the checksum of RSDT
805DBG("RSDT: Original checksum %d, ", rsdt_mod->Checksum);
806
807rsdt_mod->Checksum=0;
808rsdt_mod->Checksum=256-checksum8(rsdt_mod,rsdt_mod->Length);
809
810DBG("New checksum %d at %x\n", rsdt_mod->Checksum,rsdt_mod);
811}
812else
813{
814rsdp_mod->RsdtAddress=0;
815DBG("RSDT not found or RSDT incorrect\n");
816}
817DBG("\n");
818
819if (version)
820{
821struct acpi_2_xsdt *xsdt, *xsdt_mod;
822
823// FIXME: handle 64-bit address correctly
824
825xsdt=(struct acpi_2_xsdt*) ((uint32_t)rsdp->XsdtAddress);
826DBG("XSDT @%x;%x, Length=%d Sign=%c%c%c%c\n", (uint32_t)(rsdp->XsdtAddress>>32),
827(uint32_t)rsdp->XsdtAddress, xsdt->Length, xsdt[0], xsdt[1], xsdt[2], xsdt[3]);
828if (xsdt && (uint64_t)rsdp->XsdtAddress<0xffffffff && xsdt->Length<0x10000)
829{
830uint64_t *xsdt_entries;
831int xsdt_entries_num, i;
832int dropoffset=0;
833
834// mozo: using malloc cos I didn't found how to free already allocated kernel memory
835xsdt_mod=(struct acpi_2_xsdt*)malloc(xsdt->Length);
836memcpy(xsdt_mod, xsdt, xsdt->Length);
837
838rsdp_mod->XsdtAddress=(uint32_t)xsdt_mod;
839xsdt_entries_num=(xsdt_mod->Length-sizeof(struct acpi_2_xsdt))/8;
840xsdt_entries=(uint64_t *)(xsdt_mod+1);
841for (i=0;i<xsdt_entries_num;i++)
842{
843char *table=(char *)((uint32_t)(xsdt_entries[i]));
844if (!table)
845{
846continue;
847}
848xsdt_entries[i-dropoffset]=xsdt_entries[i];
849
850if (drop_ssdt && tableSign(table, "SSDT"))
851{
852verbose("OEM SSDT tables was dropped\n");
853dropoffset++;
854continue;
855}
856
857if (drop_hpet && tableSign(table, "HPET"))
858{
859verbose("OEM HPET table was dropped\n");
860dropoffset++;
861continue;
862}
863
864if (drop_slic && tableSign(table, "SLIC"))
865{
866verbose("OEM SLIC table was dropped\n");
867dropoffset++;
868continue;
869}
870
871if (drop_sbst && tableSign(table, "SBST"))
872{
873verbose("OEM SBST table was dropped\n");
874dropoffset++;
875continue;
876}
877
878if (drop_ecdt && tableSign(table, "ECDT"))
879{
880verbose("OEM ECDT table was dropped\n");
881dropoffset++;
882continue;
883}
884
885if (drop_asft && tableSign(table, "ASF!"))
886{
887verbose("OEM ASF! table was dropped\n");
888dropoffset++;
889continue;
890}
891
892if (drop_dmar && tableSign(table, "DMAR"))
893{
894verbose("OEM DMAR table was dropped\n");
895dropoffset++;
896continue;
897}
898
899if (tableSign(table, "DSDT"))
900{
901DBG("DSDT found\n");
902
903if (new_dsdt)
904{
905xsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;
906}
907
908DBG("TABLE %c%c%c%c@%x \n", table[0],table[1],table[2],table[3],xsdt_entries[i]);
909
910continue;
911}
912
913if (tableSign(table, "HPET"))
914{
915DBG("HPET found\n");
916
917if (new_hpet)
918{
919xsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
920}
921
922DBG("TABLE %c%c%c%c@%x \n", table[0],table[1],table[2],table[3],xsdt_entries[i]);
923
924continue;
925}
926
927if (tableSign(table, "SBST"))
928{
929DBG("SBST found\n");
930
931if (new_sbst)
932{
933xsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
934}
935
936DBG("TABLE %c%c%c%c@%x \n", table[0],table[1],table[2],table[3],xsdt_entries[i]);
937
938continue;
939}
940
941if (tableSign(table, "ECDT"))
942{
943DBG("ECDT found\n");
944
945if (new_ecdt)
946{
947xsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
948}
949
950DBG("TABLE %c%c%c%c@%x \n", table[0],table[1],table[2],table[3],xsdt_entries[i]);
951
952continue;
953}
954
955if (tableSign(table, "ASF!"))
956{
957DBG("ASF! found\n");
958
959if (new_asft)
960{
961xsdt_entries[i-dropoffset]=(uint32_t)new_asft;
962}
963
964DBG("TABLE %c%c%c%c@%x \n", table[0],table[1],table[2],table[3],xsdt_entries[i]);
965
966continue;
967}
968
969if (tableSign(table, "DMAR"))
970{
971DBG("DMAR found\n");
972
973if (new_dmar)
974{
975xsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
976}
977
978DBG("TABLE %c%c%c%c@%x \n", table[0],table[1],table[2],table[3],xsdt_entries[i]);
979
980continue;
981}
982
983if (tableSign(table, "APIC"))
984{
985DBG("APIC found\n");
986
987if (new_apic)
988{
989xsdt_entries[i-dropoffset]=(uint32_t)new_apic;
990}
991
992DBG("TABLE %c%c%c%c@%x \n", table[0],table[1],table[2],table[3],xsdt_entries[i]);
993
994continue;
995}
996
997if (tableSign(table, "MCFG"))
998{
999DBG("MCFG found\n");
1000
1001if (new_mcfg)
1002{
1003xsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
1004}
1005
1006DBG("TABLE %c%c%c%c@%x \n", table[0],table[1],table[2],table[3],xsdt_entries[i]);
1007
1008continue;
1009}
1010
1011if (tableSign(table, "FACP"))
1012{
1013struct acpi_2_fadt *fadt, *fadt_mod;
1014fadt=(struct acpi_2_fadt *)(uint32_t)xsdt_entries[i];
1015
1016DBG("FADT found @%x%x, Length %d\n",(uint32_t)(xsdt_entries[i]>>32),fadt,
1017fadt->Length);
1018
1019if (!fadt || (uint64_t)xsdt_entries[i] >= 0xffffffff || fadt->Length>0x10000)
1020{
1021DBG("FADT incorrect or after 4GB. Dropping XSDT\n");
1022goto drop_xsdt;
1023}
1024
1025fadt_mod = patch_fadt(fadt, new_dsdt);
1026xsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;
1027
1028// DBG("TABLE %c%c%c%c@%x \n", table[0],table[1],table[2],table[3],xsdt_entries[i]);
1029
1030// Generate _CST SSDT
1031if (generate_cstates && (new_ssdt[ssdt_count] = generate_cst_ssdt(fadt_mod)))
1032{
1033DBG("C-States generated\n");
1034generate_cstates = false; // Generate SSDT only once!
1035ssdt_count++;
1036}
1037
1038// Generating _PSS SSDT
1039if (generate_pstates && (new_ssdt[ssdt_count] = generate_pss_ssdt((void*)fadt_mod->DSDT)))
1040{
1041DBG("P-States generated\n");
1042generate_pstates = false; // Generate SSDT only once!
1043ssdt_count++;
1044}
1045
1046// Generating _TSS SSDT
1047/*if (generate_tstates && (new_ssdt[ssdt_count] = generate_tss_ssdt((void*)fadt_mod->DSDT)))
1048{
1049generate_tstates = false; // Generate SSDT only once!
1050ssdt_count++;
1051}*/
1052continue;
1053}
1054
1055DBG("TABLE %c%c%c%c@%x \n", table[0],table[1],table[2],table[3],xsdt_entries[i]);
1056
1057}
1058
1059// Allocate xsdt in Kernel memory area
1060xsdt_mod->Length += 8*ssdt_count - 8*dropoffset;
1061struct acpi_2_xsdt *xsdt_copy = (struct acpi_2_xsdt *)AllocateKernelMemory(xsdt_mod->Length);
1062memcpy(xsdt_copy, xsdt_mod, xsdt_mod->Length);
1063free(xsdt_mod); xsdt_mod = xsdt_copy;
1064rsdp_mod->XsdtAddress=(uint32_t)xsdt_mod;
1065xsdt_entries_num=(xsdt_mod->Length-sizeof(struct acpi_2_xsdt))/8;
1066xsdt_entries=(uint64_t *)(xsdt_mod+1);
1067
1068// Mozodojo: Insert additional SSDTs into XSDT
1069if(ssdt_count > 0)
1070{
1071int j;
1072
1073for (j=0; j<ssdt_count; j++)
1074{
1075xsdt_entries[i-dropoffset+j]=(uint32_t)new_ssdt[j];
1076}
1077
1078verbose("Added %d SSDT table(s) into XSDT\n", ssdt_count);
1079
1080}
1081
1082// Correct the checksum of XSDT
1083xsdt_mod->Checksum=0;
1084xsdt_mod->Checksum=256-checksum8(xsdt_mod,xsdt_mod->Length);
1085}
1086else
1087{
1088drop_xsdt:
1089
1090DBG("About to drop XSDT\n");
1091
1092/*FIXME: Now we just hope that if MacOS doesn't find XSDT it reverts to RSDT.
1093 * A Better strategy would be to generate
1094 */
1095
1096rsdp_mod->XsdtAddress=0xffffffffffffffffLL;
1097verbose("XSDT not found or XSDT incorrect\n");
1098}
1099}
1100DBG("\n");
1101
1102// Correct the checksum of RSDP
1103
1104DBG("RSDP: Original checksum %d, ", rsdp_mod->Checksum);
1105
1106rsdp_mod->Checksum=0;
1107rsdp_mod->Checksum=256-checksum8(rsdp_mod,20);
1108
1109DBG("New checksum %d\n", rsdp_mod->Checksum);
1110
1111if (version)
1112{
1113DBG("RSDP: Original extended checksum %d, ", rsdp_mod->ExtendedChecksum);
1114
1115rsdp_mod->ExtendedChecksum=0;
1116rsdp_mod->ExtendedChecksum=256-checksum8(rsdp_mod,rsdp_mod->Length);
1117
1118DBG("New extended checksum %d\n", rsdp_mod->ExtendedChecksum);
1119
1120}
1121
1122if (version)
1123{
1124/* XXX aserebln why uint32 cast if pointer is uint64 ? */
1125acpi20_p = (uint64_t)(uint32_t)rsdp_mod;
1126addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
1127}
1128else
1129{
1130/* XXX aserebln why uint32 cast if pointer is uint64 ? */
1131acpi10_p = (uint64_t)(uint32_t)rsdp_mod;
1132addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
1133}
1134DBG("ACPI version %d patching finished\n\n", version+1);
1135}
1136#if DEBUG_ACPI
1137printf("Press a key to continue... (DEBUG_ACPI)\n");
1138getchar();
1139#endif
1140return 1;
1141}
1142

Archive Download this file

Revision: 2471