Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2633