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

Archive Download this file

Revision: 2115