Chameleon

Chameleon Svn Source Tree

Root/branches/Chimera/i386/modules/AcpiCodec/acpi_codec.c

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

Archive Download this file

Revision: 2658