Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 2066