Chameleon

Chameleon Svn Source Tree

Root/branches/ErmaC/Trunk/i386/modules/AcpiCodec/acpi_codec.c

  • Property svn:executable set to *
1/*
2 * Copyright 2008 mackerintel
3 */
4
5/*
6 Copyright (c) 2010, Intel Corporation
7 All rights reserved.
8
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
11
12 * Redistributions of source code must retain the above copyright notice,
13 this list of conditions and the following disclaimer.
14 * Redistributions in binary form must reproduce the above copyright notice,
15 this list of conditions and the following disclaimer in the documentation
16 and/or other materials provided with the distribution.
17 * Neither the name of Intel Corporation nor the names of its contributors
18 may be used to endorse or promote products derived from this software
19 without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
25 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
28 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/*
34 * Copyright (c) 2011,2012 cparm <armelcadetpetit@gmail.com>. All rights reserved.
35 *
36 */
37
38#include "libsaio.h"
39#include "bootstruct.h"
40#include "acpi.h"
41#include "acpidecode.h"
42#include "acpicode.h"
43#include "efi_tables.h"
44#include "fake_efi.h"
45#include "acpi_codec.h"
46#include "platform.h"
47#include "cpu.h"
48#include "xml.h"
49#include "sl.h"
50#include "convert.h"
51#include "modules.h"
52#include "pci.h"
53#include "pci_root.h"
54
55U64 rsd_p;
56ACPI_TABLES acpi_tables;
57U32 uuid32;
58U32 Model32;
59bool checkOem = false;
60
61extern EFI_STATUS addConfigurationTable();
62
63extern EFI_GUID gEfiAcpiTableGuid;
64extern EFI_GUID gEfiAcpi20TableGuid;
65
66#ifndef DEBUG_ACPI
67#define DEBUG_ACPI 0
68#endif
69
70#if DEBUG_ACPI==2
71#define DBG(x...) {printf(x); sleep(1);}
72#elif DEBUG_ACPI==1
73#define DBG(x...) printf(x)
74#else
75#define DBG(x...)
76#endif
77
78#define OLD_SSDT 0
79#define BETA 0
80#define BUILD_ACPI_TSS 0
81#define pstate_power_support 1
82
83#if BETA
84#ifdef pstate_power_support
85#undef pstate_power_support
86#endif
87#define pstate_power_support 1
88#endif
89
90#if DEBUG_ACPI
91static void print_nameseg(U32 i);
92#endif
93
94static ACPI_TABLE_HEADER * get_new_table_in_list(U32 *new_table_list, U32 Signature, U8 *retIndex );
95static U8 get_number_of_tables_in_list(U32 *new_table_list, U32 Signature );
96static U8 get_0ul_index_in_list(U32 *new_table_list, bool reserved );
97static void sanitize_new_table_list(U32 *new_table_list );
98static void move_table_list_to_kmem(U32 *new_table_list );
99static ACPI_TABLE_RSDP * gen_alloc_rsdp_v2_from_v1(ACPI_TABLE_RSDP *rsdp );
100static ACPI_TABLE_RSDT * gen_alloc_rsdt_from_xsdt(ACPI_TABLE_XSDT *xsdt);
101static ACPI_TABLE_XSDT * gen_alloc_xsdt_from_rsdt(ACPI_TABLE_RSDT *rsdt);
102#if 0
103static void MakeAcpiSgn(void);
104#endif
105static void *loadACPITable(U32 *new_table_list, char *dirspec, const char *filename );
106static int generate_cpu_map_from_acpi(ACPI_TABLE_DSDT * DsdtPointer);
107static ACPI_GENERIC_ADDRESS FillGASStruct(U32 Address, U8 Length);
108static U32 process_xsdt (ACPI_TABLE_RSDP *rsdp_mod , U32 *new_table_list);
109static U32 process_rsdt(ACPI_TABLE_RSDP *rsdp_mod , bool gen_xsdt, U32 *new_table_list);
110static ACPI_TABLE_FADT * patch_fadt(ACPI_TABLE_FADT *fadt, ACPI_TABLE_DSDT *new_dsdt, bool UpdateFADT);
111
112
113#define IA32_MISC_ENABLES 0x01A0
114#define MSR_TURBO_POWER_CURRENT_LIMIT 0x1AC
115#define MSR_PKG_CST_CONFIG_CONTROL 0x00E2
116#define MSR_RAPL_POWER_UNIT 0x606
117#define MSR_PKG_RAPL_POWER_LIMIT 0x610
118static U32 turbo_enabled = 0;
119static U32 ProcessMadt(ACPI_TABLE_MADT * madt, MADT_INFO * madt_info, void * buffer, U32 bufferSize, U32 NB_CPU);
120static U32 buildMADT(U32 * new_table_list, ACPI_TABLE_DSDT *dsdt, MADT_INFO * madt_info);
121static U32 BuildSsdt(MADT_INFO * madt_info, ACPI_TABLE_DSDT *dsdt, void * buffer, U32 bufferSize, bool enable_cstates, bool enable_pstates, bool enable_tstates);
122static bool is_sandybridge(void);
123static bool is_jaketown(void);
124static U32 encode_pstate(U32 ratio);
125static void collect_cpu_info(CPU_DETAILS * cpu);
126#ifndef BETA
127//static U32 BuildCoreIPstateInfo(CPU_DETAILS * cpu);
128#endif
129static U32 BuildCstateInfo(CPU_DETAILS * cpu, U32 pmbase);
130static U32 BuildPstateInfo(CPU_DETAILS * cpu);
131static U32 ProcessSsdt(U32 * new_table_list, ACPI_TABLE_DSDT *dsdt, MADT_INFO * madt_info, bool enable_cstates, bool enable_pstates, bool enable_tstates );
132static void * buildCpuScope (void * current, U32 cpu_namespace, PROCESSOR_NUMBER_TO_NAMESEG * aslCpuNamePath);
133static void * buildPDC(void * current);
134static void * buildOSC(void * current);
135static void * buildPSS(void * current, PKG_PSTATES * pkg_pstates);
136static void * buildPSD(void * current, U32 domain, U32 cpusInDomain, U32 pstate_coordination);
137static void * buildPPC(void * current);
138static void * buildPCT(void * current);
139static void * buildCstate(void * current, ACPI_GENERIC_ADDRESS * gas, CSTATE * cstate);
140static void * buildReturnPackageCST(void * current, PKG_CSTATES * pkg_cstates);
141static void * buildCST(void * current, PKG_CSTATES * mwait_pkg_cstates, PKG_CSTATES * io_pkg_cstates);
142#if BUILD_ACPI_CSD
143static void * buildCSD(void * current, U32 domain, U32 cpusInDomain, PKG_CSTATES * pkg_cstates);
144#endif
145#if BUILD_ACPI_TSS
146static U32 BuildTstateInfo(CPU_DETAILS * cpu);
147static void * buildTPC(void * current);
148static void * buildPTC(void * current);
149static void * buildTSS(void * current, PKG_TSTATES * pkg_tstates);
150static void * buildTSD(void * current, U32 domain, U32 cpusInDomain);
151#endif
152#if pstate_power_support
153static U64 mulU64byU64(U64 a, U64 b, U64 * high);
154static U32 compute_pstate_power(CPU_DETAILS * cpu, U32 ratio, U32 TDP);
155#endif
156#if BUILD_ACPI_TSS || pstate_power_support
157static U64 divU64byU64(U64 n, U64 d, U64 * rem);
158static U32 compute_tdp(CPU_DETAILS * cpu);
159#endif
160static bool is_sandybridge(void);
161static bool is_jaketown(void);
162static U32 get_bclk(void);
163static void GetMaxRatio(U32 * max_non_turbo_ratio);
164//static U32 computePstateRatio(const U32 max, const U32 min, const U32 turboEnabled, const U32 numStates, const U32 pstate);
165//static U32 computeNumPstates(const U32 max, const U32 min, const U32 turboEnabled, const U32 pssLimit);
166
167#if UNUSED
168static ACPI_TABLE_FACS* generate_facs(bool updatefacs );
169#endif
170
171#define MAX_NON_SSDT_TABLE 15
172#define MAX_SSDT_TABLE 15 // 15 additional SSDT tables
173#define MAX_ACPI_TABLE MAX_NON_SSDT_TABLE + MAX_SSDT_TABLE
174
175// Security space for SSDT , FACP & MADT table generation,
176// the size can be increased
177// note: the table will not placed in the reserved space if the 'normal' space is not full
178#define RESERVED_AERA 3
179
180#define ACPI_TABLE_LIST_FULL MAX_ACPI_TABLE + RESERVED_AERA + 1
181
182#define ACPI_TABLE_LIST_FULL_NON_RESERVED MAX_ACPI_TABLE + 1
183
184#ifndef ULONG_MAX_32
185#define ULONG_MAX_32 4294967295UL
186#endif
187
188#define __RES(s, u)\
189static inline unsigned u\
190resolve_##s(unsigned u defaultentry, char *str, int base) \
191{\
192unsigned u entry = defaultentry;\
193if (str && (strcmp(str,"Default") != 0)) {\
194entry = strtoul((const char *)str, NULL,base);\
195}\
196return entry;\
197}
198
199__RES(pss, long)
200__RES(cst, int)
201
202static ACPI_TABLE_HEADER * get_new_table_in_list(U32 *new_table_list, U32 Signature, U8 *retIndex )
203{
204ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;
205U8 index ;
206*retIndex = 0;
207
208for (index = 0; index < (MAX_ACPI_TABLE + RESERVED_AERA); index++)
209{
210if (*(U32 *) (table_array[index]->Signature) == Signature)
211{
212*retIndex = index;
213return table_array[index] ;
214}
215}
216return (void*)0ul;
217}
218
219static U8 get_number_of_tables_in_list(U32 *new_table_list, U32 Signature )
220{
221ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;
222U8 index ;
223U8 InstalledTables = 0;
224
225for (index = 0; index < (MAX_ACPI_TABLE + RESERVED_AERA); index++)
226{
227if (*(U32 *) (table_array[index]->Signature) == Signature)
228{
229InstalledTables++ ;
230}
231}
232return InstalledTables;
233}
234
235static U8 get_0ul_index_in_list(U32 *new_table_list, bool reserved )
236{
237U8 index ;
238
239U8 maximum = (reserved == true) ? MAX_ACPI_TABLE + RESERVED_AERA : MAX_ACPI_TABLE;
240
241for (index = 0; index < maximum; index++)
242{
243if (new_table_list[index] == 0ul)
244{
245return index ;
246}
247}
248return (reserved == true)? ACPI_TABLE_LIST_FULL : ACPI_TABLE_LIST_FULL_NON_RESERVED;
249}
250
251/* cparm : This time we check it by the acpi signature */
252static void sanitize_new_table_list(U32 *new_table_list )
253{
254ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;
255U8 index ;
256
257for (index = 0; index < MAX_ACPI_TABLE; index++)
258{
259U32 current_sig = *(U32 *) (table_array[index]->Signature);
260
261if ((current_sig == NAMESEG(ACPI_SIG_FACS) /* not supported */ )
262|| (current_sig == NAMESEG(ACPI_SIG_XSDT))
263|| (current_sig == NAMESEG(ACPI_SIG_RSDT)) || (*(volatile U64 *)table_array[index] == NAMESEG64(ACPI_SIG_RSDP)) )
264{
265
266void *buf = (void*)new_table_list[index];
267free(buf);
268new_table_list[index] = 0ul ;
269}
270}
271}
272
273/* cparm : move all tables to kernel memory */
274static void move_table_list_to_kmem(U32 *new_table_list )
275{
276ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;
277U8 index ;
278
279for (index = 0; index < MAX_ACPI_TABLE; index++)
280{
281if (new_table_list[index] != 0ul)
282{
283
284U32 current_sig = *(U32 *) (table_array[index]->Signature);
285if ((current_sig != NAMESEG(ACPI_SIG_FACS) /* not supported */ )
286&& (current_sig != NAMESEG(ACPI_SIG_XSDT))
287&& (current_sig != NAMESEG(ACPI_SIG_RSDT)) && (*(volatile U64 *)table_array[index] != NAMESEG64(ACPI_SIG_RSDP))
288&& (GetChecksum(table_array[index], table_array[index]->Length) == 0))
289{
290
291void *tableAddr=(void*)AllocateKernelMemory(table_array[index]->Length);
292if (!tableAddr) {
293printf("Unable to allocate kernel memory for aml file ");
294
295void *buf = (void*)new_table_list[index];
296free(buf);
297new_table_list[index] = 0ul ;
298continue;
299}
300bcopy(table_array[index], tableAddr, table_array[index]->Length);
301new_table_list[index] = 0ul ;
302new_table_list[index] = (U32)tableAddr ;
303
304}
305else
306{
307
308void *buf = (void*)new_table_list[index];
309free(buf);
310new_table_list[index] = 0ul ;
311}
312}
313}
314}
315
316static ACPI_TABLE_RSDP * gen_alloc_rsdp_v2_from_v1(ACPI_TABLE_RSDP *rsdp )
317{
318
319ACPI_TABLE_RSDP * rsdp_conv = (ACPI_TABLE_RSDP *)AllocateKernelMemory(sizeof(ACPI_TABLE_RSDP));
320
321if (rsdp_conv) {
322bzero(rsdp_conv, sizeof(ACPI_TABLE_RSDP));
323memcpy(rsdp_conv, rsdp, ACPI_RSDP_REV0_SIZE);
324
325/* Add/change fields */
326rsdp_conv->Revision = 2; /* ACPI version 3 */
327rsdp_conv->Length = sizeof(ACPI_TABLE_RSDP);
328
329/* Correct checksums */
330setRsdpchecksum(rsdp_conv);
331setRsdpXchecksum(rsdp_conv);
332}
333
334 return (rsdp_conv) ? rsdp_conv : (void*)0ul ;
335}
336
337static ACPI_TABLE_RSDT * gen_alloc_rsdt_from_xsdt(ACPI_TABLE_XSDT *xsdt)
338{
339 U32 index;
340 U32 num_tables;
341
342DBG("Attempting to generate RSDT from XSDT \n");
343
344 num_tables= get_num_tables64(xsdt);
345
346 ACPI_TABLE_RSDT * rsdt_conv=(ACPI_TABLE_RSDT *)AllocateKernelMemory(sizeof(ACPI_TABLE_HEADER)+(num_tables * 4));
347if (!rsdt_conv)
348{
349printf("Unable to allocate kernel memory for rsdt conv\n");
350return (void*)0ul;
351}
352
353
354bzero(rsdt_conv, sizeof(ACPI_TABLE_HEADER)+(num_tables * 4));
355 memcpy(&rsdt_conv->Header, &xsdt->Header, sizeof(ACPI_TABLE_HEADER));
356
357 rsdt_conv->Header.Signature[0] = 'R';
358 rsdt_conv->Header.Signature[1] = 'S';
359 rsdt_conv->Header.Signature[2] = 'D';
360 rsdt_conv->Header.Signature[3] = 'T';
361 rsdt_conv->Header.Length = sizeof(ACPI_TABLE_HEADER)+(num_tables * 4);
362
363for (index=0;index<num_tables;index++)
364 {
365U64 ptr = xsdt->TableOffsetEntry[index];
366
367{
368if (ptr > ULONG_MAX)
369{
370#if DEBUG_ACPI
371printf("Warning xsdt->TableOffsetEntry[%d]: Beyond addressable memory in this CPU mode, ignored !!!\n",index);
372#endif
373continue;
374}
375#if DEBUG_ACPI
376printf("* Processing : ");
377print_nameseg(*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature);
378printf("\n");
379#endif
380int method = 0;
381getIntForKey(kAcpiMethod, &method, &bootInfo->chameleonConfig);
382
383
384if (method != 0x2)
385{
386if (GetChecksum(((ACPI_TABLE_HEADER *) (unsigned long)ptr),
387((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Length) != 0)
388{
389#if DEBUG_ACPI
390printf("Warning : Invalide checksum, ignored !!!\n",index);
391#endif
392continue;
393}
394}
395
396}
397
398{
399if (*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature == NAMESEG(ACPI_SIG_FADT))
400{
401ACPI_TABLE_FADT *fadt=(ACPI_TABLE_FADT *)((U32)ptr);
402
403ACPI_TABLE_FADT *fadt_conv = (void*)0ul;
404
405if (fadt->Header.Revision > 1)
406{
407U8 buffer[0x74];
408DBG("Downgrading ACPI V%d FADT to ACPI V1 FADT \n", fadt->Header.Revision);
409fadt_conv=(ACPI_TABLE_FADT *)buffer;
410memcpy(fadt_conv, fadt, 0x74);
411fadt_conv->Header.Length = 0x74;
412fadt_conv->Header.Revision = 0x01;
413SetChecksum(&fadt_conv->Header);
414}
415else
416{
417fadt_conv = fadt;
418}
419
420ACPI_TABLE_FADT *fadt_mod = patch_fadt(fadt_conv, ((ACPI_TABLE_DSDT*)((U32)fadt->XDsdt)), false);
421if (fadt_mod == (void*)0ul)
422{
423printf("Error: Failed to patch FADT Table, trying wiht the original fadt pointer\n");
424fadt_mod = fadt;
425}
426
427rsdt_conv->TableOffsetEntry[index] = ((U32)fadt_mod);
428#if DEBUG_ACPI
429print_nameseg(*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature);
430printf(" table converted and added succesfully\n");
431#endif
432continue;
433}
434}
435
436{
437rsdt_conv->TableOffsetEntry[index] = (U32)ptr;
438#if DEBUG_ACPI
439print_nameseg(*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature);
440printf(" table converted and added succesfully\n");
441#endif
442}
443
444 }
445 DBG("RSDT_CONV : Original checksum %d\n", rsdt_conv->Header.Checksum);
446 SetChecksum(&rsdt_conv->Header);
447 DBG("New checksum %d\n", rsdt_conv->Header.Checksum);
448
449 return rsdt_conv;
450}
451
452static ACPI_TABLE_XSDT * gen_alloc_xsdt_from_rsdt(ACPI_TABLE_RSDT *rsdt)
453{
454U32 index;
455 U32 num_tables;
456
457DBG("Attempting to generate XSDT from RSDT \n");
458
459 num_tables= get_num_tables(rsdt);
460
461 ACPI_TABLE_XSDT * xsdt_conv=(ACPI_TABLE_XSDT *)AllocateKernelMemory(sizeof(ACPI_TABLE_HEADER)+(num_tables * 8));
462
463if (!xsdt_conv) {
464printf("Unable to allocate kernel memory for xsdt conv\n");
465return (void*)0ul;
466}
467
468bzero(xsdt_conv, sizeof(ACPI_TABLE_HEADER)+(num_tables * 8));
469 memcpy(&xsdt_conv->Header, &rsdt->Header, sizeof(ACPI_TABLE_HEADER));
470
471 xsdt_conv->Header.Signature[0] = 'X';
472 xsdt_conv->Header.Signature[1] = 'S';
473 xsdt_conv->Header.Signature[2] = 'D';
474 xsdt_conv->Header.Signature[3] = 'T';
475 xsdt_conv->Header.Length = sizeof(ACPI_TABLE_HEADER)+(num_tables * 8);
476
477ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) rsdt->TableOffsetEntry;
478
479 for (index=0;index<num_tables;index++)
480 {
481 {
482#if DEBUG_ACPI
483 printf("* Processing : ");
484 print_nameseg(*(U32*) (table_array[index]->Signature));
485 printf("\n");
486#endif
487 int method = 0;
488getIntForKey(kAcpiMethod, &method, &bootInfo->chameleonConfig);
489
490
491if (method != 0x2)
492 {
493 if (GetChecksum(table_array[index], table_array[index]->Length) != 0)
494 {
495#if DEBUG_ACPI
496 printf("Warning : Invalide checksum, ignored !!!\n",index);
497#endif
498 continue;
499 }
500 }
501
502 }
503
504 {
505 if (*(U32 *) (table_array[index]->Signature) == NAMESEG(ACPI_SIG_FADT))
506 {
507 ACPI_TABLE_FADT *FacpPointer = ((ACPI_TABLE_FADT*)table_array[index]);
508 ACPI_TABLE_FADT *fadt_mod = (ACPI_TABLE_FADT *)patch_fadt(FacpPointer,((ACPI_TABLE_DSDT*)FacpPointer->Dsdt),true);
509 if (fadt_mod == (void*)0ul)
510 {
511 printf("Error: Failed to patch (& update) FADT Table, fallback to original fadt pointer\n");
512 fadt_mod = FacpPointer;
513 }
514 xsdt_conv->TableOffsetEntry[index] = ((U64)((U32)fadt_mod));
515
516 continue;
517 }
518 }
519
520 xsdt_conv->TableOffsetEntry[index] = ((U64)((U32)table_array[index]));
521 }
522 DBG("XSDT_CONV : Original checksum %d\n", xsdt_conv->Header.Checksum);
523 SetChecksum(&xsdt_conv->Header);
524 DBG("New checksum %d\n", xsdt_conv->Header.Checksum);
525
526 return xsdt_conv;
527}
528
529#if ACPISGN
530static void MakeAcpiSgn(void)
531{
532
533char * DefaultplatformName = NULL;
534Model32 = 0;
535
536if ((DefaultplatformName = readDefaultPlatformName()))
537{
538Model32 = OSSwapHostToBigInt32(adler32( (unsigned char *) DefaultplatformName, strlen(DefaultplatformName)));
539}
540
541uuid32 = 0;
542
543const char *uuidStr = getStringFromUUID((int8_t*)(uint32_t)get_env(envSysId));
544
545if (strlen(uuidStr))
546{
547uuid32 = OSSwapHostToBigInt32(adler32( (unsigned char *) uuidStr, UUID_STR_LEN ));
548}
549
550}
551#endif
552
553static void *loadACPITable(U32 *new_table_list, char *dirspec, const char *filename )
554{
555int fd = -1;
556char acpi_file[512];
557
558DBG("Searching for %s file ...\n", filename);
559// Check booting partition
560
561sprintf(acpi_file, "%s%s",dirspec, filename);
562
563fd=open(acpi_file,0);
564
565if (fd<0)
566{
567DBG("Couldn't open ACPI Table: %s\n", acpi_file);
568return (void *)0ul ;
569}
570
571void *tableAddr=(void*)malloc(file_size (fd));
572
573if (tableAddr)
574{
575if (read (fd, tableAddr, file_size (fd))!=file_size (fd))
576{
577printf("Couldn't read table %s\n",acpi_file);
578free (tableAddr);
579close (fd);
580return (void *)0ul ;
581}
582
583close (fd);
584
585ACPI_TABLE_HEADER * header = (ACPI_TABLE_HEADER *)tableAddr;
586
587if (*(U32*)(header->Signature) != NAMESEG("SSDT"))
588{
589U8 dummy = 0;
590if (get_new_table_in_list(new_table_list, *(U32*)(header->Signature), &dummy))
591{
592#if DEBUG_ACPI
593printf("Warning: A ");
594print_nameseg(*(U32*) (header->Signature));
595printf(" Aml file is already loaded and registred, file skipped !!\n");
596#endif
597free(tableAddr);
598return (void*)0ul;
599}
600}
601else
602{
603if (get_number_of_tables_in_list(new_table_list, NAMESEG("SSDT")) >= MAX_SSDT_TABLE)
604{
605DBG("Warning: Max number of SSDT aml files reached, file skipped !!\n");
606free(tableAddr);
607return (void*)0ul;
608}
609}
610
611
612if (checkOem == true)
613{
614if (header->OemRevision == Model32)
615{
616goto continue_loading;
617}
618
619if (header->OemRevision == uuid32)
620{
621goto continue_loading;
622}
623
624DBG("Bad signature aka Oem Revision (0x%08lx) for Aml file (%s), file skipped !!\n", header->OemRevision, acpi_file);
625DBG("uuid32 (0x%08lx) , model32 (0x%08lx)\n", uuid32, Model32);
626
627free(tableAddr);
628return (void*)0ul;
629}
630
631 continue_loading:
632
633if (GetChecksum(header, header->Length) == 0)
634{
635DBG("Found valid AML file : %s ", filename);
636verbose("[ %s ] read and stored at: %x", acpi_file, tableAddr);
637printf("\n");
638return tableAddr;
639}
640else
641{
642printf("Warning : Incorrect cheksum for the file : %s,", acpi_file);
643printf(" this file will be dropped.\n");
644free(tableAddr);
645return (void*)0ul;
646}
647}
648else
649{
650printf("Couldn't allocate memory for table %s\n", acpi_file);
651close (fd);
652}
653
654return (void *)0ul ;
655}
656
657static U32 pmbase;
658static short cpuNamespace;
659PROCESSOR_NUMBER_TO_NAMESEG cpu_map[CPU_MAP_LIMIT];
660unsigned int cpu_map_count;
661int cpu_map_error;
662
663#if DEBUG_ACPI
664static void print_nameseg(U32 i)
665{
666 printf("%c%c%c%c",
667 (int)(i & 0x000000ff),
668 (int)((i & 0x0000ff00) >> 8),
669 (int)((i & 0x00ff0000) >> 16),
670 (int)(i >> 24));
671}
672#endif
673
674static int generate_cpu_map_from_acpi(ACPI_TABLE_DSDT * DsdtPointer)
675{
676 PROCESSOR_NUMBER_TO_NAMESEG *map = cpu_map;
677 U32 processor_namespace = 0;
678 U32 cpu;
679 U8 *current, *end;
680 ACPI_TABLE_HEADER *header;
681 struct acpi_namespace ns;
682
683if ((cpu_map_error == 1) || (DsdtPointer == (void*)0ul))
684return 1;
685else if (cpu_map_count > 0)
686return 0;
687
688 DBG("Attempting to autodetect CPU map from ACPI DSDT; wish me luck\n");
689
690 current = (U8 *) DsdtPointer;
691 current = decodeTableHeader(current, &header);
692 end = current - sizeof(*header) + header->Length;
693 ns.depth = 0;
694 acpi_processor_count = 0;
695//DBG("* DSDT debug start\n");
696 parse_acpi_termlist(&ns, current, end);
697//DBG("* DSDT debug end\n");
698
699 if (acpi_processor_count > CPU_MAP_LIMIT)
700{
701verbose("Too many processors: found %u processors\n", acpi_processor_count);
702 return (cpu_map_error = 1);
703}
704 if (acpi_processor_count == 0)
705{
706verbose( "Found no processors in ACPI\n");
707 return (cpu_map_error = 1);
708}
709 for (cpu = 0; cpu < acpi_processor_count; cpu++)
710{
711 U32 nameseg;
712 if (acpi_processors[cpu].pmbase)
713{
714 U32 cpu_pmbase = acpi_processors[cpu].pmbase - 0x10;
715 if (pmbase && cpu_pmbase != pmbase)
716{
717verbose("Found inconsistent pmbase addresses in ACPI: 0x%x and 0x%x\n", pmbase, cpu_pmbase);
718return (cpu_map_error = 1);
719}
720 pmbase = cpu_pmbase;
721 }
722 if (acpi_processors[cpu].ns.depth > MAX_SUPPORTED_CPU_NAMESEGS + 1)
723{
724verbose("Processor path too deep: depth %u\n", acpi_processors[cpu].ns.depth);
725return (cpu_map_error = 1);
726}
727 if (processor_namespace && acpi_processors[cpu].ns.nameseg[0] != processor_namespace)
728{
729verbose("Processor namespaces inconsistent\n");
730return (cpu_map_error = 1);
731}
732 processor_namespace = acpi_processors[cpu].ns.nameseg[0];
733 map->acpi_processor_number = acpi_processors[cpu].id;
734 map->seg_count = acpi_processors[cpu].ns.depth - 1;
735 for (nameseg = 0; nameseg < map->seg_count; nameseg++)
736 map->nameseg[nameseg] = acpi_processors[cpu].ns.nameseg[nameseg + 1];
737 map++;
738 }
739 if (!pmbase)
740{
741verbose("No pmbase found in ACPI\n");
742return (cpu_map_error = 1);
743}
744 if (processor_namespace == NAMESEG("_PR_"))
745 cpuNamespace = CPU_NAMESPACE_PR;
746 else if (processor_namespace == NAMESEG("_SB_"))
747 cpuNamespace = CPU_NAMESPACE_SB;
748 else
749{
750 verbose("Found processors in invalid namespace; not _PR_ or _SB_\n");
751return (cpu_map_error = 1);
752}
753 cpu_map_count = map - cpu_map;
754
755#if DEBUG_ACPI
756verbose("Found %d processors in ACPI, pmbase : 0x%x, cpu_map_count : %d, namespace : ",acpi_processor_count, pmbase, cpu_map_count );
757print_nameseg(processor_namespace);
758verbose("\n");
759 U32 i;
760 verbose("Found processors name : \n" );
761 for ( i = 0; i<cpu_map_count; i++)
762{
763U32 nseg = *(U32*)cpu_map[i].nameseg;
764 print_nameseg(nseg);
765verbose(" ");
766 }
767 verbose("\n");
768#endif
769
770// TODO: Save the cpu map into the device tree
771 return (cpu_map_error = 0);
772}
773
774static bool is_sandybridge(void)
775{
776 return Platform.CPU.Model == CPU_MODEL_SANDYBRIDGE;
777}
778
779static bool is_jaketown(void)
780{
781 return Platform.CPU.Model == CPU_MODEL_JAKETOWN;
782}
783
784static U32 get_bclk(void)
785{
786return (is_jaketown() || is_sandybridge()) ? 100 : 133;
787}
788/*
789 //-----------------------------------------------------------------------------
790 static U32 computePstateRatio(const U32 max, const U32 min, const U32 turboEnabled, const U32 numStates, const U32 pstate)
791 {
792 U32 ratiorange = max-min;
793 U32 numGaps = numStates-1-turboEnabled;
794 U32 adjPstate = pstate-turboEnabled;
795 return (pstate == 0) ? (max + turboEnabled) :
796 (ratiorange == 0) ? max :
797 max-(((adjPstate*ratiorange)+(numGaps/2))/numGaps);
798 }
799 //-----------------------------------------------------------------------------
800 static U32 computeNumPstates(const U32 max, const U32 min, const U32 turboEnabled, const U32 pssLimit)
801 {
802 U32 ratiorange, maxStates, numStates;
803
804 ratiorange = max - min + 1;
805 maxStates = ratiorange + (turboEnabled ? 1 : 0);
806 numStates = (pssLimit < maxStates) ? pssLimit : maxStates;
807 return (numStates < 2) ? 0 : numStates;
808 }
809 */
810#if BUILD_ACPI_TSS || pstate_power_support
811static U64 divU64byU64(U64 n, U64 d, U64 * rem)
812{
813 U32 i;
814 U64 q = n;
815 U64 r = 0;
816
817 for (i = 0; i < 64; i++) {
818 r <<= 1;
819 r |= (q & (1ULL << 63)) >> 63;
820 q <<= 1;
821 if (r >= d) {
822 r -= d;
823 q |= 1;
824 }
825 }
826 if (rem)
827 *rem = r;
828 return q;
829}
830
831static U32 compute_tdp(CPU_DETAILS * cpu)
832{
833 {
834 if (is_jaketown() || is_sandybridge())
835 {
836 U64 power_limit_1 = cpu->package_power_limit & ((1ULL << 15) - 1);
837 U64 power_unit = cpu->package_power_sku_unit & ((1ULL << 4) - 1);
838 U64 tdp = divU64byU64(power_limit_1, 1 << power_unit, NULL);
839 return (U32)tdp;
840 }
841 else
842 {
843 // tdp = (TURBO_POWER_CURRENT_LIMIT MSR 1ACh bit [14:0] / 8) Watts
844 return cpu->tdp_limit / 8;
845 }
846 }
847return (0);
848}
849#endif // BUILD_ACPI_TSS || pstate_power_support
850
851#if pstate_power_support
852static U64 mulU64byU64(U64 a, U64 b, U64 * high)
853{
854 U64 b_high = 0;
855 U64 r_high = 0, r_low = 0;
856 U64 bit;
857
858 for (bit = 1; bit; bit <<= 1) {
859 if (a & bit) {
860 if (r_low + b < r_low)
861 r_high++;
862 r_low += b;
863 r_high += b_high;
864 }
865 b_high <<= 1;
866 b_high |= (b & (1ULL << 63)) >> 63;
867 b <<= 1;
868 }
869
870 if (high)
871 *high = r_high;
872 return r_low;
873}
874
875static U32 compute_pstate_power(CPU_DETAILS * cpu, U32 ratio, U32 TDP)
876{
877if (is_jaketown() || is_sandybridge())
878{
879U32 P1_Ratio = cpu->max_ratio_as_mfg;
880U64 M, pstate_power;
881
882// M = ((1.1 - ((P1_ratio - ratio) * 0.00625)) / 1.1) ^2
883// To prevent loss of precision compute M * 10^5 (preserves 5 decimal places)
884M = (P1_Ratio - ratio) * 625;
885M = (110000 - M);
886M = divU64byU64(M, 11, NULL);
887M = divU64byU64(mulU64byU64(M, M, NULL), 1000, NULL);
888
889// pstate_power = ((ratio/p1_ratio) * M * TDP)
890// Divide the final answer by 10^5 to remove the precision factor
891pstate_power = mulU64byU64(ratio, M, NULL);
892pstate_power = mulU64byU64(pstate_power, TDP, NULL);
893pstate_power = divU64byU64(pstate_power, P1_Ratio, NULL);
894pstate_power = divU64byU64(pstate_power, 100000, NULL);
895return (U32)pstate_power; // in Watts
896}
897else
898{
899// pstate_power[ratio] = (ratio/P1_ratio)^3 * Core_TDP + Uncore_TDP
900
901// Core_TDP = (TURBO_POWER_CURRENT_LIMIT MSR 1ACh bit [30:16] / 8) Watts
902U32 Core_TDP = cpu->tdc_limit / 8;
903
904// Uncore_TDP = TDP - Core_TDP
905U32 Uncore_TDP = TDP - Core_TDP;
906
907// max_ratio_as_mfg = P1_Ratio derived from Brand String returned by CPUID instruction
908U32 P1_Ratio = cpu->max_ratio_as_mfg;
909
910#define PRECISION_FACTOR (U32) 30
911#define PRECISION_FACTOR_CUBED (U32) (PRECISION_FACTOR * PRECISION_FACTOR * PRECISION_FACTOR)
912
913U32 ratio_factor = (ratio * PRECISION_FACTOR)/P1_Ratio;
914return ((ratio_factor * ratio_factor * ratio_factor * Core_TDP) / PRECISION_FACTOR_CUBED) + Uncore_TDP;
915}
916 return (0);
917}
918#endif // pstate_power_support
919
920static U32 encode_pstate(U32 ratio)
921{
922if (is_jaketown() || is_sandybridge())
923return ratio << 8;
924return ratio;
925}
926
927//-----------------------------------------------------------------------------
928static void GetMaxRatio(U32 * max_non_turbo_ratio)
929{
930U32 index;
931U32 max_ratio=0;
932U32 frequency=0;
933 U32 multiplier = 0;
934 char*BrandString;
935// Verify CPUID brand string function is supported
936if (Platform.CPU.CPUID[CPUID_80][0] < 80000004)
937{
938*max_non_turbo_ratio = max_ratio;
939return;
940}
941BrandString = (char *)Platform.CPU.BrandString;
942 // -2 to prevent buffer overrun because looking for y in yHz, so z is +2 from y
943 for (index=0; index<48-2; index++) {
944 // format is either “x.xxyHz” or “xxxxyHz”, where y=M,G,T and x is digits
945 // Search brand string for “yHz” where y is M, G, or T
946 // Set multiplier so frequency is in MHz
947 if ( BrandString[index+1] == 'H' && BrandString[index+2] == 'z')
948 {
949 if (BrandString[index] == 'M')
950 multiplier = 1;
951 else if (BrandString[index] == 'G')
952 multiplier = 1000;
953 else if (BrandString[index] == 'T')
954 multiplier = 1000000;
955 }
956 if (multiplier > 0 && index >= 4 /* who can i call that, buffer underflow :-) ??*/)
957 {
958 // Copy 7 characters (length of “x.xxyHz”)
959 // index is at position of y in “x.xxyHz”
960
961 // Compute frequency (in MHz) from brand string
962 if (BrandString[index-3] == '.')
963 { // If format is “x.xx”
964 if (isdigit(BrandString[index-4]) && isdigit(BrandString[index-2]) &&
965 isdigit(BrandString[index-1]))
966 {
967 frequency = (U32)(BrandString[index-4] - '0') * multiplier;
968 frequency += (U32)(BrandString[index-2] - '0') * (multiplier / 10);
969 frequency += (U32)(BrandString[index-1] - '0') * (multiplier / 100);
970 }
971 }
972 else
973 { // If format is xxxx
974 if (isdigit(BrandString[index-4]) && isdigit(BrandString[index-3]) &&
975 isdigit(BrandString[index-2]) && isdigit(BrandString[index-1]))
976 {
977 frequency = (U32)(BrandString[index-4] - '0') * 1000;
978 frequency += (U32)(BrandString[index-3] - '0') * 100;
979 frequency += (U32)(BrandString[index-2] - '0') * 10;
980 frequency += (U32)(BrandString[index-1] - '0');
981 frequency *= multiplier;
982 }
983
984 }
985
986 max_ratio = frequency / get_bclk();
987 break;
988 }
989 }
990
991// Return non-zero Max Non-Turbo Ratio obtained from CPUID brand string
992// or return 0 indicating Max Non-Turbo Ratio not available
993*max_non_turbo_ratio = max_ratio;
994}
995
996//-----------------------------------------------------------------------------
997static void collect_cpu_info(CPU_DETAILS * cpu)
998{
999boolean_tdynamic_acceleration = 0;
1000U32sub_Cstates = 0;
1001U32 extensions = 0;
1002boolean_tinvariant_APIC_timer = 0;
1003boolean_tfine_grain_clock_mod = 0;
1004
1005#if BUILD_ACPI_TSS || pstate_power_support
1006if (Platform.CPU.CPUID[CPUID_0][0] >= 0x5) {
1007/*
1008 * Extract the Monitor/Mwait Leaf info:
1009 */
1010 sub_Cstates = Platform.CPU.CPUID[CPUID_5][3];
1011 extensions = Platform.CPU.CPUID[CPUID_5][2];
1012}
1013
1014if (Platform.CPU.CPUID[CPUID_0][0] >= 6) {
1015dynamic_acceleration = bitfield(Platform.CPU.CPUID[CPUID_6][0], 1, 1); // "Dynamic Acceleration Technology (Turbo Mode)"
1016invariant_APIC_timer = bitfield(Platform.CPU.CPUID[CPUID_6][0], 2, 2); // "Invariant APIC Timer"
1017 fine_grain_clock_mod = bitfield(Platform.CPU.CPUID[CPUID_6][0], 4, 4);
1018}
1019 cpu->turbo_available = (U32)dynamic_acceleration;
1020
1021{
1022U32 temp32 = 0;
1023U64 temp64= 0;
1024int tdp;
1025if (getIntForKey("TDP", &tdp, &bootInfo->chameleonConfig))
1026{
1027temp32 = (U32) (tdp*8) ;
1028
1029int tdc;
1030if (getIntForKey("TDC", &tdc, &bootInfo->chameleonConfig))
1031{
1032temp32 = (U32) (temp32) | tdc<<16 ;
1033
1034}
1035else if (tdp)
1036{
1037temp32 = (U32) (temp32) | ((tdp)*8)<<16 ;
1038}
1039
1040}
1041else if (!is_sandybridge() && !is_jaketown())
1042{
1043if (turbo_enabled && cpu->turbo_available)
1044{
1045temp64 = rdmsr64(MSR_TURBO_POWER_CURRENT_LIMIT);
1046temp32 = (U32)temp64;
1047}
1048else
1049{
1050// Unfortunately, Intel don't provide a better method for non turbo processors
1051// and it will give a TDP of 95w (for ex. mine is 65w) , to fix this issue,
1052// you can set this value by simply adding the option TDP = XX (XX is an integer)
1053// in your boot.plist
1054temp32 = (U32)0x02a802f8;
1055}
1056
1057}
1058if (temp32) {
1059cpu->tdp_limit = ( temp32 & 0x7fff );
1060cpu->tdc_limit = ( (temp32 >> 16) & 0x7fff );
1061}
1062}
1063
1064#endif
1065
1066switch (Platform.CPU.Family)
1067{
1068case 0x06:
1069{
1070switch (Platform.CPU.Model)
1071{
1072case CPU_MODEL_DOTHAN:
1073case CPU_MODEL_YONAH: // Yonah
1074case CPU_MODEL_MEROM: // Merom
1075case CPU_MODEL_PENRYN: // Penryn
1076case CPU_MODEL_ATOM: // Intel Atom (45nm)
1077{
1078
1079cpu->core_c1_supported = ((sub_Cstates >> 4) & 0xf) ? 1 : 0;
1080cpu->core_c4_supported = ((sub_Cstates >> 16) & 0xf) ? 1 : 0;
1081
1082if (Platform.CPU.Model == CPU_MODEL_ATOM)
1083{
1084cpu->core_c2_supported = cpu->core_c3_supported = ((sub_Cstates >> 8) & 0xf) ? 1 : 0;
1085cpu->core_c6_supported = ((sub_Cstates >> 12) & 0xf) ? 1 : 0;
1086
1087}
1088else
1089{
1090cpu->core_c3_supported = ((sub_Cstates >> 12) & 0xf) ? 1 : 0;
1091cpu->core_c2_supported = ((sub_Cstates >> 8) & 0xf) ? 1 : 0;
1092cpu->core_c6_supported = 0;
1093
1094}
1095
1096cpu->core_c7_supported = 0;
1097
1098#if BETA
1099GetMaxRatio(&cpu->max_ratio_as_mfg);
1100U64 msr = rdmsr64(MSR_IA32_PERF_STATUS);
1101U16 idlo = (msr >> 48) & 0xffff;
1102U16 idhi = (msr >> 32) & 0xffff;
1103cpu->min_ratio = (U32) (idlo >> 8) & 0xff;
1104cpu->max_ratio_as_cfg = (U32) (idhi >> 8) & 0xff;
1105
1106#else
1107if (Platform.CPU.MaxCoef)
1108{
1109if (Platform.CPU.MaxDiv)
1110{
1111cpu->max_ratio_as_cfg = cpu->max_ratio_as_mfg = (U32) (Platform.CPU.MaxCoef * 10) + 5;
1112}
1113else
1114{
1115cpu->max_ratio_as_cfg = cpu->max_ratio_as_mfg = (U32) Platform.CPU.MaxCoef * 10;
1116}
1117}
1118#endif
1119
1120break;
1121}
1122case CPU_MODEL_FIELDS:
1123case CPU_MODEL_DALES:
1124case CPU_MODEL_DALES_32NM:
1125case CPU_MODEL_NEHALEM:
1126case CPU_MODEL_NEHALEM_EX:
1127case CPU_MODEL_WESTMERE:
1128case CPU_MODEL_WESTMERE_EX:
1129case CPU_MODEL_SANDYBRIDGE:
1130case CPU_MODEL_JAKETOWN:
1131{
1132
1133cpu->core_c1_supported = ((sub_Cstates >> 4) & 0xf) ? 1 : 0;
1134cpu->core_c3_supported = ((sub_Cstates >> 8) & 0xf) ? 1 : 0;
1135cpu->core_c6_supported = ((sub_Cstates >> 12) & 0xf) ? 1 : 0;
1136cpu->core_c7_supported = ((sub_Cstates >> 16) & 0xf) ? 1 : 0;
1137cpu->core_c2_supported = 0;
1138cpu->core_c4_supported = 0;
1139
1140GetMaxRatio(&cpu->max_ratio_as_mfg);
1141 U64 platform_info = rdmsr64(MSR_PLATFORM_INFO);
1142 cpu->max_ratio_as_cfg = (U32) ((U32)platform_info >> 8) & 0xff;
1143cpu->min_ratio = (U32) ((platform_info >> 40) & 0xff);
1144
1145 cpu->tdc_tdp_limits_for_turbo_flag = (platform_info & (1ULL << 29)) ? 1 : 0;
1146cpu->ratio_limits_for_turbo_flag = (platform_info & (1ULL << 28)) ? 1 : 0;
1147cpu->xe_available = cpu->tdc_tdp_limits_for_turbo_flag | cpu->ratio_limits_for_turbo_flag;
1148
1149
1150
1151if (is_sandybridge() || is_jaketown())
1152{
1153cpu->package_power_limit = rdmsr64(MSR_PKG_RAPL_POWER_LIMIT);
1154cpu->package_power_sku_unit = rdmsr64(MSR_RAPL_POWER_UNIT);
1155}
1156break;
1157}
1158default:
1159verbose ("Unsupported CPU\n");
1160return /*(0)*/;
1161break;
1162}
1163}
1164default:
1165break;
1166}
1167
1168cpu->mwait_supported = (extensions & (1UL << 0)) ? 1 : 0;
1169
1170 cpu->invariant_apic_timer_flag = (U32)invariant_APIC_timer;
1171
1172#if DEBUG_ACPI
1173printf("CPU INFO : \n");
1174#if BETA
1175printf("min_ratio : %d\n", cpu->min_ratio);
1176#endif
1177printf("max_ratio_as_cfg : %d\n", cpu->max_ratio_as_cfg);
1178printf("max_ratio_as_mfg : %d\n", cpu->max_ratio_as_mfg);
1179
1180printf("turbo_available : %d\n",cpu->turbo_available);
1181
1182printf("core_c1_supported : %d\n",cpu->core_c1_supported);
1183printf("core_c2_supported : %d\n",cpu->core_c1_supported);
1184printf("core_c3_supported : %d\n",cpu->core_c3_supported);
1185printf("core_c6_supported : %d\n",cpu->core_c6_supported);
1186printf("core_c7_supported : %d\n",cpu->core_c7_supported);
1187printf("mwait_supported : %d\n",cpu->mwait_supported);
1188
1189#if BUILD_ACPI_TSS || pstate_power_support
1190if (is_sandybridge() || is_jaketown())
1191{
1192
1193printf("package_power_limit : %d\n",cpu->package_power_limit);
1194printf("package_power_sku_unit : %d\n",cpu->package_power_sku_unit);
1195
1196}
1197#endif
1198
1199DBG("invariant_apic_timer_flag : %d\n",cpu->invariant_apic_timer_flag);
1200
1201
1202#endif
1203}
1204
1205#if BETA
1206//-----------------------------------------------------------------------------
1207static U32 BuildPstateInfo(CPU_DETAILS * cpu)
1208{
1209// Build P-state table info based on verified options
1210
1211// Compute the number of p-states based on the ratio range
1212cpu->pkg_pstates.num_pstates = computeNumPstates(cpu->max_ratio_as_cfg, cpu->min_ratio, cpu->turbo_available, MAX_PSTATES);
1213
1214if (!cpu->pkg_pstates.num_pstates)
1215{
1216return (0);
1217}
1218
1219// Compute pstate data
1220{
1221U32 TDP = compute_tdp(cpu);
1222
1223U32 index;
1224for (index=0; index < cpu->pkg_pstates.num_pstates; index ++)
1225{
1226PSTATE * pstate = &cpu->pkg_pstates.pstate[index];
1227
1228// Set ratio
1229pstate->ratio = computePstateRatio(cpu->max_ratio_as_cfg, cpu->min_ratio, cpu->turbo_available, cpu->pkg_pstates.num_pstates, index);
1230
1231// Compute frequency based on ratio
1232if ((index != 0) || (cpu->turbo_available == 0))
1233pstate->frequency = pstate->ratio * get_bclk();
1234else
1235pstate->frequency = ((pstate->ratio - 1) * get_bclk()) + 1;
1236
1237// Compute power based on ratio and other data
1238if (pstate->ratio >= cpu->max_ratio_as_mfg)
1239// Use max power in mW
1240pstate->power = TDP * 1000;
1241else
1242{
1243pstate->power = compute_pstate_power(cpu, pstate->ratio, TDP);
1244
1245// Convert to mW
1246pstate->power*= 1000;
1247}
1248}
1249}
1250
1251return (1);
1252}
1253#else
1254/*
1255 //-----------------------------------------------------------------------------
1256 static U32 BuildCoreIPstateInfo(CPU_DETAILS * cpu)
1257 {
1258 // Build P-state table info based on verified options
1259
1260 // Compute the number of p-states based on the ratio range
1261 cpu->pkg_pstates.num_pstates = computeNumPstates(cpu->max_ratio_as_cfg, cpu->min_ratio, cpu->turbo_available, MAX_PSTATES);
1262
1263 if (!cpu->pkg_pstates.num_pstates)
1264 {
1265 return (0);
1266 }
1267
1268 // Compute pstate data
1269 {
1270 #ifdef pstate_power_support
1271 U32 TDP = compute_tdp(cpu);
1272 #endif
1273
1274 U32 index;
1275 for (index=0; index < cpu->pkg_pstates.num_pstates; index ++)
1276 {
1277 PSTATE * pstate = &cpu->pkg_pstates.pstate[index];
1278
1279 // Set ratio
1280 pstate->ratio = computePstateRatio(cpu->max_ratio_as_cfg, cpu->min_ratio, cpu->turbo_available, cpu->pkg_pstates.num_pstates, index);
1281
1282 // Compute frequency based on ratio
1283 if ((index != 0) || (cpu->turbo_available == 0))
1284 pstate->frequency = pstate->ratio * get_bclk();
1285 else
1286 pstate->frequency = ((pstate->ratio - 1) * get_bclk()) + 1;
1287
1288 #ifdef pstate_power_support
1289 // Compute power based on ratio and other data
1290 if (pstate->ratio >= cpu->max_ratio_as_mfg)
1291 // Use max power in mW
1292 pstate->power = TDP * 1000;
1293 else
1294 {
1295 pstate->power = compute_pstate_power(cpu, pstate->ratio, TDP);
1296
1297 // Convert to mW
1298 pstate->power*= 1000;
1299 }
1300 #else
1301 pstate->power = 0;
1302 #endif
1303 }
1304 }
1305
1306 return (1);
1307 }
1308 */
1309//-----------------------------------------------------------------------------
1310static U32 BuildPstateInfo(CPU_DETAILS * cpu)
1311{
1312
1313struct p_state p_states[32];
1314U8 p_states_count = 0;
1315
1316 if (!cpu)
1317 {
1318 return (0);
1319 }
1320
1321{
1322#if UNUSED
1323struct p_state initial;
1324#endif
1325struct p_state maximum, minimum;
1326// Retrieving P-States, ported from code by superhai (c)
1327switch (Platform.CPU.Family)
1328{
1329case 0x06:
1330{
1331switch (Platform.CPU.Model)
1332{
1333case CPU_MODEL_DOTHAN:
1334case CPU_MODEL_YONAH: // Yonah
1335case CPU_MODEL_MEROM: // Merom
1336case CPU_MODEL_PENRYN: // Penryn
1337case CPU_MODEL_ATOM: // Intel Atom (45nm)
1338{
1339bool cpu_dynamic_fsb = false;
1340
1341if (rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 27))
1342{
1343wrmsr64(MSR_IA32_EXT_CONFIG, (rdmsr64(MSR_IA32_EXT_CONFIG) | (1 << 28)));
1344delay(1);
1345cpu_dynamic_fsb = rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 28);
1346}
1347
1348bool cpu_noninteger_bus_ratio = (rdmsr64(MSR_IA32_PERF_STATUS) & (1ULL << 46));
1349#if UNUSED
1350//initial.Control = rdmsr64(MSR_IA32_PERF_STATUS);
1351#endif
1352maximum.Control = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 32) & 0x1F3F) | (0x4000 * cpu_noninteger_bus_ratio);
1353maximum.CID = ((maximum.FID & 0x1F) << 1) | cpu_noninteger_bus_ratio;
1354
1355minimum.FID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 24) & 0x1F) | (0x80 * cpu_dynamic_fsb);
1356minimum.VID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 48) & 0x3F);
1357
1358if (minimum.FID == 0)
1359{
1360U64 msr;
1361U8 i;
1362// Probe for lowest fid
1363for (i = maximum.FID; i >= 0x6; i--)
1364{
1365msr = rdmsr64(MSR_IA32_PERF_CONTROL);
1366wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (i << 8) | minimum.VID);
1367intel_waitforsts();
1368minimum.FID = (rdmsr64(MSR_IA32_PERF_STATUS) >> 8) & 0x1F;
1369delay(1);
1370}
1371
1372msr = rdmsr64(MSR_IA32_PERF_CONTROL);
1373wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
1374intel_waitforsts();
1375}
1376
1377if (minimum.VID == maximum.VID)
1378{
1379U64 msr;
1380U8 i;
1381// Probe for lowest vid
1382for (i = maximum.VID; i > 0xA; i--)
1383{
1384msr = rdmsr64(MSR_IA32_PERF_CONTROL);
1385wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (minimum.FID << 8) | i);
1386intel_waitforsts();
1387minimum.VID = rdmsr64(MSR_IA32_PERF_STATUS) & 0x3F;
1388delay(1);
1389}
1390
1391msr = rdmsr64(MSR_IA32_PERF_CONTROL);
1392wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
1393intel_waitforsts();
1394}
1395
1396minimum.CID = ((minimum.FID & 0x1F) << 1) >> cpu_dynamic_fsb;
1397
1398// Sanity check
1399if (maximum.CID < minimum.CID)
1400{
1401DBG("Insane FID values!");
1402p_states_count = 0;
1403}
1404else
1405{
1406// Finalize P-States
1407// Find how many P-States machine supports
1408p_states_count = maximum.CID - minimum.CID + 1;
1409
1410if (p_states_count > MAX_PSTATES) // was 32
1411p_states_count = MAX_PSTATES; // was 32
1412
1413U8 vidstep;
1414U8 i = 0, u, invalid = 0;
1415
1416vidstep = ((maximum.VID << 2) - (minimum.VID << 2)) / (p_states_count - 1);
1417
1418 U32 fsb = (U32)divU64byU64(Platform.CPU.FSBFrequency , 1000000 , NULL);
1419
1420for (u = 0; u < p_states_count; u++)
1421{
1422i = u - invalid;
1423
1424p_states[i].CID = maximum.CID - u;
1425p_states[i].FID = (p_states[i].CID >> 1);
1426
1427if (p_states[i].FID < 0x6)
1428{
1429if (cpu_dynamic_fsb)
1430p_states[i].FID = (p_states[i].FID << 1) | 0x80;
1431}
1432else if (cpu_noninteger_bus_ratio)
1433{
1434p_states[i].FID = p_states[i].FID | (0x40 * (p_states[i].CID & 0x1));
1435}
1436
1437if (i && p_states[i].FID == p_states[i-1].FID)
1438invalid++;
1439
1440p_states[i].VID = ((maximum.VID << 2) - (vidstep * u)) >> 2;
1441
1442U32 multiplier = p_states[i].FID & 0x1f;// = 0x08
1443bool half = p_states[i].FID & 0x40;// = 0x01
1444bool dfsb = p_states[i].FID & 0x80;// = 0x00
1445//U32 fsb = (U32)get_env(envFSBFreq) / 1000000; // = 400
1446U32 halffsb = (fsb + 1) >> 1;// = 200
1447U32 frequency = (multiplier * fsb);// = 3200
1448
1449p_states[i].Frequency = (frequency + (half * halffsb)) >> dfsb;// = 3200 + 200 = 3400
1450}
1451
1452p_states_count -= invalid;
1453}
1454break;
1455}
1456case CPU_MODEL_FIELDS:
1457case CPU_MODEL_DALES:
1458case CPU_MODEL_DALES_32NM:
1459case CPU_MODEL_NEHALEM:
1460case CPU_MODEL_NEHALEM_EX:
1461case CPU_MODEL_WESTMERE:
1462case CPU_MODEL_WESTMERE_EX:
1463case CPU_MODEL_SANDYBRIDGE:
1464case CPU_MODEL_JAKETOWN:
1465{
1466
1467maximum.Control = rdmsr64(MSR_IA32_PERF_STATUS) & 0xff; // Seems it always contains maximum multiplier value (with turbo, that's we need)...
1468minimum.Control = (rdmsr64(MSR_PLATFORM_INFO) >> 40) & 0xff;
1469
1470DBG("P-States: min 0x%x, max 0x%x\n", minimum.Control, maximum.Control);
1471
1472// Sanity check
1473if (maximum.Control < minimum.Control)
1474{
1475DBG("Insane control values!");
1476p_states_count = 0;
1477}
1478else
1479{
1480U8 i;
1481p_states_count = 0;
1482U32 fsb = (U32)divU64byU64(Platform.CPU.FSBFrequency , 1000000, NULL) ;
1483for (i = maximum.Control; i >= minimum.Control; i--)
1484{
1485p_states[p_states_count].Control = i;
1486p_states[p_states_count].CID = p_states[p_states_count].Control << 1;
1487p_states[p_states_count].Frequency = (U32)fsb * i;
1488p_states_count++;
1489if (p_states_count >= MAX_PSTATES) { // was 32
1490
1491if (p_states_count > MAX_PSTATES) // was 32
1492p_states_count = MAX_PSTATES; // was 32
1493
1494break;
1495}
1496}
1497}
1498
1499/*
1500 U32 sta = BuildCoreIPstateInfo(cpu);
1501 if (sta)
1502 {
1503 DBG("_PSS PGK generated successfully\n");
1504 return (1);
1505
1506 }
1507 else
1508 {
1509 verbose("CoreI _PSS Generation failed !!\n");
1510 return (0);
1511 }
1512 */
1513break;
1514}
1515default:
1516verbose ("Unsupported CPU: P-States will not be generated !!!\n");
1517return (0);
1518break;
1519}
1520}
1521default:
1522break;
1523}
1524}
1525
1526// Generating Pstate PKG
1527if (p_states_count > 0)
1528{
1529 U32 fsb = (U32)Platform.CPU.FSBFrequency;
1530U8 minPSratio = divU64byU64(p_states[p_states_count-1].Frequency , divU64byU64(fsb , 10000000 , NULL ) , NULL);
1531U8 maxPSratio = divU64byU64(p_states[0].Frequency , divU64byU64(fsb , 10000000 , NULL ) , NULL);
1532U8 cpu_ratio = 0;
1533
1534{
1535U8 cpu_div = (U8)Platform.CPU.CurrDiv;
1536U8 cpu_coef = (U8)Platform.CPU.CurrCoef;
1537
1538if (cpu_div)
1539cpu_ratio = (cpu_coef * 10) + 5;
1540else
1541cpu_ratio = cpu_coef * 10;
1542}
1543
1544
1545{
1546int user_max_ratio = 0;
1547getIntForKey(kMaxRatio, &user_max_ratio, &bootInfo->chameleonConfig);
1548if (user_max_ratio >= minPSratio && maxPSratio >= user_max_ratio)
1549{
1550
1551U8 maxcurrdiv = 0, maxcurrcoef = (int)divU64byU64(user_max_ratio , 10, NULL);
1552
1553U8 maxdiv = user_max_ratio - (maxcurrcoef * 10);
1554if (maxdiv > 0)
1555maxcurrdiv = 1;
1556
1557if (maxcurrdiv)
1558cpu_ratio = (maxcurrcoef * 10) + 5;
1559else
1560cpu_ratio = maxcurrcoef * 10;
1561}
1562}
1563
1564{
1565int user_min_ratio = 0;
1566getIntForKey(kMinRatio, &user_min_ratio, &bootInfo->chameleonConfig);
1567if (user_min_ratio >= minPSratio && cpu_ratio >= user_min_ratio)
1568{
1569
1570U8 mincurrdiv = 0, mincurrcoef = (int)divU64byU64(user_min_ratio , 10 , NULL);
1571
1572U8 mindiv = user_min_ratio - (mincurrcoef * 10);
1573
1574if (mindiv > 0)
1575mincurrdiv = 1;
1576
1577if (mincurrdiv)
1578minPSratio = (mincurrcoef * 10) + 5;
1579else
1580minPSratio = mincurrcoef * 10;
1581
1582}
1583}
1584
1585
1586if (maxPSratio >= cpu_ratio && cpu_ratio >= minPSratio)maxPSratio = cpu_ratio;
1587
1588{
1589int base = 16;
1590U8 expert = 0; /* Default: 0 , mean mixed mode
1591 * expert mode : 1 , mean add only p-states found in boot.plist
1592 */
1593
1594 TagPtr PstateTag;
1595 U32 pstate_tag_count = 0;
1596
1597{
1598
1599
1600 if (bootInfo->chameleonConfig.dictionary)
1601 {
1602 PstateTag = XMLCastDict(XMLGetProperty(bootInfo->chameleonConfig.dictionary, (const char*)"P-States"));
1603 if (PstateTag) pstate_tag_count = XMLTagCount(PstateTag) ;
1604 }
1605
1606 if (!pstate_tag_count)
1607 if ((PstateTag = XMLCastDict(XMLGetProperty(bootInfo->chameleonConfig.dictionary, (const char*)"P-States")))) pstate_tag_count = XMLTagCount(PstateTag);
1608
1609
1610if ((pstate_tag_count > 0) && PstateTag)
1611{
1612char *tmpstr = XMLCastString(XMLGetProperty(PstateTag, (const char*)"Mode"));
1613
1614if (strcmp(tmpstr,"Expert") == 0)
1615{
1616p_states_count = pstate_tag_count - 1 ; // - 1 = - ("Mode" tag)
1617expert = 1;
1618}
1619
1620
1621if ((tmpstr = XMLCastString(XMLGetProperty(PstateTag, (const char*)"Base"))))
1622{
1623
1624if (expert) p_states_count--; // -= ("Base" tag)
1625
1626int mybase = strtol(tmpstr, NULL, 10);
1627
1628if (mybase == 8 || mybase == 10 || mybase == 16 )
1629base = mybase;
1630}
1631}
1632
1633}
1634
1635{
1636U32 dropPSS = 0, Pstatus = 0;
1637char MatchStat[5];
1638#ifdef pstate_power_support
1639U32 TDP = compute_tdp(cpu);
1640#endif
1641U32 i;
1642 U32 fsb = (U32)Platform.CPU.FSBFrequency;
1643for (i = 0; i < p_states_count; i++)
1644{
1645char *Lat1 = NULL, *clk = NULL, *Pw = NULL, *Lat2 = NULL, *Ctrl = NULL ;
1646
1647if ((pstate_tag_count > 0) && PstateTag)
1648{
1649sprintf(MatchStat, "%d",i);
1650TagPtr match_Status = XMLGetProperty(PstateTag, (const char*)MatchStat);
1651
1652if (match_Status && (XMLTagCount(match_Status) > 0))
1653{
1654
1655clk = XMLCastString(XMLGetProperty(match_Status, (const char*)"CoreFreq"));
1656Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power"));
1657Lat1 = XMLCastString(XMLGetProperty(match_Status, (const char*)"Transition Latency"));
1658Lat2 = XMLCastString(XMLGetProperty(match_Status, (const char*)"Bus Master Latency"));
1659Ctrl = XMLCastString(XMLGetProperty(match_Status, (const char*)"Control"));
1660
1661
1662} else if (expert)
1663continue;
1664}
1665
1666unsigned long Frequency = 0x00000000;
1667
1668if (!expert || !pstate_tag_count) Frequency = p_states[i].Frequency;
1669
1670if (clk)
1671Frequency = strtoul((const char *)clk, NULL,base);
1672
1673if (!Frequency || Frequency > p_states[0].Frequency ) continue;
1674
1675U8 curr_ratio = (U8)divU64byU64(Frequency , divU64byU64(fsb , 10000000, NULL ), NULL);
1676
1677
1678 {
1679U8 fixed_ratio = (U8)divU64byU64(Frequency , divU64byU64(fsb , 1000000 , NULL ) , NULL) * 10;
1680U8 diff = curr_ratio - fixed_ratio ;
1681
1682if (diff)
1683{
1684if (diff < 5)
1685{
1686curr_ratio = fixed_ratio;
1687}
1688else
1689{
1690curr_ratio = fixed_ratio + 5;
1691}
1692}
1693
1694}
1695
1696if (curr_ratio > maxPSratio || minPSratio > curr_ratio)
1697goto dropPstate;
1698
1699{
1700PSTATE * pstate = &cpu->pkg_pstates.pstate[Pstatus];
1701
1702pstate->ratio = curr_ratio;
1703
1704pstate->frequency = Frequency; // CoreFreq (in MHz).
1705
1706U32 power = 0x00000000;
1707#ifdef pstate_power_support
1708// Compute power based on ratio and other data
1709if (pstate->ratio >= cpu->max_ratio_as_mfg)
1710// Use max power in mW
1711power = TDP * 1000;
1712else
1713{
1714power = compute_pstate_power(cpu, pstate->ratio, TDP);
1715
1716// Convert to mW
1717power*= 1000;
1718}
1719#endif
1720pstate->power = resolve_pss(power, Pw, base); // Power (in milliWatts)
1721pstate->translatency = resolve_pss(0x0000000A, Lat1, base); // Transition Latency (in microseconds).
1722pstate->bmlatency = resolve_pss(0x0000000A, Lat2, base); // Bus Master Latency (in microseconds).
1723
1724{
1725U32 Control = 0 /*encode_pstate(curr_ratio)*/ ;
1726if (!expert || !pstate_tag_count) Control = p_states[i].Control;
1727pstate->control = resolve_pss(Control, Ctrl, base); // Control
1728}
1729
1730pstate->status = Pstatus+1; // Status
1731
1732DBG("state :: frequency :%d power: %d translatency: %d bmlatency: %d control: %d status: %d ratio :%d :: registred !! \n",pstate->frequency,pstate->power,
1733 pstate->translatency,pstate->bmlatency,pstate->control,pstate->status,pstate->ratio );
1734}
1735
1736
1737Pstatus++;
1738continue;
1739
1740dropPstate:
1741DBG("state with cpu frequency :%d and ratio :%d will be dropped\n",p_states[i].Frequency,curr_ratio);
1742dropPSS++;
1743
1744
1745}
1746
1747if (Pstatus == 0)
1748{
1749verbose("No suitable P-states found, P-States will not be generated !!!\n");
1750return (0);
1751}
1752cpu->pkg_pstates.num_pstates = Pstatus;
1753}
1754}
1755}
1756else
1757{
1758verbose("ACPI CPUs not found: P-States will not be generated !!!\n");
1759return (0);
1760}
1761
1762DBG("_PSS PGK generated successfully\n");
1763return (1);
1764}
1765#endif // BETA
1766
1767//-----------------------------------------------------------------------------
1768static U32 BuildCstateInfo(CPU_DETAILS * cpu, U32 pmbase)
1769{
1770{
1771
1772TagPtr CstateTag;
1773 U32 entry_count = 0;
1774
1775 if (bootInfo->chameleonConfig.dictionary)
1776 {
1777 CstateTag = XMLCastDict(XMLGetProperty(bootInfo->chameleonConfig.dictionary, (const char*)"C-States"));
1778 }
1779
1780if (CstateTag)
1781{
1782int base = 16;
1783
1784entry_count = XMLTagCount(CstateTag);
1785
1786if (entry_count > 0)
1787{
1788 {
1789 char *tmpstr;
1790
1791 if ((tmpstr = XMLCastString(XMLGetProperty(CstateTag, (const char*)"Base"))))
1792 {
1793
1794 entry_count--; // -= ("Base" tag)
1795
1796 int mybase = strtol(tmpstr, NULL, 10);
1797
1798 if (mybase == 8 || mybase == 10 || mybase == 16 )
1799 base = mybase;
1800 }
1801 }
1802
1803cpu->pkg_io_cstates.num_cstates = 0;
1804cpu->pkg_mwait_cstates.num_cstates = 0;
1805U32 num_cstates = 0;
1806
1807{
1808U32 i;
1809char MatchStat[5];
1810
1811for (i = 0; i < 32 ; i++)
1812{
1813char *Lat = NULL, *Pw = NULL, *BWidth= NULL, *BOffset= NULL, *Address= NULL, *AccessSize= NULL, *index= NULL;
1814
1815sprintf(MatchStat, "C%d",i);
1816TagPtr match_Status = XMLGetProperty(CstateTag, (const char*)MatchStat);
1817if (match_Status)
1818{
1819Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power"));
1820Lat = XMLCastString(XMLGetProperty(match_Status, (const char*)"Latency"));
1821BWidth= XMLCastString(XMLGetProperty(match_Status, (const char*)"BitWidth"));
1822
1823BOffset = XMLCastString(XMLGetProperty(match_Status, (const char*)"BitOffset"));
1824Address = XMLCastString(XMLGetProperty(match_Status, (const char*)"Latency"));
1825AccessSize = XMLCastString(XMLGetProperty(match_Status, (const char*)"AccessSize"));
1826index = XMLCastString(XMLGetProperty(match_Status, (const char*)"index"));
1827
1828if (Pw && Lat && BWidth && BOffset && Address && AccessSize && index)
1829{
1830U32 bw= strtoul((const char *)BWidth, NULL,base);
1831U32 boff= strtoul((const char *)BOffset, NULL,base);
1832U32 acs= strtoul((const char *)AccessSize, NULL,base);
1833U32 addr= strtoul((const char *)Address, NULL,base);
1834U32 idx= strtoul((const char *)index, NULL,base);
1835U32 lat= strtoul((const char *)Lat, NULL,base);
1836U32 pw= strtoul((const char *)Pw, NULL,base);
1837
1838ACPI_GENERIC_ADDRESS mwait_gas = {GAS_TYPE_FFH,bw,boff,acs,addr};
1839ACPI_GENERIC_ADDRESS io_gas = {(i == 1) ? GAS_TYPE_FFH : GAS_TYPE_SYSTEM_IO,bw,boff,acs,addr};
1840
1841CSTATE mwait_cstate = {idx,lat,pw};
1842CSTATE io_cstate = {idx,lat,pw};
1843
1844{
1845cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate;
1846cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas;
1847cpu->pkg_mwait_cstates.num_cstates++;
1848}
1849
1850{
1851cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate;
1852cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas;
1853cpu->pkg_io_cstates.num_cstates++;
1854}
1855num_cstates++;
1856
1857if (num_cstates >= MAX_CSTATES)
1858{
1859break;
1860}
1861}
1862}
1863}
1864}
1865
1866if (num_cstates)
1867{
1868return (1);
1869}
1870}
1871}
1872}
1873
1874{
1875static const ACPI_GENERIC_ADDRESS mwait_gas[] = {
1876{GAS_TYPE_FFH,1,2,1,0x00}, // processor C1
1877{GAS_TYPE_FFH,1,2,1,0x10}, // processor C3 as ACPI C2
1878{GAS_TYPE_FFH,1,2,1,0x10}, // processor C3 as ACPI C3
1879{GAS_TYPE_FFH,1,2,1,0x10}, // processor C3 as ACPI C4
1880{GAS_TYPE_FFH,1,2,1,0x20}, // processor C6
1881{GAS_TYPE_FFH,1,2,1,0x30}, // processor C7
1882};
1883
1884static const ACPI_GENERIC_ADDRESS io_gas[] = {
1885{GAS_TYPE_FFH, 0,0,0,0x00}, // processor C1
1886{GAS_TYPE_SYSTEM_IO,8,0,0,0x14}, // processor C3 as ACPI C2 or processor C2
1887{GAS_TYPE_SYSTEM_IO,8,0,0,0x14}, // processor C3 as ACPI C3
1888{GAS_TYPE_SYSTEM_IO,8,0,0,0x15}, // processor C4 as ACPI C4
1889{GAS_TYPE_SYSTEM_IO,8,0,0,0x15}, // processor C6
1890{GAS_TYPE_SYSTEM_IO,8,0,0,0x16}, // processor C7
1891};
1892
1893static const CSTATE mwait_cstate [] = {
1894{1,0x01,0x3e8}, // processor C1
1895{2,0x40,0x1f4}, // processor C3 as ACPI C2 or processor C2
1896{3,0x40,0x1f4}, // processor C3 as ACPI C3
1897{4,0x40,0x1f4}, // processor C4
1898{6/*was 3*/,0x60,0x15e}, // processor C6
1899{7/*was 3*/,0x60,0x0c8}, // processor C7
1900};
1901
1902static const CSTATE io_cstate [] = {
1903{1,0x01,0x3e8}, // processor C1
1904{2,0x40,0x1f4}, // processor C3 as ACPI C2 or processor C2
1905{3,0x40,0x1f4}, // processor C3 as ACPI C3
1906{4,0x40,0x1f4}, // processor C4
1907{6/*was 3*/,0x60,0x15e}, // processor C6
1908{7/*was 3*/,0x60,0x0c8}, // processor C7
1909};
1910
1911static const U32 cstate_2_index [] = {0,0,0,1,2,3,4,5};
1912
1913// Build C-state table info based on verified options
1914
1915// Desired state for the processor core C3 state included in the _CST as an
1916// ACPI C2 state.
1917// 1= processor core C3 can be used as an ACPI C2 state
1918// 0= processor core C3 cannot be used as an ACPI C2 state
1919int c2_enabled = 0;
1920
1921// Desired state for the processor core C3 state included in the _CST
1922// 0= processor core C3 cannot be used as an ACPI C state
1923// 2= processor core C3 can be used as an ACPI C2 state
1924// 3= processor core C3 can be used as an ACPI C3 state
1925// 4= processor core C3 can be used as an ACPI C2 state
1926// if Invariant APIC Timer detected, else not used as ACPI C state
1927// 5= processor core C3 can be used as an ACPI C2 state
1928// if Invariant APIC Timer detected, else APIC C3 state
1929// 6= processor core C3 can be used as an ACPI C4 state
1930int c3_enabled = 3;
1931
1932// Desired state for the processor core C3 state included in the _CST as an
1933// ACPI C4 state.
1934// 1= processor core C3 can be used as an ACPI C4 state
1935// 0= processor core C3 cannot be used as an ACPI C4 state
1936int c4_enabled = 0;
1937
1938// Desired state for the processor core C6 state included in the _CST as an
1939// ACPI C3 state.
1940// 1= processor core C6 can be used as an ACPI C3 state
1941// 0= processor core C6 cannot be used as an ACPI C3 state
1942int c6_enabled = 0;
1943
1944// Desired state for the processor core C7 state included in the _CST as an
1945// ACPI C3 state.
1946// 1= processor core C7 can be used as an ACPI C7 state
1947// 0= processor core C7 cannot be used as an ACPI C7 state
1948int c7_enabled = 0;
1949
1950{
1951bool tmpval;
1952
1953
1954if (getBoolForKey(kEnableC2State, &tmpval, &bootInfo->chameleonConfig))
1955{
1956c2_enabled = tmpval;
1957}
1958
1959if (!getIntForKey("C3StateOption", &c3_enabled, &bootInfo->chameleonConfig))
1960{
1961c3_enabled = (getBoolForKey(kEnableC3State, &tmpval, &bootInfo->chameleonConfig)&&tmpval) ? 3 : 0;
1962}
1963if (c3_enabled == 6)
1964{
1965c4_enabled = 1;
1966}
1967else
1968{
1969c4_enabled = (getBoolForKey(kEnableC4State, &tmpval, &bootInfo->chameleonConfig)&&tmpval) ? 1 : 0;
1970}
1971c6_enabled = (getBoolForKey(kEnableC6State, &tmpval, &bootInfo->chameleonConfig)&&tmpval) ? 1 : 0;
1972c7_enabled = (getBoolForKey(kEnableC7State, &tmpval, &bootInfo->chameleonConfig)&&tmpval) ? 1 : 0;
1973}
1974
1975cpu->pkg_mwait_cstates.num_cstates = 0;
1976{
1977{
1978cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C1]];
1979cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C1]];
1980cpu->pkg_mwait_cstates.num_cstates++;
1981}
1982if (((cpu->core_c3_supported || cpu->core_c2_supported) && (c2_enabled)) && ((c3_enabled == 2) ||
1983 ((c3_enabled == 4) && cpu->invariant_apic_timer_flag)))
1984{
1985cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C3_ACPI_C2]];
1986cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C3_ACPI_C2]];
1987cpu->pkg_mwait_cstates.num_cstates++;
1988}
1989if (cpu->core_c4_supported && c4_enabled)
1990{
1991
1992cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C4]];
1993cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C4]];
1994cpu->pkg_mwait_cstates.num_cstates++;
1995
1996}
1997else
1998{
1999
2000if (cpu->core_c3_supported && ((c3_enabled == 3) ||
2001 ((c3_enabled == 4) && !cpu->invariant_apic_timer_flag)))
2002{
2003cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C3_ACPI_C3]];
2004cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C3_ACPI_C3]];
2005cpu->pkg_mwait_cstates.num_cstates++;
2006}
2007}
2008
2009
2010if (cpu->core_c6_supported && c6_enabled)
2011{
2012cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C6]];
2013cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C6]];
2014cpu->pkg_mwait_cstates.num_cstates++;
2015}
2016if (cpu->core_c7_supported && c7_enabled)
2017{
2018cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C7]];
2019cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C7]];
2020cpu->pkg_mwait_cstates.num_cstates++;
2021}
2022}
2023
2024cpu->pkg_io_cstates.num_cstates = 0;
2025{
2026{
2027cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C1]];
2028cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C1]];
2029cpu->pkg_io_cstates.num_cstates++;
2030}
2031if ((cpu->core_c3_supported || cpu->core_c2_supported) && (c2_enabled || (c3_enabled == 2) ||
2032 ((c3_enabled == 4) && cpu->invariant_apic_timer_flag)))
2033{
2034cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C3_ACPI_C2]];
2035cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C3_ACPI_C2]];
2036cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase;
2037cpu->pkg_io_cstates.num_cstates++;
2038}
2039if (cpu->core_c4_supported && c4_enabled)
2040{
2041
2042cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C4]];
2043cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C4]];
2044cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase;
2045cpu->pkg_io_cstates.num_cstates++;
2046
2047}
2048else
2049{
2050
2051if (cpu->core_c3_supported && ((c3_enabled == 3) ||
2052 ((c3_enabled == 4) && !cpu->invariant_apic_timer_flag)))
2053{
2054cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C3_ACPI_C3]];
2055cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C3_ACPI_C3]];
2056cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase;
2057cpu->pkg_io_cstates.num_cstates++;
2058}
2059}
2060
2061if (cpu->core_c6_supported && c6_enabled)
2062{
2063cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C6]];
2064cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C6]];
2065cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase;
2066cpu->pkg_io_cstates.num_cstates++;
2067}
2068if (cpu->core_c7_supported && c7_enabled)
2069{
2070cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C7]];
2071cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C7]];
2072cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase;
2073cpu->pkg_io_cstates.num_cstates++;
2074}
2075}
2076}
2077
2078return (1);
2079}
2080
2081#if BUILD_ACPI_TSS
2082//-----------------------------------------------------------------------------
2083static U32 BuildTstateInfo(CPU_DETAILS * cpu)
2084{
2085 // Coarse grained clock modulation is available if cpuid.6.eax[5] = 0
2086 // Max of 8 T-states using 12.5% increments
2087 static const TSTATE tstate_coarse_grain [] = {
2088 {100,0,0,0x00,0},
2089 { 88,0,0,0x1e,0},
2090 { 75,0,0,0x1c,0},
2091 { 63,0,0,0x1a,0},
2092 { 50,0,0,0x18,0},
2093 { 38,0,0,0x16,0},
2094 { 25,0,0,0x14,0},
2095 { 13,0,0,0x12,0},
2096 };
2097
2098 // Fine grained clock modulation is available if cpuid.6.eax[5] = 1
2099 // Max of 15 T-states using 6.25% increments
2100 static const TSTATE tstate_fine_grain [] = {
2101 {100,0,0,0x00,0},
2102 { 94,0,0,0x1f,0},
2103 { 88,0,0,0x1e,0},
2104 { 81,0,0,0x1d,0},
2105 { 75,0,0,0x1c,0},
2106 { 69,0,0,0x1b,0},
2107 { 63,0,0,0x1a,0},
2108 { 56,0,0,0x19,0},
2109 { 50,0,0,0x18,0},
2110 { 44,0,0,0x17,0},
2111 { 38,0,0,0x16,0},
2112 { 31,0,0,0x15,0},
2113 { 25,0,0,0x14,0},
2114 { 19,0,0,0x13,0},
2115 { 13,0,0,0x12,0},
2116 };
2117
2118 // Build T-state table info based on verified options
2119 U32 num_cpu;
2120 const TSTATE * tstate;
2121 U32 num_tstates;
2122
2123 for (num_cpu = 0; num_cpu < cpu_map_count; num_cpu ++)
2124 {
2125 // Check if fine or coarse grained clock modulation is available
2126 if (get_env(envFineGrainClockMod))
2127 {
2128 // Fine grain thermal throttling is available
2129 num_tstates = 15;
2130 tstate = tstate_fine_grain;
2131 }
2132 else
2133 {
2134 // Coarse grain thermal throttling is available
2135 num_tstates = 8;
2136 tstate = tstate_coarse_grain;
2137 }
2138
2139 cpu->pkg_tstates.num_tstates = num_tstates;
2140 {
2141 U32 index;
2142 for (index = 0; index < num_tstates; index++)
2143 {
2144 cpu->pkg_tstates.tstate[index] = tstate[index];
2145 cpu->pkg_tstates.tstate[index].power = 1000 * (compute_tdp(cpu) * (num_tstates - index)) / num_tstates;
2146 }
2147 }
2148
2149
2150 }
2151 return (1);
2152}
2153#endif // BUILD_ACPI_TSS
2154
2155//-----------------------------------------------------------------------------
2156U32 ProcessMadt(ACPI_TABLE_MADT * madt, MADT_INFO * madt_info, void * buffer, U32 bufferSize, U32 nb_cpu)
2157{
2158 void *current;
2159 void *currentOut;
2160 void *end;
2161 void * endOut;
2162
2163 U32 LOCAL_APIC_NMI_CNT = 0, LOCAL_SAPIC_CNT = 0, INT_SRC_CNT = 0, Length = 0;
2164
2165 // Quick sanity check for a valid MADT
2166 if (madt == 0ul || !nb_cpu)
2167 return (0);
2168
2169 // Confirm a valid MADT buffer was provided
2170 if (!buffer)
2171 {
2172 printf("Error: Invalid Buffer Address for MADT\n");
2173 return(0);
2174 }
2175
2176 // Confirm a valid MADT buffer length was provided
2177 if (!bufferSize)
2178 {
2179 printf("Error: Invalid Buffer Length for MADT\n");
2180 return(0);
2181 }
2182
2183 madt_info->lapic_count = 0;
2184
2185 memcpy(buffer, madt, sizeof(ACPI_TABLE_MADT));
2186
2187 // Search MADT for Sub-tables with needed data
2188 current = madt + 1;
2189 currentOut = buffer + sizeof(ACPI_TABLE_MADT) ;
2190
2191 end = (U8 *) madt + madt->Header.Length;
2192 endOut = (U8 *)buffer + bufferSize;
2193
2194 // Check to confirm no MADT buffer overflow
2195 if ( (U8 *)currentOut > (U8 *)endOut )
2196 {
2197 printf("Error: MADT Buffer Length exceeded available space \n");
2198 return(0);
2199 }
2200
2201 Length += sizeof(ACPI_TABLE_MADT);
2202
2203 while (current < end)
2204{
2205 ACPI_SUBTABLE_HEADER *subtable = current;
2206 ACPI_SUBTABLE_HEADER *subtableOut = currentOut;
2207
2208
2209 switch (subtable->Type)
2210{
2211
2212case ACPI_MADT_TYPE_LOCAL_APIC:
2213 {
2214
2215 // Process sub-tables with Type as 0: Processor Local APIC
2216 ACPI_MADT_LOCAL_APIC *lapic = current;
2217 current = lapic + 1;
2218
2219 if (!(lapic->LapicFlags & ACPI_MADT_ENABLED))
2220 continue;
2221
2222 if (madt_info->lapic_count >= nb_cpu)
2223 continue;
2224
2225 // copy subtable
2226 {
2227
2228 memcpy(currentOut, lapic, lapic->Header.Length);
2229
2230 currentOut = currentOut + lapic->Header.Length;
2231
2232 // Check to confirm no MADT buffer overflow
2233 if ( (U8 *)currentOut > (U8 *)endOut )
2234 {
2235 printf("Error: MADT Buffer Length exceeded available space \n");
2236 return(0);
2237 }
2238 }
2239
2240 {
2241 LAPIC_INFO *lapic_info = &madt_info->lapic[madt_info->lapic_count];
2242
2243 lapic_info->processorId = lapic->ProcessorId;
2244 lapic_info->apicId = lapic->Id;
2245 lapic_info->madt_type = ACPI_MADT_TYPE_LOCAL_APIC;
2246 }
2247
2248 madt_info->lapic_count++;
2249
2250 Length += lapic->Header.Length;
2251
2252 // Sanity check to verify compile time limit for max logical CPU is not exceeded
2253 if (madt_info->lapic_count > MAX_LOGICAL_CPU)
2254 return (0);
2255
2256 break;
2257 }
2258
2259case ACPI_MADT_TYPE_X2APIC:
2260 {
2261
2262 // Process sub-tables with Type as 9: Processor X2APIC
2263 ACPI_MADT_X2APIC *x2apic = current;
2264 current = x2apic + 1;
2265
2266 if (!(x2apic->x2apicFlags & ACPI_MADT_ENABLED))
2267 continue;
2268
2269 if (madt_info->lapic_count >= nb_cpu)
2270 continue;
2271
2272 // copy subtable
2273 {
2274 memcpy(currentOut, x2apic, x2apic->Header.Length);
2275
2276 currentOut = currentOut + x2apic->Header.Length;
2277
2278 // Check to confirm no MADT buffer overflow
2279 if ( (U8 *)currentOut > (U8 *)endOut )
2280 {
2281 printf("Error: MADT Buffer Length exceeded available space \n");
2282 return(0);
2283 }
2284
2285 }
2286
2287 {
2288 LAPIC_INFO *lapic_info = &madt_info->lapic[madt_info->lapic_count];
2289
2290 lapic_info->uid = x2apic->UID;
2291 lapic_info->apicId = x2apic->x2apicId;
2292 lapic_info->madt_type = ACPI_MADT_TYPE_X2APIC;
2293 }
2294
2295 madt_info->lapic_count++;
2296
2297 Length += x2apic->Header.Length;
2298
2299 // Sanity check to verify compile time limit for max logical CPU is not exceeded
2300 if (madt_info->lapic_count > MAX_LOGICAL_CPU)
2301 return (0);
2302
2303 break;
2304 }
2305
2306 case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
2307 {
2308 // Process sub-tables with Type as 4: Local APIC NMI
2309 ACPI_MADT_LOCAL_APIC_NMI *nmi = current;
2310 current = nmi + 1;
2311 /*
2312 if (!(nmi->IntiFlags & ACPI_MADT_ENABLED))
2313 continue;
2314 */
2315 if (LOCAL_APIC_NMI_CNT >= nb_cpu)
2316 continue;
2317
2318 memcpy(currentOut, nmi, nmi->Header.Length);
2319
2320 currentOut = currentOut + nmi->Header.Length;
2321
2322 // Check to confirm no MADT buffer overflow
2323 if ( (U8 *)currentOut > (U8 *)endOut )
2324 {
2325 printf("Error: MADT Buffer Length exceeded available space \n");
2326 return(0);
2327 }
2328
2329
2330 LOCAL_APIC_NMI_CNT++;
2331
2332 Length += nmi->Header.Length;
2333
2334 // Sanity check to verify compile time limit for max logical CPU is not exceeded
2335 if (LOCAL_APIC_NMI_CNT > MAX_LOGICAL_CPU)
2336 return (0);
2337
2338 break;
2339 }
2340
2341 case ACPI_MADT_TYPE_LOCAL_SAPIC:
2342 {
2343 // Process sub-tables with Type as 7: Local Sapic
2344 ACPI_MADT_LOCAL_SAPIC *sapic = current;
2345 current = sapic + 1;
2346 /*
2347 if (!(sapic->LapicFlags & ACPI_MADT_ENABLED))
2348 continue;
2349 */
2350 if (LOCAL_SAPIC_CNT >= nb_cpu)
2351 continue;
2352
2353 memcpy(currentOut, sapic, sapic->Header.Length);
2354
2355 currentOut = currentOut + sapic->Header.Length;
2356
2357 // Check to confirm no MADT buffer overflow
2358 if ( (U8 *)currentOut > (U8 *)endOut )
2359 {
2360 printf("Error: MADT Buffer Length exceeded available space \n");
2361 return(0);
2362 }
2363
2364
2365 LOCAL_SAPIC_CNT++;
2366
2367 Length += sapic->Header.Length;
2368
2369 // Sanity check to verify compile time limit for max logical CPU is not exceeded
2370 if (LOCAL_SAPIC_CNT > MAX_LOGICAL_CPU)
2371 return (0);
2372
2373 break;
2374 }
2375
2376 case ACPI_MADT_TYPE_INTERRUPT_SOURCE:
2377 {
2378 // Process sub-tables with Type as 8: Platform Interrupt Source
2379 ACPI_MADT_INTERRUPT_SOURCE *intsrc = current;
2380 current = intsrc + 1;
2381 /*
2382 if (!(intsrc->IntiFlags & ACPI_MADT_ENABLED))
2383 continue;
2384 */
2385 if (INT_SRC_CNT >= nb_cpu)
2386 continue;
2387
2388 memcpy(currentOut, intsrc, intsrc->Header.Length);
2389
2390 currentOut = currentOut + intsrc->Header.Length;
2391
2392 // Check to confirm no MADT buffer overflow
2393 if ( (U8 *)currentOut > (U8 *)endOut )
2394 {
2395 printf("Error: MADT Buffer Length exceeded available space \n");
2396 return(0);
2397 }
2398
2399
2400 INT_SRC_CNT++;
2401
2402 Length += intsrc->Header.Length;
2403
2404 // Sanity check to verify compile time limit for max logical CPU is not exceeded
2405 if (INT_SRC_CNT > MAX_LOGICAL_CPU)
2406 return (0);
2407
2408 break;
2409 }
2410
2411default:
2412 {
2413
2414 // Process all other sub-tables
2415 current = (U8 *) subtable + subtable->Length;
2416 currentOut = (U8 *) subtableOut + subtable->Length;
2417
2418 memcpy(subtableOut, subtable, subtable->Length);
2419
2420 // Check to confirm no MADT buffer overflow
2421 if ( (U8 *)currentOut > (U8 *)endOut )
2422 {
2423 printf("Error: MADT Buffer Length exceeded available space \n");
2424 return(0);
2425 }
2426
2427 Length += subtable->Length;
2428
2429 break;
2430 }
2431 } // switch
2432
2433 } // while
2434
2435 {
2436 ACPI_TABLE_MADT * new_madt = (ACPI_TABLE_MADT * )buffer;
2437
2438 // Update the Lenght of the new MADT table
2439 new_madt->Header.Length = Length;
2440
2441 // Update the checksum of the new MADT table
2442SetChecksum(&new_madt->Header);
2443 }
2444
2445 return (1);
2446}
2447
2448static U32 buildMADT(U32 * new_table_list, ACPI_TABLE_DSDT *dsdt, MADT_INFO * madt_info)
2449{
2450 DBG("Build MADT\n");
2451
2452ACPI_TABLE_MADT * madt_file = (void*)0ul;
2453ACPI_TABLE_MADT * MadtPointer = (void*)0ul;
2454 bool oem_apic=false;
2455 U8 new_table_index = 0;
2456
2457 // Check that we have a valid cpu_map (if it's not already done, it will try to generate it)
2458 if (generate_cpu_map_from_acpi(dsdt) != 0)
2459 {
2460 return(0);
2461 }
2462
2463 {
2464bool tmpval;
2465oem_apic=getBoolForKey(kOEMAPIC, &tmpval, &bootInfo->chameleonConfig)&&tmpval;
2466}
2467
2468 if (oem_apic == true)
2469 {
2470 return(0);
2471 }
2472
2473 if ((madt_file = (ACPI_TABLE_MADT *)get_new_table_in_list(new_table_list, NAMESEG("APIC"), &new_table_index)) != (void *)0ul)
2474{
2475 MadtPointer = (ACPI_TABLE_MADT *)madt_file;
2476
2477 new_table_list[new_table_index] = 0ul; // This way, the non-patched table will not be added in our new rsdt/xsdt table list
2478}
2479 else
2480 {
2481 MadtPointer = (acpi_tables.MadtPointer64 != (void*)0ul) ? (ACPI_TABLE_MADT *)acpi_tables.MadtPointer64 : (ACPI_TABLE_MADT *)acpi_tables.MadtPointer;
2482
2483 new_table_index = get_0ul_index_in_list(new_table_list, true);
2484
2485 // Check to confirm space is available
2486 if (new_table_index == ACPI_TABLE_LIST_FULL)
2487 {
2488 printf("Error: not enought reserved space in the new acpi list for the MADT table,\n ");
2489 printf(" please increase the RESERVED_AERA\n");
2490 return(0);
2491 }
2492 }
2493
2494 // Create buffer for MADT
2495 //U8 memory_for_madt[2 * 1024]; // seems to bug with xcode4, need to found out what is going on (not enough memory in the stack ?)
2496 U8 *memory_for_madt = (U8*)AllocateKernelMemory(2 * 1024);
2497
2498 // Build the new MADT
2499 if ( (ProcessMadt(MadtPointer, madt_info, memory_for_madt, 2 * 1024, cpu_map_count))== 0)
2500{
2501printf("Error: Failed to build MADT table\n");
2502return (0);
2503}
2504
2505// insert MADT in the new_table_list
2506{
2507// Create pointer to MADT just built in the stack buffer
2508ACPI_TABLE_MADT * old_madt = (ACPI_TABLE_MADT *)memory_for_madt;
2509
2510// Reserved kernel memory for the madt table
2511ACPI_TABLE_MADT *new_madt = (ACPI_TABLE_MADT *)AllocateKernelMemory(old_madt->Header.Length);
2512
2513if (!new_madt)
2514{
2515printf("Unable to allocate kernel memory for MADT ");
2516return (0);
2517}
2518// Move the old stack buffer to kernel memory
2519memcpy(new_madt, old_madt, old_madt->Header.Length);
2520
2521// Add the new madt into an empty space of the new_table_list
2522new_table_list[new_table_index] = (U32)new_madt;
2523}
2524
2525 verbose ("MADT table successfully patched\n");
2526return(1);
2527}
2528
2529static U32 ProcessSsdt(U32 * new_table_list, ACPI_TABLE_DSDT *dsdt, MADT_INFO * madt_info, bool enable_cstates, bool enable_pstates, bool enable_tstates )
2530{
2531DBG("Processing SSDT\n");
2532
2533// Check we are on an intel platform
2534if (Platform.CPU.Vendor != CPUID_VENDOR_INTEL) {
2535verbose ("Not an Intel platform: SSDT will not be generated !!!\n");
2536return(0);
2537}
2538
2539// Check for the msr feature flag
2540if (!(Platform.CPU.Features & CPU_FEATURE_MSR)) {
2541verbose ("Unsupported CPU: SSDT will not be generated !!!\n");
2542return(0);
2543}
2544
2545if (dsdt == (void *)0ul) {
2546verbose ("DSDT not found: SSDT will not be generated !!!\n");
2547return (0);
2548}
2549
2550// Get an empty space in the new_talbe_list (true = allow reserved space)
2551U8 empty = get_0ul_index_in_list(new_table_list, true);
2552
2553// Check to confirm space is available
2554if (empty == ACPI_TABLE_LIST_FULL)
2555{
2556printf("Error: not enought reserved space in the new acpi list for the SSDT table,\n ");
2557printf(" please increase the RESERVED_AERA\n");
2558return(0);
2559}
2560
2561// Create buffer for SSDT
2562//U8 memory_for_ssdt[20 * 1024];// seems to bug with xcode4, need to found out what is going on (not enough memory in the stack ?)
2563U8 *memory_for_ssdt =(U8*)AllocateKernelMemory(20 * 1024);
2564
2565// Build the SSDT
2566if ( (BuildSsdt(madt_info, dsdt, memory_for_ssdt, 20 * 1024 /*sizeof(memory_for_ssdt)*/, enable_cstates, enable_pstates, enable_tstates)) == 0)
2567{
2568printf("Error: Failed to build SSDT table\n");
2569return (0);
2570}
2571
2572// insert SSDT in the new_table_list
2573{
2574// Create pointer to SSDT just built in the stack buffer
2575ACPI_TABLE_SSDT * old_ssdt = (ACPI_TABLE_SSDT *)memory_for_ssdt;
2576
2577// Reserved kernel memory for the ssdt table
2578ACPI_TABLE_SSDT *new_ssdt = (ACPI_TABLE_SSDT *)AllocateKernelMemory(old_ssdt->Header.Length);
2579
2580if (!new_ssdt)
2581{
2582printf("Unable to allocate kernel memory for SSDT ");
2583return (0);
2584}
2585// Move the old stack buffer to kernel memory
2586memcpy(new_ssdt, old_ssdt, old_ssdt->Header.Length);
2587
2588// Add the new ssdt into an empty space of the new_table_list
2589new_table_list[empty] = (U32)new_ssdt;
2590}
2591
2592verbose ("SSDT table generated successfully\n");
2593return(1);
2594}
2595
2596//-----------------------------------------------------------------------------
2597static void * buildCpuScope (void * current, U32 cpu_namespace, PROCESSOR_NUMBER_TO_NAMESEG * aslCpuNamePath)
2598{
2599ACPI_SCOPE * scope = current;
2600current = scope + 1;
2601
2602scope->scopeOpcode = AML_SCOPE_OP;
2603scope->rootChar = AML_ROOT_PREFIX;
2604
2605if (aslCpuNamePath->seg_count == 1)
2606{
2607DUAL_NAME_PATH * dualNamePath = current;
2608current = dualNamePath + 1;
2609dualNamePath->prefix = AML_DUAL_NAME_PREFIX;
2610dualNamePath->nameseg[0] = cpu_namespace;
2611dualNamePath->nameseg[1] = aslCpuNamePath->nameseg[0];
2612}
2613else
2614{
2615MULTI_NAME_PATH * multiNamePath = current;
2616current = multiNamePath + 1;
2617multiNamePath->prefix = AML_MULTI_NAME_PREFIX;
2618// the nameseg count includes the root prefix and all other namesegs
2619multiNamePath->segCount = (U8) aslCpuNamePath->seg_count+1;
2620multiNamePath->nameseg[0] = cpu_namespace;
2621{
2622U32 i;
2623for (i=0; i<aslCpuNamePath->seg_count; i++)
2624multiNamePath->nameseg[i+1] = aslCpuNamePath->nameseg[i];
2625}
2626}
2627return (current);
2628}
2629//-----------------------------------------------------------------------------
2630static void * buildPDC(void * current)
2631{
2632ACPI_METHOD * pdc = current;
2633current = buildMethod(current, NAMESEG("_PDC"), 1);
2634
2635// CreateDWordField (Arg0, 0x08, CAPA)
2636current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2637current = buildOpCode(current, AML_ARG0_OP);
2638current = buildByteConst(current, 0x08);
2639current = buildNameSeg(current, NAMESEG("CAPA"));
2640
2641// Store (CAPA, TYPE)
2642current = buildOpCode(current, AML_STORE_OP);
2643current = buildNameSeg(current, NAMESEG("CAPA"));
2644current = buildNameSeg(current, NAMESEG("TYPE"));
2645
2646// CreateDWordField (Arg0, 0x00, REVS)
2647current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2648current = buildOpCode(current, AML_ARG0_OP);
2649current = buildByteConst(current, 0x00);
2650current = buildNameSeg(current, NAMESEG("REVS"));
2651
2652// CreateDWordField (Arg0, 0x04, SIZE)
2653current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2654current = buildOpCode(current, AML_ARG0_OP);
2655current = buildByteConst(current, 0x04);
2656current = buildNameSeg(current, NAMESEG("SIZE"));
2657
2658// Store(SizeOf(Arg0), Local0)
2659current = buildOpCode(current, AML_STORE_OP);
2660current = buildOpCode(current, AML_SIZEOF_OP);
2661current = buildOpCode(current, AML_ARG0_OP);
2662current = buildOpCode(current, AML_LOCAL0_OP);
2663
2664// Store(Subtract(Local0, 0x08),Local1)
2665current = buildOpCode(current, AML_STORE_OP);
2666current = buildOpCode(current, AML_SUBTRACT_OP);
2667current = buildOpCode(current, AML_LOCAL0_OP);
2668current = buildByteConst(current, 0x08);
2669current = buildOpCode(current, AML_ZERO_OP);
2670current = buildOpCode(current, AML_LOCAL1_OP);
2671
2672// CreateField (Arg0, 0x40, Multiply (Local1, 0x08), TEMP)
2673current = buildOpCode(current, AML_EXT_OP_PREFIX);
2674current = buildOpCode(current, AML_CREATE_FIELD_OP);
2675current = buildOpCode(current, AML_ARG0_OP);
2676current = buildByteConst(current, 0x40);
2677current = buildOpCode(current, AML_MULTIPLY_OP);
2678current = buildOpCode(current, AML_LOCAL1_OP);
2679current = buildByteConst(current, 0x08);
2680current = buildOpCode(current, AML_ZERO_OP);
2681current = buildNameSeg(current, NAMESEG("TEMP"));
2682
2683// Name (STS0, Buffer (0x04) {0x00, 0x00, 0x00, 0x00})
2684// Create STS0 as named buffer
2685current = buildNamePath(current, NAMESEG("STS0"));
2686{
2687ACPI_SMALL_BUFFER * buff = current;
2688current = buildSmallBuffer(current);
2689
2690// count of buffer elements
2691current = buildByteConst(current, 4);
2692
2693current = buildOpCode(current, AML_ZERO_OP);
2694current = buildOpCode(current, AML_ZERO_OP);
2695current = buildOpCode(current, AML_ZERO_OP);
2696current = buildOpCode(current, AML_ZERO_OP);
2697{
2698U32 length = (U8 *)current - (U8 *)buff;
2699buff->packageLength = (U8)length - 1;
2700}
2701}
2702
2703//Concatenate (STS0, TEMP, Local2)
2704current = buildOpCode(current, AML_CONCAT_OP);
2705current = buildNameSeg(current, NAMESEG("STS0"));
2706current = buildNameSeg(current, NAMESEG("TEMP"));
2707current = buildOpCode(current, AML_LOCAL2_OP);
2708
2709//_OSC (Buffer (0x10)
2710// {
2711// /* 0000 */ 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47,
2712// /* 0008 */ 0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53
2713// }, REVS, SIZE, Local2)
2714current = buildNameSeg(current, NAMESEG("_OSC"));
2715{
2716ACPI_SMALL_BUFFER * buff = current;
2717current = buildSmallBuffer(current);
2718
2719// count of buffer elements
2720current = buildByteConst(current, 0x10);
2721
2722current = buildOpCode(current, 0x16);
2723current = buildOpCode(current, 0xa6);
2724current = buildOpCode(current, 0x77);
2725current = buildOpCode(current, 0x40);
2726current = buildOpCode(current, 0x0c);
2727current = buildOpCode(current, 0x29);
2728current = buildOpCode(current, 0xbe);
2729current = buildOpCode(current, 0x47);
2730current = buildOpCode(current, 0x9e);
2731current = buildOpCode(current, 0xbd);
2732current = buildOpCode(current, 0xd8);
2733current = buildOpCode(current, 0x70);
2734current = buildOpCode(current, 0x58);
2735current = buildOpCode(current, 0x71);
2736current = buildOpCode(current, 0x39);
2737current = buildOpCode(current, 0x53);
2738{
2739U32 length = (U8 *)current - (U8 *)buff;
2740buff->packageLength = (U8)length - 1;
2741}
2742}
2743current = buildNameSeg(current, NAMESEG("REVS"));
2744current = buildNameSeg(current, NAMESEG("SIZE"));
2745current = buildOpCode(current, AML_LOCAL2_OP);
2746
2747// Update package length in PDC object
2748//pdc->packageLength = (U8)((U8 *)current - (U8 *)&pdc->packageLength);
2749setPackageLength(&pdc->pkgLength, (U8 *)current - (U8 *)&pdc->pkgLength);
2750
2751return(current);
2752}
2753
2754//-----------------------------------------------------------------------------
2755static void * buildOSC(void * current)
2756{
2757//
2758//
2759ACPI_METHOD * osc = current;
2760current = buildMethod(current, NAMESEG("_OSC"), 4);
2761
2762// CreateDWordField (Arg3, 0x04, CAPA)
2763current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2764current = buildOpCode(current, AML_ARG3_OP);
2765current = buildByteConst(current, 0x04);
2766current = buildNameSeg(current, NAMESEG("CAPA"));
2767
2768// Store (CAPA, TYPE)
2769current = buildOpCode(current, AML_STORE_OP);
2770current = buildNameSeg(current, NAMESEG("CAPA"));
2771current = buildNameSeg(current, NAMESEG("TYPE"));
2772
2773// CreateDWordField (Arg3, 0x00, STS0)
2774current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2775current = buildOpCode(current, AML_ARG3_OP);
2776current = buildByteConst(current, 0x00);
2777current = buildNameSeg(current, NAMESEG("STS0"));
2778
2779// CreateDWordField (Arg3, 0x04, CAP0)
2780current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2781current = buildOpCode(current, AML_ARG3_OP);
2782current = buildByteConst(current, 0x04);
2783current = buildNameSeg(current, NAMESEG("CAP0"));
2784
2785// CreateDWordField (Arg0, 0x00, IID0)
2786current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2787current = buildOpCode(current, AML_ARG0_OP);
2788current = buildByteConst(current, 0x00);
2789current = buildNameSeg(current, NAMESEG("IID0"));
2790
2791// CreateDWordField (Arg0, 0x04, IID1)
2792current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2793current = buildOpCode(current, AML_ARG0_OP);
2794current = buildByteConst(current, 0x04);
2795current = buildNameSeg(current, NAMESEG("IID1"));
2796
2797// CreateDWordField (Arg0, 0x08, IID2)
2798current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2799current = buildOpCode(current, AML_ARG0_OP);
2800current = buildByteConst(current, 0x08);
2801current = buildNameSeg(current, NAMESEG("IID2"));
2802
2803// CreateDWordField (Arg0, 0x0C, IID3)
2804current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2805current = buildOpCode(current, AML_ARG0_OP);
2806current = buildByteConst(current, 0x0C);
2807current = buildNameSeg(current, NAMESEG("IID3"));
2808
2809// Name (UID0, Buffer (0x10)
2810// {
2811// 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47,
2812// 0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53
2813// })
2814current = buildNamePath(current, NAMESEG("UID0"));
2815{
2816ACPI_SMALL_BUFFER * buff = current;
2817current = buildSmallBuffer(current);
2818
2819// count of buffer elements
2820current = buildByteConst(current, 0x10);
2821
2822current = buildOpCode(current, 0x16);
2823current = buildOpCode(current, 0xa6);
2824current = buildOpCode(current, 0x77);
2825current = buildOpCode(current, 0x40);
2826current = buildOpCode(current, 0x0c);
2827current = buildOpCode(current, 0x29);
2828current = buildOpCode(current, 0xbe);
2829current = buildOpCode(current, 0x47);
2830current = buildOpCode(current, 0x9e);
2831current = buildOpCode(current, 0xbd);
2832current = buildOpCode(current, 0xd8);
2833current = buildOpCode(current, 0x70);
2834current = buildOpCode(current, 0x58);
2835current = buildOpCode(current, 0x71);
2836current = buildOpCode(current, 0x39);
2837current = buildOpCode(current, 0x53);
2838
2839{
2840U32 length = (U8 *)current - (U8 *)buff;
2841buff->packageLength = (U8)length - 1;
2842}
2843}
2844
2845// CreateDWordField (UID0, 0x00, EID0)
2846current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2847current = buildOpCode(current, AML_ARG0_OP);
2848current = buildByteConst(current, 0x00);
2849current = buildNameSeg(current, NAMESEG("EID0"));
2850
2851// CreateDWordField (UID0, 0x04, EID1)
2852current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2853current = buildOpCode(current, AML_ARG0_OP);
2854current = buildByteConst(current, 0x04);
2855current = buildNameSeg(current, NAMESEG("EID1"));
2856
2857// CreateDWordField (UID0, 0x08, EID2)
2858current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2859current = buildOpCode(current, AML_ARG0_OP);
2860current = buildByteConst(current, 0x08);
2861current = buildNameSeg(current, NAMESEG("EID2"));
2862
2863// CreateDWordField (UID0, 0x0C, EID3)
2864current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2865current = buildOpCode(current, AML_ARG0_OP);
2866current = buildByteConst(current, 0x0C);
2867current = buildNameSeg(current, NAMESEG("EID3"));
2868
2869// If (LNot (LAnd (LAnd (LEqual (IID0, EID0), LEqual (IID1, EID1)),
2870// LAnd (LEqual (IID2, EID2), LEqual (IID3, EID3)))))
2871// {
2872// Store (0x06, Index (STS0, 0x00))
2873// Return (Arg3)
2874// }
2875{
2876current = buildOpCode(current, AML_IF_OP);
2877{
2878ACPI_PACKAGE_LENGTH * packageLength = current;
2879current = buildPackageLength(current, 0);
2880
2881current = buildOpCode(current, AML_LNOT_OP);
2882current = buildOpCode(current, AML_LAND_OP);
2883current = buildOpCode(current, AML_LAND_OP);
2884current = buildOpCode(current, AML_LEQUAL_OP);
2885current = buildNameSeg(current, NAMESEG("IID0"));
2886current = buildNameSeg(current, NAMESEG("EID0"));
2887
2888current = buildOpCode(current, AML_LEQUAL_OP);
2889current = buildNameSeg(current, NAMESEG("IID1"));
2890current = buildNameSeg(current, NAMESEG("EID1"));
2891
2892current = buildOpCode(current, AML_LAND_OP);
2893current = buildOpCode(current, AML_LEQUAL_OP);
2894current = buildNameSeg(current, NAMESEG("IID2"));
2895current = buildNameSeg(current, NAMESEG("EID2"));
2896
2897current = buildOpCode(current, AML_LEQUAL_OP);
2898current = buildNameSeg(current, NAMESEG("IID3"));
2899current = buildNameSeg(current, NAMESEG("EID3"));
2900
2901// Store (0x06, Index (STS0, 0x00))
2902current = buildOpCode(current, AML_STORE_OP);
2903current = buildByteConst(current, 0x06);
2904current = buildOpCode(current, AML_INDEX_OP);
2905current = buildNameSeg(current, NAMESEG("STS0"));
2906current = buildByteConst(current, 0x00);
2907current = buildOpCode(current, AML_ZERO_OP);
2908
2909// Return (Arg3)
2910current = buildReturnOpcode(current, AML_ARG3_OP);
2911
2912setPackageLength(packageLength,
2913 (U8 *)current - (U8 *)packageLength);
2914}
2915}
2916
2917// If (LNotEqual (Arg1, 0x01))
2918// {
2919// Store (0x0A, Index (STS0, 0x00))
2920// Return (Arg3)
2921// }
2922{
2923current = buildOpCode(current, AML_IF_OP);
2924{
2925ACPI_PACKAGE_LENGTH * packageLength = current;
2926current = buildPackageLength(current, 0);
2927
2928// If ("LNotEqual (Arg1, 0x01)")
2929current = buildOpCode(current, AML_LNOT_OP);
2930current = buildOpCode(current, AML_LEQUAL_OP);
2931current = buildOpCode(current, AML_ARG1_OP);
2932current = buildByteConst(current, 0x01);
2933
2934// Store (0x0A, Index (STS0, 0x00))
2935current = buildOpCode(current, AML_STORE_OP);
2936current = buildByteConst(current, 0x0A);
2937current = buildOpCode(current, AML_INDEX_OP);
2938current = buildNameSeg(current, NAMESEG("STS0"));
2939current = buildByteConst(current, 0x00);
2940current = buildOpCode(current, AML_ZERO_OP);
2941
2942// Return (Arg3)
2943current = buildReturnOpcode(current, AML_ARG3_OP);
2944
2945setPackageLength(packageLength,
2946 (U8 *)current - (U8 *)packageLength);
2947}
2948}
2949
2950// If (And (STS0, 0x01))
2951// {
2952// And (CAP0, 0x0BFF, CAP0)
2953// Return (Arg3)
2954// }
2955{
2956current = buildOpCode(current, AML_IF_OP);
2957{
2958ACPI_PACKAGE_LENGTH * packageLength = current;
2959current = buildPackageLength(current, 0);
2960
2961// If ("And (STS0, 0x01)")
2962current = buildOpCode(current, AML_AND_OP);
2963current = buildNameSeg(current, NAMESEG("STS0"));
2964current = buildByteConst(current, 0x01);
2965current = buildOpCode(current, AML_ZERO_OP);
2966
2967// And (CAP0, 0x0BFF, CAP0)
2968current = buildOpCode(current, AML_AND_OP);
2969current = buildNameSeg(current, NAMESEG("CAP0"));
2970current = buildWordConst(current, 0x0BFF);
2971current = buildNameSeg(current, NAMESEG("CAP0"));
2972
2973// Return (Arg3)
2974current = buildReturnOpcode(current, AML_ARG3_OP);
2975
2976setPackageLength(packageLength,
2977 (U8 *)current - (U8 *)packageLength);
2978}
2979}
2980
2981// And (CAP0, 0x0BFF, CAP0)
2982current = buildOpCode(current, AML_AND_OP);
2983current = buildNameSeg(current, NAMESEG("CAP0"));
2984current = buildWordConst(current, 0x0BFF);
2985current = buildNameSeg(current, NAMESEG("CAP0"));
2986
2987// Store (CAP0, TYPE)
2988current = buildOpCode(current, AML_STORE_OP);
2989current = buildNameSeg(current, NAMESEG("CAP0"));
2990current = buildNameSeg(current, NAMESEG("TYPE"));
2991
2992// Return (Arg3)
2993current = buildReturnOpcode(current, AML_ARG3_OP);
2994
2995// Set package length for the OSC object
2996setPackageLength(&osc->pkgLength, (U8 *)current - (U8 *)&osc->pkgLength);
2997
2998return(current);
2999}
3000
3001//-----------------------------------------------------------------------------
3002static void * buildPSS(void * current, PKG_PSTATES * pkg_pstates)
3003{
3004//
3005// IF (PSEN)
3006// {
3007// Return (Package of Pstate Packages)
3008// }
3009// Return(Zero)
3010//
3011ACPI_METHOD * pss = current;
3012current = buildMethod(current, NAMESEG("_PSS"), 0);
3013
3014{
3015// "IF" (PSEN) -- IF Opcode
3016current = buildOpCode(current, AML_IF_OP);
3017{
3018ACPI_PACKAGE_LENGTH * packageLength = current;
3019current = buildPackageLength(current, 0);
3020
3021// IF "(PSEN)" -- IF Predicate
3022current = buildNameSeg(current, NAMESEG("PSEN"));
3023
3024{
3025ACPI_RETURN_PACKAGE * returnPkg = current;
3026current = buildReturnPackage(current, (U8)pkg_pstates->num_pstates);
3027
3028// (3.3.3) For each P-state
3029{
3030U32 pstateIndex = 0;
3031for (pstateIndex=0; pstateIndex < pkg_pstates->num_pstates; pstateIndex++)
3032{
3033// (3.3.3.1) Create P-state package
3034ACPI_PSTATE_PACKAGE * pstate = current;
3035current = pstate + 1;
3036
3037setSmallPackage(&pstate->package, 6);
3038pstate->package.packageLength = (U8)(sizeof(ACPI_PSTATE_PACKAGE) - 1);
3039
3040setDwordConst(&pstate->CoreFreq, pkg_pstates->pstate[pstateIndex].frequency);// CoreFreq (in MHz).
3041setDwordConst(&pstate->Power, pkg_pstates->pstate[pstateIndex].power);// Power (in milliWatts).
3042setDwordConst(&pstate->TransLatency, pkg_pstates->pstate[pstateIndex].translatency);// Transition Latency (in microseconds).
3043setDwordConst(&pstate->BMLatency, pkg_pstates->pstate[pstateIndex].bmlatency);// Bus Master Latency (in microseconds).
3044setDwordConst(&pstate->Control, pkg_pstates->pstate[pstateIndex].control); // Control.
3045
3046setDwordConst(&pstate->Status, encode_pstate(pkg_pstates->pstate[pstateIndex].ratio));// Status.
3047} // for
3048} // for block
3049
3050// (3.3.4) Update package length in return package
3051setPackageLength(&returnPkg->package.pkgLength, (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3052}
3053
3054// "IF (PSEN) and its body" -- Set package length
3055setPackageLength(packageLength,
3056 (U8 *)current - (U8 *)packageLength);
3057}
3058// "Return (ZERO)"
3059current = buildReturnZero(current);
3060}
3061// Set package length for the _PSS object
3062setPackageLength(&pss->pkgLength, (U8 *)current - (U8 *)&pss->pkgLength);
3063
3064return(current);
3065}
3066
3067//-----------------------------------------------------------------------------
3068static void * buildPSD(void * current, U32 domain, U32 cpusInDomain, U32 pstate_coordination)
3069{
3070// If (And(TYPE, 0x0820))
3071// {
3072// Return (PSD Package)
3073// }
3074// Return(Zero)
3075
3076ACPI_METHOD * psdMethod = current;
3077current = buildMethod(current, NAMESEG("_PSD"), 0);
3078{
3079// "IF" (And(TYPE, 0x0820)) -- IF Opcode
3080current = buildOpCode(current, AML_IF_OP);
3081{
3082ACPI_PACKAGE_LENGTH * packageLength = current;
3083current = buildPackageLength(current, 0);
3084
3085// IF ("And"(TYPE, 0x820)) -- AND Opcode
3086current = buildOpCode(current, AML_AND_OP);
3087
3088// IF (And("TYPE", 0x820)) -- TYPE Term
3089current = buildNameSeg(current, NAMESEG("TYPE"));
3090
3091// IF (And(TYPE, "0x0820")) -- DWORD Value Term
3092current = buildDwordConst(current, 0x820);
3093
3094// IF ("And(TYPE, 0x200)") -- Target for And term (unused)
3095current = buildOpCode(current, AML_ZERO_OP);
3096
3097// Build return package containing PSD package
3098{
3099ACPI_RETURN_PACKAGE * returnPkg = current;
3100current = buildReturnPackage(current, 1);
3101
3102{
3103// Create PSD package
3104ACPI_PSD_PACKAGE * psd = current;
3105current = psd + 1;
3106
3107setSmallPackage(&psd->package, 5);
3108psd->package.packageLength = (U8)(sizeof(ACPI_PSD_PACKAGE) - 1);
3109
3110setByteConst(&psd->NumberOfEntries, 5);
3111setByteConst(&psd->Revision, 0);
3112setDwordConst(&psd->Domain, domain);
3113setDwordConst(&psd->CoordType, pstate_coordination);
3114setDwordConst(&psd->NumProcessors, cpusInDomain);
3115
3116} // PSD package
3117
3118setPackageLength(&returnPkg->package.pkgLength,
3119 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3120}
3121setPackageLength(packageLength, (U8 *)current - (U8 *)packageLength);
3122}
3123// "Return (ZERO)"
3124current = buildReturnZero(current);
3125}
3126// Update length in _PSD method
3127setPackageLength(&psdMethod->pkgLength, (U8 *)current - (U8 *)&psdMethod->pkgLength);
3128
3129return(current);
3130}
3131
3132//-----------------------------------------------------------------------------
3133static void * buildPPC(void * current/*, U8 valueToReturn*/)
3134{
3135ACPI_SMALL_METHOD * ppc = current;
3136current = buildSmallMethod(current, NAMESEG("_PPC"), 0);
3137
3138current = buildReturnZero(current);
3139
3140//current = buildReturnOpcode(current, valueToReturn);
3141
3142// Update package length in PPC object
3143ppc->packageLength = (U8) ( (U8 *)current - (U8 *)&ppc->packageLength );
3144
3145return(current);
3146}
3147
3148#if UNUSED
3149//-----------------------------------------------------------------------------
3150static void * buildPDL(void * current, U8 valueToReturn)
3151{
3152ACPI_SMALL_METHOD * pdl = current;
3153current = buildSmallMethod(current, NAMESEG("_PDL"), 0);
3154
3155current = buildReturnOpcode(current, valueToReturn);
3156
3157// Update package length in PDL object
3158pdl->packageLength = (U8) ( (U8 *)current - (U8 *)&pdl->packageLength );
3159
3160return(current);
3161}
3162#endif
3163
3164//-----------------------------------------------------------------------------
3165static void * buildPCT(void * current)
3166{
3167static const ACPI_GENERIC_ADDRESS pct_gas[] = {
3168{0x7f,0x40,0,0,0x199},
3169{0x7f,0x10,0,0,0x198},
3170};
3171
3172ACPI_SMALL_METHOD * pct = current;
3173current = buildSmallMethod(current, NAMESEG("_PCT"), 0);
3174
3175{
3176ACPI_RETURN_PACKAGE * returnPkg = current;
3177current = buildReturnPackage(current, 2);
3178
3179{
3180ACPI_SMALL_BUFFER * buff = current;
3181current = buildSmallBuffer(current);
3182
3183current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) );
3184current = buildGenericRegister(current, &pct_gas[0]);
3185current = buildEndTag(current);
3186
3187{
3188U32 length = (U8 *)current - (U8 *)buff;
3189buff->packageLength = (U8)length - 1;
3190}
3191}
3192{
3193ACPI_SMALL_BUFFER * buff = current;
3194current = buildSmallBuffer(current);
3195
3196current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) );
3197current = buildGenericRegister(current, &pct_gas[1]);
3198current = buildEndTag(current);
3199
3200{
3201U32 length = (U8 *)current - (U8 *)buff;
3202buff->packageLength = (U8)length - 1;
3203}
3204
3205}
3206
3207setPackageLength(&returnPkg->package.pkgLength,
3208 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3209}
3210
3211// Update package length in PCT object
3212pct->packageLength = (U8)((U8 *)current - (U8 *)&pct->packageLength);
3213
3214return(current);
3215}
3216
3217//-----------------------------------------------------------------------------
3218static void * buildCstate(void * current, ACPI_GENERIC_ADDRESS * gas, CSTATE * cstate)
3219{
3220//
3221// Build a C-state
3222//
3223ACPI_SMALL_PACKAGE * pkg1 = current;
3224current = buildSmallPackage(current, 4);
3225
3226{
3227{
3228ACPI_SMALL_BUFFER * buffer = current;
3229current = buildSmallBuffer(current);
3230
3231{
3232// Buffer length
3233current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) );
3234current = buildGenericRegister(current, gas);
3235current = buildEndTag(current);
3236}
3237{
3238U32 length = (U8 *)current - (U8 *)buffer;
3239buffer->packageLength = (U8)length - 1;
3240}
3241}
3242
3243{
3244current = buildByteConst(current, cstate->type);
3245current = buildWordConst(current, cstate->latency);
3246current = buildDwordConst(current, cstate->power);
3247}
3248}
3249pkg1->packageLength = (U8)((U8 *)current - (U8 *)&pkg1->packageLength);
3250
3251return(current);
3252}
3253
3254//-----------------------------------------------------------------------------
3255static void * buildReturnPackageCST(void * current, PKG_CSTATES * pkg_cstates)
3256{
3257// Create package returning C-states
3258ACPI_RETURN_PACKAGE * returnPkg = current;
3259current = buildReturnPackage(current, (U8)pkg_cstates->num_cstates + 1);
3260
3261{
3262// Include number of C-states
3263current = buildByteConst(current, (U8)pkg_cstates->num_cstates);
3264
3265{
3266U32 cstateIndex = 0;
3267for (cstateIndex=0; cstateIndex < pkg_cstates->num_cstates; cstateIndex++)
3268// Build C-state
3269current = buildCstate(current, &pkg_cstates->gas[cstateIndex], &pkg_cstates->cstate[cstateIndex]);
3270}
3271}
3272
3273// Update package length in return package
3274setPackageLength(&returnPkg->package.pkgLength,
3275 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3276
3277return(current);
3278}
3279
3280//-----------------------------------------------------------------------------
3281static void * buildCST(void * current, PKG_CSTATES * mwait_pkg_cstates, PKG_CSTATES * io_pkg_cstates)
3282{
3283//
3284// IF (CSEN)
3285// {
3286// IF (LAnd(MWOS, And(TYPE, 0x200)))
3287// {
3288// Return package containing MWAIT C-states
3289// }
3290// Return package containing IO C-states
3291// }
3292// Return(Zero)
3293//
3294ACPI_METHOD * cst = current;
3295current = buildMethod(current, NAMESEG("_CST"), 0);
3296{
3297// "IF" CSEN -- IF Opcode
3298current = buildOpCode(current, AML_IF_OP);
3299{
3300ACPI_PACKAGE_LENGTH * packageLength1 = current;
3301current = buildPackageLength(current, 0);
3302
3303// IF "(CSEN)" -- IF Predicate
3304current = buildNameSeg(current, NAMESEG("CSEN"));
3305
3306// "IF" (LAnd(MWOS, And(TYPE, 0x200))) -- IF Opcode
3307current = buildOpCode(current, AML_IF_OP);
3308{
3309ACPI_PACKAGE_LENGTH * packageLength2 = current;
3310current = buildPackageLength(current, 0);
3311
3312// IF ("LAnd"(MWOS, And(TYPE, 0x200))) -- LAND Opcode
3313current = buildOpCode(current, AML_LAND_OP);
3314
3315// IF (LAnd("MWOS", And(TYPE, 0x200))) -- MWOS Term
3316current = buildNameSeg(current, NAMESEG("MWOS"));
3317
3318// IF (LAnd(MWOS, "And"(TYPE, 0x200))) -- AND Opcode
3319current = buildOpCode(current, AML_AND_OP);
3320
3321// IF (LAnd(MWOS, And("TYPE", 0x200))) -- TYPE Term
3322current = buildNameSeg(current, NAMESEG("TYPE"));
3323
3324// IF (LAnd(MWOS, And(TYPE, "0x200"))) -- DWORD Value Term
3325current = buildWordConst(current, 0x200);
3326
3327// IF (LAnd(MWOS, "And(TYPE, 0x200)")) -- Target for And term (unused)
3328current = buildOpCode(current, AML_ZERO_OP);
3329
3330// Build return package for mwait c-states
3331current = buildReturnPackageCST(current, mwait_pkg_cstates);
3332
3333setPackageLength(packageLength2,
3334 (U8 *)current - (U8 *)packageLength2);
3335}
3336
3337// Build return package for io c-states
3338current = buildReturnPackageCST(current, io_pkg_cstates);
3339
3340setPackageLength(packageLength1,
3341 (U8 *)current - (U8 *)packageLength1);
3342}
3343// "Return (ZERO)"
3344current = buildReturnZero(current);
3345}
3346// Update length in _CST method
3347setPackageLength(&cst->pkgLength, (U8 *)current - (U8 *)&cst->pkgLength);
3348
3349return(current);
3350}
3351
3352#if BUILD_ACPI_CSD
3353//-----------------------------------------------------------------------------
3354static void * buildCSD(void * current, U32 domain, U32 cpusInDomain, PKG_CSTATES * pkg_cstates)
3355{
3356 // If (And(TYPE, 0x0040))
3357 // {
3358 // Return (CSD Package)
3359 // }
3360 // Return(Zero)
3361
3362 ACPI_METHOD * csdMethod = current;
3363 current = buildMethod(current, NAMESEG("_CSD"), 0);
3364 {
3365 // "IF" (And(TYPE, 0x0040)) -- IF Opcode
3366 current = buildOpCode(current, AML_IF_OP);
3367 {
3368 ACPI_PACKAGE_LENGTH * packageLength = current;
3369 current = buildPackageLength(current, 0);
3370
3371 // IF ("And"(TYPE, 0x0040)) -- AND Opcode
3372 current = buildOpCode(current, AML_AND_OP);
3373
3374 // IF (And("TYPE", 0x0040)) -- TYPE Term
3375 current = buildNameSeg(current, NAMESEG("TYPE"));
3376
3377 // IF (And(TYPE, "0x0040")) -- DWORD Value Term
3378 current = buildDwordConst(current, 0x0040);
3379
3380 // IF ("And(TYPE, 0x0040)") -- Target for And term (unused)
3381 current = buildOpCode(current, AML_ZERO_OP);
3382
3383 // Build return package containing CSD package(s)
3384 {
3385 ACPI_RETURN_PACKAGE * returnPkg = current;
3386 current = buildReturnPackage(current, (U8)pkg_cstates->num_cstates - 1);
3387
3388 {
3389 U32 cstateIndex;
3390 for (cstateIndex=1; cstateIndex < pkg_cstates->num_cstates; cstateIndex++)
3391 {
3392 // Build CSD for this C-state
3393
3394 // Create CSD package
3395 ACPI_CSD_PACKAGE * csd = current;
3396 current = csd + 1;
3397
3398 setSmallPackage(&csd->package, 6);
3399 csd->package.packageLength = (U8)(sizeof(ACPI_CSD_PACKAGE) - 1);
3400
3401 setByteConst(&csd->NumberOfEntries, 6);
3402 setByteConst(&csd->Revision, 0);
3403 setDwordConst(&csd->Domain, domain);
3404 setDwordConst(&csd->CoordType, ACPI_COORD_TYPE_HW_ALL);
3405 setDwordConst(&csd->NumProcessors, cpusInDomain);
3406 setDwordConst(&csd->Index, cstateIndex);
3407 }
3408 }
3409
3410 setPackageLength(&returnPkg->package.pkgLength,
3411 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3412 }
3413
3414 setPackageLength(packageLength, (U8 *)current - (U8 *)packageLength);
3415 }
3416 // "Return (ZERO)"
3417 current = buildReturnZero(current);
3418 }
3419 // Update length in _CSD method
3420 setPackageLength(&csdMethod->pkgLength, (U8 *)current - (U8 *)&csdMethod->pkgLength);
3421
3422 return(current);
3423}
3424#endif // BUILD_ACPI_CSD
3425
3426#if BUILD_ACPI_TSS
3427//-----------------------------------------------------------------------------
3428static void * buildTPC(void * current)
3429{
3430 ACPI_SMALL_METHOD * tpc = current;
3431 current = buildSmallMethod(current, NAMESEG("_TPC"), 0);
3432
3433 current = buildReturnZero(current);
3434
3435 // Update package length in PPC object
3436 tpc->packageLength = (U8) ( (U8 *)current - (U8 *)&tpc->packageLength );
3437
3438 return(current);
3439}
3440
3441//-----------------------------------------------------------------------------
3442static void * buildPTC(void * current)
3443{
3444 static const ACPI_GENERIC_ADDRESS ptc_gas[] = {
3445 {0x7f,0x00,0,0,0},
3446 {0x7f,0x00,0,0,0},
3447 };
3448
3449 ACPI_SMALL_METHOD * ptc = current;
3450 current = buildSmallMethod(current, NAMESEG("_PTC"), 0);
3451
3452 {
3453 ACPI_RETURN_PACKAGE * returnPkg = current;
3454 current = buildReturnPackage(current, 2);
3455
3456 {
3457 ACPI_SMALL_BUFFER * buff = current;
3458 current = buildSmallBuffer(current);
3459
3460 current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) );
3461 current = buildGenericRegister(current, &ptc_gas[0]);
3462 current = buildEndTag(current);
3463
3464 {
3465 U32 length = (U8 *)current - (U8 *)buff;
3466 buff->packageLength = (U8)length - 1;
3467 }
3468 }
3469 {
3470 ACPI_SMALL_BUFFER * buff = current;
3471 current = buildSmallBuffer(current);
3472
3473 current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) );
3474 current = buildGenericRegister(current, &ptc_gas[1]);
3475 current = buildEndTag(current);
3476
3477 {
3478 U32 length = (U8 *)current - (U8 *)buff;
3479 buff->packageLength = (U8)length - 1;
3480 }
3481 }
3482
3483 setPackageLength(&returnPkg->package.pkgLength,
3484 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3485 }
3486
3487 // Update package length in PTC object
3488 ptc->packageLength = (U8)((U8 *)current - (U8 *)&ptc->packageLength);
3489
3490 return(current);
3491}
3492
3493//-----------------------------------------------------------------------------
3494static void * buildTSS(void * current, PKG_TSTATES * pkg_tstates)
3495{
3496 //
3497 // IF (LAnd(TSEN, And(TYPE,4)))
3498 // {
3499 // Return (Package of Tstate Packages)
3500 // }
3501 // Return(Zero)
3502 //
3503 ACPI_METHOD * tss = current;
3504 current = buildMethod(current, NAMESEG("_TSS"), 0);
3505
3506 {
3507 // "IF" (LAnd(TSEN, And(TYPE,4))) -- IF Opcode
3508 current = buildOpCode(current, AML_IF_OP);
3509 {
3510 ACPI_PACKAGE_LENGTH * packageLength = current;
3511 current = buildPackageLength(current, 0);
3512
3513 // IF ("LAnd"(TSEN, And(TYPE, 4))) -- LAND Opcode
3514 current = buildOpCode(current, AML_LAND_OP);
3515
3516 // IF (LAnd("TSEN", And(TYPE, 4))) -- TSEN Term
3517 current = buildNameSeg(current, NAMESEG("TSEN"));
3518
3519 // IF (LAnd(TSEN, "And"(TYPE, 4))) -- AND Opcode
3520 current = buildOpCode(current, AML_AND_OP);
3521
3522 // IF (LAnd(TSEN, And("TYPE", 4))) -- TYPE Term
3523 current = buildNameSeg(current, NAMESEG("TYPE"));
3524
3525 // IF (LAnd(TSEN, And(TYPE, "4"))) -- DWORD Value Term
3526 current = buildWordConst(current, 4);
3527
3528 // IF (LAnd(MWOS, "And(TYPE, 4)")) -- Target for And term (unused)
3529 current = buildOpCode(current, AML_ZERO_OP);
3530
3531 // Return (Package of Tstate Packages)
3532 {
3533 ACPI_RETURN_PACKAGE * returnPkg = current;
3534 current = buildReturnPackage(current, (U8)pkg_tstates->num_tstates);
3535
3536 // (3.3.3) For each T-state
3537 {
3538 U32 tstateIndex = 0;
3539 for (tstateIndex=0; tstateIndex < pkg_tstates->num_tstates; tstateIndex++)
3540 {
3541 // (3.3.3.1) Create T-state package
3542 ACPI_TSTATE_PACKAGE * tstate = current;
3543 current = tstate + 1;
3544
3545 setSmallPackage(&tstate->package, 5);
3546 tstate->package.packageLength = (U8)(sizeof(ACPI_TSTATE_PACKAGE) - 1);
3547
3548 setDwordConst(&tstate->FreqPercent, pkg_tstates->tstate[tstateIndex].freqpercent);
3549 setDwordConst(&tstate->Power, pkg_tstates->tstate[tstateIndex].power);
3550 setDwordConst(&tstate->TransLatency, pkg_tstates->tstate[tstateIndex].latency);
3551 setDwordConst(&tstate->Control, pkg_tstates->tstate[tstateIndex].control);
3552 setDwordConst(&tstate->Status, pkg_tstates->tstate[tstateIndex].status);
3553 } // for
3554 } // for block
3555
3556 // (3.3.4) Update package length in return package
3557 setPackageLength(&returnPkg->package.pkgLength, (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3558 }
3559
3560 // "IF (LAnd(TSEN, And(TYPE,4))) and its body" -- Set package length
3561 setPackageLength(packageLength, (U8 *)current - (U8 *)packageLength);
3562 }
3563 // "Return (ZERO)"
3564 current = buildReturnZero(current);
3565 }
3566 // Set package length for the _TSS object
3567 setPackageLength(&tss->pkgLength, (U8 *)current - (U8 *)&tss->pkgLength);
3568
3569 return(current);
3570}
3571
3572//-----------------------------------------------------------------------------
3573static void * buildTSD(void * current, U32 domain, U32 cpusInDomain)
3574{
3575 // If (And(TYPE, 0x0080))
3576 // {
3577 // Return (Package containing TSD package)
3578 // }
3579 // Return(Zero)
3580
3581 ACPI_METHOD * tsdMethod = current;
3582 current = buildMethod(current, NAMESEG("_TSD"), 0);
3583 {
3584 // "IF" (And(TYPE, 0x0080)) -- IF Opcode
3585 current = buildOpCode(current, AML_IF_OP);
3586 {
3587 ACPI_PACKAGE_LENGTH * packageLength = current;
3588 current = buildPackageLength(current, 0);
3589
3590 // IF ("And"(TYPE, 0x0080)) -- AND Opcode
3591 current = buildOpCode(current, AML_AND_OP);
3592
3593 // IF (And("TYPE", 0x0080)) -- TYPE Term
3594 current = buildNameSeg(current, NAMESEG("TYPE"));
3595
3596 // IF (And(TYPE, "0x0080")) -- DWORD Value Term
3597 current = buildDwordConst(current, 0x0080);
3598
3599 // IF ("And(TYPE, 0x0080)") -- Target for And term (unused)
3600 current = buildOpCode(current, AML_ZERO_OP);
3601
3602 // Build package containing TSD package
3603 {
3604 ACPI_RETURN_PACKAGE * returnPkg = current;
3605 current = buildReturnPackage(current, 1);
3606
3607 {
3608 // Create PSD package
3609 ACPI_TSD_PACKAGE * tsd = current;
3610 current = tsd + 1;
3611
3612 setSmallPackage(&tsd->package, 5);
3613 tsd->package.packageLength = (U8)(sizeof(ACPI_TSD_PACKAGE) - 1);
3614
3615 setByteConst(&tsd->NumberOfEntries, 5);
3616 setByteConst(&tsd->Revision, 0);
3617 setDwordConst(&tsd->Domain, domain);
3618 setDwordConst(&tsd->CoordType, ACPI_COORD_TYPE_SW_ANY);
3619 setDwordConst(&tsd->NumProcessors, cpusInDomain);
3620
3621 } // TSD package
3622
3623 setPackageLength(&returnPkg->package.pkgLength,
3624 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3625 }
3626
3627 setPackageLength(packageLength, (U8 *)current - (U8 *)packageLength);
3628 }
3629 // "Return (ZERO)"
3630 current = buildReturnZero(current);
3631 }
3632 // Update length in _TSD method
3633 setPackageLength(&tsdMethod->pkgLength, (U8 *)current - (U8 *)&tsdMethod->pkgLength);
3634
3635 return(current);
3636}
3637#endif // BUILD_ACPI_TSS
3638
3639//-----------------------------------------------------------------------------
3640static U32 BuildSsdt(MADT_INFO * madt_info, ACPI_TABLE_DSDT *dsdt, void * buffer, U32 bufferSize, bool enable_cstates, bool enable_pstates, bool enable_tstates)
3641{
3642// Build SSDT
3643{
3644// (1) Setup pointers to SSDT memory location
3645// (2) Create SSDT Definition Block
3646// (2.1) Save pointer to SSDT package length and checksum fields
3647// (2.2) Create variables in SSDT scope
3648// (3) For each logical processor CPUn
3649// (3.1) Create scope for CPUn
3650// (3.2) Create variables in CPU scope
3651// (3.3) Create _OSC and/or _PDC Methods
3652// (3.4) Create P-state related structures
3653// (3.4.1) Create _PSS Method
3654// (3.4.2) Create _PCT Object
3655// (3.4.3) Create _PPC Method
3656// (3.4.4) Create _PSD Object
3657// (3.5) Create C-state related structures
3658// (3.5.1) Create _CST Method
3659// (3.5.2) Create _CSD Method
3660// (3.6) Create T-state related structures (Optional)
3661// (3.6.1) Create _TPC Method
3662// (3.6.2) Create _PTC Method
3663// (3.6.3) Create _TSS Method
3664// (3.6.4) Create _TSD Method
3665// (3.7) Update length in CPUn Scope
3666// (4) Update length and checksum in SSDT Definition Block
3667DBG("Attempting to build SSDT\n");
3668
3669U32 pstates_enabled = 0;
3670U32 cstates_enabled = 0;
3671CPU_DETAILS cpu;
3672cpu.max_ratio_as_mfg = 0;
3673cpu.package_power_limit = 0;
3674
3675U8 ACPI_COORD_TYPE = ACPI_COORD_TYPE_SW_ANY; // default
3676ACPI_TABLE_SSDT *SsdtPointer = (void*)0ul;
3677
3678// Desired state for providing alternate ACPI _CST structure using MWAIT
3679// extensions
3680// 1= Alternate _CST using MWAIT extension is enabled for OSPM use
3681// 0= Alternate _CST using MWAIT extension is disabled for OSPM use
3682bool enable_mwait = 1;
3683
3684// (1) Setup pointers to SSDT memory location
3685void * current = buffer;
3686void * end = (U8 *)buffer + bufferSize;
3687
3688// Confirm a valid SSDT buffer was provided
3689if (!buffer)
3690{
3691printf("Error: Invalid Buffer Address for SSDT\n");
3692return(0);
3693}
3694
3695// Confirm a valid SSDT buffer length was provided
3696if (!bufferSize)
3697{
3698printf("Error: Invalid Buffer Length for SSDT\n");
3699return(0);
3700}
3701
3702if (madt_info == (void*) 0ul)
3703{
3704return(0);
3705}
3706
3707if (dsdt == (void*) 0ul)
3708{
3709return(0);
3710}
3711
3712// Check that we have a valid cpu_map (if it's not already done, it will try to generate it)
3713if (generate_cpu_map_from_acpi(dsdt) != 0)
3714{
3715return(0);
3716}
3717
3718collect_cpu_info(&cpu);
3719
3720if (enable_cstates && pmbase)
3721{
3722DBG("Building Cstate Info\n");
3723
3724cstates_enabled = BuildCstateInfo(&cpu, pmbase);
3725if (cstates_enabled)
3726{
3727getBoolForKey(KEnableMwait, &enable_mwait, &bootInfo->chameleonConfig);
3728}
3729}
3730
3731if (enable_pstates)
3732{
3733DBG("Building Pstate Info\n");
3734
3735pstates_enabled = BuildPstateInfo(&cpu);
3736if (pstates_enabled)
3737{
3738const char *str = getStringForKey(KAcpiCoordType, &bootInfo->chameleonConfig);
3739U8 tmp = (U8)strtoul(str, NULL,16);
3740if ((tmp == ACPI_COORD_TYPE_SW_ALL) || (tmp == ACPI_COORD_TYPE_SW_ANY) || (tmp == ACPI_COORD_TYPE_HW_ALL) )
3741{
3742ACPI_COORD_TYPE = tmp;
3743}
3744}
3745}
3746#if BUILD_ACPI_TSS
3747 U32 tstates_enabled = 0;
3748 if (enable_tstates)
3749{
3750DBG("Building Pstate Info\n");
3751
3752tstates_enabled = BuildTstateInfo(&cpu);
3753}
3754#endif
3755
3756SsdtPointer = (ACPI_TABLE_SSDT *)buffer;
3757
3758// (2) Create SSDT Definition Block
3759// (2.1) Save pointer to SSDT package length and checksum fields
3760current = buildTableHeader(current, NAMESEG("SSDT"), NAMESEG64("PPM RCM "));
3761
3762// Check to confirm no SSDT buffer overflow
3763if ( (U8 *)current > (U8 *)end )
3764{
3765printf("Error: SSDT Buffer Length exceeded available space \n");
3766return(0);
3767}
3768
3769// (3) For each logical processor CPUn
3770// We will use the dsdt datas in place of madt,for the cpu(s) detection.
3771// 'Cause most users use the dsdt table to change the numbers of cpu(s) that the OS and the bootloader should use,
3772// Note also that due to chameleon limit we use the same package per each cpu(s) for all objects and methods
3773// (package detection for each cpu(s) is still in progress)
3774{
3775U32 lapic_index;
3776for (lapic_index=0; lapic_index < cpu_map_count; lapic_index++)
3777{
3778// (3.1) Create scope for CPUn
3779ACPI_SCOPE * scope = current;
3780
3781{
3782DBG("Building CPU Scope\n");
3783U32 cpu_namespace = (cpuNamespace == CPU_NAMESPACE_SB) ? NAMESEG("_SB_") : NAMESEG("_PR_");
3784PROCESSOR_NUMBER_TO_NAMESEG * namepath = &cpu_map[lapic_index];
3785current = buildCpuScope (current, cpu_namespace, namepath );
3786}
3787
3788// Check to confirm no SSDT buffer overflow
3789if ( (U8 *)current > (U8 *)end )
3790{
3791printf("Error: SSDT Buffer Length exceeded available space \n");
3792return(0);
3793}
3794
3795// (3.2) Create variables in CPU scope
3796DBG("Creating variables in CPU scope\n");// Build Type variable used to store PDC capabilities
3797current = buildNamedDword(current, NAMESEG("TYPE"), 0);
3798
3799// Build PSEN variable used to store state of P-State Enable setup option
3800current = buildNamedDword(current, NAMESEG("PSEN"), pstates_enabled);
3801
3802// Build CSEN variable used to store state of C-State Enable setup option
3803current = buildNamedDword(current, NAMESEG("CSEN"), cstates_enabled);
3804
3805// Build MWOS variable used to store state of MWAIT OS setup option
3806current = buildNamedDword(current, NAMESEG("MWOS"), (U32)(enable_mwait&&cpu.mwait_supported));
3807
3808// (3.3) Create _OSC and/or _PDC Methods
3809{
3810// Build _PDC method
3811DBG("Building PDC method\n");
3812current = buildPDC(current);
3813
3814// Check to confirm no SSDT buffer overflow
3815if ( (U8 *)current > (U8 *)end )
3816{
3817printf("Error: SSDT Buffer Length exceeded available space \n");
3818return(0);
3819}
3820
3821// Build _OSC method
3822DBG("Building _OSC method\n");
3823current = buildOSC(current);
3824
3825// Check to confirm no SSDT buffer overflow
3826if ( (U8 *)current > (U8 *)end )
3827{
3828printf("Error: SSDT Buffer Length exceeded available space \n");
3829return(0);
3830}
3831}
3832
3833// (3.4) Create P-state related structures
3834if (pstates_enabled == 1)
3835{
3836// (3.4.1) Create _PSS Method
3837{
3838DBG("Building _PSS method\n");
3839PKG_PSTATES * pkg_pstates = &cpu.pkg_pstates;
3840current = buildPSS(current, pkg_pstates);
3841}
3842
3843// Check to confirm no SSDT buffer overflow
3844if ( (U8 *)(current) > (U8 *)end )
3845{
3846printf("Error: SSDT Buffer Length exceeded available space \n");
3847return(0);
3848}
3849
3850// (3.4.2) Create _PCT Object
3851DBG("Building _PCT Object\n");
3852current = buildPCT(current);
3853
3854// Check to confirm no SSDT buffer overflow
3855if ( (U8 *)(current) > (U8 *)end )
3856{
3857printf("Error: SSDT Buffer Length exceeded available space \n");
3858return(0);
3859}
3860
3861// (3.4.3) Create _PPC Method
3862DBG("Building _PPC Method\n");
3863current = buildPPC(current);
3864
3865// Check to confirm no SSDT buffer overflow
3866if ( (U8 *)(current) > (U8 *)end )
3867{
3868printf("Error: SSDT Buffer Length exceeded available space \n");
3869return(0);
3870}
3871
3872// (3.4.4) Create PSD with hardware coordination
3873{
3874DBG("Building _PSD Method\n");
3875U32 domain = madt_info->lapic[lapic_index].pkg_index;
3876
3877 // In this (bad?) implementation we use the nb of cpu found in the dsdt
3878U32 cpusInDomain = cpu_map_count;
3879current = buildPSD(current, domain, cpusInDomain, ACPI_COORD_TYPE);
3880}
3881
3882// Check to confirm no SSDT buffer overflow
3883if ( (U8 *)(current) > (U8 *)end )
3884{
3885printf("Error: SSDT Buffer Length exceeded available space \n");
3886return(0);
3887}
3888}
3889
3890// (3.5) Create C-state related structures
3891if (cstates_enabled == 1)
3892{
3893{
3894PKG_CSTATES * mwait_pkg_cstates = &cpu.pkg_mwait_cstates;
3895PKG_CSTATES * io_pkg_cstates = &cpu.pkg_io_cstates;
3896
3897// Build CST
3898DBG("Building _CST Method\n");
3899current = buildCST(current, mwait_pkg_cstates, io_pkg_cstates);
3900}
3901
3902#if BUILD_ACPI_CSD
3903 {
3904 // Use core_apic_id as domain
3905 U32 domain = lapic->core_apic_id;
3906
3907 // In this (bad?) implementation we use the nb of cpu found in the dsdt
3908 U32 cpusInDomain = cpu_map_count;
3909
3910 // Create CSD
3911 current = buildCSD(current, domain, cpusInDomain, io_pkg_cstates);
3912 }
3913#endif
3914
3915// Check to confirm no SSDT buffer overflow
3916if ( (U8 *)(current) > (U8 *)end )
3917{
3918printf("Error: SSDT Buffer Length exceeded available space \n");
3919return(0);
3920}
3921}
3922#if BUILD_ACPI_TSS
3923 // (3.6) Create T-state related structures
3924 if (tstates_enabled == 1)
3925 {
3926 // (3.6.1) Create _TPC Method
3927 current = buildTPC(current);
3928
3929 // (3.6.2) Create _PTC Method
3930 current = buildPTC(current);
3931
3932 // (3.6.3) Create _TSS Method
3933 {
3934 PKG_TSTATES * pkg_tstates = &cpu.pkg_tstates;
3935 current = buildTSS(current, pkg_tstates);
3936 }
3937
3938 // (3.6.4) Create _TSD Method
3939 {
3940 LAPIC_INFO * lapic = &madt_info.lapic[lapic_index];
3941
3942 // Use core_apic_id as domain
3943 U32 domain = lapic->core_apic_id;
3944
3945 // In this (bad?) implementation we use the nb of cpu found in the dsdt
3946 U32 cpusInDomain = cpu_map_count;
3947
3948 current = buildTSD(current, domain, cpusInDomain);
3949 }
3950 }
3951#endif
3952// (3.7) Update length in CPUn Scope
3953setPackageLength(&scope->pkgLength, (U8 *)current - (U8 *)&scope->pkgLength);
3954
3955} // End for
3956
3957// (4) Update length and checksum in SSDT Definition Block
3958{
3959DBG("Updating length and checksum in SSDT Definition Block\n");
3960
3961SsdtPointer->Header.Length = (U8 *)current - (U8 *)SsdtPointer;
3962SetChecksum(&SsdtPointer->Header);
3963}
3964
3965// Check to confirm no SSDT buffer overflow
3966if ( (U8 *)current > (U8 *)end )
3967{
3968printf("Error: SSDT Buffer Length exceeded available space \n");
3969return(0);
3970}
3971
3972} // End build SSDT
3973
3974} // SSDT
3975
3976return(1);
3977}
3978
3979#if UNUSED
3980static ACPI_TABLE_FACS* generate_facs(bool updatefacs )
3981{
3982 ACPI_TABLE_FACS* facs_mod=(ACPI_TABLE_FACS *)AllocateKernelMemory(sizeof(ACPI_TABLE_FACS));
3983if (!facs_mod)
3984{
3985printf("Unable to allocate kernel memory for facs mod\n");
3986return (void*)0ul;
3987}
3988 bzero(facs_mod, sizeof(ACPI_TABLE_FACS));
3989
3990ACPI_TABLE_FACS * FacsPointer =(acpi_tables.FacsPointer64 != (void *)0ul) ?
3991(ACPI_TABLE_FACS *)acpi_tables.FacsPointer64 : (ACPI_TABLE_FACS *)acpi_tables.FacsPointer;
3992
3993 memcpy(facs_mod, FacsPointer , FacsPointer->Length);
3994 facs_mod->Length = sizeof(ACPI_TABLE_FACS);
3995
3996if (FacsPointer->Length < sizeof(ACPI_TABLE_FACS))
3997{
3998facs_mod->FirmwareWakingVector = 0;
3999facs_mod->GlobalLock = 0;
4000facs_mod->Flags = 0;
4001}
4002
4003 if (updatefacs && FacsPointer->Version < 2)
4004{
4005if (FacsPointer->Version > 0)
4006{
4007facs_mod->XFirmwareWakingVector = FacsPointer->XFirmwareWakingVector;
4008}
4009else
4010{
4011facs_mod->XFirmwareWakingVector = (U64)facs_mod->FirmwareWakingVector;
4012}
4013
4014facs_mod->Version = 2; /* ACPI 1.0: 0, ACPI 2.0/3.0: 1, ACPI 4.0: 2 */
4015
4016}
4017
4018 return facs_mod;
4019}
4020#endif
4021
4022static ACPI_GENERIC_ADDRESS FillGASStruct(U32 Address, U8 Length)
4023{
4024ACPI_GENERIC_ADDRESS TmpGAS;
4025
4026TmpGAS.SpaceId = 1; /* I/O Address */
4027
4028if (Address == 0)
4029{
4030TmpGAS.BitWidth = 0;
4031}
4032else
4033{
4034TmpGAS.BitWidth = Length * 8;
4035}
4036
4037TmpGAS.BitOffset = 0;
4038TmpGAS.AccessWidth = 0; /* Not set for Legacy reasons... */
4039TmpGAS.Address = (U64)Address;
4040
4041return (TmpGAS);
4042}
4043
4044static ACPI_TABLE_FADT *
4045patch_fadt(ACPI_TABLE_FADT *fadt, ACPI_TABLE_DSDT *new_dsdt, bool UpdateFADT)
4046{
4047ACPI_TABLE_FADT *fadt_mod = (void*)0;
4048bool fadt_rev2_needed = false;
4049bool fix_restart = false;
4050const char * value;
4051
4052// Restart Fix
4053if (Platform.CPU.Vendor == CPUID_VENDOR_INTEL)
4054{
4055fix_restart = true;
4056getBoolForKey(kRestartFix, &fix_restart, &bootInfo->chameleonConfig);
4057
4058} else {
4059verbose ("Not an Intel platform: Restart Fix disabled !!!\n");
4060}
4061
4062if (fix_restart)
4063fadt_rev2_needed = true;
4064
4065// Allocate new fadt table
4066if (UpdateFADT)
4067{
4068 if (fadt->Header.Length < 0xF4)
4069 {
4070 fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(0xF4);
4071 if (!fadt_mod)
4072 {
4073 printf("Unable to allocate kernel memory for fadt mod\n");
4074 return (void*)0ul;
4075 }
4076 bzero(fadt_mod, 0xF4);
4077 memcpy(fadt_mod, fadt, fadt->Header.Length);
4078 fadt_mod->Header.Length = 0xF4;
4079
4080}
4081else
4082{
4083fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(fadt->Header.Length);
4084if (!fadt_mod)
4085{
4086printf("Unable to allocate kernel memory for fadt mod\n");
4087return (void*)0ul;
4088}
4089memcpy(fadt_mod, fadt, fadt->Header.Length);
4090}
4091
4092
4093//fadt_mod->Header.Revision = 0x04; // FADT rev 4
4094fadt_mod->ResetRegister = FillGASStruct(0, 0);
4095fadt_mod->ResetValue = 0;
4096fadt_mod->Reserved4[0] = 0;
4097fadt_mod->Reserved4[1] = 0;
4098fadt_mod->Reserved4[2] = 0;
4099
4100 fadt_mod->XPm1aEventBlock = FillGASStruct(fadt_mod->Pm1aEventBlock, fadt_mod->Pm1EventLength);
4101fadt_mod->XPm1bEventBlock = FillGASStruct(fadt_mod->Pm1bEventBlock, fadt_mod->Pm1EventLength);
4102fadt_mod->XPm1aControlBlock = FillGASStruct(fadt_mod->Pm1aControlBlock, fadt_mod->Pm1ControlLength);
4103fadt_mod->XPm1bControlBlock = FillGASStruct(fadt_mod->Pm1bControlBlock, fadt_mod->Pm1ControlLength);
4104fadt_mod->XPm2ControlBlock = FillGASStruct(fadt_mod->Pm2ControlBlock, fadt_mod->Pm2ControlLength);
4105fadt_mod->XPmTimerBlock = FillGASStruct(fadt_mod->PmTimerBlock, fadt_mod->PmTimerLength);
4106fadt_mod->XGpe0Block = FillGASStruct(fadt_mod->Gpe0Block, fadt_mod->Gpe0BlockLength);
4107fadt_mod->XGpe1Block = FillGASStruct(fadt_mod->Gpe1Block, fadt_mod->Gpe1BlockLength);
4108 if (fadt->Header.Revision < 4)
4109{
4110fadt_mod->Header.Revision = 0x04; // FADT rev 4
4111verbose("Converted ACPI V%d FADT to ACPI V4 FADT\n", fadt->Header.Revision);
4112
4113}
4114}
4115else
4116{
4117
4118if (fadt_rev2_needed)
4119{
4120if (fadt->Header.Length < 0x84 )
4121{
4122fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(0x84);
4123if (!fadt_mod)
4124{
4125printf("Unable to allocate kernel memory for fadt mod\n");
4126return (void*)0ul;
4127}
4128bzero(fadt_mod, 0x84);
4129memcpy(fadt_mod, fadt, fadt->Header.Length);
4130fadt_mod->Header.Length = 0x84;
4131}
4132else
4133{
4134fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(fadt->Header.Length);
4135if (!fadt_mod)
4136{
4137printf("Unable to allocate kernel memory for fadt mod\n");
4138return (void*)0ul;
4139}
4140memcpy(fadt_mod, fadt, fadt->Header.Length);
4141}
4142
4143if (fadt->Header.Revision < 2)
4144{
4145fadt_mod->Header.Revision = 0x02; // FADT rev 2 (ACPI 1.0B MS extensions)
4146verbose("Converted ACPI V%d FADT to ACPI V2 FADT\n", fadt->Header.Revision );
4147}
4148}
4149else
4150{
4151if (fadt->Header.Length < 0x74 )
4152{
4153fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(0x74);
4154if (!fadt_mod)
4155{
4156printf("Unable to allocate kernel memory for fadt mod\n");
4157return (void*)0ul;
4158}
4159bzero(fadt_mod, 0x74);
4160memcpy(fadt_mod, fadt, fadt->Header.Length);
4161fadt_mod->Header.Length = 0x74;
4162fadt_mod->Header.Revision = 0x01;
4163verbose("Warning: ACPI FADT length was < 0x74 which is the minimum for the ACPI FADT V1 specification, \n", fadt->Header.Revision );
4164verbose(" trying to convert it to Version 1. \n");
4165
4166}
4167else
4168{
4169fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(fadt->Header.Length);
4170if (!fadt_mod)
4171{
4172printf("Unable to allocate kernel memory for fadt mod\n");
4173return (void*)0ul;
4174}
4175memcpy(fadt_mod, fadt, fadt->Header.Length);
4176}
4177}
4178}
4179bool intelfadtspec = true;
4180U8 Type = PMProfileError;
4181// Determine system type / PM_Model
4182
4183// Fix System-type if needed (should never happen)
4184if (Platform.Type > MaxSupportedPMProfile)
4185{
4186if(fadt_mod->PreferredProfile <= MaxSupportedPMProfile)
4187 Platform.Type = fadt_mod->PreferredProfile;// get the fadt if correct
4188else
4189Platform.Type = 1;/* Set a fixed value (Desktop) */
4190}
4191
4192// If needed, set System-type from PM_Profile (if valid) else set PM_Profile with a fixed the System-type
4193// Give prior to the FADT pm profile, allow to also control this value with a patched FADT table
4194if (fadt_mod->PreferredProfile != Platform.Type)
4195{
4196bool val = false;
4197getBoolForKey("PreferInternalProfileDetect", &val, &bootInfo->chameleonConfig); // if true Give prior to the profile resolved trought the CPU model
4198
4199//val = get_env(envIsServer) ;
4200
4201if (fadt_mod->PreferredProfile <= MaxSupportedPMProfile && !val)
4202{
4203Platform.Type = fadt_mod->PreferredProfile;
4204}
4205else
4206{
4207fadt_mod->PreferredProfile = (U8)Platform.Type;
4208}
4209
4210}
4211
4212// Set PM_Profile and System-type if user wanted this value to be forced
4213if ( (value=getStringForKey("SystemType", &bootInfo->chameleonConfig))!=NULL)
4214{
4215if ((Type = (unsigned char) strtoul(value, NULL, 10) ) <= MaxSupportedPMProfile)
4216{
4217if (fadt_mod->PreferredProfile != Type)
4218{
4219verbose("FADT: changing Preferred_PM_Profile from %d to %d\n", fadt->PreferredProfile, Type);
4220
4221Platform.Type = (fadt_mod->PreferredProfile = Type);
4222}
4223else
4224{
4225DBG("FADT: Preferred_PM_Profile was already set to %d, no need to be changed\n",Type);
4226}
4227
4228} else printf("Error: system-type must be 0..6. Defaulting to %d !\n", (U8)Platform.Type);
4229}
4230
4231getBoolForKey(KIntelFADT, &intelfadtspec, &bootInfo->chameleonConfig);
4232if ((pmbase == 0) && (cpu_map_error == 0) && (intelfadtspec == true))
4233{
4234ACPI_TABLE_DSDT *DsdtPointer ;
4235if (new_dsdt != (void*)0ul)
4236DsdtPointer = new_dsdt;
4237else if ((fadt_mod->Header.Revision >= 3) && (fadt_mod->XDsdt != 0ul))
4238DsdtPointer = (ACPI_TABLE_DSDT *)((U32)fadt_mod->XDsdt);
4239else
4240DsdtPointer = (ACPI_TABLE_DSDT *)fadt_mod->Dsdt;
4241
4242generate_cpu_map_from_acpi(DsdtPointer);
4243}
4244
4245// Patch DSDT Address if we have loaded a DSDT table
4246if(new_dsdt != (void*)0ul)
4247fadt_mod->Dsdt=(U32)new_dsdt;
4248
4249fadt_mod->Facs= fadt->Facs;
4250//fadt_mod->Facs=(U32)generate_facs(false);
4251
4252// Patch FADT to fix restart
4253if (fadt_mod->Header.Revision >= 2 && fix_restart)
4254{
4255 fadt_mod->Flags|= 0x400;
4256
4257int type = PCI_RESET_TYPE;
4258getIntForKey(KResetType, &type, &bootInfo->chameleonConfig);
4259if (type == KEYBOARD_RESET_TYPE)
4260{
4261//Azi: keyboard reset; http://forum.voodooprojects.org/index.php/topic,1056.msg9802.html#msg9802
4262fadt_mod->ResetRegister = FillGASStruct(0x64, 1);
4263fadt_mod->ResetValue = 0xfe;
4264}
4265else
4266{
4267fadt_mod->ResetRegister = FillGASStruct(0x0cf9, 1);
4268fadt_mod->ResetValue = 0x06;
4269}
4270verbose("FADT: Restart Fix applied (Type : %s) !\n", (type == 0) ? "PCI": "KEYBOARD");
4271}
4272
4273 if (fadt_mod->Header.Revision >= 3)
4274{
4275
4276
4277 if (UpdateFADT)
4278{
4279
4280//fadt_mod->XFacs= (U64)((U32)generate_facs(true));
4281 fadt_mod->XFacs=(U64)fadt->Facs;
4282
4283 }
4284else
4285{
4286fadt_mod->XFacs=(U64)fadt->XFacs;
4287}
4288
4289
4290 if(new_dsdt != (void*)0ul)
4291 fadt_mod->XDsdt=((U64)(U32)new_dsdt);
4292else if (UpdateFADT)
4293 fadt_mod->XDsdt=(U64)fadt_mod->Dsdt;
4294
4295
4296//safe_set_env(envHardwareSignature,((ACPI_TABLE_FACS *)((U32)fadt_mod->XFacs))->HardwareSignature);
4297
4298
4299 }
4300#if 0
4301else
4302{
4303
4304safe_set_env(envHardwareSignature,((ACPI_TABLE_FACS *)fadt_mod->Facs)->HardwareSignature);
4305
4306 }
4307
4308
4309DBG("setting hardware_signature to %x \n",(U32)get_env(envHardwareSignature));
4310#endif
4311
4312
4313
4314if (pmbase && (intelfadtspec == true))
4315ProcessFadt(fadt_mod, pmbase); // The checksum correction will be done by ProcessFadt
4316else
4317SetChecksum(&fadt_mod->Header); // Correct the checksum
4318
4319return fadt_mod;
4320}
4321
4322static U32 process_xsdt (ACPI_TABLE_RSDP *rsdp_mod , U32 *new_table_list)
4323{
4324TagPtr DropTables_p = 0;
4325 int DropTables_tag_count = 0;
4326
4327 if (bootInfo->chameleonConfig.dictionary)
4328 {
4329 DropTables_p = XMLCastDict(XMLGetProperty(bootInfo->chameleonConfig.dictionary, (const char*)"ACPIDropTables"));
4330 if (DropTables_p) DropTables_tag_count = XMLTagCount(DropTables_p) ;
4331 }
4332
4333U32 new_table = 0ul;
4334U8 new_table_index = 0, table_added = 0;
4335ACPI_TABLE_XSDT *xsdt = (void*)0ul, *xsdt_mod = (void*)0ul;
4336ACPI_TABLE_RSDT *rsdt_conv= (void *)0ul;
4337
4338// FIXME: handle 64-bit address correctly
4339
4340xsdt=(ACPI_TABLE_XSDT *)acpi_tables.XsdtPointer;
4341
4342verbose("* Processing XSDT: \n");
4343
4344DBG(" XSDT @%x, Length=%d\n", (U32)xsdt,
4345xsdt->Header.Length);
4346
4347if (xsdt != (void *)0ul)
4348{
4349U32 dropoffset=0, index;
4350table_added = 0;
4351
4352xsdt_mod=(ACPI_TABLE_XSDT *)AllocateKernelMemory(xsdt->Header.Length);
4353if (!xsdt_mod)
4354{
4355printf("Unable to allocate kernel memory for xsdt mod\n");
4356return (0);
4357}
4358bzero(xsdt_mod, xsdt->Header.Length);
4359memcpy(&xsdt_mod->Header, &xsdt->Header, sizeof(ACPI_TABLE_HEADER));
4360
4361U32 num_tables=get_num_tables64(xsdt);
4362
4363for (index = 0; index < num_tables; index++)
4364{
4365
4366U64 ptr = xsdt->TableOffsetEntry[index];
4367
4368{
4369if (ptr > ULONG_MAX)
4370{
4371#if DEBUG_ACPI
4372printf("Warning xsdt->TableOffsetEntry[%d]: Beyond addressable memory in this CPU mode, ignored !!!\n",index);
4373#endif
4374continue;
4375}
4376
4377int method = 0;
4378getIntForKey(kAcpiMethod, &method, &bootInfo->chameleonConfig);
4379
4380
4381if (method != 0x2)
4382{
4383if (GetChecksum(((ACPI_TABLE_HEADER *) (unsigned long)ptr),
4384((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Length) != 0)
4385{
4386#if DEBUG_ACPI
4387printf("Warning xsdt->TableOffsetEntry[%d]: Invalide checksum, ignored !!!\n",index);
4388#endif
4389continue;
4390}
4391}
4392
4393}
4394
4395xsdt_mod->TableOffsetEntry[index-dropoffset]=ptr;
4396
4397char tableSig[5];
4398strlcpy(tableSig, (char*)((U32)ptr), sizeof(tableSig));
4399
4400DBG("** Processing %s,", tableSig );
4401
4402DBG(" @%x, Length=%d\n", (U32)ptr,
4403((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Length);
4404
4405{
4406bool oem = false;
4407char oemOption[OEMOPT_SIZE];
4408sprintf(oemOption, "oem%s",tableSig );
4409if (getBoolForKey(oemOption, &oem, &bootInfo->chameleonConfig) && oem) // This method don't work for DSDT and FACS
4410{
4411
4412DBG(" %s required\n", oemOption);
4413
4414if (get_new_table_in_list(new_table_list,(*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature), &new_table_index) != (void*)0ul)
4415new_table_list[new_table_index] = 0ul; // This way new table will not be added to the new rsdt list !!
4416
4417continue;
4418}
4419}
4420
4421 if ((DropTables_tag_count > 0) && DropTables_p)
4422{
4423TagPtr match_drop = XMLGetProperty(DropTables_p, (const char*)tableSig);
4424if ( match_drop )
4425{
4426char *tmp = XMLCastString(match_drop);
4427if (tmp && (strcmp(tmp,"No") != 0))
4428{
4429dropoffset++;
4430DBG(" %s table dropped\n",tableSig);
4431continue;
4432}
4433}
4434}
4435
4436{
4437if ((new_table = (U32)get_new_table_in_list(new_table_list,(*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature), &new_table_index)) != 0ul)
4438{
4439DBG(" Found replacement for table %s\n",tableSig);
4440xsdt_mod->TableOffsetEntry[index-dropoffset]=(U64)new_table;
4441new_table_list[new_table_index] = 0ul; // table replaced !!
4442continue;
4443}
4444}
4445
4446}
4447
4448
4449{
4450U8 i;
4451for (i = 0; i< (MAX_ACPI_TABLE + RESERVED_AERA); i++)
4452{
4453if (new_table_list[i] != 0ul)
4454{
4455#if DEBUG_ACPI
4456ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;
4457printf("Adding table : ");
4458print_nameseg(*(U32 *) (table_array[i]->Signature));
4459printf("\n");
4460#endif
4461xsdt_mod->TableOffsetEntry[index-dropoffset]=(U64)new_table_list[i];
4462table_added++;
4463index++;
4464}
4465}
4466}
4467
4468// Correct the checksum of XSDT
4469xsdt_mod->Header.Length-=8*dropoffset;
4470xsdt_mod->Header.Length+=8*table_added;
4471
4472SetChecksum(&xsdt_mod->Header);
4473
4474update_rsdp_with_xsdt(rsdp_mod, xsdt_mod);
4475
4476verbose("* Creating new RSDT from XSDT table\n");
4477
4478rsdt_conv = (ACPI_TABLE_RSDT *)gen_alloc_rsdt_from_xsdt(xsdt_mod);
4479
4480if (rsdt_conv != (void*)0ul)
4481{
4482#if DEBUG_ACPI
4483DBG("Attempting to update RSDP with RSDT \n");
4484{
4485U32 ret = update_rsdp_with_rsdt(rsdp_mod, rsdt_conv);
4486if (ret)
4487DBG("RSDP update with RSDT successfully !!! \n");
4488}
4489#else
4490update_rsdp_with_rsdt(rsdp_mod, rsdt_conv);
4491#endif
4492}
4493
4494}
4495else
4496{
4497DBG("About to drop XSDT\n");
4498
4499/*FIXME: Now we just hope that if MacOS doesn't find XSDT it reverts to RSDT.
4500 * A Better strategy would be to generate
4501 */
4502
4503rsdp_mod->XsdtPhysicalAddress=0xffffffffffffffffLL;
4504verbose("XSDT not found or XSDT incorrect\n");
4505}
4506return (1);
4507
4508}
4509
4510static U32 process_rsdt(ACPI_TABLE_RSDP *rsdp_mod , bool gen_xsdt, U32 *new_table_list)
4511{
4512TagPtr DropTables_p = 0;
4513 int DropTables_tag_count = 0;
4514
4515 if (bootInfo->chameleonConfig.dictionary)
4516 {
4517 DropTables_p = XMLCastDict(XMLGetProperty(bootInfo->chameleonConfig.dictionary, (const char*)"ACPIDropTables"));
4518 if (DropTables_p) DropTables_tag_count = XMLTagCount(DropTables_p) ;
4519 }
4520
4521U32 new_table = 0ul;
4522U8 new_table_index = 0, table_added = 0;
4523U32 dropoffset=0, index;
4524ACPI_TABLE_RSDT *rsdt = (void *)0ul, *rsdt_mod= (void *)0ul;
4525ACPI_TABLE_XSDT *xsdt_conv = (void *)0ul;
4526
4527rsdt=(ACPI_TABLE_RSDT *)acpi_tables.RsdtPointer;
4528
4529rsdt_mod=(ACPI_TABLE_RSDT *)AllocateKernelMemory(rsdt->Header.Length);
4530
4531if (!rsdt_mod)
4532{
4533printf("Unable to allocate kernel memory for rsdt mod\n");
4534return (0);
4535}
4536
4537bzero(rsdt_mod, rsdt->Header.Length);
4538memcpy (&rsdt_mod->Header, &rsdt->Header, sizeof(ACPI_TABLE_HEADER));
4539
4540 // Compute number of table pointers included in RSDT
4541U32 num_tables = get_num_tables(rsdt);
4542
4543verbose("* Processing RSDT: \n");
4544
4545DBG(" RSDT @%x, Length %d\n",rsdt, rsdt->Header.Length);
4546
4547ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) rsdt->TableOffsetEntry;
4548
4549for (index = 0; index < num_tables; index++)
4550{
4551
4552{
4553
4554int method = 0;
4555getIntForKey(kAcpiMethod, &method, &bootInfo->chameleonConfig);
4556
4557
4558if (method != 0x2)
4559{
4560if (GetChecksum(table_array[index], table_array[index]->Length) != 0)
4561{
4562#if DEBUG_ACPI
4563printf("Warning rsdt->TableOffsetEntry[%d]: Invalide checksum, ignored !!!\n",index);
4564#endif
4565continue;
4566}
4567}
4568
4569}
4570
4571rsdt_mod->TableOffsetEntry[index-dropoffset]=rsdt->TableOffsetEntry[index];
4572
4573char tableSig[5];
4574strlcpy(tableSig, (char*)(rsdt->TableOffsetEntry[index]), sizeof(tableSig));
4575
4576DBG("** Processing %s,", tableSig );
4577
4578DBG(" @%x, Length=%d\n", (U32)table_array[index],
4579table_array[index]->Length);
4580
4581{
4582bool oem = false;
4583char oemOption[OEMOPT_SIZE];
4584sprintf(oemOption, "oem%s",tableSig );
4585if (getBoolForKey(oemOption, &oem, &bootInfo->chameleonConfig) && oem) // This method don't work for DSDT and FACS
4586{
4587DBG(" %s required\n", oemOption);
4588
4589if (get_new_table_in_list(new_table_list,(*(U32 *) (table_array[index]->Signature)), &new_table_index) != (void*)0ul )
4590new_table_list[new_table_index] = 0ul; // This way new table will not be added to the new rsdt list !!
4591
4592continue;
4593}
4594}
4595
4596 if ((DropTables_tag_count > 0) && DropTables_p)
4597{
4598TagPtr match_drop = XMLGetProperty(DropTables_p, (const char*)tableSig);
4599if ( match_drop )
4600{
4601char *tmp = XMLCastString(match_drop);
4602if (strcmp(tmp,"No") != 0)
4603{
4604dropoffset++;
4605DBG(" %s table dropped\n",tableSig);
4606continue;
4607}
4608}
4609}
4610
4611{
4612if ((new_table = (U32)get_new_table_in_list(new_table_list,(*(U32 *) (table_array[index]->Signature)), &new_table_index)) != 0ul)
4613{
4614DBG(" Found replacement for table %s\n",tableSig);
4615
4616rsdt_mod->TableOffsetEntry[index-dropoffset]=new_table;
4617new_table_list[new_table_index] = 0ul; // table replaced !!
4618continue;
4619}
4620}
4621
4622}
4623DBG("\n");
4624
4625{
4626U8 i;
4627for (i = 0; i< (MAX_ACPI_TABLE + RESERVED_AERA); i++)
4628{
4629if (new_table_list[i] != 0ul)
4630{
4631#if DEBUG_ACPI
4632ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;
4633printf("Adding table : ");
4634print_nameseg(*(U32 *) (table_array[i]->Signature));
4635printf("\n");
4636#endif
4637rsdt_mod->TableOffsetEntry[index-dropoffset]=new_table_list[i];
4638table_added++;
4639index++;
4640}
4641}
4642}
4643
4644// Correct the checksum of RSDT
4645rsdt_mod->Header.Length-=4*dropoffset;
4646rsdt_mod->Header.Length+=4*table_added;
4647
4648DBG("RSDT: Original checksum %d\n", rsdt_mod->Header.Checksum);
4649
4650SetChecksum(&rsdt_mod->Header);
4651
4652DBG("New checksum %d at %x\n", rsdt_mod->Header.Checksum,rsdt_mod);
4653
4654update_rsdp_with_rsdt(rsdp_mod, rsdt_mod);
4655
4656if (gen_xsdt)
4657{
4658verbose("* Creating new XSDT from RSDT table\n");
4659xsdt_conv = (ACPI_TABLE_XSDT *)gen_alloc_xsdt_from_rsdt(rsdt_mod);
4660
4661if (xsdt_conv != (void *)0ul )
4662{
4663#if DEBUG_ACPI
4664DBG("Attempting to update RSDP with XSDT \n");
4665{
4666U32 ret = update_rsdp_with_xsdt(rsdp_mod, xsdt_conv);
4667if (ret)
4668DBG("RSDP update with XSDT successfully !!! \n");
4669}
4670#else
4671update_rsdp_with_xsdt(rsdp_mod, xsdt_conv);
4672#endif
4673
4674}
4675
4676}
4677return (1);
4678}
4679
4680EFI_STATUS setup_Acpi(void)
4681{
4682U8 Revision = 0;
4683
4684 cpu_map_error = 0;
4685 cpu_map_count = 0;
4686 pmbase = 0;
4687
4688 EFI_STATUS Status = EFI_ABORTED;
4689
4690U32 new_table_list[MAX_ACPI_TABLE + RESERVED_AERA]; //max table + reserved aera
4691U8 new_table_index = 0;
4692
4693ACPI_TABLE_DSDT* DsdtPtr = (void *)0ul; // a Pointer to the dsdt table present in fadt_mod
4694
4695ACPI_TABLE_DSDT *new_dsdt = (void *)0ul;// a Pointer to the dsdt file
4696ACPI_TABLE_FADT *fadt_mod = (void *)0ul; // a Pointer to the patched FACP table
4697ACPI_TABLE_FADT *fadt_file = (void *)0ul; // a Pointer to the (non-patched) fadt file
4698ACPI_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
4699ACPI_TABLE_RSDP *rsdp_mod = (void *)0ul, *rsdp_conv= (void *)0ul;
4700
4701U32 rsdplength;
4702
4703bool update_acpi=false, gen_xsdt=false;
4704
4705bool gen_csta=false, gen_psta=false, speed_step=false;
4706bool gen_ssdt=false; // will force to generate ssdt even if gen_csta and gen_psta = false
4707 bool gen_tsta=false;
4708bool oem_dsdt=false, oem_fadt=false;
4709
4710// Find original rsdp
4711if (!FindAcpiTables(&acpi_tables))
4712{
4713printf("Error: AcpiCodec Failed to detect ACPI tables.\n");
4714getchar();
4715return EFI_NOT_FOUND;
4716}
4717
4718{
4719U8 i;
4720
4721for (i=0; i<(MAX_ACPI_TABLE + RESERVED_AERA); i++)
4722{
4723new_table_list[i] = 0ul;
4724}
4725bool tmpval;
4726
4727oem_dsdt=getBoolForKey(kOEMDSDT, &tmpval, &bootInfo->chameleonConfig)&&tmpval;
4728oem_fadt=getBoolForKey(kOEMFADT, &tmpval, &bootInfo->chameleonConfig)&&tmpval;
4729
4730gen_csta=getBoolForKey(kGenerateCStates, &tmpval, &bootInfo->chameleonConfig)&&tmpval;
4731gen_psta=getBoolForKey(kGeneratePStates, &tmpval, &bootInfo->chameleonConfig)&&tmpval;
4732gen_ssdt=getBoolForKey(KForceSSDT, &tmpval, &bootInfo->chameleonConfig)&&tmpval;
4733update_acpi=getBoolForKey(kUpdateACPI, &tmpval, &bootInfo->chameleonConfig)&&tmpval;
4734
4735speed_step=getBoolForKey(kSpeedstep, &tmpval, &bootInfo->chameleonConfig)&&tmpval;
4736turbo_enabled=(U32)getBoolForKey(kCoreTurbo, &tmpval, &bootInfo->chameleonConfig)&&tmpval;
4737#if BUILD_ACPI_TSS
4738gen_tsta=(U32)getBoolForKey(kGenerateTStates, &tmpval, &bootInfo->chameleonConfig)&&tmpval;
4739#endif
4740checkOem=getBoolForKey(kOnlySignedAml, &tmpval, &bootInfo->chameleonConfig)&&tmpval;
4741}
4742
4743{
4744 long ret, length, flags, time;
4745 long long index = 0;
4746 const char * name;
4747
4748U8 i = 0;
4749char dirspec[512];
4750bool acpidir_found = false;
4751
4752ret = GetFileInfo("rd(0,0)/Extra/", "Acpi", &flags, &time);
4753 if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory))
4754{
4755 sprintf(dirspec, "rd(0,0)/Extra/Acpi/");
4756 acpidir_found = true;
4757
4758 }
4759else
4760{
4761
4762 ret = GetFileInfo("/Extra/", "Acpi", &flags, &time);
4763 if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory))
4764{
4765 sprintf(dirspec, "/Extra/Acpi/");
4766 acpidir_found = true;
4767
4768 }
4769else
4770{
4771 ret = GetFileInfo("bt(0,0)/Extra/", "Acpi", &flags, &time);
4772 if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory))
4773{
4774 sprintf(dirspec, "bt(0,0)/Extra/Acpi/");
4775 acpidir_found = true;
4776
4777 }
4778 }
4779 }
4780
4781if (acpidir_found == true)
4782{
4783#if ACPISGN
4784 if (checkOem == true)
4785 {
4786 MakeAcpiSgn();
4787 }
4788#endif
4789
4790 while (1) {
4791 ret = GetDirEntry(dirspec, &index, &name, &flags, &time);
4792 if (ret == -1) break;
4793#if DEBUG_ACPI
4794 printf("testing %s\n", name);
4795#endif
4796 // Make sure this is a directory.
4797 if ((flags & kFileTypeMask) == kFileTypeDirectory) continue;
4798
4799 // Make sure this is a kext.
4800 length = strlen(name);
4801 if (strcmp(name + length - 4, ".aml"))
4802 {
4803#if DEBUG_ACPI
4804 printf("Ignoring %s\n", name);
4805#endif
4806 continue;
4807 }
4808
4809 // Some simple verifications to save time in case of those tables simply named as follow:
4810 if ((strncmp(name, "RSDT", 4) == 0) || (strncmp(name, "rsdt", 4) == 0) ||
4811 (strncmp(name, "XSDT", 4) == 0) || (strncmp(name, "xsdt", 4) == 0) ||
4812 (strncmp(name, "RSDP", 4) == 0) || (strncmp(name, "rsdp", 4) == 0))
4813 {
4814#if DEBUG_ACPI
4815 printf("Ignoring %s\n", name);
4816#endif
4817 continue;
4818 }
4819
4820 if ((strncmp(name, "FACS", 4) == 0) || (strncmp(name, "facs", 4) == 0)) // FACS is not supported
4821 {
4822#if DEBUG_ACPI
4823 printf("Ignoring %s\n", name);
4824#endif
4825 continue;
4826 }
4827
4828 DBG("* Attempting to load acpi table: %s\n", name);
4829 if ( (new_table_list[i]=(U32)loadACPITable(new_table_list,dirspec,name)))
4830 {
4831 if (i < MAX_ACPI_TABLE)
4832 {
4833 i++;
4834 }
4835 else
4836 {
4837 DBG("Max nb of allowed aml files reached, exiting .");
4838 break;
4839 }
4840 }
4841 }
4842
4843 if (i)
4844 {
4845 //sanitize the new tables list
4846 sanitize_new_table_list(new_table_list);
4847
4848 //move to kernel memory
4849 move_table_list_to_kmem(new_table_list);
4850
4851 DBG("New ACPI tables Loaded in memory\n");
4852 }
4853
4854
4855}
4856
4857}
4858#if HARDCODED_DSDT
4859 do {
4860#include "dsdt_PRLSACPI.h"
4861
4862 U8 index = 0;
4863
4864 if ((get_new_table_in_list(new_table_list, NAMESEG("DSDT"), &new_table_index)) != (void*)0ul )
4865 {
4866 index = new_table_index;
4867 }
4868 else
4869 {
4870 U8 empty = get_0ul_index_in_list(new_table_list, false);
4871 if (empty != ACPI_TABLE_LIST_FULL_NON_RESERVED)
4872 {
4873 index = empty;
4874 }
4875 else
4876 {
4877 printf("Error: not enought reserved space in the new acpi list for the Harcoded DSDT table,\n ");
4878 printf(" please increase the RESERVED_AERA\n");
4879
4880 break;
4881 }
4882 }
4883
4884if (index)
4885{
4886
4887ACPI_TABLE_DSDT *tmp = (ACPI_TABLE_DSDT *)DsdtAmlCode;
4888ACPI_TABLE_DSDT *hardcoded_dsdt = (void *)0ul;
4889
4890hardcoded_dsdt = (ACPI_TABLE_DSDT *)AllocateKernelMemory(tmp->Header.Length);
4891memcpy(hardcoded_dsdt, tmp, tmp->Header.Length);
4892new_table_list[index] = (U32)hardcoded_dsdt; // add the patched table to the list
4893}
4894else
4895{
4896printf("Error: not enought reserved space in the new acpi list for the Harcoded DSDT table,\n ");
4897printf(" please increase the RESERVED_AERA\n");
4898
4899break;
4900}
4901 } while (0);
4902#endif
4903if (speed_step)
4904{
4905gen_psta= true;
4906gen_csta= true;
4907}
4908
4909
4910ACPI_TABLE_RSDP *rsdp=(ACPI_TABLE_RSDP *)acpi_tables.RsdPointer;
4911
4912if (rsdp == (void*)0ul || (GetChecksum(rsdp, (rsdp->Revision == 0) ? ACPI_RSDP_REV0_SIZE:sizeof(ACPI_TABLE_RSDP)) != 0) )
4913{
4914printf("Error : ACPI RSD PTR Revision %d checksum is incorrect or table not found \n",rsdp->Revision );
4915return EFI_UNSUPPORTED;
4916}
4917
4918if ((update_acpi) && (rsdp->Revision == 0))
4919{
4920
4921rsdp_conv = (ACPI_TABLE_RSDP *)gen_alloc_rsdp_v2_from_v1(rsdp);
4922if (rsdp_conv != (void *)0ul)
4923{
4924gen_xsdt = true;
4925rsdp = rsdp_conv;
4926verbose("Converted ACPI RSD PTR Revision 0 to Revision 2\n");
4927}
4928
4929}
4930
4931Revision = rsdp->Revision ;
4932rsdplength=(Revision == 2)?rsdp->Length:ACPI_RSDP_REV0_SIZE;
4933
4934DBG("RSDP Revision %d found @%x. Length=%d\n",Revision,rsdp,rsdplength);
4935
4936if (gen_xsdt)
4937{
4938rsdp_mod=rsdp_conv;
4939}
4940else
4941{
4942rsdp_mod=(ACPI_TABLE_RSDP *) AllocateKernelMemory(rsdplength);
4943
4944if (!rsdp_mod) return EFI_OUT_OF_RESOURCES;
4945
4946memcpy(rsdp_mod, rsdp, rsdplength);
4947}
4948
4949
4950if ((fadt_file = (ACPI_TABLE_FADT *)get_new_table_in_list(new_table_list, NAMESEG("FACP"), &new_table_index)) != (void *)0ul)
4951{
4952
4953if (oem_fadt == false)
4954FacpPointer = (ACPI_TABLE_FADT *)fadt_file;
4955
4956new_table_list[new_table_index] = 0ul; // This way, the non-patched table will not be added in our new rsdt/xsdt table list
4957
4958} else
4959FacpPointer = (acpi_tables.FacpPointer64 != (void *)0ul) ?
4960(ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer;
4961
4962#if DEBUG_ACPI
4963if ((FacpPointer != (void *)0ul) || (oem_fadt == false))
4964{
4965printf("FADT found @%x, Length %d\n",FacpPointer, FacpPointer->Header.Length);
4966printf("Attempting to patch FADT entry of %s\n",(acpi_tables.FacpPointer64 != (void *)0ul) ? ACPI_SIG_XSDT : ACPI_SIG_RSDT);
4967}
4968else if (oem_fadt == true)
4969{
4970ACPI_TABLE_FADT * FacpPtr = (acpi_tables.FacpPointer64 != (void *)0ul) ?
4971(ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer;
4972
4973printf("FADT found @%x ( Length %d ) in %s \n",FacpPtr, FacpPtr->Header.Length, (acpi_tables.FacpPointer64 != (void *)0ul) ? ACPI_SIG_XSDT : ACPI_SIG_RSDT);
4974}
4975#endif
4976
4977if ((new_dsdt = (ACPI_TABLE_DSDT *)get_new_table_in_list(new_table_list, NAMESEG("DSDT"), &new_table_index)) != (void*)0ul )
4978{
4979new_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
4980}
4981
4982if (oem_fadt == false)
4983{
4984
4985fadt_mod = patch_fadt(FacpPointer, (oem_dsdt == false) ? new_dsdt : (void*)0ul , (acpi_tables.FacpPointer64 != (void *)0ul ));
4986
4987if (fadt_mod != (void*)0ul)
4988{
4989DsdtPtr = ((fadt_mod->Header.Revision >= 3) && (fadt_mod->XDsdt != 0)) ? (ACPI_TABLE_DSDT*)((U32)fadt_mod->XDsdt):(ACPI_TABLE_DSDT*)fadt_mod->Dsdt;
4990
4991U8 empty = get_0ul_index_in_list(new_table_list,true);
4992if (empty != ACPI_TABLE_LIST_FULL)
4993{
4994new_table_list[empty] = (U32)fadt_mod; // add the patched table to the list
4995}
4996else
4997{
4998printf("Error: not enought reserved space in the new acpi list for the Patched FACP table,\n ");
4999printf(" please increase the RESERVED_AERA\n");
5000}
5001
5002}
5003else
5004{
5005printf("Error: Failed to patch the FADT Table, trying fallback to the FADT original pointer\n");
5006fadt_mod = (acpi_tables.FacpPointer64 != (void *)0ul) ?
5007(ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer;
5008
5009DsdtPtr = ((fadt_mod->Header.Revision >= 3) && (fadt_mod->XDsdt != 0)) ? (ACPI_TABLE_DSDT*)((U32)fadt_mod->XDsdt):(ACPI_TABLE_DSDT*)fadt_mod->Dsdt;
5010
5011U8 empty = get_0ul_index_in_list(new_table_list,true);
5012if (empty != ACPI_TABLE_LIST_FULL)
5013{
5014new_table_list[empty] = (U32)fadt_mod;
5015}
5016else
5017{
5018printf("Error: not enought reserved space in the new acpi list for the FACP table,\n ");
5019printf(" please increase the RESERVED_AERA\n");
5020}
5021}
5022
5023if (oem_dsdt == false)
5024{
5025if (generate_cpu_map_from_acpi(DsdtPtr) == 0)
5026{
5027U8 new_uid = (U8)getPciRootUID();
5028
5029/* WARNING: THIS METHOD WORK PERFECTLY BUT IT CAN RESULT TO AN INCORRECT CHECKSUM */
5030
5031if (ProcessDsdt(DsdtPtr, UIDPointer, new_uid))
5032{
5033printf("PCI0 _UID patched to %d in the DSDT table\n", new_uid);
5034}
5035
5036}
5037}
5038
5039
5040}
5041else
5042{
5043
5044// here we use the variable fadt_mod only for SSDT Generation
5045
5046fadt_mod = (acpi_tables.FacpPointer64 != (void *)0ul) ?
5047(ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer;
5048
5049DsdtPtr = ((fadt_mod->Header.Revision >= 3) && (fadt_mod->XDsdt != 0)) ? (ACPI_TABLE_DSDT*)((U32)fadt_mod->XDsdt)
5050 :(ACPI_TABLE_DSDT*)fadt_mod->Dsdt;
5051}
5052
5053 {
5054 MADT_INFO madt_info;
5055 bool strip_madt = true;
5056
5057 getBoolForKey(kSTRIPAPIC, &strip_madt, &bootInfo->chameleonConfig);
5058
5059 if ((strip_madt == false) || (!buildMADT(new_table_list, DsdtPtr, &madt_info )))
5060 {
5061
5062 ACPI_TABLE_MADT * madt_file = (void*)0ul;
5063 ACPI_TABLE_MADT * MadtPointer = (void*)0ul;
5064 bool oem_apic=false;
5065
5066 {
5067 bool tmpval;
5068 oem_apic=getBoolForKey(kOEMAPIC, &tmpval, &bootInfo->chameleonConfig)&&tmpval;
5069 }
5070
5071 if ((madt_file = (ACPI_TABLE_MADT *)get_new_table_in_list(new_table_list, NAMESEG("APIC"), &new_table_index)) != (void *)0ul)
5072 {
5073 if (oem_apic == false)
5074 {
5075 MadtPointer = (ACPI_TABLE_MADT *)madt_file;
5076 }
5077
5078 } else
5079 MadtPointer = (acpi_tables.MadtPointer64 != (void*)0ul) ? (ACPI_TABLE_MADT *)acpi_tables.MadtPointer64 : (ACPI_TABLE_MADT *)acpi_tables.MadtPointer;
5080
5081 ProcessMadtInfo(MadtPointer, &madt_info);
5082
5083 }
5084
5085 if (gen_ssdt || gen_csta || gen_psta || gen_tsta)
5086 {
5087 ProcessSsdt(new_table_list, DsdtPtr, &madt_info, gen_csta, gen_psta, gen_tsta );
5088 }
5089 }
5090
5091if ((rsdp_mod != (void *)0ul) && (rsdp_mod->Length >= ACPI_RSDP_REV0_SIZE) )
5092{
5093if ((rsdp_mod->Revision == 0) || (gen_xsdt == true))
5094{
5095process_rsdt(rsdp_mod, gen_xsdt, new_table_list);
5096goto out;
5097}
5098
5099}
5100else
5101{
5102printf("Error: Incorect ACPI RSD PTR or not found \n");
5103return EFI_UNSUPPORTED;
5104}
5105
5106if ((GetChecksum(rsdp_mod, sizeof(ACPI_TABLE_RSDP)) == 0) &&
5107(Revision == 2) &&
5108(rsdplength == sizeof(ACPI_TABLE_RSDP)))
5109{
5110process_xsdt(rsdp_mod, new_table_list);
5111
5112}
5113else
5114{
5115printf("Warning : ACPI RSD PTR Revision 2 is incorrect, \n");
5116printf(" trying to fallback to Revision 1\n");
5117if ((rsdp_mod != (void *)0ul) && (rsdp_mod->Length >= ACPI_RSDP_REV0_SIZE) )
5118{
5119process_rsdt(rsdp_mod, false, new_table_list);
5120
5121}
5122else
5123{
5124printf("Error: Incorect ACPI RSD PTR or not found \n");
5125return EFI_UNSUPPORTED;
5126}
5127}
5128
5129out:
5130// Correct the checksum of RSDP
5131
5132DBG("RSDP: Original checksum %d\n", rsdp_mod->Checksum);
5133
5134setRsdpchecksum(rsdp_mod);
5135
5136DBG("New checksum %d\n", rsdp_mod->Checksum);
5137
5138if (Revision == 2)
5139{
5140DBG("RSDP: Original extended checksum %d\n", rsdp_mod->ExtendedChecksum);
5141
5142setRsdpXchecksum(rsdp_mod);
5143
5144DBG("New extended checksum %d\n", rsdp_mod->ExtendedChecksum);
5145
5146}
5147
5148verbose("ACPI Revision %d successfully patched\n", Revision);
5149
5150 if (Revision == 2)
5151{
5152/* XXX aserebln why uint32 cast if pointer is uint64 ? */
5153rsd_p = (U32)rsdp_mod;
5154addConfigurationTable(&gEfiAcpi20TableGuid, &rsd_p, "ACPI_20");
5155}
5156else
5157{
5158/* XXX aserebln why uint32 cast if pointer is uint64 ? */
5159rsd_p = (U32)rsdp_mod;
5160addConfigurationTable(&gEfiAcpiTableGuid, &rsd_p, "ACPI");
5161}
5162
5163
5164#if DEBUG_ACPI==2
5165printf("Press a key to continue... (DEBUG_ACPI)\n");
5166getc();
5167#endif
5168return Status;
5169}
5170
5171int AcpiSetup(void)
5172{
5173EFI_STATUS status = setup_Acpi();
5174
5175return (status == EFI_SUCCESS);
5176}
5177

Archive Download this file

Revision: 2034