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

Archive Download this file

Revision: 1929