Root/
Source at commit 429 created 13 years 9 months ago. By meklort, Updated module system. Hooks can now be used within modules when cetaion functions are called in chameleon. Note that onle two hooks currently exist, more need to be added. I also updated the HelloWorld module to use a hook instead of print out right away. | |
---|---|
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 */␊ |
27 | static 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 */␊ |
49 | static 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 | /** The folowing ACPI Table search algo. should be reused anywhere needed:*/␊ |
76 | int search_and_get_acpi_fd(const char * filename, const char ** outDirspec)␊ |
77 | {␊ |
78 | int fd=0;␊ |
79 | const char * overriden_pathname=NULL;␊ |
80 | static char dirspec[512]="";␊ |
81 | static bool first_time =true; ␊ |
82 | int len=0;␊ |
83 | ␊ |
84 | /// Take in accound user overriding if it's DSDT only␊ |
85 | if (strstr(filename, "DSDT") && ␊ |
86 | getValueForKey(kDSDT, &overriden_pathname, &len, ␊ |
87 | ␉␉␉ &bootInfo->bootConfig))␊ |
88 | {␊ |
89 | sprintf(dirspec, "%s", overriden_pathname);␊ |
90 | fd=open (dirspec,0);␊ |
91 | if (fd>=0) goto success_fd;␊ |
92 | }␊ |
93 | // Check that dirspec is not already assigned with a path␊ |
94 | if (!first_time && *dirspec) ␊ |
95 | { // it is so start searching this cached patch first␊ |
96 | //extract path␊ |
97 | for (len=strlen(dirspec)-1; len; len--)␊ |
98 | if (dirspec[len]=='/' || len==0)␊ |
99 | {␊ |
100 | dirspec[len]='\0';␊ |
101 | break;␊ |
102 | }␊ |
103 | // now concat with the filename␊ |
104 | strncat(dirspec, "/", sizeof(dirspec));␊ |
105 | strncat(dirspec, filename, sizeof(dirspec));␊ |
106 | // and test to see if we don't have our big boy here:␊ |
107 | fd=open (dirspec,0);␊ |
108 | if (fd>=0) ␊ |
109 | {␊ |
110 | // printf("ACPI file search cache hit: file found at %s\n", dirspec);␊ |
111 | goto success_fd;␊ |
112 | }␊ |
113 | }␊ |
114 | // Start searching any potential location for ACPI Table␊ |
115 | // search the Extra folders first␊ |
116 | sprintf(dirspec,"/Extra/%s",filename); ␊ |
117 | fd=open (dirspec,0);␊ |
118 | if (fd>=0) goto success_fd;␊ |
119 | ␊ |
120 | sprintf(dirspec,"bt(0,0)/Extra/%s",filename);␊ |
121 | fd=open (dirspec,0);␊ |
122 | if (fd>=0) goto success_fd;␊ |
123 | ␊ |
124 | sprintf(dirspec, "%s", filename); // search current dir␊ |
125 | fd=open (dirspec,0);␊ |
126 | if (fd>=0) goto success_fd;␊ |
127 | ␊ |
128 | sprintf(dirspec, "/%s", filename); // search root␊ |
129 | fd=open (dirspec,0);␊ |
130 | if (fd>=0) goto success_fd;␊ |
131 | ␊ |
132 | // NOT FOUND:␊ |
133 | verbose("ACPI Table not found: %s\n", filename);␊ |
134 | if (outDirspec) *outDirspec = "";␊ |
135 | first_time = false;␊ |
136 | return -1;␊ |
137 | // FOUND␊ |
138 | success_fd:␊ |
139 | first_time = false;␊ |
140 | if (outDirspec) *outDirspec = dirspec; ␊ |
141 | return fd;␊ |
142 | }␊ |
143 | ␊ |
144 | void *loadACPITable (const char * filename)␊ |
145 | {␊ |
146 | ␉void *tableAddr;␊ |
147 | ␉const char * dirspec=NULL;␊ |
148 | ␉␊ |
149 | ␉int fd = search_and_get_acpi_fd(filename, &dirspec);␊ |
150 | ␊ |
151 | ␉if (fd>=0)␊ |
152 | ␉{␊ |
153 | ␉ tableAddr=(void*)AllocateKernelMemory(file_size (fd));␊ |
154 | ␉ if (tableAddr)␊ |
155 | ␉ {␊ |
156 | ␉ if (read (fd, tableAddr, file_size (fd))!=file_size (fd))␊ |
157 | ␉ {␊ |
158 | ␉␉ printf("Couldn't read table %s\n",dirspec);␊ |
159 | ␉␉ free (tableAddr);␊ |
160 | ␉␉ close (fd);␊ |
161 | ␉␉ return NULL;␊ |
162 | ␉ }␊ |
163 | ␉ ␊ |
164 | ␉ DBG("Table %s read and stored at: %x\n", dirspec, tableAddr);␊ |
165 | ␉ close (fd);␊ |
166 | ␉ return tableAddr;␊ |
167 | ␉ }␊ |
168 | ␉ close (fd);␊ |
169 | printf("Couldn't allocate memory for table \n", dirspec);␊ |
170 | ␉} ␊ |
171 | ␉printf("Couldn't find table %s\n", filename);␊ |
172 | ␉return NULL;␊ |
173 | }␊ |
174 | ␊ |
175 | ␊ |
176 | struct acpi_2_fadt *␊ |
177 | patch_fadt(struct acpi_2_fadt *fadt, void *new_dsdt)␊ |
178 | {␊ |
179 | ␊ |
180 | extern void setupSystemType(); ␊ |
181 | ␉␊ |
182 | ␉struct acpi_2_fadt *fadt_mod;␊ |
183 | ␉bool fadt_rev2_needed = false;␊ |
184 | ␉bool fix_restart;␊ |
185 | ␉const char * value;␊ |
186 | ␉␊ |
187 | ␉// Restart Fix␊ |
188 | ␉if (Platform.CPU.Vendor == 0x756E6547) {␉/* Intel */␊ |
189 | ␉␉fix_restart = true;␊ |
190 | ␉␉getBoolForKey(kRestartFix, &fix_restart, &bootInfo->bootConfig);␊ |
191 | ␉} else {␊ |
192 | ␉␉verbose ("Not an Intel platform: Restart Fix not applied !!!\n");␊ |
193 | ␉␉fix_restart = false;␊ |
194 | ␉}␊ |
195 | ␊ |
196 | ␉if (fix_restart) fadt_rev2_needed = true;␊ |
197 | ␊ |
198 | ␉// Allocate new fadt table␊ |
199 | ␉if (fadt->Length < 0x84 && fadt_rev2_needed)␊ |
200 | ␉{␊ |
201 | ␉␉fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(0x84);␊ |
202 | ␉␉memcpy(fadt_mod, fadt, fadt->Length);␊ |
203 | ␉␉fadt_mod->Length = 0x84;␊ |
204 | ␉␉fadt_mod->Revision = 0x02; // FADT rev 2 (ACPI 1.0B MS extensions)␊ |
205 | ␉}␊ |
206 | ␉else␊ |
207 | ␉{␊ |
208 | ␉␉fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(fadt->Length);␊ |
209 | ␉␉memcpy(fadt_mod, fadt, fadt->Length);␊ |
210 | ␉}␊ |
211 | ␉// Determine system type / PM_Model␊ |
212 | ␉if ( (value=getStringForKey(kSystemType, &bootInfo->bootConfig))!=NULL)␊ |
213 | ␉{␊ |
214 | ␉ if (Platform.Type > 6) ␊ |
215 | ␉ {␊ |
216 | ␉ if(fadt_mod->PM_Profile<=6)␊ |
217 | ␉ Platform.Type = fadt_mod->PM_Profile; // get the fadt if correct␊ |
218 | ␉ else ␊ |
219 | ␉ Platform.Type = 1;␉␉/* Set a fixed value (Desktop) */␊ |
220 | ␉ verbose("Error: system-type must be 0..6. Defaulting to %d !\n", Platform.Type);␊ |
221 | ␉ }␊ |
222 | ␉ else␊ |
223 | ␉ Platform.Type = (unsigned char) strtoul(value, NULL, 10);␊ |
224 | ␉}␊ |
225 | ␉// Set PM_Profile from System-type if only if user wanted this value to be forced␊ |
226 | ␉if (fadt_mod->PM_Profile != Platform.Type) ␊ |
227 | ␉{␊ |
228 | ␉ if (value) ␊ |
229 | ␉ { // user has overriden the SystemType so take care of it in FACP␊ |
230 | ␉␉verbose("FADT: changing PM_Profile from 0x%02x to 0x%02x\n", fadt_mod->PM_Profile, Platform.Type);␊ |
231 | ␉␉fadt_mod->PM_Profile = Platform.Type;␊ |
232 | ␉ }␊ |
233 | ␉ else␊ |
234 | ␉ { // PM_Profile has a different value and no override has been set, so reflect the user value to ioregs␊ |
235 | ␉ Platform.Type = fadt_mod->PM_Profile <= 6 ? fadt_mod->PM_Profile : 1;␊ |
236 | ␉ } ␊ |
237 | ␉}␊ |
238 | ␉// We now have to write the systemm-type in ioregs: we cannot do it before in setupDeviceTree()␊ |
239 | ␉// because we need to take care of facp original content, if it is correct.␊ |
240 | ␉setupSystemType();␊ |
241 | ␊ |
242 | ␉// Patch FADT to fix restart␊ |
243 | ␉if (fix_restart)␊ |
244 | ␉{␊ |
245 | ␉␉fadt_mod->Flags|= 0x400;␊ |
246 | ␉␉fadt_mod->Reset_SpaceID␉␉= 0x01; // System I/O␊ |
247 | ␉␉fadt_mod->Reset_BitWidth␉= 0x08; // 1 byte␊ |
248 | ␉␉fadt_mod->Reset_BitOffset␉= 0x00; // Offset 0␊ |
249 | ␉␉fadt_mod->Reset_AccessWidth␉= 0x01; // Byte access␊ |
250 | ␉␉fadt_mod->Reset_Address␉␉= 0x0cf9; // Address of the register␊ |
251 | ␉␉fadt_mod->Reset_Value␉␉= 0x06; // Value to write to reset the system␊ |
252 | ␉␉verbose("FADT: Restart Fix applied !\n");␊ |
253 | ␉}␊ |
254 | ␊ |
255 | ␉// Save old DSDT to the IORegistery␊ |
256 | ␉Node* node = DT__FindNode("/", false);␊ |
257 | ␉if(node != NULL)␊ |
258 | ␉{␊ |
259 | ␉␉node = DT__AddChild(node, "dsdt");␊ |
260 | ␉␉␉␉␊ |
261 | ␉␉struct acpi_2_dsdt *dsdt;␊ |
262 | ␉␉dsdt = (struct acpi_2_dsdt*) (fadt_mod->DSDT);␊ |
263 | ␉␉DT__AddProperty(node, "originaldsdt", (dsdt->Length + sizeof(struct acpi_2_dsdt) - 1), (void*)dsdt);␉/// Insert old dsdt. Length is header length (36) + dsdt length␊ |
264 | ␉␉␊ |
265 | ␉}␊ |
266 | ␉␊ |
267 | ␉␊ |
268 | ␉// Patch DSDT Address␊ |
269 | ␉DBG("DSDT: Old @%x,%x, ",fadt_mod->DSDT,fadt_mod->X_DSDT);␊ |
270 | ␊ |
271 | ␉␊ |
272 | ␉fadt_mod->DSDT=(uint32_t)new_dsdt;␊ |
273 | ␉if ((uint32_t)(&(fadt_mod->X_DSDT))-(uint32_t)fadt_mod+8<=fadt_mod->Length)␊ |
274 | ␉␉fadt_mod->X_DSDT=(uint32_t)new_dsdt;␊ |
275 | ␊ |
276 | ␉DBG("New @%x,%x\n",fadt_mod->DSDT,fadt_mod->X_DSDT);␊ |
277 | ␊ |
278 | ␉// Correct the checksum␊ |
279 | ␉fadt_mod->Checksum=0;␊ |
280 | ␉fadt_mod->Checksum=256-checksum8(fadt_mod,fadt_mod->Length);␊ |
281 | ␊ |
282 | ␉return fadt_mod;␊ |
283 | }␊ |
284 | ␊ |
285 | /* Setup ACPI without replacing DSDT. */␊ |
286 | int setupAcpiNoMod()␊ |
287 | {␊ |
288 | //␉addConfigurationTable(&gEfiAcpiTableGuid, getAddressOfAcpiTable(), "ACPI");␊ |
289 | //␉addConfigurationTable(&gEfiAcpi20TableGuid, getAddressOfAcpi20Table(), "ACPI_20");␊ |
290 | ␉/* XXX aserebln why uint32 cast if pointer is uint64 ? */␊ |
291 | ␉acpi10_p = (uint32_t)getAddressOfAcpiTable();␊ |
292 | ␉acpi20_p = (uint32_t)getAddressOfAcpi20Table();␊ |
293 | ␉addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");␊ |
294 | ␉if(acpi20_p) addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");␊ |
295 | ␉return 1;␊ |
296 | }␊ |
297 | ␊ |
298 | /* Setup ACPI. Replace DSDT if DSDT.aml is found */␊ |
299 | int setupAcpi(void)␊ |
300 | {␊ |
301 | ␉int version;␊ |
302 | ␉void *new_dsdt;␊ |
303 | ␊ |
304 | ␉bool drop_ssdt;␊ |
305 | ␉␊ |
306 | ␉// Load replacement DSDT␊ |
307 | ␉new_dsdt=loadACPITable("DSDT.aml");␊ |
308 | ␉if (!new_dsdt)␊ |
309 | ␉{␊ |
310 | ␉␉return setupAcpiNoMod();␊ |
311 | ␉}␊ |
312 | ␊ |
313 | ␉DBG("New DSDT Loaded in memory\n");␊ |
314 | ␉␊ |
315 | ␉{␊ |
316 | ␉␉bool tmp;␊ |
317 | ␉␉drop_ssdt=getBoolForKey(kDropSSDT, &tmp, &bootInfo->bootConfig)&&tmp;␊ |
318 | ␉}␊ |
319 | ␊ |
320 | ␉// Do the same procedure for both versions of ACPI␊ |
321 | ␉for (version=0; version<2; version++) {␊ |
322 | ␉␉struct acpi_2_rsdp *rsdp, *rsdp_mod;␊ |
323 | ␉␉struct acpi_2_rsdt *rsdt, *rsdt_mod;␊ |
324 | ␉␉int rsdplength;␊ |
325 | ␉␉␊ |
326 | ␉␉// Find original rsdp␊ |
327 | ␉␉rsdp=(struct acpi_2_rsdp *)(version?getAddressOfAcpi20Table():getAddressOfAcpiTable());␊ |
328 | ␉␉if (!rsdp)␊ |
329 | ␉␉{␊ |
330 | ␉␉␉DBG("No ACPI version %d found. Ignoring\n", version+1);␊ |
331 | ␉␉␉if (version)␊ |
332 | ␉␉␉␉addConfigurationTable(&gEfiAcpi20TableGuid, NULL, "ACPI_20");␊ |
333 | ␉␉␉else␊ |
334 | ␉␉␉␉addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI");␊ |
335 | ␉␉␉continue;␊ |
336 | ␉␉}␊ |
337 | ␉␉rsdplength=version?rsdp->Length:20;␊ |
338 | ␊ |
339 | ␉␉DBG("RSDP version %d found @%x. Length=%d\n",version+1,rsdp,rsdplength);␊ |
340 | ␊ |
341 | ␉␉/* FIXME: no check that memory allocation succeeded ␊ |
342 | ␉␉ * Copy and patch RSDP,RSDT, XSDT and FADT␊ |
343 | ␉␉ * For more info see ACPI Specification pages 110 and following␊ |
344 | ␉␉ */␊ |
345 | ␊ |
346 | ␉␉rsdp_mod=(struct acpi_2_rsdp *) AllocateKernelMemory(rsdplength);␊ |
347 | ␉␉memcpy(rsdp_mod, rsdp, rsdplength); ␊ |
348 | ␉␉rsdt=(struct acpi_2_rsdt *)(rsdp->RsdtAddress);␊ |
349 | ␊ |
350 | ␉␉DBG("RSDT @%x, Length %d\n",rsdt, rsdt->Length);␊ |
351 | ␉␉␊ |
352 | ␉␉if (rsdt && (uint32_t)rsdt !=0xffffffff && rsdt->Length<0x10000)␊ |
353 | ␉␉{␊ |
354 | ␉␉␉uint32_t *rsdt_entries;␊ |
355 | ␉␉␉int rsdt_entries_num;␊ |
356 | ␉␉␉int dropoffset=0, i;␊ |
357 | ␉␉␉␊ |
358 | ␉␉␉rsdt_mod=(struct acpi_2_rsdt *)AllocateKernelMemory(rsdt->Length); ␊ |
359 | ␉␉␉memcpy (rsdt_mod, rsdt, rsdt->Length);␊ |
360 | ␉␉␉rsdp_mod->RsdtAddress=(uint32_t)rsdt_mod;␊ |
361 | ␉␉␉rsdt_entries_num=(rsdt_mod->Length-sizeof(struct acpi_2_rsdt))/4;␊ |
362 | ␉␉␉rsdt_entries=(uint32_t *)(rsdt_mod+1);␊ |
363 | ␉␉␉for (i=0;i<rsdt_entries_num;i++)␊ |
364 | ␉␉␉{␊ |
365 | ␉␉␉␉char *table=(char *)(rsdt_entries[i]);␊ |
366 | ␉␉␉␉if (!table)␊ |
367 | ␉␉␉␉␉continue;␊ |
368 | ␊ |
369 | ␉␉␉␉DBG("TABLE %c%c%c%c,",table[0],table[1],table[2],table[3]);␊ |
370 | ␊ |
371 | ␉␉␉␉rsdt_entries[i-dropoffset]=rsdt_entries[i];␊ |
372 | ␉␉␉␉if (drop_ssdt && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')␊ |
373 | ␉␉␉␉{␊ |
374 | ␉␉␉␉␉dropoffset++;␊ |
375 | ␉␉␉␉␉continue;␊ |
376 | ␉␉␉␉}␊ |
377 | ␉␉␉␉if (table[0]=='D' && table[1]=='S' && table[2]=='D' && table[3]=='T')␊ |
378 | ␉␉␉␉{␊ |
379 | ␉␉␉␉␉DBG("DSDT found\n");␊ |
380 | ␉␉␉␉␉rsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;␊ |
381 | ␉␉␉␉␉continue;␊ |
382 | ␉␉␉␉}␊ |
383 | ␉␉␉␉if (table[0]=='F' && table[1]=='A' && table[2]=='C' && table[3]=='P')␊ |
384 | ␉␉␉␉{␊ |
385 | ␉␉␉␉␉struct acpi_2_fadt *fadt, *fadt_mod;␊ |
386 | ␉␉␉␉␉fadt=(struct acpi_2_fadt *)rsdt_entries[i];␊ |
387 | ␊ |
388 | ␉␉␉␉␉DBG("FADT found @%x, Length %d\n",fadt, fadt->Length);␊ |
389 | ␊ |
390 | ␉␉␉␉␉if (!fadt || (uint32_t)fadt == 0xffffffff || fadt->Length>0x10000)␊ |
391 | ␉␉␉␉␉{␊ |
392 | ␉␉␉␉␉␉printf("FADT incorrect. Not modified\n");␊ |
393 | ␉␉␉␉␉␉continue;␊ |
394 | ␉␉␉␉␉}␊ |
395 | ␉␉␉␉␉␊ |
396 | ␉␉␉␉␉fadt_mod = patch_fadt(fadt, new_dsdt);␊ |
397 | ␉␉␉␉␉rsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;␊ |
398 | ␉␉␉␉␉continue;␊ |
399 | ␉␉␉␉}␊ |
400 | ␉␉␉}␊ |
401 | ␉␉␉DBG("\n");␊ |
402 | ␊ |
403 | ␉␉␉// Correct the checksum of RSDT␊ |
404 | ␉␉␉rsdt_mod->Length-=4*dropoffset;␊ |
405 | ␊ |
406 | ␉␉␉DBG("RSDT: Original checksum %d, ", rsdt_mod->Checksum);␊ |
407 | ␊ |
408 | ␉␉␉rsdt_mod->Checksum=0;␊ |
409 | ␉␉␉rsdt_mod->Checksum=256-checksum8(rsdt_mod,rsdt_mod->Length);␊ |
410 | ␊ |
411 | ␉␉␉DBG("New checksum %d at %x\n", rsdt_mod->Checksum,rsdt_mod);␊ |
412 | ␉␉}␊ |
413 | ␉␉else␊ |
414 | ␉␉{␊ |
415 | ␉␉␉rsdp_mod->RsdtAddress=0;␊ |
416 | ␉␉␉printf("RSDT not found or RSDT incorrect\n");␊ |
417 | ␉␉}␊ |
418 | ␊ |
419 | ␉␉if (version)␊ |
420 | ␉␉{␊ |
421 | ␉␉␉struct acpi_2_xsdt *xsdt, *xsdt_mod;␊ |
422 | ␊ |
423 | ␉␉␉// FIXME: handle 64-bit address correctly␊ |
424 | ␊ |
425 | ␉␉␉xsdt=(struct acpi_2_xsdt*) ((uint32_t)rsdp->XsdtAddress);␊ |
426 | ␉␉␉DBG("XSDT @%x;%x, Length=%d\n", (uint32_t)(rsdp->XsdtAddress>>32),(uint32_t)rsdp->XsdtAddress,␊ |
427 | ␉␉␉␉␉xsdt->Length);␊ |
428 | ␉␉␉if (xsdt && (uint64_t)rsdp->XsdtAddress<0xffffffff && xsdt->Length<0x10000)␊ |
429 | ␉␉␉{␊ |
430 | ␉␉␉␉uint64_t *xsdt_entries;␊ |
431 | ␉␉␉␉int xsdt_entries_num, i;␊ |
432 | ␉␉␉␉int dropoffset=0;␊ |
433 | ␉␉␉␉␊ |
434 | ␉␉␉␉xsdt_mod=(struct acpi_2_xsdt*)AllocateKernelMemory(xsdt->Length); ␊ |
435 | ␉␉␉␉memcpy(xsdt_mod, xsdt, xsdt->Length);␊ |
436 | ␉␉␉␉rsdp_mod->XsdtAddress=(uint32_t)xsdt_mod;␊ |
437 | ␉␉␉␉xsdt_entries_num=(xsdt_mod->Length-sizeof(struct acpi_2_xsdt))/8;␊ |
438 | ␉␉␉␉xsdt_entries=(uint64_t *)(xsdt_mod+1);␊ |
439 | ␉␉␉␉for (i=0;i<xsdt_entries_num;i++)␊ |
440 | ␉␉␉␉{␊ |
441 | ␉␉␉␉␉char *table=(char *)((uint32_t)(xsdt_entries[i]));␊ |
442 | ␉␉␉␉␉if (!table)␊ |
443 | ␉␉␉␉␉␉continue;␊ |
444 | ␉␉␉␉␉xsdt_entries[i-dropoffset]=xsdt_entries[i];␊ |
445 | ␉␉␉␉␉if (drop_ssdt && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')␊ |
446 | ␉␉␉␉␉{␊ |
447 | ␉␉␉␉␉␉dropoffset++;␊ |
448 | ␉␉␉␉␉␉continue;␊ |
449 | ␉␉␉␉␉}␉␉␉␉␉␊ |
450 | ␉␉␉␉␉if (table[0]=='D' && table[1]=='S' && table[2]=='D' && table[3]=='T')␊ |
451 | ␉␉␉␉␉{␊ |
452 | ␉␉␉␉␉␉DBG("DSDT found\n");␊ |
453 | ␊ |
454 | ␉␉␉␉␉␉xsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;␊ |
455 | ␊ |
456 | ␉␉␉␉␉␉DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);␊ |
457 | ␉␉␉␉␉␉␊ |
458 | ␉␉␉␉␉␉continue;␊ |
459 | ␉␉␉␉␉}␊ |
460 | ␉␉␉␉␉if (table[0]=='F' && table[1]=='A' && table[2]=='C' && table[3]=='P')␊ |
461 | ␉␉␉␉␉{␊ |
462 | ␉␉␉␉␉␉struct acpi_2_fadt *fadt, *fadt_mod;␊ |
463 | ␉␉␉␉␉␉fadt=(struct acpi_2_fadt *)(uint32_t)xsdt_entries[i];␊ |
464 | ␊ |
465 | ␉␉␉␉␉␉DBG("FADT found @%x,%x, Length %d\n",(uint32_t)(xsdt_entries[i]>>32),fadt, ␊ |
466 | ␉␉␉␉␉␉␉␉ fadt->Length);␊ |
467 | ␊ |
468 | ␉␉␉␉␉␉if (!fadt || (uint64_t)xsdt_entries[i] >= 0xffffffff || fadt->Length>0x10000)␊ |
469 | ␉␉␉␉␉␉{␊ |
470 | ␉␉␉␉␉␉␉verbose("FADT incorrect or after 4GB. Dropping XSDT\n");␊ |
471 | ␉␉␉␉␉␉␉goto drop_xsdt;␊ |
472 | ␉␉␉␉␉␉}␊ |
473 | ␊ |
474 | ␉␉␉␉␉␉fadt_mod = patch_fadt(fadt, new_dsdt);␊ |
475 | ␉␉␉␉␉␉xsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;␊ |
476 | ␊ |
477 | ␉␉␉␉␉␉DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);␊ |
478 | ␊ |
479 | ␉␉␉␉␉␉continue;␊ |
480 | ␉␉␉␉␉}␊ |
481 | ␊ |
482 | ␉␉␉␉␉DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);␊ |
483 | ␊ |
484 | ␉␉␉␉}␊ |
485 | ␊ |
486 | ␉␉␉␉// Correct the checksum of XSDT␊ |
487 | ␉␉␉␉xsdt_mod->Length-=8*dropoffset;␊ |
488 | ␉␉␉␉xsdt_mod->Checksum=0;␊ |
489 | ␉␉␉␉xsdt_mod->Checksum=256-checksum8(xsdt_mod,xsdt_mod->Length);␊ |
490 | ␉␉␉}␊ |
491 | ␉␉␉else␊ |
492 | ␉␉␉{␊ |
493 | ␉␉␉drop_xsdt:␊ |
494 | ␊ |
495 | ␉␉␉␉DBG("About to drop XSDT\n");␊ |
496 | ␊ |
497 | ␉␉␉␉/*FIXME: Now we just hope that if MacOS doesn't find XSDT it reverts to RSDT. ␊ |
498 | ␉␉␉␉ * A Better strategy would be to generate␊ |
499 | ␉␉␉␉ */␊ |
500 | ␊ |
501 | ␉␉␉␉rsdp_mod->XsdtAddress=0xffffffffffffffffLL;␊ |
502 | ␉␉␉␉verbose("XSDT not found or XSDT incorrect\n");␊ |
503 | ␉␉␉}␊ |
504 | ␉␉}␊ |
505 | ␊ |
506 | ␉␉// Correct the checksum of RSDP ␊ |
507 | ␊ |
508 | ␉␉DBG("RSDP: Original checksum %d, ", rsdp_mod->Checksum);␊ |
509 | ␊ |
510 | ␉␉rsdp_mod->Checksum=0;␊ |
511 | ␉␉rsdp_mod->Checksum=256-checksum8(rsdp_mod,20);␊ |
512 | ␊ |
513 | ␉␉DBG("New checksum %d\n", rsdp_mod->Checksum);␊ |
514 | ␊ |
515 | ␉␉if (version)␊ |
516 | ␉␉{␊ |
517 | ␉␉␉DBG("RSDP: Original extended checksum %d", rsdp_mod->ExtendedChecksum);␊ |
518 | ␊ |
519 | ␉␉␉rsdp_mod->ExtendedChecksum=0;␊ |
520 | ␉␉␉rsdp_mod->ExtendedChecksum=256-checksum8(rsdp_mod,rsdp_mod->Length);␊ |
521 | ␊ |
522 | ␉␉␉DBG("New extended checksum %d\n", rsdp_mod->ExtendedChecksum);␊ |
523 | ␊ |
524 | ␉␉}␊ |
525 | ␉␉␊ |
526 | ␉␉verbose("Patched ACPI version %d DSDT\n", version+1);␊ |
527 | ␉␉if (version)␊ |
528 | ␉␉{␊ |
529 | ␉/* XXX aserebln why uint32 cast if pointer is uint64 ? */␊ |
530 | ␉␉␉acpi20_p = (uint32_t)rsdp_mod;␊ |
531 | ␉␉␉addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");␊ |
532 | ␉␉}␊ |
533 | ␉␉else␊ |
534 | ␉␉{␊ |
535 | ␉/* XXX aserebln why uint32 cast if pointer is uint64 ? */␊ |
536 | ␉␉␉acpi10_p = (uint32_t)rsdp_mod;␊ |
537 | ␉␉␉addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");␊ |
538 | ␉␉}␊ |
539 | ␉}␊ |
540 | #if DEBUG_DSDT␊ |
541 | ␉printf("Press a key to continue... (DEBUG_DSDT)\n");␊ |
542 | ␉getc();␊ |
543 | #endif␊ |
544 | ␉return 1;␊ |
545 | }␊ |
546 |