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