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:
112//verbose("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{
223//verbose("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 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
387if (new_dsdt)
388{
389
390// Patch FACS Address
391fadt_mod->FIRMWARE_CTRL=(uint32_t)fadt->FIRMWARE_CTRL;
392if ((uint32_t)(&(fadt_mod->X_FIRMWARE_CTRL))-(uint32_t)fadt_mod+8<=fadt_mod->Length)
393fadt_mod->X_FIRMWARE_CTRL=(uint32_t)fadt->FIRMWARE_CTRL
394
395// Patch DSDT Address
396DBG("DSDT: Old @%x,%x, ",fadt_mod->DSDT,fadt_mod->X_DSDT);
397
398fadt_mod->DSDT=(uint32_t)new_dsdt;
399if ((uint32_t)(&(fadt_mod->X_DSDT))-(uint32_t)fadt_mod+8<=fadt_mod->Length)
400fadt_mod->X_DSDT=(uint32_t)new_dsdt;
401
402DBG("New @%x,%x\n",fadt_mod->DSDT,fadt_mod->X_DSDT);
403verbose("FADT: Custom DSDT used !\n");
404}
405
406// Correct the checksum
407fadt_mod->Checksum=0;
408fadt_mod->Checksum=256-checksum8(fadt_mod,fadt_mod->Length);
409
410return fadt_mod;
411}
412
413/* Setup ACPI without replacing DSDT. */
414int setupAcpiNoMod()
415{
416//addConfigurationTable(&gEfiAcpiTableGuid, getAddressOfAcpiTable(), "ACPI");
417//addConfigurationTable(&gEfiAcpi20TableGuid, getAddressOfAcpi20Table(), "ACPI_20");
418/* XXX aserebln why uint32 cast if pointer is uint64 ? */
419acpi10_p = (uint32_t)getAddressOfAcpiTable();
420acpi20_p = (uint32_t)getAddressOfAcpi20Table();
421addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
422if(acpi20_p) addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
423return 1;
424}
425
426/* Setup ACPI. Replace DSDT if DSDT.aml is found */
427int setupAcpi(void)
428{
429int version;
430void *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];
431
432bool 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;
433bool drop_ssdt=false, drop_hpet=false, drop_slic=false, drop_sbst=false, drop_ecdt=false, drop_asft=false, drop_dmar=false;
434bool update_acpi=false, gen_xsdt=false;
435bool hpet_replaced=false, sbst_replaced=false, ecdt_replaced=false, asft_replaced=false, dmar_replaced=false, apic_replaced=false, mcfg_replaced=false;
436bool hpet_added=false, sbst_added=false, ecdt_added=false, asft_added=false, dmar_added=false, apic_added=false, mcfg_added=false;
437
438int curssdt=0, loadtotssdt=0, totssdt=0, newtotssdt=0;
439
440{
441bool tmpval;
442
443drop_ssdt=getBoolForKey(kDropSSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
444drop_hpet=getBoolForKey(kDropHPET, &tmpval, &bootInfo->bootConfig)&&tmpval;
445drop_slic=getBoolForKey(kDropSLIC, &tmpval, &bootInfo->bootConfig)&&tmpval;
446drop_sbst=getBoolForKey(kDropSBST, &tmpval, &bootInfo->bootConfig)&&tmpval;
447drop_ecdt=getBoolForKey(kDropECDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
448drop_asft=getBoolForKey(kDropASFT, &tmpval, &bootInfo->bootConfig)&&tmpval;
449drop_dmar=getBoolForKey(kDropDMAR, &tmpval, &bootInfo->bootConfig)&&tmpval;
450
451oem_dsdt=getBoolForKey(kOEMDSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
452oem_ssdt=getBoolForKey(kOEMSSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
453oem_hpet=getBoolForKey(kOEMHPET, &tmpval, &bootInfo->bootConfig)&&tmpval;
454oem_sbst=getBoolForKey(kOEMSBST, &tmpval, &bootInfo->bootConfig)&&tmpval;
455oem_ecdt=getBoolForKey(kOEMECDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
456oem_asft=getBoolForKey(kOEMASFT, &tmpval, &bootInfo->bootConfig)&&tmpval;
457oem_dmar=getBoolForKey(kOEMDMAR, &tmpval, &bootInfo->bootConfig)&&tmpval;
458oem_apic=getBoolForKey(kOEMAPIC, &tmpval, &bootInfo->bootConfig)&&tmpval;
459oem_mcfg=getBoolForKey(kOEMMCFG, &tmpval, &bootInfo->bootConfig)&&tmpval;
460
461update_acpi=getBoolForKey(kUpdateACPI, &tmpval, &bootInfo->bootConfig)&&tmpval;
462}
463
464// Load replacement ACPI tables
465if (!oem_dsdt)
466new_dsdt=loadACPITable(kDSDT);
467
468if (!oem_hpet)
469new_hpet=loadACPITable(kHPET);
470
471if (!oem_sbst)
472new_sbst=loadACPITable(kSBST);
473
474if (!oem_ecdt)
475new_ecdt=loadACPITable(kECDT);
476
477if (!oem_asft)
478new_asft=loadACPITable(kASFT);
479
480if (!oem_dmar)
481new_dmar=loadACPITable(kDMAR);
482
483if (!oem_apic)
484new_apic=loadACPITable(kAPIC);
485
486if (!oem_mcfg)
487new_mcfg=loadACPITable(kMCFG);
488
489if (!oem_ssdt)
490{
491for (curssdt=0;curssdt<14;curssdt++)
492{
493new_ssdts[curssdt]=loadSSDTTable(curssdt);
494if (new_ssdts[curssdt])
495loadtotssdt++;
496}
497curssdt=0;
498}
499/*
500if (!new_dsdt)
501return setupAcpiNoMod();
502*/
503DBG("New ACPI tables Loaded in memory\n");
504
505// Do the same procedure for both versions of ACPI
506for (version=0; version<2; version++) {
507struct acpi_2_rsdp *rsdp, *rsdp_mod, *rsdp_conv=(struct acpi_2_rsdp *)0;
508struct acpi_2_rsdt *rsdt, *rsdt_mod;
509struct acpi_2_xsdt *xsdt_conv = (struct acpi_2_xsdt *)0;
510int rsdplength;
511
512// Find original rsdp
513rsdp=(struct acpi_2_rsdp *)(version?getAddressOfAcpi20Table():getAddressOfAcpiTable());
514if ((update_acpi) && (rsdp->Revision == 0))
515{
516rsdp_conv = (struct acpi_2_rsdp *)AllocateKernelMemory(sizeof(struct acpi_2_rsdp));
517memcpy(rsdp_conv, rsdp, 20);
518
519/* Add/change fields */
520rsdp_conv->Revision = 2; /* ACPI version 3 */
521rsdp_conv->Length = sizeof(struct acpi_2_rsdp);
522
523/* Correct checksums */
524rsdp_conv->Checksum = 0;
525rsdp_conv->Checksum = 256-checksum8(rsdp_conv, 20);
526rsdp_conv->ExtendedChecksum = 0;
527rsdp_conv->ExtendedChecksum = 256-checksum8(rsdp_conv, rsdp_conv->Length);
528
529rsdp = rsdp_conv;
530
531gen_xsdt = true;
532version = 1;
533
534addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI");
535
536verbose("Converted ACPI RSD PTR version 1 to version 3\n");
537}
538if (!rsdp)
539{
540DBG("No ACPI version %d found. Ignoring\n", version+1);
541if (version)
542addConfigurationTable(&gEfiAcpi20TableGuid, NULL, "ACPI_20");
543else
544addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI");
545continue;
546}
547rsdplength=version?rsdp->Length:20;
548
549DBG("RSDP version %d found @%x. Length=%d\n",version+1,rsdp,rsdplength);
550
551/* FIXME: no check that memory allocation succeeded
552 * Copy and patch RSDP,RSDT, XSDT and FADT
553 * For more info see ACPI Specification pages 110 and following
554 */
555
556if (gen_xsdt)
557{
558rsdp_mod=rsdp_conv;
559} else {
560rsdp_mod=(struct acpi_2_rsdp *) AllocateKernelMemory(rsdplength);
561memcpy(rsdp_mod, rsdp, rsdplength);
562}
563
564rsdt=(struct acpi_2_rsdt *)(rsdp->RsdtAddress);
565
566DBG("RSDT @%x, Length %d\n",rsdt, rsdt->Length);
567
568if (rsdt && (uint32_t)rsdt !=0xffffffff && rsdt->Length<0x10000)
569{
570uint32_t *rsdt_entries;
571int rsdt_entries_num;
572int dropoffset=0, i;
573
574rsdt_mod=(struct acpi_2_rsdt *)AllocateKernelMemory(rsdt->Length);
575memcpy (rsdt_mod, rsdt, rsdt->Length);
576rsdp_mod->RsdtAddress=(uint32_t)rsdt_mod;
577rsdt_entries_num=(rsdt_mod->Length-sizeof(struct acpi_2_rsdt))/4;
578rsdt_entries=(uint32_t *)(rsdt_mod+1);
579
580if (gen_xsdt)
581{
582uint64_t *xsdt_conv_entries;
583
584xsdt_conv=(struct acpi_2_xsdt *)AllocateKernelMemory(sizeof(struct acpi_2_xsdt)+(rsdt_entries_num * 8));
585memcpy(xsdt_conv, rsdt, sizeof(struct acpi_2_rsdt));
586
587xsdt_conv->Signature[0] = 'X';
588xsdt_conv->Signature[1] = 'S';
589xsdt_conv->Signature[2] = 'D';
590xsdt_conv->Signature[3] = 'T';
591xsdt_conv->Length = sizeof(struct acpi_2_xsdt)+(rsdt_entries_num * 8);
592
593xsdt_conv_entries=(uint64_t *)(xsdt_conv+1);
594
595for (i=0;i<rsdt_entries_num;i++)
596{
597xsdt_conv_entries[i] = (uint64_t)rsdt_entries[i];
598}
599
600xsdt_conv->Checksum = 0;
601xsdt_conv->Checksum = 256-checksum8(xsdt_conv, xsdt_conv->Length);
602
603rsdp->XsdtAddress = (uint32_t)xsdt_conv;
604
605rsdp->ExtendedChecksum = 0;
606rsdp->ExtendedChecksum = 256-checksum8(rsdp, rsdp->Length);
607
608verbose("Converted RSDT table to XSDT table\n");
609}
610
611for (i=0;i<rsdt_entries_num;i++)
612{
613char *table=(char *)(rsdt_entries[i]);
614if (!table)
615continue;
616
617DBG("TABLE %c%c%c%c,",table[0],table[1],table[2],table[3]);
618
619rsdt_entries[i-dropoffset]=rsdt_entries[i];
620if (drop_ssdt && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')
621{
622dropoffset++;
623continue;
624}
625if (drop_hpet && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')
626{
627dropoffset++;
628continue;
629}
630if (drop_slic && table[0]=='S' && table[1]=='L' && table[2]=='I' && table[3]=='C')
631{
632dropoffset++;
633continue;
634}
635if (drop_sbst && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')
636{
637dropoffset++;
638continue;
639}
640if (drop_ecdt && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')
641{
642dropoffset++;
643continue;
644}
645if (drop_asft && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')
646{
647dropoffset++;
648continue;
649}
650if (drop_dmar && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')
651{
652dropoffset++;
653continue;
654}
655if ((!(oem_hpet)) && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')
656{
657DBG("HPET found\n");
658if (new_hpet)
659{
660rsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
661hpet_replaced=true;
662}
663continue;
664}
665if ((!(oem_sbst)) && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')
666{
667DBG("SBST found\n");
668if (new_sbst)
669{
670rsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
671sbst_replaced=true;
672}
673continue;
674}
675if ((!(oem_ecdt)) && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')
676{
677DBG("ECDT found\n");
678if (new_ecdt)
679{
680rsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
681ecdt_replaced=true;
682}
683continue;
684}
685if ((!(oem_asft)) && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')
686{
687DBG("ASF! found\n");
688if (new_asft)
689{
690rsdt_entries[i-dropoffset]=(uint32_t)new_asft;
691asft_replaced=true;
692}
693continue;
694}
695if ((!(oem_dmar)) && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')
696{
697DBG("DMAR found\n");
698if (new_dmar)
699{
700rsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
701dmar_replaced=true;
702}
703continue;
704}
705if ((!(oem_apic)) && table[0]=='A' && table[1]=='P' && table[2]=='I' && table[3]=='C')
706{
707DBG("APIC found\n");
708if (new_apic)
709{
710rsdt_entries[i-dropoffset]=(uint32_t)new_apic;
711apic_replaced=true;
712}
713continue;
714}
715if ((!(oem_mcfg)) && table[0]=='M' && table[1]=='C' && table[2]=='F' && table[3]=='G')
716{
717DBG("MCFG found\n");
718if (new_mcfg)
719{
720rsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
721mcfg_replaced=true;
722}
723continue;
724}
725if ((!(oem_ssdt)) && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')
726{
727DBG("SSDT %d found", curssdt);
728if (new_ssdts[curssdt])
729{
730DBG(" and replaced");
731rsdt_entries[i-dropoffset]=(uint32_t)new_ssdts[curssdt];
732totssdt++;
733}
734DBG("\n");
735curssdt++;
736continue;
737}
738if (table[0]=='D' && table[1]=='S' && table[2]=='D' && table[3]=='T')
739{
740DBG("DSDT found\n");
741rsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;
742continue;
743}
744if (table[0]=='F' && table[1]=='A' && table[2]=='C' && table[3]=='P')
745{
746struct acpi_2_fadt *fadt, *fadt_mod;
747fadt=(struct acpi_2_fadt *)rsdt_entries[i];
748
749DBG("FADT found @%x, Length %d\n",fadt, fadt->Length);
750
751if (!fadt || (uint32_t)fadt == 0xffffffff || fadt->Length>0x10000)
752{
753printf("FADT incorrect. Not modified\n");
754continue;
755}
756
757fadt_mod = patch_fadt(fadt, new_dsdt, update_acpi);
758rsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;
759continue;
760}
761}
762DBG("\n");
763
764if ((!oem_hpet) && (!hpet_replaced))
765{
766if (new_hpet)
767{
768rsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
769hpet_added=true;
770i++;
771}
772}
773
774if ((!oem_sbst) && (!sbst_replaced))
775{
776if (new_sbst)
777{
778rsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
779sbst_added=true;
780i++;
781}
782}
783
784if ((!oem_ecdt) && (!ecdt_replaced))
785{
786if (new_ecdt)
787{
788rsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
789ecdt_added=true;
790i++;
791}
792}
793
794if ((!oem_asft) && (!asft_replaced))
795{
796if (new_asft)
797{
798rsdt_entries[i-dropoffset]=(uint32_t)new_asft;
799asft_added=true;
800i++;
801}
802}
803
804if ((!oem_dmar) && (!dmar_replaced))
805{
806if (new_dmar)
807{
808rsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
809dmar_added=true;
810i++;
811}
812}
813
814if ((!oem_apic) && (!apic_replaced))
815{
816if (new_apic)
817{
818rsdt_entries[i-dropoffset]=(uint32_t)new_apic;
819apic_added=true;
820i++;
821}
822}
823
824if ((!oem_mcfg) && (!mcfg_replaced))
825{
826if (new_mcfg)
827{
828rsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
829mcfg_added=true;
830i++;
831}
832}
833
834if (!oem_ssdt)
835{
836while ((totssdt < loadtotssdt) && (curssdt < 14))
837{
838if (new_ssdts[curssdt])
839{
840DBG("adding SSDT %d\n", curssdt);
841rsdt_entries[i-dropoffset]=(uint32_t)new_ssdts[curssdt];
842totssdt++;
843newtotssdt++;
844i++;
845}
846curssdt++;
847}
848}
849
850// Correct the checksum of RSDT
851rsdt_mod->Length-=4*dropoffset;
852rsdt_mod->Length+=4*newtotssdt;
853if (hpet_added)
854rsdt_mod->Length+=4;
855if (sbst_added)
856rsdt_mod->Length+=4;
857if (ecdt_added)
858rsdt_mod->Length+=4;
859if (asft_added)
860rsdt_mod->Length+=4;
861if (dmar_added)
862rsdt_mod->Length+=4;
863if (apic_added)
864rsdt_mod->Length+=4;
865if (mcfg_added)
866rsdt_mod->Length+=4;
867
868DBG("RSDT: Original checksum %d, ", rsdt_mod->Checksum);
869
870rsdt_mod->Checksum=0;
871rsdt_mod->Checksum=256-checksum8(rsdt_mod,rsdt_mod->Length);
872
873DBG("New checksum %d at %x\n", rsdt_mod->Checksum,rsdt_mod);
874}
875else
876{
877rsdp_mod->RsdtAddress=0;
878printf("RSDT not found or RSDT incorrect\n");
879}
880
881if (version)
882{
883struct acpi_2_xsdt *xsdt, *xsdt_mod;
884
885// FIXME: handle 64-bit address correctly
886
887if (gen_xsdt)
888xsdt=xsdt_conv;
889else
890xsdt=(struct acpi_2_xsdt*) ((uint32_t)rsdp->XsdtAddress);
891
892DBG("XSDT @%x;%x, Length=%d\n", (uint32_t)(rsdp->XsdtAddress>>32),(uint32_t)rsdp->XsdtAddress,
893xsdt->Length);
894if (xsdt && (uint64_t)rsdp->XsdtAddress<0xffffffff && xsdt->Length<0x10000)
895{
896uint64_t *xsdt_entries;
897int xsdt_entries_num, i;
898int dropoffset=0;
899curssdt=0, totssdt=0, newtotssdt=0;
900hpet_replaced=false, hpet_added=false;
901sbst_replaced=false, sbst_added=false;
902ecdt_replaced=false, ecdt_added=false;
903asft_replaced=false, asft_added=false;
904dmar_replaced=false, dmar_added=false;
905apic_replaced=false, apic_added=false;
906mcfg_replaced=false, mcfg_added=false;
907
908if (gen_xsdt)
909xsdt_mod=xsdt;
910else
911{
912xsdt_mod=(struct acpi_2_xsdt*)AllocateKernelMemory(xsdt->Length);
913memcpy(xsdt_mod, xsdt, xsdt->Length);
914}
915
916rsdp_mod->XsdtAddress=(uint32_t)xsdt_mod;
917xsdt_entries_num=(xsdt_mod->Length-sizeof(struct acpi_2_xsdt))/8;
918xsdt_entries=(uint64_t *)(xsdt_mod+1);
919for (i=0;i<xsdt_entries_num;i++)
920{
921char *table=(char *)((uint32_t)(xsdt_entries[i]));
922if (!table)
923continue;
924xsdt_entries[i-dropoffset]=xsdt_entries[i];
925if (drop_ssdt && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')
926{
927dropoffset++;
928continue;
929}
930if (drop_hpet && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')
931{
932dropoffset++;
933continue;
934}
935if (drop_slic && table[0]=='S' && table[1]=='L' && table[2]=='I' && table[3]=='C')
936{
937dropoffset++;
938continue;
939}
940if (drop_sbst && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')
941{
942dropoffset++;
943continue;
944}
945if (drop_ecdt && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')
946{
947dropoffset++;
948continue;
949}
950if (drop_asft && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')
951{
952dropoffset++;
953continue;
954}
955if (drop_dmar && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')
956{
957dropoffset++;
958continue;
959}
960if ((!(oem_hpet)) && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')
961{
962DBG("HPET found\n");
963if (new_hpet)
964{
965xsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
966hpet_replaced=true;
967}
968continue;
969}
970if ((!(oem_sbst)) && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')
971{
972DBG("SBST found\n");
973if (new_sbst)
974{
975xsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
976sbst_replaced=true;
977}
978continue;
979}
980if ((!(oem_ecdt)) && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')
981{
982DBG("ECDT found\n");
983if (new_ecdt)
984{
985xsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
986ecdt_replaced=true;
987}
988continue;
989}
990if ((!(oem_asft)) && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')
991{
992DBG("ASF! found\n");
993if (new_asft)
994{
995xsdt_entries[i-dropoffset]=(uint32_t)new_asft;
996asft_replaced=true;
997}
998continue;
999}
1000if ((!(oem_dmar)) && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')
1001{
1002DBG("DMAR found\n");
1003if (new_dmar)
1004{
1005xsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
1006dmar_replaced=true;
1007}
1008continue;
1009}
1010if ((!(oem_apic)) && table[0]=='A' && table[1]=='P' && table[2]=='I' && table[3]=='C')
1011{
1012DBG("APIC found\n");
1013if (new_apic)
1014{
1015xsdt_entries[i-dropoffset]=(uint32_t)new_apic;
1016apic_replaced=true;
1017}
1018continue;
1019}
1020if ((!(oem_mcfg)) && table[0]=='M' && table[1]=='C' && table[2]=='F' && table[3]=='G')
1021{
1022DBG("MCFG found\n");
1023if (new_mcfg)
1024{
1025xsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
1026mcfg_replaced=true;
1027}
1028continue;
1029}
1030if ((!(oem_ssdt)) && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1031{
1032DBG("SSDT %d found", curssdt);
1033if (new_ssdts[curssdt])
1034{
1035DBG(" and replaced");
1036xsdt_entries[i-dropoffset]=(uint32_t)new_ssdts[curssdt];
1037totssdt++;
1038}
1039DBG("\n");
1040curssdt++;
1041continue;
1042}
1043if (table[0]=='D' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1044{
1045DBG("DSDT found\n");
1046
1047xsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;
1048
1049DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
1050
1051continue;
1052}
1053if (table[0]=='F' && table[1]=='A' && table[2]=='C' && table[3]=='P')
1054{
1055struct acpi_2_fadt *fadt, *fadt_mod;
1056fadt=(struct acpi_2_fadt *)(uint32_t)xsdt_entries[i];
1057
1058DBG("FADT found @%x,%x, Length %d\n",(uint32_t)(xsdt_entries[i]>>32),fadt,
1059 fadt->Length);
1060
1061if (!fadt || (uint64_t)xsdt_entries[i] >= 0xffffffff || fadt->Length>0x10000)
1062{
1063verbose("FADT incorrect or after 4GB. Dropping XSDT\n");
1064goto drop_xsdt;
1065}
1066
1067fadt_mod = patch_fadt(fadt, new_dsdt,update_acpi);
1068xsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;
1069
1070DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
1071
1072continue;
1073}
1074
1075DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
1076
1077}
1078
1079if ((!oem_hpet) && (!hpet_replaced))
1080{
1081if (new_hpet)
1082{
1083xsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
1084hpet_added=true;
1085i++;
1086}
1087}
1088
1089if ((!oem_sbst) && (!sbst_replaced))
1090{
1091if (new_sbst)
1092{
1093xsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
1094sbst_added=true;
1095i++;
1096}
1097}
1098
1099if ((!oem_ecdt) && (!ecdt_replaced))
1100{
1101if (new_ecdt)
1102{
1103xsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
1104ecdt_added=true;
1105i++;
1106}
1107}
1108
1109if ((!oem_asft) && (!asft_replaced))
1110{
1111if (new_asft)
1112{
1113xsdt_entries[i-dropoffset]=(uint32_t)new_asft;
1114asft_added=true;
1115i++;
1116}
1117}
1118
1119if ((!oem_dmar) && (!dmar_replaced))
1120{
1121if (new_dmar)
1122{
1123xsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
1124dmar_added=true;
1125i++;
1126}
1127}
1128
1129if ((!oem_apic) && (!apic_replaced))
1130{
1131if (new_apic)
1132{
1133xsdt_entries[i-dropoffset]=(uint32_t)new_apic;
1134apic_added=true;
1135i++;
1136}
1137}
1138
1139if ((!oem_mcfg) && (!mcfg_replaced))
1140{
1141if (new_mcfg)
1142{
1143xsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
1144mcfg_added=true;
1145i++;
1146}
1147}
1148
1149if (!oem_ssdt)
1150{
1151while ((totssdt < loadtotssdt) && (curssdt < 14))
1152{
1153if (new_ssdts[curssdt])
1154{
1155DBG("adding SSDT %d\n", curssdt);
1156xsdt_entries[i-dropoffset]=(uint32_t)new_ssdts[curssdt];
1157totssdt++;
1158newtotssdt++;
1159i++;
1160}
1161curssdt++;
1162}
1163}
1164
1165// Correct the checksum of XSDT
1166xsdt_mod->Length-=8*dropoffset;
1167xsdt_mod->Length+=8*newtotssdt;
1168if (hpet_added)
1169xsdt_mod->Length+=8;
1170if (sbst_added)
1171xsdt_mod->Length+=8;
1172if (ecdt_added)
1173xsdt_mod->Length+=8;
1174if (asft_added)
1175xsdt_mod->Length+=8;
1176if (dmar_added)
1177xsdt_mod->Length+=8;
1178if (apic_added)
1179xsdt_mod->Length+=8;
1180if (mcfg_added)
1181xsdt_mod->Length+=8;
1182
1183xsdt_mod->Checksum=0;
1184xsdt_mod->Checksum=256-checksum8(xsdt_mod,xsdt_mod->Length);
1185}
1186else
1187{
1188drop_xsdt:
1189
1190DBG("About to drop XSDT\n");
1191
1192/*FIXME: Now we just hope that if MacOS doesn't find XSDT it reverts to RSDT.
1193 * A Better strategy would be to generate
1194 */
1195
1196rsdp_mod->XsdtAddress=0xffffffffffffffffLL;
1197verbose("XSDT not found or XSDT incorrect\n");
1198}
1199}
1200
1201// Correct the checksum of RSDP
1202
1203DBG("RSDP: Original checksum %d, ", rsdp_mod->Checksum);
1204
1205rsdp_mod->Checksum=0;
1206rsdp_mod->Checksum=256-checksum8(rsdp_mod,20);
1207
1208DBG("New checksum %d\n", rsdp_mod->Checksum);
1209
1210if (version)
1211{
1212DBG("RSDP: Original extended checksum %d", rsdp_mod->ExtendedChecksum);
1213
1214rsdp_mod->ExtendedChecksum=0;
1215rsdp_mod->ExtendedChecksum=256-checksum8(rsdp_mod,rsdp_mod->Length);
1216
1217DBG("New extended checksum %d\n", rsdp_mod->ExtendedChecksum);
1218
1219}
1220
1221verbose("Patched ACPI version %d DSDT\n", version+1);
1222if (version)
1223{
1224/* XXX aserebln why uint32 cast if pointer is uint64 ? */
1225acpi20_p = (uint32_t)rsdp_mod;
1226acpi10_p = (uint32_t)rsdp_mod;
1227addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
1228addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
1229}
1230else
1231{
1232/* XXX aserebln why uint32 cast if pointer is uint64 ? */
1233acpi10_p = (uint32_t)rsdp_mod;
1234addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
1235}
1236}
1237#if DEBUG_DSDT
1238printf("Press a key to continue... (DEBUG_DSDT)\n");
1239getc();
1240#endif
1241return 1;
1242}
1243

Archive Download this file

Revision: 177