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 | void *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/ACPI/%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), "/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 | snprintf(dirSpec, sizeof(dirSpec), "bt(0,0)/Extra/Acpi/%s", filename);␊ |
181 | fd = open(dirSpec, 0);␊ |
182 | if (fd < 0)␊ |
183 | {␊ |
184 | snprintf(dirSpec, sizeof(dirSpec), "bt(0,0)/Extra/%s", filename);␊ |
185 | fd = open(dirSpec, 0);␊ |
186 | if (fd < 0)␊ |
187 | {␊ |
188 | // NOT FOUND:␊ |
189 | dirSpec[0] = 0;␊ |
190 | }␊ |
191 | }␊ |
192 | }␊ |
193 | }␊ |
194 | }␊ |
195 | }␊ |
196 | ␉}␊ |
197 | ␊ |
198 | ␉if (outDirspec) *outDirspec = dirSpec;␊ |
199 | ␉return fd;␊ |
200 | }␊ |
201 | ␊ |
202 | void *loadACPITable (const char *filename)␊ |
203 | {␊ |
204 | ␉void *tableAddr;␊ |
205 | ␉const char *dirspec = NULL;␊ |
206 | ␊ |
207 | ␉int fd = search_and_get_acpi_fd(filename, &dirspec);␊ |
208 | ␊ |
209 | ␉if (fd >= 0)␊ |
210 | ␉{␊ |
211 | ␉␉tableAddr = (void *)AllocateKernelMemory(file_size(fd));␊ |
212 | ␉␉if (tableAddr)␊ |
213 | ␉␉{␊ |
214 | ␉␉␉if (read(fd, tableAddr, file_size(fd)) != file_size(fd))␊ |
215 | ␉␉␉{␊ |
216 | ␉␉␉␉verbose("loadACPITable: Couldn't read table from: %s.\n", dirspec);␊ |
217 | ␉␉␉␉free(tableAddr);␊ |
218 | ␉␉␉␉close(fd);␊ |
219 | ␉␉␉␉return NULL;␊ |
220 | ␉␉␉}␊ |
221 | ␉␉␉//verbose("ACPIpatcher: Table %s read and stored at: 0x%08X\n", dirspec, tableAddr);␊ |
222 | ␉␉␉close(fd);␊ |
223 | ␉␉␉return tableAddr;␊ |
224 | ␉␉}␊ |
225 | ␉␉close(fd);␊ |
226 | ␉␉verbose("loadACPITable: Couldn't allocate memory for table: %s.\n", dirspec);␊ |
227 | ␉}␊ |
228 | ␊ |
229 | ␉return NULL;␊ |
230 | }␊ |
231 | ␊ |
232 | struct acpi_2_fadt *patch_fadt(struct acpi_2_fadt *fadt, struct acpi_2_dsdt *new_dsdt)␊ |
233 | {␊ |
234 | ␉// extern void setupSystemType();␊ |
235 | ␊ |
236 | ␉struct acpi_2_fadt *fadt_mod = NULL;␊ |
237 | ␉bool fadt_rev2_needed = false;␊ |
238 | ␉bool fix_restart = false;␊ |
239 | ␉bool fix_restart_ps2 = false;␊ |
240 | ␉int value = 1;␊ |
241 | ␉static bool ver_20 = false;␊ |
242 | ␊ |
243 | ␉// Restart Fix␊ |
244 | ␉if (Platform.CPU.Vendor == CPUID_VENDOR_INTEL) { // Intel=0x756E6547␊ |
245 | ␉␉fix_restart = true;␊ |
246 | ␉␉fix_restart_ps2 = false;␊ |
247 | ␉␉if ( getBoolForKey(kPS2RestartFix, &fix_restart_ps2, &bootInfo->chameleonConfig) && fix_restart_ps2) {␊ |
248 | ␉␉␉fix_restart = true;␊ |
249 | ␉␉}␊ |
250 | ␉␉else␊ |
251 | ␉␉{␊ |
252 | ␉␉␉getBoolForKey(kRestartFix, &fix_restart, &bootInfo->chameleonConfig);␊ |
253 | ␉␉}␊ |
254 | ␉}␊ |
255 | ␉else␊ |
256 | ␉{␊ |
257 | ␉␉verbose("\tNot an Intel platform, FACP Restart Fix will not be applied!\n");␊ |
258 | ␉␉fix_restart = false;␊ |
259 | ␉}␊ |
260 | ␊ |
261 | ␉if (fix_restart)␊ |
262 | ␉{␊ |
263 | ␉␉fadt_rev2_needed = true;␊ |
264 | ␉}␊ |
265 | ␊ |
266 | ␉// Allocate new fadt table␊ |
267 | ␉if ((fadt->Length < 0x84) && fadt_rev2_needed)␊ |
268 | ␉{␊ |
269 | ␉␉fadt_mod = (struct acpi_2_fadt *)AllocateKernelMemory(0x84);␊ |
270 | ␉␉memcpy(fadt_mod, fadt, fadt->Length);␊ |
271 | ␉␉fadt_mod->Length = 0x84;␊ |
272 | ␉␉fadt_mod->Revision = 0x02; // FACP rev 2 (ACPI 1.0B MS extensions)␊ |
273 | ␉}␊ |
274 | ␉else␊ |
275 | ␉{␊ |
276 | ␉␉fadt_mod = (struct acpi_2_fadt *)AllocateKernelMemory(fadt->Length);␊ |
277 | ␉␉memcpy(fadt_mod, fadt, fadt->Length);␊ |
278 | ␉}␊ |
279 | ␉verbose("\tNew FACP loaded @%08X, length=%d\n", (uint32_t)fadt_mod, fadt_mod->Length);␊ |
280 | ␊ |
281 | ␉// Bungo: Determine PM Profile␊ |
282 | ␉verbose("\tPM Profile=0x%02X", fadt_mod->PM_Profile);␊ |
283 | ␉if (getIntForKey(kSystemType, &value, &bootInfo->chameleonConfig))␊ |
284 | ␉{␊ |
285 | ␉␉verbose(", overriding with: 0x%02X.\n", (uint8_t)value);␊ |
286 | ␉␉fadt_mod->PM_Profile = (uint8_t)value; // user has overriden the PM Profile so take care of it in FACP␊ |
287 | ␉}␊ |
288 | ␉else␊ |
289 | ␉{␊ |
290 | ␉␉switch (fadt_mod->PM_Profile) { // check if PM Profile is correct (1..3)␊ |
291 | ␉␉␉case 1:␊ |
292 | ␉␉␉case 2:␊ |
293 | ␉␉␉case 3:␊ |
294 | ␉␉␉␉verbose(", using.\n");␊ |
295 | ␉␉␉␉break;␊ |
296 | ␉␉␉default:␊ |
297 | ␉␉␉␉// use SMBIOS chassisType to determine PM Profile (saved previously for us)␊ |
298 | ␉␉␉␉verbose(", expected value: 1, 2 or 3, setting to 0x%02X.\n", Platform.Type);␊ |
299 | ␉␉␉␉fadt_mod->PM_Profile = Platform.Type; // take care of modified FACP's PM Profile entry␊ |
300 | ␉␉␉␉break;␊ |
301 | ␉␉}␊ |
302 | ␉}␊ |
303 | ␉Platform.Type = fadt_mod->PM_Profile; // Save fixed PM Profile (system-type)␊ |
304 | ␊ |
305 | /* Bungo: Moved into fake_efi.c␊ |
306 | ␉// Setup system-type: We now have to write the systemm-type in ioregs: we cannot do it before in setupDeviceTree()␊ |
307 | ␉// because we need to take care of FACP original content, if it is correct.␊ |
308 | ␉setupSystemType();␊ |
309 | */␊ |
310 | ␉// Patch FACP to fix restart␊ |
311 | ␉if (fix_restart)␊ |
312 | ␉{␊ |
313 | ␉␉if (fix_restart_ps2)␊ |
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␉␉= 0x64;␉␉// Address of the register␊ |
321 | ␉␉␉fadt_mod->Reset_Value␉␉= 0xfe;␉␉// Value to write to reset the system␊ |
322 | ␉␉␉verbose("\tFACP PS2 Restart Fix applied!\n");␊ |
323 | ␉␉}␊ |
324 | ␉␉else␊ |
325 | ␉␉{␊ |
326 | ␉␉␉fadt_mod->Flags|= 0x400;␉␉␉// Reset register supported␊ |
327 | ␉␉␉fadt_mod->Reset_SpaceID␉␉= 0x01;␉␉// System I/O␊ |
328 | ␉␉␉fadt_mod->Reset_BitWidth␉= 0x08;␉␉// 1 byte␊ |
329 | ␉␉␉fadt_mod->Reset_BitOffset␉= 0x00;␉␉// Offset 0␊ |
330 | ␉␉␉fadt_mod->Reset_AccessWidth␉= 0x01;␉␉// Byte access␊ |
331 | ␉␉␉fadt_mod->Reset_Address␉␉= 0x0cf9;␉// Address of the register␊ |
332 | ␉␉␉fadt_mod->Reset_Value␉␉= 0x06;␉␉// Value to write to reset the system␊ |
333 | ␉␉␉verbose("\tFACP Restart Fix applied!\n");␊ |
334 | ␉␉}␊ |
335 | ␉}␊ |
336 | ␉else␊ |
337 | ␉{␊ |
338 | ␉␉//verbose("\tRestart Fix: No.\n");␊ |
339 | ␉}␊ |
340 | ␊ |
341 | ␉// Bungo: FACS table fix and load␊ |
342 | ␉verbose("\tOEM table FACS@%08X, length=%d, ", fadt_mod->FACS, ((struct acpi_2_facs *)fadt_mod->FACS)->Length);␊ |
343 | ␉if ((fadt_mod->FACS > 0) && (fadt_mod->FACS < 0xFFFFFFFF) && (((struct acpi_2_facs *)fadt_mod->FACS)->Length >= 64))␊ |
344 | ␉{␊ |
345 | ␉␉verbose("using.\n");␊ |
346 | ␉}␊ |
347 | ␉else␊ |
348 | ␉{␊ |
349 | ␉␉verbose(" Incorrect!\n");␊ |
350 | ␉}␊ |
351 | ␉if (ver_20 && (((uint32_t)(&(fadt_mod->X_FACS)) - (uint32_t)fadt_mod + 8) <= fadt_mod->Length))␊ |
352 | ␉{␊ |
353 | ␉␉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);␊ |
354 | ␉␉if (fadt_mod->FACS != fadt_mod->X_FACS)␊ |
355 | ␉␉{␊ |
356 | ␉␉␉verbose("differes from FACS - fixing");␊ |
357 | ␉␉␉if ((fadt_mod->X_FACS > 0) && (fadt_mod->X_FACS < 0xFFFFFFFF) && (((struct acpi_2_facs *)(uint32_t)fadt_mod->X_FACS)->Length >= 64))␊ |
358 | ␉␉␉{␊ |
359 | ␉␉␉␉// Bungo: in my case only from X_FACS loading correct table (64 bytes) into IOReg␊ |
360 | ␉␉␉␉fadt_mod->FACS = (uint32_t)fadt_mod->X_FACS;␊ |
361 | ␉␉␉}␊ |
362 | ␉␉␉else␊ |
363 | ␉␉␉{␊ |
364 | ␉␉␉␉fadt_mod->X_FACS = (uint64_t)fadt_mod->FACS;␊ |
365 | ␉␉␉}␊ |
366 | ␉␉␉verbose(" \tUsing FACS@%08X = X_FACS@%08X\n", fadt_mod->FACS, (uint32_t)fadt_mod->X_FACS);␊ |
367 | ␉␉}␊ |
368 | ␉␉else␊ |
369 | ␉␉{␊ |
370 | ␉␉␉verbose("using.\n");␊ |
371 | ␉␉}␊ |
372 | ␉}␊ |
373 | ␊ |
374 | ␉// Bungo: Save Hardware Signature (machine-signature)␊ |
375 | ␉if ((fadt_mod->FACS > 0) && (fadt_mod->FACS < 0xFFFFFFFF) && (((struct acpi_2_facs *)fadt_mod->FACS)->Length >= 64))␊ |
376 | ␉{␊ |
377 | ␉␉Platform.HWSignature = ((struct acpi_2_facs *)fadt_mod->FACS)->HWSignature;␊ |
378 | ␉␉verbose("\tHardware Signature=0x%08X, using.\n", Platform.HWSignature);␊ |
379 | ␉}␊ |
380 | ␉else␊ |
381 | ␉{␊ |
382 | ␉␉Platform.HWSignature = 0;␊ |
383 | ␉␉verbose("\tFixing Hardware Signature=0x%08X.\n", Platform.HWSignature);␊ |
384 | ␉}␊ |
385 | ␊ |
386 | ␉verbose("\tOEM table DSDT@%08X, length=%d, %susing.\n", fadt_mod->DSDT, ((struct acpi_2_dsdt *)fadt_mod->DSDT)->Length, new_dsdt ? "not " : "");␊ |
387 | ␉if (ver_20 && (((uint32_t)(&(fadt_mod->X_DSDT)) - (uint32_t)fadt_mod + 8) <= fadt_mod->Length))␊ |
388 | ␉{␊ |
389 | ␉␉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 " : "");␊ |
390 | ␉}␊ |
391 | ␉// Patch DSDT address if we have loaded DSDT.aml␊ |
392 | ␉if (new_dsdt)␊ |
393 | ␉{␊ |
394 | fadt_mod->DSDT = (uint32_t)new_dsdt;␊ |
395 | verbose("\tFACP uses custom DSDT@%08X", fadt_mod->DSDT);␊ |
396 | ␉␉if (ver_20 && (((uint32_t)(&(fadt_mod->X_DSDT)) - (uint32_t)fadt_mod + 8) <= fadt_mod->Length))␊ |
397 | ␉␉{␊ |
398 | ␉␉␉fadt_mod->X_DSDT = (uint64_t)new_dsdt;␊ |
399 | ␉␉␉verbose(" / X_DSDT@%08X%08X", (uint32_t)(fadt_mod->X_DSDT >> 32), (uint32_t)(fadt_mod->X_DSDT & 0xFFFFFFFF));␊ |
400 | ␉␉}␊ |
401 | ␉␉verbose(", length=%d\n", ((struct acpi_2_dsdt *)fadt_mod->DSDT)->Length);␊ |
402 | ␉}␊ |
403 | ␊ |
404 | ␉// Correct the checksum␊ |
405 | ␉fadt_mod->Checksum=0;␊ |
406 | ␉fadt_mod->Checksum=256-checksum8(fadt_mod, fadt_mod->Length);␊ |
407 | ␊ |
408 | ␉ver_20 = TRUE;␊ |
409 | ␉return fadt_mod;␊ |
410 | }␊ |
411 | // Bung: Unused␊ |
412 | /* Setup ACPI without replacing DSDT.␊ |
413 | int setupAcpiNoMod()␊ |
414 | {␊ |
415 | //␉addConfigurationTable(&gEfiAcpiTableGuid, getAddressOfAcpiTable(), "ACPI");␊ |
416 | //␉addConfigurationTable(&gEfiAcpi20TableGuid, getAddressOfAcpi20Table(), "ACPI_20");␊ |
417 | ␉// XXX aserebln why uint32 cast if pointer is uint64 ?␊ |
418 | ␉acpi10_p = (uint64_t)(uint32_t)getAddressOfAcpiTable();␊ |
419 | ␉acpi20_p = (uint64_t)(uint32_t)getAddressOfAcpi20Table();␊ |
420 | ␉// addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");␊ |
421 | ␉if(acpi20_p)␊ |
422 | ␉{␊ |
423 | ␉␉// addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");␊ |
424 | ␉}␊ |
425 | ␉else␊ |
426 | ␉{␊ |
427 | ␉␉DBG("ACPIpatcher: version 2.0 not found.\n");␊ |
428 | ␉}␊ |
429 | ␉return 1;␊ |
430 | }␊ |
431 | */␊ |
432 | /* Setup ACPI. Replace DSDT if DSDT.aml is found */␊ |
433 | int setupAcpi(void)␊ |
434 | {␊ |
435 | ␉int version;␊ |
436 | ␉const char *filename;␊ |
437 | ␉char dirSpec[128];␊ |
438 | ␉int len = 0;␊ |
439 | ␊ |
440 | ␉// always reset cpu count to 0 when injecting new acpi␊ |
441 | ␉acpi_cpu_count = 0;␊ |
442 | ␊ |
443 | ␉verbose("\nACPIpatcher: Start patching...\n");␊ |
444 | ␊ |
445 | ␉if (new_dsdt != NULL)␊ |
446 | ␉{␊ |
447 | ␉␉verbose("ACPIpatcher: custom table DSDT already loaded @%08X, length=%d, using.\n", new_dsdt, ((struct acpi_2_header *)new_dsdt)->Length);␊ |
448 | ␉}␊ |
449 | ␉else␊ |
450 | ␉{␊ |
451 | ␉␉// Try using the file specified with the DSDT option␊ |
452 | ␉␉if (getValueForKey(kDSDT, &filename, &len, &bootInfo->chameleonConfig) && len)␊ |
453 | ␉␉{␊ |
454 | ␉␉␉snprintf(dirSpec, sizeof(dirSpec), filename);␊ |
455 | ␉␉}␊ |
456 | ␉␉else␊ |
457 | ␉␉{␊ |
458 | ␉␉␉sprintf(dirSpec, "DSDT.aml");␊ |
459 | ␉␉}␊ |
460 | ␊ |
461 | ␉␉verbose("ACPIpatcher: attempting to load custom table DSDT...\n");␊ |
462 | ␉␉if ((new_dsdt = loadACPITable(dirSpec)))␊ |
463 | ␉␉{␊ |
464 | ␉␉␉verbose("ACPIpatcher: custom table DSDT loaded @%08X, length=%d.\n", new_dsdt, ((struct acpi_2_header *)new_dsdt)->Length);␊ |
465 | ␉␉}␊ |
466 | ␉␉else␊ |
467 | ␉␉{␊ |
468 | ␉␉␉//verbose("ACPIpatcher: custom DSDT not found!.\n");␊ |
469 | ␉␉}␊ |
470 | ␉}␊ |
471 | ␊ |
472 | ␉/* Try using the file specified with the DSDT option␊ |
473 | ␉if (getValueForKey(kDSDT, &filename, &len, &bootInfo->chameleonConfig))␊ |
474 | ␉{␊ |
475 | ␉␉snprintf(dirSpec, sizeof(dirSpec), filename);␊ |
476 | ␉}␊ |
477 | ␉else␊ |
478 | ␉{␊ |
479 | ␉␉sprintf(dirSpec, "DSDT.aml");␊ |
480 | ␉␉//DBG("dirSpec, DSDT.aml");␊ |
481 | ␉}␊ |
482 | ␊ |
483 | ␉// Load replacement DSDT␊ |
484 | ␉new_dsdt = loadACPITable(dirSpec);␊ |
485 | */␊ |
486 | ␊ |
487 | ␉// Load ECDT table␊ |
488 | ␉if (new_ecdt != NULL)␊ |
489 | ␉{␊ |
490 | ␉␉verbose("ACPIpatcher: custom table ECDT already loaded @%08X, length=%d, using.\n", new_ecdt, ((struct acpi_2_header *)new_ecdt)->Length);␊ |
491 | ␉}␊ |
492 | ␉else␊ |
493 | ␉{␊ |
494 | ␉␉sprintf(dirSpec, "ECDT.aml");␊ |
495 | ␉␉verbose("ACPIpatcher: attempting to load custom table ECDT...\n");␊ |
496 | ␉␉if ((new_ecdt = loadACPITable(dirSpec)))␊ |
497 | ␉␉{␊ |
498 | ␉␉␉verbose("ACPIpatcher: custom table ECDT loaded @%08X, length=%d.\n", new_ecdt, ((struct acpi_2_header *)new_ecdt)->Length);␊ |
499 | ␉␉}␊ |
500 | ␉␉else␊ |
501 | ␉␉{␊ |
502 | ␉␉␉//verbose("ACPIpatcher: custom ECDT not found!.\n");␊ |
503 | ␉␉}␊ |
504 | ␉}␊ |
505 | ␊ |
506 | ␉// Mozodojo: Load additional SSDTs␊ |
507 | ␉struct acpi_2_ssdt *new_ssdt[32]; // 26 custom + 4 subssdt + 2 for pss & cst␊ |
508 | ␉int ssdtotal_number = 0;␊ |
509 | ␉{␊ |
510 | ␉␉int i;␊ |
511 | ␉␉for (i = 0; i < 26; i++)␊ |
512 | ␉␉{␊ |
513 | ␉␉␉//char filename[512];␊ |
514 | ␊ |
515 | ␉␉␉sprintf(dirSpec, (i > 0)? "SSDT-%d.aml":"SSDT.aml", i);␊ |
516 | ␊ |
517 | ␉␉␉if ((new_ssdt[ssdtotal_number] = loadACPITable(dirSpec)))␊ |
518 | ␉␉␉{␊ |
519 | ␉␉␉␉verbose("ACPIpatcher: custom table %s loaded @%08X, length=%d\n", dirSpec, new_ssdt[ssdtotal_number], new_ssdt[ssdtotal_number]->Length);␊ |
520 | ␉␉␉␉ssdtotal_number++;␊ |
521 | ␉␉␉}␊ |
522 | ␉␉␉else␊ |
523 | ␉␉␉{␊ |
524 | ␉␉␉␉//verbose("ACPIpatcher: custom table '%s' not found.\n", filename);␊ |
525 | ␉␉␉␉// Bungo: load up to 26 custom tables enabled now␊ |
526 | ␉␉␉␉//break;␊ |
527 | ␉␉␉}␊ |
528 | ␉␉}␊ |
529 | ␉}␊ |
530 | ␊ |
531 | ␉// Mozodojo: going to patch FACP and load SSDTs even if DSDT.aml is not present␊ |
532 | ␉/*if (!new_dsdt)␊ |
533 | ␉{␊ |
534 | ␉␉return setupAcpiNoMod();␊ |
535 | ␉}*/␊ |
536 | ␊ |
537 | ␉// SSDT options␊ |
538 | ␉bool drop_ssdt = false, generate_pstates = false, generate_cstates = false;␊ |
539 | ␊ |
540 | ␉getBoolForKey(kDropSSDT, &drop_ssdt, &bootInfo->chameleonConfig);␊ |
541 | ␉getBoolForKey(kGeneratePStates, &generate_pstates, &bootInfo->chameleonConfig);␊ |
542 | ␉getBoolForKey(kGenerateCStates, &generate_cstates, &bootInfo->chameleonConfig);␊ |
543 | ␉verbose("ACPIpatcher: drop SSDT tables: %s.\n", drop_ssdt ? "Yes" : "No");␊ |
544 | ␉verbose("ACPIpatcher: generate P-States: %s.\n", generate_pstates ? "Yes" : "No");␊ |
545 | ␉verbose("ACPIpatcher: generate C-States: %s.\n", generate_cstates ? "Yes" : "No");␊ |
546 | ␊ |
547 | ␉bool getSubSSDT = !generate_pstates && !generate_cstates;␊ |
548 | ␊ |
549 | ␉// Do the same procedure for both versions of ACPI␊ |
550 | ␉for (version = 0; version < 2; version++)␊ |
551 | ␉{␊ |
552 | ␉␉struct acpi_2_rsdp *rsdp, *rsdp_mod;␊ |
553 | ␉␉struct acpi_2_rsdt *rsdt, *rsdt_mod;␊ |
554 | ␉␉struct acpi_2_xsdt *xsdt, *xsdt_mod;␊ |
555 | ␉␉struct acpi_2_fadt *fadt_mod;␊ |
556 | ␉␉uint32_t *rsdt_entries;␊ |
557 | ␉␉uint64_t *xsdt_entries;␊ |
558 | ␊ |
559 | ␉␉// Find original rsdp␊ |
560 | ␉␉rsdp = (struct acpi_2_rsdp *)(version ? getAddressOfAcpi20Table() : getAddressOfAcpiTable());␊ |
561 | ␉␉if (!rsdp)␊ |
562 | ␉␉{␊ |
563 | ␉␉/*␊ |
564 | ␉␉␉if (version)␊ |
565 | ␉␉␉{␊ |
566 | ␉␉␉␉addConfigurationTable(&gEfiAcpi20TableGuid, NULL, "ACPI_20");␊ |
567 | ␉␉␉}␊ |
568 | ␉␉␉else␊ |
569 | ␉␉␉{␊ |
570 | ␉␉␉␉addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI");␊ |
571 | ␉␉␉}␊ |
572 | ␉␉*/␊ |
573 | ␉␉␉verbose("ACPIpatcher: ACPI version %d.0 not found. Not patching.\n", version + 1);␊ |
574 | ␉␉␉continue;␊ |
575 | ␉␉}␊ |
576 | ␊ |
577 | ␉␉int rsdplength = version ? rsdp->Length : 20;␊ |
578 | ␉␉int l = version ? 20 : 0;␊ |
579 | ␉␉verbose("ACPIpatcher: OEM table RSDP@%08X, length=%d. ACPI version %d.0. Patching.\n", rsdp, rsdplength, version + 1);␊ |
580 | ␊ |
581 | ␉␉/* FIXME: no check that memory allocation succeeded ␊ |
582 | ␉␉ * Copy and patch RSDP, RSDT, XSDT and FADT␊ |
583 | ␉␉ * For more info see ACPI Specification pages 110 and following␊ |
584 | ␉␉ */␊ |
585 | ␊ |
586 | ␉␉rsdp_mod = (struct acpi_2_rsdp *)(l + AllocateKernelMemory(l + rsdplength));␊ |
587 | ␉␉memcpy(rsdp_mod, rsdp, rsdplength);␊ |
588 | ␊ |
589 | ␉␉rsdt = (struct acpi_2_rsdt *)rsdp->RsdtAddress;␊ |
590 | ␉␉verbose("ACPIpatcher: OEM table RSDT@%08X, length=%d, ", rsdp->RsdtAddress, rsdt->Length);␊ |
591 | ␊ |
592 | ␉␉if ((rsdp->RsdtAddress > 0) && (rsdp->RsdtAddress < 0xFFFFFFFF) && (rsdt->Length < 0x10000))␊ |
593 | ␉␉{␊ |
594 | ␉␉␉verbose("using.\n");␊ |
595 | ␉␉␉int rsdt_entries_num;␊ |
596 | ␉␉␉int dropoffset = 0, i, j;␊ |
597 | ␊ |
598 | ␉␉␉// mozo: using malloc cos I didn't found how to free already allocated kernel memory␊ |
599 | ␉␉␉rsdt_mod = (struct acpi_2_rsdt *)malloc(rsdt->Length);␊ |
600 | ␉␉␉memcpy(rsdt_mod, rsdt, rsdt->Length);␊ |
601 | ␉␉␉rsdp_mod->RsdtAddress = (uint32_t)rsdt_mod;␊ |
602 | ␉␉␉rsdt_entries_num = (rsdt_mod->Length - sizeof(struct acpi_2_rsdt)) / 4;␊ |
603 | ␉␉␉rsdt_entries = (uint32_t *)(rsdt_mod + 1);␊ |
604 | ␊ |
605 | ␉␉␉for (i = 0; i < rsdt_entries_num; i++)␊ |
606 | ␉␉␉{␊ |
607 | ␉␉␉␉struct acpi_2_header *oemTable = (struct acpi_2_header *)rsdt_entries[i];␊ |
608 | ␉␉␉␉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);␊ |
609 | ␊ |
610 | ␉␉␉␉if (!(rsdt_entries[i] > 0) || !(rsdt_entries[i] < 0xFFFFFFFF))␊ |
611 | ␉␉␉␉{␊ |
612 | ␉␉␉␉␉verbose("Incorrect! Dropping.\n");␊ |
613 | ␉␉␉␉␉dropoffset++;␊ |
614 | ␉␉␉␉␉continue;␊ |
615 | ␉␉␉␉}␊ |
616 | ␊ |
617 | ␉␉␉␉if (tableSign(oemTable, "SSDT"))␊ |
618 | ␉␉␉␉{␊ |
619 | ␉␉␉␉␉if (drop_ssdt)␊ |
620 | ␉␉␉␉␉{␊ |
621 | ␉␉␉␉␉␉verbose("dropping.\n");␊ |
622 | ␉␉␉␉␉␉dropoffset++;␊ |
623 | ␉␉␉␉␉}␊ |
624 | ␉␉␉␉␉else␊ |
625 | ␉␉␉␉␉{␊ |
626 | ␉␉␉␉␉␉verbose("using.\n");␊ |
627 | ␉␉␉␉␉␉rsdt_entries[i-dropoffset] = rsdt_entries[i];␊ |
628 | ␉␉␉␉␉␉// get rest of ssdt tables from inside ssdt_pmref␊ |
629 | ␉␉␉␉␉␉if (getSubSSDT) { // prevent from extracting originals if user choosed generating PSS and/or CSS tables␊ |
630 | ␉␉␉␉␉␉␉struct ssdt_pmref *subSSDT = (struct ssdt_pmref *)(rsdt_entries[i] + sizeof(struct acpi_2_header) + 15);␊ |
631 | ␉␉␉␉␉␉␉uint8_t tabNum = *((uint8_t *)subSSDT - 2) / 3; // e.g Name (SSDT, Package (0x0C) -> 0x0C / 3 = number of sub SSDTs␊ |
632 | ␉␉␉␉␉␉␉for (j = 0; (j < tabNum) && (ssdtotal_number < 30); j++)␊ |
633 | ␉␉␉␉␉␉␉{␊ |
634 | ␉␉␉␉␉␉␉␉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);␊ |
635 | ␉␉␉␉␉␉␉␉if (!(subSSDT[j].addr > 0) || !(subSSDT[j].addr < 0xFFFFFFFF))␊ |
636 | ␉␉␉␉␉␉␉␉{␊ |
637 | ␉␉␉␉␉␉␉␉␉verbose("Incorrect! Dropping.\n");␊ |
638 | ␉␉␉␉␉␉␉␉␉continue;␊ |
639 | ␉␉␉␉␉␉␉␉}␊ |
640 | ␉␉␉␉␉␉␉␉verbose("using.\n");␊ |
641 | ␉␉␉␉␉␉␉␉new_ssdt[ssdtotal_number] = (struct acpi_2_ssdt *)subSSDT[j].addr;␊ |
642 | ␉␉␉␉␉␉␉␉ssdtotal_number++;␊ |
643 | ␉␉␉␉␉␉␉}␊ |
644 | ␉␉␉␉␉␉}␊ |
645 | ␉␉␉␉␉}␊ |
646 | ␉␉␉␉␉continue;␊ |
647 | ␉␉␉␉}␊ |
648 | ␊ |
649 | ␉␉␉␉/* Bungo: According to ACPI Spec. no DSDT in RSDT, so what this for?␊ |
650 | ␊ |
651 | ␉␉␉␉if (tableSign(oemTable, "DSDT"))␊ |
652 | ␉␉␉␉{␊ |
653 | ␉␉␉␉␉if (new_dsdt)␊ |
654 | ␉␉␉␉␉{␊ |
655 | ␉␉␉␉␉␉rsdt_entries[i-dropoffset] = (uint32_t)new_dsdt;␊ |
656 | ␉␉␉␉␉␉verbose("custom table added.\n");␊ |
657 | ␉␉␉␉␉}␊ |
658 | ␉␉␉␉␉continue;␊ |
659 | ␉␉␉␉}␊ |
660 | ␉␉␉␉*/␊ |
661 | ␊ |
662 | // Suggest to drop OEM DSDT here if present, it should be in FACP, if custom DSDT present ocourse␊ |
663 | if (tableSign(oemTable, "DSDT") && new_dsdt)␊ |
664 | {␊ |
665 | verbose("dropping.\n");␊ |
666 | dropoffset++;␊ |
667 | continue;␊ |
668 | }␊ |
669 | // Dropping DMAR (DMA Remapping table) table to fix stuck on "waitForSystemMapper" or "PCI configuration begin" cause nothing wokrked for me␊ |
670 | if (tableSign(oemTable, "DMAR"))␊ |
671 | {␊ |
672 | verbose("dropping.\n");␊ |
673 | dropoffset++;␊ |
674 | continue;␊ |
675 | }␊ |
676 | ␊ |
677 | ␉␉␉␉if (tableSign(oemTable, "ECDT") && new_ecdt)␊ |
678 | ␉␉␉␉{␊ |
679 | ␉␉␉␉␉verbose("dropping.\n");␊ |
680 | ␉␉␉␉␉dropoffset++;␊ |
681 | ␉␉␉␉␉continue;␊ |
682 | ␉␉␉␉}␊ |
683 | ␊ |
684 | ␉␉␉␉if (tableSign(oemTable, "FACP"))␊ |
685 | ␉␉␉␉{␊ |
686 | ␉␉␉␉␉if (oemTable->Length > 0x10000)␊ |
687 | ␉␉␉␉␉{␊ |
688 | ␉␉␉␉␉␉verbose("Incorrect. Not modifying.\n");␊ |
689 | ␉␉␉␉␉␉continue;␊ |
690 | ␉␉␉␉␉}␊ |
691 | ␊ |
692 | ␉␉␉␉␉verbose("patching.\n");␊ |
693 | ␉␉␉␉␉fadt_mod = patch_fadt((struct acpi_2_fadt *)oemTable, new_dsdt);␊ |
694 | ␉␉␉␉␉rsdt_entries[i-dropoffset] = (uint32_t)fadt_mod;␊ |
695 | ␉␉␉␉␉␊ |
696 | ␉␉␉␉␉// Generate _CST SSDT␊ |
697 | ␉␉␉␉␉if (generate_cstates && (new_ssdt[ssdtotal_number] = generate_cst_ssdt(fadt_mod)))␊ |
698 | ␉␉␉␉␉{␊ |
699 | ␉␉␉␉␉␉verbose("\tC-States generated.\n");␊ |
700 | ␉␉␉␉␉␉generate_cstates = false; // Generate SSDT only once!␊ |
701 | ␉␉␉␉␉␉ssdtotal_number++;␊ |
702 | ␉␉␉␉␉}␊ |
703 | ␊ |
704 | ␉␉␉␉␉// Generating _PSS SSDT␊ |
705 | ␉␉␉␉␉if (generate_pstates && (new_ssdt[ssdtotal_number] = generate_pss_ssdt((void*)fadt_mod->DSDT)))␊ |
706 | ␉␉␉␉␉{␊ |
707 | ␉␉␉␉␉␉verbose("\tP-States generated.\n");␊ |
708 | ␉␉␉␉␉␉generate_pstates = false; // Generate SSDT only once!␊ |
709 | ␉␉␉␉␉␉ssdtotal_number++;␊ |
710 | ␉␉␉␉␉}␊ |
711 | ␉␉␉␉␉continue;␊ |
712 | ␉␉␉␉}␊ |
713 | ␊ |
714 | ␉␉␉␉verbose("using.\n");␊ |
715 | ␉␉␉␉rsdt_entries[i-dropoffset] = rsdt_entries[i];␊ |
716 | ␉␉␉}␊ |
717 | ␊ |
718 | ␉␉␉// For moded rsdt calculate new lenght␊ |
719 | rsdt_mod->Length += 4*ssdtotal_number - 4*dropoffset;␊ |
720 | ␉␉␉if (new_ecdt)␊ |
721 | ␉␉␉{␊ |
722 | ␉␉␉␉rsdt_mod->Length += 4; // + ECDT␊ |
723 | ␉␉␉}␊ |
724 | ␊ |
725 | ␉␉␉// Allocate moded rsdt in Kernel memory area␊ |
726 | ␉␉␉struct acpi_2_rsdt *rsdt_copy = (struct acpi_2_rsdt *)AllocateKernelMemory(rsdt_mod->Length);␊ |
727 | ␉␉␉memcpy(rsdt_copy, rsdt_mod, rsdt_mod->Length); // should be rsdt_mod->Length - 4*ssdtotal_number - 4 but don't care␊ |
728 | ␉␉␉free(rsdt_mod);␊ |
729 | ␉␉␉rsdt_mod = rsdt_copy;␊ |
730 | ␉␉␉rsdp_mod->RsdtAddress = (uint32_t)rsdt_mod;␊ |
731 | ␉␉␉rsdt_entries_num = (rsdt_mod->Length-sizeof(struct acpi_2_rsdt)) / 4;␊ |
732 | ␉␉␉rsdt_entries = (uint32_t *)(rsdt_mod + 1);␊ |
733 | ␊ |
734 | ␉␉␉// Mozodojo: Insert additional SSDTs into RSDT␊ |
735 | ␉␉␉for (j = 0; j < ssdtotal_number; j++)␊ |
736 | ␉␉␉{␊ |
737 | ␉␉␉␉rsdt_entries[i-dropoffset+j] = (uint32_t)new_ssdt[j];␊ |
738 | ␉␉␉}␊ |
739 | ␉␉␉verbose("ACPIpatcher: added %d custom SSDT table%s into RSDT.\n", ssdtotal_number, (ssdtotal_number != 1) ? "s" : "");␊ |
740 | ␊ |
741 | ␉␉␉if (new_ecdt)␊ |
742 | ␉␉␉{␊ |
743 | ␉␉␉␉rsdt_entries[i - dropoffset + j] = (uint32_t)new_ecdt;␊ |
744 | ␉␉␉␉verbose("ACPIpatcher: added custom table %s @%08X into RSDT.\n", "ECDT", new_ecdt);␊ |
745 | ␉␉␉}␊ |
746 | ␊ |
747 | ␉␉␉// Correct the checksum of RSDT␊ |
748 | ␉␉␉verbose("ACPIpatcher: modified RSDT@%08X, length=%d. Checksum: old=%d, ", rsdt_mod, rsdt_mod->Length, rsdt_mod->Checksum);␊ |
749 | ␉␉␉rsdt_mod->Checksum=0;␊ |
750 | ␉␉␉rsdt_mod->Checksum=256-checksum8(rsdt_mod,rsdt_mod->Length);␊ |
751 | ␉␉␉verbose("new=%d.\n", rsdt_mod->Checksum);␊ |
752 | ␉␉}␊ |
753 | ␉␉else␊ |
754 | ␉␉{␊ |
755 | ␉␉␉rsdp_mod->RsdtAddress = 0;␊ |
756 | ␉␉␉verbose("Not found or incorrect!\n");␊ |
757 | ␉␉}␊ |
758 | ␉␉verbose("\n");␊ |
759 | ␊ |
760 | #if DEBUG_ACPI␊ |
761 | pause("\n[DEBUG_ACPI] ");␊ |
762 | #endif␊ |
763 | ␊ |
764 | ␉␉if (version)␊ |
765 | ␉␉{␊ |
766 | ␉␉␉// FIXME: handle 64-bit address correctly␊ |
767 | ␉␉␉xsdt = (struct acpi_2_xsdt *)(uint32_t)rsdp->XsdtAddress;␊ |
768 | ␉␉␉verbose("ACPIpatcher: OEM table XSDT@%08X%08X, length=%d, ", (uint32_t)(rsdp->XsdtAddress >> 32), (uint32_t)(rsdp->XsdtAddress & 0xFFFFFFFF), xsdt->Length);␊ |
769 | ␊ |
770 | ␉␉␉if ((rsdp->XsdtAddress > 0) && (rsdp->XsdtAddress < 0xFFFFFFFF) && (xsdt->Length < 0x10000))␊ |
771 | ␉␉␉{␊ |
772 | ␉␉␉␉verbose("using.\n");␊ |
773 | ␉␉␉␉int xsdt_entries_num, i, j;␊ |
774 | ␉␉␉␉int dropoffset = 0;␊ |
775 | ␊ |
776 | ␉␉␉␉// mozo: using malloc cos I didn't found how to free already allocated kernel memory␊ |
777 | ␉␉␉␉xsdt_mod = (struct acpi_2_xsdt *)malloc(xsdt->Length);␊ |
778 | ␉␉␉␉memcpy(xsdt_mod, xsdt, xsdt->Length);␊ |
779 | ␊ |
780 | ␉␉␉␉rsdp_mod->XsdtAddress = (uint64_t)xsdt_mod;␊ |
781 | ␉␉␉␉xsdt_entries_num = (xsdt_mod->Length - sizeof(struct acpi_2_xsdt)) / 8;␊ |
782 | ␉␉␉␉xsdt_entries = (uint64_t *)(xsdt_mod + 1);␊ |
783 | ␊ |
784 | ␉␉␉␉for (i = 0; i < xsdt_entries_num; i++)␊ |
785 | ␉␉␉␉{␊ |
786 | ␉␉␉␉␉struct acpi_2_header *oemTable = (struct acpi_2_header *)(uint32_t)xsdt_entries[i];␊ |
787 | ␉␉␉␉␉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);␊ |
788 | ␊ |
789 | ␉␉␉␉␉if (!(xsdt_entries[i] > 0) || !(xsdt_entries[i] < 0xFFFFFFFF))␊ |
790 | ␉␉␉␉␉{␊ |
791 | ␉␉␉␉␉␉verbose(", Incorrect! Dropping.\n");␊ |
792 | ␉␉␉␉␉␉dropoffset++;␊ |
793 | ␉␉␉␉␉␉continue;␊ |
794 | ␉␉␉␉␉}␊ |
795 | ␊ |
796 | ␉␉␉␉␉bool inRSDT = (uint32_t)oemTable == ((uint32_t *)(rsdt + 1))[i]; // check if already in RSDT␊ |
797 | ␉␉␉␉␉if (inRSDT)␊ |
798 | ␉␉␉␉␉{␊ |
799 | ␉␉␉␉␉␉verbose(" (already in RSDT)");␊ |
800 | ␉␉␉␉␉}␊ |
801 | ␊ |
802 | ␉␉␉␉␉if (tableSign(oemTable, "SSDT") && !inRSDT)␊ |
803 | ␉␉␉␉␉{␊ |
804 | ␉␉␉␉␉␉if (drop_ssdt)␊ |
805 | ␉␉␉␉␉␉{␊ |
806 | ␉␉␉␉␉␉␉verbose(", dropping.\n");␊ |
807 | ␉␉␉␉␉␉␉dropoffset++;␊ |
808 | ␉␉␉␉␉␉}␊ |
809 | ␉␉␉␉␉␉else␊ |
810 | ␉␉␉␉␉␉{␊ |
811 | ␉␉␉␉␉␉␉verbose(", using.\n");␊ |
812 | ␉␉␉␉␉␉␉xsdt_entries[i - dropoffset] = xsdt_entries[i];␊ |
813 | ␉␉␉␉␉␉␉// Get rest of ssdts from ssdt_pmref␊ |
814 | ␉␉␉␉␉␉␉if (getSubSSDT)␊ |
815 | ␉␉␉␉␉␉␉{␊ |
816 | ␉␉␉␉␉␉␉␉struct ssdt_pmref *subSSDT = (struct ssdt_pmref *)((uint32_t)xsdt_entries[i - dropoffset] + sizeof(struct acpi_2_header) + 15);␊ |
817 | ␉␉␉␉␉␉␉␉uint8_t tabNum = *((uint8_t *)subSSDT - 2) / 3; // e.g: Name (SSDT, Package (0x0C) -> 0x0C / 3 = 4 is number of sub SSDTs␊ |
818 | ␉␉␉␉␉␉␉␉for (j = 0; (j < tabNum) && (ssdtotal_number < 30); j++)␊ |
819 | ␉␉␉␉␉␉␉␉{␊ |
820 | ␉␉␉␉␉␉␉␉␉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);␊ |
821 | ␉␉␉␉␉␉␉␉␉if (!(subSSDT[j].addr > 0) || !(subSSDT[j].addr < 0xFFFFFFFF))␊ |
822 | ␉␉␉␉␉␉␉␉␉{␊ |
823 | ␉␉␉␉␉␉␉␉␉␉verbose(", Incorrect! Dropping.\n");␊ |
824 | ␉␉␉␉␉␉␉␉␉␉continue;␊ |
825 | ␉␉␉␉␉␉␉␉␉}␊ |
826 | ␉␉␉␉␉␉␉␉␉new_ssdt[ssdtotal_number] = (struct acpi_2_ssdt *)subSSDT[j].addr;␊ |
827 | ␉␉␉␉␉␉␉␉␉ssdtotal_number++;␊ |
828 | ␉␉␉␉␉␉␉␉␉verbose(", using.\n");␊ |
829 | ␉␉␉␉␉␉␉␉}␊ |
830 | ␉␉␉␉␉␉␉}␊ |
831 | ␉␉␉␉␉␉}␊ |
832 | continue;␊ |
833 | }␊ |
834 | ␊ |
835 | // Bungo: According to ACPI Spec. no DSDT in RSDT, so what this for?␊ |
836 | /*␊ |
837 | if (tableSign(oemTable, "DSDT"))␊ |
838 | {␊ |
839 | if (new_dsdt)␊ |
840 | {␊ |
841 | xsdt_entries[i-dropoffset] = (uint64_t)new_dsdt;␊ |
842 | verbose("custom table added.\n");␊ |
843 | }␊ |
844 | continue;␊ |
845 | }␊ |
846 | */␊ |
847 | // Suggest to drop OEM DSDT here if present, it should be in FACP, if custom DSDT present ocourse␊ |
848 | if (tableSign(oemTable, "DSDT") && new_dsdt)␊ |
849 | {␊ |
850 | verbose(", dropping.\n");␊ |
851 | dropoffset++;␊ |
852 | continue;␊ |
853 | }␊ |
854 | // Dropping DMAR (DMA Remapping table) table to fix stuck on "waitForSystemMapper" or "PCI configuration begin" cause nothing wokrked for me␊ |
855 | if (tableSign(oemTable, "DMAR"))␊ |
856 | {␊ |
857 | verbose(", dropping.\n");␊ |
858 | dropoffset++;␊ |
859 | continue;␊ |
860 | }␊ |
861 | ␊ |
862 | if (tableSign(oemTable, "ECDT") && new_ecdt)␊ |
863 | {␊ |
864 | verbose(", dropping.\n");␊ |
865 | dropoffset++;␊ |
866 | continue;␊ |
867 | }␊ |
868 | ␊ |
869 | if (tableSign(oemTable, "FACP") && !inRSDT)␊ |
870 | {␊ |
871 | if (oemTable->Length > 0x10000)␊ |
872 | {␊ |
873 | goto drop_xsdt;␊ |
874 | }␊ |
875 | ␊ |
876 | verbose(", patching.\n");␊ |
877 | fadt_mod = patch_fadt((struct acpi_2_fadt *)oemTable, new_dsdt);␊ |
878 | xsdt_entries[i - dropoffset] = (uint64_t)fadt_mod;␊ |
879 | ␊ |
880 | // Generate _CST SSDT␊ |
881 | if (generate_cstates && (new_ssdt[ssdtotal_number] = generate_cst_ssdt(fadt_mod)))␊ |
882 | {␊ |
883 | verbose("\tC-States generated\n");␊ |
884 | generate_cstates = false; // Generate SSDT only once!␊ |
885 | ssdtotal_number++;␊ |
886 | }␊ |
887 | ␊ |
888 | // Generating _PSS SSDT␊ |
889 | if (generate_pstates && (new_ssdt[ssdtotal_number] = generate_pss_ssdt((void *)fadt_mod->DSDT)))␊ |
890 | {␊ |
891 | verbose("\tP-States generated\n");␊ |
892 | generate_pstates = false; // Generate SSDT only once!␊ |
893 | ssdtotal_number++;␊ |
894 | }␊ |
895 | ␉␉␉␉␉␉continue;␊ |
896 | ␉␉␉␉␉}␊ |
897 | ␊ |
898 | ␉␉␉␉␉verbose(", using.\n");␊ |
899 | ␉␉␉␉␉xsdt_entries[i - dropoffset] = xsdt_entries[i];␊ |
900 | ␉␉␉␉}␊ |
901 | ␊ |
902 | ␉␉␉␉// For moded xsdt calculate new lenght␊ |
903 | xsdt_mod->Length += 8*ssdtotal_number - 8*dropoffset;␊ |
904 | ␉␉␉␉if (new_ecdt)␊ |
905 | ␉␉␉␉{␊ |
906 | ␉␉␉␉␉xsdt_mod->Length += 8; // + ECDT␊ |
907 | ␉␉␉␉}␊ |
908 | ␊ |
909 | ␉␉␉␉// Allocate xsdt in Kernel memory area␊ |
910 | ␉␉␉␉struct acpi_2_xsdt *xsdt_copy = (struct acpi_2_xsdt *)AllocateKernelMemory(xsdt_mod->Length);␊ |
911 | ␉␉␉␉memcpy(xsdt_copy, xsdt_mod, xsdt_mod->Length); // should be: rsdt_mod->Length - 8*ssdtotal_number - 8 but don't care␊ |
912 | ␉␉␉␉free(xsdt_mod);␊ |
913 | ␉␉␉␉xsdt_mod = xsdt_copy;␊ |
914 | ␉␉␉␉rsdp_mod->XsdtAddress = (uint64_t)xsdt_mod;␊ |
915 | ␉␉␉␉xsdt_entries_num = (xsdt_mod->Length - sizeof(struct acpi_2_xsdt)) / 8;␊ |
916 | ␉␉␉␉xsdt_entries = (uint64_t *)(xsdt_mod + 1);␊ |
917 | ␊ |
918 | ␉␉␉␉// Mozodojo: Insert additional SSDTs into XSDT␊ |
919 | ␉␉␉␉for (j = 0; j < ssdtotal_number; j++)␊ |
920 | ␉␉␉␉{␊ |
921 | ␉␉␉␉␉xsdt_entries[i-dropoffset+j] = (uint64_t)new_ssdt[j];␊ |
922 | ␉␉␉␉}␊ |
923 | ␉␉␉␉verbose("ACPIpatcher: added %d custom SSDT table%s into XSDT.\n", ssdtotal_number, (ssdtotal_number != 1) ? "s" : "");␊ |
924 | ␊ |
925 | ␉␉␉␉if (new_ecdt)␊ |
926 | ␉␉␉␉{␊ |
927 | ␉␉␉␉␉xsdt_entries[i - dropoffset + j] = (uint64_t)new_ecdt;␊ |
928 | ␉␉␉␉␉verbose("ACPIpatcher: added custom table %s@%016X into XSDT.\n", "ECDT", new_ecdt);␊ |
929 | ␉␉␉␉}␊ |
930 | ␊ |
931 | ␉␉␉␉// Correct the checksum of XSDT␊ |
932 | ␉␉␉␉verbose("ACPIpatcher: modified XSDT@%016X, length=%d. Checksum: old=%d, ", xsdt_mod, xsdt_mod->Length, xsdt_mod->Checksum);␊ |
933 | ␉␉␉␉xsdt_mod->Checksum=0;␊ |
934 | ␉␉␉␉xsdt_mod->Checksum=256-checksum8(xsdt_mod, xsdt_mod->Length);␊ |
935 | ␉␉␉␉verbose("new=%d.\n", xsdt_mod->Checksum);␊ |
936 | ␉␉␉}␊ |
937 | ␉␉␉else␊ |
938 | ␉␉␉{␊ |
939 | ␉␉␉␉drop_xsdt:␊ |
940 | ␉␉␉␉/*FIXME: Now we just hope that if MacOS doesn't find XSDT it reverts to RSDT. ␊ |
941 | ␉␉␉␉ * A Better strategy would be to generate␊ |
942 | ␉␉␉␉ */␊ |
943 | ␉␉␉␉verbose("Not found or incorrect!\n");␊ |
944 | ␉␉␉␉rsdp_mod->XsdtAddress=0xffffffffffffffffLL;␊ |
945 | ␉␉␉}␊ |
946 | ␊ |
947 | #if DEBUG_ACPI␊ |
948 | pause("\n[DEBUG_ACPI] ");␊ |
949 | #endif␊ |
950 | ␉␉}␊ |
951 | ␊ |
952 | ␉␉// Correct the checksum of RSDP␊ |
953 | ␉␉verbose("ACPIpatcher: modified RSDP@%08X, checksum: old=%d, ", rsdp_mod, rsdp_mod->Checksum);␊ |
954 | ␉␉rsdp_mod->Checksum=0;␊ |
955 | ␉␉rsdp_mod->Checksum=256-checksum8(rsdp_mod, 20);␊ |
956 | ␉␉verbose("new=%d", rsdp_mod->Checksum);␊ |
957 | ␊ |
958 | ␉␉if (version)␊ |
959 | ␉␉{␊ |
960 | ␉␉␉verbose("; extended checksum: old=%d, ", rsdp_mod->ExtendedChecksum);␊ |
961 | ␊ |
962 | ␉␉␉rsdp_mod->ExtendedChecksum=0;␊ |
963 | ␉␉␉rsdp_mod->ExtendedChecksum=256-checksum8(rsdp_mod,rsdp_mod->Length);␊ |
964 | ␉␉␉verbose("new=%d.\n", rsdp_mod->ExtendedChecksum);␊ |
965 | ␉␉}␊ |
966 | ␉␉else␊ |
967 | ␉␉{␊ |
968 | ␉␉␉verbose(".\n");␊ |
969 | ␉␉}␊ |
970 | ␊ |
971 | ␉␉if (version)␊ |
972 | ␉␉{␊ |
973 | ␉␉␉acpi20_p = (uint64_t)(uint32_t)rsdp_mod; // efi configuration table pointer to ACPI_20 RSDP␊ |
974 | ␉␉␉acpi10_p = acpi20_p - 20; // efi configuration table pointer to ACPI RSDP␊ |
975 | ␉␉␉memcpy((struct acpi_2_rsdp *)(uint32_t)acpi10_p, (struct acpi_2_rsdp *)(uint32_t)acpi20_p, 20);␊ |
976 | ␉␉␉//addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");␊ |
977 | ␉␉}␊ |
978 | ␉␉else␊ |
979 | ␉␉{␊ |
980 | ␉␉␉acpi10_p = (uint64_t)(uint32_t)rsdp_mod; // efi configuration table pointer to ACPI RSDP␊ |
981 | ␉␉␉//addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");␊ |
982 | ␉␉}␊ |
983 | ␊ |
984 | ␉␉␉verbose("ACPIpatcher: acpi version %d.0 patching finished.\n", version + 1);␊ |
985 | ␉}␊ |
986 | ␊ |
987 | #if DEBUG_ACPI␊ |
988 | ␉pause("\n[DEBUG_ACPI] ");␊ |
989 | #endif␊ |
990 | ␊ |
991 | ␉return 1;␊ |
992 | }␊ |
993 | ␊ |
994 | struct acpi_2_rsdp *getRSDPaddress()␊ |
995 | {␊ |
996 | ␉bool found = false;␊ |
997 | ␉/* Before searching the BIOS space we are supposed to search the first 1K of the EBDA */␊ |
998 | ␉EBDA_RANGE_START = (uint32_t)swapUint16(*(uint16_t *)BDA_EBDA_START) << 4;␊ |
999 | ␉verbose("getRSDPaddress: scanning EBDA [%08X:%08X] for RSDP... ", EBDA_RANGE_START, EBDA_RANGE_END);␊ |
1000 | ␉void *rsdp_addr = (void*)EBDA_RANGE_START;␊ |
1001 | ␉for (; rsdp_addr <= (void*)EBDA_RANGE_END; rsdp_addr += 1)␊ |
1002 | ␉{␊ |
1003 | ␉␉if (*(uint64_t *)rsdp_addr == ACPI_SIGNATURE_UINT64_LE)␊ |
1004 | ␉␉{␊ |
1005 | ␉␉␉found = true;␊ |
1006 | ␉␉␉break;␊ |
1007 | ␉␉}␊ |
1008 | ␉}␊ |
1009 | ␊ |
1010 | ␉if (!found)␊ |
1011 | ␉{␊ |
1012 | ␉␉verbose("Nothing found.\n");␊ |
1013 | ␉␉verbose("getRSDPaddress: scanning BIOS area [%08X:%08X] for RSDP... ", ACPI_RANGE_START, ACPI_RANGE_END);␊ |
1014 | ␉␉rsdp_addr = (void*)ACPI_RANGE_START;␊ |
1015 | ␉␉for (; rsdp_addr <= (void*)ACPI_RANGE_END; rsdp_addr += 16)␊ |
1016 | ␉␉{␊ |
1017 | ␉␉␉if (*(uint64_t *)rsdp_addr == ACPI_SIGNATURE_UINT64_LE)␊ |
1018 | ␉␉␉{␊ |
1019 | ␉␉␉␉found = true;␊ |
1020 | ␉␉␉␉break;␊ |
1021 | ␉␉␉}␊ |
1022 | ␉␉}␊ |
1023 | ␉}␊ |
1024 | ␊ |
1025 | ␉if (found)␊ |
1026 | ␉{␊ |
1027 | ␉␉verbose("Found @0%08X, Rev.: %d.0).\n", rsdp_addr, ((struct acpi_2_rsdp *)rsdp_addr)->Revision + 1);␊ |
1028 | ␉␉uint8_t csum = checksum8(rsdp_addr, 20);␊ |
1029 | ␉␉if (csum == 0)␊ |
1030 | ␉␉{␊ |
1031 | ␉␉␉if (((struct acpi_2_rsdp *)rsdp_addr)->Revision == 0)␊ |
1032 | ␉␉␉{␊ |
1033 | ␉␉␉␉return rsdp_addr;␊ |
1034 | ␉␉␉}␊ |
1035 | ␉␉␉csum = checksum8(rsdp_addr, sizeof(struct acpi_2_rsdp));␊ |
1036 | ␉␉␉if (csum == 0)␊ |
1037 | ␉␉␉{␊ |
1038 | ␉␉␉␉return rsdp_addr;␊ |
1039 | ␉␉␉}␊ |
1040 | ␉␉␉else␊ |
1041 | ␉␉␉{␊ |
1042 | ␉␉␉␉verbose("getRSDPaddress: RSDP extended checksum incorrect: %d.\n", csum);␊ |
1043 | ␉␉␉}␊ |
1044 | ␉␉}␊ |
1045 | ␉␉else␊ |
1046 | ␉␉{␊ |
1047 | ␉␉␉verbose("getRSDPaddress: RSDP checksum incorrect: %d.\n", csum);␊ |
1048 | ␉␉}␊ |
1049 | ␉}␊ |
1050 | ␉else␊ |
1051 | ␉{␊ |
1052 | ␉␉verbose("Nothing found.\n");␊ |
1053 | ␉}␊ |
1054 | ␊ |
1055 | ␉return NULL;␊ |
1056 | }␊ |
1057 | |