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

Archive Download this file

Revision: 2490