1 | /*␊ |
2 | * Copyright 2008 mackerintel␊ |
3 | * 2010 mojodojo, 2012 slice␊ |
4 | */␊ |
5 | ␊ |
6 | #include "libsaio.h"␊ |
7 | #include "boot.h"␊ |
8 | #include "bootstruct.h"␊ |
9 | #include "acpi.h"␊ |
10 | #include "efi_tables.h"␊ |
11 | #include "fake_efi.h"␊ |
12 | #include "acpi_patcher.h"␊ |
13 | #include "platform.h"␊ |
14 | #include "cpu.h"␊ |
15 | #include "aml_generator.h"␊ |
16 | #include "state_generator.h"␊ |
17 | ␊ |
18 | #ifndef DEBUG_ACPI␊ |
19 | #define DEBUG_ACPI 0␊ |
20 | #endif␊ |
21 | ␊ |
22 | #if DEBUG_ACPI==2␊ |
23 | #define DBG(x...) {printf(x); sleep(1);}␊ |
24 | #elif DEBUG_ACPI==1␊ |
25 | #define DBG(x...) printf(x)␊ |
26 | #else␊ |
27 | #define DBG(x...) msglog(x)␊ |
28 | #endif␊ |
29 | ␊ |
30 | // Bungo:␊ |
31 | void *new_dsdt = NULL,␊ |
32 | *new_ecdt = NULL;␊ |
33 | ␊ |
34 | // Slice: New signature compare function␊ |
35 | boolean_t tableSign(void *table, const char *sgn)␊ |
36 | {␊ |
37 | ␉int i;␊ |
38 | ␉for (i = 0; i < 4; i++)␊ |
39 | ␉{␊ |
40 | ␉␉if ((((char *)table)[i] & ~0x20) != (sgn[i] & ~0x20))␊ |
41 | ␉␉{␊ |
42 | ␉␉␉return false;␊ |
43 | ␉␉}␊ |
44 | ␉}␊ |
45 | ␉return true;␊ |
46 | }␊ |
47 | ␊ |
48 | uint32_t EBDA_RANGE_START = EBDA_RANGE_MIN;␊ |
49 | ␊ |
50 | uint64_t acpi10_p = 0;␊ |
51 | uint64_t acpi20_p = 0;␊ |
52 | ␊ |
53 | /* Gets the ACPI 1.0 RSDP address */␊ |
54 | static struct acpi_2_rsdp *getAddressOfAcpiTable()␊ |
55 | {␊ |
56 | /* Before searching the BIOS space we are supposed to search the first 1K of the EBDA */␊ |
57 | EBDA_RANGE_START = /* (uint32_t)swapUint16(*(uint16_t *)BDA_EBDA_START) << 4 */ EBDA_RANGE_MIN;␊ |
58 | verbose("ACPIpatcher: scanning EBDA [%08X-%08X] for RSDP 1.0... ", EBDA_RANGE_START, EBDA_RANGE_END);␊ |
59 | void *acpi_addr = (void*)EBDA_RANGE_START;␊ |
60 | ␉for (; acpi_addr < (void*)EBDA_RANGE_END; acpi_addr++)␊ |
61 | ␉{␊ |
62 | ␉␉if (*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE)␊ |
63 | ␉␉{␊ |
64 | break;␊ |
65 | ␉␉}␊ |
66 | ␉}␊ |
67 | ␊ |
68 | ␉if (acpi_addr >= (void*)EBDA_RANGE_END)␊ |
69 | ␉{␊ |
70 | verbose("Nothing found.\n");␊ |
71 | verbose("ACPIpatcher: scanning BIOS area [%08X-%08X] for RSDP 1.0...\n", ACPI_RANGE_START, ACPI_RANGE_END);␊ |
72 | acpi_addr = (void*)ACPI_RANGE_START;␊ |
73 | ␉␉for (; acpi_addr < (void*)ACPI_RANGE_END; acpi_addr += 16)␊ |
74 | ␉␉{␊ |
75 | ␉␉␉if (*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE)␊ |
76 | ␉␉␉{␊ |
77 | break;␊ |
78 | }␊ |
79 | }␊ |
80 | ␉}␊ |
81 | ␉else␊ |
82 | ␉{␊ |
83 | verbose("\n");␊ |
84 | }␊ |
85 | ␊ |
86 | uint8_t csum = checksum8(acpi_addr, 20);␊ |
87 | ␊ |
88 | ␉if (csum == 0)␊ |
89 | ␉{␊ |
90 | // Only return the table if it is a true version 1.0 table (Revision 0)␊ |
91 | ␉␉if(((struct acpi_2_rsdp*)acpi_addr)->Revision == 0)␊ |
92 | ␉␉{␊ |
93 | return acpi_addr;␊ |
94 | }␊ |
95 | }␊ |
96 | ␉␊ |
97 | ␉return NULL;␊ |
98 | }␊ |
99 | ␊ |
100 | /* Gets the ACPI 2.0 RSDP address */␊ |
101 | static struct acpi_2_rsdp *getAddressOfAcpi20Table()␊ |
102 | {␊ |
103 | /* Before searching the BIOS space we are supposed to search the first 1K of the EBDA */␊ |
104 | ␉EBDA_RANGE_START = /* (uint32_t)swapUint16(*(uint16_t *)BDA_EBDA_START) << 4 */ EBDA_RANGE_MIN;␊ |
105 | verbose("ACPIpatcher: scanning EBDA [%08X-%08X] for RSDP 2.0 or newer... ", EBDA_RANGE_START, EBDA_RANGE_END);␊ |
106 | void *acpi_addr = (void *)EBDA_RANGE_START;␊ |
107 | ␉for (; acpi_addr < (void *)EBDA_RANGE_END; acpi_addr++)␊ |
108 | ␉{␊ |
109 | ␉␉if (*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE)␊ |
110 | ␉␉{␊ |
111 | break;␊ |
112 | ␉␉}␊ |
113 | ␉}␊ |
114 | ␊ |
115 | ␉if (acpi_addr >= (void *)EBDA_RANGE_END)␊ |
116 | ␉{␊ |
117 | verbose("Nothing found.\n");␊ |
118 | verbose("ACPIpatcher: scanning BIOS area [%08X-%08X] for RSDP 2.0 or newer...\n", ACPI_RANGE_START, ACPI_RANGE_END);␊ |
119 | acpi_addr = (void *)ACPI_RANGE_START;␊ |
120 | ␉␉for (; acpi_addr <= (void *)ACPI_RANGE_END; acpi_addr += 16)␊ |
121 | ␉␉{␊ |
122 | ␉␉␉if(*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE)␊ |
123 | ␉␉␉{␊ |
124 | break;␊ |
125 | }␊ |
126 | }␊ |
127 | ␉}␊ |
128 | ␉else␊ |
129 | ␉{␊ |
130 | verbose("\n");␊ |
131 | }␊ |
132 | ␊ |
133 | uint8_t csum = checksum8(acpi_addr, 20);␊ |
134 | ␊ |
135 | /* Only assume this is a 2.0 or better table if the revision is greater than 0␊ |
136 | * NOTE: ACPI 3.0 spec only seems to say that 1.0 tables have revision 1␊ |
137 | * and that the current revision is 2.. I am going to assume that rev > 0 is 2.0.␊ |
138 | */␊ |
139 | ␊ |
140 | if(csum == 0 && (((struct acpi_2_rsdp*)acpi_addr)->Revision > 0)) {␊ |
141 | uint8_t csum2 = checksum8(acpi_addr, sizeof(struct acpi_2_rsdp));␊ |
142 | ␉␉if(csum2 == 0)␊ |
143 | ␉␉{␊ |
144 | return acpi_addr;␊ |
145 | }␊ |
146 | }␊ |
147 | ␉␊ |
148 | ␉return NULL;␊ |
149 | }␊ |
150 | ␊ |
151 | /* The folowing ACPI Table search algo. should be reused anywhere needed:*/␊ |
152 | /* WARNING: outDirspec string will be overwritten by subsequent calls! */␊ |
153 | int search_and_get_acpi_fd(const char *filename, const char **outDirspec)␊ |
154 | {␊ |
155 | ␉int fd = 0;␊ |
156 | ␉static char dirSpec[512];␊ |
157 | ␊ |
158 | ␉// Try finding 'filename' in the usual places␊ |
159 | ␉// Start searching any potential location for ACPI Table␊ |
160 | snprintf(dirSpec, sizeof(dirSpec), "%s", filename);␊ |
161 | fd = open(dirSpec, 0);␊ |
162 | ␉if (fd < 0)␊ |
163 | ␉{␊ |
164 | ␉␉snprintf(dirSpec, sizeof(dirSpec), "/Extra/%s", filename); ␊ |
165 | ␉␉fd = open(dirSpec, 0);␊ |
166 | ␉␉if (fd < 0)␊ |
167 | ␉␉{␊ |
168 | snprintf(dirSpec, sizeof(dirSpec), "/Extra/Acpi/%s", filename);␊ |
169 | fd = open(dirSpec, 0);␊ |
170 | ␉␉␉if (fd < 0)␊ |
171 | ␉␉␉{␊ |
172 | snprintf(dirSpec, sizeof(dirSpec), "bt(0,0)/Extra/%s", filename);␊ |
173 | fd = open(dirSpec, 0);␊ |
174 | ␉␉␉␉if (fd < 0)␊ |
175 | ␉␉␉␉{␊ |
176 | snprintf(dirSpec, sizeof(dirSpec), "bt(0,0)/Extra/Acpi/%s", filename);␊ |
177 | fd = open(dirSpec, 0);␊ |
178 | ␉␉␉␉␉if (fd < 0)␊ |
179 | ␉␉␉␉␉{␊ |
180 | // NOT FOUND:␊ |
181 | dirSpec[0] = 0;␊ |
182 | }␊ |
183 | }␊ |
184 | ␉␉␉}␊ |
185 | ␉␉}␊ |
186 | ␉}␊ |
187 | ␊ |
188 | ␉if (outDirspec) *outDirspec = dirSpec; ␊ |
189 | ␉return fd;␊ |
190 | }␊ |
191 | ␊ |
192 | void *loadACPITable (const char *filename)␊ |
193 | {␊ |
194 | ␉void *tableAddr;␊ |
195 | ␉const char *dirspec = NULL;␊ |
196 | ␊ |
197 | ␉int fd = search_and_get_acpi_fd(filename, &dirspec);␊ |
198 | ␊ |
199 | ␉if (fd >= 0)␊ |
200 | ␉{␊ |
201 | ␉␉tableAddr = (void *)AllocateKernelMemory(file_size(fd));␊ |
202 | ␉␉if (tableAddr)␊ |
203 | ␉␉{␊ |
204 | ␉␉␉if (read(fd, tableAddr, file_size(fd)) != file_size(fd))␊ |
205 | ␉␉␉{␊ |
206 | ␉␉␉␉verbose("loadACPITable: Couldn't read table from: %s.\n", dirspec);␊ |
207 | ␉␉␉␉free(tableAddr);␊ |
208 | ␉␉␉␉close(fd);␊ |
209 | ␉␉␉␉return NULL;␊ |
210 | ␉␉␉}␊ |
211 | ␉␉␉//verbose("ACPIpatcher: Table %s read and stored at: 0x%08X\n", dirspec, tableAddr);␊ |
212 | ␉␉␉close(fd);␊ |
213 | ␉␉␉return tableAddr;␊ |
214 | ␉␉}␊ |
215 | ␉␉close(fd);␊ |
216 | ␉␉verbose("loadACPITable: Couldn't allocate memory for table: %s.\n", dirspec);␊ |
217 | }␊ |
218 | ␊ |
219 | ␉return NULL;␊ |
220 | }␊ |
221 | ␊ |
222 | struct acpi_2_fadt *patch_fadt(struct acpi_2_fadt *fadt, struct acpi_2_dsdt *new_dsdt)␊ |
223 | {␊ |
224 | ␉// extern void setupSystemType();␊ |
225 | ␊ |
226 | ␉struct acpi_2_fadt *fadt_mod = NULL;␊ |
227 | ␉bool fadt_rev2_needed = false;␊ |
228 | ␉bool fix_restart = false;␊ |
229 | ␉bool fix_restart_ps2 = false;␊ |
230 | ␉int value = 1;␊ |
231 | static bool ver_20 = false;␊ |
232 | ␊ |
233 | ␉// Restart Fix␊ |
234 | ␉if (Platform.CPU.Vendor == CPUID_VENDOR_INTEL) { // Intel=0x756E6547␊ |
235 | ␉␉fix_restart = true;␊ |
236 | ␉␉fix_restart_ps2 = false;␊ |
237 | ␉␉if ( getBoolForKey(kPS2RestartFix, &fix_restart_ps2, &bootInfo->chameleonConfig) && fix_restart_ps2)␊ |
238 | ␉␉{␊ |
239 | ␉␉␉fix_restart = true;␊ |
240 | ␉␉}␊ |
241 | ␉␉else␊ |
242 | ␉␉{␊ |
243 | ␉␉␉getBoolForKey(kRestartFix, &fix_restart, &bootInfo->chameleonConfig);␊ |
244 | ␉␉}␊ |
245 | ␉}␊ |
246 | ␉else␊ |
247 | ␉{␊ |
248 | ␉␉verbose("\tNot an Intel platform, FACP Restart Fix will not be applied!\n");␊ |
249 | ␉␉fix_restart = false;␊ |
250 | ␉}␊ |
251 | ␊ |
252 | ␉if (fix_restart)␊ |
253 | ␉{␊ |
254 | ␉␉fadt_rev2_needed = true;␊ |
255 | ␉}␊ |
256 | ␊ |
257 | ␉// Allocate new fadt table␊ |
258 | ␉if ((fadt->Length < 0x84) && fadt_rev2_needed)␊ |
259 | ␉{␊ |
260 | ␉␉fadt_mod = (struct acpi_2_fadt *)AllocateKernelMemory(0x84);␊ |
261 | ␉␉memcpy(fadt_mod, fadt, fadt->Length);␊ |
262 | ␉␉fadt_mod->Length = 0x84;␊ |
263 | ␉␉fadt_mod->Revision = 0x02; // FACP rev 2 (ACPI 1.0B MS extensions)␊ |
264 | ␉}␊ |
265 | ␉else␊ |
266 | ␉{␊ |
267 | ␉␉fadt_mod = (struct acpi_2_fadt *)AllocateKernelMemory(fadt->Length);␊ |
268 | ␉␉memcpy(fadt_mod, fadt, fadt->Length);␊ |
269 | ␉}␊ |
270 | verbose("\tNew FACP loaded @%08X, length=%d\n", (uint32_t)fadt_mod, fadt_mod->Length);␊ |
271 | ␊ |
272 | ␉// Bungo: Determine PM Profile␊ |
273 | ␉verbose("\tPM Profile=0x%02X", fadt_mod->PM_Profile);␊ |
274 | ␉if (getIntForKey(kSystemType, &value, &bootInfo->chameleonConfig))␊ |
275 | ␉{␊ |
276 | ␉␉verbose(", overriding with: 0x%02X.\n", (uint8_t)value);␊ |
277 | ␉␉fadt_mod->PM_Profile = (uint8_t)value; // user has overriden the PM Profile so take care of it in FACP␊ |
278 | ␉}␊ |
279 | ␉else␊ |
280 | ␉{␊ |
281 | switch (fadt_mod->PM_Profile) { // check if PM Profile is correct (1..3)␊ |
282 | case 1:␊ |
283 | case 2:␊ |
284 | case 3:␊ |
285 | verbose(": using.\n");␊ |
286 | break;␊ |
287 | default:␊ |
288 | // use SMBIOS chassisType to determine PM Profile (saved previously for us)␊ |
289 | verbose(", expected value: 1, 2 or 3, setting to 0x%02X.\n", Platform.Type);␊ |
290 | fadt_mod->PM_Profile = Platform.Type; // take care of modified FACP's PM Profile entry␊ |
291 | break;␊ |
292 | }␊ |
293 | }␊ |
294 | ␉Platform.Type = fadt_mod->PM_Profile; // Save fixed PM Profile (system-type)␊ |
295 | ␊ |
296 | /* Bungo: Moved into fake_efi.c␊ |
297 | // Setup system-type: We now have to write the systemm-type in ioregs: we cannot do it before in setupDeviceTree()␊ |
298 | ␉// because we need to take care of FACP original content, if it is correct.␊ |
299 | ␉setupSystemType();␊ |
300 | */␊ |
301 | ␉// Patch FACP to fix restart␊ |
302 | ␉if (fix_restart) {␊ |
303 | ␉␉if (fix_restart_ps2) {␊ |
304 | ␉␉␉fadt_mod->Flags|= 0x400; // Reset register supported␊ |
305 | ␉␉␉fadt_mod->Reset_SpaceID␉␉= 0x01; // System I/O␊ |
306 | ␉␉␉fadt_mod->Reset_BitWidth␉= 0x08; // 1 byte␊ |
307 | ␉␉␉fadt_mod->Reset_BitOffset␉= 0x00; // Offset 0␊ |
308 | ␉␉␉fadt_mod->Reset_AccessWidth␉= 0x01; // Byte access␊ |
309 | ␉␉␉fadt_mod->Reset_Address␉␉= 0x64; // Address of the register␊ |
310 | ␉␉␉fadt_mod->Reset_Value␉␉= 0xfe; // Value to write to reset the system␊ |
311 | ␉␉␉verbose("\tFACP PS2 Restart Fix applied!\n");␊ |
312 | ␉␉}␊ |
313 | ␉␉else␊ |
314 | ␉␉{␊ |
315 | ␉␉␉fadt_mod->Flags|= 0x400; // Reset register supported␊ |
316 | ␉␉␉fadt_mod->Reset_SpaceID␉␉= 0x01; // System I/O␊ |
317 | ␉␉␉fadt_mod->Reset_BitWidth␉= 0x08; // 1 byte␊ |
318 | ␉␉␉fadt_mod->Reset_BitOffset␉= 0x00; // Offset 0␊ |
319 | ␉␉␉fadt_mod->Reset_AccessWidth␉= 0x01; // Byte access␊ |
320 | ␉␉␉fadt_mod->Reset_Address␉␉= 0x0cf9; // Address of the register␊ |
321 | ␉␉␉fadt_mod->Reset_Value␉␉= 0x06; // Value to write to reset the system␊ |
322 | ␉␉␉verbose("\tFACP Restart Fix applied!\n");␊ |
323 | ␉␉}␊ |
324 | ␉}␊ |
325 | ␉else␊ |
326 | ␉{␊ |
327 | //verbose("\tRestart Fix: No.\n");␊ |
328 | }␊ |
329 | ␊ |
330 | // Bungo: FACS table fix and load␊ |
331 | verbose("\tOEM table FACS@%08X, length=%d: ", fadt_mod->FACS, ((struct acpi_2_facs *)fadt_mod->FACS)->Length);␊ |
332 | ␉if ((fadt_mod->FACS > 0) && (fadt_mod->FACS < 0xFFFFFFFF) && (((struct acpi_2_facs *)fadt_mod->FACS)->Length >= 64))␊ |
333 | ␉{␊ |
334 | verbose("using.\n");␊ |
335 | ␉}␊ |
336 | ␉else␊ |
337 | ␉{␊ |
338 | verbose(" incorrect!\n");␊ |
339 | }␊ |
340 | ␉if (ver_20 && (((uint32_t)(&(fadt_mod->X_FACS)) - (uint32_t)fadt_mod + 8) <= fadt_mod->Length))␊ |
341 | ␉{␊ |
342 | verbose("\tOEM table X_FACS@%08X%08X, length=%d: ", (uint32_t)(fadt_mod->X_FACS >> 32), (uint32_t)(fadt_mod->X_FACS & 0xFFFFFFFF), ((struct acpi_2_facs *)fadt_mod->X_FACS)->Length);␊ |
343 | ␉␉if (fadt_mod->FACS != fadt_mod->X_FACS)␊ |
344 | ␉␉{␊ |
345 | verbose("differes from FACS - fixing");␊ |
346 | ␉␉␉if ((fadt_mod->X_FACS > 0) && (fadt_mod->X_FACS < 0xFFFFFFFF) && (((struct acpi_2_facs *)(uint32_t)fadt_mod->X_FACS)->Length >= 64))␊ |
347 | ␉␉␉{␊ |
348 | // Bungo: in my case only from X_FACS loading correct table (64 bytes) into IOReg␊ |
349 | fadt_mod->FACS = (uint32_t)fadt_mod->X_FACS;␊ |
350 | ␉␉␉}␊ |
351 | ␉␉␉else␊ |
352 | ␉␉␉{␊ |
353 | fadt_mod->X_FACS = (uint64_t)fadt_mod->FACS;␊ |
354 | }␊ |
355 | verbose(" \tUsing FACS@%08X = X_FACS@%08X\n", fadt_mod->FACS, (uint32_t)fadt_mod->X_FACS);␊ |
356 | ␉␉}␊ |
357 | ␉␉else␊ |
358 | ␉␉{␊ |
359 | verbose("using.\n");␊ |
360 | }␊ |
361 | }␊ |
362 | ␊ |
363 | // Bungo: Save Hardware Signature (machine-signature)␊ |
364 | if ((fadt_mod->FACS > 0) && (fadt_mod->FACS < 0xFFFFFFFF) && (((struct acpi_2_facs *)fadt_mod->FACS)->Length >= 64)) {␊ |
365 | Platform.HWSignature = ((struct acpi_2_facs *)fadt_mod->FACS)->HWSignature;␊ |
366 | verbose("\tHardware Signature=0x%08X: using.\n", Platform.HWSignature);␊ |
367 | } else {␊ |
368 | Platform.HWSignature = 0;␊ |
369 | verbose("\tFixing Hardware Signature=0x%08X.\n", Platform.HWSignature);␊ |
370 | }␊ |
371 | ␉␊ |
372 | verbose("\tOEM table DSDT@%08X, length=%d: %susing.\n", fadt_mod->DSDT, ((struct acpi_2_dsdt *)fadt_mod->DSDT)->Length, new_dsdt ? "not " : "");␊ |
373 | if (ver_20 && (((uint32_t)(&(fadt_mod->X_DSDT)) - (uint32_t)fadt_mod + 8) <= fadt_mod->Length)) {␊ |
374 | verbose("\tOEM table X_DSDT@%08X%08X, length=%d: %susing.\n", (uint32_t)(fadt_mod->X_DSDT >> 32), (uint32_t)(fadt_mod->X_DSDT & 0xFFFFFFFF), ((struct acpi_2_dsdt *)fadt_mod->X_DSDT)->Length, new_dsdt ? "not " : "");␊ |
375 | }␊ |
376 | ␉// Patch DSDT address if we have loaded DSDT.aml␊ |
377 | ␉if (new_dsdt) {␊ |
378 | fadt_mod->DSDT = (uint32_t)new_dsdt;␊ |
379 | verbose("\tFACP uses custom DSDT@%08X", fadt_mod->DSDT);␊ |
380 | ␉␉if (ver_20 && (((uint32_t)(&(fadt_mod->X_DSDT)) - (uint32_t)fadt_mod + 8) <= fadt_mod->Length)) {␊ |
381 | ␉␉␉fadt_mod->X_DSDT = (uint64_t)new_dsdt;␊ |
382 | verbose(" / X_DSDT@%08X%08X", (uint32_t)(fadt_mod->X_DSDT >> 32), (uint32_t)(fadt_mod->X_DSDT & 0xFFFFFFFF));␊ |
383 | ␉␉}␊ |
384 | verbose(", length=%d\n", ((struct acpi_2_dsdt *)fadt_mod->DSDT)->Length);␊ |
385 | ␉}␊ |
386 | ␊ |
387 | ␉// Correct the checksum␊ |
388 | ␉fadt_mod->Checksum=0;␊ |
389 | ␉fadt_mod->Checksum=256-checksum8(fadt_mod, fadt_mod->Length);␊ |
390 | ␊ |
391 | ver_20 = TRUE;␊ |
392 | ␉return fadt_mod;␊ |
393 | }␊ |
394 | // Bung: Unused␊ |
395 | /* Setup ACPI without replacing DSDT.␊ |
396 | int setupAcpiNoMod()␊ |
397 | {␊ |
398 | //␉addConfigurationTable(&gEfiAcpiTableGuid, getAddressOfAcpiTable(), "ACPI");␊ |
399 | //␉addConfigurationTable(&gEfiAcpi20TableGuid, getAddressOfAcpi20Table(), "ACPI_20");␊ |
400 | ␉// XXX aserebln why uint32 cast if pointer is uint64 ?␊ |
401 | ␉acpi10_p = (uint64_t)(uint32_t)getAddressOfAcpiTable();␊ |
402 | ␉acpi20_p = (uint64_t)(uint32_t)getAddressOfAcpi20Table();␊ |
403 | ␉// addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");␊ |
404 | ␉if(acpi20_p)␊ |
405 | ␉{␊ |
406 | ␉␉// addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");␊ |
407 | ␉}␊ |
408 | ␉else␊ |
409 | ␉{␊ |
410 | ␉␉DBG("ACPIpatcher: version 2.0 not found.\n");␊ |
411 | ␉}␊ |
412 | ␉return 1;␊ |
413 | }␊ |
414 | */␊ |
415 | /* Setup ACPI. Replace DSDT if DSDT.aml is found */␊ |
416 | int setupAcpi(void)␊ |
417 | {␊ |
418 | ␉int version;␊ |
419 | ␉const char *filename;␊ |
420 | ␉char dirSpec[128];␊ |
421 | ␉int len = 0;␊ |
422 | ␊ |
423 | ␉// always reset cpu count to 0 when injecting new acpi␊ |
424 | ␉acpi_cpu_count = 0;␊ |
425 | ␊ |
426 | verbose("\nACPIpatcher: Start patching...\n");␊ |
427 | ␊ |
428 | if (new_dsdt != NULL) {␊ |
429 | verbose("ACPIpatcher: custom table DSDT already loaded @%08X, length=%d: using.\n", new_dsdt, ((struct acpi_2_header *)new_dsdt)->Length);␊ |
430 | } else {␊ |
431 | // Try using the file specified with the DSDT option␊ |
432 | if (getValueForKey(kDSDT, &filename, &len, &bootInfo->chameleonConfig) && len) {␊ |
433 | snprintf(dirSpec, sizeof(dirSpec), filename);␊ |
434 | } else {␊ |
435 | sprintf(dirSpec, "DSDT.aml");␊ |
436 | }␊ |
437 | ␊ |
438 | verbose("ACPIpatcher: attempting to load custom table DSDT...\n", dirSpec);␊ |
439 | if ((new_dsdt = loadACPITable(dirSpec))) {␊ |
440 | verbose("ACPIpatcher: custom table DSDT loaded @%08X, length=%d.\n", new_dsdt, ((struct acpi_2_header *)new_dsdt)->Length);␊ |
441 | } else {␊ |
442 | //verbose("ACPIpatcher: custom DSDT not found!.\n");␊ |
443 | }␊ |
444 | }␊ |
445 | ␊ |
446 | ␉/* Try using the file specified with the DSDT option␊ |
447 | ␉if (getValueForKey(kDSDT, &filename, &len, &bootInfo->chameleonConfig)) {␊ |
448 | ␉␉snprintf(dirSpec, sizeof(dirSpec), filename);␊ |
449 | ␉} else {␊ |
450 | ␉␉sprintf(dirSpec, "DSDT.aml");␊ |
451 | ␉␉//DBG("dirSpec, DSDT.aml");␊ |
452 | ␉}␊ |
453 | ␊ |
454 | ␉// Load replacement DSDT␊ |
455 | ␉new_dsdt = loadACPITable(dirSpec);␊ |
456 | */␊ |
457 | ␊ |
458 | // Load ECDT table␊ |
459 | if (new_ecdt != NULL) {␊ |
460 | verbose("ACPIpatcher: custom table ECDT already loaded @%08X, length=%d: using.\n", new_ecdt, ((struct acpi_2_header *)new_ecdt)->Length);␊ |
461 | } else {␊ |
462 | sprintf(dirSpec, "ECDT.aml");␊ |
463 | filename = "ECDT.aml";␊ |
464 | verbose("ACPIpatcher: attempting to load custom table ECDT...\n");␊ |
465 | if ((new_ecdt = loadACPITable(filename))) {␊ |
466 | verbose("ACPIpatcher: custom table ECDT loaded @%08X, length=%d.\n", new_ecdt, ((struct acpi_2_header *)new_ecdt)->Length);␊ |
467 | } else {␊ |
468 | //verbose("ACPIpatcher: custom ECDT not found!.\n");␊ |
469 | }␊ |
470 | }␊ |
471 | ␊ |
472 | // Mozodojo: Load additional SSDTs␊ |
473 | ␉struct acpi_2_ssdt *new_ssdt[32]; // 26 custom + 4 subssdt + 2 for pss & cst␊ |
474 | ␉int ssdtotal_number = 0;␊ |
475 | ␉{␊ |
476 | ␉␉int i;␊ |
477 | ␉␉for (i = 0; i < 26; i++) {␊ |
478 | ␉␉␉//char filename[512];␊ |
479 | ␊ |
480 | ␉␉␉sprintf(dirSpec, (i > 0)? "SSDT-%d.aml":"SSDT.aml", i);␊ |
481 | ␊ |
482 | ␉␉␉if ((new_ssdt[ssdtotal_number] = loadACPITable(dirSpec))) {␊ |
483 | verbose("ACPIpatcher: custom table %s loaded @%08X, length=%d\n", dirSpec, new_ssdt[ssdtotal_number], new_ssdt[ssdtotal_number]->Length);␊ |
484 | ssdtotal_number++;␊ |
485 | ␉␉␉} else {␊ |
486 | //verbose("ACPIpatcher: custom table '%s' not found.\n", filename);␊ |
487 | // Bungo: load up to 26 custom tables enabled now␊ |
488 | ␉␉␉␉//break;␊ |
489 | ␉␉␉}␊ |
490 | ␉␉}␊ |
491 | ␉}␊ |
492 | ␊ |
493 | ␉// Mozodojo: going to patch FACP and load SSDTs even if DSDT.aml is not present␊ |
494 | ␉/*if (!new_dsdt)␊ |
495 | ␉ {␊ |
496 | ␉ return setupAcpiNoMod();␊ |
497 | ␉ }*/␊ |
498 | ␊ |
499 | ␉// SSDT options␊ |
500 | ␉bool drop_ssdt = false, generate_pstates = false, generate_cstates = false;␊ |
501 | ␊ |
502 | ␉getBoolForKey(kDropSSDT, &drop_ssdt, &bootInfo->chameleonConfig);␊ |
503 | ␉getBoolForKey(kGeneratePStates, &generate_pstates, &bootInfo->chameleonConfig);␊ |
504 | ␉getBoolForKey(kGenerateCStates, &generate_cstates, &bootInfo->chameleonConfig);␊ |
505 | verbose("ACPIpatcher: drop SSDT tables: %s.\n", drop_ssdt ? "Yes" : "No");␊ |
506 | ␉verbose("ACPIpatcher: generate P-States: %s.\n", generate_pstates ? "Yes" : "No");␊ |
507 | ␉verbose("ACPIpatcher: generate C-States: %s.\n", generate_cstates ? "Yes" : "No");␊ |
508 | ␊ |
509 | bool getSubSSDT = !generate_pstates && !generate_cstates;␊ |
510 | ␊ |
511 | ␉// Do the same procedure for both versions of ACPI␊ |
512 | ␉for (version = 0; version < 2; version++)␊ |
513 | ␉{␊ |
514 | ␉␉struct acpi_2_rsdp *rsdp, *rsdp_mod;␊ |
515 | ␉␉struct acpi_2_rsdt *rsdt, *rsdt_mod;␊ |
516 | struct acpi_2_xsdt *xsdt, *xsdt_mod;␊ |
517 | struct acpi_2_fadt *fadt_mod;␊ |
518 | uint32_t *rsdt_entries;␊ |
519 | uint64_t *xsdt_entries;␊ |
520 | ␊ |
521 | ␉␉// Find original rsdp␊ |
522 | ␉␉rsdp = (struct acpi_2_rsdp *)(version ? getAddressOfAcpi20Table() : getAddressOfAcpiTable());␊ |
523 | ␉␉if (!rsdp) {␊ |
524 | /*␊ |
525 | ␉␉␉if (version) {␊ |
526 | ␉␉␉␉addConfigurationTable(&gEfiAcpi20TableGuid, NULL, "ACPI_20");␊ |
527 | ␉␉␉} else {␊ |
528 | ␉␉␉␉addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI");␊ |
529 | ␉␉␉}␊ |
530 | */␊ |
531 | verbose("ACPIpatcher: ACPI version %d.0 not found. Not patching.\n", version + 1);␊ |
532 | ␉␉␉continue;␊ |
533 | ␉␉}␊ |
534 | ␊ |
535 | int rsdplength = version ? rsdp->Length : 20;␊ |
536 | ␉␉int l = version ? 20 : 0;␊ |
537 | ␉␉verbose("ACPIpatcher: OEM table RSDP@%08X, length=%d. ACPI version %d.0: patching.\n", rsdp, rsdplength, version + 1);␊ |
538 | ␊ |
539 | ␉␉/* FIXME: no check that memory allocation succeeded ␊ |
540 | ␉␉ * Copy and patch RSDP, RSDT, XSDT and FADT␊ |
541 | ␉␉ * For more info see ACPI Specification pages 110 and following␊ |
542 | ␉␉ */␊ |
543 | ␊ |
544 | ␉␉rsdp_mod = (struct acpi_2_rsdp *)(l + AllocateKernelMemory(l + rsdplength));␊ |
545 | ␉␉memcpy(rsdp_mod, rsdp, rsdplength);␊ |
546 | ␊ |
547 | ␉␉rsdt = (struct acpi_2_rsdt *)rsdp->RsdtAddress;␊ |
548 | ␉␉verbose("ACPIpatcher: OEM table RSDT@%08X, length=%d: ", rsdp->RsdtAddress, rsdt->Length);␊ |
549 | ␉␉␊ |
550 | ␉␉if ((rsdp->RsdtAddress > 0) && (rsdp->RsdtAddress < 0xFFFFFFFF) && (rsdt->Length < 0x10000)) {␊ |
551 | verbose("using.\n");␊ |
552 | ␉␉␉int rsdt_entries_num;␊ |
553 | ␉␉␉int dropoffset = 0, i, j;␊ |
554 | ␊ |
555 | ␉␉␉// mozo: using malloc cos I didn't found how to free already allocated kernel memory␊ |
556 | ␉␉␉rsdt_mod = (struct acpi_2_rsdt *)malloc(rsdt->Length);␊ |
557 | ␉␉␉memcpy(rsdt_mod, rsdt, rsdt->Length);␊ |
558 | ␉␉␉rsdp_mod->RsdtAddress = (uint32_t)rsdt_mod;␊ |
559 | ␉␉␉rsdt_entries_num = (rsdt_mod->Length - sizeof(struct acpi_2_rsdt)) / 4;␊ |
560 | ␉␉␉rsdt_entries = (uint32_t *)(rsdt_mod + 1);␊ |
561 | ␊ |
562 | ␉␉␉for (i = 0; i < rsdt_entries_num; i++) {␊ |
563 | struct acpi_2_header *oemTable = (struct acpi_2_header *)rsdt_entries[i];␊ |
564 | verbose("ACPIpatcher: OEM table %c%c%c%c@%08X, length=%d: ", oemTable->Signature[0], oemTable->Signature[1], oemTable->Signature[2], oemTable->Signature[3], oemTable, oemTable->Length);␊ |
565 | ␊ |
566 | ␉␉␉␉if (!(rsdt_entries[i] > 0) || !(rsdt_entries[i] < 0xFFFFFFFF)) {␊ |
567 | verbose("incorrect! Dropping.\n");␊ |
568 | dropoffset++;␊ |
569 | continue;␊ |
570 | ␉␉␉␉}␊ |
571 | ␊ |
572 | ␉␉␉␉if (tableSign(oemTable, "SSDT")) {␊ |
573 | if (drop_ssdt) {␊ |
574 | verbose("dropping.\n");␊ |
575 | dropoffset++;␊ |
576 | } else {␊ |
577 | verbose("using.\n");␊ |
578 | rsdt_entries[i-dropoffset] = rsdt_entries[i];␊ |
579 | // get rest of ssdt tables from inside ssdt_pmref␊ |
580 | if (getSubSSDT) { // prevent from extracting originals if user choosed generatind PSS and/or CSS tables␊ |
581 | struct ssdt_pmref *subSSDT = (struct ssdt_pmref *)(rsdt_entries[i] + sizeof(struct acpi_2_header) + 15);␊ |
582 | uint8_t tabNum = *((uint8_t *)subSSDT - 2) / 3; // e.g Name (SSDT, Package (0x0C) -> 0x0C / 3 = number of sub SSDTs␊ |
583 | for (j = 0; (j < tabNum) && (ssdtotal_number < 30); j++) {␊ |
584 | verbose("ACPIpatcher: OEM table SSDT_%s@%08X, length=%d: ", ((struct acpi_2_ssdt *)subSSDT[j].addr)->OEMTableId, subSSDT[j].addr, ((struct acpi_2_ssdt *)subSSDT[j].addr)->Length);␊ |
585 | if (!(subSSDT[j].addr > 0) || !(subSSDT[j].addr < 0xFFFFFFFF)) {␊ |
586 | verbose("incorrect! Dropping.\n");␊ |
587 | continue;␊ |
588 | }␊ |
589 | verbose("using.\n");␊ |
590 | new_ssdt[ssdtotal_number] = (struct acpi_2_ssdt *)subSSDT[j].addr;␊ |
591 | ssdtotal_number++;␊ |
592 | }␊ |
593 | }␊ |
594 | }␊ |
595 | continue;␊ |
596 | ␉␉␉␉}␊ |
597 | ␊ |
598 | /* Bungo: According to ACPI Spec. no DSDT in RSDT, so what this for?␊ |
599 | ␊ |
600 | if (tableSign(oemTable, "DSDT")) {␊ |
601 | ␉␉␉␉␉if (new_dsdt) {␊ |
602 | ␉␉␉␉␉␉rsdt_entries[i-dropoffset] = (uint32_t)new_dsdt;␊ |
603 | ␉␉␉␉␉␉verbose("custom table added.\n");␊ |
604 | ␉␉␉␉␉}␊ |
605 | ␉␉␉␉␉continue;␊ |
606 | ␉␉␉␉}␊ |
607 | ␊ |
608 | So, suggest to drop, it should be in FACP */␊ |
609 | ␊ |
610 | if (tableSign(oemTable, "DSDT")) {␊ |
611 | verbose("dropping.\n");␊ |
612 | dropoffset++;␊ |
613 | continue;␊ |
614 | ␉␉␉␉}␊ |
615 | ␊ |
616 | if (tableSign(oemTable, "ECDT") && new_ecdt) {␊ |
617 | verbose("dropping.\n");␊ |
618 | dropoffset++;␊ |
619 | continue;␊ |
620 | ␉␉␉␉}␊ |
621 | ␊ |
622 | ␉␉␉␉if (tableSign(oemTable, "FACP")) {␊ |
623 | ␉␉␉␉␉if (oemTable->Length > 0x10000) {␊ |
624 | ␉␉␉␉␉␉verbose("incorrect. Not modifying.\n");␊ |
625 | ␉␉␉␉␉␉continue;␊ |
626 | ␉␉␉␉␉}␊ |
627 | ␊ |
628 | ␉␉␉␉␉verbose("patching.\n");␊ |
629 | ␉␉␉␉␉fadt_mod = patch_fadt((struct acpi_2_fadt *)oemTable, new_dsdt);␊ |
630 | ␉␉␉␉␉rsdt_entries[i-dropoffset] = (uint32_t)fadt_mod;␊ |
631 | ␉␉␉␉␉␊ |
632 | ␉␉␉␉␉// Generate _CST SSDT␊ |
633 | ␉␉␉␉␉if (generate_cstates && (new_ssdt[ssdtotal_number] = generate_cst_ssdt(fadt_mod))) {␊ |
634 | ␉␉␉␉␉␉verbose("\tC-States generated.\n");␊ |
635 | ␉␉␉␉␉␉generate_cstates = false; // Generate SSDT only once!␊ |
636 | ␉␉␉␉␉␉ssdtotal_number++;␊ |
637 | ␉␉␉␉␉}␊ |
638 | ␊ |
639 | ␉␉␉␉␉// Generating _PSS SSDT␊ |
640 | ␉␉␉␉␉if (generate_pstates && (new_ssdt[ssdtotal_number] = generate_pss_ssdt((void*)fadt_mod->DSDT))) {␊ |
641 | ␉␉␉␉␉␉verbose("\tP-States generated.\n");␊ |
642 | ␉␉␉␉␉␉generate_pstates = false; // Generate SSDT only once!␊ |
643 | ␉␉␉␉␉␉ssdtotal_number++;␊ |
644 | ␉␉␉␉␉}␊ |
645 | ␉␉␉␉␉continue;␊ |
646 | ␉␉␉␉}␊ |
647 | ␊ |
648 | verbose("using.\n");␊ |
649 | rsdt_entries[i-dropoffset] = rsdt_entries[i];␊ |
650 | ␉␉␉}␊ |
651 | ␊ |
652 | // For moded rsdt calculate new lenght␊ |
653 | if (new_ecdt)␊ |
654 | rsdt_mod->Length += 4*ssdtotal_number - 4*dropoffset + 4; // custom - dropped + ECDT␊ |
655 | ␉␉␉else␊ |
656 | rsdt_mod->Length += 4*ssdtotal_number - 4*dropoffset;␊ |
657 | // Allocate moded rsdt in Kernel memory area␊ |
658 | ␉␉␉struct acpi_2_rsdt *rsdt_copy = (struct acpi_2_rsdt *)AllocateKernelMemory(rsdt_mod->Length);␊ |
659 | memcpy(rsdt_copy, rsdt_mod, rsdt_mod->Length); // should be rsdt_mod->Length - 4*ssdtotal_number - 4 but don't care␊ |
660 | ␉␉␉free(rsdt_mod);␊ |
661 | ␉␉␉rsdt_mod = rsdt_copy;␊ |
662 | ␉␉␉rsdp_mod->RsdtAddress = (uint32_t)rsdt_mod;␊ |
663 | ␉␉␉rsdt_entries_num = (rsdt_mod->Length-sizeof(struct acpi_2_rsdt)) / 4;␊ |
664 | ␉␉␉rsdt_entries = (uint32_t *)(rsdt_mod + 1);␊ |
665 | ␊ |
666 | ␉␉␉// Mozodojo: Insert additional SSDTs into RSDT␊ |
667 | for (j = 0; j < ssdtotal_number; j++) {␊ |
668 | rsdt_entries[i-dropoffset+j] = (uint32_t)new_ssdt[j];␊ |
669 | }␊ |
670 | verbose("ACPIpatcher: added %d custom SSDT table%s into RSDT.\n", ssdtotal_number, (ssdtotal_number != 1) ? "s" : "");␊ |
671 | ␉␉␉␊ |
672 | ␉␉␉if (new_ecdt) {␊ |
673 | ␉␉␉␉rsdt_entries[i - dropoffset + j] = (uint32_t)new_ecdt;␊ |
674 | ␉␉␉␉verbose("ACPIpatcher: added custom table %s @%08X into RSDT.\n", "ECDT", new_ecdt);␊ |
675 | ␉␉␉}␊ |
676 | ␊ |
677 | ␉␉␉// Correct the checksum of RSDT␊ |
678 | ␉␉␉verbose("ACPIpatcher: modified RSDT@%08X, length=%d. Checksum: old=%d, ", rsdt_mod, rsdt_mod->Length, rsdt_mod->Checksum);␊ |
679 | ␉␉␉rsdt_mod->Checksum=0;␊ |
680 | ␉␉␉rsdt_mod->Checksum=256-checksum8(rsdt_mod,rsdt_mod->Length);␊ |
681 | ␉␉␉verbose("new=%d.\n", rsdt_mod->Checksum);␊ |
682 | ␉␉} else {␊ |
683 | ␉␉␉rsdp_mod->RsdtAddress = 0;␊ |
684 | ␉␉␉verbose("not found or incorrect!\n");␊ |
685 | ␉␉}␊ |
686 | ␉␉verbose("\n");␊ |
687 | ␊ |
688 | if (gVerboseMode) pause("");␊ |
689 | ␊ |
690 | ␉␉if (version) {␊ |
691 | ␉␉␉// FIXME: handle 64-bit address correctly␊ |
692 | ␉␉␉xsdt = (struct acpi_2_xsdt *)(uint32_t)rsdp->XsdtAddress;␊ |
693 | verbose("ACPIpatcher: OEM table XSDT@%08X%08X, length=%d: ", (uint32_t)(rsdp->XsdtAddress >> 32), (uint32_t)(rsdp->XsdtAddress & 0xFFFFFFFF), xsdt->Length);␊ |
694 | ␊ |
695 | ␉␉␉if ((rsdp->XsdtAddress > 0) && (rsdp->XsdtAddress < 0xFFFFFFFF) && (xsdt->Length < 0x10000)) {␊ |
696 | verbose("using.\n");␊ |
697 | ␉␉␉␉int xsdt_entries_num, i, j;␊ |
698 | ␉␉␉␉int dropoffset = 0;␊ |
699 | ␊ |
700 | ␉␉␉␉// mozo: using malloc cos I didn't found how to free already allocated kernel memory␊ |
701 | ␉␉␉␉xsdt_mod = (struct acpi_2_xsdt *)malloc(xsdt->Length);␊ |
702 | ␉␉␉␉memcpy(xsdt_mod, xsdt, xsdt->Length);␊ |
703 | rsdp_mod->XsdtAddress = (uint64_t)xsdt_mod;␊ |
704 | ␉␉␉␉xsdt_entries_num = (xsdt_mod->Length - sizeof(struct acpi_2_xsdt)) / 8;␊ |
705 | ␉␉␉␉xsdt_entries = (uint64_t *)(xsdt_mod + 1);␊ |
706 | ␊ |
707 | ␉␉␉␉for (i = 0; i < xsdt_entries_num; i++) {␊ |
708 | struct acpi_2_header *oemTable = (struct acpi_2_header *)(uint32_t)xsdt_entries[i];␊ |
709 | verbose("ACPIpatcher: OEM table %c%c%c%c@%08X%08X, length=%d", oemTable->Signature[0], oemTable->Signature[1], oemTable->Signature[2], oemTable->Signature[3], (uint32_t)(xsdt_entries[i] >> 32), (uint32_t)(xsdt_entries[i] & 0xFFFFFFFF), oemTable->Length);␊ |
710 | ␊ |
711 | ␉␉␉␉␉if (!(xsdt_entries[i] > 0) || !(xsdt_entries[i] < 0xFFFFFFFF)) {␊ |
712 | verbose(": incorrect! Dropping.\n");␊ |
713 | dropoffset++;␊ |
714 | ␉␉␉␉␉␉continue;␊ |
715 | ␉␉␉␉␉}␊ |
716 | ␊ |
717 | bool inRSDT = (uint32_t)oemTable == ((uint32_t *)(rsdt + 1))[i]; // check if already in RSDT␊ |
718 | if (inRSDT) {␊ |
719 | verbose(" (already in RSDT)");␊ |
720 | }␊ |
721 | ␊ |
722 | if (tableSign(oemTable, "SSDT") && !inRSDT) {␊ |
723 | if (drop_ssdt) {␊ |
724 | verbose(": dropping.\n");␊ |
725 | dropoffset++;␊ |
726 | } else {␊ |
727 | verbose(": using.\n");␊ |
728 | xsdt_entries[i - dropoffset] = xsdt_entries[i];␊ |
729 | // Get rest of ssdts from ssdt_pmref␊ |
730 | if (getSubSSDT) {␊ |
731 | struct ssdt_pmref *subSSDT = (struct ssdt_pmref *)((uint32_t)xsdt_entries[i - dropoffset] + sizeof(struct acpi_2_header) + 15);␊ |
732 | uint8_t tabNum = *((uint8_t *)subSSDT - 2) / 3; // e.g: Name (SSDT, Package (0x0C) -> 0x0C / 3 = 4 is number of sub SSDTs␊ |
733 | for (j = 0; (j < tabNum) && (ssdtotal_number < 30); j++) {␊ |
734 | verbose("ACPIpatcher: OEM table SSDT_%s@%08X, length=%d", ((struct acpi_2_ssdt *)subSSDT[j].addr)->OEMTableId, subSSDT[j].addr, ((struct acpi_2_ssdt *)subSSDT[j].addr)->Length);␊ |
735 | if (!(subSSDT[j].addr > 0) || !(subSSDT[j].addr < 0xFFFFFFFF)) {␊ |
736 | verbose(": incorrect! Dropping.\n");␊ |
737 | continue;␊ |
738 | }␊ |
739 | new_ssdt[ssdtotal_number] = (struct acpi_2_ssdt *)subSSDT[j].addr;␊ |
740 | ssdtotal_number++;␊ |
741 | verbose(": using.\n");␊ |
742 | }␊ |
743 | }␊ |
744 | }␊ |
745 | continue;␊ |
746 | }␊ |
747 | ␊ |
748 | // Bungo: According to ACPI Spec. no DSDT in RSDT, so what this for?␊ |
749 | /*␊ |
750 | if (tableSign(oemTable, "DSDT")) {␊ |
751 | if (new_dsdt) {␊ |
752 | xsdt_entries[i-dropoffset] = (uint64_t)new_dsdt;␊ |
753 | verbose("custom table added.\n");␊ |
754 | }␊ |
755 | continue;␊ |
756 | }␊ |
757 | */␊ |
758 | // Suggest to drop, it should be in FACP␊ |
759 | if (tableSign(oemTable, "DSDT") && !inRSDT) {␊ |
760 | verbose(": dropping.\n");␊ |
761 | dropoffset++;␊ |
762 | continue;␊ |
763 | }␊ |
764 | ␊ |
765 | ␉␉␉␉␉if (tableSign(oemTable, "FACP") && !inRSDT) {␊ |
766 | ␉␉␉␉␉␉if (oemTable->Length > 0x10000) {␊ |
767 | ␉␉␉␉␉␉␉goto drop_xsdt;␊ |
768 | ␉␉␉␉␉␉}␊ |
769 | ␊ |
770 | verbose(": patching.\n");␊ |
771 | ␉␉␉␉␉␉fadt_mod = patch_fadt((struct acpi_2_fadt *)oemTable, new_dsdt);␊ |
772 | ␉␉␉␉␉␉xsdt_entries[i - dropoffset] = (uint64_t)fadt_mod;␊ |
773 | ␊ |
774 | ␉␉␉␉␉␉// Generate _CST SSDT␊ |
775 | ␉␉␉␉␉␉if (generate_cstates && (new_ssdt[ssdtotal_number] = generate_cst_ssdt(fadt_mod))) {␊ |
776 | ␉␉␉␉␉␉␉verbose("\tC-States generated\n");␊ |
777 | ␉␉␉␉␉␉␉generate_cstates = false; // Generate SSDT only once!␊ |
778 | ␉␉␉␉␉␉␉ssdtotal_number++;␊ |
779 | ␉␉␉␉␉␉}␊ |
780 | ␊ |
781 | ␉␉␉␉␉␉// Generating _PSS SSDT␊ |
782 | ␉␉␉␉␉␉if (generate_pstates && (new_ssdt[ssdtotal_number] = generate_pss_ssdt((void *)fadt_mod->DSDT))) {␊ |
783 | ␉␉␉␉␉␉␉verbose("\tP-States generated\n");␊ |
784 | ␉␉␉␉␉␉␉generate_pstates = false; // Generate SSDT only once!␊ |
785 | ␉␉␉␉␉␉␉ssdtotal_number++;␊ |
786 | ␉␉␉␉␉␉}␊ |
787 | ␉␉␉␉␉␉continue;␊ |
788 | ␉␉␉␉␉}␊ |
789 | ␊ |
790 | verbose(": using.\n");␊ |
791 | xsdt_entries[i - dropoffset] = xsdt_entries[i];␊ |
792 | ␉␉␉␉}␊ |
793 | ␊ |
794 | // For moded xsdt calculate new lenght␊ |
795 | if (new_ecdt)␊ |
796 | xsdt_mod->Length += 8*ssdtotal_number - 8*dropoffset + 8; // custom - dropped + ECDT␊ |
797 | else␊ |
798 | xsdt_mod->Length += 8*ssdtotal_number - 8*dropoffset;␊ |
799 | // Allocate xsdt in Kernel memory area␊ |
800 | ␉␉␉␉struct acpi_2_xsdt *xsdt_copy = (struct acpi_2_xsdt *)AllocateKernelMemory(xsdt_mod->Length);␊ |
801 | ␉␉␉␉memcpy(xsdt_copy, xsdt_mod, xsdt_mod->Length); // should be: rsdt_mod->Length - 8*ssdtotal_number - 8 but don't care␊ |
802 | ␉␉␉␉free(xsdt_mod);␊ |
803 | xsdt_mod = xsdt_copy;␊ |
804 | ␉␉␉␉rsdp_mod->XsdtAddress = (uint64_t)xsdt_mod;␊ |
805 | ␉␉␉␉xsdt_entries_num = (xsdt_mod->Length - sizeof(struct acpi_2_xsdt)) / 8;␊ |
806 | ␉␉␉␉xsdt_entries = (uint64_t *)(xsdt_mod + 1);␊ |
807 | ␊ |
808 | ␉␉␉␉// Mozodojo: Insert additional SSDTs into XSDT␊ |
809 | for (j = 0; j < ssdtotal_number; j++) {␊ |
810 | xsdt_entries[i-dropoffset+j] = (uint64_t)new_ssdt[j];␊ |
811 | }␊ |
812 | verbose("ACPIpatcher: added %d custom SSDT table%s into XSDT.\n", ssdtotal_number, (ssdtotal_number != 1) ? "s" : "");␊ |
813 | ␊ |
814 | ␉␉␉␉if (new_ecdt) {␊ |
815 | ␉␉␉␉␉xsdt_entries[i - dropoffset + j] = (uint64_t)new_ecdt;␊ |
816 | ␉␉␉␉␉verbose("ACPIpatcher: added custom table %s@%016X into XSDT.\n", "ECDT", new_ecdt);␊ |
817 | ␉␉␉␉}␊ |
818 | ␊ |
819 | ␉␉␉␉// Correct the checksum of XSDT␊ |
820 | ␉␉␉␉verbose("ACPIpatcher: modified XSDT@%016X, length=%d. Checksum: old=%d, ", xsdt_mod, xsdt_mod->Length, xsdt_mod->Checksum);␊ |
821 | xsdt_mod->Checksum=0;␊ |
822 | xsdt_mod->Checksum=256-checksum8(xsdt_mod, xsdt_mod->Length);␊ |
823 | verbose("new=%d.\n", xsdt_mod->Checksum);␊ |
824 | ␉␉␉} else {␊ |
825 | ␉␉␉drop_xsdt:␊ |
826 | ␉␉␉␉/*FIXME: Now we just hope that if MacOS doesn't find XSDT it reverts to RSDT. ␊ |
827 | ␉␉␉␉ * A Better strategy would be to generate␊ |
828 | ␉␉␉␉ */␊ |
829 | verbose("not found or incorrect!\n");␊ |
830 | ␉␉␉␉rsdp_mod->XsdtAddress=0xffffffffffffffffLL;␊ |
831 | ␉␉␉}␊ |
832 | ␊ |
833 | if (gVerboseMode) pause("");␊ |
834 | ␉␉}␊ |
835 | ␊ |
836 | ␉␉// Correct the checksum of RSDP␊ |
837 | ␉␉verbose("ACPIpatcher: modified RSDP@%08X, checksum: old=%d, ", rsdp_mod, rsdp_mod->Checksum);␊ |
838 | ␉␉rsdp_mod->Checksum=0;␊ |
839 | ␉␉rsdp_mod->Checksum=256-checksum8(rsdp_mod, 20);␊ |
840 | ␉␉verbose("new=%d", rsdp_mod->Checksum);␊ |
841 | ␊ |
842 | ␉␉if (version) {␊ |
843 | ␉␉␉verbose("; extended checksum: old=%d, ", rsdp_mod->ExtendedChecksum);␊ |
844 | ␉␉␉rsdp_mod->ExtendedChecksum=0;␊ |
845 | ␉␉␉rsdp_mod->ExtendedChecksum=256-checksum8(rsdp_mod,rsdp_mod->Length);␊ |
846 | ␉␉␉verbose("new=%d.\n", rsdp_mod->ExtendedChecksum);␊ |
847 | ␉␉} else {␊ |
848 | verbose(".\n");␊ |
849 | }␊ |
850 | ␊ |
851 | ␉␉if (version) {␊ |
852 | ␉␉␉acpi20_p = (uint64_t)(uint32_t)rsdp_mod; // efi configuration table pointer to ACPI_20 RSDP␊ |
853 | acpi10_p = acpi20_p - 20; // efi configuration table pointer to ACPI RSDP␊ |
854 | memcpy((struct acpi_2_rsdp *)(uint32_t)acpi10_p, (struct acpi_2_rsdp *)(uint32_t)acpi20_p, 20);␊ |
855 | ␉␉␉//addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");␊ |
856 | ␉␉} else {␊ |
857 | ␉␉␉acpi10_p = (uint64_t)(uint32_t)rsdp_mod; // efi configuration table pointer to ACPI RSDP␊ |
858 | ␉␉␉//addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");␊ |
859 | ␉␉}␊ |
860 | ␊ |
861 | verbose("ACPIpatcher: acpi version %d.0 patching finished.\n", version + 1);␊ |
862 | ␉}␊ |
863 | ␊ |
864 | #if DEBUG_ACPI␊ |
865 | pause("[DEBUG ACPI] ");␊ |
866 | #else␊ |
867 | if (gVerboseMode) pause("");␊ |
868 | #endif␊ |
869 | ␊ |
870 | ␉return 1;␊ |
871 | }␊ |
872 | ␊ |
873 | struct acpi_2_rsdp *getRSDPaddress()␊ |
874 | {␊ |
875 | bool found = false;␊ |
876 | /* Before searching the BIOS space we are supposed to search the first 1K of the EBDA */␊ |
877 | ␉EBDA_RANGE_START = (uint32_t)swapUint16(*(uint16_t *)BDA_EBDA_START) << 4;␊ |
878 | verbose("getRSDPaddress: scanning EBDA [%08X:%08X] for RSDP... ", EBDA_RANGE_START, EBDA_RANGE_END);␊ |
879 | void *rsdp_addr = (void*)EBDA_RANGE_START;␊ |
880 | ␉for (; rsdp_addr <= (void*)EBDA_RANGE_END; rsdp_addr += 1) {␊ |
881 | ␉␉if (*(uint64_t *)rsdp_addr == ACPI_SIGNATURE_UINT64_LE) {␊ |
882 | found = true;␊ |
883 | break;␊ |
884 | ␉␉}␊ |
885 | ␉}␊ |
886 | ␊ |
887 | if (!found) {␊ |
888 | verbose("Nothing found.\n");␊ |
889 | verbose("getRSDPaddress: scanning BIOS area [%08X:%08X] for RSDP... ", ACPI_RANGE_START, ACPI_RANGE_END);␊ |
890 | rsdp_addr = (void*)ACPI_RANGE_START;␊ |
891 | for (; rsdp_addr <= (void*)ACPI_RANGE_END; rsdp_addr += 16) {␊ |
892 | if (*(uint64_t *)rsdp_addr == ACPI_SIGNATURE_UINT64_LE) {␊ |
893 | found = true;␊ |
894 | break;␊ |
895 | }␊ |
896 | }␊ |
897 | }␊ |
898 | ␊ |
899 | if (found) {␊ |
900 | verbose("Found @0%08X, Rev.: %d.0).\n", rsdp_addr, ((struct acpi_2_rsdp *)rsdp_addr)->Revision + 1);␊ |
901 | uint8_t csum = checksum8(rsdp_addr, 20);␊ |
902 | if (csum == 0) {␊ |
903 | if (((struct acpi_2_rsdp *)rsdp_addr)->Revision == 0) return rsdp_addr;␊ |
904 | csum = checksum8(rsdp_addr, sizeof(struct acpi_2_rsdp));␊ |
905 | if (csum == 0) return rsdp_addr;␊ |
906 | else verbose("getRSDPaddress: RSDP extended checksum incorrect: %d.\n", csum);␊ |
907 | } else verbose("getRSDPaddress: RSDP checksum incorrect: %d.\n", csum);␊ |
908 | } else verbose("Nothing found.\n");␊ |
909 | ␊ |
910 | ␉return NULL;␊ |
911 | }␊ |
912 | |