Root/
Source at commit 171 created 14 years 22 days ago. By valv, added 18seven's Quick-args macro, merged meklort's effort on ramdisk.. | |
---|---|
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 | struct acpi_2_fadt *␊ |
27 | patch_fadt(struct acpi_2_fadt *fadt, void *new_dsdt, bool UpdateFADT)␊ |
28 | {␊ |
29 | extern void setupSystemType(); ␊ |
30 | ␉␊ |
31 | struct acpi_2_fadt *fadt_mod;␊ |
32 | struct acpi_2_fadt *fadt_file = (struct acpi_2_fadt *)acpiLoadTable(kFADT);␊ |
33 | bool fadt_rev2_needed = false;␊ |
34 | bool fix_restart;␊ |
35 | const char * value;␊ |
36 | ␊ |
37 | // Restart Fix␊ |
38 | if (Platform.CPU.Vendor == 0x756E6547) {␉/* Intel */␊ |
39 | fix_restart = true;␊ |
40 | getBoolForKey(kRestartFix, &fix_restart, &bootInfo->bootConfig);␊ |
41 | } else {␊ |
42 | verbose ("Not an Intel platform: Restart Fix not applied !!!\n");␊ |
43 | fix_restart = false;␊ |
44 | }␊ |
45 | ␊ |
46 | if (fix_restart)␊ |
47 | fadt_rev2_needed = true;␊ |
48 | ␊ |
49 | // Allocate new fadt table␊ |
50 | if ((UpdateFADT) && (((fadt_file) && (fadt_file->Length < sizeof(struct acpi_2_fadt))) ||␊ |
51 | ((!fadt_file) && (fadt->Length < sizeof(struct acpi_2_fadt)))))␊ |
52 | {␊ |
53 | fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(sizeof(struct acpi_2_fadt));␊ |
54 | ␊ |
55 | if (fadt_file)␊ |
56 | memcpy(fadt_mod, fadt_file, fadt_file->Length);␊ |
57 | else␊ |
58 | memcpy(fadt_mod, fadt, fadt->Length);␊ |
59 | ␊ |
60 | fadt_mod->Length = sizeof(struct acpi_2_fadt);␊ |
61 | fadt_mod->Revision = 0x04; // FADT rev 4␊ |
62 | fadt_mod->RESET_REG = acpiFillGASStruct(0, 0);␊ |
63 | fadt_mod->RESET_VALUE = 0;␊ |
64 | fadt_mod->Reserved2[0] = 0;␊ |
65 | fadt_mod->Reserved2[1] = 0;␊ |
66 | fadt_mod->Reserved2[2] = 0;␊ |
67 | fadt_mod->X_PM1a_EVT_BLK = acpiFillGASStruct(fadt_mod->PM1a_EVT_BLK, fadt_mod->PM1_EVT_LEN);␊ |
68 | fadt_mod->X_PM1b_EVT_BLK = acpiFillGASStruct(fadt_mod->PM1b_EVT_BLK, fadt_mod->PM1_EVT_LEN);␊ |
69 | fadt_mod->X_PM1a_CNT_BLK = acpiFillGASStruct(fadt_mod->PM1a_CNT_BLK, fadt_mod->PM1_CNT_LEN);␊ |
70 | fadt_mod->X_PM1b_CNT_BLK = acpiFillGASStruct(fadt_mod->PM1b_CNT_BLK, fadt_mod->PM1_CNT_LEN);␊ |
71 | fadt_mod->X_PM2_CNT_BLK = acpiFillGASStruct(fadt_mod->PM2_CNT_BLK, fadt_mod->PM2_CNT_LEN);␊ |
72 | fadt_mod->X_PM_TMR_BLK = acpiFillGASStruct(fadt_mod->PM_TMR_BLK, fadt_mod->PM_TMR_LEN);␊ |
73 | fadt_mod->X_GPE0_BLK = acpiFillGASStruct(fadt_mod->GPE0_BLK, fadt_mod->GPE0_BLK_LEN);␊ |
74 | fadt_mod->X_GPE1_BLK = acpiFillGASStruct(fadt_mod->GPE1_BLK, fadt_mod->GPE1_BLK_LEN);␊ |
75 | verbose("Converted ACPI V%d FADT to ACPI V4 FADT\n", (fadt_file) ? fadt_file->Revision : fadt->Revision);␊ |
76 | } else {␊ |
77 | if (((!fadt_file) && ((fadt->Length < 0x84) && (fadt_rev2_needed))) ||␊ |
78 | ((fadt_file) && ((fadt_file->Length < 0x84) && (fadt_rev2_needed))))␊ |
79 | {␊ |
80 | fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(0x84);␊ |
81 | ␊ |
82 | if (fadt_file)␊ |
83 | memcpy(fadt_mod, fadt_file, fadt_file->Length);␊ |
84 | else␊ |
85 | memcpy(fadt_mod, fadt, fadt->Length);␊ |
86 | ␊ |
87 | fadt_mod->Length = 0x84;␊ |
88 | fadt_mod->Revision = 0x02; // FADT rev 2 (ACPI 1.0B MS extensions)␊ |
89 | }␊ |
90 | else␊ |
91 | {␊ |
92 | if (fadt_file)␊ |
93 | {␊ |
94 | fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(fadt_file->Length);␊ |
95 | memcpy(fadt_mod, fadt_file, fadt_file->Length);␊ |
96 | } else {␊ |
97 | fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(fadt->Length);␊ |
98 | memcpy(fadt_mod, fadt, fadt->Length);␊ |
99 | }␊ |
100 | }␊ |
101 | }␊ |
102 | // Determine system type / PM_Model␊ |
103 | if ( (value=getStringForKey(kSystemType, &bootInfo->bootConfig))!=NULL)␊ |
104 | {␊ |
105 | if (Platform.Type > 6) ␊ |
106 | {␊ |
107 | if(fadt_mod->Preferred_PM_Profile<=6)␊ |
108 | Platform.Type = fadt_mod->Preferred_PM_Profile; // get the fadt if correct␊ |
109 | else ␊ |
110 | Platform.Type = 1;␉␉/* Set a fixed value (Desktop) */␊ |
111 | verbose("Error: system-type must be 0..6. Defaulting to %d !\n", Platform.Type);␊ |
112 | }␊ |
113 | else␊ |
114 | Platform.Type = (unsigned char) strtoul(value, NULL, 10);␊ |
115 | }␊ |
116 | // Set Preferred_PM_Profile from System-type if only if user wanted this value to be forced␊ |
117 | if (fadt_mod->Preferred_PM_Profile != Platform.Type) ␊ |
118 | {␊ |
119 | if (value) ␊ |
120 | { // user has overriden the SystemType so take care of it in FACP␊ |
121 | verbose("FADT: changing Preferred_PM_Profile from 0x%02x to 0x%02x\n", fadt_mod->Preferred_PM_Profile, Platform.Type);␊ |
122 | fadt_mod->Preferred_PM_Profile = Platform.Type;␊ |
123 | }␊ |
124 | else␊ |
125 | { // Preferred_PM_Profile has a different value and no override has been set, so reflect the user value to ioregs␊ |
126 | Platform.Type = fadt_mod->Preferred_PM_Profile <= 6 ? fadt_mod->Preferred_PM_Profile : 1;␊ |
127 | } ␊ |
128 | }␊ |
129 | // We now have to write the systemm-type in ioregs: we cannot do it before in setupDeviceTree()␊ |
130 | // because we need to take care of facp original content, if it is correct.␊ |
131 | setupSystemType();␊ |
132 | ␊ |
133 | // Patch FADT to fix restart␊ |
134 | if (fix_restart)␊ |
135 | {␊ |
136 | fadt_mod->Flags|= 0x400;␊ |
137 | fadt_mod->RESET_REG = acpiFillGASStruct(0x0cf9, 1);␊ |
138 | fadt_mod->RESET_VALUE = 0x06;␊ |
139 | verbose("FADT: Restart Fix applied !\n");␊ |
140 | }␊ |
141 | ␊ |
142 | // Patch FACS Address␊ |
143 | fadt_mod->FIRMWARE_CTRL=(uint32_t)fadt->FIRMWARE_CTRL;␊ |
144 | if ((uint32_t)(&(fadt_mod->X_FIRMWARE_CTRL))-(uint32_t)fadt_mod+8<=fadt_mod->Length)␊ |
145 | fadt_mod->X_FIRMWARE_CTRL=(uint32_t)fadt->FIRMWARE_CTRL␊ |
146 | ␊ |
147 | // Patch DSDT Address␊ |
148 | DBG("DSDT: Old @%x,%x, ",fadt_mod->DSDT,fadt_mod->X_DSDT);␊ |
149 | ␊ |
150 | fadt_mod->DSDT=(uint32_t)new_dsdt;␊ |
151 | if ((uint32_t)(&(fadt_mod->X_DSDT))-(uint32_t)fadt_mod+8<=fadt_mod->Length)␊ |
152 | fadt_mod->X_DSDT=(uint32_t)new_dsdt;␊ |
153 | ␊ |
154 | DBG("New @%x,%x\n",fadt_mod->DSDT,fadt_mod->X_DSDT);␊ |
155 | ␊ |
156 | // Correct the checksum␊ |
157 | fadt_mod->Checksum=0;␊ |
158 | fadt_mod->Checksum=256-checksum8(fadt_mod,fadt_mod->Length);␊ |
159 | ␊ |
160 | return fadt_mod;␊ |
161 | }␊ |
162 | ␊ |
163 | /* Setup ACPI without replacing DSDT. */␊ |
164 | int setupAcpiNoMod()␊ |
165 | {␊ |
166 | //␉addConfigurationTable(&gEfiAcpiTableGuid, acpiGetAddressOfTable10(), "ACPI");␊ |
167 | //␉addConfigurationTable(&gEfiAcpi20TableGuid, acpiGetAddressOfTable20(), "ACPI_20");␊ |
168 | /* XXX aserebln why uint32 cast if pointer is uint64 ? */␊ |
169 | acpi10_p = (uint32_t) acpiGetAddressOfTable10();␊ |
170 | acpi20_p = (uint32_t) acpiGetAddressOfTable20();␊ |
171 | addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");␊ |
172 | if(acpi20_p) addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");␊ |
173 | return 1;␊ |
174 | }␊ |
175 | ␊ |
176 | ␊ |
177 | /* Setup ACPI. Replace DSDT if DSDT.aml is found */␊ |
178 | int setupAcpi(void)␊ |
179 | {␊ |
180 | int version;␊ |
181 | void *new_dsdt=NULL, *new_content=NULL;␊ |
182 | ␊ |
183 | bool update_acpi=false, gen_xsdt=false;␊ |
184 | bool hpet_replaced=false, sbst_replaced=false, ecdt_replaced=false, asft_replaced=false, dmar_replaced=false, apic_replaced=false, mcfg_replaced=false;␊ |
185 | bool hpet_added=false, sbst_added=false, ecdt_added=false, asft_added=false, dmar_added=false, apic_added=false, mcfg_added=false;␊ |
186 | ␊ |
187 | int curssdt=0, loadtotssdt=0, totssdt=0, newtotssdt=0;␊ |
188 | ␊ |
189 | {␊ |
190 | bool tmpval;␊ |
191 | ␊ |
192 | update_acpi=getBoolForKey(kUpdateACPI, &tmpval, &bootInfo->bootConfig)&&tmpval;␊ |
193 | }␊ |
194 | ␊ |
195 | // Load replacement ACPI tables if they provided by user according to the drop table list␊ |
196 | acpiLoadUserTables();␊ |
197 | ␊ |
198 | if (!(new_dsdt=acpiLoadTable("DSDT")))␊ |
199 | return setupAcpiNoMod();␊ |
200 | ␊ |
201 | DBG("New ACPI tables Loaded in memory\n");␊ |
202 | ␉␉␉␊ |
203 | // Do the same procedure for both versions of ACPI␊ |
204 | for (version=0; version<2; version++) {␊ |
205 | struct acpi_2_rsdp *rsdp, *rsdp_mod, *rsdp_conv=(struct acpi_2_rsdp *)0;␊ |
206 | struct acpi_2_rsdt *rsdt, *rsdt_mod;␊ |
207 | struct acpi_2_xsdt *xsdt_conv = (struct acpi_2_xsdt *)0;␊ |
208 | int rsdplength;␊ |
209 | ␊ |
210 | // Find original rsdp␊ |
211 | rsdp=(struct acpi_2_rsdp *) (version? ␊ |
212 | acpiGetAddressOfTable20() : ␊ |
213 | acpiGetAddressOfTable10());␊ |
214 | if ((update_acpi) && (rsdp->Revision == 0))␊ |
215 | {␊ |
216 | rsdp_conv = (struct acpi_2_rsdp *)AllocateKernelMemory(sizeof(struct acpi_2_rsdp));␊ |
217 | memcpy(rsdp_conv, rsdp, 20);␊ |
218 | ␊ |
219 | /* Add/change fields */␊ |
220 | rsdp_conv->Revision = 2; /* ACPI version 3 */␊ |
221 | rsdp_conv->Length = sizeof(struct acpi_2_rsdp);␊ |
222 | ␊ |
223 | /* Correct checksums */␊ |
224 | rsdp_conv->Checksum = 0;␊ |
225 | rsdp_conv->Checksum = 256-checksum8(rsdp_conv, 20);␊ |
226 | rsdp_conv->ExtendedChecksum = 0;␊ |
227 | rsdp_conv->ExtendedChecksum = 256-checksum8(rsdp_conv, rsdp_conv->Length);␊ |
228 | ␊ |
229 | rsdp = rsdp_conv;␊ |
230 | ␊ |
231 | gen_xsdt = true;␊ |
232 | version = 1;␊ |
233 | ␊ |
234 | addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI");␊ |
235 | ␊ |
236 | verbose("Converted ACPI RSD PTR version 1 to version 3\n");␊ |
237 | }␊ |
238 | if (!rsdp)␊ |
239 | {␊ |
240 | DBG("No ACPI version %d found. Ignoring\n", version+1);␊ |
241 | if (version)␊ |
242 | addConfigurationTable(&gEfiAcpi20TableGuid, NULL, "ACPI_20");␊ |
243 | else␊ |
244 | addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI");␊ |
245 | continue;␊ |
246 | }␊ |
247 | rsdplength=version?rsdp->Length:20;␊ |
248 | ␊ |
249 | DBG("RSDP version %d found @%x. Length=%d\n",version+1,rsdp,rsdplength);␊ |
250 | ␊ |
251 | /* FIXME: no check that memory allocation succeeded ␊ |
252 | * Copy and patch RSDP,RSDT, XSDT and FADT␊ |
253 | * For more info see ACPI Specification pages 110 and following␊ |
254 | */␊ |
255 | ␊ |
256 | if (gen_xsdt)␊ |
257 | {␊ |
258 | rsdp_mod=rsdp_conv;␊ |
259 | } else {␊ |
260 | rsdp_mod=(struct acpi_2_rsdp *) AllocateKernelMemory(rsdplength);␊ |
261 | memcpy(rsdp_mod, rsdp, rsdplength);␊ |
262 | }␊ |
263 | ␊ |
264 | rsdt=(struct acpi_2_rsdt *)(rsdp->RsdtAddress);␊ |
265 | ␊ |
266 | DBG("RSDT @%x, Length %d\n",rsdt, rsdt->Length);␊ |
267 | ␉␉␊ |
268 | if (rsdt && (uint32_t)rsdt !=0xffffffff && rsdt->Length<0x10000)␊ |
269 | {␊ |
270 | uint32_t *rsdt_entries;␊ |
271 | int rsdt_entries_num;␊ |
272 | int dropoffset=0, i;␊ |
273 | ␉␉␉␊ |
274 | rsdt_mod=(struct acpi_2_rsdt *)AllocateKernelMemory(rsdt->Length); ␊ |
275 | memcpy (rsdt_mod, rsdt, rsdt->Length);␊ |
276 | rsdp_mod->RsdtAddress=(uint32_t)rsdt_mod;␊ |
277 | rsdt_entries_num=(rsdt_mod->Length-sizeof(struct acpi_2_rsdt))/4;␊ |
278 | rsdt_entries=(uint32_t *)(rsdt_mod+1);␊ |
279 | ␊ |
280 | if (gen_xsdt)␊ |
281 | {␊ |
282 | uint64_t *xsdt_conv_entries;␊ |
283 | ␊ |
284 | xsdt_conv=(struct acpi_2_xsdt *)AllocateKernelMemory(sizeof(struct acpi_2_xsdt)+(rsdt_entries_num * 8));␊ |
285 | memcpy(xsdt_conv, rsdt, sizeof(struct acpi_2_rsdt));␊ |
286 | ␊ |
287 | xsdt_conv->Signature[0] = 'X';␊ |
288 | xsdt_conv->Signature[1] = 'S';␊ |
289 | xsdt_conv->Signature[2] = 'D';␊ |
290 | xsdt_conv->Signature[3] = 'T';␊ |
291 | xsdt_conv->Length = sizeof(struct acpi_2_xsdt)+(rsdt_entries_num * 8);␊ |
292 | ␊ |
293 | xsdt_conv_entries=(uint64_t *)(xsdt_conv+1);␊ |
294 | ␊ |
295 | for (i=0;i<rsdt_entries_num;i++)␊ |
296 | {␊ |
297 | xsdt_conv_entries[i] = (uint64_t)rsdt_entries[i];␊ |
298 | }␊ |
299 | ␊ |
300 | xsdt_conv->Checksum = 0;␊ |
301 | xsdt_conv->Checksum = 256-checksum8(xsdt_conv, xsdt_conv->Length);␊ |
302 | ␊ |
303 | rsdp->XsdtAddress = (uint32_t)xsdt_conv;␊ |
304 | ␊ |
305 | rsdp->ExtendedChecksum = 0;␊ |
306 | rsdp->ExtendedChecksum = 256-checksum8(rsdp, rsdp->Length);␊ |
307 | ␊ |
308 | verbose("Converted RSDT table to XSDT table\n");␊ |
309 | }␊ |
310 | ␊ |
311 | for (i=0;i<rsdt_entries_num;i++)␊ |
312 | {␊ |
313 | char *table=(char *)(rsdt_entries[i]);␊ |
314 | if (!table)␊ |
315 | continue;␊ |
316 | ␊ |
317 | DBG("TABLE %c%c%c%c,",table[0],table[1],table[2],table[3]);␊ |
318 | ␊ |
319 | /*****************/␊ |
320 | /* CHECK ME here:*/␊ |
321 | /****************/␊ |
322 | ␊ |
323 | /* either we add a user table*/␊ |
324 | if ((new_content=acpiTableUserContent(table)))␊ |
325 | {␊ |
326 | DBG("..Installing user acpi table %c%c%c%c\n", table[0],table[1],table[2],table[3]);␊ |
327 | if (new_content)␊ |
328 | {␊ |
329 | rsdt_entries[i-dropoffset]=(uint32_t)new_content;␊ |
330 | rsdt_mod->Length+=4;␊ |
331 | }␊ |
332 | continue;␊ |
333 | }␊ |
334 | else if (acpiIsTableDropped(table))␊ |
335 | { // or it is in the drop list and we don't add it at all␊ |
336 | dropoffset++;␊ |
337 | continue;␊ |
338 | }␊ |
339 | else // or we keep the default table␊ |
340 | rsdt_entries[i-dropoffset]=rsdt_entries[i];␊ |
341 | ␊ |
342 | /* CHECK ME HERE: for special cases */␊ |
343 | /*␊ |
344 | if ((!(oem_ssdt)) && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')␊ |
345 | {␊ |
346 | DBG("SSDT %d found", curssdt);␊ |
347 | if (new_ssdts[curssdt])␊ |
348 | {␊ |
349 | DBG(" and replaced");␊ |
350 | rsdt_entries[i-dropoffset]=(uint32_t)new_ssdts[curssdt];␊ |
351 | totssdt++;␊ |
352 | }␊ |
353 | DBG("\n");␊ |
354 | curssdt++;␊ |
355 | continue;␊ |
356 | }␊ |
357 | if (table[0]=='F' && table[1]=='A' && table[2]=='C' && table[3]=='P')␊ |
358 | {␊ |
359 | struct acpi_2_fadt *fadt, *fadt_mod;␊ |
360 | fadt=(struct acpi_2_fadt *)rsdt_entries[i];␊ |
361 | ␊ |
362 | DBG("FADT found @%x, Length %d\n",fadt, fadt->Length);␊ |
363 | ␊ |
364 | if (!fadt || (uint32_t)fadt == 0xffffffff || fadt->Length>0x10000)␊ |
365 | {␊ |
366 | printf("FADT incorrect. Not modified\n");␊ |
367 | continue;␊ |
368 | }␊ |
369 | ␉␉␉␉␉␊ |
370 | fadt_mod = patch_fadt(fadt, new_dsdt, update_acpi);␊ |
371 | rsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;␊ |
372 | continue;␊ |
373 | }␊ |
374 | */␊ |
375 | }␊ |
376 | DBG("\n");␊ |
377 | ␊ |
378 | /* CHECK ME here */␊ |
379 | /* if (!oem_ssdt)␊ |
380 | { ␉␉␉␊ |
381 | while ((totssdt < loadtotssdt) && (curssdt < 30))␊ |
382 | {␊ |
383 | if (new_ssdts[curssdt])␊ |
384 | {␊ |
385 | DBG("adding SSDT %d\n", curssdt);␊ |
386 | rsdt_entries[i-dropoffset]=(uint32_t)new_ssdts[curssdt];␊ |
387 | totssdt++;␊ |
388 | newtotssdt++;␊ |
389 | i++;␊ |
390 | }␊ |
391 | curssdt++;␊ |
392 | }␊ |
393 | }␊ |
394 | */␊ |
395 | ␊ |
396 | // Correct the checksum of RSDT␊ |
397 | rsdt_mod->Length-=4*dropoffset;␊ |
398 | rsdt_mod->Length+=4*newtotssdt;␊ |
399 | ␊ |
400 | DBG("RSDT: Original checksum %d, ", rsdt_mod->Checksum);␊ |
401 | ␊ |
402 | rsdt_mod->Checksum=0;␊ |
403 | rsdt_mod->Checksum=256-checksum8(rsdt_mod,rsdt_mod->Length);␊ |
404 | ␊ |
405 | DBG("New checksum %d at %x\n", rsdt_mod->Checksum,rsdt_mod);␊ |
406 | }␊ |
407 | else␊ |
408 | {␊ |
409 | rsdp_mod->RsdtAddress=0;␊ |
410 | printf("RSDT not found or RSDT incorrect\n");␊ |
411 | }␊ |
412 | ␊ |
413 | if (version)␊ |
414 | {␊ |
415 | struct acpi_2_xsdt *xsdt, *xsdt_mod;␊ |
416 | ␊ |
417 | // FIXME: handle 64-bit address correctly␊ |
418 | ␊ |
419 | if (gen_xsdt)␊ |
420 | xsdt=xsdt_conv;␊ |
421 | else␊ |
422 | xsdt=(struct acpi_2_xsdt*) ((uint32_t)rsdp->XsdtAddress);␊ |
423 | ␊ |
424 | DBG("XSDT @%x;%x, Length=%d\n", (uint32_t)(rsdp->XsdtAddress>>32),(uint32_t)rsdp->XsdtAddress,␊ |
425 | xsdt->Length);␊ |
426 | if (xsdt && (uint64_t)rsdp->XsdtAddress<0xffffffff && xsdt->Length<0x10000)␊ |
427 | {␊ |
428 | uint64_t *xsdt_entries;␊ |
429 | int xsdt_entries_num, i;␊ |
430 | int dropoffset=0;␊ |
431 | curssdt=0, totssdt=0, newtotssdt=0;␊ |
432 | hpet_replaced=false, hpet_added=false;␊ |
433 | sbst_replaced=false, sbst_added=false;␊ |
434 | ecdt_replaced=false, ecdt_added=false;␊ |
435 | asft_replaced=false, asft_added=false;␊ |
436 | dmar_replaced=false, dmar_added=false;␊ |
437 | apic_replaced=false, apic_added=false;␊ |
438 | mcfg_replaced=false, mcfg_added=false;␊ |
439 | ␊ |
440 | if (gen_xsdt)␊ |
441 | xsdt_mod=xsdt;␊ |
442 | else␊ |
443 | {␊ |
444 | xsdt_mod=(struct acpi_2_xsdt*)AllocateKernelMemory(xsdt->Length); ␊ |
445 | memcpy(xsdt_mod, xsdt, xsdt->Length);␊ |
446 | }␊ |
447 | ␊ |
448 | rsdp_mod->XsdtAddress=(uint32_t)xsdt_mod;␊ |
449 | xsdt_entries_num=(xsdt_mod->Length-sizeof(struct acpi_2_xsdt))/8;␊ |
450 | xsdt_entries=(uint64_t *)(xsdt_mod+1);␊ |
451 | for (i=0;i<xsdt_entries_num;i++)␊ |
452 | {␊ |
453 | char *table=(char *)((uint32_t)(xsdt_entries[i]));␊ |
454 | if (!table)␊ |
455 | continue;␊ |
456 | xsdt_entries[i-dropoffset]=xsdt_entries[i];␊ |
457 | if (drop_ssdt && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')␊ |
458 | {␊ |
459 | dropoffset++;␊ |
460 | continue;␊ |
461 | }␉␊ |
462 | if (drop_hpet && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')␊ |
463 | {␊ |
464 | dropoffset++;␊ |
465 | continue;␊ |
466 | }␊ |
467 | if (drop_slic && table[0]=='S' && table[1]=='L' && table[2]=='I' && table[3]=='C')␊ |
468 | {␊ |
469 | dropoffset++;␊ |
470 | continue;␊ |
471 | }␊ |
472 | if (drop_sbst && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')␊ |
473 | {␊ |
474 | dropoffset++;␊ |
475 | continue;␊ |
476 | }␊ |
477 | if (drop_ecdt && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')␊ |
478 | {␊ |
479 | dropoffset++;␊ |
480 | continue;␊ |
481 | }␉␉␉␉␉␊ |
482 | if (drop_asft && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')␊ |
483 | {␊ |
484 | dropoffset++;␊ |
485 | continue;␊ |
486 | }␊ |
487 | if (drop_dmar && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')␊ |
488 | {␊ |
489 | dropoffset++;␊ |
490 | continue;␊ |
491 | }␉␉␉␉␉␊ |
492 | if ((!(oem_hpet)) && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')␊ |
493 | {␊ |
494 | DBG("HPET found\n");␊ |
495 | if (new_hpet)␊ |
496 | {␊ |
497 | xsdt_entries[i-dropoffset]=(uint32_t)new_hpet;␊ |
498 | hpet_replaced=true;␊ |
499 | }␊ |
500 | continue;␊ |
501 | }␉␉␉␉␉␊ |
502 | if ((!(oem_sbst)) && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')␊ |
503 | {␊ |
504 | DBG("SBST found\n");␊ |
505 | if (new_sbst)␊ |
506 | {␊ |
507 | xsdt_entries[i-dropoffset]=(uint32_t)new_sbst;␊ |
508 | sbst_replaced=true;␊ |
509 | }␊ |
510 | continue;␊ |
511 | }␉␉␉␉␉␊ |
512 | if ((!(oem_ecdt)) && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')␊ |
513 | {␊ |
514 | DBG("ECDT found\n");␊ |
515 | if (new_ecdt)␊ |
516 | {␊ |
517 | xsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;␊ |
518 | ecdt_replaced=true;␊ |
519 | }␊ |
520 | continue;␊ |
521 | }␉␉␉␉␉␊ |
522 | if ((!(oem_asft)) && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')␊ |
523 | {␊ |
524 | DBG("ASF! found\n");␊ |
525 | if (new_asft)␊ |
526 | {␊ |
527 | xsdt_entries[i-dropoffset]=(uint32_t)new_asft;␊ |
528 | asft_replaced=true;␊ |
529 | }␊ |
530 | continue;␊ |
531 | }␉␉␉␉␉␊ |
532 | if ((!(oem_dmar)) && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')␊ |
533 | {␊ |
534 | DBG("DMAR found\n");␊ |
535 | if (new_dmar)␊ |
536 | {␊ |
537 | xsdt_entries[i-dropoffset]=(uint32_t)new_dmar;␊ |
538 | dmar_replaced=true;␊ |
539 | }␊ |
540 | continue;␊ |
541 | }␉␉␉␉␉␊ |
542 | if ((!(oem_apic)) && table[0]=='A' && table[1]=='P' && table[2]=='I' && table[3]=='C')␊ |
543 | {␊ |
544 | DBG("APIC found\n");␊ |
545 | if (new_apic)␊ |
546 | {␊ |
547 | xsdt_entries[i-dropoffset]=(uint32_t)new_apic;␊ |
548 | apic_replaced=true;␊ |
549 | }␊ |
550 | continue;␊ |
551 | }␉␉␉␉␉␊ |
552 | if ((!(oem_mcfg)) && table[0]=='M' && table[1]=='C' && table[2]=='F' && table[3]=='G')␊ |
553 | {␊ |
554 | DBG("MCFG found\n");␊ |
555 | if (new_mcfg)␊ |
556 | {␊ |
557 | xsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;␊ |
558 | mcfg_replaced=true;␊ |
559 | }␊ |
560 | continue;␊ |
561 | }␉␉␉␉␉␊ |
562 | if ((!(oem_ssdt)) && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')␊ |
563 | {␊ |
564 | DBG("SSDT %d found", curssdt);␊ |
565 | if (new_ssdts[curssdt])␊ |
566 | {␊ |
567 | DBG(" and replaced");␊ |
568 | xsdt_entries[i-dropoffset]=(uint32_t)new_ssdts[curssdt];␊ |
569 | totssdt++;␊ |
570 | }␊ |
571 | DBG("\n");␊ |
572 | curssdt++;␊ |
573 | continue;␊ |
574 | }␉␉␉␉␉␊ |
575 | if (table[0]=='D' && table[1]=='S' && table[2]=='D' && table[3]=='T')␊ |
576 | {␊ |
577 | DBG("DSDT found\n");␊ |
578 | ␊ |
579 | xsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;␊ |
580 | ␊ |
581 | DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);␊ |
582 | ␉␉␉␉␉␉␊ |
583 | continue;␊ |
584 | }␊ |
585 | if (table[0]=='F' && table[1]=='A' && table[2]=='C' && table[3]=='P')␊ |
586 | {␊ |
587 | struct acpi_2_fadt *fadt, *fadt_mod;␊ |
588 | fadt=(struct acpi_2_fadt *)(uint32_t)xsdt_entries[i];␊ |
589 | ␊ |
590 | DBG("FADT found @%x,%x, Length %d\n",(uint32_t)(xsdt_entries[i]>>32),fadt, ␊ |
591 | fadt->Length);␊ |
592 | ␊ |
593 | if (!fadt || (uint64_t)xsdt_entries[i] >= 0xffffffff || fadt->Length>0x10000)␊ |
594 | {␊ |
595 | verbose("FADT incorrect or after 4GB. Dropping XSDT\n");␊ |
596 | goto drop_xsdt;␊ |
597 | }␊ |
598 | ␊ |
599 | fadt_mod = patch_fadt(fadt, new_dsdt,update_acpi);␊ |
600 | xsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;␊ |
601 | ␊ |
602 | DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);␊ |
603 | ␊ |
604 | continue;␊ |
605 | }␊ |
606 | ␊ |
607 | DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);␊ |
608 | ␊ |
609 | }␊ |
610 | ␊ |
611 | if ((!oem_hpet) && (!hpet_replaced))␊ |
612 | {␊ |
613 | if (new_hpet)␊ |
614 | {␊ |
615 | xsdt_entries[i-dropoffset]=(uint32_t)new_hpet;␊ |
616 | hpet_added=true;␊ |
617 | i++;␊ |
618 | }␊ |
619 | }␊ |
620 | ␊ |
621 | if ((!oem_sbst) && (!sbst_replaced))␊ |
622 | {␊ |
623 | if (new_sbst)␊ |
624 | {␊ |
625 | xsdt_entries[i-dropoffset]=(uint32_t)new_sbst;␊ |
626 | sbst_added=true;␊ |
627 | i++;␊ |
628 | }␊ |
629 | }␊ |
630 | ␊ |
631 | if ((!oem_ecdt) && (!ecdt_replaced))␊ |
632 | {␊ |
633 | if (new_ecdt)␊ |
634 | {␊ |
635 | xsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;␊ |
636 | ecdt_added=true;␊ |
637 | i++;␊ |
638 | }␊ |
639 | }␊ |
640 | ␊ |
641 | if ((!oem_asft) && (!asft_replaced))␊ |
642 | {␊ |
643 | if (new_asft)␊ |
644 | {␊ |
645 | xsdt_entries[i-dropoffset]=(uint32_t)new_asft;␊ |
646 | asft_added=true;␊ |
647 | i++;␊ |
648 | }␊ |
649 | }␊ |
650 | ␊ |
651 | if ((!oem_dmar) && (!dmar_replaced))␊ |
652 | {␊ |
653 | if (new_dmar)␊ |
654 | {␊ |
655 | xsdt_entries[i-dropoffset]=(uint32_t)new_dmar;␊ |
656 | dmar_added=true;␊ |
657 | i++;␊ |
658 | }␊ |
659 | }␊ |
660 | ␊ |
661 | if ((!oem_apic) && (!apic_replaced))␊ |
662 | {␊ |
663 | if (new_apic)␊ |
664 | {␊ |
665 | xsdt_entries[i-dropoffset]=(uint32_t)new_apic;␊ |
666 | apic_added=true;␊ |
667 | i++;␊ |
668 | }␊ |
669 | }␊ |
670 | ␊ |
671 | if ((!oem_mcfg) && (!mcfg_replaced))␊ |
672 | {␊ |
673 | if (new_mcfg)␊ |
674 | {␊ |
675 | xsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;␊ |
676 | mcfg_added=true;␊ |
677 | i++;␊ |
678 | }␊ |
679 | }␊ |
680 | ␊ |
681 | if (!oem_ssdt)␊ |
682 | { ␉␉␉␊ |
683 | while ((totssdt < loadtotssdt) && (curssdt < 30))␊ |
684 | {␊ |
685 | if (new_ssdts[curssdt])␊ |
686 | {␊ |
687 | DBG("adding SSDT %d\n", curssdt);␊ |
688 | xsdt_entries[i-dropoffset]=(uint32_t)new_ssdts[curssdt];␊ |
689 | totssdt++;␊ |
690 | newtotssdt++;␊ |
691 | i++;␊ |
692 | }␊ |
693 | curssdt++;␊ |
694 | }␊ |
695 | }␊ |
696 | ␊ |
697 | // Correct the checksum of XSDT␊ |
698 | xsdt_mod->Length-=8*dropoffset;␊ |
699 | xsdt_mod->Length+=8*newtotssdt;␊ |
700 | if (hpet_added)␊ |
701 | xsdt_mod->Length+=8;␊ |
702 | if (sbst_added)␊ |
703 | xsdt_mod->Length+=8;␊ |
704 | if (ecdt_added)␊ |
705 | xsdt_mod->Length+=8;␊ |
706 | if (asft_added)␊ |
707 | xsdt_mod->Length+=8;␊ |
708 | if (dmar_added)␊ |
709 | xsdt_mod->Length+=8;␊ |
710 | if (apic_added)␊ |
711 | xsdt_mod->Length+=8;␊ |
712 | if (mcfg_added)␊ |
713 | xsdt_mod->Length+=8;␊ |
714 | ␊ |
715 | xsdt_mod->Checksum=0;␊ |
716 | xsdt_mod->Checksum=256-checksum8(xsdt_mod,xsdt_mod->Length);␊ |
717 | }␊ |
718 | else␊ |
719 | {␊ |
720 | drop_xsdt:␊ |
721 | ␊ |
722 | DBG("About to drop XSDT\n");␊ |
723 | ␊ |
724 | /*FIXME: Now we just hope that if MacOS doesn't find XSDT it reverts to RSDT. ␊ |
725 | * A Better strategy would be to generate␊ |
726 | */␊ |
727 | ␊ |
728 | rsdp_mod->XsdtAddress=0xffffffffffffffffLL;␊ |
729 | verbose("XSDT not found or XSDT incorrect\n");␊ |
730 | }␊ |
731 | }␊ |
732 | ␊ |
733 | // Correct the checksum of RSDP ␊ |
734 | ␊ |
735 | DBG("RSDP: Original checksum %d, ", rsdp_mod->Checksum);␊ |
736 | ␊ |
737 | rsdp_mod->Checksum=0;␊ |
738 | rsdp_mod->Checksum=256-checksum8(rsdp_mod,20);␊ |
739 | ␊ |
740 | DBG("New checksum %d\n", rsdp_mod->Checksum);␊ |
741 | ␊ |
742 | if (version)␊ |
743 | {␊ |
744 | DBG("RSDP: Original extended checksum %d", rsdp_mod->ExtendedChecksum);␊ |
745 | ␊ |
746 | rsdp_mod->ExtendedChecksum=0;␊ |
747 | rsdp_mod->ExtendedChecksum=256-checksum8(rsdp_mod,rsdp_mod->Length);␊ |
748 | ␊ |
749 | DBG("New extended checksum %d\n", rsdp_mod->ExtendedChecksum);␊ |
750 | ␊ |
751 | }␊ |
752 | ␉␉␊ |
753 | verbose("Patched ACPI version %d DSDT\n", version+1);␊ |
754 | if (version)␊ |
755 | {␊ |
756 | /* XXX aserebln why uint32 cast if pointer is uint64 ? */␊ |
757 | acpi20_p = (uint32_t)rsdp_mod;␊ |
758 | addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");␊ |
759 | }␊ |
760 | else␊ |
761 | {␊ |
762 | /* XXX aserebln why uint32 cast if pointer is uint64 ? */␊ |
763 | acpi10_p = (uint32_t)rsdp_mod;␊ |
764 | addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");␊ |
765 | }␊ |
766 | }␊ |
767 | #if DEBUG_DSDT␊ |
768 | printf("Press a key to continue... (DEBUG_DSDT)\n");␊ |
769 | getc();␊ |
770 | #endif␊ |
771 | return 1;␊ |
772 | }␊ |
773 |