Chameleon

Chameleon Svn Source Tree

Root/branches/andyvand/i386/libsaio/dsdt_patcher.c

1/*
2 * Copyright 2008 mackerintel
3 */
4
5#include "libsaio.h"
6#include "boot.h"
7#include "bootstruct.h"
8#include "acpi.h"
9#include "efi_tables.h"
10#include "fake_efi.h"
11#include "dsdt_patcher.h"
12#include "platform.h"
13
14#ifndef DEBUG_DSDT
15#define DEBUG_DSDT 0
16#endif
17
18#if DEBUG_DSDT==2
19#define DBG(x...) {printf(x); sleep(1);}
20#elif DEBUG_DSDT==1
21#define DBG(x...) printf(x)
22#else
23#define DBG(x...)
24#endif
25
26/* Gets the ACPI 1.0 RSDP address */
27static struct acpi_2_rsdp* getAddressOfAcpiTable()
28{
29 /* TODO: Before searching the BIOS space we are supposed to search the first 1K of the EBDA */
30
31 void *acpi_addr = (void*)ACPI_RANGE_START;
32 for(; acpi_addr <= (void*)ACPI_RANGE_END; acpi_addr += 16)
33 {
34 if(*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE)
35 {
36 uint8_t csum = checksum8(acpi_addr, 20);
37 if(csum == 0)
38 {
39 // Only return the table if it is a true version 1.0 table (Revision 0)
40 if(((struct acpi_2_rsdp*)acpi_addr)->Revision == 0)
41 return acpi_addr;
42 }
43 }
44 }
45 return NULL;
46}
47
48/* Gets the ACPI 2.0 RSDP address */
49static struct acpi_2_rsdp* getAddressOfAcpi20Table()
50{
51 /* TODO: Before searching the BIOS space we are supposed to search the first 1K of the EBDA */
52
53 void *acpi_addr = (void*)ACPI_RANGE_START;
54 for(; acpi_addr <= (void*)ACPI_RANGE_END; acpi_addr += 16)
55 {
56 if(*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE)
57 {
58 uint8_t csum = checksum8(acpi_addr, 20);
59
60 /* Only assume this is a 2.0 or better table if the revision is greater than 0
61 * NOTE: ACPI 3.0 spec only seems to say that 1.0 tables have revision 1
62 * and that the current revision is 2.. I am going to assume that rev > 0 is 2.0.
63 */
64
65 if(csum == 0 && (((struct acpi_2_rsdp*)acpi_addr)->Revision > 0))
66 {
67 uint8_t csum2 = checksum8(acpi_addr, sizeof(struct acpi_2_rsdp));
68 if(csum2 == 0)
69 return acpi_addr;
70 }
71 }
72 }
73 return NULL;
74}
75<<<<<<< .mine
76
77void *loadACPITable(char *key)
78=======
79/** The folowing ACPI Table search algo. should be reused anywhere needed:*/
80int search_and_get_acpi_fd(const char * filename, const char ** outDirspec)
81>>>>>>> .r60
82{
83<<<<<<< .mine
84void *tableAddr;
85int fd = -1;
86char dirspec[512];
87char filename[512];
88const char * overriden_pathname=NULL;
89int len=0;
90=======
91 int fd=0;
92 const char * overriden_pathname=NULL;
93 static char dirspec[512]="";
94 int len=0;
95>>>>>>> .r60
96
97<<<<<<< .mine
98sprintf(filename, "%s.aml", key);
99
100// Check booting partition
101
102// Rek: if user specified a full path name then take it in consideration
103if (getValueForKey(key, &overriden_pathname, &len,
104&bootInfo->bootConfig))
105=======
106 /// Take in accound user overriding if it's DSDT only
107 if (strstr(filename, "DSDT") &&
108 getValueForKey(kDSDT, &overriden_pathname, &len,
109 &bootInfo->bootConfig))
110>>>>>>> .r60
111<<<<<<< .mine
112{
113sprintf(dirspec, "%s", overriden_pathname); // start searching root
114//printf("Using custom %s path %s\n", key, dirspec);
115//getc();
116}
117else
118sprintf(dirspec, "/%s", filename); // start searching root
119=======
120 {
121 sprintf(dirspec, "%s", overriden_pathname); // start searching root
122 fd=open (dirspec,0);
123 if (fd>=0) goto success_fd;
124 }
125>>>>>>> .r60
126
127 // Start searching any potential location for ACPI Table
128 sprintf(dirspec, "/%s", filename); // start searching root
129 fd=open (dirspec,0);
130 if (fd>=0) goto success_fd;
131
132<<<<<<< .mine
133if (fd<0)
134{// Check Extra on booting partition
135 //verbose("Searching for %s.aml file ...\n", key);
136sprintf(dirspec,"/Extra/%s",filename);
137fd=open (dirspec,0);
138if (fd<0)
139{// Fall back to booter partition
140sprintf(dirspec,"bt(0,0)/Extra/%s",filename);
141fd=open (dirspec,0);
142if (fd<0)
143{
144verbose("ACPI Table not found: %s\n", filename);
145return NULL;
146}
147}
148}
149=======
150 sprintf(dirspec, "%s", filename); // start current dir
151 fd=open (dirspec,0);
152 if (fd>=0) goto success_fd;
153>>>>>>> .r60
154
155 sprintf(dirspec,"/Extra/%s",filename);
156 fd=open (dirspec,0);
157 if (fd>=0) goto success_fd;
158
159 sprintf(dirspec,"bt(0,0)/Extra/%s",filename);
160 fd=open (dirspec,0);
161 if (fd>=0) goto success_fd;
162
163 // NOT FOUND:
164 verbose("ACPI Table not found: %s\n", filename);
165 if (outDirspec) *outDirspec = "";
166 return -1;
167 // FOUND
168success_fd:
169 if (outDirspec) *outDirspec = dirspec;
170 return fd;
171}
172
173void *loadACPITable (const char * filename)
174{
175void *tableAddr;
176const char * dirspec=NULL;
177
178int fd = search_and_get_acpi_fd(filename, &dirspec);
179
180if (fd>=0)
181{
182 tableAddr=(void*)AllocateKernelMemory(file_size (fd));
183 if (tableAddr)
184 {
185 if (read (fd, tableAddr, file_size (fd))!=file_size (fd))
186 {
187 printf("Couldn't read table %s\n",dirspec);
188 free (tableAddr);
189 close (fd);
190 return NULL;
191 }
192
193 DBG("Table %s read and stored at: %x\n", dirspec, tableAddr);
194 close (fd);
195 return tableAddr;
196 }
197 close (fd);
198}
199printf("Couldn't allocate memory for table %s\n", dirspec);
200
201return NULL;
202}
203
204void *loadSSDTTable(int ssdt_number)
205{
206void *tableAddr;
207int fd = -1;
208char dirspec[512];
209char filename[512];
210const char * overriden_pathname=NULL;
211int len=0;
212
213sprintf(filename, "SSDT-%d.aml", ssdt_number);
214
215// Check booting partition
216
217// Rek: if user specified a full path name then take it in consideration
218if (getValueForKey(kSSDT, &overriden_pathname, &len,
219 &bootInfo->bootConfig))
220{
221sprintf(dirspec, "%s-%d.aml", overriden_pathname, ssdt_number); // start searching root
222//printf("Using custom %s path %s\n", key, dirspec);
223//getc();
224}
225else
226sprintf(dirspec, "/%s", filename); // start searching root
227
228fd=open (dirspec,0);
229
230if (fd<0)
231{// Check Extra on booting partition
232//verbose("Searching for %s.aml file ...\n", key);
233sprintf(dirspec,"/Extra/%s",filename);
234fd=open (dirspec,0);
235if (fd<0)
236{// Fall back to booter partition
237sprintf(dirspec,"bt(0,0)/Extra/%s",filename);
238fd=open (dirspec,0);
239if (fd<0)
240{
241verbose("SSDT Table not found: %s\n", filename);
242return NULL;
243}
244}
245}
246
247tableAddr=(void*)AllocateKernelMemory(file_size (fd));
248if (tableAddr)
249{
250if (read (fd, tableAddr, file_size (fd))!=file_size (fd))
251{
252printf("Couldn't read table %s\n",dirspec);
253free (tableAddr);
254close (fd);
255return NULL;
256}
257
258DBG("Table %s read and stored at: %x\n", dirspec, tableAddr);
259close (fd);
260return tableAddr;
261}
262
263printf("Couldn't allocate memory for table %s\n", dirspec);
264close (fd);
265
266return NULL;
267}
268
269struct acpi_2_gas FillGASStruct(uint32_t Address, uint8_t Length)
270{
271struct acpi_2_gas TmpGAS;
272
273TmpGAS.Address_Space_ID = 1; /* I/O Address */
274
275if (Address == 0)
276{
277TmpGAS.Register_Bit_Width = 0;
278} else {
279TmpGAS.Register_Bit_Width = Length * 8;
280}
281
282TmpGAS.Register_Bit_Offset = 0;
283TmpGAS.Access_Size = 0; /* Not set for Legacy reasons... */
284TmpGAS.Address = (uint64_t)Address;
285
286return(TmpGAS);
287}
288
289struct acpi_2_fadt *
290patch_fadt(struct acpi_2_fadt *fadt, void *new_dsdt, bool UpdateFADT)
291{
292 extern void setupSystemType();
293
294struct acpi_2_fadt *fadt_mod;
295struct acpi_2_fadt *fadt_file = (struct acpi_2_fadt *)loadACPITable(kFADT);
296bool fadt_rev2_needed = false;
297bool fix_restart;
298const char * value;
299
300// Restart Fix
301if (Platform.CPU.Vendor == 0x756E6547) {/* Intel */
302fix_restart = true;
303getBoolForKey(kRestartFix, &fix_restart, &bootInfo->bootConfig);
304} else {
305verbose ("Not an Intel platform: Restart Fix not applied !!!\n");
306fix_restart = false;
307}
308
309if (fix_restart)
310fadt_rev2_needed = true;
311
312// Allocate new fadt table
313if ((UpdateFADT) && (((fadt_file) && (fadt_file->Length < sizeof(struct acpi_2_fadt))) ||
314 ((!fadt_file) && (fadt->Length < sizeof(struct acpi_2_fadt)))))
315{
316fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(sizeof(struct acpi_2_fadt));
317
318if (fadt_file)
319memcpy(fadt_mod, fadt_file, fadt_file->Length);
320else
321memcpy(fadt_mod, fadt, fadt->Length);
322
323fadt_mod->Length = sizeof(struct acpi_2_fadt);
324fadt_mod->Revision = 0x04; // FADT rev 4
325fadt_mod->RESET_REG = FillGASStruct(0, 0);
326fadt_mod->RESET_VALUE = 0;
327fadt_mod->Reserved2[0] = 0;
328fadt_mod->Reserved2[1] = 0;
329fadt_mod->Reserved2[2] = 0;
330fadt_mod->X_PM1a_EVT_BLK = FillGASStruct(fadt_mod->PM1a_EVT_BLK, fadt_mod->PM1_EVT_LEN);
331fadt_mod->X_PM1b_EVT_BLK = FillGASStruct(fadt_mod->PM1b_EVT_BLK, fadt_mod->PM1_EVT_LEN);
332fadt_mod->X_PM1a_CNT_BLK = FillGASStruct(fadt_mod->PM1a_CNT_BLK, fadt_mod->PM1_CNT_LEN);
333fadt_mod->X_PM1b_CNT_BLK = FillGASStruct(fadt_mod->PM1b_CNT_BLK, fadt_mod->PM1_CNT_LEN);
334fadt_mod->X_PM2_CNT_BLK = FillGASStruct(fadt_mod->PM2_CNT_BLK, fadt_mod->PM2_CNT_LEN);
335fadt_mod->X_PM_TMR_BLK = FillGASStruct(fadt_mod->PM_TMR_BLK, fadt_mod->PM_TMR_LEN);
336fadt_mod->X_GPE0_BLK = FillGASStruct(fadt_mod->GPE0_BLK, fadt_mod->GPE0_BLK_LEN);
337fadt_mod->X_GPE1_BLK = FillGASStruct(fadt_mod->GPE1_BLK, fadt_mod->GPE1_BLK_LEN);
338verbose("Converted ACPI V%d FADT to ACPI V4 FADT\n", (fadt_file) ? fadt_file->Revision : fadt->Revision);
339} else {
340if (((!fadt_file) && ((fadt->Length < 0x84) && (fadt_rev2_needed))) ||
341 ((fadt_file) && ((fadt_file->Length < 0x84) && (fadt_rev2_needed))))
342{
343fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(0x84);
344
345if (fadt_file)
346memcpy(fadt_mod, fadt_file, fadt_file->Length);
347else
348memcpy(fadt_mod, fadt, fadt->Length);
349
350fadt_mod->Length = 0x84;
351fadt_mod->Revision = 0x02; // FADT rev 2 (ACPI 1.0B MS extensions)
352}
353else
354{
355if (fadt_file)
356{
357fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(fadt_file->Length);
358memcpy(fadt_mod, fadt_file, fadt_file->Length);
359} else {
360fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(fadt->Length);
361memcpy(fadt_mod, fadt, fadt->Length);
362}
363}
364}
365// Determine system type / PM_Model
366if ( (value=getStringForKey(kSystemType, &bootInfo->bootConfig))!=NULL)
367{
368 if (Platform.Type > 6)
369 {
370 if(fadt_mod->Preferred_PM_Profile<=6)
371 Platform.Type = fadt_mod->Preferred_PM_Profile; // get the fadt if correct
372 else
373 Platform.Type = 1;/* Set a fixed value (Desktop) */
374 verbose("Error: system-type must be 0..6. Defaulting to %d !\n", Platform.Type);
375 }
376 else
377 Platform.Type = (unsigned char) strtoul(value, NULL, 10);
378}
379// Set Preferred_PM_Profile from System-type if only if user wanted this value to be forced
380if (fadt_mod->Preferred_PM_Profile != Platform.Type)
381{
382 if (value)
383 { // user has overriden the SystemType so take care of it in FACP
384verbose("FADT: changing Preferred_PM_Profile from 0x%02x to 0x%02x\n", fadt_mod->Preferred_PM_Profile, Platform.Type);
385fadt_mod->Preferred_PM_Profile = Platform.Type;
386 }
387 else
388 { // Preferred_PM_Profile has a different value and no override has been set, so reflect the user value to ioregs
389 Platform.Type = fadt_mod->Preferred_PM_Profile <= 6 ? fadt_mod->Preferred_PM_Profile : 1;
390 }
391}
392// We now have to write the systemm-type in ioregs: we cannot do it before in setupDeviceTree()
393// because we need to take care of facp original content, if it is correct.
394setupSystemType();
395
396// Patch FADT to fix restart
397if (fix_restart)
398{
399fadt_mod->Flags|= 0x400;
400fadt_mod->RESET_REG = FillGASStruct(0x0cf9, 1);
401fadt_mod->RESET_VALUE = 0x06;
402verbose("FADT: Restart Fix applied !\n");
403}
404
405// Patch FACS Address
406fadt_mod->FIRMWARE_CTRL=(uint32_t)fadt->FIRMWARE_CTRL;
407if ((uint32_t)(&(fadt_mod->X_FIRMWARE_CTRL))-(uint32_t)fadt_mod+8<=fadt_mod->Length)
408fadt_mod->X_FIRMWARE_CTRL=(uint32_t)fadt->FIRMWARE_CTRL
409
410// Patch DSDT Address
411DBG("DSDT: Old @%x,%x, ",fadt_mod->DSDT,fadt_mod->X_DSDT);
412
413fadt_mod->DSDT=(uint32_t)new_dsdt;
414if ((uint32_t)(&(fadt_mod->X_DSDT))-(uint32_t)fadt_mod+8<=fadt_mod->Length)
415fadt_mod->X_DSDT=(uint32_t)new_dsdt;
416
417DBG("New @%x,%x\n",fadt_mod->DSDT,fadt_mod->X_DSDT);
418
419// Correct the checksum
420fadt_mod->Checksum=0;
421fadt_mod->Checksum=256-checksum8(fadt_mod,fadt_mod->Length);
422
423return fadt_mod;
424}
425
426/* Setup ACPI without replacing DSDT. */
427int setupAcpiNoMod()
428{
429//addConfigurationTable(&gEfiAcpiTableGuid, getAddressOfAcpiTable(), "ACPI");
430//addConfigurationTable(&gEfiAcpi20TableGuid, getAddressOfAcpi20Table(), "ACPI_20");
431/* XXX aserebln why uint32 cast if pointer is uint64 ? */
432acpi10_p = (uint32_t)getAddressOfAcpiTable();
433acpi20_p = (uint32_t)getAddressOfAcpi20Table();
434addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
435if(acpi20_p) addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
436return 1;
437}
438
439/* Setup ACPI. Replace DSDT if DSDT.aml is found */
440int setupAcpi(void)
441{
442int version;
443void *new_dsdt=NULL, *new_hpet=NULL, *new_sbst=NULL, *new_ecdt=NULL, *new_asft=NULL, *new_dmar=NULL, *new_apic=NULL, *new_mcfg=NULL, *new_ssdts[30];
444
445<<<<<<< .mine
446bool oem_dsdt=false, oem_ssdt=false, oem_hpet=false, oem_sbst=false, oem_ecdt=false, oem_asft=false, oem_dmar=false, oem_apic=false, oem_mcfg=false;
447bool drop_ssdt=false, drop_hpet=false, drop_slic=false, drop_sbst=false, drop_ecdt=false, drop_asft=false, drop_dmar=false;
448bool update_acpi=false, gen_xsdt=false;
449bool hpet_replaced=false, sbst_replaced=false, ecdt_replaced=false, asft_replaced=false, dmar_replaced=false, apic_replaced=false, mcfg_replaced=false;
450bool hpet_added=false, sbst_added=false, ecdt_added=false, asft_added=false, dmar_added=false, apic_added=false, mcfg_added=false;
451
452int curssdt=0, loadtotssdt=0, totssdt=0, newtotssdt=0;
453
454=======
455bool drop_ssdt;
456
457// Load replacement DSDT
458new_dsdt=loadACPITable("DSDT.aml");
459if (!new_dsdt)
460>>>>>>> .r60
461{
462bool tmpval;
463
464drop_ssdt=getBoolForKey(kDropSSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
465drop_hpet=getBoolForKey(kDropHPET, &tmpval, &bootInfo->bootConfig)&&tmpval;
466drop_slic=getBoolForKey(kDropSLIC, &tmpval, &bootInfo->bootConfig)&&tmpval;
467drop_sbst=getBoolForKey(kDropSBST, &tmpval, &bootInfo->bootConfig)&&tmpval;
468drop_ecdt=getBoolForKey(kDropECDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
469drop_asft=getBoolForKey(kDropASFT, &tmpval, &bootInfo->bootConfig)&&tmpval;
470drop_dmar=getBoolForKey(kDropDMAR, &tmpval, &bootInfo->bootConfig)&&tmpval;
471
472oem_dsdt=getBoolForKey(kOEMDSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
473oem_ssdt=getBoolForKey(kOEMSSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
474oem_hpet=getBoolForKey(kOEMHPET, &tmpval, &bootInfo->bootConfig)&&tmpval;
475oem_sbst=getBoolForKey(kOEMSBST, &tmpval, &bootInfo->bootConfig)&&tmpval;
476oem_ecdt=getBoolForKey(kOEMECDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
477oem_asft=getBoolForKey(kOEMASFT, &tmpval, &bootInfo->bootConfig)&&tmpval;
478oem_dmar=getBoolForKey(kOEMDMAR, &tmpval, &bootInfo->bootConfig)&&tmpval;
479oem_apic=getBoolForKey(kOEMAPIC, &tmpval, &bootInfo->bootConfig)&&tmpval;
480oem_mcfg=getBoolForKey(kOEMMCFG, &tmpval, &bootInfo->bootConfig)&&tmpval;
481
482update_acpi=getBoolForKey(kUpdateACPI, &tmpval, &bootInfo->bootConfig)&&tmpval;
483}
484
485// Load replacement ACPI tables
486if (!oem_dsdt)
487new_dsdt=loadACPITable(kDSDT);
488
489if (!oem_hpet)
490new_hpet=loadACPITable(kHPET);
491
492if (!oem_sbst)
493new_sbst=loadACPITable(kSBST);
494
495if (!oem_ecdt)
496new_ecdt=loadACPITable(kECDT);
497
498if (!oem_asft)
499new_asft=loadACPITable(kASFT);
500
501if (!oem_dmar)
502new_dmar=loadACPITable(kDMAR);
503
504if (!oem_apic)
505new_apic=loadACPITable(kAPIC);
506
507if (!oem_mcfg)
508new_mcfg=loadACPITable(kMCFG);
509
510if (!oem_ssdt)
511{
512for (curssdt=0;curssdt<30;curssdt++)
513{
514new_ssdts[curssdt]=loadSSDTTable(curssdt);
515if (new_ssdts[curssdt])
516loadtotssdt++;
517}
518curssdt=0;
519}
520
521if (!new_dsdt)
522return setupAcpiNoMod();
523
524DBG("New ACPI tables Loaded in memory\n");
525
526// Do the same procedure for both versions of ACPI
527for (version=0; version<2; version++) {
528struct acpi_2_rsdp *rsdp, *rsdp_mod, *rsdp_conv=(struct acpi_2_rsdp *)0;
529struct acpi_2_rsdt *rsdt, *rsdt_mod;
530struct acpi_2_xsdt *xsdt_conv = (struct acpi_2_xsdt *)0;
531int rsdplength;
532
533// Find original rsdp
534rsdp=(struct acpi_2_rsdp *)(version?getAddressOfAcpi20Table():getAddressOfAcpiTable());
535if ((update_acpi) && (rsdp->Revision == 0))
536{
537rsdp_conv = (struct acpi_2_rsdp *)AllocateKernelMemory(sizeof(struct acpi_2_rsdp));
538memcpy(rsdp_conv, rsdp, 20);
539
540/* Add/change fields */
541rsdp_conv->Revision = 2; /* ACPI version 3 */
542rsdp_conv->Length = sizeof(struct acpi_2_rsdp);
543
544/* Correct checksums */
545rsdp_conv->Checksum = 0;
546rsdp_conv->Checksum = 256-checksum8(rsdp_conv, 20);
547rsdp_conv->ExtendedChecksum = 0;
548rsdp_conv->ExtendedChecksum = 256-checksum8(rsdp_conv, rsdp_conv->Length);
549
550rsdp = rsdp_conv;
551
552gen_xsdt = true;
553version = 1;
554
555addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI");
556
557verbose("Converted ACPI RSD PTR version 1 to version 3\n");
558}
559if (!rsdp)
560{
561DBG("No ACPI version %d found. Ignoring\n", version+1);
562if (version)
563addConfigurationTable(&gEfiAcpi20TableGuid, NULL, "ACPI_20");
564else
565addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI");
566continue;
567}
568rsdplength=version?rsdp->Length:20;
569
570DBG("RSDP version %d found @%x. Length=%d\n",version+1,rsdp,rsdplength);
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
577if (gen_xsdt)
578{
579rsdp_mod=rsdp_conv;
580} else {
581rsdp_mod=(struct acpi_2_rsdp *) AllocateKernelMemory(rsdplength);
582memcpy(rsdp_mod, rsdp, rsdplength);
583}
584
585rsdt=(struct acpi_2_rsdt *)(rsdp->RsdtAddress);
586
587DBG("RSDT @%x, Length %d\n",rsdt, rsdt->Length);
588
589if (rsdt && (uint32_t)rsdt !=0xffffffff && rsdt->Length<0x10000)
590{
591uint32_t *rsdt_entries;
592int rsdt_entries_num;
593int dropoffset=0, i;
594
595rsdt_mod=(struct acpi_2_rsdt *)AllocateKernelMemory(rsdt->Length);
596memcpy (rsdt_mod, rsdt, rsdt->Length);
597rsdp_mod->RsdtAddress=(uint32_t)rsdt_mod;
598rsdt_entries_num=(rsdt_mod->Length-sizeof(struct acpi_2_rsdt))/4;
599rsdt_entries=(uint32_t *)(rsdt_mod+1);
600
601if (gen_xsdt)
602{
603uint64_t *xsdt_conv_entries;
604
605xsdt_conv=(struct acpi_2_xsdt *)AllocateKernelMemory(sizeof(struct acpi_2_xsdt)+(rsdt_entries_num * 8));
606memcpy(xsdt_conv, rsdt, sizeof(struct acpi_2_rsdt));
607
608xsdt_conv->Signature[0] = 'X';
609xsdt_conv->Signature[1] = 'S';
610xsdt_conv->Signature[2] = 'D';
611xsdt_conv->Signature[3] = 'T';
612xsdt_conv->Length = sizeof(struct acpi_2_xsdt)+(rsdt_entries_num * 8);
613
614xsdt_conv_entries=(uint64_t *)(xsdt_conv+1);
615
616for (i=0;i<rsdt_entries_num;i++)
617{
618xsdt_conv_entries[i] = (uint64_t)rsdt_entries[i];
619}
620
621xsdt_conv->Checksum = 0;
622xsdt_conv->Checksum = 256-checksum8(xsdt_conv, xsdt_conv->Length);
623
624rsdp->XsdtAddress = (uint32_t)xsdt_conv;
625
626rsdp->ExtendedChecksum = 0;
627rsdp->ExtendedChecksum = 256-checksum8(rsdp, rsdp->Length);
628
629verbose("Converted RSDT table to XSDT table\n");
630}
631
632for (i=0;i<rsdt_entries_num;i++)
633{
634char *table=(char *)(rsdt_entries[i]);
635if (!table)
636continue;
637
638DBG("TABLE %c%c%c%c,",table[0],table[1],table[2],table[3]);
639
640rsdt_entries[i-dropoffset]=rsdt_entries[i];
641if (drop_ssdt && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')
642{
643dropoffset++;
644continue;
645}
646if (drop_hpet && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')
647{
648dropoffset++;
649continue;
650}
651if (drop_slic && table[0]=='S' && table[1]=='L' && table[2]=='I' && table[3]=='C')
652{
653dropoffset++;
654continue;
655}
656if (drop_sbst && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')
657{
658dropoffset++;
659continue;
660}
661if (drop_ecdt && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')
662{
663dropoffset++;
664continue;
665}
666if (drop_asft && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')
667{
668dropoffset++;
669continue;
670}
671if (drop_dmar && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')
672{
673dropoffset++;
674continue;
675}
676if ((!(oem_hpet)) && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')
677{
678DBG("HPET found\n");
679if (new_hpet)
680{
681rsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
682hpet_replaced=true;
683}
684continue;
685}
686if ((!(oem_sbst)) && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')
687{
688DBG("SBST found\n");
689if (new_sbst)
690{
691rsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
692sbst_replaced=true;
693}
694continue;
695}
696if ((!(oem_ecdt)) && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')
697{
698DBG("ECDT found\n");
699if (new_ecdt)
700{
701rsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
702ecdt_replaced=true;
703}
704continue;
705}
706if ((!(oem_asft)) && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')
707{
708DBG("ASF! found\n");
709if (new_asft)
710{
711rsdt_entries[i-dropoffset]=(uint32_t)new_asft;
712asft_replaced=true;
713}
714continue;
715}
716if ((!(oem_dmar)) && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')
717{
718DBG("DMAR found\n");
719if (new_dmar)
720{
721rsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
722dmar_replaced=true;
723}
724continue;
725}
726if ((!(oem_apic)) && table[0]=='A' && table[1]=='P' && table[2]=='I' && table[3]=='C')
727{
728DBG("APIC found\n");
729if (new_apic)
730{
731rsdt_entries[i-dropoffset]=(uint32_t)new_apic;
732apic_replaced=true;
733}
734continue;
735}
736if ((!(oem_mcfg)) && table[0]=='M' && table[1]=='C' && table[2]=='F' && table[3]=='G')
737{
738DBG("MCFG found\n");
739if (new_mcfg)
740{
741rsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
742mcfg_replaced=true;
743}
744continue;
745}
746if ((!(oem_ssdt)) && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')
747{
748DBG("SSDT %d found", curssdt);
749if (new_ssdts[curssdt])
750{
751DBG(" and replaced");
752rsdt_entries[i-dropoffset]=(uint32_t)new_ssdts[curssdt];
753totssdt++;
754}
755DBG("\n");
756curssdt++;
757continue;
758}
759if (table[0]=='D' && table[1]=='S' && table[2]=='D' && table[3]=='T')
760{
761DBG("DSDT found\n");
762rsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;
763continue;
764}
765if (table[0]=='F' && table[1]=='A' && table[2]=='C' && table[3]=='P')
766{
767struct acpi_2_fadt *fadt, *fadt_mod;
768fadt=(struct acpi_2_fadt *)rsdt_entries[i];
769
770DBG("FADT found @%x, Length %d\n",fadt, fadt->Length);
771
772if (!fadt || (uint32_t)fadt == 0xffffffff || fadt->Length>0x10000)
773{
774printf("FADT incorrect. Not modified\n");
775continue;
776}
777
778fadt_mod = patch_fadt(fadt, new_dsdt, update_acpi);
779rsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;
780continue;
781}
782}
783DBG("\n");
784
785if ((!oem_hpet) && (!hpet_replaced))
786{
787if (new_hpet)
788{
789rsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
790hpet_added=true;
791i++;
792}
793}
794
795if ((!oem_sbst) && (!sbst_replaced))
796{
797if (new_sbst)
798{
799rsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
800sbst_added=true;
801i++;
802}
803}
804
805if ((!oem_ecdt) && (!ecdt_replaced))
806{
807if (new_ecdt)
808{
809rsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
810ecdt_added=true;
811i++;
812}
813}
814
815if ((!oem_asft) && (!asft_replaced))
816{
817if (new_asft)
818{
819rsdt_entries[i-dropoffset]=(uint32_t)new_asft;
820asft_added=true;
821i++;
822}
823}
824
825if ((!oem_dmar) && (!dmar_replaced))
826{
827if (new_dmar)
828{
829rsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
830dmar_added=true;
831i++;
832}
833}
834
835if ((!oem_apic) && (!apic_replaced))
836{
837if (new_apic)
838{
839rsdt_entries[i-dropoffset]=(uint32_t)new_apic;
840apic_added=true;
841i++;
842}
843}
844
845if ((!oem_mcfg) && (!mcfg_replaced))
846{
847if (new_mcfg)
848{
849rsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
850mcfg_added=true;
851i++;
852}
853}
854
855if (!oem_ssdt)
856{
857while ((totssdt < loadtotssdt) && (curssdt < 30))
858{
859if (new_ssdts[curssdt])
860{
861DBG("adding SSDT %d\n", curssdt);
862rsdt_entries[i-dropoffset]=(uint32_t)new_ssdts[curssdt];
863totssdt++;
864newtotssdt++;
865i++;
866}
867curssdt++;
868}
869}
870
871// Correct the checksum of RSDT
872rsdt_mod->Length-=4*dropoffset;
873rsdt_mod->Length+=4*newtotssdt;
874if (hpet_added)
875rsdt_mod->Length+=4;
876if (sbst_added)
877rsdt_mod->Length+=4;
878if (ecdt_added)
879rsdt_mod->Length+=4;
880if (asft_added)
881rsdt_mod->Length+=4;
882if (dmar_added)
883rsdt_mod->Length+=4;
884if (apic_added)
885rsdt_mod->Length+=4;
886if (mcfg_added)
887rsdt_mod->Length+=4;
888
889DBG("RSDT: Original checksum %d, ", rsdt_mod->Checksum);
890
891rsdt_mod->Checksum=0;
892rsdt_mod->Checksum=256-checksum8(rsdt_mod,rsdt_mod->Length);
893
894DBG("New checksum %d at %x\n", rsdt_mod->Checksum,rsdt_mod);
895}
896else
897{
898rsdp_mod->RsdtAddress=0;
899printf("RSDT not found or RSDT incorrect\n");
900}
901
902if (version)
903{
904struct acpi_2_xsdt *xsdt, *xsdt_mod;
905
906// FIXME: handle 64-bit address correctly
907
908if (gen_xsdt)
909xsdt=xsdt_conv;
910else
911xsdt=(struct acpi_2_xsdt*) ((uint32_t)rsdp->XsdtAddress);
912
913DBG("XSDT @%x;%x, Length=%d\n", (uint32_t)(rsdp->XsdtAddress>>32),(uint32_t)rsdp->XsdtAddress,
914xsdt->Length);
915if (xsdt && (uint64_t)rsdp->XsdtAddress<0xffffffff && xsdt->Length<0x10000)
916{
917uint64_t *xsdt_entries;
918int xsdt_entries_num, i;
919int dropoffset=0;
920curssdt=0, totssdt=0, newtotssdt=0;
921hpet_replaced=false, hpet_added=false;
922sbst_replaced=false, sbst_added=false;
923ecdt_replaced=false, ecdt_added=false;
924asft_replaced=false, asft_added=false;
925dmar_replaced=false, dmar_added=false;
926apic_replaced=false, apic_added=false;
927mcfg_replaced=false, mcfg_added=false;
928
929if (gen_xsdt)
930xsdt_mod=xsdt;
931else
932{
933xsdt_mod=(struct acpi_2_xsdt*)AllocateKernelMemory(xsdt->Length);
934memcpy(xsdt_mod, xsdt, xsdt->Length);
935}
936
937rsdp_mod->XsdtAddress=(uint32_t)xsdt_mod;
938xsdt_entries_num=(xsdt_mod->Length-sizeof(struct acpi_2_xsdt))/8;
939xsdt_entries=(uint64_t *)(xsdt_mod+1);
940for (i=0;i<xsdt_entries_num;i++)
941{
942char *table=(char *)((uint32_t)(xsdt_entries[i]));
943if (!table)
944continue;
945xsdt_entries[i-dropoffset]=xsdt_entries[i];
946if (drop_ssdt && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')
947{
948dropoffset++;
949continue;
950}
951if (drop_hpet && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')
952{
953dropoffset++;
954continue;
955}
956if (drop_slic && table[0]=='S' && table[1]=='L' && table[2]=='I' && table[3]=='C')
957{
958dropoffset++;
959continue;
960}
961if (drop_sbst && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')
962{
963dropoffset++;
964continue;
965}
966if (drop_ecdt && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')
967{
968dropoffset++;
969continue;
970}
971if (drop_asft && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')
972{
973dropoffset++;
974continue;
975}
976if (drop_dmar && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')
977{
978dropoffset++;
979continue;
980}
981if ((!(oem_hpet)) && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')
982{
983DBG("HPET found\n");
984if (new_hpet)
985{
986xsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
987hpet_replaced=true;
988}
989continue;
990}
991if ((!(oem_sbst)) && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')
992{
993DBG("SBST found\n");
994if (new_sbst)
995{
996xsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
997sbst_replaced=true;
998}
999continue;
1000}
1001if ((!(oem_ecdt)) && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')
1002{
1003DBG("ECDT found\n");
1004if (new_ecdt)
1005{
1006xsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
1007ecdt_replaced=true;
1008}
1009continue;
1010}
1011if ((!(oem_asft)) && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')
1012{
1013DBG("ASF! found\n");
1014if (new_asft)
1015{
1016xsdt_entries[i-dropoffset]=(uint32_t)new_asft;
1017asft_replaced=true;
1018}
1019continue;
1020}
1021if ((!(oem_dmar)) && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')
1022{
1023DBG("DMAR found\n");
1024if (new_dmar)
1025{
1026xsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
1027dmar_replaced=true;
1028}
1029continue;
1030}
1031if ((!(oem_apic)) && table[0]=='A' && table[1]=='P' && table[2]=='I' && table[3]=='C')
1032{
1033DBG("APIC found\n");
1034if (new_apic)
1035{
1036xsdt_entries[i-dropoffset]=(uint32_t)new_apic;
1037apic_replaced=true;
1038}
1039continue;
1040}
1041if ((!(oem_mcfg)) && table[0]=='M' && table[1]=='C' && table[2]=='F' && table[3]=='G')
1042{
1043DBG("MCFG found\n");
1044if (new_mcfg)
1045{
1046xsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
1047mcfg_replaced=true;
1048}
1049continue;
1050}
1051if ((!(oem_ssdt)) && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1052{
1053DBG("SSDT %d found", curssdt);
1054if (new_ssdts[curssdt])
1055{
1056DBG(" and replaced");
1057xsdt_entries[i-dropoffset]=(uint32_t)new_ssdts[curssdt];
1058totssdt++;
1059}
1060DBG("\n");
1061curssdt++;
1062continue;
1063}
1064if (table[0]=='D' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1065{
1066DBG("DSDT found\n");
1067
1068xsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;
1069
1070DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
1071
1072continue;
1073}
1074if (table[0]=='F' && table[1]=='A' && table[2]=='C' && table[3]=='P')
1075{
1076struct acpi_2_fadt *fadt, *fadt_mod;
1077fadt=(struct acpi_2_fadt *)(uint32_t)xsdt_entries[i];
1078
1079DBG("FADT found @%x,%x, Length %d\n",(uint32_t)(xsdt_entries[i]>>32),fadt,
1080 fadt->Length);
1081
1082if (!fadt || (uint64_t)xsdt_entries[i] >= 0xffffffff || fadt->Length>0x10000)
1083{
1084verbose("FADT incorrect or after 4GB. Dropping XSDT\n");
1085goto drop_xsdt;
1086}
1087
1088fadt_mod = patch_fadt(fadt, new_dsdt,update_acpi);
1089xsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;
1090
1091DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
1092
1093continue;
1094}
1095
1096DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
1097
1098}
1099
1100if ((!oem_hpet) && (!hpet_replaced))
1101{
1102if (new_hpet)
1103{
1104xsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
1105hpet_added=true;
1106i++;
1107}
1108}
1109
1110if ((!oem_sbst) && (!sbst_replaced))
1111{
1112if (new_sbst)
1113{
1114xsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
1115sbst_added=true;
1116i++;
1117}
1118}
1119
1120if ((!oem_ecdt) && (!ecdt_replaced))
1121{
1122if (new_ecdt)
1123{
1124xsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
1125ecdt_added=true;
1126i++;
1127}
1128}
1129
1130if ((!oem_asft) && (!asft_replaced))
1131{
1132if (new_asft)
1133{
1134xsdt_entries[i-dropoffset]=(uint32_t)new_asft;
1135asft_added=true;
1136i++;
1137}
1138}
1139
1140if ((!oem_dmar) && (!dmar_replaced))
1141{
1142if (new_dmar)
1143{
1144xsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
1145dmar_added=true;
1146i++;
1147}
1148}
1149
1150if ((!oem_apic) && (!apic_replaced))
1151{
1152if (new_apic)
1153{
1154xsdt_entries[i-dropoffset]=(uint32_t)new_apic;
1155apic_added=true;
1156i++;
1157}
1158}
1159
1160if ((!oem_mcfg) && (!mcfg_replaced))
1161{
1162if (new_mcfg)
1163{
1164xsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
1165mcfg_added=true;
1166i++;
1167}
1168}
1169
1170if (!oem_ssdt)
1171{
1172while ((totssdt < loadtotssdt) && (curssdt < 30))
1173{
1174if (new_ssdts[curssdt])
1175{
1176DBG("adding SSDT %d\n", curssdt);
1177xsdt_entries[i-dropoffset]=(uint32_t)new_ssdts[curssdt];
1178totssdt++;
1179newtotssdt++;
1180i++;
1181}
1182curssdt++;
1183}
1184}
1185
1186// Correct the checksum of XSDT
1187xsdt_mod->Length-=8*dropoffset;
1188xsdt_mod->Length+=8*newtotssdt;
1189if (hpet_added)
1190xsdt_mod->Length+=8;
1191if (sbst_added)
1192xsdt_mod->Length+=8;
1193if (ecdt_added)
1194xsdt_mod->Length+=8;
1195if (asft_added)
1196xsdt_mod->Length+=8;
1197if (dmar_added)
1198xsdt_mod->Length+=8;
1199if (apic_added)
1200xsdt_mod->Length+=8;
1201if (mcfg_added)
1202xsdt_mod->Length+=8;
1203
1204xsdt_mod->Checksum=0;
1205xsdt_mod->Checksum=256-checksum8(xsdt_mod,xsdt_mod->Length);
1206}
1207else
1208{
1209drop_xsdt:
1210
1211DBG("About to drop XSDT\n");
1212
1213/*FIXME: Now we just hope that if MacOS doesn't find XSDT it reverts to RSDT.
1214 * A Better strategy would be to generate
1215 */
1216
1217rsdp_mod->XsdtAddress=0xffffffffffffffffLL;
1218verbose("XSDT not found or XSDT incorrect\n");
1219}
1220}
1221
1222// Correct the checksum of RSDP
1223
1224DBG("RSDP: Original checksum %d, ", rsdp_mod->Checksum);
1225
1226rsdp_mod->Checksum=0;
1227rsdp_mod->Checksum=256-checksum8(rsdp_mod,20);
1228
1229DBG("New checksum %d\n", rsdp_mod->Checksum);
1230
1231if (version)
1232{
1233DBG("RSDP: Original extended checksum %d", rsdp_mod->ExtendedChecksum);
1234
1235rsdp_mod->ExtendedChecksum=0;
1236rsdp_mod->ExtendedChecksum=256-checksum8(rsdp_mod,rsdp_mod->Length);
1237
1238DBG("New extended checksum %d\n", rsdp_mod->ExtendedChecksum);
1239
1240}
1241
1242verbose("Patched ACPI version %d DSDT\n", version+1);
1243if (version)
1244{
1245/* XXX aserebln why uint32 cast if pointer is uint64 ? */
1246acpi20_p = (uint32_t)rsdp_mod;
1247addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
1248}
1249else
1250{
1251/* XXX aserebln why uint32 cast if pointer is uint64 ? */
1252acpi10_p = (uint32_t)rsdp_mod;
1253addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
1254}
1255}
1256#if DEBUG_DSDT
1257printf("Press a key to continue... (DEBUG_DSDT)\n");
1258getc();
1259#endif
1260return 1;
1261}
1262

Archive Download this file

Revision: 67