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

Archive Download this file

Revision: 1899