1 | /*␊ |
2 | * Copyright 2008 mackerintel␊ |
3 | */␊ |
4 | ␊ |
5 | /*␊ |
6 | * Copyright (c) 2011 cparm <armelcadetpetit@gmail.com>. All rights reserved.␊ |
7 | *␊ |
8 | */␊ |
9 | ␊ |
10 | #include "libsaio.h"␊ |
11 | #include "boot.h"␊ |
12 | #include "bootstruct.h"␊ |
13 | #include "acpi.h"␊ |
14 | #include "acpidecode.h"␊ |
15 | #include "acpicode.h"␊ |
16 | #include "efi_tables.h"␊ |
17 | #include "fake_efi.h"␊ |
18 | #include "acpi_codec.h"␊ |
19 | #include "platform.h"␊ |
20 | #include "cpu.h"␊ |
21 | #include "aml_generator.h"␊ |
22 | #include "xml.h"␊ |
23 | #include "pci_root.h"␊ |
24 | #include "sl.h"␊ |
25 | ␊ |
26 | U64 rsd_p;␊ |
27 | ACPI_TABLES acpi_tables;␊ |
28 | ␊ |
29 | #ifndef DEBUG_ACPI␊ |
30 | #define DEBUG_ACPI 0␊ |
31 | #endif␊ |
32 | ␊ |
33 | #if DEBUG_ACPI==2␊ |
34 | #define DBG(x...) {printf(x); sleep(1);}␊ |
35 | #elif DEBUG_ACPI==1␊ |
36 | #define DBG(x...) printf(x)␊ |
37 | #else␊ |
38 | #define DBG(x...)␊ |
39 | #endif␊ |
40 | ␊ |
41 | extern EFI_STATUS addConfigurationTable();␊ |
42 | ␊ |
43 | extern EFI_GUID gEfiAcpiTableGuid;␊ |
44 | extern EFI_GUID gEfiAcpi20TableGuid;␊ |
45 | ␊ |
46 | #define MAX_NON_SSDT_TABLE 15␊ |
47 | #define MAX_SSDT_TABLE 15 // 15 additional SSDT tables ␊ |
48 | #define MAX_ACPI_TABLE MAX_NON_SSDT_TABLE + MAX_SSDT_TABLE␊ |
49 | ␊ |
50 | // Security space for SSDT & FACP generation,␊ |
51 | // the size can be increased ␊ |
52 | // note: the table will not placed in the reserved space if the 'normal' space is not full␊ |
53 | #define RESERVED_AERA 3 ␊ |
54 | ␊ |
55 | #define ACPI_TABLE_LIST_FULL MAX_ACPI_TABLE + RESERVED_AERA + 1␊ |
56 | ␊ |
57 | #define ACPI_TABLE_LIST_FULL_NON_RESERVED MAX_ACPI_TABLE + 1␊ |
58 | ␊ |
59 | ␊ |
60 | ACPI_TABLE_FADT *␊ |
61 | patch_fadt(ACPI_TABLE_FADT *fadt, ACPI_TABLE_DSDT *new_dsdt, bool UpdateFADT);␊ |
62 | ␊ |
63 | #define __RES(s, u)␉␉␉␉␉␉␉␉␉␉␉␉\␊ |
64 | inline unsigned u␉␉␉␉␉␉␉␉␉␉\␊ |
65 | resolve_##s(unsigned u defaultentry, char *str, int base) \␊ |
66 | {␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉\␊ |
67 | unsigned u entry = defaultentry;␉␉␉␉␉␉␉\␊ |
68 | if (str && (strcmp(str,"Default") != 0)) {␉␉␉␉␉\␊ |
69 | entry = strtoul((const char *)str, NULL,base);␉␉␉␉\␊ |
70 | }␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉\␊ |
71 | return entry;␉␉␉␉␉␉␉␉␉␉␉␉\␊ |
72 | }␊ |
73 | ␊ |
74 | __RES(pss, long) ␊ |
75 | __RES(cst, int) ␊ |
76 | ␊ |
77 | ␊ |
78 | ACPI_TABLE_HEADER * get_new_table_in_list(U32 *new_table_list, U32 Signature, U8 *retIndex )␊ |
79 | {␊ |
80 | ␉ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;␊ |
81 | ␉U8 index ;␊ |
82 | ␉*retIndex = 0;␊ |
83 | ␉␊ |
84 | ␉for (index = 0; index < (MAX_ACPI_TABLE + RESERVED_AERA); index++) {␊ |
85 | ␉␉if (*(U32 *) (table_array[index]->Signature) == Signature) {␊ |
86 | ␉␉␉*retIndex = index;␊ |
87 | ␉␉␉return table_array[index] ;␊ |
88 | ␉␉}␊ |
89 | ␉}␊ |
90 | ␉return (void*)0ul;␊ |
91 | }␊ |
92 | ␊ |
93 | U8 get_0ul_index_in_list(U32 *new_table_list, bool reserved )␊ |
94 | {␊ |
95 | ␉U8 index ;␊ |
96 | ␉␊ |
97 | ␉U8 maximum = (reserved == true) ? MAX_ACPI_TABLE + RESERVED_AERA : MAX_ACPI_TABLE;␊ |
98 | ␉␊ |
99 | ␉for (index = 0; index < maximum; index++) {␊ |
100 | ␉␉if (new_table_list[index] == 0ul) {␊ |
101 | ␉␉␉return index ;␊ |
102 | ␉␉}␊ |
103 | ␉}␊ |
104 | ␉return (reserved == true)? ACPI_TABLE_LIST_FULL : ACPI_TABLE_LIST_FULL_NON_RESERVED;␊ |
105 | }␊ |
106 | ␊ |
107 | /* cparm : This time we check it by the acpi signature */␊ |
108 | void sanitize_new_table_list(U32 *new_table_list )␊ |
109 | {␊ |
110 | ␉ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;␊ |
111 | ␉U8 index ;␊ |
112 | ␉␊ |
113 | ␉for (index = 0; index < MAX_ACPI_TABLE; index++) {␊ |
114 | ␉␉U32 current_sig = *(U32 *) (table_array[index]->Signature);␊ |
115 | ␉␉␊ |
116 | ␉␉if ((current_sig == NAMESEG(ACPI_SIG_FACS)/* not supported for now */) ␊ |
117 | ␉␉␉|| (current_sig == NAMESEG(ACPI_SIG_XSDT)) ␊ |
118 | ␉␉␉|| (current_sig == NAMESEG(ACPI_SIG_RSDT)) || (*(volatile U64 *)table_array[index] == NAMESEG64(ACPI_SIG_RSDP)) ) {␊ |
119 | ␉␉␉␊ |
120 | ␉␉␉void *buf = (void*)new_table_list[index];␊ |
121 | ␉␉␉free(buf);␊ |
122 | ␉␉␉new_table_list[index] = 0ul ;␊ |
123 | ␉␉}␊ |
124 | ␉}␊ |
125 | }␊ |
126 | ␊ |
127 | /* cparm : move all table to kernel memory */␊ |
128 | void move_table_list_to_kmem(U32 *new_table_list )␊ |
129 | {␊ |
130 | ␉ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;␊ |
131 | ␉U8 index ;␊ |
132 | ␉␊ |
133 | ␉for (index = 0; index < MAX_ACPI_TABLE; index++) {␊ |
134 | ␉␉if (new_table_list[index] != 0ul) {␊ |
135 | ␊ |
136 | ␉␉␉U32 current_sig = *(U32 *) (table_array[index]->Signature);␊ |
137 | ␉␉␉if ((current_sig != NAMESEG(ACPI_SIG_FACS)/* not supported for now */) ␊ |
138 | ␉␉␉␉&& (current_sig != NAMESEG(ACPI_SIG_XSDT)) ␊ |
139 | ␉␉␉␉&& (current_sig != NAMESEG(ACPI_SIG_RSDT)) && (*(volatile U64 *)table_array[index] != NAMESEG64(ACPI_SIG_RSDP))␊ |
140 | ␉␉␉␉&& (GetChecksum(table_array[index], table_array[index]->Length) == 0)) {␊ |
141 | ␉␉␉␉␊ |
142 | ␉␉␉␉void *tableAddr=(void*)AllocateKernelMemory(table_array[index]->Length);␊ |
143 | ␉␉␉␉bcopy(table_array[index], tableAddr, table_array[index]->Length);␊ |
144 | ␉␉␉␉new_table_list[index] = 0ul ;␊ |
145 | ␉␉␉␉new_table_list[index] = (U32)tableAddr ;␊ |
146 | ␉␉␉␉␊ |
147 | ␉␉␉} else {␊ |
148 | ␉␉␉␉␊ |
149 | ␉␉␉␉void *buf = (void*)new_table_list[index];␊ |
150 | ␉␉␉␉free(buf);␊ |
151 | ␉␉␉␉new_table_list[index] = 0ul ;␊ |
152 | ␉␉␉}␉␉␉␊ |
153 | ␉␉}␊ |
154 | ␉}␊ |
155 | }␊ |
156 | ␊ |
157 | ACPI_TABLE_RSDP * gen_alloc_rsdp_v2_from_v1(ACPI_TABLE_RSDP *rsdp )␊ |
158 | {␊ |
159 | ␉␊ |
160 | ␉ACPI_TABLE_RSDP * rsdp_conv = (ACPI_TABLE_RSDP *)AllocateKernelMemory(sizeof(ACPI_TABLE_RSDP));␊ |
161 | ␉bzero(rsdp_conv, sizeof(ACPI_TABLE_RSDP));␊ |
162 | memcpy(rsdp_conv, rsdp, ACPI_RSDP_REV0_SIZE);␊ |
163 | ␊ |
164 | /* Add/change fields */␊ |
165 | rsdp_conv->Revision = 2; /* ACPI version 3 */␊ |
166 | rsdp_conv->Length = sizeof(ACPI_TABLE_RSDP);␊ |
167 | ␊ |
168 | /* Correct checksums */ ␊ |
169 | setRsdpchecksum(rsdp_conv);␊ |
170 | setRsdpXchecksum(rsdp_conv); ␊ |
171 | ␊ |
172 | return rsdp_conv;␊ |
173 | }␊ |
174 | ␊ |
175 | ACPI_TABLE_RSDT * gen_alloc_rsdt_from_xsdt(ACPI_TABLE_XSDT *xsdt)␊ |
176 | {␊ |
177 | U32 index;␊ |
178 | U32 num_tables;␊ |
179 | ␉␉␉␊ |
180 | num_tables= get_num_tables64(xsdt);␊ |
181 | ␊ |
182 | ACPI_TABLE_RSDT * rsdt_conv=(ACPI_TABLE_RSDT *)AllocateKernelMemory(sizeof(ACPI_TABLE_HEADER)+(num_tables * 4));␊ |
183 | ␉bzero(rsdt_conv, sizeof(ACPI_TABLE_HEADER)+(num_tables * 4));␊ |
184 | memcpy(&rsdt_conv->Header, &xsdt->Header, sizeof(ACPI_TABLE_HEADER));␊ |
185 | ␊ |
186 | rsdt_conv->Header.Signature[0] = 'R';␊ |
187 | rsdt_conv->Header.Signature[1] = 'S';␊ |
188 | rsdt_conv->Header.Signature[2] = 'D';␊ |
189 | rsdt_conv->Header.Signature[3] = 'T';␊ |
190 | rsdt_conv->Header.Length = sizeof(ACPI_TABLE_HEADER)+(num_tables * 4);␊ |
191 | ␉␊ |
192 | ␉ACPI_TABLE_HEADER *table = (ACPI_TABLE_HEADER *) xsdt->TableOffsetEntry;␉␊ |
193 | ␊ |
194 | ␉for (index=0;index<num_tables;index++)␊ |
195 | {␊ |
196 | ␉␉if (GetChecksum(table, table->Length) == 0)␊ |
197 | ␉␉{␊ |
198 | ␉␉␉if (((U32) (table->Signature) == NAMESEG(ACPI_SIG_FADT))) {␊ |
199 | ␉␉␉␉ACPI_TABLE_FADT *fadt=(ACPI_TABLE_FADT *)((U32)table);␊ |
200 | ␉␉␉␉␊ |
201 | ␉␉␉␉DBG("Downgrading ACPI V%d FADT to ACPI V1 FADT \n", fadt->Header.Revision);␊ |
202 | ␉␉␉␉ACPI_TABLE_FADT *fadt_conv=(ACPI_TABLE_FADT *)malloc(0x74);␊ |
203 | ␉␉␉␉memcpy(fadt_conv, fadt, 0x74);␊ |
204 | ␉␉␉␉fadt_conv->Header.Length = 0x74;␊ |
205 | ␉␉␉␉fadt_conv->Header.Revision = 0x01;␊ |
206 | ␉␉␉␉␊ |
207 | ␉␉␉␉SetChecksum(&fadt_conv->Header);␊ |
208 | ␉␉␉␉ACPI_TABLE_FADT *fadt_mod = patch_fadt(fadt_conv, ((ACPI_TABLE_DSDT*)((U32)fadt->XDsdt)), false); ␊ |
209 | ␉␉␉␉if (fadt_mod == (void*)0ul) {␊ |
210 | ␉␉␉␉␉printf("Error: Failed to patch FADT Table, fallback to fadt original pointer\n");␊ |
211 | ␉␉␉␉␉fadt_mod = fadt;␊ |
212 | ␉␉␉␉}␊ |
213 | ␉␉␉␉␊ |
214 | ␉␉␉␉rsdt_conv->TableOffsetEntry[index] = ((U32)fadt_mod);␊ |
215 | ␉␉␉␉// Move array pointer to next 64-bit pointer␊ |
216 | ␉␉␉␉table = (ACPI_TABLE_HEADER *) ((U32) table + sizeof(U64));␊ |
217 | ␉␉␉␉continue;␊ |
218 | ␉␉␉}␊ |
219 | ␉␉␉␊ |
220 | ␉␉␉rsdt_conv->TableOffsetEntry[index] = (U32)table;␊ |
221 | ␉␉}␊ |
222 | // Move array pointer to next 64-bit pointer␊ |
223 | table = (ACPI_TABLE_HEADER *) ((U32) table + sizeof(U64));␉␉␊ |
224 | ␉␉␊ |
225 | }␊ |
226 | ␊ |
227 | SetChecksum(&rsdt_conv->Header);␊ |
228 | ␊ |
229 | return rsdt_conv;␊ |
230 | }␊ |
231 | ␊ |
232 | ACPI_TABLE_XSDT * gen_alloc_xsdt_from_rsdt(ACPI_TABLE_RSDT *rsdt)␊ |
233 | {␊ |
234 | ␉␊ |
235 | ␉␊ |
236 | ␉U32 index;␊ |
237 | U32 num_tables;␊ |
238 | ␉␉␉␊ |
239 | num_tables= get_num_tables(rsdt);␊ |
240 | ␊ |
241 | ACPI_TABLE_XSDT * xsdt_conv=(ACPI_TABLE_XSDT *)AllocateKernelMemory(sizeof(ACPI_TABLE_HEADER)+(num_tables * 8));␊ |
242 | ␉bzero(xsdt_conv, sizeof(ACPI_TABLE_HEADER)+(num_tables * 8));␊ |
243 | memcpy(&xsdt_conv->Header, &rsdt->Header, sizeof(ACPI_TABLE_HEADER));␊ |
244 | ␊ |
245 | xsdt_conv->Header.Signature[0] = 'X';␊ |
246 | xsdt_conv->Header.Signature[1] = 'S';␊ |
247 | xsdt_conv->Header.Signature[2] = 'D';␊ |
248 | xsdt_conv->Header.Signature[3] = 'T';␊ |
249 | xsdt_conv->Header.Length = sizeof(ACPI_TABLE_HEADER)+(num_tables * 8);␊ |
250 | ␊ |
251 | ␉ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) rsdt->TableOffsetEntry;␊ |
252 | ␉␊ |
253 | for (index=0;index<num_tables;index++)␊ |
254 | {␊ |
255 | ␉␉if (GetChecksum(table_array[index], table_array[index]->Length) == 0) {␊ |
256 | ␉␉␉␊ |
257 | ␉␉␉if ((*(U32 *) (table_array[index]->Signature) == NAMESEG(ACPI_SIG_FADT))){␊ |
258 | ␉␉␉␉ACPI_TABLE_FADT *FacpPointer = ((ACPI_TABLE_FADT*)table_array[index]);␊ |
259 | ␉␉␉␉ACPI_TABLE_FADT *fadt_mod = (ACPI_TABLE_FADT *)patch_fadt(FacpPointer,((ACPI_TABLE_DSDT*)FacpPointer->Dsdt),true);␊ |
260 | ␉␉␉␉if (fadt_mod == (void*)0ul) {␊ |
261 | ␉␉␉␉␉printf("Error: Failed to patch (& update) FADT Table, fallback to original fadt pointer\n");␊ |
262 | ␉␉␉␉␉fadt_mod = FacpPointer;␊ |
263 | ␉␉␉␉}␊ |
264 | ␉␉␉␉xsdt_conv->TableOffsetEntry[index] = ((U64)((U32)fadt_mod));␊ |
265 | ␉␉␉␉␊ |
266 | ␉␉␉␉continue;␊ |
267 | ␉␉␉}␊ |
268 | ␉␉␉xsdt_conv->TableOffsetEntry[index] = ((U64)((U32)table_array[index])); ␊ |
269 | }␊ |
270 | ␊ |
271 | }␊ |
272 | ␊ |
273 | SetChecksum(&xsdt_conv->Header);␊ |
274 | ␊ |
275 | return xsdt_conv;␊ |
276 | }␊ |
277 | ␊ |
278 | void *loadACPITable(char *dirspec, char *filename )␊ |
279 | {␉␊ |
280 | ␉int fd = -1;␊ |
281 | ␉char acpi_file[512];␊ |
282 | ␊ |
283 | ␉DBG("Searching for %s file ...\n", filename);␊ |
284 | ␉// Check booting partition␉␊ |
285 | ␉␊ |
286 | ␉sprintf(acpi_file, "%s%s",dirspec, filename); ␊ |
287 | ␉␊ |
288 | ␉fd=open(acpi_file);␊ |
289 | ␉␊ |
290 | ␉if (fd<0)␊ |
291 | ␉{␉␉␉␉␉␉␉␊ |
292 | ␉␉DBG("Couldn't open ACPI Table: %s\n", acpi_file);␊ |
293 | ␉␉return (void *)0ul ;␉␉␉␉␊ |
294 | ␉}␉␉␊ |
295 | ␉␊ |
296 | ␉void *tableAddr=(void*)malloc(file_size (fd));␊ |
297 | ␊ |
298 | ␉if (tableAddr)␊ |
299 | ␉{␊ |
300 | ␉␉if (read (fd, tableAddr, file_size (fd))!=file_size (fd))␊ |
301 | ␉␉{␊ |
302 | ␉␉␉printf("Couldn't read table %s\n",acpi_file);␊ |
303 | ␉␉␉free (tableAddr);␊ |
304 | ␉␉␉close (fd);␊ |
305 | ␉␉␉return (void *)0ul ;␊ |
306 | ␉␉}␊ |
307 | ␉␉␊ |
308 | ␉␉close (fd);␊ |
309 | ␉␉␊ |
310 | ␉␉ACPI_TABLE_HEADER * header = (ACPI_TABLE_HEADER *)tableAddr;␊ |
311 | ␉␉␊ |
312 | ␉␉if (GetChecksum(header, header->Length) == 0) {␊ |
313 | ␉␉␉DBG("Found valid ACPI file : %s", filename);␊ |
314 | ␉␉␉DBG(", Table %s read and stored at: %x", acpi_file, tableAddr);␊ |
315 | ␉␉␉DBG("\n");␊ |
316 | ␉␉␉return tableAddr;␊ |
317 | ␉␉} else {␊ |
318 | ␉␉␉printf("Warning : Incorrect cheksum for the file : %s,");␊ |
319 | ␉␉␉printf("␉␉ this file will be dropped.\n");␊ |
320 | ␉␉␉free(tableAddr);␊ |
321 | ␉␉␉return (void*)0ul;␊ |
322 | ␉␉}␉␉␊ |
323 | ␉}␊ |
324 | ␉␊ |
325 | ␉printf("Couldn't allocate memory for table %s\n", acpi_file);␊ |
326 | ␉close (fd);␊ |
327 | ␉␊ |
328 | ␉return (void *)0ul ;␊ |
329 | }␊ |
330 | ␊ |
331 | /*␊ |
332 | * License for␊ |
333 | * print_nameseg, generate_cpu_map_from_acpi, sprintf_nameseg .␊ |
334 | *␊ |
335 | Copyright (c) 2010, Intel Corporation␊ |
336 | All rights reserved.␊ |
337 | ␊ |
338 | Redistribution and use in source and binary forms, with or without␊ |
339 | modification, are permitted provided that the following conditions are met:␊ |
340 | ␊ |
341 | * Redistributions of source code must retain the above copyright notice,␊ |
342 | this list of conditions and the following disclaimer.␊ |
343 | * Redistributions in binary form must reproduce the above copyright notice,␊ |
344 | this list of conditions and the following disclaimer in the documentation␊ |
345 | and/or other materials provided with the distribution.␊ |
346 | * Neither the name of Intel Corporation nor the names of its contributors␊ |
347 | may be used to endorse or promote products derived from this software␊ |
348 | without specific prior written permission.␊ |
349 | ␊ |
350 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND␊ |
351 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED␊ |
352 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE␊ |
353 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR␊ |
354 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES␊ |
355 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;␊ |
356 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON␊ |
357 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT␊ |
358 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS␊ |
359 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.␊ |
360 | */␊ |
361 | static U32 pmbase;␊ |
362 | static short cpuNamespace;␊ |
363 | PROCESSOR_NUMBER_TO_NAMESEG cpu_map[CPU_MAP_LIMIT];␊ |
364 | unsigned int cpu_map_count;␊ |
365 | int cpu_map_error;␊ |
366 | ␊ |
367 | #if DEBUG_ACPI␊ |
368 | static void print_nameseg(U32 i)␊ |
369 | {␊ |
370 | printf("%c%c%c%c",␊ |
371 | (int)(i & 0x000000ff),␊ |
372 | (int)((i & 0x0000ff00) >> 8),␊ |
373 | (int)((i & 0x00ff0000) >> 16),␊ |
374 | (int)(i >> 24));␊ |
375 | }␊ |
376 | ␊ |
377 | static void sprintf_nameseg(char* dest, U32 src)␊ |
378 | {␊ |
379 | sprintf(dest,"%c%c%c%c",␊ |
380 | (int)(src & 0x000000ff),␊ |
381 | (int)((src & 0x0000ff00) >> 8),␊ |
382 | (int)((src & 0x00ff0000) >> 16),␊ |
383 | (int)(src >> 24));␊ |
384 | }␊ |
385 | #endif␊ |
386 | ␊ |
387 | static int generate_cpu_map_from_acpi(ACPI_TABLE_DSDT * DsdtPointer)␊ |
388 | {␊ |
389 | PROCESSOR_NUMBER_TO_NAMESEG *map = cpu_map;␊ |
390 | U32 processor_namespace = 0;␊ |
391 | U32 cpu;␊ |
392 | U8 *current, *end;␊ |
393 | ACPI_TABLE_HEADER *header;␊ |
394 | struct acpi_namespace ns;␊ |
395 | ␉␉␊ |
396 | ␉if ((cpu_map_error == 1) || (DsdtPointer == (void*)0ul)) ␊ |
397 | ␉␉return 1;␊ |
398 | ␉else if (cpu_map_count > 0) ␊ |
399 | ␉␉return 0;␊ |
400 | ␉␊ |
401 | DBG("Attempting to autodetect CPU map from ACPI DSDT; wish me luck\n");␉␊ |
402 | ␊ |
403 | current = (U8 *) DsdtPointer;␊ |
404 | current = decodeTableHeader(current, &header);␊ |
405 | end = current - sizeof(*header) + header->Length;␊ |
406 | ns.depth = 0;␊ |
407 | acpi_processor_count = 0;␊ |
408 | ␉DBG("* DSDT debug start\n");␊ |
409 | parse_acpi_termlist(&ns, current, end);␊ |
410 | ␉DBG("* DSDT debug end\n");␊ |
411 | ␉␊ |
412 | if (acpi_processor_count > CPU_MAP_LIMIT){␊ |
413 | ␉␉verbose("Too many processors: found %u processors\n", acpi_processor_count);␊ |
414 | return (cpu_map_error = 1);␊ |
415 | ␉}␊ |
416 | if (acpi_processor_count == 0){␊ |
417 | ␉␉verbose( "Found no processors in ACPI\n");␊ |
418 | return (cpu_map_error = 1);␊ |
419 | ␉}␊ |
420 | for (cpu = 0; cpu < acpi_processor_count; cpu++) {␊ |
421 | U32 nameseg;␊ |
422 | if (acpi_processors[cpu].pmbase) {␊ |
423 | U32 cpu_pmbase = acpi_processors[cpu].pmbase - 0x10;␊ |
424 | if (pmbase && cpu_pmbase != pmbase){␊ |
425 | ␉␉␉␉verbose("Found inconsistent pmbase addresses in ACPI: 0x%x and 0x%x\n", pmbase, cpu_pmbase);␊ |
426 | ␉␉␉␉return (cpu_map_error = 1);␊ |
427 | ␉␉␉}␊ |
428 | pmbase = cpu_pmbase;␊ |
429 | }␊ |
430 | if (acpi_processors[cpu].ns.depth > MAX_SUPPORTED_CPU_NAMESEGS + 1){␊ |
431 | ␉␉␉verbose("Processor path too deep: depth %u\n", acpi_processors[cpu].ns.depth);␊ |
432 | ␉␉␉return (cpu_map_error = 1);␊ |
433 | ␉␉}␊ |
434 | if (processor_namespace && acpi_processors[cpu].ns.nameseg[0] != processor_namespace){␊ |
435 | ␉␉␉verbose("Processor namespaces inconsistent\n");␊ |
436 | ␉␉␉return (cpu_map_error = 1);␊ |
437 | ␉␉}␊ |
438 | processor_namespace = acpi_processors[cpu].ns.nameseg[0];␊ |
439 | map->acpi_processor_number = acpi_processors[cpu].id;␊ |
440 | map->seg_count = acpi_processors[cpu].ns.depth - 1;␊ |
441 | for (nameseg = 0; nameseg < map->seg_count; nameseg++)␊ |
442 | map->nameseg[nameseg] = acpi_processors[cpu].ns.nameseg[nameseg + 1];␊ |
443 | map++;␊ |
444 | }␊ |
445 | if (!pmbase){␊ |
446 | ␉␉verbose("No pmbase found in ACPI\n");␊ |
447 | ␉␉return (cpu_map_error = 1);␊ |
448 | ␉}␊ |
449 | if (processor_namespace == NAMESEG("_PR_"))␊ |
450 | cpuNamespace = CPU_NAMESPACE_PR;␊ |
451 | else if (processor_namespace == NAMESEG("_SB_"))␊ |
452 | cpuNamespace = CPU_NAMESPACE_SB;␊ |
453 | else {␊ |
454 | verbose("Found processors in invalid namespace; not _PR_ or _SB_\n");␊ |
455 | ␉␉return (cpu_map_error = 1);␊ |
456 | ␉}␊ |
457 | cpu_map_count = map - cpu_map;␊ |
458 | ␉␊ |
459 | #if DEBUG_ACPI␊ |
460 | ␉char pns[3]; ␊ |
461 | ␉sprintf_nameseg(pns,processor_namespace);␊ |
462 | ␉verbose("Found %d processors in ACPI, pmbase : 0x%x, cpu_map_count : %d, namespace : %s \n",acpi_processor_count, pmbase, cpu_map_count ,pns );␊ |
463 | ␉␊ |
464 | getc();␊ |
465 | U32 i;␊ |
466 | verbose("Found processors name : \n" );␊ |
467 | for ( i = 0; i<cpu_map_count; i++) {␉␉␉␊ |
468 | char pname[3]; ␊ |
469 | sprintf_nameseg(pname, *cpu_map[i].nameseg);␊ |
470 | verbose(" %s ",pname );␊ |
471 | ␊ |
472 | }␊ |
473 | verbose("\n");␊ |
474 | ␉getc();␊ |
475 | #endif␊ |
476 | ␉␊ |
477 | ␉// TODO: Save the cpu map into the device tree␊ |
478 | return (cpu_map_error = 0);␊ |
479 | }␊ |
480 | ␊ |
481 | ACPI_TABLE_SSDT *generate_cst_ssdt(ACPI_TABLE_FADT* fadt)␊ |
482 | {␉␊ |
483 | ␉char ssdt_header[] =␊ |
484 | ␉{␊ |
485 | ␉␉0x53, 0x53, 0x44, 0x54, 0xE7, 0x00, 0x00, 0x00, /* SSDT.... */␊ |
486 | ␉␉0x01, 0x17, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x41, /* ..PmRefA */␊ |
487 | ␉␉0x43, 0x70, 0x75, 0x43, 0x73, 0x74, 0x00, 0x00, /* CpuCst.. */␊ |
488 | ␉␉0x00, 0x10, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* ....INTL */␊ |
489 | ␉␉0x31, 0x03, 0x10, 0x20 ␉␉␉␉␉␉␉/* 1.._␉␉*/␊ |
490 | ␉};␊ |
491 | ␉␊ |
492 | ␉char cstate_resource_template[] = ␊ |
493 | ␉{␊ |
494 | ␉␉0x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00, 0x7F, ␊ |
495 | ␉␉0x01, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, ␊ |
496 | ␉␉0x00, 0x00, 0x00, 0x79, 0x00␊ |
497 | ␉};␊ |
498 | ␉␊ |
499 | ␉if (Platform->CPU.Vendor != 0x756E6547) {␊ |
500 | ␉␉verbose ("Not an Intel platform: C-States will not be generated !!!\n");␊ |
501 | ␉␉return (void *)0ul;␊ |
502 | ␉}␊ |
503 | ␉␊ |
504 | ␉if (fadt == (void *)0ul) {␊ |
505 | ␉␉verbose ("FACP not exists: C-States will not be generated !!!\n");␊ |
506 | ␉␉return (void *)0ul;␊ |
507 | ␉}␊ |
508 | ␊ |
509 | ␉ACPI_TABLE_DSDT* dsdt = ((fadt->Header.Revision >= 3) && (fadt->XDsdt != 0)) ? (ACPI_TABLE_DSDT*)((U32)fadt->XDsdt):(ACPI_TABLE_DSDT*)fadt->Dsdt;␊ |
510 | ␉if (dsdt == (void *)0ul) {␊ |
511 | ␉␉verbose ("DSDT not found: C-States will not be generated !!!\n");␊ |
512 | ␉␉return (void *)0ul;␊ |
513 | ␉}␊ |
514 | ␉␉␊ |
515 | ␉if (generate_cpu_map_from_acpi(dsdt) == 0) ␊ |
516 | ␉{␊ |
517 | ␉␉bool c2_enabled = fadt->C2Latency < 100;␊ |
518 | ␉␉bool c3_enabled = fadt->C3Latency < 1000;␊ |
519 | ␉␉bool c4_enabled = false;␊ |
520 | ␉␉␊ |
521 | ␉␉getBoolForKey(kEnableC4State, &c4_enabled, &bootInfo->bootConfig);␊ |
522 | ␊ |
523 | ␉␉unsigned char cstates_count = 1 + (c2_enabled ? 1 : 0) + ((c3_enabled || c4_enabled) ? 1 : 0);␊ |
524 | ␉␉char *Lat = NULL, *Pw = NULL, *tmpstr =NULL;␊ |
525 | ␉␉int base = 16;␊ |
526 | ␉␉TagPtr personality = XMLCastDict(XMLGetProperty(bootInfo->bootConfig.dictionary, (const char*)"C-States"));␊ |
527 | ␉␉␊ |
528 | ␉␉if ((tmpstr = XMLCastString(XMLGetProperty(personality, (const char*)"Base")))) {␊ |
529 | ␉␉␉␊ |
530 | ␉␉␉int mybase = strtol(tmpstr, NULL, 10);␉␊ |
531 | ␉␉␉␊ |
532 | ␉␉␉if (mybase == 8 || mybase == 10 || mybase == 16 ) ␊ |
533 | ␉␉␉␉base = mybase;␉␉␉␉␉␉␉␉␉␊ |
534 | ␉␉}␊ |
535 | ␉␉␊ |
536 | ␉␉struct aml_chunk* root = aml_create_node(NULL);␊ |
537 | aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header␊ |
538 | struct aml_chunk* scop;␊ |
539 | ␉␉if (cpuNamespace == CPU_NAMESPACE_PR) ␊ |
540 | ␉␉␉scop = aml_add_scope(root, "\\_PR_");␊ |
541 | ␉␉else if (cpuNamespace == CPU_NAMESPACE_SB) ␊ |
542 | ␉␉␉scop = aml_add_scope(root, "\\_SB_");␊ |
543 | ␉␉else ␊ |
544 | ␉␉{␊ |
545 | ␉␉␉aml_destroy_node(root);␉␊ |
546 | ␉␉␉goto out;␊ |
547 | ␉␉}␊ |
548 | struct aml_chunk* name = aml_add_name(scop, "CST_");␊ |
549 | struct aml_chunk* pack = aml_add_package(name);␊ |
550 | aml_add_byte(pack, cstates_count);␊ |
551 | ␉␉␊ |
552 | struct aml_chunk* tmpl = aml_add_package(pack);␊ |
553 | TagPtr match_Status = XMLGetProperty(personality, (const char*)"C1");␊ |
554 | if (match_Status) {␉␊ |
555 | Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power"));␊ |
556 | Lat = XMLCastString(XMLGetProperty(match_Status, (const char*)"Latency"));␊ |
557 | }␊ |
558 | cstate_resource_template[11] = 0x00; // C1␊ |
559 | aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));␊ |
560 | aml_add_byte(tmpl, 0x01); // C1␊ |
561 | aml_add_byte(tmpl, (unsigned char)resolve_cst(0x01, Lat, base)); // Latency␊ |
562 | aml_add_word(tmpl, resolve_cst(0x03e8, Pw, base)); // Power␊ |
563 | ␉␉// C2␊ |
564 | ␉␉if (c2_enabled) ␊ |
565 | ␉␉{␊ |
566 | ␉␉␉tmpl = aml_add_package(pack);␊ |
567 | ␉␉␉Lat = NULL; ␊ |
568 | ␉␉␉Pw = NULL;␊ |
569 | ␉␉␉match_Status = XMLGetProperty(personality, (const char*)"C2");␊ |
570 | ␉␉␉if (match_Status) {␉␊ |
571 | ␉␉␉␉Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power"));␊ |
572 | ␉␉␉␉Lat = XMLCastString(XMLGetProperty(match_Status, (const char*)"Latency"));␊ |
573 | ␉␉␉}␊ |
574 | ␉␉␉␊ |
575 | ␉␉␉cstate_resource_template[11] = 0x10; // C2␊ |
576 | ␉␉␉aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));␊ |
577 | ␉␉␉aml_add_byte(tmpl, 0x02); // C2␉␉␉␉␊ |
578 | ␉␉␉aml_add_word(tmpl, resolve_cst(fadt->C2Latency, Lat, base)); // Latency␊ |
579 | ␉␉␉aml_add_word(tmpl, resolve_cst(0x01f4, Pw, base)); // Power␊ |
580 | ␉␉}␊ |
581 | ␉␉␊ |
582 | ␉␉// C4␊ |
583 | ␉␉if (c4_enabled) ␊ |
584 | ␉␉{␊ |
585 | ␉␉␉tmpl = aml_add_package(pack);␊ |
586 | ␉␉␉Lat = NULL; ␊ |
587 | ␉␉␉Pw = NULL;␊ |
588 | ␉␉␉match_Status = XMLGetProperty(personality, (const char*)"C4"); ␊ |
589 | ␉␉␉if (match_Status) {␉␊ |
590 | ␉␉␉␉Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power"));␊ |
591 | ␉␉␉␉Lat = XMLCastString(XMLGetProperty(match_Status, (const char*)"Latency"));␊ |
592 | ␉␉␉}␊ |
593 | ␉␉␉cstate_resource_template[11] = 0x30; // C4␊ |
594 | ␉␉␉aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));␊ |
595 | ␉␉␉aml_add_byte(tmpl, 0x04); // C4␉␊ |
596 | ␉␉␉aml_add_word(tmpl, resolve_cst(fadt->C3Latency / 2, Lat, base)); // TODO: right latency for C4␊ |
597 | ␉␉␉aml_add_word(tmpl, resolve_cst(0xfa, Pw, base)); // Power␊ |
598 | ␉␉␉␊ |
599 | ␉␉}␉␉␊ |
600 | ␉␉// C3␊ |
601 | ␉␉else if (c3_enabled) ␊ |
602 | ␉␉{␊ |
603 | ␉␉␉tmpl = aml_add_package(pack);␊ |
604 | ␉␉␉Lat = NULL; ␊ |
605 | ␉␉␉Pw = NULL;␊ |
606 | ␉␉␉match_Status = XMLGetProperty(personality, (const char*)"C3"); ␊ |
607 | ␉␉␉if (match_Status) {␉␊ |
608 | ␉␉␉␉Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power"));␊ |
609 | ␉␉␉␉Lat = XMLCastString(XMLGetProperty(match_Status, (const char*)"Latency"));␊ |
610 | ␉␉␉}␊ |
611 | ␉␉␉cstate_resource_template[11] = 0x20; // C3␊ |
612 | ␉␉␉aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));␊ |
613 | ␉␉␉aml_add_byte(tmpl, 0x03); // C3␉␉␉␉␊ |
614 | ␉␉␉aml_add_word(tmpl, resolve_cst(fadt->C3Latency , Lat, base)); ␊ |
615 | ␉␉␉aml_add_word(tmpl, resolve_cst(0x015e, Pw, base)); // Power␊ |
616 | ␉␉␉␊ |
617 | ␉␉}␊ |
618 | ␉␉ ␊ |
619 | // Aliaces␊ |
620 | unsigned int i;␊ |
621 | for (i = 0; i < cpu_map_count; i++) ␊ |
622 | {␊ |
623 | char name[9];␊ |
624 | U32 nseg = *(U32*)cpu_map[i].nameseg;␊ |
625 | if (cpuNamespace == CPU_NAMESPACE_PR) {␊ |
626 | sprintf(name, "_PR_%c%c%c%c",␊ |
627 | (int)(nseg & 0x000000ff),␊ |
628 | (int)((nseg & 0x0000ff00) >> 8),␊ |
629 | (int)((nseg & 0x00ff0000) >> 16),␊ |
630 | (int)(nseg >> 24));␊ |
631 | } else if (cpuNamespace == CPU_NAMESPACE_SB) {␊ |
632 | sprintf(name, "_SB_%c%c%c%c",␊ |
633 | (int)(nseg & 0x000000ff),␊ |
634 | (int)((nseg & 0x0000ff00) >> 8),␊ |
635 | (int)((nseg & 0x00ff0000) >> 16),␊ |
636 | (int)(nseg >> 24));␊ |
637 | } else {␊ |
638 | aml_destroy_node(root);␉␊ |
639 | goto out;␊ |
640 | }␊ |
641 | ␊ |
642 | scop = aml_add_scope(root, name);␊ |
643 | aml_add_alias(scop, "CST_", "_CST");␊ |
644 | }␊ |
645 | ␉␉␊ |
646 | ␉␉aml_calculate_size(root);␊ |
647 | ␉␉␊ |
648 | ␉␉ACPI_TABLE_SSDT *ssdt = (ACPI_TABLE_SSDT *)AllocateKernelMemory(root->Size);␊ |
649 | ␊ |
650 | ␉␉aml_write_node(root, (void*)ssdt, 0);␊ |
651 | ␉␉␊ |
652 | ␉␉ssdt->Header.Length = root->Size; ␊ |
653 | ␉␉␊ |
654 | ␉␉SetChecksum(&ssdt->Header);␊ |
655 | ␊ |
656 | ␉␉aml_destroy_node(root);␉␉␊ |
657 | ␊ |
658 | ␉␉verbose ("SSDT with CPU C-States generated successfully\n");␊ |
659 | ␉␉␊ |
660 | ␉␉return ssdt;␊ |
661 | ␉}␊ |
662 | ␉else ␊ |
663 | ␉{␊ |
664 | out:␊ |
665 | ␉␉verbose ("ACPI CPUs not found: C-States will not be generated !!!\n");␊ |
666 | ␉}␊ |
667 | ␊ |
668 | ␉return (void *)0ul;␊ |
669 | }␊ |
670 | ␊ |
671 | ACPI_TABLE_SSDT *generate_pss_ssdt(ACPI_TABLE_DSDT* dsdt)␊ |
672 | {␉␉␊ |
673 | ␉␊ |
674 | ␉char ssdt_header[] =␊ |
675 | ␉{␊ |
676 | ␉␉0x53, 0x53, 0x44, 0x54, 0x7E, 0x00, 0x00, 0x00, /* SSDT.... */␊ |
677 | ␉␉0x01, 0x6A, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x00, /* ..PmRef. */␊ |
678 | ␉␉0x43, 0x70, 0x75, 0x50, 0x6D, 0x00, 0x00, 0x00, /* CpuPm... */␊ |
679 | ␉␉0x00, 0x30, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* .0..INTL */␊ |
680 | ␉␉0x31, 0x03, 0x10, 0x20,␉␉␉␉␉␉␉/* 1.._␉␉*/␊ |
681 | ␉};␊ |
682 | ␊ |
683 | ␉if (Platform->CPU.Vendor != 0x756E6547) {␊ |
684 | ␉␉verbose ("Not an Intel platform: P-States will not be generated !!!\n");␊ |
685 | ␉␉return (void *)0ul;␊ |
686 | ␉}␊ |
687 | ␉␊ |
688 | ␉if (!(Platform->CPU.Features & CPUID_FEATURE_MSR)) {␊ |
689 | ␉␉verbose ("Unsupported CPU: P-States will not be generated !!!\n");␊ |
690 | ␉␉return (void *)0ul;␊ |
691 | ␉}␊ |
692 | ␉␊ |
693 | ␉if (dsdt == (void *)0ul) {␊ |
694 | ␉␉verbose ("DSDT not found: P-States will not be generated !!!\n");␊ |
695 | ␉␉return (void *)0ul;␊ |
696 | ␉}␊ |
697 | ␉␉ ␊ |
698 | ␉if (generate_cpu_map_from_acpi(dsdt) == 0 ) ␊ |
699 | ␉{␊ |
700 | ␉␉struct p_state initial, maximum, minimum, p_states[32];␊ |
701 | ␉␉U8 p_states_count = 0;␉␉␊ |
702 | ␉␉␊ |
703 | ␉␉// Retrieving P-States, ported from code by superhai (c)␊ |
704 | ␉␉switch (Platform->CPU.Family) {␊ |
705 | ␉␉␉case 0x06: ␊ |
706 | ␉␉␉{␊ |
707 | ␉␉␉␉switch (Platform->CPU.Model) ␊ |
708 | ␉␉␉␉{␊ |
709 | ␉␉␉␉␉case CPUID_MODEL_DOTHAN: ␊ |
710 | ␉␉␉␉␉case CPUID_MODEL_YONAH: // Yonah␊ |
711 | ␉␉␉␉␉case CPUID_MODEL_MEROM: // Merom␊ |
712 | ␉␉␉␉␉case CPUID_MODEL_PENRYN: // Penryn␊ |
713 | ␉␉␉␉␉case CPUID_MODEL_ATOM: // Intel Atom (45nm)␊ |
714 | ␉␉␉␉␉{␊ |
715 | ␉␉␉␉␉␉bool cpu_dynamic_fsb = false;␊ |
716 | ␉␉␉␉␉␉␊ |
717 | ␉␉␉␉␉␉if (rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 27)) ␊ |
718 | ␉␉␉␉␉␉{␊ |
719 | ␉␉␉␉␉␉␉wrmsr64(MSR_IA32_EXT_CONFIG, (rdmsr64(MSR_IA32_EXT_CONFIG) | (1 << 28))); ␊ |
720 | ␉␉␉␉␉␉␉delay(1);␊ |
721 | ␉␉␉␉␉␉␉cpu_dynamic_fsb = rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 28);␊ |
722 | ␉␉␉␉␉␉}␊ |
723 | ␉␉␉␉␉␉␊ |
724 | ␉␉␉␉␉␉bool cpu_noninteger_bus_ratio = (rdmsr64(MSR_IA32_PERF_STATUS) & (1ULL << 46));␊ |
725 | ␉␉␉␉␉␉␊ |
726 | ␉␉␉␉␉␉initial.Control = rdmsr64(MSR_IA32_PERF_STATUS);␊ |
727 | ␉␉␉␉␉␉␊ |
728 | ␉␉␉␉␉␉maximum.Control = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 32) & 0x1F3F) | (0x4000 * cpu_noninteger_bus_ratio);␊ |
729 | ␉␉␉␉␉␉maximum.CID = ((maximum.FID & 0x1F) << 1) | cpu_noninteger_bus_ratio;␊ |
730 | ␉␉␉␉␉␉␊ |
731 | ␉␉␉␉␉␉minimum.FID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 24) & 0x1F) | (0x80 * cpu_dynamic_fsb);␊ |
732 | ␉␉␉␉␉␉minimum.VID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 48) & 0x3F);␊ |
733 | ␉␉␉␉␉␉␊ |
734 | ␉␉␉␉␉␉if (minimum.FID == 0) ␊ |
735 | ␉␉␉␉␉␉{␊ |
736 | ␉␉␉␉␉␉␉U64 msr;␊ |
737 | ␉␉␉␉␉␉␉U8 i;␊ |
738 | ␉␉␉␉␉␉␉// Probe for lowest fid␊ |
739 | ␉␉␉␉␉␉␉for (i = maximum.FID; i >= 0x6; i--) ␊ |
740 | ␉␉␉␉␉␉␉{␊ |
741 | ␉␉␉␉␉␉␉␉msr = rdmsr64(MSR_IA32_PERF_CONTROL);␊ |
742 | ␉␉␉␉␉␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (i << 8) | minimum.VID);␊ |
743 | ␉␉␉␉␉␉␉␉intel_waitforsts();␊ |
744 | ␉␉␉␉␉␉␉␉minimum.FID = (rdmsr64(MSR_IA32_PERF_STATUS) >> 8) & 0x1F; ␊ |
745 | ␉␉␉␉␉␉␉␉delay(1);␊ |
746 | ␉␉␉␉␉␉␉}␊ |
747 | ␉␉␉␉␉␉␉␊ |
748 | ␉␉␉␉␉␉␉msr = rdmsr64(MSR_IA32_PERF_CONTROL);␊ |
749 | ␉␉␉␉␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);␊ |
750 | ␉␉␉␉␉␉␉intel_waitforsts();␊ |
751 | ␉␉␉␉␉␉}␊ |
752 | ␉␉␉␉␉␉␊ |
753 | ␉␉␉␉␉␉if (minimum.VID == maximum.VID) ␊ |
754 | ␉␉␉␉␉␉{␉␊ |
755 | ␉␉␉␉␉␉␉U64 msr;␊ |
756 | ␉␉␉␉␉␉␉U8 i;␊ |
757 | ␉␉␉␉␉␉␉// Probe for lowest vid␊ |
758 | ␉␉␉␉␉␉␉for (i = maximum.VID; i > 0xA; i--) ␊ |
759 | ␉␉␉␉␉␉␉{␊ |
760 | ␉␉␉␉␉␉␉␉msr = rdmsr64(MSR_IA32_PERF_CONTROL);␊ |
761 | ␉␉␉␉␉␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (minimum.FID << 8) | i);␊ |
762 | ␉␉␉␉␉␉␉␉intel_waitforsts();␊ |
763 | ␉␉␉␉␉␉␉␉minimum.VID = rdmsr64(MSR_IA32_PERF_STATUS) & 0x3F; ␊ |
764 | ␉␉␉␉␉␉␉␉delay(1);␊ |
765 | ␉␉␉␉␉␉␉}␊ |
766 | ␉␉␉␉␉␉␉␊ |
767 | ␉␉␉␉␉␉␉msr = rdmsr64(MSR_IA32_PERF_CONTROL);␊ |
768 | ␉␉␉␉␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);␊ |
769 | ␉␉␉␉␉␉␉intel_waitforsts();␊ |
770 | ␉␉␉␉␉␉}␊ |
771 | ␉␉␉␉␉␉␊ |
772 | ␉␉␉␉␉␉minimum.CID = ((minimum.FID & 0x1F) << 1) >> cpu_dynamic_fsb;␊ |
773 | ␉␉␉␉␉␉␊ |
774 | ␉␉␉␉␉␉// Sanity check␊ |
775 | ␉␉␉␉␉␉if (maximum.CID < minimum.CID) ␊ |
776 | ␉␉␉␉␉␉{␊ |
777 | ␉␉␉␉␉␉␉DBG("Insane FID values!");␊ |
778 | ␉␉␉␉␉␉␉p_states_count = 0;␊ |
779 | ␉␉␉␉␉␉}␊ |
780 | ␉␉␉␉␉␉else␊ |
781 | ␉␉␉␉␉␉{␊ |
782 | ␉␉␉␉␉␉␉// Finalize P-States␊ |
783 | ␉␉␉␉␉␉␉// Find how many P-States machine supports␊ |
784 | ␉␉␉␉␉␉␉p_states_count = maximum.CID - minimum.CID + 1;␊ |
785 | ␉␉␉␉␉␉␉␊ |
786 | ␉␉␉␉␉␉␉if (p_states_count > 32) ␊ |
787 | ␉␉␉␉␉␉␉␉p_states_count = 32;␊ |
788 | ␉␉␉␉␉␉␉␊ |
789 | ␉␉␉␉␉␉␉U8 vidstep;␊ |
790 | ␉␉␉␉␉␉␉U8 i = 0, u, invalid = 0;␊ |
791 | ␉␉␉␉␉␉␉␊ |
792 | ␉␉␉␉␉␉␉vidstep = ((maximum.VID << 2) - (minimum.VID << 2)) / (p_states_count - 1);␊ |
793 | ␉␉␉␉␉␉␉␊ |
794 | ␉␉␉␉␉␉␉for (u = 0; u < p_states_count; u++) ␊ |
795 | ␉␉␉␉␉␉␉{␊ |
796 | ␉␉␉␉␉␉␉␉i = u - invalid;␊ |
797 | ␉␉␉␉␉␉␉␉␊ |
798 | ␉␉␉␉␉␉␉␉p_states[i].CID = maximum.CID - u;␊ |
799 | ␉␉␉␉␉␉␉␉p_states[i].FID = (p_states[i].CID >> 1);␊ |
800 | ␉␉␉␉␉␉␉␉␊ |
801 | ␉␉␉␉␉␉␉␉if (p_states[i].FID < 0x6) ␊ |
802 | ␉␉␉␉␉␉␉␉{␊ |
803 | ␉␉␉␉␉␉␉␉␉if (cpu_dynamic_fsb) ␊ |
804 | ␉␉␉␉␉␉␉␉␉␉p_states[i].FID = (p_states[i].FID << 1) | 0x80;␊ |
805 | ␉␉␉␉␉␉␉␉} ␊ |
806 | ␉␉␉␉␉␉␉␉else if (cpu_noninteger_bus_ratio) ␊ |
807 | ␉␉␉␉␉␉␉␉{␊ |
808 | ␉␉␉␉␉␉␉␉␉p_states[i].FID = p_states[i].FID | (0x40 * (p_states[i].CID & 0x1));␊ |
809 | ␉␉␉␉␉␉␉␉}␊ |
810 | ␉␉␉␉␉␉␉␉␊ |
811 | ␉␉␉␉␉␉␉␉if (i && p_states[i].FID == p_states[i-1].FID)␊ |
812 | ␉␉␉␉␉␉␉␉␉invalid++;␊ |
813 | ␉␉␉␉␉␉␉␉␊ |
814 | ␉␉␉␉␉␉␉␉p_states[i].VID = ((maximum.VID << 2) - (vidstep * u)) >> 2;␊ |
815 | ␉␉␉␉␉␉␉␉␊ |
816 | ␉␉␉␉␉␉␉␉U32 multiplier = p_states[i].FID & 0x1f;␉␉// = 0x08␊ |
817 | ␉␉␉␉␉␉␉␉bool half = p_states[i].FID & 0x40;␉␉␉␉␉// = 0x01␊ |
818 | ␉␉␉␉␉␉␉␉bool dfsb = p_states[i].FID & 0x80;␉␉␉␉␉// = 0x00␊ |
819 | ␉␉␉␉␉␉␉␉U32 fsb = Platform->CPU.FSBFrequency / 1000000; // = 400␊ |
820 | ␉␉␉␉␉␉␉␉U32 halffsb = (fsb + 1) >> 1;␉␉␉␉␉// = 200␊ |
821 | ␉␉␉␉␉␉␉␉U32 frequency = (multiplier * fsb);␉␉␉// = 3200␊ |
822 | ␉␉␉␉␉␉␉␉␊ |
823 | ␉␉␉␉␉␉␉␉p_states[i].Frequency = (frequency + (half * halffsb)) >> dfsb;␉// = 3200 + 200 = 3400␊ |
824 | ␉␉␉␉␉␉␉}␊ |
825 | ␉␉␉␉␉␉␉␊ |
826 | ␉␉␉␉␉␉␉p_states_count -= invalid;␊ |
827 | ␉␉␉␉␉␉}␊ |
828 | ␉␉␉␉␉␉break;␊ |
829 | ␉␉␉␉␉} ␊ |
830 | ␉␉␉␉␉case CPUID_MODEL_FIELDS:␊ |
831 | ␉␉␉␉␉case CPUID_MODEL_DALES:␊ |
832 | ␉␉␉␉␉case CPUID_MODEL_DALES_32NM:␊ |
833 | ␉␉␉␉␉case CPUID_MODEL_NEHALEM: ␊ |
834 | ␉␉␉␉␉case CPUID_MODEL_NEHALEM_EX:␊ |
835 | ␉␉␉␉␉case CPUID_MODEL_WESTMERE:␊ |
836 | ␉␉␉␉␉case CPUID_MODEL_WESTMERE_EX:␊ |
837 | ␉␉␉␉␉case CPUID_MODEL_SANDYBRIDGE:␊ |
838 | case CPUID_MODEL_JAKETOWN:␊ |
839 | ␉␉␉␉␉{␉␉␊ |
840 | ␉␉␉␉␉␉maximum.Control = rdmsr64(MSR_IA32_PERF_STATUS) & 0xff; // Seems it always contains maximum multiplier value (with turbo, that's we need)...␊ |
841 | ␉␉␉␉␉␉minimum.Control = (rdmsr64(MSR_PLATFORM_INFO) >> 40) & 0xff;␊ |
842 | ␉␉␉␉␉␉␊ |
843 | ␉␉␉␉␉␉verbose("P-States: min 0x%x, max 0x%x\n", minimum.Control, maximum.Control);␊ |
844 | ␉␉␉␉␉␉␊ |
845 | ␉␉␉␉␉␉// Sanity check␊ |
846 | ␉␉␉␉␉␉if (maximum.Control < minimum.Control) ␊ |
847 | ␉␉␉␉␉␉{␊ |
848 | ␉␉␉␉␉␉␉DBG("Insane control values!");␊ |
849 | ␉␉␉␉␉␉␉p_states_count = 0;␊ |
850 | ␉␉␉␉␉␉}␊ |
851 | ␉␉␉␉␉␉else␊ |
852 | ␉␉␉␉␉␉{␊ |
853 | ␉␉␉␉␉␉␉U8 i;␊ |
854 | ␉␉␉␉␉␉␉p_states_count = 0;␊ |
855 | ␉␉␉␉␉␉␉␊ |
856 | ␉␉␉␉␉␉␉for (i = maximum.Control; i >= minimum.Control; i--) ␊ |
857 | ␉␉␉␉␉␉␉{␊ |
858 | ␉␉␉␉␉␉␉␉p_states[p_states_count].Control = i;␊ |
859 | ␉␉␉␉␉␉␉␉p_states[p_states_count].CID = p_states[p_states_count].Control << 1;␊ |
860 | ␉␉␉␉␉␉␉␉p_states[p_states_count].Frequency = (Platform->CPU.FSBFrequency / 1000000) * i;␊ |
861 | ␉␉␉␉␉␉␉␉p_states_count++;␊ |
862 | ␉␉␉␉␉␉␉}␊ |
863 | ␉␉␉␉␉␉}␊ |
864 | ␉␉␉␉␉␉␊ |
865 | ␉␉␉␉␉␉break;␊ |
866 | ␉␉␉␉␉}␊ |
867 | ␉␉␉␉␉default:␊ |
868 | ␉␉␉␉␉␉verbose ("Unsupported CPU: P-States will not be generated !!!\n");␊ |
869 | ␉␉␉␉␉␉break;␊ |
870 | ␉␉␉␉}␊ |
871 | ␉␉␉}␊ |
872 | ␉␉␉default:␊ |
873 | ␉␉␉␉break;␊ |
874 | ␉␉}␊ |
875 | ␉␉␊ |
876 | ␉␉// Generating SSDT␊ |
877 | ␉␉if (p_states_count) ␊ |
878 | ␉␉{␉␊ |
879 | ␉␉␉unsigned int i;␊ |
880 | ␉␉␉␊ |
881 | ␉␉␉struct aml_chunk* root = aml_create_node(NULL);␊ |
882 | aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header␊ |
883 | ␉␉␉struct aml_chunk* scop;␊ |
884 | ␉␉␉if (cpuNamespace == CPU_NAMESPACE_PR) ␊ |
885 | ␉␉␉␉␉scop = aml_add_scope(root, "\\_PR_");␊ |
886 | ␉␉␉else if (cpuNamespace == CPU_NAMESPACE_SB) ␊ |
887 | ␉␉␉␉␉scop = aml_add_scope(root, "\\_SB_");␊ |
888 | else ␊ |
889 | ␉␉␉{␊ |
890 | aml_destroy_node(root);␉␊ |
891 | goto out;␊ |
892 | }␉␉␉␉␊ |
893 | struct aml_chunk* name = aml_add_name(scop, "PSS_");␊ |
894 | struct aml_chunk* pack = aml_add_package(name);␊ |
895 | ␉␉␉␊ |
896 | U8 minPSratio = (p_states[p_states_count-1].Frequency / (Platform->CPU.FSBFrequency / 10000000 ));␊ |
897 | U8 maxPSratio = (p_states[0].Frequency / (Platform->CPU.FSBFrequency / 10000000 ));␊ |
898 | ␊ |
899 | U8 cpu_div = Platform->CPU.CurrDiv;␊ |
900 | U8 cpu_ratio = 0;␊ |
901 | ␉␉␉␊ |
902 | if (cpu_div) ␉␉␉␉␉␉␉␉␊ |
903 | cpu_ratio = (Platform->CPU.CurrCoef * 10) + 5;␉␉␉␉␉␉␉␉␊ |
904 | else ␉␉␉␉␉␉␉␉␊ |
905 | cpu_ratio = Platform->CPU.CurrCoef * 10;␊ |
906 | ␊ |
907 | ␉␉␉␊ |
908 | int user_max_ratio = 0;␊ |
909 | getIntForKey(kMaxRatio, &user_max_ratio, &bootInfo->bootConfig);␊ |
910 | if (user_max_ratio >= minPSratio && maxPSratio >= user_max_ratio) {␉␉␉␉␉␉␉␉␉␊ |
911 | ␉␉␉␉␊ |
912 | U8 maxcurrdiv = 0, maxcurrcoef = (int)(user_max_ratio / 10);␉␉␉␉␉␉␉␉␉␊ |
913 | ␉␉␉␉␊ |
914 | U8 maxdiv = user_max_ratio - (maxcurrcoef * 10);␊ |
915 | if (maxdiv > 0)␊ |
916 | maxcurrdiv = 1;␊ |
917 | ␉␉␉␉␊ |
918 | if (maxcurrdiv) ␉␉␉␉␉␉␉␉␉␊ |
919 | cpu_ratio = (maxcurrcoef * 10) + 5;␉␉␉␉␉␉␉␉␉␊ |
920 | else ␉␉␉␉␉␉␉␉␉␊ |
921 | cpu_ratio = maxcurrcoef * 10;␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␊ |
922 | }␊ |
923 | ␉␉␉␊ |
924 | int user_min_ratio = 0;␊ |
925 | getIntForKey(kMinRatio, &user_min_ratio, &bootInfo->bootConfig);␊ |
926 | if (user_min_ratio >= minPSratio && cpu_ratio >= user_min_ratio) {␊ |
927 | ␉␉␉␉␊ |
928 | U8 mincurrdiv = 0, mincurrcoef = (int)(user_min_ratio / 10);␉␉␉␉␉␉␉␉␉␊ |
929 | ␉␉␉␉␊ |
930 | U8 mindiv = user_min_ratio - (mincurrcoef * 10);␊ |
931 | ␉␉␉␉␊ |
932 | if (mindiv > 0)␊ |
933 | mincurrdiv = 1;␉␉␉␉␉␉␉␉␉␊ |
934 | ␉␉␉␉␊ |
935 | if (mincurrdiv) ␉␉␉␉␉␉␉␉␉␊ |
936 | minPSratio = (mincurrcoef * 10) + 5;␉␉␉␉␉␉␉␉␉␊ |
937 | else ␉␉␉␉␉␉␉␉␉␊ |
938 | minPSratio = mincurrcoef * 10;␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␊ |
939 | ␉␉␉␉␊ |
940 | }␊ |
941 | ␉␉␉␊ |
942 | if (maxPSratio >= cpu_ratio && cpu_ratio >= minPSratio)␉maxPSratio = cpu_ratio;␉␉␉␉␉␉␉␉␉␉␉␉␉␊ |
943 | ␉␉␉␊ |
944 | TagPtr personality = XMLCastDict(XMLGetProperty(bootInfo->bootConfig.dictionary, (const char*)"P-States"));␊ |
945 | char* MatchStat = 0;␊ |
946 | int dropPSS = 0, Pstatus = 0, base = 16;␉␉␉␉␉␉␉␉␊ |
947 | int expert = 0;/* Default: 0 , mean mixed mode | expert mode : 1 , mean add only p-states found in boot.plist*/␊ |
948 | char *tmpstr = XMLCastString(XMLGetProperty(personality, (const char*)"Mode"));␊ |
949 | ␊ |
950 | if (strcmp(tmpstr,"Expert") == 0) {␊ |
951 | p_states_count = (XMLTagCount(personality)) - 1 ; // - 1 = - ("Mode" tag) ␉␉␉␉␉␉␉␉␉␉␊ |
952 | expert = 1;␊ |
953 | }␊ |
954 | ␉␉␉␊ |
955 | ␊ |
956 | if ((tmpstr = XMLCastString(XMLGetProperty(personality, (const char*)"Base")))) {␊ |
957 | ␊ |
958 | if (expert) p_states_count--; // -= ("Base" tag) ␊ |
959 | ␊ |
960 | int mybase = strtol(tmpstr, NULL, 10);␉␊ |
961 | ␊ |
962 | if (mybase == 8 || mybase == 10 || mybase == 16 )␊ |
963 | base = mybase;␉␉␉␉␉␉␉␉␉␊ |
964 | }␊ |
965 | ␉␉␉␊ |
966 | for (i = 0; i < p_states_count; i++) ␊ |
967 | {␉␉␉␉␉␉␉␉␉␊ |
968 | sprintf(MatchStat, "%d",i);␊ |
969 | TagPtr match_Status = XMLGetProperty(personality, (const char*)MatchStat); ␉␉␉␉␉␉␉␉ ␊ |
970 | ␊ |
971 | char *Lat1 = NULL, *clk = NULL, *Pw = NULL, *Lat2 = NULL, *Ctrl = NULL ;␊ |
972 | ␊ |
973 | if (match_Status) {␉␉␉␉␉␉␉␉␉␉␉␉␊ |
974 | ␊ |
975 | clk = XMLCastString(XMLGetProperty(match_Status, (const char*)"CoreFreq"));␊ |
976 | Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power"));␊ |
977 | Lat1 = XMLCastString(XMLGetProperty(match_Status, (const char*)"Transition Latency"));␊ |
978 | Lat2 = XMLCastString(XMLGetProperty(match_Status, (const char*)"Bus Master Latency"));␊ |
979 | Ctrl = XMLCastString(XMLGetProperty(match_Status, (const char*)"Control"));␊ |
980 | ␊ |
981 | ␊ |
982 | } else if (expert) ␊ |
983 | continue;␊ |
984 | ␊ |
985 | ␊ |
986 | unsigned long Frequency = 0x00000000;␊ |
987 | ␊ |
988 | if (!expert) Frequency = p_states[i].Frequency;␊ |
989 | ␊ |
990 | if (clk) ␊ |
991 | Frequency = strtoul((const char *)clk, NULL,base);␊ |
992 | ␊ |
993 | if (!Frequency || Frequency > p_states[0].Frequency ) continue;␊ |
994 | ␊ |
995 | U8 curr_ratio = (Frequency / (Platform->CPU.FSBFrequency / 10000000 ));␊ |
996 | ␊ |
997 | if (curr_ratio > maxPSratio || minPSratio > curr_ratio)␊ |
998 | goto dropPstate;␊ |
999 | ␊ |
1000 | struct aml_chunk* pstt = aml_add_package(pack);␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␊ |
1001 | aml_add_dword(pstt, Frequency); // CoreFreq (in MHz).␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␊ |
1002 | aml_add_dword(pstt, resolve_pss(0x00000000, Pw, base)); // Power (in milliWatts)␉␉␉␉␉␉␉␉␉␊ |
1003 | aml_add_dword(pstt, resolve_pss(0x0000000A, Lat1, base)); // Transition Latency (in microseconds).␉␉␉␉␉␉␉␉␉␊ |
1004 | aml_add_dword(pstt, resolve_pss(0x0000000A, Lat2, base)); // Bus Master Latency (in microseconds).␉␉␉␉␉␉␉␉␉␊ |
1005 | unsigned long Control = 0x00000000;␊ |
1006 | if (!expert) Control = p_states[i].Control;␉␉␉␉␉␉␉␉␉␊ |
1007 | aml_add_dword(pstt, resolve_pss(Control, Ctrl, base)); // Control␉␉␉␉␉␉␉␉␉␊ |
1008 | Pstatus++;␊ |
1009 | aml_add_dword(pstt, Pstatus); // Status␉␉␉␉␉␉␉␉␉␊ |
1010 | continue;␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␊ |
1011 | dropPstate:␊ |
1012 | ␊ |
1013 | DBG("state with cpu frequency :%d and ratio :%d will be dropped\n",p_states[i].Frequency,curr_ratio);␉␉␊ |
1014 | ␊ |
1015 | dropPSS++;␊ |
1016 | ␊ |
1017 | ␊ |
1018 | }␉␉␉␊ |
1019 | ␉␉␉␊ |
1020 | ␊ |
1021 | ␉␉␉// Add aliaces␊ |
1022 | ␉␉␉for (i = 0; i < cpu_map_count; i++) ␊ |
1023 | ␉␉␉{␊ |
1024 | ␉␉␉␉char name[9];␊ |
1025 | U32 nseg = *(U32*)cpu_map[i].nameseg;␊ |
1026 | if (cpuNamespace == CPU_NAMESPACE_PR) {␊ |
1027 | sprintf(name, "_PR_%c%c%c%c",␊ |
1028 | (int)(nseg & 0x000000ff),␊ |
1029 | (int)((nseg & 0x0000ff00) >> 8),␊ |
1030 | (int)((nseg & 0x00ff0000) >> 16),␊ |
1031 | (int)(nseg >> 24));␊ |
1032 | } else if (cpuNamespace == CPU_NAMESPACE_SB) {␊ |
1033 | sprintf(name, "_SB_%c%c%c%c",␊ |
1034 | (int)(nseg & 0x000000ff),␊ |
1035 | (int)((nseg & 0x0000ff00) >> 8),␊ |
1036 | (int)((nseg & 0x00ff0000) >> 16),␊ |
1037 | (int)(nseg >> 24));␊ |
1038 | } else {␊ |
1039 | aml_destroy_node(root);␉␊ |
1040 | goto out;␊ |
1041 | }␊ |
1042 | ␊ |
1043 | ␉␉␉␉scop = aml_add_scope(root, name);␊ |
1044 | ␉␉␉␉aml_add_alias(scop, "PSS_", "_PSS");␊ |
1045 | ␉␉␉}␊ |
1046 | ␉␉␉␊ |
1047 | ␉␉␉aml_calculate_size(root);␊ |
1048 | ␉␉␉␊ |
1049 | ␉␉␉ACPI_TABLE_SSDT *ssdt = (ACPI_TABLE_SSDT *)AllocateKernelMemory(root->Size);␊ |
1050 | ␉␉␉␊ |
1051 | ␉␉␉aml_write_node(root, (void*)ssdt, 0);␊ |
1052 | ␉␉␉␊ |
1053 | ␉␉␉ssdt->Header.Length = root->Size;␊ |
1054 | ␉␉␉␊ |
1055 | SetChecksum(&ssdt->Header);␊ |
1056 | ␉␉␉␊ |
1057 | ␉␉␉aml_destroy_node(root);␉␉␉␊ |
1058 | ␉␉␉␊ |
1059 | ␉␉␉verbose ("SSDT with CPU P-States generated successfully");␊ |
1060 | ␉␉␉␊ |
1061 | ␉␉␉if (dropPSS)␊ |
1062 | verbose(", %d P-state(s) dropped",dropPSS);␊ |
1063 | ␉␉␉␊ |
1064 | ␉␉␉verbose("\n");␊ |
1065 | ␉␉␉␊ |
1066 | ␉␉␉return ssdt;␊ |
1067 | ␉␉}␊ |
1068 | ␉}␊ |
1069 | ␉else ␊ |
1070 | ␉{␊ |
1071 | out:␊ |
1072 | ␉␉verbose("ACPI CPUs not found: P-States will not be generated !!!\n");␊ |
1073 | ␉}␊ |
1074 | ␉␊ |
1075 | ␉return (void *)0ul;␊ |
1076 | }␊ |
1077 | #if UNUSED␊ |
1078 | ACPI_TABLE_FACS* generate_facs(bool updatefacs )␊ |
1079 | {␊ |
1080 | ACPI_TABLE_FACS* facs_mod=(ACPI_TABLE_FACS *)AllocateKernelMemory(sizeof(ACPI_TABLE_FACS));␊ |
1081 | bzero(facs_mod, sizeof(ACPI_TABLE_FACS));␊ |
1082 | ␉␊ |
1083 | ␉ACPI_TABLE_FACS * FacsPointer =(acpi_tables.FacsPointer64 != (void *)0ul) ? ␊ |
1084 | ␉(ACPI_TABLE_FACS *)acpi_tables.FacsPointer64 : (ACPI_TABLE_FACS *)acpi_tables.FacsPointer;␊ |
1085 | ␉␊ |
1086 | memcpy(facs_mod, FacsPointer , FacsPointer->Length);␊ |
1087 | facs_mod->Length = sizeof(ACPI_TABLE_FACS);␊ |
1088 | ␉␉ ␊ |
1089 | ␉if (FacsPointer->Length < sizeof(ACPI_TABLE_FACS)) {␊ |
1090 | ␉␉facs_mod->FirmwareWakingVector = 0;␊ |
1091 | ␉␉facs_mod->GlobalLock = 0;␊ |
1092 | ␉␉facs_mod->Flags = 0;␊ |
1093 | ␉}␉␉␊ |
1094 | ␊ |
1095 | if (updatefacs && FacsPointer->Version < 2) {␊ |
1096 | ␉␉if (FacsPointer->Version > 0) {␊ |
1097 | ␉␉␉facs_mod->XFirmwareWakingVector = FacsPointer->XFirmwareWakingVector;␊ |
1098 | ␉␉} else {␊ |
1099 | ␉␉␉facs_mod->XFirmwareWakingVector = (U64)facs_mod->FirmwareWakingVector;␊ |
1100 | ␉␉}␊ |
1101 | ␊ |
1102 | ␉␉facs_mod->Version = 2; /* ACPI 1.0: 0, ACPI 2.0/3.0: 1, ACPI 4.0: 2 */␊ |
1103 | ␉␉␊ |
1104 | ␉}␊ |
1105 | ␊ |
1106 | return facs_mod;␊ |
1107 | }␊ |
1108 | #endif␊ |
1109 | ␊ |
1110 | ACPI_GENERIC_ADDRESS FillGASStruct(U32 Address, U8 Length)␊ |
1111 | {␊ |
1112 | ␉ACPI_GENERIC_ADDRESS TmpGAS;␊ |
1113 | ␉␊ |
1114 | ␉TmpGAS.SpaceId = 1; /* I/O Address */␊ |
1115 | ␉␊ |
1116 | ␉if (Address == 0)␊ |
1117 | ␉{␊ |
1118 | ␉␉TmpGAS.BitWidth = 0;␊ |
1119 | ␉} else {␊ |
1120 | ␉␉TmpGAS.BitWidth = Length * 8;␊ |
1121 | ␉}␊ |
1122 | ␉␊ |
1123 | ␉TmpGAS.BitOffset = 0;␊ |
1124 | ␉TmpGAS.AccessWidth = 0; /* Not set for Legacy reasons... */␊ |
1125 | ␉TmpGAS.Address = (U64)Address;␊ |
1126 | ␉␊ |
1127 | ␉return (TmpGAS);␊ |
1128 | }␊ |
1129 | ␊ |
1130 | ACPI_TABLE_FADT *␊ |
1131 | patch_fadt(ACPI_TABLE_FADT *fadt, ACPI_TABLE_DSDT *new_dsdt, bool UpdateFADT)␊ |
1132 | {␉␉␊ |
1133 | ␉ACPI_TABLE_FADT *fadt_mod = (void*)0;␊ |
1134 | ␉bool fadt_rev2_needed = false;␊ |
1135 | ␉bool fix_restart = false;␉␊ |
1136 | ␉const char * value;␉␊ |
1137 | ␊ |
1138 | ␉// Restart Fix␊ |
1139 | ␉if (Platform->CPU.Vendor == 0x756E6547) {␉/* Intel */␊ |
1140 | ␉␉fix_restart = true;␊ |
1141 | ␉␉getBoolForKey(kRestartFix, &fix_restart, &bootInfo->bootConfig);␊ |
1142 | ␉␉␊ |
1143 | ␉} else {␊ |
1144 | ␉␉verbose ("Not an Intel platform: Restart Fix disabled !!!\n");␊ |
1145 | ␉}␊ |
1146 | ␉␊ |
1147 | ␉if (fix_restart)␊ |
1148 | ␉␉fadt_rev2_needed = true;␊ |
1149 | ␉␉␉␊ |
1150 | ␉// Allocate new fadt table␊ |
1151 | ␉if (UpdateFADT) ␊ |
1152 | ␉{ ␊ |
1153 | if (fadt->Header.Length < 0xF4)␊ |
1154 | ␉ {␊ |
1155 | ␉␉␉fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(0xF4);␊ |
1156 | ␉␉ bzero(fadt_mod, 0xF4);␊ |
1157 | ␉␉␉memcpy(fadt_mod, fadt, fadt->Header.Length);␊ |
1158 | ␉␉␉fadt_mod->Header.Length = 0xF4;␊ |
1159 | ␉␉}␊ |
1160 | ␉␉else␊ |
1161 | ␉␉{␉␉␉␊ |
1162 | ␉␉␉fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(fadt->Header.Length);␉␊ |
1163 | ␉␉␉memcpy(fadt_mod, fadt, fadt->Header.Length);␊ |
1164 | ␉␉}␉␉ ␊ |
1165 | ␉␉␉␉␊ |
1166 | ␊ |
1167 | ␉␉//fadt_mod->Header.Revision = 0x04; // FADT rev 4␊ |
1168 | ␉␉fadt_mod->ResetRegister = FillGASStruct(0, 0);␊ |
1169 | ␉␉fadt_mod->ResetValue = 0;␊ |
1170 | ␉␉fadt_mod->Reserved4[0] = 0;␊ |
1171 | ␉␉fadt_mod->Reserved4[1] = 0;␊ |
1172 | ␉␉fadt_mod->Reserved4[2] = 0;␊ |
1173 | ␊ |
1174 | fadt_mod->XPm1aEventBlock = FillGASStruct(fadt_mod->Pm1aEventBlock, fadt_mod->Pm1EventLength);␊ |
1175 | ␉␉fadt_mod->XPm1bEventBlock = FillGASStruct(fadt_mod->Pm1bEventBlock, fadt_mod->Pm1EventLength);␊ |
1176 | ␉␉fadt_mod->XPm1aControlBlock = FillGASStruct(fadt_mod->Pm1aControlBlock, fadt_mod->Pm1ControlLength);␊ |
1177 | ␉␉fadt_mod->XPm1bControlBlock = FillGASStruct(fadt_mod->Pm1bControlBlock, fadt_mod->Pm1ControlLength);␊ |
1178 | ␉␉fadt_mod->XPm2ControlBlock = FillGASStruct(fadt_mod->Pm2ControlBlock, fadt_mod->Pm2ControlLength);␊ |
1179 | ␉␉fadt_mod->XPmTimerBlock = FillGASStruct(fadt_mod->PmTimerBlock, fadt_mod->PmTimerLength);␊ |
1180 | ␉␉fadt_mod->XGpe0Block = FillGASStruct(fadt_mod->Gpe0Block, fadt_mod->Gpe0BlockLength);␊ |
1181 | ␉␉fadt_mod->XGpe1Block = FillGASStruct(fadt_mod->Gpe1Block, fadt_mod->Gpe1BlockLength);␉␊ |
1182 | if (fadt->Header.Revision < 4) {␉␉␉␉␉␊ |
1183 | ␉␉␉fadt_mod->Header.Revision = 0x04; // FADT rev 4␊ |
1184 | ␉␉␉verbose("Converted ACPI V%d FADT to ACPI V4 FADT\n", fadt->Header.Revision);␊ |
1185 | ␊ |
1186 | ␉␉}␊ |
1187 | ␉} else {␊ |
1188 | ␉␉␊ |
1189 | ␉␉if (fadt_rev2_needed)␊ |
1190 | ␉␉{␊ |
1191 | ␉␉␉if (fadt->Header.Length < 0x84 )␊ |
1192 | ␉␉␉{␊ |
1193 | ␉␉␉␉fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(0x84);␊ |
1194 | ␉␉␉␉bzero(fadt_mod, 0x84);␊ |
1195 | ␉␉␉␉memcpy(fadt_mod, fadt, fadt->Header.Length);␊ |
1196 | ␉␉␉␉fadt_mod->Header.Length = 0x84;␊ |
1197 | ␉␉␉} else {␊ |
1198 | ␉␉␉␉fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(fadt->Header.Length);␊ |
1199 | ␉␉␉␉memcpy(fadt_mod, fadt, fadt->Header.Length);␊ |
1200 | ␉␉␉}␉␉␉␊ |
1201 | ␉␉␉␊ |
1202 | ␉␉␉if (fadt->Header.Revision < 2) {␉␉␉␉␉␊ |
1203 | ␉␉␉␉fadt_mod->Header.Revision = 0x02; // FADT rev 2 (ACPI 1.0B MS extensions) ␊ |
1204 | ␉␉␉␉verbose("Converted ACPI V%d FADT to ACPI V2 FADT\n", fadt->Header.Revision );␊ |
1205 | ␉␉␉}␊ |
1206 | ␉␉} else {␊ |
1207 | ␉␉␉if (fadt->Header.Length < 0x74 )␊ |
1208 | ␉␉␉{␊ |
1209 | ␉␉␉␉fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(0x74);␊ |
1210 | ␉␉␉␉bzero(fadt_mod, 0x74);␊ |
1211 | ␉␉␉␉memcpy(fadt_mod, fadt, fadt->Header.Length);␊ |
1212 | ␉␉␉␉fadt_mod->Header.Length = 0x74;␊ |
1213 | ␉␉␉␉fadt_mod->Header.Revision = 0x01; ␊ |
1214 | ␉␉␉␉verbose("Warning: ACPI FADT length was < 0x74 which is the minimum for the ACPI FADT V1 specification, \n", fadt->Header.Revision );␊ |
1215 | ␉␉␉␉verbose(" trying to convert it to Version 1. \n");␉␉␉␉␊ |
1216 | ␊ |
1217 | ␉␉␉} else {␊ |
1218 | ␉␉␉␉fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(fadt->Header.Length);␊ |
1219 | ␉␉␉␉memcpy(fadt_mod, fadt, fadt->Header.Length);␊ |
1220 | ␉␉␉}␊ |
1221 | ␉␉}␉␉ ␉␉␊ |
1222 | ␉}␊ |
1223 | ␉bool intelfadtspec = true;␊ |
1224 | ␉U8 Type = PMProfileError;␊ |
1225 | ␉// Determine system type / PM_Model␊ |
1226 | ␉␊ |
1227 | ␉// Fix System-type if needed (should never happen)␊ |
1228 | ␉if (Platform->Type > MaxSupportedPMProfile) ␊ |
1229 | ␉{␊ |
1230 | ␉␉if(fadt_mod->PreferredProfile <= MaxSupportedPMProfile)␊ |
1231 | ␉␉␉Platform->Type = fadt_mod->PreferredProfile; // get the fadt if correct␊ |
1232 | ␉␉else ␊ |
1233 | ␉␉␉Platform->Type = 1;␉␉/* Set a fixed value (Desktop) */␊ |
1234 | ␉}␊ |
1235 | ␉␊ |
1236 | ␉// If needed, set System-type from PM_Profile (if valid) else set PM_Profile with a fixed the System-type ␊ |
1237 | ␉// Give prior to the FADT pm profile, allow to also control this value with a patched FADT table␊ |
1238 | ␉if (fadt_mod->PreferredProfile != Platform->Type) ␊ |
1239 | ␉{␊ |
1240 | ␉␉bool val = false; ␊ |
1241 | ␉␉getBoolForKey("PreferInternalProfileDetect", &val, &bootInfo->bootConfig); // if true Give prior to the profile resolved trought the CPU model␊ |
1242 | ␉␉␊ |
1243 | ␉␉val = Platform->CPU.isServer ;␊ |
1244 | ␉␉␊ |
1245 | ␉␉if (fadt_mod->PreferredProfile <= MaxSupportedPMProfile && !val) {␊ |
1246 | ␉␉␉Platform->Type = fadt_mod->PreferredProfile;␊ |
1247 | ␉␉} else {␊ |
1248 | ␉␉␉fadt_mod->PreferredProfile = Platform->Type;␊ |
1249 | ␉␉}␉␉␊ |
1250 | ␉␉␊ |
1251 | ␉}␊ |
1252 | ␉␊ |
1253 | ␉// Set PM_Profile and System-type if user wanted this value to be forced␊ |
1254 | ␉if ( (value=getStringForKey("SystemType", &bootInfo->bootConfig))!=NULL) {␊ |
1255 | ␉␉if ((Type = (unsigned char) strtoul(value, NULL, 10) ) <= MaxSupportedPMProfile)␊ |
1256 | ␉␉{␊ |
1257 | ␉␉␉if (fadt_mod->PreferredProfile != Type) {␊ |
1258 | ␉␉␉␉verbose("FADT: changing Preferred_PM_Profile from %d to %d\n", fadt->PreferredProfile, Type);␊ |
1259 | ␉␉␉␉fadt_mod->PreferredProfile = Platform->Type = Type;␊ |
1260 | ␉␉␉} else {␊ |
1261 | ␉␉␉␉DBG("FADT: Preferred_PM_Profile was already set to %d, no need to be changed\n",Type);␊ |
1262 | ␉␉␉}␊ |
1263 | ␉␉␉␊ |
1264 | ␉␉} else printf("Error: system-type must be 0..6. Defaulting to %d !\n", Platform->Type);␊ |
1265 | ␉}␉␉␊ |
1266 | ␉␊ |
1267 | ␉getBoolForKey(KIntelFADT, &intelfadtspec, &bootInfo->bootConfig);␊ |
1268 | ␉if ((pmbase == 0) && (cpu_map_error == 0) && (intelfadtspec == true)) ␊ |
1269 | ␉{␊ |
1270 | ␉␉ACPI_TABLE_DSDT *DsdtPointer ;␊ |
1271 | ␉␉if (new_dsdt != (void*)0ul) ␊ |
1272 | ␉␉␉DsdtPointer = new_dsdt;␊ |
1273 | ␉␉else if ((fadt_mod->Header.Revision >= 3) && (fadt_mod->XDsdt != 0ul))␊ |
1274 | ␉␉␉DsdtPointer = (ACPI_TABLE_DSDT *)((U32)fadt_mod->XDsdt);␊ |
1275 | ␉␉else␊ |
1276 | ␉␉␉DsdtPointer = (ACPI_TABLE_DSDT *)fadt_mod->Dsdt;␊ |
1277 | ␉␉␊ |
1278 | ␉␉generate_cpu_map_from_acpi(DsdtPointer);␊ |
1279 | ␉}␉␊ |
1280 | ␉␊ |
1281 | ␉// Patch DSDT Address if we have loaded a DSDT table␊ |
1282 | ␉if(new_dsdt != (void*)0ul)␉␉␊ |
1283 | ␉␉fadt_mod->Dsdt=(U32)new_dsdt;␉␊ |
1284 | ␉␊ |
1285 | ␉fadt_mod->Facs= fadt->Facs;␊ |
1286 | ␉//fadt_mod->Facs=(U32)generate_facs(false);␊ |
1287 | ␊ |
1288 | ␉// Patch FADT to fix restart␊ |
1289 | ␉if (fadt_mod->Header.Revision >= 2 && fix_restart)␊ |
1290 | ␉{␉␉␊ |
1291 | fadt_mod->Flags|= 0x400;␉␉␊ |
1292 | ␉␉␊ |
1293 | ␉␉int type = PCI_RESET_TYPE;␊ |
1294 | ␉␉getIntForKey(KResetType, &type, &bootInfo->bootConfig);␊ |
1295 | ␉␉if (type == KEYBOARD_RESET_TYPE) {␊ |
1296 | ␉␉␉//Azi: keyboard reset; http://forum.voodooprojects.org/index.php/topic,1056.msg9802.html#msg9802␊ |
1297 | ␉␉␉fadt_mod->ResetRegister = FillGASStruct(0x64, 1);␊ |
1298 | ␉␉␉fadt_mod->ResetValue = 0xfe;␊ |
1299 | ␉␉} else {␊ |
1300 | ␉␉␉fadt_mod->ResetRegister = FillGASStruct(0x0cf9, 1);␊ |
1301 | ␉␉␉fadt_mod->ResetValue = 0x06;␊ |
1302 | ␉␉}␊ |
1303 | ␉␉verbose("FADT: Restart Fix applied (Type : %s) !\n", (type == 0) ? "PCI": "KEYBOARD");␊ |
1304 | ␉}␊ |
1305 | ␉ ␊ |
1306 | if (fadt_mod->Header.Revision >= 3) { ␊ |
1307 | ␊ |
1308 | ␊ |
1309 | if (UpdateFADT) { ␊ |
1310 | ␊ |
1311 | ␉␉␉//fadt_mod->XFacs= (U64)((U32)generate_facs(true));␊ |
1312 | fadt_mod->XFacs=(U64)fadt->Facs; ␊ |
1313 | ␊ |
1314 | } else {␊ |
1315 | ␉␉␉fadt_mod->XFacs=(U64)fadt->XFacs;␊ |
1316 | ␉␉}␊ |
1317 | ␊ |
1318 | ␊ |
1319 | if(new_dsdt != (void*)0ul)␊ |
1320 | fadt_mod->XDsdt=((U64)(U32)new_dsdt);␊ |
1321 | ␉␉else if (UpdateFADT)␊ |
1322 | ␉␉␉␉fadt_mod->XDsdt=(U64)fadt_mod->Dsdt;␊ |
1323 | ␊ |
1324 | ␊ |
1325 | Platform->hardware_signature = ((ACPI_TABLE_FACS *)((U32)fadt_mod->XFacs))->HardwareSignature;␊ |
1326 | ␊ |
1327 | } else {␊ |
1328 | ␊ |
1329 | Platform->hardware_signature = ␉((ACPI_TABLE_FACS *)fadt_mod->Facs)->HardwareSignature;␊ |
1330 | ␊ |
1331 | } ␊ |
1332 | ␉␊ |
1333 | ␊ |
1334 | ␉DBG("setting hardware_signature to %x \n",Platform->hardware_signature); ␊ |
1335 | ␉␉␉␊ |
1336 | ␉␉␊ |
1337 | ␊ |
1338 | ␉if (pmbase && (intelfadtspec == true))␊ |
1339 | ␉␉ProcessFadt(fadt_mod, pmbase); // The checksum correction will be done by ProcessFadt␊ |
1340 | ␉else␊ |
1341 | ␉␉SetChecksum(&fadt_mod->Header); // Correct the checksum␊ |
1342 | ␊ |
1343 | ␉return fadt_mod;␊ |
1344 | }␊ |
1345 | ␊ |
1346 | void process_xsdt (ACPI_TABLE_RSDP *rsdp_mod , U32 *new_table_list){␊ |
1347 | ␉TagPtr DropTables_p = XMLCastDict(XMLGetProperty(bootInfo->bootConfig.dictionary, (const char*)"ACPIDropTables"));␊ |
1348 | ␉U32 new_table = 0ul;␊ |
1349 | ␉U8 new_table_index = 0, table_added = 0;␊ |
1350 | ␉ACPI_TABLE_XSDT *xsdt = (void*)0ul, *xsdt_mod = (void*)0ul;␊ |
1351 | ␉ACPI_TABLE_RSDT *rsdt_conv␉= (void *)0ul;␊ |
1352 | ␉␊ |
1353 | ␉// FIXME: handle 64-bit address correctly␊ |
1354 | ␉␊ |
1355 | ␉xsdt=(ACPI_TABLE_XSDT *)acpi_tables.XsdtPointer;␊ |
1356 | ␉␊ |
1357 | ␉verbose("* Processing XSDT: \n");␊ |
1358 | ␉␊ |
1359 | ␉DBG("XSDT @%x, Length=%d\n", (U32)xsdt,␊ |
1360 | ␉␉xsdt->Header.Length);␊ |
1361 | ␉␊ |
1362 | ␉if (xsdt != (void *)0ul)␊ |
1363 | ␉{␉␉␉␉␊ |
1364 | ␉␉U32 dropoffset=0, index;␊ |
1365 | ␉␉table_added = 0;␊ |
1366 | ␉␉␊ |
1367 | ␉␉xsdt_mod=(ACPI_TABLE_XSDT *)AllocateKernelMemory(xsdt->Header.Length); ␊ |
1368 | ␉␉bzero(xsdt_mod, xsdt->Header.Length);␊ |
1369 | ␉␉memcpy(&xsdt_mod->Header, &xsdt->Header, sizeof(ACPI_TABLE_HEADER));␊ |
1370 | ␉␉␊ |
1371 | ␉␉U32 num_tables=get_num_tables64(xsdt);␊ |
1372 | ␉␉␊ |
1373 | ␉␉ACPI_TABLE_HEADER *table = (ACPI_TABLE_HEADER *) xsdt->TableOffsetEntry;␊ |
1374 | ␉␉␊ |
1375 | ␉␉for (index = 0; index < num_tables; index++) {␊ |
1376 | ␉␉␉if (GetChecksum(table, table->Length) == 0) {␊ |
1377 | ␉␉␉␉␊ |
1378 | ␉␉␉␉xsdt_mod->TableOffsetEntry[index-dropoffset]=xsdt->TableOffsetEntry[index];␊ |
1379 | ␉␉␉␉␊ |
1380 | ␉␉␉␉char tableSig[4];␊ |
1381 | ␉␉␉␉bool oem = false;␊ |
1382 | ␉␉␉␉char oemOption[OEMOPT_SIZE];␊ |
1383 | ␉␉␉␉␊ |
1384 | ␉␉␉␉strlcpy(tableSig, (char*)((U32)(xsdt->TableOffsetEntry[index])), sizeof(tableSig)+1);␊ |
1385 | ␉␉␉␉␊ |
1386 | ␉␉␉␉sprintf(oemOption, "oem%s",tableSig );␊ |
1387 | ␉␉␉␉if (getBoolForKey(oemOption, &oem, &bootInfo->bootConfig) && oem) { // This method don't work for DSDT and FACS␊ |
1388 | ␉␉␉␉␉␊ |
1389 | ␉␉␉␉␉if (get_new_table_in_list(new_table_list,((U32) (table->Signature)), &new_table_index) != (void*)0ul) ␊ |
1390 | ␉␉␉␉␉␉new_table_list[new_table_index] = 0ul; // This way new table will not be added to the new rsdt list !!␊ |
1391 | ␉␉␉␉␉␊ |
1392 | ␉␉␉␉␉continue;␊ |
1393 | ␉␉␉␉}␊ |
1394 | ␉␉␉␉␊ |
1395 | ␉␉␉␉TagPtr match_drop = XMLGetProperty(DropTables_p, (const char*)tableSig); ␊ |
1396 | ␉␉␉␉if ( match_drop ) {␊ |
1397 | ␉␉␉␉␉char *tmp = XMLCastString(match_drop);␊ |
1398 | ␉␉␉␉␉if (strcmp(tmp,"No") != 0) {␊ |
1399 | ␉␉␉␉␉␉dropoffset++;␊ |
1400 | ␉␉␉␉␉␉DBG("%s table dropped\n",tableSig);␊ |
1401 | ␉␉␉␉␉␉continue;␊ |
1402 | ␉␉␉␉␉}␊ |
1403 | ␉␉␉␉}␊ |
1404 | ␉␉␉␉␊ |
1405 | ␉␉␉␉if ((new_table = (U32)get_new_table_in_list(new_table_list,((U32) (table->Signature)), &new_table_index)) != 0ul)␊ |
1406 | ␉␉␉␉{␊ |
1407 | ␉␉␉␉␉xsdt_mod->TableOffsetEntry[index-dropoffset]=(U64)new_table;␊ |
1408 | ␉␉␉␉␉new_table_list[new_table_index] = 0ul; // table replaced !!␊ |
1409 | ␉␉␉␉␉continue;␊ |
1410 | ␉␉␉␉}␊ |
1411 | ␉␉␉}␊ |
1412 | ␉␉␉// Move array pointer to next 64-bit pointer␊ |
1413 | ␉␉␉table = (ACPI_TABLE_HEADER *) ((U32) table + sizeof(U64));␊ |
1414 | ␉␉} ␊ |
1415 | ␉␉␊ |
1416 | ␉␉␊ |
1417 | ␉␉{␊ |
1418 | ␉␉␉U8 i;␊ |
1419 | ␉␉␉for (i = 0; i< (MAX_ACPI_TABLE + RESERVED_AERA); i++) {␊ |
1420 | ␉␉␉␉if (new_table_list[i] != 0ul) {␊ |
1421 | ␉␉␉␉␉xsdt_mod->TableOffsetEntry[index-dropoffset]=(U64)new_table_list[i];␊ |
1422 | ␉␉␉␉␉table_added++;␊ |
1423 | ␉␉␉␉␉index++;␊ |
1424 | ␉␉␉␉}␊ |
1425 | ␉␉␉}␊ |
1426 | ␉␉}␊ |
1427 | ␉␉␊ |
1428 | ␉␉// Correct the checksum of XSDT␊ |
1429 | ␉␉xsdt_mod->Header.Length-=8*dropoffset;␊ |
1430 | ␉␉xsdt_mod->Header.Length+=8*table_added;␊ |
1431 | ␉␉␊ |
1432 | ␉␉SetChecksum(&xsdt_mod->Header);␊ |
1433 | ␉␉␊ |
1434 | ␉␉update_rsdp_with_xsdt(rsdp_mod, xsdt_mod);␊ |
1435 | ␉␉␊ |
1436 | ␉␉verbose("* Creating new RSDT from XSDT table\n");␊ |
1437 | ␉␉␊ |
1438 | ␉␉rsdt_conv = (ACPI_TABLE_RSDT *)gen_alloc_rsdt_from_xsdt(xsdt_mod);␊ |
1439 | ␉␉update_rsdp_with_rsdt(rsdp_mod, rsdt_conv);␉␉␉␉␊ |
1440 | ␉␉␊ |
1441 | ␉␉␊ |
1442 | ␉␉␊ |
1443 | ␉}␊ |
1444 | ␉else␊ |
1445 | ␉{␉␉␉␉␊ |
1446 | ␉␉DBG("About to drop XSDT\n");␊ |
1447 | ␉␉␊ |
1448 | ␉␉/*FIXME: Now we just hope that if MacOS doesn't find XSDT it reverts to RSDT. ␊ |
1449 | ␉␉ * A Better strategy would be to generate␊ |
1450 | ␉␉ */␊ |
1451 | ␉␉␊ |
1452 | ␉␉rsdp_mod->XsdtPhysicalAddress=0xffffffffffffffffLL;␊ |
1453 | ␉␉verbose("XSDT not found or XSDT incorrect\n");␊ |
1454 | ␉}␊ |
1455 | ␊ |
1456 | }␊ |
1457 | ␊ |
1458 | void process_rsdt(ACPI_TABLE_RSDP *rsdp_mod , bool gen_xsdt, U32 *new_table_list)␊ |
1459 | {␉␉␉␊ |
1460 | ␉TagPtr DropTables_p = XMLCastDict(XMLGetProperty(bootInfo->bootConfig.dictionary, (const char*)"ACPIDropTables"));␊ |
1461 | ␉U32 new_table = 0ul;␊ |
1462 | ␉U8 new_table_index = 0, table_added = 0;␊ |
1463 | ␉U32 dropoffset=0, index;␊ |
1464 | ␉ACPI_TABLE_RSDT *rsdt␉␉ = (void *)0ul, *rsdt_mod␉= (void *)0ul;␊ |
1465 | ␉ACPI_TABLE_XSDT *xsdt_conv␉ = (void *)0ul;␊ |
1466 | ␉␊ |
1467 | ␉rsdt=(ACPI_TABLE_RSDT *)acpi_tables.RsdtPointer;␊ |
1468 | ␉␊ |
1469 | ␉DBG("RSDT @%x, Length %d\n",rsdt, rsdt->Header.Length);␉␊ |
1470 | ␉␊ |
1471 | ␉rsdt_mod=(ACPI_TABLE_RSDT *)AllocateKernelMemory(rsdt->Header.Length);␊ |
1472 | ␉bzero(rsdt_mod, rsdt->Header.Length);␊ |
1473 | ␉memcpy (&rsdt_mod->Header, &rsdt->Header, sizeof(ACPI_TABLE_HEADER));␊ |
1474 | ␉␊ |
1475 | ␉U32 num_tables = get_num_tables(rsdt); ␊ |
1476 | ␉␊ |
1477 | ␉verbose("* Processing RSDT: \n");␉␉␉␊ |
1478 | ␉ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) rsdt->TableOffsetEntry;␊ |
1479 | ␉␊ |
1480 | ␉// Compute number of table pointers included in RSDT␊ |
1481 | ␉num_tables = get_num_tables(rsdt);␊ |
1482 | ␉␊ |
1483 | ␉for (index = 0; index < num_tables; index++) {␊ |
1484 | ␉␉if (GetChecksum(table_array[index], table_array[index]->Length) == 0) {␊ |
1485 | ␉␉␉␊ |
1486 | ␉␉␉rsdt_mod->TableOffsetEntry[index-dropoffset]=rsdt->TableOffsetEntry[index];␊ |
1487 | ␉␉␉␊ |
1488 | ␉␉␉char tableSig[4];␊ |
1489 | ␉␉␉bool oem = false;␊ |
1490 | ␉␉␉char oemOption[OEMOPT_SIZE];␊ |
1491 | ␉␉␉␊ |
1492 | ␉␉␉strlcpy(tableSig, (char*)(rsdt->TableOffsetEntry[index]), sizeof(tableSig)+1);␊ |
1493 | ␉␉␉␊ |
1494 | ␉␉␉sprintf(oemOption, "oem%s",tableSig );␊ |
1495 | ␉␉␉if (getBoolForKey(oemOption, &oem, &bootInfo->bootConfig) && oem) { // This method don't work for DSDT and FACS␊ |
1496 | ␉␉␉␉␊ |
1497 | ␉␉␉␉if (get_new_table_in_list(new_table_list,(*(U32 *) (table_array[index]->Signature)), &new_table_index) != (void*)0ul ) ␊ |
1498 | ␉␉␉␉␉new_table_list[new_table_index] = 0ul; // This way new table will not be added to the new rsdt list !!␊ |
1499 | ␉␉␉␉␊ |
1500 | ␉␉␉␉continue;␊ |
1501 | ␉␉␉}␊ |
1502 | ␉␉␉␊ |
1503 | ␉␉␉TagPtr match_drop = XMLGetProperty(DropTables_p, (const char*)tableSig);␊ |
1504 | ␉␉␉if ( match_drop ) {␊ |
1505 | ␉␉␉␉char *tmp = XMLCastString(match_drop);␊ |
1506 | ␉␉␉␉if (strcmp(tmp,"No") != 0) {␉␉␉␉␉␉␊ |
1507 | ␉␉␉␉␉dropoffset++;␊ |
1508 | ␉␉␉␉␉DBG("%s table dropped\n",tableSig);␊ |
1509 | ␉␉␉␉␉continue;␊ |
1510 | ␉␉␉␉}␊ |
1511 | ␉␉␉}␉␉␉␉␊ |
1512 | ␉␉␉␊ |
1513 | ␉␉␉if ((new_table = (U32)get_new_table_in_list(new_table_list,(*(U32 *) (table_array[index]->Signature)), &new_table_index)) != 0ul)␊ |
1514 | ␉␉␉{␉␉␉␉␉␊ |
1515 | ␉␉␉␉rsdt_mod->TableOffsetEntry[index-dropoffset]=new_table;␊ |
1516 | ␉␉␉␉new_table_list[new_table_index] = 0ul; // table replaced !!␊ |
1517 | ␉␉␉␉continue;␊ |
1518 | ␉␉␉}␊ |
1519 | ␉␉␉␊ |
1520 | ␉␉}␊ |
1521 | ␉}␉␉␉␊ |
1522 | ␉DBG("\n");␊ |
1523 | ␉␊ |
1524 | ␉{␊ |
1525 | ␉␉U8 i;␊ |
1526 | ␉␉for (i = 0; i< (MAX_ACPI_TABLE + RESERVED_AERA); i++) {␊ |
1527 | ␉␉␉if (new_table_list[i] != 0ul) {␊ |
1528 | ␉␉␉␉rsdt_mod->TableOffsetEntry[index-dropoffset]=new_table_list[i];␊ |
1529 | ␉␉␉␉table_added++;␊ |
1530 | ␉␉␉␉index++;␊ |
1531 | ␉␉␉}␊ |
1532 | ␉␉}␊ |
1533 | ␉}␉␉␊ |
1534 | ␉␊ |
1535 | ␉// Correct the checksum of RSDT␊ |
1536 | ␉rsdt_mod->Header.Length-=4*dropoffset;␊ |
1537 | ␉rsdt_mod->Header.Length+=4*table_added;␉␉␊ |
1538 | ␉␊ |
1539 | ␉DBG("RSDT: Original checksum %d\n", rsdt_mod->Header.Checksum);␉␉␉␊ |
1540 | ␉␊ |
1541 | ␉SetChecksum(&rsdt_mod->Header);␊ |
1542 | ␉␊ |
1543 | ␉DBG("New checksum %d at %x\n", rsdt_mod->Header.Checksum,rsdt_mod);␊ |
1544 | ␉␊ |
1545 | ␉update_rsdp_with_rsdt(rsdp_mod, rsdt_mod);␊ |
1546 | ␉␊ |
1547 | ␉if (gen_xsdt)␊ |
1548 | ␉{␊ |
1549 | ␉␉verbose("* Creating new XSDT from RSDT table\n");␊ |
1550 | ␉␉xsdt_conv = (ACPI_TABLE_XSDT *)gen_alloc_xsdt_from_rsdt(rsdt_mod);␊ |
1551 | ␉␉update_rsdp_with_xsdt(rsdp_mod, xsdt_conv); ␉␉␉␉␊ |
1552 | ␉␉␊ |
1553 | ␉}␉␊ |
1554 | }␉␊ |
1555 | ␊ |
1556 | ␊ |
1557 | ␊ |
1558 | EFI_STATUS setupAcpi(void)␊ |
1559 | {␉␊ |
1560 | ␉U8 Revision = 0;␊ |
1561 | ␉␊ |
1562 | cpu_map_error = 0;␊ |
1563 | cpu_map_count = 0;␊ |
1564 | pmbase = 0;␊ |
1565 | ␊ |
1566 | EFI_STATUS Status = EFI_ABORTED;␊ |
1567 | ␉␊ |
1568 | ␉U32 new_table_list[MAX_ACPI_TABLE + RESERVED_AERA]; //max table + reserved aera ␊ |
1569 | ␉U8 new_table_index = 0;␊ |
1570 | ␉␊ |
1571 | ␉ACPI_TABLE_DSDT* DsdtPtr␉ = (void *)0ul; // a Pointer to the dsdt table present in fadt_mod␊ |
1572 | ␉␊ |
1573 | ␉ACPI_TABLE_DSDT *new_dsdt␉ = (void *)0ul;␉// a Pointer to the dsdt file␉␊ |
1574 | ␉ACPI_TABLE_FADT *fadt_mod␉ = (void *)0ul; // a Pointer to the patched FACP table␊ |
1575 | ␉ACPI_TABLE_FADT *fadt_file␉ = (void *)0ul; // a Pointer to the (non-patched) fadt file ␊ |
1576 | ␉ACPI_TABLE_FADT *FacpPointer = (void *)0ul; // a Pointer to the non-patched FACP table, it can be a file or the FACP table found in the RSDT/XSDT␊ |
1577 | ␉ACPI_TABLE_RSDP *rsdp_mod␉ = (void *)0ul, *rsdp_conv␉= (void *)0ul;␊ |
1578 | ␉␊ |
1579 | ␉␊ |
1580 | ␉U32 rsdplength;␊ |
1581 | ␉␊ |
1582 | ␉bool update_acpi=false, gen_xsdt=false;␊ |
1583 | ␉␊ |
1584 | ␉bool gen_csta=false, gen_psta=false, speed_step=false;␊ |
1585 | ␉␊ |
1586 | ␉bool oem_dsdt=false, oem_fadt=false;␊ |
1587 | ␉␊ |
1588 | ␉// Find original rsdp ␊ |
1589 | ␉if (!FindAcpiTables(&acpi_tables)){␊ |
1590 | ␉␉printf("Error: AcpiCodec Failed to detect ACPI tables.\n");␊ |
1591 | ␉␉getc();␊ |
1592 | ␉␉return EFI_NOT_FOUND;␊ |
1593 | ␉}␊ |
1594 | ␉␊ |
1595 | ␉{␊ |
1596 | ␉␉U8 i;␊ |
1597 | ␉␉␊ |
1598 | ␉␉for (i=0; i<(MAX_ACPI_TABLE + RESERVED_AERA); i++) {␊ |
1599 | ␉␉␉new_table_list[i] = 0ul;␊ |
1600 | ␉␉}␊ |
1601 | ␉␉bool tmpval;␊ |
1602 | ␉␉␊ |
1603 | ␉␉oem_dsdt=getBoolForKey(kOEMDSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;␊ |
1604 | ␉␉oem_fadt=getBoolForKey(kOEMFADT, &tmpval, &bootInfo->bootConfig)&&tmpval;␊ |
1605 | ␊ |
1606 | ␉␉␊ |
1607 | ␉␉gen_csta=getBoolForKey(kGenerateCStates, &tmpval, &bootInfo->bootConfig)&&tmpval;␊ |
1608 | ␉␉gen_psta=getBoolForKey(kGeneratePStates, &tmpval, &bootInfo->bootConfig)&&tmpval;␊ |
1609 | ␊ |
1610 | ␉␉update_acpi=getBoolForKey(kUpdateACPI, &tmpval, &bootInfo->bootConfig)&&tmpval;␊ |
1611 | ␉␉␊ |
1612 | ␉␉speed_step=getBoolForKey(kSpeedstep, &tmpval, &bootInfo->bootConfig)&&tmpval;␊ |
1613 | ␉␉␊ |
1614 | ␉} ␊ |
1615 | ␉␉␊ |
1616 | ␉{␊ |
1617 | ␉␉char* name;␊ |
1618 | ␉␉long flags;␊ |
1619 | ␉␉long time;␊ |
1620 | ␉␉long ret = -1;␊ |
1621 | ␉␉U8 i = 0;␊ |
1622 | ␉␉char dirspec[512];␊ |
1623 | ␉␉bool acpidir_found = false;␊ |
1624 | ␉␉␊ |
1625 | ␉␉ret = GetFileInfo("/Extra/", "Acpi", &flags, &time);␊ |
1626 | ␉␉if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory)) {␊ |
1627 | ␉␉␉sprintf(dirspec, "/Extra/Acpi/");␊ |
1628 | ␉␉␉acpidir_found = true;␊ |
1629 | ␊ |
1630 | ␉␉} else {␊ |
1631 | ␉␉␉ret = GetFileInfo("bt(0,0)/Extra/", "Acpi", &flags, &time);␊ |
1632 | ␉␉␉if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory)) {␊ |
1633 | ␉␉␉␉sprintf(dirspec, "bt(0,0)/Extra/Acpi/");␊ |
1634 | ␉␉␉␉acpidir_found = true;␊ |
1635 | ␊ |
1636 | ␉␉␉} ␊ |
1637 | ␉␉}␊ |
1638 | ␊ |
1639 | ␉␉if (acpidir_found == true) {␊ |
1640 | ␉␉␉struct dirstuff* moduleDir = opendir(dirspec);␊ |
1641 | ␉␉␉while(readdir(moduleDir, (const char**)&name, &flags, &time) >= 0)␊ |
1642 | ␉␉␉{␉␉␊ |
1643 | ␉␉␉␉if((strcmp(&name[strlen(name) - sizeof("aml")], ".aml") == 0) && ((strlen(dirspec)+strlen(name)) < 512))␊ |
1644 | ␉␉␉␉{␉␉␉␉␉␊ |
1645 | ␉␉␉␉␉// Some simple verifications to save time in case of those tables simply named as follow:␊ |
1646 | ␉␉␉␉␉if ((strncmp(name, "RSDT", 4) == 0) || (strncmp(name, "rsdt", 4) == 0) ||␊ |
1647 | ␉␉␉␉␉␉(strncmp(name, "XSDT", 4) == 0) || (strncmp(name, "xsdt", 4) == 0) ||␊ |
1648 | ␉␉␉␉␉␉(strncmp(name, "RSDP", 4) == 0) || (strncmp(name, "rsdp", 4) == 0))␊ |
1649 | ␉␉␉␉␉{ ␊ |
1650 | ␉␉␉␉␉␉continue;␊ |
1651 | ␉␉␉␉␉}␊ |
1652 | ␉␉␉␉␉␊ |
1653 | ␉␉␉␉␉if ((strncmp(name, "FACS", 4) == 0) || (strncmp(name, "facs", 4) == 0)) { // For now FACS is not supported␊ |
1654 | ␉␉␉␉␉␉continue;␊ |
1655 | ␉␉␉␉␉}␉␉␉␉␉␊ |
1656 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␊ |
1657 | ␉␉␉␉␉char* tmp = malloc(strlen(name) + 1);␊ |
1658 | ␉␉␉␉␉strcpy(tmp, name);␊ |
1659 | ␉␉␉␉␉␊ |
1660 | ␉␉␉␉␉DBG("* Attempting to load acpi table: %s\n", tmp);␉␉␉␊ |
1661 | ␉␉␉␉␉if( (new_table_list[i]=(U32)loadACPITable(dirspec,tmp)))␊ |
1662 | ␉␉␉␉␉{␊ |
1663 | ␉␉␉␉␉␉if (i < MAX_ACPI_TABLE) {␊ |
1664 | ␉␉␉␉␉␉␉i++;␊ |
1665 | ␉␉␉␉␉␉} else {␊ |
1666 | ␉␉␉␉␉␉␉break;␊ |
1667 | ␉␉␉␉␉␉}␊ |
1668 | ␊ |
1669 | ␉␉␉␉␉␉␊ |
1670 | ␉␉␉␉␉} else {␊ |
1671 | ␉␉␉␉␉␉free(tmp);␊ |
1672 | ␉␉␉␉␉}␊ |
1673 | ␊ |
1674 | ␉␉␉␉}␊ |
1675 | #if DEBUG_ACPI␊ |
1676 | ␉␉␉␉else ␊ |
1677 | ␉␉␉␉{␊ |
1678 | ␉␉␉␉␉DBG("Ignoring %s\n", name);␊ |
1679 | ␉␉␉␉}␊ |
1680 | #endif␊ |
1681 | ␉␉␉␉␊ |
1682 | ␉␉␉}␊ |
1683 | ␉␉␉␊ |
1684 | ␉␉␉if (i) {␊ |
1685 | ␉␉␉␉//sanitize the new tables list ␊ |
1686 | ␉␉␉␉sanitize_new_table_list(new_table_list);␊ |
1687 | ␉␉␉␉␊ |
1688 | ␉␉␉␉//move to kernel memory ␊ |
1689 | ␉␉␉␉move_table_list_to_kmem(new_table_list);␊ |
1690 | ␉␉␉␉␊ |
1691 | ␉␉␉␉DBG("New ACPI tables Loaded in memory\n");␊ |
1692 | ␉␉␉}␊ |
1693 | ␉␉}␊ |
1694 | ␉␉␊ |
1695 | ␉}␉␉␉␊ |
1696 | ␊ |
1697 | ␉// TODO : Add an option for that␊ |
1698 | //cpuNamespace = CPU_NAMESPACE_PR; //Default␊ |
1699 | ␊ |
1700 | ␊ |
1701 | ␉if (speed_step) {␊ |
1702 | ␉␉gen_psta= true;␊ |
1703 | ␉␉gen_csta= true;␊ |
1704 | ␉} ␉␉␊ |
1705 | ␉ ␊ |
1706 | ␉␊ |
1707 | ␉ACPI_TABLE_RSDP *rsdp=(ACPI_TABLE_RSDP *)acpi_tables.RsdPointer;␊ |
1708 | ␉␊ |
1709 | ␉if (rsdp == (void*)0ul || (GetChecksum(rsdp, (rsdp->Revision == 0) ? ACPI_RSDP_REV0_SIZE:sizeof(ACPI_TABLE_RSDP)) != 0) ) {␊ |
1710 | ␉␉printf("Error : ACPI RSD PTR Revision %d checksum is incorrect or table not found \n",rsdp->Revision );␊ |
1711 | ␉␉return EFI_UNSUPPORTED;␊ |
1712 | ␉}␊ |
1713 | ␉␊ |
1714 | ␉if ((update_acpi) && (rsdp->Revision == 0))␊ |
1715 | ␉{␊ |
1716 | ␉␉␊ |
1717 | ␉␉rsdp_conv = (ACPI_TABLE_RSDP *)gen_alloc_rsdp_v2_from_v1(rsdp);␊ |
1718 | ␉␉if (rsdp_conv != (void *)0ul) {␊ |
1719 | ␉␉␉gen_xsdt = true; ␊ |
1720 | ␉␉␉rsdp = rsdp_conv;␊ |
1721 | ␉␉␉verbose("Converted ACPI RSD PTR Revision 0 to Revision 2\n");␊ |
1722 | ␉␉}␊ |
1723 | ␉␉␊ |
1724 | ␉}␊ |
1725 | ␉␊ |
1726 | ␉Revision = rsdp->Revision ;␊ |
1727 | ␉rsdplength=(Revision == 2)?rsdp->Length:ACPI_RSDP_REV0_SIZE;␊ |
1728 | ␉␊ |
1729 | ␉DBG("RSDP Revision %d found @%x. Length=%d\n",Revision,rsdp,rsdplength);␊ |
1730 | ␉␊ |
1731 | ␉/* FIXME: no check that memory allocation succeeded ␊ |
1732 | ␉ * Copy and patch RSDP,RSDT, XSDT and FADT␊ |
1733 | ␉ * For more info see ACPI Specification pages 110 and following␊ |
1734 | ␉ */␊ |
1735 | ␉␊ |
1736 | ␉if (gen_xsdt)␊ |
1737 | ␉{␊ |
1738 | ␉␉rsdp_mod=rsdp_conv;␊ |
1739 | ␉} else {␊ |
1740 | ␉␉rsdp_mod=(ACPI_TABLE_RSDP *) AllocateKernelMemory(rsdplength);␊ |
1741 | ␉␉memcpy(rsdp_mod, rsdp, rsdplength);␊ |
1742 | ␉}␉␊ |
1743 | ␉␊ |
1744 | ␉␉␊ |
1745 | ␉if ((fadt_file = (ACPI_TABLE_FADT *)get_new_table_in_list(new_table_list, NAMESEG("FACP"), &new_table_index)) != (void *)0ul) {␊ |
1746 | ␉␉␊ |
1747 | ␉␉if (oem_fadt == false)␊ |
1748 | ␉␉␉FacpPointer = (ACPI_TABLE_FADT *)fadt_file;␊ |
1749 | ␉␉␊ |
1750 | ␉␉new_table_list[new_table_index] = 0ul; // This way, the non-patched table will not be added in our new rsdt/xsdt table list␊ |
1751 | ␉␉␊ |
1752 | ␉} else␊ |
1753 | ␉␉FacpPointer = (acpi_tables.FacpPointer64 != (void *)0ul) ? ␊ |
1754 | ␉␉(ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer;␉␉␉␊ |
1755 | ␉␊ |
1756 | #if DEBUG_ACPI␊ |
1757 | ␉if ((FacpPointer != (void *)0ul) || (oem_fadt == false)) {␊ |
1758 | ␉␉printf("FADT found @%x, Length %d\n",FacpPointer, FacpPointer->Header.Length);␊ |
1759 | ␉␉printf("Attempting to patch FADT entry of %s\n",(acpi_tables.FacpPointer64 != (void *)0ul) ? ACPI_SIG_XSDT : ACPI_SIG_RSDT);␊ |
1760 | ␉}␊ |
1761 | #endif␉␊ |
1762 | ␉␊ |
1763 | ␉if ((new_dsdt = (ACPI_TABLE_DSDT *)get_new_table_in_list(new_table_list, NAMESEG("DSDT"), &new_table_index)) != (void*)0ul ) {␊ |
1764 | ␉␉new_table_list[new_table_index] = 0ul; // This way, the DSDT file will not be added in our new rsdt/xsdt table list, and it shouldn't be anyway␊ |
1765 | ␉}␊ |
1766 | ␉␊ |
1767 | ␉if (oem_fadt == false) {␊ |
1768 | ␉␉␊ |
1769 | ␉␉fadt_mod = patch_fadt(FacpPointer, (oem_dsdt == false) ? new_dsdt : (void*)0ul , (acpi_tables.FacpPointer64 != (void *)0ul ));␉␊ |
1770 | ␉␉␊ |
1771 | ␉␉␊ |
1772 | ␉␉DsdtPtr = ((fadt_mod->Header.Revision >= 3) && (fadt_mod->XDsdt != 0)) ? (ACPI_TABLE_DSDT*)((U32)fadt_mod->XDsdt):(ACPI_TABLE_DSDT*)fadt_mod->Dsdt;␊ |
1773 | ␉␉␊ |
1774 | ␉␉if (fadt_mod != (void*)0ul) {␊ |
1775 | ␉␉␉␊ |
1776 | ␉␉␉U8 empty = get_0ul_index_in_list(new_table_list,true);␊ |
1777 | ␉␉␉if (empty != ACPI_TABLE_LIST_FULL) {␊ |
1778 | ␉␉␉␉new_table_list[empty] = (U32)fadt_mod; // add the patched table to the list␊ |
1779 | ␉␉␉} else {␊ |
1780 | ␉␉␉␉printf("Error: not enought reserved space in the new acpi list for the Patched FACP table,\n ");␊ |
1781 | ␉␉␉␉printf(" please increase the RESERVED_AERA\n");␊ |
1782 | ␉␉␉}␉␉␉␊ |
1783 | ␉␉␉␊ |
1784 | ␉␉} else {␊ |
1785 | ␉␉␉printf("Error: Failed to patch the FADT Table, trying fallback to the FADT original pointer\n");␊ |
1786 | ␉␉␉fadt_mod = (acpi_tables.FacpPointer64 != (void *)0ul) ? ␊ |
1787 | ␉␉␉(ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer;␊ |
1788 | ␉␉␉␊ |
1789 | ␉␉␉U8 empty = get_0ul_index_in_list(new_table_list,true);␊ |
1790 | ␉␉␉if (empty != ACPI_TABLE_LIST_FULL) {␊ |
1791 | ␉␉␉␉new_table_list[empty] = (U32)fadt_mod; ␊ |
1792 | ␉␉␉} else {␊ |
1793 | ␉␉␉␉printf("Error: not enought reserved space in the new acpi list for the FACP table,\n ");␊ |
1794 | ␉␉␉␉printf(" please increase the RESERVED_AERA\n");␊ |
1795 | ␉␉␉}␊ |
1796 | ␉␉}␉␊ |
1797 | ␉␉␊ |
1798 | ␉␉if (oem_dsdt == false) {␊ |
1799 | ␉␉␉if (generate_cpu_map_from_acpi(DsdtPtr) == 0){␊ |
1800 | ␉␉␉␉U8 new_uid = (U8)getPciRootUID();␊ |
1801 | ␉␉␉␉␊ |
1802 | ␉␉␉␉/* WARNING: THIS METHOD WORK PERFECTLY BUT IT CAN RESULT TO AN INCORRECT CHECKSUM */␊ |
1803 | ␉␉␉␉␊ |
1804 | ␉␉␉␉if (ProcessDsdt(DsdtPtr, UIDPointer, new_uid)) {␊ |
1805 | ␉␉␉␉␉printf("PCI0 _UID patched to %d in the DSDT table\n", new_uid);␊ |
1806 | ␉␉␉␉}␉␉␉␉␊ |
1807 | ␉␉␉␉␊ |
1808 | ␉␉␉}␊ |
1809 | ␉␉}␊ |
1810 | ␉␉␊ |
1811 | ␉␉ ␊ |
1812 | ␉} else {␊ |
1813 | ␉␉␊ |
1814 | ␉␉// here we use the variable fadt_mod only for SSDT Generation␊ |
1815 | ␉␉␊ |
1816 | ␉␉fadt_mod = (acpi_tables.FacpPointer64 != (void *)0ul) ? ␊ |
1817 | ␉␉(ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer;␊ |
1818 | ␉␉␊ |
1819 | ␉␉DsdtPtr = ((fadt_mod->Header.Revision >= 3) && (fadt_mod->XDsdt != 0)) ? (ACPI_TABLE_DSDT*)((U32)fadt_mod->XDsdt)␊ |
1820 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉:(ACPI_TABLE_DSDT*)fadt_mod->Dsdt;␊ |
1821 | ␉}␊ |
1822 | ␉␊ |
1823 | ␉if (speed_step || gen_csta || gen_psta) {␊ |
1824 | ␉␉U8 empty = get_0ul_index_in_list(new_table_list, true);␊ |
1825 | ␉␉␊ |
1826 | ␉␉// Generate _CST SSDT␊ |
1827 | ␉␉if ( speed_step || gen_csta)␊ |
1828 | ␉␉{␊ |
1829 | ␉␉␉if (empty != ACPI_TABLE_LIST_FULL) {␊ |
1830 | ␉␉␉␉if (new_table_list[empty] =(U32)generate_cst_ssdt(fadt_mod))␊ |
1831 | ␉␉␉␉{␊ |
1832 | ␉␉␉␉␉if (speed_step || gen_psta)␊ |
1833 | ␉␉␉␉␉␉empty = get_0ul_index_in_list(new_table_list,true);␊ |
1834 | ␉␉␉␉}␊ |
1835 | ␉␉␉} else {␊ |
1836 | ␉␉␉␉printf("Error: not enought reserved space in the new acpi list for the _CST SSDT table,\n ");␊ |
1837 | ␉␉␉␉printf(" please increase the RESERVED_AERA\n");␊ |
1838 | ␉␉␉}␊ |
1839 | ␉␉}␊ |
1840 | ␉␉␊ |
1841 | ␉␉␊ |
1842 | ␉␉// Generating _PSS SSDT␊ |
1843 | ␉␉if (speed_step || gen_psta)␊ |
1844 | ␉␉{␊ |
1845 | ␉␉␉if (empty != ACPI_TABLE_LIST_FULL) {␊ |
1846 | ␉␉␉␉␊ |
1847 | ␉␉␉␉new_table_list[empty] =(U32)generate_pss_ssdt(DsdtPtr);␊ |
1848 | ␉␉␉␉␊ |
1849 | ␉␉␉} else {␊ |
1850 | ␉␉␉␉printf("Error: not enought reserved space in the new acpi list for the _PSS SSDT table,\n ");␊ |
1851 | ␉␉␉␉printf(" please increase the RESERVED_AERA\n");␊ |
1852 | ␉␉␉}␊ |
1853 | ␉␉}␊ |
1854 | ␉}␊ |
1855 | ␊ |
1856 | ␉if ((rsdp_mod != (void *)0ul) && (rsdp_mod->Length >= ACPI_RSDP_REV0_SIZE) ) ␊ |
1857 | ␉{␊ |
1858 | ␉␉if ((rsdp_mod->Revision == 0) || (gen_xsdt == true)) {␊ |
1859 | ␉␉␉process_rsdt(rsdp_mod, gen_xsdt, new_table_list);␊ |
1860 | ␉␉␉goto out;␊ |
1861 | ␉␉}␊ |
1862 | ␉␉␊ |
1863 | ␉} else {␊ |
1864 | ␉␉printf("Error: Incorect ACPI RSD PTR or not found \n");␊ |
1865 | ␉␉return EFI_UNSUPPORTED;␊ |
1866 | ␉}␊ |
1867 | ␊ |
1868 | ␉if ((GetChecksum(rsdp_mod, sizeof(ACPI_TABLE_RSDP)) == 0) &&␊ |
1869 | ␉␉(Revision == 2) &&␊ |
1870 | ␉␉(rsdplength == sizeof(ACPI_TABLE_RSDP)))␊ |
1871 | ␉{␊ |
1872 | ␉␉process_xsdt(rsdp_mod, new_table_list);␊ |
1873 | ␉} else {␊ |
1874 | ␉␉printf("Warning : ACPI RSD PTR Revision 2 is incorrect, \n");␊ |
1875 | ␉␉printf(" trying to fallback to Revision 1\n");␊ |
1876 | ␉␉if ((rsdp_mod != (void *)0ul) && (rsdp_mod->Length >= ACPI_RSDP_REV0_SIZE) ) ␊ |
1877 | ␉␉{␉␉␉␊ |
1878 | ␉␉␉process_rsdt(rsdp_mod, false, new_table_list);␊ |
1879 | ␉␉␉␉␉␉␊ |
1880 | ␉␉} else {␊ |
1881 | ␉␉␉printf("Error: Incorect ACPI RSD PTR or not found \n");␊ |
1882 | ␉␉␉return EFI_UNSUPPORTED;␊ |
1883 | ␉␉}␊ |
1884 | ␉}␊ |
1885 | ␊ |
1886 | out:␊ |
1887 | ␉// Correct the checksum of RSDP ␊ |
1888 | ␉␊ |
1889 | ␉DBG("RSDP: Original checksum %d\n", rsdp_mod->Checksum);␉␉␊ |
1890 | ␉␊ |
1891 | ␉setRsdpchecksum(rsdp_mod);␊ |
1892 | ␉␊ |
1893 | ␉DBG("New checksum %d\n", rsdp_mod->Checksum);␊ |
1894 | ␉␊ |
1895 | ␉if (Revision == 2)␊ |
1896 | ␉{␊ |
1897 | ␉␉DBG("RSDP: Original extended checksum %d\n", rsdp_mod->ExtendedChecksum);␉␉␉␊ |
1898 | ␉␉␊ |
1899 | ␉␉setRsdpXchecksum(rsdp_mod);␊ |
1900 | ␉␉␊ |
1901 | ␉␉DBG("New extended checksum %d\n", rsdp_mod->ExtendedChecksum);␊ |
1902 | ␉␉␊ |
1903 | ␉}␊ |
1904 | ␉␊ |
1905 | ␉verbose("ACPI Revision %d successfully patched\n", Revision);␊ |
1906 | ␉␊ |
1907 | ␉if (Revision == 2)␊ |
1908 | ␉{␊ |
1909 | ␉␉rsd_p = ((U64)((U32)rsdp_mod));␊ |
1910 | ␉␉if (rsd_p)␊ |
1911 | ␉␉␉Status = addConfigurationTable(&gEfiAcpi20TableGuid, &rsd_p, "ACPI_20");␊ |
1912 | ␉}␊ |
1913 | ␉else␊ |
1914 | ␉{␊ |
1915 | ␉␉rsd_p = ((U64)((U32)rsdp_mod));␊ |
1916 | ␉␉if (rsd_p)␊ |
1917 | ␉␉␉Status = addConfigurationTable(&gEfiAcpiTableGuid, &rsd_p, "ACPI");␉␉␊ |
1918 | ␊ |
1919 | ␉}␊ |
1920 | ␉␊ |
1921 | #if DEBUG_ACPI␊ |
1922 | ␉printf("Press a key to continue... (DEBUG_DSDT)\n");␊ |
1923 | ␉getc();␊ |
1924 | #endif␊ |
1925 | ␉return Status;␊ |
1926 | }␊ |
1927 | |