Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/modules/ACPICodec/acpi_codec.c

  • Property svn:executable set to *
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
26U64 rsd_p;
27ACPI_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
41extern EFI_STATUS addConfigurationTable();
42
43extern EFI_GUID gEfiAcpiTableGuid;
44extern 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
60ACPI_TABLE_FADT *
61patch_fadt(ACPI_TABLE_FADT *fadt, ACPI_TABLE_DSDT *new_dsdt, bool UpdateFADT);
62
63#define __RES(s, u)\
64inline unsigned u\
65resolve_##s(unsigned u defaultentry, char *str, int base) \
66{\
67unsigned u entry = defaultentry;\
68if (str && (strcmp(str,"Default") != 0)) {\
69entry = strtoul((const char *)str, NULL,base);\
70}\
71return entry;\
72}
73
74__RES(pss, long)
75__RES(cst, int)
76
77
78ACPI_TABLE_HEADER * get_new_table_in_list(U32 *new_table_list, U32 Signature, U8 *retIndex )
79{
80ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;
81U8 index ;
82*retIndex = 0;
83
84for (index = 0; index < (MAX_ACPI_TABLE + RESERVED_AERA); index++) {
85if (*(U32 *) (table_array[index]->Signature) == Signature) {
86*retIndex = index;
87return table_array[index] ;
88}
89}
90return (void*)0ul;
91}
92
93U8 get_0ul_index_in_list(U32 *new_table_list, bool reserved )
94{
95U8 index ;
96
97U8 maximum = (reserved == true) ? MAX_ACPI_TABLE + RESERVED_AERA : MAX_ACPI_TABLE;
98
99for (index = 0; index < maximum; index++) {
100if (new_table_list[index] == 0ul) {
101return index ;
102}
103}
104return (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 */
108void sanitize_new_table_list(U32 *new_table_list )
109{
110ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;
111U8 index ;
112
113for (index = 0; index < MAX_ACPI_TABLE; index++) {
114U32 current_sig = *(U32 *) (table_array[index]->Signature);
115
116if ((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
120void *buf = (void*)new_table_list[index];
121free(buf);
122new_table_list[index] = 0ul ;
123}
124}
125}
126
127/* cparm : move all table to kernel memory */
128void move_table_list_to_kmem(U32 *new_table_list )
129{
130ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;
131U8 index ;
132
133for (index = 0; index < MAX_ACPI_TABLE; index++) {
134if (new_table_list[index] != 0ul) {
135
136U32 current_sig = *(U32 *) (table_array[index]->Signature);
137if ((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
142void *tableAddr=(void*)AllocateKernelMemory(table_array[index]->Length);
143bcopy(table_array[index], tableAddr, table_array[index]->Length);
144new_table_list[index] = 0ul ;
145new_table_list[index] = (U32)tableAddr ;
146
147} else {
148
149void *buf = (void*)new_table_list[index];
150free(buf);
151new_table_list[index] = 0ul ;
152}
153}
154}
155}
156
157ACPI_TABLE_RSDP * gen_alloc_rsdp_v2_from_v1(ACPI_TABLE_RSDP *rsdp )
158{
159
160ACPI_TABLE_RSDP * rsdp_conv = (ACPI_TABLE_RSDP *)AllocateKernelMemory(sizeof(ACPI_TABLE_RSDP));
161bzero(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
175ACPI_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));
183bzero(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
192ACPI_TABLE_HEADER *table = (ACPI_TABLE_HEADER *) xsdt->TableOffsetEntry;
193
194for (index=0;index<num_tables;index++)
195 {
196if (GetChecksum(table, table->Length) == 0)
197{
198if (((U32) (table->Signature) == NAMESEG(ACPI_SIG_FADT))) {
199ACPI_TABLE_FADT *fadt=(ACPI_TABLE_FADT *)((U32)table);
200
201DBG("Downgrading ACPI V%d FADT to ACPI V1 FADT \n", fadt->Header.Revision);
202ACPI_TABLE_FADT *fadt_conv=(ACPI_TABLE_FADT *)malloc(0x74);
203memcpy(fadt_conv, fadt, 0x74);
204fadt_conv->Header.Length = 0x74;
205fadt_conv->Header.Revision = 0x01;
206
207SetChecksum(&fadt_conv->Header);
208ACPI_TABLE_FADT *fadt_mod = patch_fadt(fadt_conv, ((ACPI_TABLE_DSDT*)((U32)fadt->XDsdt)), false);
209if (fadt_mod == (void*)0ul) {
210printf("Error: Failed to patch FADT Table, fallback to fadt original pointer\n");
211fadt_mod = fadt;
212}
213
214rsdt_conv->TableOffsetEntry[index] = ((U32)fadt_mod);
215// Move array pointer to next 64-bit pointer
216table = (ACPI_TABLE_HEADER *) ((U32) table + sizeof(U64));
217continue;
218}
219
220rsdt_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
232ACPI_TABLE_XSDT * gen_alloc_xsdt_from_rsdt(ACPI_TABLE_RSDT *rsdt)
233{
234
235
236U32 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));
242bzero(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
251ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) rsdt->TableOffsetEntry;
252
253 for (index=0;index<num_tables;index++)
254 {
255if (GetChecksum(table_array[index], table_array[index]->Length) == 0) {
256
257if ((*(U32 *) (table_array[index]->Signature) == NAMESEG(ACPI_SIG_FADT))){
258ACPI_TABLE_FADT *FacpPointer = ((ACPI_TABLE_FADT*)table_array[index]);
259ACPI_TABLE_FADT *fadt_mod = (ACPI_TABLE_FADT *)patch_fadt(FacpPointer,((ACPI_TABLE_DSDT*)FacpPointer->Dsdt),true);
260if (fadt_mod == (void*)0ul) {
261printf("Error: Failed to patch (& update) FADT Table, fallback to original fadt pointer\n");
262fadt_mod = FacpPointer;
263}
264xsdt_conv->TableOffsetEntry[index] = ((U64)((U32)fadt_mod));
265
266continue;
267}
268xsdt_conv->TableOffsetEntry[index] = ((U64)((U32)table_array[index]));
269 }
270
271 }
272
273 SetChecksum(&xsdt_conv->Header);
274
275 return xsdt_conv;
276}
277
278void *loadACPITable(char *dirspec, char *filename )
279{
280int fd = -1;
281char acpi_file[512];
282
283DBG("Searching for %s file ...\n", filename);
284// Check booting partition
285
286sprintf(acpi_file, "%s%s",dirspec, filename);
287
288fd=open(acpi_file);
289
290if (fd<0)
291{
292DBG("Couldn't open ACPI Table: %s\n", acpi_file);
293return (void *)0ul ;
294}
295
296void *tableAddr=(void*)malloc(file_size (fd));
297
298if (tableAddr)
299{
300if (read (fd, tableAddr, file_size (fd))!=file_size (fd))
301{
302printf("Couldn't read table %s\n",acpi_file);
303free (tableAddr);
304close (fd);
305return (void *)0ul ;
306}
307
308close (fd);
309
310ACPI_TABLE_HEADER * header = (ACPI_TABLE_HEADER *)tableAddr;
311
312if (GetChecksum(header, header->Length) == 0) {
313DBG("Found valid ACPI file : %s", filename);
314DBG(", Table %s read and stored at: %x", acpi_file, tableAddr);
315DBG("\n");
316return tableAddr;
317} else {
318printf("Warning : Incorrect cheksum for the file : %s,");
319printf(" this file will be dropped.\n");
320free(tableAddr);
321return (void*)0ul;
322}
323}
324
325printf("Couldn't allocate memory for table %s\n", acpi_file);
326close (fd);
327
328return (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 */
361static U32 pmbase;
362static short cpuNamespace;
363PROCESSOR_NUMBER_TO_NAMESEG cpu_map[CPU_MAP_LIMIT];
364unsigned int cpu_map_count;
365int cpu_map_error;
366
367#if DEBUG_ACPI
368static 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
377static 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
387static 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
396if ((cpu_map_error == 1) || (DsdtPointer == (void*)0ul))
397return 1;
398else if (cpu_map_count > 0)
399return 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;
408DBG("* DSDT debug start\n");
409 parse_acpi_termlist(&ns, current, end);
410DBG("* DSDT debug end\n");
411
412 if (acpi_processor_count > CPU_MAP_LIMIT){
413verbose("Too many processors: found %u processors\n", acpi_processor_count);
414 return (cpu_map_error = 1);
415}
416 if (acpi_processor_count == 0){
417verbose( "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){
425verbose("Found inconsistent pmbase addresses in ACPI: 0x%x and 0x%x\n", pmbase, cpu_pmbase);
426return (cpu_map_error = 1);
427}
428 pmbase = cpu_pmbase;
429 }
430 if (acpi_processors[cpu].ns.depth > MAX_SUPPORTED_CPU_NAMESEGS + 1){
431verbose("Processor path too deep: depth %u\n", acpi_processors[cpu].ns.depth);
432return (cpu_map_error = 1);
433}
434 if (processor_namespace && acpi_processors[cpu].ns.nameseg[0] != processor_namespace){
435verbose("Processor namespaces inconsistent\n");
436return (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){
446verbose("No pmbase found in ACPI\n");
447return (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");
455return (cpu_map_error = 1);
456}
457 cpu_map_count = map - cpu_map;
458
459#if DEBUG_ACPI
460char pns[3];
461sprintf_nameseg(pns,processor_namespace);
462verbose("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");
474getc();
475#endif
476
477// TODO: Save the cpu map into the device tree
478 return (cpu_map_error = 0);
479}
480
481ACPI_TABLE_SSDT *generate_cst_ssdt(ACPI_TABLE_FADT* fadt)
482{
483char ssdt_header[] =
484{
4850x53, 0x53, 0x44, 0x54, 0xE7, 0x00, 0x00, 0x00, /* SSDT.... */
4860x01, 0x17, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x41, /* ..PmRefA */
4870x43, 0x70, 0x75, 0x43, 0x73, 0x74, 0x00, 0x00, /* CpuCst.. */
4880x00, 0x10, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* ....INTL */
4890x31, 0x03, 0x10, 0x20 /* 1.._*/
490};
491
492char cstate_resource_template[] =
493{
4940x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00, 0x7F,
4950x01, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
4960x00, 0x00, 0x00, 0x79, 0x00
497};
498
499if (Platform->CPU.Vendor != 0x756E6547) {
500verbose ("Not an Intel platform: C-States will not be generated !!!\n");
501return (void *)0ul;
502}
503
504if (fadt == (void *)0ul) {
505verbose ("FACP not exists: C-States will not be generated !!!\n");
506return (void *)0ul;
507}
508
509ACPI_TABLE_DSDT* dsdt = ((fadt->Header.Revision >= 3) && (fadt->XDsdt != 0)) ? (ACPI_TABLE_DSDT*)((U32)fadt->XDsdt):(ACPI_TABLE_DSDT*)fadt->Dsdt;
510if (dsdt == (void *)0ul) {
511verbose ("DSDT not found: C-States will not be generated !!!\n");
512return (void *)0ul;
513}
514
515if (generate_cpu_map_from_acpi(dsdt) == 0)
516{
517bool c2_enabled = fadt->C2Latency < 100;
518bool c3_enabled = fadt->C3Latency < 1000;
519bool c4_enabled = false;
520
521getBoolForKey(kEnableC4State, &c4_enabled, &bootInfo->bootConfig);
522
523unsigned char cstates_count = 1 + (c2_enabled ? 1 : 0) + ((c3_enabled || c4_enabled) ? 1 : 0);
524char *Lat = NULL, *Pw = NULL, *tmpstr =NULL;
525int base = 16;
526TagPtr personality = XMLCastDict(XMLGetProperty(bootInfo->bootConfig.dictionary, (const char*)"C-States"));
527
528if ((tmpstr = XMLCastString(XMLGetProperty(personality, (const char*)"Base")))) {
529
530int mybase = strtol(tmpstr, NULL, 10);
531
532if (mybase == 8 || mybase == 10 || mybase == 16 )
533base = mybase;
534}
535
536struct aml_chunk* root = aml_create_node(NULL);
537 aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header
538 struct aml_chunk* scop;
539if (cpuNamespace == CPU_NAMESPACE_PR)
540scop = aml_add_scope(root, "\\_PR_");
541else if (cpuNamespace == CPU_NAMESPACE_SB)
542scop = aml_add_scope(root, "\\_SB_");
543else
544{
545aml_destroy_node(root);
546goto 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
564if (c2_enabled)
565{
566tmpl = aml_add_package(pack);
567Lat = NULL;
568Pw = NULL;
569match_Status = XMLGetProperty(personality, (const char*)"C2");
570if (match_Status) {
571Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power"));
572Lat = XMLCastString(XMLGetProperty(match_Status, (const char*)"Latency"));
573}
574
575cstate_resource_template[11] = 0x10; // C2
576aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
577aml_add_byte(tmpl, 0x02); // C2
578aml_add_word(tmpl, resolve_cst(fadt->C2Latency, Lat, base)); // Latency
579aml_add_word(tmpl, resolve_cst(0x01f4, Pw, base)); // Power
580}
581
582// C4
583if (c4_enabled)
584{
585tmpl = aml_add_package(pack);
586Lat = NULL;
587Pw = NULL;
588match_Status = XMLGetProperty(personality, (const char*)"C4");
589if (match_Status) {
590Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power"));
591Lat = XMLCastString(XMLGetProperty(match_Status, (const char*)"Latency"));
592}
593cstate_resource_template[11] = 0x30; // C4
594aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
595aml_add_byte(tmpl, 0x04); // C4
596aml_add_word(tmpl, resolve_cst(fadt->C3Latency / 2, Lat, base)); // TODO: right latency for C4
597aml_add_word(tmpl, resolve_cst(0xfa, Pw, base)); // Power
598
599}
600// C3
601else if (c3_enabled)
602{
603tmpl = aml_add_package(pack);
604Lat = NULL;
605Pw = NULL;
606match_Status = XMLGetProperty(personality, (const char*)"C3");
607if (match_Status) {
608Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power"));
609Lat = XMLCastString(XMLGetProperty(match_Status, (const char*)"Latency"));
610}
611cstate_resource_template[11] = 0x20; // C3
612aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
613aml_add_byte(tmpl, 0x03); // C3
614aml_add_word(tmpl, resolve_cst(fadt->C3Latency , Lat, base));
615aml_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
646aml_calculate_size(root);
647
648ACPI_TABLE_SSDT *ssdt = (ACPI_TABLE_SSDT *)AllocateKernelMemory(root->Size);
649
650aml_write_node(root, (void*)ssdt, 0);
651
652ssdt->Header.Length = root->Size;
653
654SetChecksum(&ssdt->Header);
655
656aml_destroy_node(root);
657
658verbose ("SSDT with CPU C-States generated successfully\n");
659
660return ssdt;
661}
662else
663{
664out:
665verbose ("ACPI CPUs not found: C-States will not be generated !!!\n");
666}
667
668return (void *)0ul;
669}
670
671ACPI_TABLE_SSDT *generate_pss_ssdt(ACPI_TABLE_DSDT* dsdt)
672{
673
674char ssdt_header[] =
675{
6760x53, 0x53, 0x44, 0x54, 0x7E, 0x00, 0x00, 0x00, /* SSDT.... */
6770x01, 0x6A, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x00, /* ..PmRef. */
6780x43, 0x70, 0x75, 0x50, 0x6D, 0x00, 0x00, 0x00, /* CpuPm... */
6790x00, 0x30, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* .0..INTL */
6800x31, 0x03, 0x10, 0x20,/* 1.._*/
681};
682
683if (Platform->CPU.Vendor != 0x756E6547) {
684verbose ("Not an Intel platform: P-States will not be generated !!!\n");
685return (void *)0ul;
686}
687
688if (!(Platform->CPU.Features & CPUID_FEATURE_MSR)) {
689verbose ("Unsupported CPU: P-States will not be generated !!!\n");
690return (void *)0ul;
691}
692
693if (dsdt == (void *)0ul) {
694verbose ("DSDT not found: P-States will not be generated !!!\n");
695return (void *)0ul;
696}
697
698if (generate_cpu_map_from_acpi(dsdt) == 0 )
699{
700struct p_state initial, maximum, minimum, p_states[32];
701U8 p_states_count = 0;
702
703// Retrieving P-States, ported from code by superhai (c)
704switch (Platform->CPU.Family) {
705case 0x06:
706{
707switch (Platform->CPU.Model)
708{
709case CPUID_MODEL_DOTHAN:
710case CPUID_MODEL_YONAH: // Yonah
711case CPUID_MODEL_MEROM: // Merom
712case CPUID_MODEL_PENRYN: // Penryn
713case CPUID_MODEL_ATOM: // Intel Atom (45nm)
714{
715bool cpu_dynamic_fsb = false;
716
717if (rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 27))
718{
719wrmsr64(MSR_IA32_EXT_CONFIG, (rdmsr64(MSR_IA32_EXT_CONFIG) | (1 << 28)));
720delay(1);
721cpu_dynamic_fsb = rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 28);
722}
723
724bool cpu_noninteger_bus_ratio = (rdmsr64(MSR_IA32_PERF_STATUS) & (1ULL << 46));
725
726initial.Control = rdmsr64(MSR_IA32_PERF_STATUS);
727
728maximum.Control = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 32) & 0x1F3F) | (0x4000 * cpu_noninteger_bus_ratio);
729maximum.CID = ((maximum.FID & 0x1F) << 1) | cpu_noninteger_bus_ratio;
730
731minimum.FID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 24) & 0x1F) | (0x80 * cpu_dynamic_fsb);
732minimum.VID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 48) & 0x3F);
733
734if (minimum.FID == 0)
735{
736U64 msr;
737U8 i;
738// Probe for lowest fid
739for (i = maximum.FID; i >= 0x6; i--)
740{
741msr = rdmsr64(MSR_IA32_PERF_CONTROL);
742wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (i << 8) | minimum.VID);
743intel_waitforsts();
744minimum.FID = (rdmsr64(MSR_IA32_PERF_STATUS) >> 8) & 0x1F;
745delay(1);
746}
747
748msr = rdmsr64(MSR_IA32_PERF_CONTROL);
749wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
750intel_waitforsts();
751}
752
753if (minimum.VID == maximum.VID)
754{
755U64 msr;
756U8 i;
757// Probe for lowest vid
758for (i = maximum.VID; i > 0xA; i--)
759{
760msr = rdmsr64(MSR_IA32_PERF_CONTROL);
761wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (minimum.FID << 8) | i);
762intel_waitforsts();
763minimum.VID = rdmsr64(MSR_IA32_PERF_STATUS) & 0x3F;
764delay(1);
765}
766
767msr = rdmsr64(MSR_IA32_PERF_CONTROL);
768wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
769intel_waitforsts();
770}
771
772minimum.CID = ((minimum.FID & 0x1F) << 1) >> cpu_dynamic_fsb;
773
774// Sanity check
775if (maximum.CID < minimum.CID)
776{
777DBG("Insane FID values!");
778p_states_count = 0;
779}
780else
781{
782// Finalize P-States
783// Find how many P-States machine supports
784p_states_count = maximum.CID - minimum.CID + 1;
785
786if (p_states_count > 32)
787p_states_count = 32;
788
789U8 vidstep;
790U8 i = 0, u, invalid = 0;
791
792vidstep = ((maximum.VID << 2) - (minimum.VID << 2)) / (p_states_count - 1);
793
794for (u = 0; u < p_states_count; u++)
795{
796i = u - invalid;
797
798p_states[i].CID = maximum.CID - u;
799p_states[i].FID = (p_states[i].CID >> 1);
800
801if (p_states[i].FID < 0x6)
802{
803if (cpu_dynamic_fsb)
804p_states[i].FID = (p_states[i].FID << 1) | 0x80;
805}
806else if (cpu_noninteger_bus_ratio)
807{
808p_states[i].FID = p_states[i].FID | (0x40 * (p_states[i].CID & 0x1));
809}
810
811if (i && p_states[i].FID == p_states[i-1].FID)
812invalid++;
813
814p_states[i].VID = ((maximum.VID << 2) - (vidstep * u)) >> 2;
815
816U32 multiplier = p_states[i].FID & 0x1f;// = 0x08
817bool half = p_states[i].FID & 0x40;// = 0x01
818bool dfsb = p_states[i].FID & 0x80;// = 0x00
819U32 fsb = Platform->CPU.FSBFrequency / 1000000; // = 400
820U32 halffsb = (fsb + 1) >> 1;// = 200
821U32 frequency = (multiplier * fsb);// = 3200
822
823p_states[i].Frequency = (frequency + (half * halffsb)) >> dfsb;// = 3200 + 200 = 3400
824}
825
826p_states_count -= invalid;
827}
828break;
829}
830case CPUID_MODEL_FIELDS:
831case CPUID_MODEL_DALES:
832case CPUID_MODEL_DALES_32NM:
833case CPUID_MODEL_NEHALEM:
834case CPUID_MODEL_NEHALEM_EX:
835case CPUID_MODEL_WESTMERE:
836case CPUID_MODEL_WESTMERE_EX:
837case CPUID_MODEL_SANDYBRIDGE:
838 case CPUID_MODEL_JAKETOWN:
839{
840maximum.Control = rdmsr64(MSR_IA32_PERF_STATUS) & 0xff; // Seems it always contains maximum multiplier value (with turbo, that's we need)...
841minimum.Control = (rdmsr64(MSR_PLATFORM_INFO) >> 40) & 0xff;
842
843verbose("P-States: min 0x%x, max 0x%x\n", minimum.Control, maximum.Control);
844
845// Sanity check
846if (maximum.Control < minimum.Control)
847{
848DBG("Insane control values!");
849p_states_count = 0;
850}
851else
852{
853U8 i;
854p_states_count = 0;
855
856for (i = maximum.Control; i >= minimum.Control; i--)
857{
858p_states[p_states_count].Control = i;
859p_states[p_states_count].CID = p_states[p_states_count].Control << 1;
860p_states[p_states_count].Frequency = (Platform->CPU.FSBFrequency / 1000000) * i;
861p_states_count++;
862}
863}
864
865break;
866}
867default:
868verbose ("Unsupported CPU: P-States will not be generated !!!\n");
869break;
870}
871}
872default:
873break;
874}
875
876// Generating SSDT
877if (p_states_count)
878{
879unsigned int i;
880
881struct aml_chunk* root = aml_create_node(NULL);
882 aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header
883struct aml_chunk* scop;
884if (cpuNamespace == CPU_NAMESPACE_PR)
885scop = aml_add_scope(root, "\\_PR_");
886else if (cpuNamespace == CPU_NAMESPACE_SB)
887scop = 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
1022for (i = 0; i < cpu_map_count; i++)
1023{
1024char 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
1043scop = aml_add_scope(root, name);
1044aml_add_alias(scop, "PSS_", "_PSS");
1045}
1046
1047aml_calculate_size(root);
1048
1049ACPI_TABLE_SSDT *ssdt = (ACPI_TABLE_SSDT *)AllocateKernelMemory(root->Size);
1050
1051aml_write_node(root, (void*)ssdt, 0);
1052
1053ssdt->Header.Length = root->Size;
1054
1055 SetChecksum(&ssdt->Header);
1056
1057aml_destroy_node(root);
1058
1059verbose ("SSDT with CPU P-States generated successfully");
1060
1061if (dropPSS)
1062 verbose(", %d P-state(s) dropped",dropPSS);
1063
1064verbose("\n");
1065
1066return ssdt;
1067}
1068}
1069else
1070{
1071out:
1072verbose("ACPI CPUs not found: P-States will not be generated !!!\n");
1073}
1074
1075return (void *)0ul;
1076}
1077#if UNUSED
1078ACPI_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
1083ACPI_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
1089if (FacsPointer->Length < sizeof(ACPI_TABLE_FACS)) {
1090facs_mod->FirmwareWakingVector = 0;
1091facs_mod->GlobalLock = 0;
1092facs_mod->Flags = 0;
1093}
1094
1095 if (updatefacs && FacsPointer->Version < 2) {
1096if (FacsPointer->Version > 0) {
1097facs_mod->XFirmwareWakingVector = FacsPointer->XFirmwareWakingVector;
1098} else {
1099facs_mod->XFirmwareWakingVector = (U64)facs_mod->FirmwareWakingVector;
1100}
1101
1102facs_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
1110ACPI_GENERIC_ADDRESS FillGASStruct(U32 Address, U8 Length)
1111{
1112ACPI_GENERIC_ADDRESS TmpGAS;
1113
1114TmpGAS.SpaceId = 1; /* I/O Address */
1115
1116if (Address == 0)
1117{
1118TmpGAS.BitWidth = 0;
1119} else {
1120TmpGAS.BitWidth = Length * 8;
1121}
1122
1123TmpGAS.BitOffset = 0;
1124TmpGAS.AccessWidth = 0; /* Not set for Legacy reasons... */
1125TmpGAS.Address = (U64)Address;
1126
1127return (TmpGAS);
1128}
1129
1130ACPI_TABLE_FADT *
1131patch_fadt(ACPI_TABLE_FADT *fadt, ACPI_TABLE_DSDT *new_dsdt, bool UpdateFADT)
1132{
1133ACPI_TABLE_FADT *fadt_mod = (void*)0;
1134bool fadt_rev2_needed = false;
1135bool fix_restart = false;
1136const char * value;
1137
1138// Restart Fix
1139if (Platform->CPU.Vendor == 0x756E6547) {/* Intel */
1140fix_restart = true;
1141getBoolForKey(kRestartFix, &fix_restart, &bootInfo->bootConfig);
1142
1143} else {
1144verbose ("Not an Intel platform: Restart Fix disabled !!!\n");
1145}
1146
1147if (fix_restart)
1148fadt_rev2_needed = true;
1149
1150// Allocate new fadt table
1151if (UpdateFADT)
1152{
1153 if (fadt->Header.Length < 0xF4)
1154 {
1155fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(0xF4);
1156 bzero(fadt_mod, 0xF4);
1157memcpy(fadt_mod, fadt, fadt->Header.Length);
1158fadt_mod->Header.Length = 0xF4;
1159}
1160else
1161{
1162fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(fadt->Header.Length);
1163memcpy(fadt_mod, fadt, fadt->Header.Length);
1164}
1165
1166
1167//fadt_mod->Header.Revision = 0x04; // FADT rev 4
1168fadt_mod->ResetRegister = FillGASStruct(0, 0);
1169fadt_mod->ResetValue = 0;
1170fadt_mod->Reserved4[0] = 0;
1171fadt_mod->Reserved4[1] = 0;
1172fadt_mod->Reserved4[2] = 0;
1173
1174 fadt_mod->XPm1aEventBlock = FillGASStruct(fadt_mod->Pm1aEventBlock, fadt_mod->Pm1EventLength);
1175fadt_mod->XPm1bEventBlock = FillGASStruct(fadt_mod->Pm1bEventBlock, fadt_mod->Pm1EventLength);
1176fadt_mod->XPm1aControlBlock = FillGASStruct(fadt_mod->Pm1aControlBlock, fadt_mod->Pm1ControlLength);
1177fadt_mod->XPm1bControlBlock = FillGASStruct(fadt_mod->Pm1bControlBlock, fadt_mod->Pm1ControlLength);
1178fadt_mod->XPm2ControlBlock = FillGASStruct(fadt_mod->Pm2ControlBlock, fadt_mod->Pm2ControlLength);
1179fadt_mod->XPmTimerBlock = FillGASStruct(fadt_mod->PmTimerBlock, fadt_mod->PmTimerLength);
1180fadt_mod->XGpe0Block = FillGASStruct(fadt_mod->Gpe0Block, fadt_mod->Gpe0BlockLength);
1181fadt_mod->XGpe1Block = FillGASStruct(fadt_mod->Gpe1Block, fadt_mod->Gpe1BlockLength);
1182 if (fadt->Header.Revision < 4) {
1183fadt_mod->Header.Revision = 0x04; // FADT rev 4
1184verbose("Converted ACPI V%d FADT to ACPI V4 FADT\n", fadt->Header.Revision);
1185
1186}
1187} else {
1188
1189if (fadt_rev2_needed)
1190{
1191if (fadt->Header.Length < 0x84 )
1192{
1193fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(0x84);
1194bzero(fadt_mod, 0x84);
1195memcpy(fadt_mod, fadt, fadt->Header.Length);
1196fadt_mod->Header.Length = 0x84;
1197} else {
1198fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(fadt->Header.Length);
1199memcpy(fadt_mod, fadt, fadt->Header.Length);
1200}
1201
1202if (fadt->Header.Revision < 2) {
1203fadt_mod->Header.Revision = 0x02; // FADT rev 2 (ACPI 1.0B MS extensions)
1204verbose("Converted ACPI V%d FADT to ACPI V2 FADT\n", fadt->Header.Revision );
1205}
1206} else {
1207if (fadt->Header.Length < 0x74 )
1208{
1209fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(0x74);
1210bzero(fadt_mod, 0x74);
1211memcpy(fadt_mod, fadt, fadt->Header.Length);
1212fadt_mod->Header.Length = 0x74;
1213fadt_mod->Header.Revision = 0x01;
1214verbose("Warning: ACPI FADT length was < 0x74 which is the minimum for the ACPI FADT V1 specification, \n", fadt->Header.Revision );
1215verbose(" trying to convert it to Version 1. \n");
1216
1217} else {
1218fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(fadt->Header.Length);
1219memcpy(fadt_mod, fadt, fadt->Header.Length);
1220}
1221}
1222}
1223bool intelfadtspec = true;
1224U8 Type = PMProfileError;
1225// Determine system type / PM_Model
1226
1227// Fix System-type if needed (should never happen)
1228if (Platform->Type > MaxSupportedPMProfile)
1229{
1230if(fadt_mod->PreferredProfile <= MaxSupportedPMProfile)
1231Platform->Type = fadt_mod->PreferredProfile; // get the fadt if correct
1232else
1233Platform->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
1238if (fadt_mod->PreferredProfile != Platform->Type)
1239{
1240bool val = false;
1241getBoolForKey("PreferInternalProfileDetect", &val, &bootInfo->bootConfig); // if true Give prior to the profile resolved trought the CPU model
1242
1243val = Platform->CPU.isServer ;
1244
1245if (fadt_mod->PreferredProfile <= MaxSupportedPMProfile && !val) {
1246Platform->Type = fadt_mod->PreferredProfile;
1247} else {
1248fadt_mod->PreferredProfile = Platform->Type;
1249}
1250
1251}
1252
1253// Set PM_Profile and System-type if user wanted this value to be forced
1254if ( (value=getStringForKey("SystemType", &bootInfo->bootConfig))!=NULL) {
1255if ((Type = (unsigned char) strtoul(value, NULL, 10) ) <= MaxSupportedPMProfile)
1256{
1257if (fadt_mod->PreferredProfile != Type) {
1258verbose("FADT: changing Preferred_PM_Profile from %d to %d\n", fadt->PreferredProfile, Type);
1259fadt_mod->PreferredProfile = Platform->Type = Type;
1260} else {
1261DBG("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
1267getBoolForKey(KIntelFADT, &intelfadtspec, &bootInfo->bootConfig);
1268if ((pmbase == 0) && (cpu_map_error == 0) && (intelfadtspec == true))
1269{
1270ACPI_TABLE_DSDT *DsdtPointer ;
1271if (new_dsdt != (void*)0ul)
1272DsdtPointer = new_dsdt;
1273else if ((fadt_mod->Header.Revision >= 3) && (fadt_mod->XDsdt != 0ul))
1274DsdtPointer = (ACPI_TABLE_DSDT *)((U32)fadt_mod->XDsdt);
1275else
1276DsdtPointer = (ACPI_TABLE_DSDT *)fadt_mod->Dsdt;
1277
1278generate_cpu_map_from_acpi(DsdtPointer);
1279}
1280
1281// Patch DSDT Address if we have loaded a DSDT table
1282if(new_dsdt != (void*)0ul)
1283fadt_mod->Dsdt=(U32)new_dsdt;
1284
1285fadt_mod->Facs= fadt->Facs;
1286//fadt_mod->Facs=(U32)generate_facs(false);
1287
1288// Patch FADT to fix restart
1289if (fadt_mod->Header.Revision >= 2 && fix_restart)
1290{
1291 fadt_mod->Flags|= 0x400;
1292
1293int type = PCI_RESET_TYPE;
1294getIntForKey(KResetType, &type, &bootInfo->bootConfig);
1295if (type == KEYBOARD_RESET_TYPE) {
1296//Azi: keyboard reset; http://forum.voodooprojects.org/index.php/topic,1056.msg9802.html#msg9802
1297fadt_mod->ResetRegister = FillGASStruct(0x64, 1);
1298fadt_mod->ResetValue = 0xfe;
1299} else {
1300fadt_mod->ResetRegister = FillGASStruct(0x0cf9, 1);
1301fadt_mod->ResetValue = 0x06;
1302}
1303verbose("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 {
1315fadt_mod->XFacs=(U64)fadt->XFacs;
1316}
1317
1318
1319 if(new_dsdt != (void*)0ul)
1320 fadt_mod->XDsdt=((U64)(U32)new_dsdt);
1321else if (UpdateFADT)
1322fadt_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
1334DBG("setting hardware_signature to %x \n",Platform->hardware_signature);
1335
1336
1337
1338if (pmbase && (intelfadtspec == true))
1339ProcessFadt(fadt_mod, pmbase); // The checksum correction will be done by ProcessFadt
1340else
1341SetChecksum(&fadt_mod->Header); // Correct the checksum
1342
1343return fadt_mod;
1344}
1345
1346void process_xsdt (ACPI_TABLE_RSDP *rsdp_mod , U32 *new_table_list){
1347TagPtr DropTables_p = XMLCastDict(XMLGetProperty(bootInfo->bootConfig.dictionary, (const char*)"ACPIDropTables"));
1348U32 new_table = 0ul;
1349U8 new_table_index = 0, table_added = 0;
1350ACPI_TABLE_XSDT *xsdt = (void*)0ul, *xsdt_mod = (void*)0ul;
1351ACPI_TABLE_RSDT *rsdt_conv= (void *)0ul;
1352
1353// FIXME: handle 64-bit address correctly
1354
1355xsdt=(ACPI_TABLE_XSDT *)acpi_tables.XsdtPointer;
1356
1357verbose("* Processing XSDT: \n");
1358
1359DBG("XSDT @%x, Length=%d\n", (U32)xsdt,
1360xsdt->Header.Length);
1361
1362if (xsdt != (void *)0ul)
1363{
1364U32 dropoffset=0, index;
1365table_added = 0;
1366
1367xsdt_mod=(ACPI_TABLE_XSDT *)AllocateKernelMemory(xsdt->Header.Length);
1368bzero(xsdt_mod, xsdt->Header.Length);
1369memcpy(&xsdt_mod->Header, &xsdt->Header, sizeof(ACPI_TABLE_HEADER));
1370
1371U32 num_tables=get_num_tables64(xsdt);
1372
1373ACPI_TABLE_HEADER *table = (ACPI_TABLE_HEADER *) xsdt->TableOffsetEntry;
1374
1375for (index = 0; index < num_tables; index++) {
1376if (GetChecksum(table, table->Length) == 0) {
1377
1378xsdt_mod->TableOffsetEntry[index-dropoffset]=xsdt->TableOffsetEntry[index];
1379
1380char tableSig[4];
1381bool oem = false;
1382char oemOption[OEMOPT_SIZE];
1383
1384strlcpy(tableSig, (char*)((U32)(xsdt->TableOffsetEntry[index])), sizeof(tableSig)+1);
1385
1386sprintf(oemOption, "oem%s",tableSig );
1387if (getBoolForKey(oemOption, &oem, &bootInfo->bootConfig) && oem) { // This method don't work for DSDT and FACS
1388
1389if (get_new_table_in_list(new_table_list,((U32) (table->Signature)), &new_table_index) != (void*)0ul)
1390new_table_list[new_table_index] = 0ul; // This way new table will not be added to the new rsdt list !!
1391
1392continue;
1393}
1394
1395TagPtr match_drop = XMLGetProperty(DropTables_p, (const char*)tableSig);
1396if ( match_drop ) {
1397char *tmp = XMLCastString(match_drop);
1398if (strcmp(tmp,"No") != 0) {
1399dropoffset++;
1400DBG("%s table dropped\n",tableSig);
1401continue;
1402}
1403}
1404
1405if ((new_table = (U32)get_new_table_in_list(new_table_list,((U32) (table->Signature)), &new_table_index)) != 0ul)
1406{
1407xsdt_mod->TableOffsetEntry[index-dropoffset]=(U64)new_table;
1408new_table_list[new_table_index] = 0ul; // table replaced !!
1409continue;
1410}
1411}
1412// Move array pointer to next 64-bit pointer
1413table = (ACPI_TABLE_HEADER *) ((U32) table + sizeof(U64));
1414}
1415
1416
1417{
1418U8 i;
1419for (i = 0; i< (MAX_ACPI_TABLE + RESERVED_AERA); i++) {
1420if (new_table_list[i] != 0ul) {
1421xsdt_mod->TableOffsetEntry[index-dropoffset]=(U64)new_table_list[i];
1422table_added++;
1423index++;
1424}
1425}
1426}
1427
1428// Correct the checksum of XSDT
1429xsdt_mod->Header.Length-=8*dropoffset;
1430xsdt_mod->Header.Length+=8*table_added;
1431
1432SetChecksum(&xsdt_mod->Header);
1433
1434update_rsdp_with_xsdt(rsdp_mod, xsdt_mod);
1435
1436verbose("* Creating new RSDT from XSDT table\n");
1437
1438rsdt_conv = (ACPI_TABLE_RSDT *)gen_alloc_rsdt_from_xsdt(xsdt_mod);
1439update_rsdp_with_rsdt(rsdp_mod, rsdt_conv);
1440
1441
1442
1443}
1444else
1445{
1446DBG("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
1452rsdp_mod->XsdtPhysicalAddress=0xffffffffffffffffLL;
1453verbose("XSDT not found or XSDT incorrect\n");
1454}
1455
1456}
1457
1458void process_rsdt(ACPI_TABLE_RSDP *rsdp_mod , bool gen_xsdt, U32 *new_table_list)
1459{
1460TagPtr DropTables_p = XMLCastDict(XMLGetProperty(bootInfo->bootConfig.dictionary, (const char*)"ACPIDropTables"));
1461U32 new_table = 0ul;
1462U8 new_table_index = 0, table_added = 0;
1463U32 dropoffset=0, index;
1464ACPI_TABLE_RSDT *rsdt = (void *)0ul, *rsdt_mod= (void *)0ul;
1465ACPI_TABLE_XSDT *xsdt_conv = (void *)0ul;
1466
1467rsdt=(ACPI_TABLE_RSDT *)acpi_tables.RsdtPointer;
1468
1469DBG("RSDT @%x, Length %d\n",rsdt, rsdt->Header.Length);
1470
1471rsdt_mod=(ACPI_TABLE_RSDT *)AllocateKernelMemory(rsdt->Header.Length);
1472bzero(rsdt_mod, rsdt->Header.Length);
1473memcpy (&rsdt_mod->Header, &rsdt->Header, sizeof(ACPI_TABLE_HEADER));
1474
1475U32 num_tables = get_num_tables(rsdt);
1476
1477verbose("* Processing RSDT: \n");
1478ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) rsdt->TableOffsetEntry;
1479
1480// Compute number of table pointers included in RSDT
1481num_tables = get_num_tables(rsdt);
1482
1483for (index = 0; index < num_tables; index++) {
1484if (GetChecksum(table_array[index], table_array[index]->Length) == 0) {
1485
1486rsdt_mod->TableOffsetEntry[index-dropoffset]=rsdt->TableOffsetEntry[index];
1487
1488char tableSig[4];
1489bool oem = false;
1490char oemOption[OEMOPT_SIZE];
1491
1492strlcpy(tableSig, (char*)(rsdt->TableOffsetEntry[index]), sizeof(tableSig)+1);
1493
1494sprintf(oemOption, "oem%s",tableSig );
1495if (getBoolForKey(oemOption, &oem, &bootInfo->bootConfig) && oem) { // This method don't work for DSDT and FACS
1496
1497if (get_new_table_in_list(new_table_list,(*(U32 *) (table_array[index]->Signature)), &new_table_index) != (void*)0ul )
1498new_table_list[new_table_index] = 0ul; // This way new table will not be added to the new rsdt list !!
1499
1500continue;
1501}
1502
1503TagPtr match_drop = XMLGetProperty(DropTables_p, (const char*)tableSig);
1504if ( match_drop ) {
1505char *tmp = XMLCastString(match_drop);
1506if (strcmp(tmp,"No") != 0) {
1507dropoffset++;
1508DBG("%s table dropped\n",tableSig);
1509continue;
1510}
1511}
1512
1513if ((new_table = (U32)get_new_table_in_list(new_table_list,(*(U32 *) (table_array[index]->Signature)), &new_table_index)) != 0ul)
1514{
1515rsdt_mod->TableOffsetEntry[index-dropoffset]=new_table;
1516new_table_list[new_table_index] = 0ul; // table replaced !!
1517continue;
1518}
1519
1520}
1521}
1522DBG("\n");
1523
1524{
1525U8 i;
1526for (i = 0; i< (MAX_ACPI_TABLE + RESERVED_AERA); i++) {
1527if (new_table_list[i] != 0ul) {
1528rsdt_mod->TableOffsetEntry[index-dropoffset]=new_table_list[i];
1529table_added++;
1530index++;
1531}
1532}
1533}
1534
1535// Correct the checksum of RSDT
1536rsdt_mod->Header.Length-=4*dropoffset;
1537rsdt_mod->Header.Length+=4*table_added;
1538
1539DBG("RSDT: Original checksum %d\n", rsdt_mod->Header.Checksum);
1540
1541SetChecksum(&rsdt_mod->Header);
1542
1543DBG("New checksum %d at %x\n", rsdt_mod->Header.Checksum,rsdt_mod);
1544
1545update_rsdp_with_rsdt(rsdp_mod, rsdt_mod);
1546
1547if (gen_xsdt)
1548{
1549verbose("* Creating new XSDT from RSDT table\n");
1550xsdt_conv = (ACPI_TABLE_XSDT *)gen_alloc_xsdt_from_rsdt(rsdt_mod);
1551update_rsdp_with_xsdt(rsdp_mod, xsdt_conv);
1552
1553}
1554}
1555
1556
1557
1558EFI_STATUS setupAcpi(void)
1559{
1560U8 Revision = 0;
1561
1562 cpu_map_error = 0;
1563 cpu_map_count = 0;
1564 pmbase = 0;
1565
1566 EFI_STATUS Status = EFI_ABORTED;
1567
1568U32 new_table_list[MAX_ACPI_TABLE + RESERVED_AERA]; //max table + reserved aera
1569U8 new_table_index = 0;
1570
1571ACPI_TABLE_DSDT* DsdtPtr = (void *)0ul; // a Pointer to the dsdt table present in fadt_mod
1572
1573ACPI_TABLE_DSDT *new_dsdt = (void *)0ul;// a Pointer to the dsdt file
1574ACPI_TABLE_FADT *fadt_mod = (void *)0ul; // a Pointer to the patched FACP table
1575ACPI_TABLE_FADT *fadt_file = (void *)0ul; // a Pointer to the (non-patched) fadt file
1576ACPI_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
1577ACPI_TABLE_RSDP *rsdp_mod = (void *)0ul, *rsdp_conv= (void *)0ul;
1578
1579
1580U32 rsdplength;
1581
1582bool update_acpi=false, gen_xsdt=false;
1583
1584bool gen_csta=false, gen_psta=false, speed_step=false;
1585
1586bool oem_dsdt=false, oem_fadt=false;
1587
1588// Find original rsdp
1589if (!FindAcpiTables(&acpi_tables)){
1590printf("Error: AcpiCodec Failed to detect ACPI tables.\n");
1591getc();
1592return EFI_NOT_FOUND;
1593}
1594
1595{
1596U8 i;
1597
1598for (i=0; i<(MAX_ACPI_TABLE + RESERVED_AERA); i++) {
1599new_table_list[i] = 0ul;
1600}
1601bool tmpval;
1602
1603oem_dsdt=getBoolForKey(kOEMDSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1604oem_fadt=getBoolForKey(kOEMFADT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1605
1606
1607gen_csta=getBoolForKey(kGenerateCStates, &tmpval, &bootInfo->bootConfig)&&tmpval;
1608gen_psta=getBoolForKey(kGeneratePStates, &tmpval, &bootInfo->bootConfig)&&tmpval;
1609
1610update_acpi=getBoolForKey(kUpdateACPI, &tmpval, &bootInfo->bootConfig)&&tmpval;
1611
1612speed_step=getBoolForKey(kSpeedstep, &tmpval, &bootInfo->bootConfig)&&tmpval;
1613
1614}
1615
1616{
1617char* name;
1618long flags;
1619long time;
1620long ret = -1;
1621U8 i = 0;
1622char dirspec[512];
1623bool acpidir_found = false;
1624
1625ret = GetFileInfo("/Extra/", "Acpi", &flags, &time);
1626if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory)) {
1627sprintf(dirspec, "/Extra/Acpi/");
1628acpidir_found = true;
1629
1630} else {
1631ret = GetFileInfo("bt(0,0)/Extra/", "Acpi", &flags, &time);
1632if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory)) {
1633sprintf(dirspec, "bt(0,0)/Extra/Acpi/");
1634acpidir_found = true;
1635
1636}
1637}
1638
1639if (acpidir_found == true) {
1640struct dirstuff* moduleDir = opendir(dirspec);
1641while(readdir(moduleDir, (const char**)&name, &flags, &time) >= 0)
1642{
1643if((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:
1646if ((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{
1650continue;
1651}
1652
1653if ((strncmp(name, "FACS", 4) == 0) || (strncmp(name, "facs", 4) == 0)) { // For now FACS is not supported
1654continue;
1655}
1656
1657char* tmp = malloc(strlen(name) + 1);
1658strcpy(tmp, name);
1659
1660DBG("* Attempting to load acpi table: %s\n", tmp);
1661if( (new_table_list[i]=(U32)loadACPITable(dirspec,tmp)))
1662{
1663if (i < MAX_ACPI_TABLE) {
1664i++;
1665} else {
1666break;
1667}
1668
1669
1670} else {
1671free(tmp);
1672}
1673
1674}
1675#if DEBUG_ACPI
1676else
1677{
1678DBG("Ignoring %s\n", name);
1679}
1680#endif
1681
1682}
1683
1684if (i) {
1685//sanitize the new tables list
1686sanitize_new_table_list(new_table_list);
1687
1688//move to kernel memory
1689move_table_list_to_kmem(new_table_list);
1690
1691DBG("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
1701if (speed_step) {
1702gen_psta= true;
1703gen_csta= true;
1704}
1705
1706
1707ACPI_TABLE_RSDP *rsdp=(ACPI_TABLE_RSDP *)acpi_tables.RsdPointer;
1708
1709if (rsdp == (void*)0ul || (GetChecksum(rsdp, (rsdp->Revision == 0) ? ACPI_RSDP_REV0_SIZE:sizeof(ACPI_TABLE_RSDP)) != 0) ) {
1710printf("Error : ACPI RSD PTR Revision %d checksum is incorrect or table not found \n",rsdp->Revision );
1711return EFI_UNSUPPORTED;
1712}
1713
1714if ((update_acpi) && (rsdp->Revision == 0))
1715{
1716
1717rsdp_conv = (ACPI_TABLE_RSDP *)gen_alloc_rsdp_v2_from_v1(rsdp);
1718if (rsdp_conv != (void *)0ul) {
1719gen_xsdt = true;
1720rsdp = rsdp_conv;
1721verbose("Converted ACPI RSD PTR Revision 0 to Revision 2\n");
1722}
1723
1724}
1725
1726Revision = rsdp->Revision ;
1727rsdplength=(Revision == 2)?rsdp->Length:ACPI_RSDP_REV0_SIZE;
1728
1729DBG("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
1736if (gen_xsdt)
1737{
1738rsdp_mod=rsdp_conv;
1739} else {
1740rsdp_mod=(ACPI_TABLE_RSDP *) AllocateKernelMemory(rsdplength);
1741memcpy(rsdp_mod, rsdp, rsdplength);
1742}
1743
1744
1745if ((fadt_file = (ACPI_TABLE_FADT *)get_new_table_in_list(new_table_list, NAMESEG("FACP"), &new_table_index)) != (void *)0ul) {
1746
1747if (oem_fadt == false)
1748FacpPointer = (ACPI_TABLE_FADT *)fadt_file;
1749
1750new_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
1753FacpPointer = (acpi_tables.FacpPointer64 != (void *)0ul) ?
1754(ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer;
1755
1756#if DEBUG_ACPI
1757if ((FacpPointer != (void *)0ul) || (oem_fadt == false)) {
1758printf("FADT found @%x, Length %d\n",FacpPointer, FacpPointer->Header.Length);
1759printf("Attempting to patch FADT entry of %s\n",(acpi_tables.FacpPointer64 != (void *)0ul) ? ACPI_SIG_XSDT : ACPI_SIG_RSDT);
1760}
1761#endif
1762
1763if ((new_dsdt = (ACPI_TABLE_DSDT *)get_new_table_in_list(new_table_list, NAMESEG("DSDT"), &new_table_index)) != (void*)0ul ) {
1764new_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
1767if (oem_fadt == false) {
1768
1769fadt_mod = patch_fadt(FacpPointer, (oem_dsdt == false) ? new_dsdt : (void*)0ul , (acpi_tables.FacpPointer64 != (void *)0ul ));
1770
1771
1772DsdtPtr = ((fadt_mod->Header.Revision >= 3) && (fadt_mod->XDsdt != 0)) ? (ACPI_TABLE_DSDT*)((U32)fadt_mod->XDsdt):(ACPI_TABLE_DSDT*)fadt_mod->Dsdt;
1773
1774if (fadt_mod != (void*)0ul) {
1775
1776U8 empty = get_0ul_index_in_list(new_table_list,true);
1777if (empty != ACPI_TABLE_LIST_FULL) {
1778new_table_list[empty] = (U32)fadt_mod; // add the patched table to the list
1779} else {
1780printf("Error: not enought reserved space in the new acpi list for the Patched FACP table,\n ");
1781printf(" please increase the RESERVED_AERA\n");
1782}
1783
1784} else {
1785printf("Error: Failed to patch the FADT Table, trying fallback to the FADT original pointer\n");
1786fadt_mod = (acpi_tables.FacpPointer64 != (void *)0ul) ?
1787(ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer;
1788
1789U8 empty = get_0ul_index_in_list(new_table_list,true);
1790if (empty != ACPI_TABLE_LIST_FULL) {
1791new_table_list[empty] = (U32)fadt_mod;
1792} else {
1793printf("Error: not enought reserved space in the new acpi list for the FACP table,\n ");
1794printf(" please increase the RESERVED_AERA\n");
1795}
1796}
1797
1798if (oem_dsdt == false) {
1799if (generate_cpu_map_from_acpi(DsdtPtr) == 0){
1800U8 new_uid = (U8)getPciRootUID();
1801
1802/* WARNING: THIS METHOD WORK PERFECTLY BUT IT CAN RESULT TO AN INCORRECT CHECKSUM */
1803
1804if (ProcessDsdt(DsdtPtr, UIDPointer, new_uid)) {
1805printf("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
1816fadt_mod = (acpi_tables.FacpPointer64 != (void *)0ul) ?
1817(ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer;
1818
1819DsdtPtr = ((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
1823if (speed_step || gen_csta || gen_psta) {
1824U8 empty = get_0ul_index_in_list(new_table_list, true);
1825
1826// Generate _CST SSDT
1827if ( speed_step || gen_csta)
1828{
1829if (empty != ACPI_TABLE_LIST_FULL) {
1830if (new_table_list[empty] =(U32)generate_cst_ssdt(fadt_mod))
1831{
1832if (speed_step || gen_psta)
1833empty = get_0ul_index_in_list(new_table_list,true);
1834}
1835} else {
1836printf("Error: not enought reserved space in the new acpi list for the _CST SSDT table,\n ");
1837printf(" please increase the RESERVED_AERA\n");
1838}
1839}
1840
1841
1842// Generating _PSS SSDT
1843if (speed_step || gen_psta)
1844{
1845if (empty != ACPI_TABLE_LIST_FULL) {
1846
1847new_table_list[empty] =(U32)generate_pss_ssdt(DsdtPtr);
1848
1849} else {
1850printf("Error: not enought reserved space in the new acpi list for the _PSS SSDT table,\n ");
1851printf(" please increase the RESERVED_AERA\n");
1852}
1853}
1854}
1855
1856if ((rsdp_mod != (void *)0ul) && (rsdp_mod->Length >= ACPI_RSDP_REV0_SIZE) )
1857{
1858if ((rsdp_mod->Revision == 0) || (gen_xsdt == true)) {
1859process_rsdt(rsdp_mod, gen_xsdt, new_table_list);
1860goto out;
1861}
1862
1863} else {
1864printf("Error: Incorect ACPI RSD PTR or not found \n");
1865return EFI_UNSUPPORTED;
1866}
1867
1868if ((GetChecksum(rsdp_mod, sizeof(ACPI_TABLE_RSDP)) == 0) &&
1869(Revision == 2) &&
1870(rsdplength == sizeof(ACPI_TABLE_RSDP)))
1871{
1872process_xsdt(rsdp_mod, new_table_list);
1873} else {
1874printf("Warning : ACPI RSD PTR Revision 2 is incorrect, \n");
1875printf(" trying to fallback to Revision 1\n");
1876if ((rsdp_mod != (void *)0ul) && (rsdp_mod->Length >= ACPI_RSDP_REV0_SIZE) )
1877{
1878process_rsdt(rsdp_mod, false, new_table_list);
1879
1880} else {
1881printf("Error: Incorect ACPI RSD PTR or not found \n");
1882return EFI_UNSUPPORTED;
1883}
1884}
1885
1886out:
1887// Correct the checksum of RSDP
1888
1889DBG("RSDP: Original checksum %d\n", rsdp_mod->Checksum);
1890
1891setRsdpchecksum(rsdp_mod);
1892
1893DBG("New checksum %d\n", rsdp_mod->Checksum);
1894
1895if (Revision == 2)
1896{
1897DBG("RSDP: Original extended checksum %d\n", rsdp_mod->ExtendedChecksum);
1898
1899setRsdpXchecksum(rsdp_mod);
1900
1901DBG("New extended checksum %d\n", rsdp_mod->ExtendedChecksum);
1902
1903}
1904
1905verbose("ACPI Revision %d successfully patched\n", Revision);
1906
1907if (Revision == 2)
1908{
1909rsd_p = ((U64)((U32)rsdp_mod));
1910if (rsd_p)
1911Status = addConfigurationTable(&gEfiAcpi20TableGuid, &rsd_p, "ACPI_20");
1912}
1913else
1914{
1915rsd_p = ((U64)((U32)rsdp_mod));
1916if (rsd_p)
1917Status = addConfigurationTable(&gEfiAcpiTableGuid, &rsd_p, "ACPI");
1918
1919}
1920
1921#if DEBUG_ACPI
1922printf("Press a key to continue... (DEBUG_DSDT)\n");
1923getc();
1924#endif
1925return Status;
1926}
1927

Archive Download this file

Revision: 1141