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

Archive Download this file

Revision: HEAD