Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/modules/ACPICodec/acpi_codec.c

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

Archive Download this file

Revision: 2118