Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2647