Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 164