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

Archive Download this file

Revision: 1913