Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 62