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{
1257verbose("FADT: changing Preferred_PM_Profile from %d to %d\n", fadt->PreferredProfile, Type);
1258fadt_mod->PreferredProfile = Platform->Type = Type;
1259} else verbose("Error: system-type must be 0..6. Defaulting to %d !\n", Platform->Type);
1260}
1261
1262getBoolForKey(KIntelFADT, &intelfadtspec, &bootInfo->bootConfig);
1263if ((pmbase == 0) && (cpu_map_error == 0) && (intelfadtspec == true))
1264{
1265ACPI_TABLE_DSDT *DsdtPointer ;
1266if (new_dsdt != (void*)0ul)
1267DsdtPointer = new_dsdt;
1268else if ((fadt_mod->Header.Revision >= 3) && (fadt_mod->XDsdt != 0ul))
1269DsdtPointer = (ACPI_TABLE_DSDT *)((U32)fadt_mod->XDsdt);
1270else
1271DsdtPointer = (ACPI_TABLE_DSDT *)fadt_mod->Dsdt;
1272
1273generate_cpu_map_from_acpi(DsdtPointer);
1274}
1275
1276// Patch DSDT Address if we have loaded a DSDT table
1277if(new_dsdt != (void*)0ul)
1278fadt_mod->Dsdt=(U32)new_dsdt;
1279
1280fadt_mod->Facs= fadt->Facs;
1281//fadt_mod->Facs=(U32)generate_facs(false);
1282
1283// Patch FADT to fix restart
1284if (fadt_mod->Header.Revision >= 2 && fix_restart)
1285{
1286 fadt_mod->Flags|= 0x400;
1287
1288int type = PCI_RESET_TYPE;
1289getIntForKey(KResetType, &type, &bootInfo->bootConfig);
1290if (type == KEYBOARD_RESET_TYPE) {
1291//Azi: keyboard reset; http://forum.voodooprojects.org/index.php/topic,1056.msg9802.html#msg9802
1292fadt_mod->ResetRegister = FillGASStruct(0x64, 1);
1293fadt_mod->ResetValue = 0xfe;
1294} else {
1295fadt_mod->ResetRegister = FillGASStruct(0x0cf9, 1);
1296fadt_mod->ResetValue = 0x06;
1297}
1298verbose("FADT: Restart Fix applied (Type : %s) !\n", (type == 0) ? "PCI": "KEYBOARD");
1299}
1300
1301 if (fadt_mod->Header.Revision >= 3) {
1302
1303
1304 if (UpdateFADT) {
1305
1306//fadt_mod->XFacs= (U64)((U32)generate_facs(true));
1307 fadt_mod->XFacs=(U64)fadt->Facs;
1308
1309 } else {
1310fadt_mod->XFacs=(U64)fadt->XFacs;
1311}
1312
1313
1314 if(new_dsdt != (void*)0ul)
1315 fadt_mod->XDsdt=((U64)(U32)new_dsdt);
1316else if (UpdateFADT)
1317fadt_mod->XDsdt=(U64)fadt_mod->Dsdt;
1318
1319
1320 Platform->hardware_signature = ((ACPI_TABLE_FACS *)((U32)fadt_mod->XFacs))->HardwareSignature;
1321
1322 } else {
1323
1324 Platform->hardware_signature = ((ACPI_TABLE_FACS *)fadt_mod->Facs)->HardwareSignature;
1325
1326 }
1327
1328
1329DBG("setting hardware_signature to %x \n",Platform->hardware_signature);
1330
1331
1332
1333if (pmbase && (intelfadtspec == true))
1334ProcessFadt(fadt_mod, pmbase); // The checksum correction will be done by ProcessFadt
1335else
1336SetChecksum(&fadt_mod->Header); // Correct the checksum
1337
1338return fadt_mod;
1339}
1340
1341void process_xsdt (ACPI_TABLE_RSDP *rsdp_mod , U32 *new_table_list){
1342TagPtr DropTables_p = XMLCastDict(XMLGetProperty(bootInfo->bootConfig.dictionary, (const char*)"ACPIDropTables"));
1343U32 new_table = 0ul;
1344U8 new_table_index = 0, table_added = 0;
1345ACPI_TABLE_XSDT *xsdt = (void*)0ul, *xsdt_mod = (void*)0ul;
1346ACPI_TABLE_RSDT *rsdt_conv= (void *)0ul;
1347
1348// FIXME: handle 64-bit address correctly
1349
1350xsdt=(ACPI_TABLE_XSDT *)acpi_tables.XsdtPointer;
1351
1352verbose("* Processing XSDT: \n");
1353
1354DBG("XSDT @%x, Length=%d\n", (U32)xsdt,
1355xsdt->Header.Length);
1356
1357if (xsdt != (void *)0ul)
1358{
1359U32 dropoffset=0, index;
1360table_added = 0;
1361
1362xsdt_mod=(ACPI_TABLE_XSDT *)AllocateKernelMemory(xsdt->Header.Length);
1363bzero(xsdt_mod, xsdt->Header.Length);
1364memcpy(&xsdt_mod->Header, &xsdt->Header, sizeof(ACPI_TABLE_HEADER));
1365
1366U32 num_tables=get_num_tables64(xsdt);
1367
1368ACPI_TABLE_HEADER *table = (ACPI_TABLE_HEADER *) xsdt->TableOffsetEntry;
1369
1370for (index = 0; index < num_tables; index++) {
1371if (GetChecksum(table, table->Length) == 0) {
1372
1373xsdt_mod->TableOffsetEntry[index-dropoffset]=xsdt->TableOffsetEntry[index];
1374
1375char tableSig[4];
1376bool oem = false;
1377char oemOption[OEMOPT_SIZE];
1378
1379strlcpy(tableSig, (char*)((U32)(xsdt->TableOffsetEntry[index])), sizeof(tableSig)+1);
1380
1381sprintf(oemOption, "oem%s",tableSig );
1382if (getBoolForKey(oemOption, &oem, &bootInfo->bootConfig) && oem) { // This method don't work for DSDT and FACS
1383
1384if (get_new_table_in_list(new_table_list,((U32) (table->Signature)), &new_table_index) != (void*)0ul)
1385new_table_list[new_table_index] = 0ul; // This way new table will not be added to the new rsdt list !!
1386
1387continue;
1388}
1389
1390TagPtr match_drop = XMLGetProperty(DropTables_p, (const char*)tableSig);
1391if ( match_drop ) {
1392char *tmp = XMLCastString(match_drop);
1393if (strcmp(tmp,"No") != 0) {
1394dropoffset++;
1395DBG("%s table dropped\n",tableSig);
1396continue;
1397}
1398}
1399
1400if ((new_table = (U32)get_new_table_in_list(new_table_list,((U32) (table->Signature)), &new_table_index)) != 0ul)
1401{
1402xsdt_mod->TableOffsetEntry[index-dropoffset]=(U64)new_table;
1403new_table_list[new_table_index] = 0ul; // table replaced !!
1404continue;
1405}
1406}
1407// Move array pointer to next 64-bit pointer
1408table = (ACPI_TABLE_HEADER *) ((U32) table + sizeof(U64));
1409}
1410
1411
1412{
1413U8 i;
1414for (i = 0; i< (MAX_ACPI_TABLE + RESERVED_AERA); i++) {
1415if (new_table_list[i] != 0ul) {
1416xsdt_mod->TableOffsetEntry[index-dropoffset]=(U64)new_table_list[i];
1417table_added++;
1418index++;
1419}
1420}
1421}
1422
1423// Correct the checksum of XSDT
1424xsdt_mod->Header.Length-=8*dropoffset;
1425xsdt_mod->Header.Length+=8*table_added;
1426
1427SetChecksum(&xsdt_mod->Header);
1428
1429update_rsdp_with_xsdt(rsdp_mod, xsdt_mod);
1430
1431verbose("* Creating new RSDT from XSDT table\n");
1432
1433rsdt_conv = (ACPI_TABLE_RSDT *)gen_alloc_rsdt_from_xsdt(xsdt_mod);
1434update_rsdp_with_rsdt(rsdp_mod, rsdt_conv);
1435
1436
1437
1438}
1439else
1440{
1441DBG("About to drop XSDT\n");
1442
1443/*FIXME: Now we just hope that if MacOS doesn't find XSDT it reverts to RSDT.
1444 * A Better strategy would be to generate
1445 */
1446
1447rsdp_mod->XsdtPhysicalAddress=0xffffffffffffffffLL;
1448verbose("XSDT not found or XSDT incorrect\n");
1449}
1450
1451}
1452
1453void process_rsdt(ACPI_TABLE_RSDP *rsdp_mod , bool gen_xsdt, U32 *new_table_list)
1454{
1455TagPtr DropTables_p = XMLCastDict(XMLGetProperty(bootInfo->bootConfig.dictionary, (const char*)"ACPIDropTables"));
1456U32 new_table = 0ul;
1457U8 new_table_index = 0, table_added = 0;
1458U32 dropoffset=0, index;
1459ACPI_TABLE_RSDT *rsdt = (void *)0ul, *rsdt_mod= (void *)0ul;
1460ACPI_TABLE_XSDT *xsdt_conv = (void *)0ul;
1461
1462rsdt=(ACPI_TABLE_RSDT *)acpi_tables.RsdtPointer;
1463
1464DBG("RSDT @%x, Length %d\n",rsdt, rsdt->Header.Length);
1465
1466rsdt_mod=(ACPI_TABLE_RSDT *)AllocateKernelMemory(rsdt->Header.Length);
1467bzero(rsdt_mod, rsdt->Header.Length);
1468memcpy (&rsdt_mod->Header, &rsdt->Header, sizeof(ACPI_TABLE_HEADER));
1469
1470U32 num_tables = get_num_tables(rsdt);
1471
1472verbose("* Processing RSDT: \n");
1473ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) rsdt->TableOffsetEntry;
1474
1475// Compute number of table pointers included in RSDT
1476num_tables = get_num_tables(rsdt);
1477
1478for (index = 0; index < num_tables; index++) {
1479if (GetChecksum(table_array[index], table_array[index]->Length) == 0) {
1480
1481rsdt_mod->TableOffsetEntry[index-dropoffset]=rsdt->TableOffsetEntry[index];
1482
1483char tableSig[4];
1484bool oem = false;
1485char oemOption[OEMOPT_SIZE];
1486
1487strlcpy(tableSig, (char*)(rsdt->TableOffsetEntry[index]), sizeof(tableSig)+1);
1488
1489sprintf(oemOption, "oem%s",tableSig );
1490if (getBoolForKey(oemOption, &oem, &bootInfo->bootConfig) && oem) { // This method don't work for DSDT and FACS
1491
1492if (get_new_table_in_list(new_table_list,(*(U32 *) (table_array[index]->Signature)), &new_table_index) != (void*)0ul )
1493new_table_list[new_table_index] = 0ul; // This way new table will not be added to the new rsdt list !!
1494
1495continue;
1496}
1497
1498TagPtr match_drop = XMLGetProperty(DropTables_p, (const char*)tableSig);
1499if ( match_drop ) {
1500char *tmp = XMLCastString(match_drop);
1501if (strcmp(tmp,"No") != 0) {
1502dropoffset++;
1503DBG("%s table dropped\n",tableSig);
1504continue;
1505}
1506}
1507
1508if ((new_table = (U32)get_new_table_in_list(new_table_list,(*(U32 *) (table_array[index]->Signature)), &new_table_index)) != 0ul)
1509{
1510rsdt_mod->TableOffsetEntry[index-dropoffset]=new_table;
1511new_table_list[new_table_index] = 0ul; // table replaced !!
1512continue;
1513}
1514
1515}
1516}
1517DBG("\n");
1518
1519{
1520U8 i;
1521for (i = 0; i< (MAX_ACPI_TABLE + RESERVED_AERA); i++) {
1522if (new_table_list[i] != 0ul) {
1523rsdt_mod->TableOffsetEntry[index-dropoffset]=new_table_list[i];
1524table_added++;
1525index++;
1526}
1527}
1528}
1529
1530// Correct the checksum of RSDT
1531rsdt_mod->Header.Length-=4*dropoffset;
1532rsdt_mod->Header.Length+=4*table_added;
1533
1534DBG("RSDT: Original checksum %d\n", rsdt_mod->Header.Checksum);
1535
1536SetChecksum(&rsdt_mod->Header);
1537
1538DBG("New checksum %d at %x\n", rsdt_mod->Header.Checksum,rsdt_mod);
1539
1540update_rsdp_with_rsdt(rsdp_mod, rsdt_mod);
1541
1542if (gen_xsdt)
1543{
1544verbose("* Creating new XSDT from RSDT table\n");
1545xsdt_conv = (ACPI_TABLE_XSDT *)gen_alloc_xsdt_from_rsdt(rsdt_mod);
1546update_rsdp_with_xsdt(rsdp_mod, xsdt_conv);
1547
1548}
1549}
1550
1551
1552
1553EFI_STATUS setupAcpi(void)
1554{
1555U8 Revision = 0;
1556
1557 cpu_map_error = 0;
1558 cpu_map_count = 0;
1559 pmbase = 0;
1560
1561 EFI_STATUS Status = EFI_ABORTED;
1562
1563U32 new_table_list[MAX_ACPI_TABLE + RESERVED_AERA]; //max table + reserved aera
1564U8 new_table_index = 0;
1565
1566ACPI_TABLE_DSDT* DsdtPtr = (void *)0ul; // a Pointer to the dsdt table present in fadt_mod
1567
1568ACPI_TABLE_DSDT *new_dsdt = (void *)0ul;// a Pointer to the dsdt file
1569ACPI_TABLE_FADT *fadt_mod = (void *)0ul; // a Pointer to the patched FACP table
1570ACPI_TABLE_FADT *fadt_file = (void *)0ul; // a Pointer to the (non-patched) fadt file
1571ACPI_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
1572ACPI_TABLE_RSDP *rsdp_mod = (void *)0ul, *rsdp_conv= (void *)0ul;
1573
1574
1575U32 rsdplength;
1576
1577bool update_acpi=false, gen_xsdt=false;
1578
1579bool gen_csta=false, gen_psta=false, speed_step=false;
1580
1581bool oem_dsdt=false, oem_fadt=false;
1582
1583// Find original rsdp
1584if (!FindAcpiTables(&acpi_tables)){
1585printf("Error: AcpiCodec Failed to detect ACPI tables.\n");
1586getc();
1587return EFI_NOT_FOUND;
1588}
1589
1590{
1591U8 i;
1592
1593for (i=0; i<(MAX_ACPI_TABLE + RESERVED_AERA); i++) {
1594new_table_list[i] = 0ul;
1595}
1596bool tmpval;
1597
1598oem_dsdt=getBoolForKey(kOEMDSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1599oem_fadt=getBoolForKey(kOEMFADT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1600
1601
1602gen_csta=getBoolForKey(kGenerateCStates, &tmpval, &bootInfo->bootConfig)&&tmpval;
1603gen_psta=getBoolForKey(kGeneratePStates, &tmpval, &bootInfo->bootConfig)&&tmpval;
1604
1605update_acpi=getBoolForKey(kUpdateACPI, &tmpval, &bootInfo->bootConfig)&&tmpval;
1606
1607speed_step=getBoolForKey(kSpeedstep, &tmpval, &bootInfo->bootConfig)&&tmpval;
1608
1609}
1610
1611{
1612char* name;
1613long flags;
1614long time;
1615long ret = -1;
1616U8 i = 0;
1617char dirspec[512];
1618bool acpidir_found = false;
1619
1620ret = GetFileInfo("/Extra/", "Acpi", &flags, &time);
1621if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory)) {
1622sprintf(dirspec, "/Extra/Acpi/");
1623acpidir_found = true;
1624
1625} else {
1626ret = GetFileInfo("bt(0,0)/Extra/", "Acpi", &flags, &time);
1627if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory)) {
1628sprintf(dirspec, "bt(0,0)/Extra/Acpi/");
1629acpidir_found = true;
1630
1631}
1632}
1633
1634if (acpidir_found == true) {
1635struct dirstuff* moduleDir = opendir(dirspec);
1636while(readdir(moduleDir, (const char**)&name, &flags, &time) >= 0)
1637{
1638if((strcmp(&name[strlen(name) - sizeof("aml")], ".aml") == 0) && ((strlen(dirspec)+strlen(name)) < 512))
1639{
1640// Some simple verifications to save time in case of those tables simply named as follow:
1641if ((strncmp(name, "RSDT", 4) == 0) || (strncmp(name, "rsdt", 4) == 0) ||
1642(strncmp(name, "XSDT", 4) == 0) || (strncmp(name, "xsdt", 4) == 0) ||
1643(strncmp(name, "RSDP", 4) == 0) || (strncmp(name, "rsdp", 4) == 0))
1644{
1645continue;
1646}
1647
1648if ((strncmp(name, "FACS", 4) == 0) || (strncmp(name, "facs", 4) == 0)) { // For now FACS is not supported
1649continue;
1650}
1651
1652char* tmp = malloc(strlen(name) + 1);
1653strcpy(tmp, name);
1654
1655DBG("* Attempting to load acpi table: %s\n", tmp);
1656if( (new_table_list[i]=(U32)loadACPITable(dirspec,tmp)))
1657{
1658if (i < MAX_ACPI_TABLE) {
1659i++;
1660} else {
1661break;
1662}
1663
1664
1665} else {
1666free(tmp);
1667}
1668
1669}
1670#if DEBUG_ACPI
1671else
1672{
1673DBG("Ignoring %s\n", name);
1674}
1675#endif
1676
1677}
1678
1679if (i) {
1680//sanitize the new tables list
1681sanitize_new_table_list(new_table_list);
1682
1683//move to kernel memory
1684move_table_list_to_kmem(new_table_list);
1685
1686DBG("New ACPI tables Loaded in memory\n");
1687}
1688}
1689
1690}
1691
1692// TODO : Add an option for that
1693 //cpuNamespace = CPU_NAMESPACE_PR; //Default
1694
1695
1696if (speed_step) {
1697gen_psta= true;
1698gen_csta= true;
1699}
1700
1701
1702ACPI_TABLE_RSDP *rsdp=(ACPI_TABLE_RSDP *)acpi_tables.RsdPointer;
1703
1704if (rsdp == (void*)0ul || (GetChecksum(rsdp, (rsdp->Revision == 0) ? ACPI_RSDP_REV0_SIZE:sizeof(ACPI_TABLE_RSDP)) != 0) ) {
1705printf("Error : ACPI RSD PTR Revision %d checksum is incorrect or table not found \n",rsdp->Revision );
1706return EFI_UNSUPPORTED;
1707}
1708
1709if ((update_acpi) && (rsdp->Revision == 0))
1710{
1711
1712rsdp_conv = (ACPI_TABLE_RSDP *)gen_alloc_rsdp_v2_from_v1(rsdp);
1713if (rsdp_conv != (void *)0ul) {
1714gen_xsdt = true;
1715rsdp = rsdp_conv;
1716verbose("Converted ACPI RSD PTR Revision 0 to Revision 2\n");
1717}
1718
1719}
1720
1721Revision = rsdp->Revision ;
1722rsdplength=(Revision == 2)?rsdp->Length:ACPI_RSDP_REV0_SIZE;
1723
1724DBG("RSDP Revision %d found @%x. Length=%d\n",Revision,rsdp,rsdplength);
1725
1726/* FIXME: no check that memory allocation succeeded
1727 * Copy and patch RSDP,RSDT, XSDT and FADT
1728 * For more info see ACPI Specification pages 110 and following
1729 */
1730
1731if (gen_xsdt)
1732{
1733rsdp_mod=rsdp_conv;
1734} else {
1735rsdp_mod=(ACPI_TABLE_RSDP *) AllocateKernelMemory(rsdplength);
1736memcpy(rsdp_mod, rsdp, rsdplength);
1737}
1738
1739
1740if ((fadt_file = (ACPI_TABLE_FADT *)get_new_table_in_list(new_table_list, NAMESEG("FACP"), &new_table_index)) != (void *)0ul) {
1741
1742if (oem_fadt == false)
1743FacpPointer = (ACPI_TABLE_FADT *)fadt_file;
1744
1745new_table_list[new_table_index] = 0ul; // This way, the non-patched table will not be added in our new rsdt/xsdt table list
1746
1747} else
1748FacpPointer = (acpi_tables.FacpPointer64 != (void *)0ul) ?
1749(ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer;
1750
1751#if DEBUG_ACPI
1752if ((FacpPointer != (void *)0ul) || (oem_fadt == false)) {
1753printf("FADT found @%x, Length %d\n",FacpPointer, FacpPointer->Header.Length);
1754printf("Attempting to patch FADT entry of %s\n",(acpi_tables.FacpPointer64 != (void *)0ul) ? ACPI_SIG_XSDT : ACPI_SIG_RSDT);
1755}
1756#endif
1757
1758if ((new_dsdt = (ACPI_TABLE_DSDT *)get_new_table_in_list(new_table_list, NAMESEG("DSDT"), &new_table_index)) != (void*)0ul ) {
1759new_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
1760}
1761
1762if (oem_fadt == false) {
1763
1764fadt_mod = patch_fadt(FacpPointer, (oem_dsdt == false) ? new_dsdt : (void*)0ul , (acpi_tables.FacpPointer64 != (void *)0ul ));
1765
1766
1767DsdtPtr = ((fadt_mod->Header.Revision >= 3) && (fadt_mod->XDsdt != 0)) ? (ACPI_TABLE_DSDT*)((U32)fadt_mod->XDsdt):(ACPI_TABLE_DSDT*)fadt_mod->Dsdt;
1768
1769if (fadt_mod != (void*)0ul) {
1770
1771U8 empty = get_0ul_index_in_list(new_table_list,true);
1772if (empty != ACPI_TABLE_LIST_FULL) {
1773new_table_list[empty] = (U32)fadt_mod; // add the patched table to the list
1774} else {
1775printf("Error: not enought reserved space in the new acpi list for the Patched FACP table,\n ");
1776printf(" please increase the RESERVED_AERA\n");
1777}
1778
1779} else {
1780printf("Error: Failed to patch the FADT Table, trying fallback to the FADT original pointer\n");
1781fadt_mod = (acpi_tables.FacpPointer64 != (void *)0ul) ?
1782(ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer;
1783
1784U8 empty = get_0ul_index_in_list(new_table_list,true);
1785if (empty != ACPI_TABLE_LIST_FULL) {
1786new_table_list[empty] = (U32)fadt_mod;
1787} else {
1788printf("Error: not enought reserved space in the new acpi list for the FACP table,\n ");
1789printf(" please increase the RESERVED_AERA\n");
1790}
1791}
1792
1793if (oem_dsdt == false) {
1794if (generate_cpu_map_from_acpi(DsdtPtr) == 0){
1795U8 new_uid = (U8)getPciRootUID();
1796
1797/* WARNING: THIS METHOD WORK PERFECTLY BUT IT CAN RESULT TO AN INCORRECT CHECKSUM */
1798
1799if (ProcessDsdt(DsdtPtr, UIDPointer, new_uid)) {
1800printf("PCI0 _UID patched to %d in the DSDT table\n", new_uid);
1801}
1802
1803}
1804}
1805
1806
1807} else {
1808
1809// here we use the variable fadt_mod only for SSDT Generation
1810
1811fadt_mod = (acpi_tables.FacpPointer64 != (void *)0ul) ?
1812(ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer;
1813
1814DsdtPtr = ((fadt_mod->Header.Revision >= 3) && (fadt_mod->XDsdt != 0)) ? (ACPI_TABLE_DSDT*)((U32)fadt_mod->XDsdt)
1815:(ACPI_TABLE_DSDT*)fadt_mod->Dsdt;
1816}
1817
1818if (speed_step || gen_csta || gen_psta) {
1819U8 empty = get_0ul_index_in_list(new_table_list, true);
1820
1821// Generate _CST SSDT
1822if ( speed_step || gen_csta)
1823{
1824if (empty != ACPI_TABLE_LIST_FULL) {
1825if (new_table_list[empty] =(U32)generate_cst_ssdt(fadt_mod))
1826{
1827if (speed_step || gen_psta)
1828empty = get_0ul_index_in_list(new_table_list,true);
1829}
1830} else {
1831printf("Error: not enought reserved space in the new acpi list for the _CST SSDT table,\n ");
1832printf(" please increase the RESERVED_AERA\n");
1833}
1834}
1835
1836
1837// Generating _PSS SSDT
1838if (speed_step || gen_psta)
1839{
1840if (empty != ACPI_TABLE_LIST_FULL) {
1841
1842new_table_list[empty] =(U32)generate_pss_ssdt(DsdtPtr);
1843
1844} else {
1845printf("Error: not enought reserved space in the new acpi list for the _PSS SSDT table,\n ");
1846printf(" please increase the RESERVED_AERA\n");
1847}
1848}
1849}
1850
1851if ((rsdp_mod != (void *)0ul) && (rsdp_mod->Length >= ACPI_RSDP_REV0_SIZE) )
1852{
1853if ((rsdp_mod->Revision == 0) || (gen_xsdt == true)) {
1854process_rsdt(rsdp_mod, gen_xsdt, new_table_list);
1855goto out;
1856}
1857
1858} else {
1859printf("Error: Incorect ACPI RSD PTR or not found \n");
1860return EFI_UNSUPPORTED;
1861}
1862
1863if ((GetChecksum(rsdp_mod, sizeof(ACPI_TABLE_RSDP)) == 0) &&
1864(Revision == 2) &&
1865(rsdplength == sizeof(ACPI_TABLE_RSDP)))
1866{
1867process_xsdt(rsdp_mod, new_table_list);
1868} else {
1869printf("Warning : ACPI RSD PTR Revision 2 is incorrect, \n");
1870printf(" trying to fallback to Revision 1\n");
1871if ((rsdp_mod != (void *)0ul) && (rsdp_mod->Length >= ACPI_RSDP_REV0_SIZE) )
1872{
1873process_rsdt(rsdp_mod, false, new_table_list);
1874
1875} else {
1876printf("Error: Incorect ACPI RSD PTR or not found \n");
1877return EFI_UNSUPPORTED;
1878}
1879}
1880
1881out:
1882// Correct the checksum of RSDP
1883
1884DBG("RSDP: Original checksum %d\n", rsdp_mod->Checksum);
1885
1886setRsdpchecksum(rsdp_mod);
1887
1888DBG("New checksum %d\n", rsdp_mod->Checksum);
1889
1890if (Revision == 2)
1891{
1892DBG("RSDP: Original extended checksum %d\n", rsdp_mod->ExtendedChecksum);
1893
1894setRsdpXchecksum(rsdp_mod);
1895
1896DBG("New extended checksum %d\n", rsdp_mod->ExtendedChecksum);
1897
1898}
1899
1900verbose("ACPI Revision %d successfully patched\n", Revision);
1901
1902if (Revision == 2)
1903{
1904rsd_p = ((U64)((U32)rsdp_mod));
1905if (rsd_p)
1906Status = addConfigurationTable(&gEfiAcpi20TableGuid, &rsd_p, "ACPI_20");
1907}
1908else
1909{
1910rsd_p = ((U64)((U32)rsdp_mod));
1911if (rsd_p)
1912Status = addConfigurationTable(&gEfiAcpiTableGuid, &rsd_p, "ACPI");
1913
1914}
1915
1916#if DEBUG_ACPI
1917printf("Press a key to continue... (DEBUG_DSDT)\n");
1918getc();
1919#endif
1920return Status;
1921}
1922

Archive Download this file

Revision: 1119