Chameleon

Chameleon Svn Source Tree

Root/trunk/i386/modules/AcpiCodec/acpi_codec.c

  • Property svn:executable set to *
1/*
2 * Copyright 2008 mackerintel
3 */
4
5/*
6 Copyright (c) 2010, Intel Corporation
7 All rights reserved.
8
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
11
12 * Redistributions of source code must retain the above copyright notice,
13 this list of conditions and the following disclaimer.
14 * Redistributions in binary form must reproduce the above copyright notice,
15 this list of conditions and the following disclaimer in the documentation
16 and/or other materials provided with the distribution.
17 * Neither the name of Intel Corporation nor the names of its contributors
18 may be used to endorse or promote products derived from this software
19 without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
25 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
28 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/*
34 * Copyright (c) 2011,2012 cparm <armelcadetpetit@gmail.com>. All rights reserved.
35 *
36 */
37
38#include "libsaio.h"
39#include "bootstruct.h"
40#include "acpi.h"
41#include "acpidecode.h"
42#include "acpicode.h"
43#include "efi_tables.h"
44#include "fake_efi.h"
45#include "acpi_codec.h"
46#include "platform.h"
47#include "cpu.h"
48#include "xml.h"
49#include "sl.h"
50#include "convert.h"
51#include "modules.h"
52#include "pci.h"
53#include "pci_root.h"
54
55U64 rsd_p;
56ACPI_TABLES acpi_tables;
57U32 uuid32;
58U32 Model32;
59bool checkOem = false;
60
61extern EFI_STATUS addConfigurationTable();
62
63extern EFI_GUID gEfiAcpiTableGuid;
64extern EFI_GUID gEfiAcpi20TableGuid;
65
66#ifndef DEBUG_ACPI
67#define DEBUG_ACPI 0
68#endif
69
70#if DEBUG_ACPI==2
71#define DBG(x...) {printf(x); sleep(1);}
72#elif DEBUG_ACPI==1
73#define DBG(x...) printf(x)
74#else
75#define DBG(x...)
76#endif
77
78#define OLD_SSDT 0
79#define BETA 0
80#define BUILD_ACPI_TSS 0
81#define pstate_power_support 1
82
83#if BETA
84#ifdef pstate_power_support
85#undef pstate_power_support
86#endif
87#define pstate_power_support 1
88#endif
89
90#if DEBUG_ACPI
91static void print_nameseg(U32 i);
92#endif
93
94static ACPI_TABLE_HEADER * get_new_table_in_list(U32 *new_table_list, U32 Signature, U8 *retIndex );
95static U8 get_number_of_tables_in_list(U32 *new_table_list, U32 Signature );
96static U8 get_0ul_index_in_list(U32 *new_table_list, bool reserved );
97static void sanitize_new_table_list(U32 *new_table_list );
98static void move_table_list_to_kmem(U32 *new_table_list );
99static ACPI_TABLE_RSDP * gen_alloc_rsdp_v2_from_v1(ACPI_TABLE_RSDP *rsdp );
100static ACPI_TABLE_RSDT * gen_alloc_rsdt_from_xsdt(ACPI_TABLE_XSDT *xsdt);
101static ACPI_TABLE_XSDT * gen_alloc_xsdt_from_rsdt(ACPI_TABLE_RSDT *rsdt);
102#if 0
103static void MakeAcpiSgn(void);
104#endif
105static void *loadACPITable(U32 *new_table_list, char *dirspec, const char *filename );
106static int generate_cpu_map_from_acpi(ACPI_TABLE_DSDT * DsdtPointer);
107static ACPI_GENERIC_ADDRESS FillGASStruct(U32 Address, U8 Length);
108static U32 process_xsdt (ACPI_TABLE_RSDP *rsdp_mod , U32 *new_table_list);
109static U32 process_rsdt(ACPI_TABLE_RSDP *rsdp_mod , bool gen_xsdt, U32 *new_table_list);
110static ACPI_TABLE_FADT * patch_fadt(ACPI_TABLE_FADT *fadt, ACPI_TABLE_DSDT *new_dsdt, bool UpdateFADT);
111
112
113#define IA32_MISC_ENABLES 0x01A0
114#define MSR_TURBO_POWER_CURRENT_LIMIT 0x1AC
115#define MSR_PKG_CST_CONFIG_CONTROL 0x00E2
116#define MSR_RAPL_POWER_UNIT 0x606
117#define MSR_PKG_RAPL_POWER_LIMIT 0x610
118static U32 turbo_enabled = 0;
119static U32 ProcessMadt(ACPI_TABLE_MADT * madt, MADT_INFO * madt_info, void * buffer, U32 bufferSize, U32 NB_CPU);
120static U32 buildMADT(U32 * new_table_list, ACPI_TABLE_DSDT *dsdt, MADT_INFO * madt_info);
121static U32 BuildSsdt(MADT_INFO * madt_info, ACPI_TABLE_DSDT *dsdt, void * buffer, U32 bufferSize, bool enable_cstates, bool enable_pstates, bool enable_tstates);
122static bool is_sandybridge(void);
123static bool is_jaketown(void);
124static U32 encode_pstate(U32 ratio);
125static void collect_cpu_info(CPU_DETAILS * cpu);
126#ifndef BETA
127//static U32 BuildCoreIPstateInfo(CPU_DETAILS * cpu);
128#endif
129static U32 BuildCstateInfo(CPU_DETAILS * cpu, U32 pmbase);
130static U32 BuildPstateInfo(CPU_DETAILS * cpu);
131static U32 ProcessSsdt(U32 * new_table_list, ACPI_TABLE_DSDT *dsdt, MADT_INFO * madt_info, bool enable_cstates, bool enable_pstates, bool enable_tstates );
132static void * buildCpuScope (void * current, U32 cpu_namespace, PROCESSOR_NUMBER_TO_NAMESEG * aslCpuNamePath);
133static void * buildPDC(void * current);
134static void * buildOSC(void * current);
135static void * buildPSS(void * current, PKG_PSTATES * pkg_pstates);
136static void * buildPSD(void * current, U32 domain, U32 cpusInDomain, U32 pstate_coordination);
137static void * buildPPC(void * current);
138static void * buildPCT(void * current);
139static void * buildCstate(void * current, ACPI_GENERIC_ADDRESS * gas, CSTATE * cstate);
140static void * buildReturnPackageCST(void * current, PKG_CSTATES * pkg_cstates);
141static void * buildCST(void * current, PKG_CSTATES * mwait_pkg_cstates, PKG_CSTATES * io_pkg_cstates);
142#if BUILD_ACPI_CSD
143static void * buildCSD(void * current, U32 domain, U32 cpusInDomain, PKG_CSTATES * pkg_cstates);
144#endif
145#if BUILD_ACPI_TSS
146static U32 BuildTstateInfo(CPU_DETAILS * cpu);
147static void * buildTPC(void * current);
148static void * buildPTC(void * current);
149static void * buildTSS(void * current, PKG_TSTATES * pkg_tstates);
150static void * buildTSD(void * current, U32 domain, U32 cpusInDomain);
151#endif
152#if pstate_power_support
153static U64 mulU64byU64(U64 a, U64 b, U64 * high);
154static U32 compute_pstate_power(CPU_DETAILS * cpu, U32 ratio, U32 TDP);
155#endif
156#if BUILD_ACPI_TSS || pstate_power_support
157static U64 divU64byU64(U64 n, U64 d, U64 * rem);
158static U32 compute_tdp(CPU_DETAILS * cpu);
159#endif
160static bool is_sandybridge(void);
161static bool is_jaketown(void);
162static U32 get_bclk(void);
163static void GetMaxRatio(U32 * max_non_turbo_ratio);
164//static U32 computePstateRatio(const U32 max, const U32 min, const U32 turboEnabled, const U32 numStates, const U32 pstate);
165//static U32 computeNumPstates(const U32 max, const U32 min, const U32 turboEnabled, const U32 pssLimit);
166
167#if UNUSED
168static ACPI_TABLE_FACS* generate_facs(bool updatefacs );
169#endif
170
171#define MAX_NON_SSDT_TABLE 15
172#define MAX_SSDT_TABLE 15 // 15 additional SSDT tables
173#define MAX_ACPI_TABLE MAX_NON_SSDT_TABLE + MAX_SSDT_TABLE
174
175// Security space for SSDT , FACP & MADT table generation,
176// the size can be increased
177// note: the table will not placed in the reserved space if the 'normal' space is not full
178#define RESERVED_AERA 3
179
180#define ACPI_TABLE_LIST_FULL MAX_ACPI_TABLE + RESERVED_AERA + 1
181
182#define ACPI_TABLE_LIST_FULL_NON_RESERVED MAX_ACPI_TABLE + 1
183
184#ifndef ULONG_MAX_32
185#define ULONG_MAX_32 4294967295UL
186#endif
187
188#define __RES(s, u)\
189static inline unsigned u\
190resolve_##s(unsigned u defaultentry, char *str, int base) \
191{\
192unsigned u entry = defaultentry;\
193if (str && (strcmp(str,"Default") != 0)) {\
194entry = strtoul((const char *)str, NULL,base);\
195}\
196return entry;\
197}
198
199__RES(pss, long)
200#if UNUSED
201__RES(cst, int)
202#endif /* UNUSED */
203
204static ACPI_TABLE_HEADER * get_new_table_in_list(U32 *new_table_list, U32 Signature, U8 *retIndex )
205{
206ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;
207U8 index ;
208*retIndex = 0;
209
210for (index = 0; index < (MAX_ACPI_TABLE + RESERVED_AERA); index++)
211{
212if (*(U32 *) (table_array[index]->Signature) == Signature)
213{
214*retIndex = index;
215return table_array[index] ;
216}
217}
218return (void*)0ul;
219}
220
221static U8 get_number_of_tables_in_list(U32 *new_table_list, U32 Signature )
222{
223ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;
224U8 index ;
225U8 InstalledTables = 0;
226
227for (index = 0; index < (MAX_ACPI_TABLE + RESERVED_AERA); index++)
228{
229if (*(U32 *) (table_array[index]->Signature) == Signature)
230{
231InstalledTables++ ;
232}
233}
234return InstalledTables;
235}
236
237static U8 get_0ul_index_in_list(U32 *new_table_list, bool reserved )
238{
239U8 index ;
240
241U8 maximum = (reserved == true) ? MAX_ACPI_TABLE + RESERVED_AERA : MAX_ACPI_TABLE;
242
243for (index = 0; index < maximum; index++)
244{
245if (new_table_list[index] == 0ul)
246{
247return index ;
248}
249}
250return (reserved == true)? ACPI_TABLE_LIST_FULL : ACPI_TABLE_LIST_FULL_NON_RESERVED;
251}
252
253/* cparm : This time we check it by the acpi signature */
254static void sanitize_new_table_list(U32 *new_table_list )
255{
256ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;
257U8 index ;
258
259for (index = 0; index < MAX_ACPI_TABLE; index++)
260{
261U32 current_sig = *(U32 *) (table_array[index]->Signature);
262
263if ((current_sig == NAMESEG(ACPI_SIG_FACS) /* not supported */ )
264|| (current_sig == NAMESEG(ACPI_SIG_XSDT))
265|| (current_sig == NAMESEG(ACPI_SIG_RSDT)) || (*(volatile U64 *)table_array[index] == NAMESEG64(ACPI_SIG_RSDP)) )
266{
267
268void *buf = (void*)new_table_list[index];
269free(buf);
270new_table_list[index] = 0ul ;
271}
272}
273}
274
275/* cparm : move all tables to kernel memory */
276static void move_table_list_to_kmem(U32 *new_table_list )
277{
278ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;
279U8 index ;
280
281for (index = 0; index < MAX_ACPI_TABLE; index++)
282{
283if (new_table_list[index] != 0ul)
284{
285
286U32 current_sig = *(U32 *) (table_array[index]->Signature);
287if ((current_sig != NAMESEG(ACPI_SIG_FACS) /* not supported */ )
288&& (current_sig != NAMESEG(ACPI_SIG_XSDT))
289&& (current_sig != NAMESEG(ACPI_SIG_RSDT)) && (*(volatile U64 *)table_array[index] != NAMESEG64(ACPI_SIG_RSDP))
290&& (GetChecksum(table_array[index], table_array[index]->Length) == 0))
291{
292
293void *tableAddr=(void*)AllocateKernelMemory(table_array[index]->Length);
294if (!tableAddr) {
295printf("Unable to allocate kernel memory for aml file ");
296
297void *buf = (void*)new_table_list[index];
298free(buf);
299new_table_list[index] = 0ul ;
300continue;
301}
302bcopy(table_array[index], tableAddr, table_array[index]->Length);
303new_table_list[index] = 0ul ;
304new_table_list[index] = (U32)tableAddr ;
305
306}
307else
308{
309
310void *buf = (void*)new_table_list[index];
311free(buf);
312new_table_list[index] = 0ul ;
313}
314}
315}
316}
317
318static ACPI_TABLE_RSDP * gen_alloc_rsdp_v2_from_v1(ACPI_TABLE_RSDP *rsdp )
319{
320
321ACPI_TABLE_RSDP * rsdp_conv = (ACPI_TABLE_RSDP *)AllocateKernelMemory(sizeof(ACPI_TABLE_RSDP));
322
323if (rsdp_conv) {
324bzero(rsdp_conv, sizeof(ACPI_TABLE_RSDP));
325memcpy(rsdp_conv, rsdp, ACPI_RSDP_REV0_SIZE);
326
327/* Add/change fields */
328rsdp_conv->Revision = 2; /* ACPI version 3 */
329rsdp_conv->Length = sizeof(ACPI_TABLE_RSDP);
330
331/* Correct checksums */
332setRsdpchecksum(rsdp_conv);
333setRsdpXchecksum(rsdp_conv);
334}
335
336 return (rsdp_conv) ? rsdp_conv : (void*)0ul ;
337}
338
339static ACPI_TABLE_RSDT * gen_alloc_rsdt_from_xsdt(ACPI_TABLE_XSDT *xsdt)
340{
341 U32 index;
342 U32 num_tables;
343
344DBG("Attempting to generate RSDT from XSDT \n");
345
346 num_tables= get_num_tables64(xsdt);
347
348 ACPI_TABLE_RSDT * rsdt_conv=(ACPI_TABLE_RSDT *)AllocateKernelMemory(sizeof(ACPI_TABLE_HEADER)+(num_tables * 4));
349if (!rsdt_conv)
350{
351printf("Unable to allocate kernel memory for rsdt conv\n");
352return (void*)0ul;
353}
354
355
356bzero(rsdt_conv, sizeof(ACPI_TABLE_HEADER)+(num_tables * 4));
357 memcpy(&rsdt_conv->Header, &xsdt->Header, sizeof(ACPI_TABLE_HEADER));
358
359 rsdt_conv->Header.Signature[0] = 'R';
360 rsdt_conv->Header.Signature[1] = 'S';
361 rsdt_conv->Header.Signature[2] = 'D';
362 rsdt_conv->Header.Signature[3] = 'T';
363 rsdt_conv->Header.Length = sizeof(ACPI_TABLE_HEADER)+(num_tables * 4);
364
365for (index=0;index<num_tables;index++)
366 {
367U64 ptr = xsdt->TableOffsetEntry[index];
368
369{
370if (ptr > ULONG_MAX)
371{
372#if DEBUG_ACPI
373printf("Warning xsdt->TableOffsetEntry[%d]: Beyond addressable memory in this CPU mode, ignored !!!\n",index);
374#endif
375continue;
376}
377#if DEBUG_ACPI
378printf("* Processing : ");
379print_nameseg(*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature);
380printf("\n");
381#endif
382int method = 0;
383getIntForKey(kAcpiMethod, &method, &bootInfo->chameleonConfig);
384
385
386if (method != 0x2)
387{
388if (GetChecksum(((ACPI_TABLE_HEADER *) (unsigned long)ptr),
389((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Length) != 0)
390{
391#if DEBUG_ACPI
392printf("Warning : Invalide checksum, ignored !!!\n",index);
393#endif
394continue;
395}
396}
397
398}
399
400{
401if (*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature == NAMESEG(ACPI_SIG_FADT))
402{
403ACPI_TABLE_FADT *fadt=(ACPI_TABLE_FADT *)((U32)ptr);
404
405ACPI_TABLE_FADT *fadt_conv = (void*)0ul;
406
407if (fadt->Header.Revision > 1)
408{
409U8 buffer[0x74];
410DBG("Downgrading ACPI V%d FADT to ACPI V1 FADT \n", fadt->Header.Revision);
411fadt_conv=(ACPI_TABLE_FADT *)buffer;
412memcpy(fadt_conv, fadt, 0x74);
413fadt_conv->Header.Length = 0x74;
414fadt_conv->Header.Revision = 0x01;
415SetChecksum(&fadt_conv->Header);
416}
417else
418{
419fadt_conv = fadt;
420}
421
422ACPI_TABLE_FADT *fadt_mod = patch_fadt(fadt_conv, ((ACPI_TABLE_DSDT*)((U32)fadt->XDsdt)), false);
423if (fadt_mod == (void*)0ul)
424{
425printf("Error: Failed to patch FADT Table, trying wiht the original fadt pointer\n");
426fadt_mod = fadt;
427}
428
429rsdt_conv->TableOffsetEntry[index] = ((U32)fadt_mod);
430#if DEBUG_ACPI
431print_nameseg(*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature);
432printf(" table converted and added succesfully\n");
433#endif
434continue;
435}
436}
437
438{
439rsdt_conv->TableOffsetEntry[index] = (U32)ptr;
440#if DEBUG_ACPI
441print_nameseg(*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature);
442printf(" table converted and added succesfully\n");
443#endif
444}
445
446 }
447 DBG("RSDT_CONV : Original checksum %d\n", rsdt_conv->Header.Checksum);
448 SetChecksum(&rsdt_conv->Header);
449 DBG("New checksum %d\n", rsdt_conv->Header.Checksum);
450
451 return rsdt_conv;
452}
453
454static ACPI_TABLE_XSDT * gen_alloc_xsdt_from_rsdt(ACPI_TABLE_RSDT *rsdt)
455{
456U32 index;
457 U32 num_tables;
458
459DBG("Attempting to generate XSDT from RSDT \n");
460
461 num_tables= get_num_tables(rsdt);
462
463 ACPI_TABLE_XSDT * xsdt_conv=(ACPI_TABLE_XSDT *)AllocateKernelMemory(sizeof(ACPI_TABLE_HEADER)+(num_tables * 8));
464
465if (!xsdt_conv) {
466printf("Unable to allocate kernel memory for xsdt conv\n");
467return (void*)0ul;
468}
469
470bzero(xsdt_conv, sizeof(ACPI_TABLE_HEADER)+(num_tables * 8));
471 memcpy(&xsdt_conv->Header, &rsdt->Header, sizeof(ACPI_TABLE_HEADER));
472
473 xsdt_conv->Header.Signature[0] = 'X';
474 xsdt_conv->Header.Signature[1] = 'S';
475 xsdt_conv->Header.Signature[2] = 'D';
476 xsdt_conv->Header.Signature[3] = 'T';
477 xsdt_conv->Header.Length = sizeof(ACPI_TABLE_HEADER)+(num_tables * 8);
478
479ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) rsdt->TableOffsetEntry;
480
481 for (index=0;index<num_tables;index++)
482 {
483 {
484#if DEBUG_ACPI
485 printf("* Processing : ");
486 print_nameseg(*(U32*) (table_array[index]->Signature));
487 printf("\n");
488#endif
489 int method = 0;
490getIntForKey(kAcpiMethod, &method, &bootInfo->chameleonConfig);
491
492
493if (method != 0x2)
494 {
495 if (GetChecksum(table_array[index], table_array[index]->Length) != 0)
496 {
497#if DEBUG_ACPI
498 printf("Warning : Invalide checksum, ignored !!!\n",index);
499#endif
500 continue;
501 }
502 }
503
504 }
505
506 {
507 if (*(U32 *) (table_array[index]->Signature) == NAMESEG(ACPI_SIG_FADT))
508 {
509 ACPI_TABLE_FADT *FacpPointer = ((ACPI_TABLE_FADT*)table_array[index]);
510 ACPI_TABLE_FADT *fadt_mod = (ACPI_TABLE_FADT *)patch_fadt(FacpPointer,((ACPI_TABLE_DSDT*)FacpPointer->Dsdt),true);
511 if (fadt_mod == (void*)0ul)
512 {
513 printf("Error: Failed to patch (& update) FADT Table, fallback to original fadt pointer\n");
514 fadt_mod = FacpPointer;
515 }
516 xsdt_conv->TableOffsetEntry[index] = ((U64)((U32)fadt_mod));
517
518 continue;
519 }
520 }
521
522 xsdt_conv->TableOffsetEntry[index] = ((U64)((U32)table_array[index]));
523 }
524 DBG("XSDT_CONV : Original checksum %d\n", xsdt_conv->Header.Checksum);
525 SetChecksum(&xsdt_conv->Header);
526 DBG("New checksum %d\n", xsdt_conv->Header.Checksum);
527
528 return xsdt_conv;
529}
530
531#if ACPISGN
532static void MakeAcpiSgn(void)
533{
534
535char * DefaultplatformName = NULL;
536Model32 = 0;
537
538if ((DefaultplatformName = readDefaultPlatformName()))
539{
540Model32 = OSSwapHostToBigInt32(adler32( (unsigned char *) DefaultplatformName, strlen(DefaultplatformName)));
541}
542
543uuid32 = 0;
544
545const char *uuidStr = getStringFromUUID((int8_t*)(uint32_t)get_env(envSysId));
546
547if (strlen(uuidStr))
548{
549uuid32 = OSSwapHostToBigInt32(adler32( (unsigned char *) uuidStr, UUID_STR_LEN ));
550}
551
552}
553#endif
554
555static void *loadACPITable(U32 *new_table_list, char *dirspec, const char *filename )
556{
557int fd = -1;
558char acpi_file[512];
559
560DBG("Searching for %s file ...\n", filename);
561// Check booting partition
562
563sprintf(acpi_file, "%s%s",dirspec, filename);
564
565fd=open(acpi_file,0);
566
567if (fd<0)
568{
569DBG("Couldn't open ACPI Table: %s\n", acpi_file);
570return (void *)0ul ;
571}
572
573void *tableAddr=(void*)malloc(file_size (fd));
574
575if (tableAddr)
576{
577if (read (fd, tableAddr, file_size (fd))!=file_size (fd))
578{
579printf("Couldn't read table %s\n",acpi_file);
580free (tableAddr);
581close (fd);
582return (void *)0ul ;
583}
584
585close (fd);
586
587ACPI_TABLE_HEADER * header = (ACPI_TABLE_HEADER *)tableAddr;
588
589if (*(U32*)(header->Signature) != NAMESEG("SSDT"))
590{
591U8 dummy = 0;
592if (get_new_table_in_list(new_table_list, *(U32*)(header->Signature), &dummy))
593{
594#if DEBUG_ACPI
595printf("Warning: A ");
596print_nameseg(*(U32*) (header->Signature));
597printf(" Aml file is already loaded and registred, file skipped !!\n");
598#endif
599free(tableAddr);
600return (void*)0ul;
601}
602}
603else
604{
605if (get_number_of_tables_in_list(new_table_list, NAMESEG("SSDT")) >= MAX_SSDT_TABLE)
606{
607DBG("Warning: Max number of SSDT aml files reached, file skipped !!\n");
608free(tableAddr);
609return (void*)0ul;
610}
611}
612
613
614if (checkOem == true)
615{
616if (header->OemRevision == Model32)
617{
618goto continue_loading;
619}
620
621if (header->OemRevision == uuid32)
622{
623goto continue_loading;
624}
625
626DBG("Bad signature aka Oem Revision (0x%08lx) for Aml file (%s), file skipped !!\n", header->OemRevision, acpi_file);
627DBG("uuid32 (0x%08lx) , model32 (0x%08lx)\n", uuid32, Model32);
628
629free(tableAddr);
630return (void*)0ul;
631}
632
633 continue_loading:
634
635if (GetChecksum(header, header->Length) == 0)
636{
637DBG("Found valid AML file : %s ", filename);
638verbose("[ %s ] read and stored at: %x", acpi_file, tableAddr);
639printf("\n");
640return tableAddr;
641}
642else
643{
644printf("Warning : Incorrect cheksum for the file : %s,", acpi_file);
645printf(" this file will be dropped.\n");
646free(tableAddr);
647return (void*)0ul;
648}
649}
650else
651{
652printf("Couldn't allocate memory for table %s\n", acpi_file);
653close (fd);
654}
655
656return (void *)0ul ;
657}
658
659static U32 pmbase;
660static short cpuNamespace;
661PROCESSOR_NUMBER_TO_NAMESEG cpu_map[CPU_MAP_LIMIT];
662unsigned int cpu_map_count;
663int cpu_map_error;
664
665#if DEBUG_ACPI
666static void print_nameseg(U32 i)
667{
668 printf("%c%c%c%c",
669 (int)(i & 0x000000ff),
670 (int)((i & 0x0000ff00) >> 8),
671 (int)((i & 0x00ff0000) >> 16),
672 (int)(i >> 24));
673}
674#endif
675
676static int generate_cpu_map_from_acpi(ACPI_TABLE_DSDT * DsdtPointer)
677{
678 PROCESSOR_NUMBER_TO_NAMESEG *map = cpu_map;
679 U32 processor_namespace = 0;
680 U32 cpu;
681 U8 *current, *end;
682 ACPI_TABLE_HEADER *header;
683 struct acpi_namespace ns;
684
685if ((cpu_map_error == 1) || (DsdtPointer == (void*)0ul))
686return 1;
687else if (cpu_map_count > 0)
688return 0;
689
690 DBG("Attempting to autodetect CPU map from ACPI DSDT; wish me luck\n");
691
692 current = (U8 *) DsdtPointer;
693 current = decodeTableHeader(current, &header);
694 end = current - sizeof(*header) + header->Length;
695 ns.depth = 0;
696 acpi_processor_count = 0;
697//DBG("* DSDT debug start\n");
698 parse_acpi_termlist(&ns, current, end);
699//DBG("* DSDT debug end\n");
700
701 if (acpi_processor_count > CPU_MAP_LIMIT)
702{
703verbose("Too many processors: found %u processors\n", acpi_processor_count);
704 return (cpu_map_error = 1);
705}
706 if (acpi_processor_count == 0)
707{
708verbose( "Found no processors in ACPI\n");
709 return (cpu_map_error = 1);
710}
711 for (cpu = 0; cpu < acpi_processor_count; cpu++)
712{
713 U32 nameseg;
714 if (acpi_processors[cpu].pmbase)
715{
716 U32 cpu_pmbase = acpi_processors[cpu].pmbase - 0x10;
717 if (pmbase && cpu_pmbase != pmbase)
718{
719verbose("Found inconsistent pmbase addresses in ACPI: 0x%x and 0x%x\n", pmbase, cpu_pmbase);
720return (cpu_map_error = 1);
721}
722 pmbase = cpu_pmbase;
723 }
724 if (acpi_processors[cpu].ns.depth > MAX_SUPPORTED_CPU_NAMESEGS + 1)
725{
726verbose("Processor path too deep: depth %u\n", acpi_processors[cpu].ns.depth);
727return (cpu_map_error = 1);
728}
729 if (processor_namespace && acpi_processors[cpu].ns.nameseg[0] != processor_namespace)
730{
731verbose("Processor namespaces inconsistent\n");
732return (cpu_map_error = 1);
733}
734 processor_namespace = acpi_processors[cpu].ns.nameseg[0];
735 map->acpi_processor_number = acpi_processors[cpu].id;
736 map->seg_count = acpi_processors[cpu].ns.depth - 1;
737 for (nameseg = 0; nameseg < map->seg_count; nameseg++)
738 map->nameseg[nameseg] = acpi_processors[cpu].ns.nameseg[nameseg + 1];
739 map++;
740 }
741 if (!pmbase)
742{
743verbose("No pmbase found in ACPI\n");
744return (cpu_map_error = 1);
745}
746 if (processor_namespace == NAMESEG("_PR_"))
747 cpuNamespace = CPU_NAMESPACE_PR;
748 else if (processor_namespace == NAMESEG("_SB_"))
749 cpuNamespace = CPU_NAMESPACE_SB;
750 else
751{
752 verbose("Found processors in invalid namespace; not _PR_ or _SB_\n");
753return (cpu_map_error = 1);
754}
755 cpu_map_count = map - cpu_map;
756
757#if DEBUG_ACPI
758verbose("Found %d processors in ACPI, pmbase : 0x%x, cpu_map_count : %d, namespace : ",acpi_processor_count, pmbase, cpu_map_count );
759print_nameseg(processor_namespace);
760verbose("\n");
761 U32 i;
762 verbose("Found processors name : \n" );
763 for ( i = 0; i<cpu_map_count; i++)
764{
765U32 nseg = *(U32*)cpu_map[i].nameseg;
766 print_nameseg(nseg);
767verbose(" ");
768 }
769 verbose("\n");
770#endif
771
772// TODO: Save the cpu map into the device tree
773 return (cpu_map_error = 0);
774}
775
776static bool is_sandybridge(void)
777{
778 return Platform.CPU.Model == CPUID_MODEL_SANDYBRIDGE;
779}
780
781static bool is_jaketown(void)
782{
783 return Platform.CPU.Model == CPUID_MODEL_JAKETOWN;
784}
785
786static U32 get_bclk(void)
787{
788return (is_jaketown() || is_sandybridge()) ? 100 : 133;
789}
790/*
791 //-----------------------------------------------------------------------------
792 static U32 computePstateRatio(const U32 max, const U32 min, const U32 turboEnabled, const U32 numStates, const U32 pstate)
793 {
794 U32 ratiorange = max-min;
795 U32 numGaps = numStates-1-turboEnabled;
796 U32 adjPstate = pstate-turboEnabled;
797 return (pstate == 0) ? (max + turboEnabled) :
798 (ratiorange == 0) ? max :
799 max-(((adjPstate*ratiorange)+(numGaps/2))/numGaps);
800 }
801 //-----------------------------------------------------------------------------
802 static U32 computeNumPstates(const U32 max, const U32 min, const U32 turboEnabled, const U32 pssLimit)
803 {
804 U32 ratiorange, maxStates, numStates;
805
806 ratiorange = max - min + 1;
807 maxStates = ratiorange + (turboEnabled ? 1 : 0);
808 numStates = (pssLimit < maxStates) ? pssLimit : maxStates;
809 return (numStates < 2) ? 0 : numStates;
810 }
811 */
812#if BUILD_ACPI_TSS || pstate_power_support
813static U64 divU64byU64(U64 n, U64 d, U64 * rem)
814{
815 U32 i;
816 U64 q = n;
817 U64 r = 0;
818
819 for (i = 0; i < 64; i++) {
820 r <<= 1;
821 r |= (q & (1ULL << 63)) >> 63;
822 q <<= 1;
823 if (r >= d) {
824 r -= d;
825 q |= 1;
826 }
827 }
828 if (rem)
829 *rem = r;
830 return q;
831}
832
833static U32 compute_tdp(CPU_DETAILS * cpu)
834{
835 {
836 if (is_jaketown() || is_sandybridge())
837 {
838 U64 power_limit_1 = cpu->package_power_limit & ((1ULL << 15) - 1);
839 U64 power_unit = cpu->package_power_sku_unit & ((1ULL << 4) - 1);
840 U64 tdp = divU64byU64(power_limit_1, 1 << power_unit, NULL);
841 return (U32)tdp;
842 }
843 else
844 {
845 // tdp = (TURBO_POWER_CURRENT_LIMIT MSR 1ACh bit [14:0] / 8) Watts
846 return cpu->tdp_limit / 8;
847 }
848 }
849return (0);
850}
851#endif // BUILD_ACPI_TSS || pstate_power_support
852
853#if pstate_power_support
854static U64 mulU64byU64(U64 a, U64 b, U64 * high)
855{
856 U64 b_high = 0;
857 U64 r_high = 0, r_low = 0;
858 U64 bit;
859
860 for (bit = 1; bit; bit <<= 1) {
861 if (a & bit) {
862 if (r_low + b < r_low)
863 r_high++;
864 r_low += b;
865 r_high += b_high;
866 }
867 b_high <<= 1;
868 b_high |= (b & (1ULL << 63)) >> 63;
869 b <<= 1;
870 }
871
872 if (high)
873 *high = r_high;
874 return r_low;
875}
876
877static U32 compute_pstate_power(CPU_DETAILS * cpu, U32 ratio, U32 TDP)
878{
879if (is_jaketown() || is_sandybridge())
880{
881U32 P1_Ratio = cpu->max_ratio_as_mfg;
882U64 M, pstate_power;
883
884// M = ((1.1 - ((P1_ratio - ratio) * 0.00625)) / 1.1) ^2
885// To prevent loss of precision compute M * 10^5 (preserves 5 decimal places)
886M = (P1_Ratio - ratio) * 625;
887M = (110000 - M);
888M = divU64byU64(M, 11, NULL);
889M = divU64byU64(mulU64byU64(M, M, NULL), 1000, NULL);
890
891// pstate_power = ((ratio/p1_ratio) * M * TDP)
892// Divide the final answer by 10^5 to remove the precision factor
893pstate_power = mulU64byU64(ratio, M, NULL);
894pstate_power = mulU64byU64(pstate_power, TDP, NULL);
895pstate_power = divU64byU64(pstate_power, P1_Ratio, NULL);
896pstate_power = divU64byU64(pstate_power, 100000, NULL);
897return (U32)pstate_power; // in Watts
898}
899else
900{
901// pstate_power[ratio] = (ratio/P1_ratio)^3 * Core_TDP + Uncore_TDP
902
903// Core_TDP = (TURBO_POWER_CURRENT_LIMIT MSR 1ACh bit [30:16] / 8) Watts
904U32 Core_TDP = cpu->tdc_limit / 8;
905
906// Uncore_TDP = TDP - Core_TDP
907U32 Uncore_TDP = TDP - Core_TDP;
908
909// max_ratio_as_mfg = P1_Ratio derived from Brand String returned by CPUID instruction
910U32 P1_Ratio = cpu->max_ratio_as_mfg;
911
912#define PRECISION_FACTOR (U32) 30
913#define PRECISION_FACTOR_CUBED (U32) (PRECISION_FACTOR * PRECISION_FACTOR * PRECISION_FACTOR)
914
915U32 ratio_factor = (ratio * PRECISION_FACTOR)/P1_Ratio;
916return ((ratio_factor * ratio_factor * ratio_factor * Core_TDP) / PRECISION_FACTOR_CUBED) + Uncore_TDP;
917}
918 return (0);
919}
920#endif // pstate_power_support
921
922static U32 encode_pstate(U32 ratio)
923{
924if (is_jaketown() || is_sandybridge())
925return ratio << 8;
926return ratio;
927}
928
929//-----------------------------------------------------------------------------
930static void GetMaxRatio(U32 * max_non_turbo_ratio)
931{
932U32 index;
933U32 max_ratio=0;
934U32 frequency=0;
935 U32 multiplier = 0;
936 char*BrandString;
937// Verify CPUID brand string function is supported
938if (Platform.CPU.CPUID[CPUID_80][0] < 80000004)
939{
940*max_non_turbo_ratio = max_ratio;
941return;
942}
943BrandString = (char *)Platform.CPU.BrandString;
944 // -2 to prevent buffer overrun because looking for y in yHz, so z is +2 from y
945 for (index=0; index<48-2; index++) {
946 // format is either “x.xxyHz” or “xxxxyHz”, where y=M,G,T and x is digits
947 // Search brand string for “yHz” where y is M, G, or T
948 // Set multiplier so frequency is in MHz
949 if ( BrandString[index+1] == 'H' && BrandString[index+2] == 'z')
950 {
951 if (BrandString[index] == 'M')
952 multiplier = 1;
953 else if (BrandString[index] == 'G')
954 multiplier = 1000;
955 else if (BrandString[index] == 'T')
956 multiplier = 1000000;
957 }
958 if (multiplier > 0 && index >= 4 /* who can i call that, buffer underflow :-) ??*/)
959 {
960 // Copy 7 characters (length of “x.xxyHz”)
961 // index is at position of y in “x.xxyHz”
962
963 // Compute frequency (in MHz) from brand string
964 if (BrandString[index-3] == '.')
965 { // If format is “x.xx”
966 if (isdigit(BrandString[index-4]) && isdigit(BrandString[index-2]) &&
967 isdigit(BrandString[index-1]))
968 {
969 frequency = (U32)(BrandString[index-4] - '0') * multiplier;
970 frequency += (U32)(BrandString[index-2] - '0') * (multiplier / 10);
971 frequency += (U32)(BrandString[index-1] - '0') * (multiplier / 100);
972 }
973 }
974 else
975 { // If format is xxxx
976 if (isdigit(BrandString[index-4]) && isdigit(BrandString[index-3]) &&
977 isdigit(BrandString[index-2]) && isdigit(BrandString[index-1]))
978 {
979 frequency = (U32)(BrandString[index-4] - '0') * 1000;
980 frequency += (U32)(BrandString[index-3] - '0') * 100;
981 frequency += (U32)(BrandString[index-2] - '0') * 10;
982 frequency += (U32)(BrandString[index-1] - '0');
983 frequency *= multiplier;
984 }
985
986 }
987
988 max_ratio = frequency / get_bclk();
989 break;
990 }
991 }
992
993// Return non-zero Max Non-Turbo Ratio obtained from CPUID brand string
994// or return 0 indicating Max Non-Turbo Ratio not available
995*max_non_turbo_ratio = max_ratio;
996}
997
998//-----------------------------------------------------------------------------
999static void collect_cpu_info(CPU_DETAILS * cpu)
1000{
1001boolean_tdynamic_acceleration = 0;
1002U32sub_Cstates = 0;
1003U32 extensions = 0;
1004boolean_tinvariant_APIC_timer = 0;
1005boolean_tfine_grain_clock_mod = 0;
1006
1007#if BUILD_ACPI_TSS || pstate_power_support
1008if (Platform.CPU.CPUID[CPUID_0][0] >= 0x5) {
1009/*
1010 * Extract the Monitor/Mwait Leaf info:
1011 */
1012 sub_Cstates = Platform.CPU.CPUID[CPUID_5][3];
1013 extensions = Platform.CPU.CPUID[CPUID_5][2];
1014}
1015
1016if (Platform.CPU.CPUID[CPUID_0][0] >= 6) {
1017dynamic_acceleration = bitfield(Platform.CPU.CPUID[CPUID_6][0], 1, 1); // "Dynamic Acceleration Technology (Turbo Mode)"
1018invariant_APIC_timer = bitfield(Platform.CPU.CPUID[CPUID_6][0], 2, 2); // "Invariant APIC Timer"
1019 fine_grain_clock_mod = bitfield(Platform.CPU.CPUID[CPUID_6][0], 4, 4);
1020}
1021 cpu->turbo_available = (U32)dynamic_acceleration;
1022
1023{
1024U32 temp32 = 0;
1025U64 temp64= 0;
1026int tdp;
1027if (getIntForKey("TDP", &tdp, &bootInfo->chameleonConfig))
1028{
1029temp32 = (U32) (tdp*8) ;
1030
1031int tdc;
1032if (getIntForKey("TDC", &tdc, &bootInfo->chameleonConfig))
1033{
1034temp32 = (U32) (temp32) | tdc<<16 ;
1035
1036}
1037else if (tdp)
1038{
1039temp32 = (U32) (temp32) | ((tdp)*8)<<16 ;
1040}
1041
1042}
1043else if (!is_sandybridge() && !is_jaketown())
1044{
1045if (turbo_enabled && cpu->turbo_available)
1046{
1047temp64 = rdmsr64(MSR_TURBO_POWER_CURRENT_LIMIT);
1048temp32 = (U32)temp64;
1049}
1050else
1051{
1052// Unfortunately, Intel don't provide a better method for non turbo processors
1053// and it will give a TDP of 95w (for ex. mine is 65w) , to fix this issue,
1054// you can set this value by simply adding the option TDP = XX (XX is an integer)
1055// in your boot.plist
1056temp32 = (U32)0x02a802f8;
1057}
1058
1059}
1060if (temp32) {
1061cpu->tdp_limit = ( temp32 & 0x7fff );
1062cpu->tdc_limit = ( (temp32 >> 16) & 0x7fff );
1063}
1064}
1065
1066#endif
1067
1068switch (Platform.CPU.Family)
1069{
1070case 0x06:
1071{
1072switch (Platform.CPU.Model)
1073{
1074case CPUID_MODEL_DOTHAN:
1075case CPUID_MODEL_YONAH: // Yonah
1076case CPUID_MODEL_MEROM: // Merom
1077case CPUID_MODEL_PENRYN: // Penryn
1078case CPUID_MODEL_ATOM: // Intel Atom (45nm)
1079{
1080
1081cpu->core_c1_supported = ((sub_Cstates >> 4) & 0xf) ? 1 : 0;
1082cpu->core_c4_supported = ((sub_Cstates >> 16) & 0xf) ? 1 : 0;
1083
1084if (Platform.CPU.Model == CPUID_MODEL_ATOM)
1085{
1086cpu->core_c2_supported = cpu->core_c3_supported = ((sub_Cstates >> 8) & 0xf) ? 1 : 0;
1087cpu->core_c6_supported = ((sub_Cstates >> 12) & 0xf) ? 1 : 0;
1088
1089}
1090else
1091{
1092cpu->core_c3_supported = ((sub_Cstates >> 12) & 0xf) ? 1 : 0;
1093cpu->core_c2_supported = ((sub_Cstates >> 8) & 0xf) ? 1 : 0;
1094cpu->core_c6_supported = 0;
1095
1096}
1097
1098cpu->core_c7_supported = 0;
1099
1100#if BETA
1101GetMaxRatio(&cpu->max_ratio_as_mfg);
1102U64 msr = rdmsr64(MSR_IA32_PERF_STATUS);
1103U16 idlo = (msr >> 48) & 0xffff;
1104U16 idhi = (msr >> 32) & 0xffff;
1105cpu->min_ratio = (U32) (idlo >> 8) & 0xff;
1106cpu->max_ratio_as_cfg = (U32) (idhi >> 8) & 0xff;
1107
1108#else
1109if (Platform.CPU.MaxCoef)
1110{
1111if (Platform.CPU.MaxDiv)
1112{
1113cpu->max_ratio_as_cfg = cpu->max_ratio_as_mfg = (U32) (Platform.CPU.MaxCoef * 10) + 5;
1114}
1115else
1116{
1117cpu->max_ratio_as_cfg = cpu->max_ratio_as_mfg = (U32) Platform.CPU.MaxCoef * 10;
1118}
1119}
1120#endif
1121
1122break;
1123}
1124case CPUID_MODEL_FIELDS:
1125case CPUID_MODEL_DALES:
1126case CPUID_MODEL_DALES_32NM:
1127case CPUID_MODEL_NEHALEM:
1128case CPUID_MODEL_NEHALEM_EX:
1129case CPUID_MODEL_WESTMERE:
1130case CPUID_MODEL_WESTMERE_EX:
1131case CPUID_MODEL_SANDYBRIDGE:
1132case CPUID_MODEL_JAKETOWN:
1133{
1134
1135cpu->core_c1_supported = ((sub_Cstates >> 4) & 0xf) ? 1 : 0;
1136cpu->core_c3_supported = ((sub_Cstates >> 8) & 0xf) ? 1 : 0;
1137cpu->core_c6_supported = ((sub_Cstates >> 12) & 0xf) ? 1 : 0;
1138cpu->core_c7_supported = ((sub_Cstates >> 16) & 0xf) ? 1 : 0;
1139cpu->core_c2_supported = 0;
1140cpu->core_c4_supported = 0;
1141
1142GetMaxRatio(&cpu->max_ratio_as_mfg);
1143 U64 platform_info = rdmsr64(MSR_PLATFORM_INFO);
1144 cpu->max_ratio_as_cfg = (U32) ((U32)platform_info >> 8) & 0xff;
1145cpu->min_ratio = (U32) ((platform_info >> 40) & 0xff);
1146
1147 cpu->tdc_tdp_limits_for_turbo_flag = (platform_info & (1ULL << 29)) ? 1 : 0;
1148cpu->ratio_limits_for_turbo_flag = (platform_info & (1ULL << 28)) ? 1 : 0;
1149cpu->xe_available = cpu->tdc_tdp_limits_for_turbo_flag | cpu->ratio_limits_for_turbo_flag;
1150
1151
1152
1153if (is_sandybridge() || is_jaketown())
1154{
1155cpu->package_power_limit = rdmsr64(MSR_PKG_RAPL_POWER_LIMIT);
1156cpu->package_power_sku_unit = rdmsr64(MSR_RAPL_POWER_UNIT);
1157}
1158break;
1159}
1160default:
1161verbose ("Unsupported CPU\n");
1162return /*(0)*/;
1163break;
1164}
1165}
1166default:
1167break;
1168}
1169
1170cpu->mwait_supported = (extensions & (1UL << 0)) ? 1 : 0;
1171
1172 cpu->invariant_apic_timer_flag = (U32)invariant_APIC_timer;
1173
1174#if DEBUG_ACPI
1175printf("CPU INFO : \n");
1176#if BETA
1177printf("min_ratio : %d\n", cpu->min_ratio);
1178#endif
1179printf("max_ratio_as_cfg : %d\n", cpu->max_ratio_as_cfg);
1180printf("max_ratio_as_mfg : %d\n", cpu->max_ratio_as_mfg);
1181
1182printf("turbo_available : %d\n",cpu->turbo_available);
1183
1184printf("core_c1_supported : %d\n",cpu->core_c1_supported);
1185printf("core_c2_supported : %d\n",cpu->core_c1_supported);
1186printf("core_c3_supported : %d\n",cpu->core_c3_supported);
1187printf("core_c6_supported : %d\n",cpu->core_c6_supported);
1188printf("core_c7_supported : %d\n",cpu->core_c7_supported);
1189printf("mwait_supported : %d\n",cpu->mwait_supported);
1190
1191#if BUILD_ACPI_TSS || pstate_power_support
1192if (is_sandybridge() || is_jaketown())
1193{
1194
1195printf("package_power_limit : %d\n",cpu->package_power_limit);
1196printf("package_power_sku_unit : %d\n",cpu->package_power_sku_unit);
1197
1198}
1199#endif
1200
1201DBG("invariant_apic_timer_flag : %d\n",cpu->invariant_apic_timer_flag);
1202
1203
1204#endif
1205}
1206
1207#if BETA
1208//-----------------------------------------------------------------------------
1209static U32 BuildPstateInfo(CPU_DETAILS * cpu)
1210{
1211// Build P-state table info based on verified options
1212
1213// Compute the number of p-states based on the ratio range
1214cpu->pkg_pstates.num_pstates = computeNumPstates(cpu->max_ratio_as_cfg, cpu->min_ratio, cpu->turbo_available, MAX_PSTATES);
1215
1216if (!cpu->pkg_pstates.num_pstates)
1217{
1218return (0);
1219}
1220
1221// Compute pstate data
1222{
1223U32 TDP = compute_tdp(cpu);
1224
1225U32 index;
1226for (index=0; index < cpu->pkg_pstates.num_pstates; index ++)
1227{
1228PSTATE * pstate = &cpu->pkg_pstates.pstate[index];
1229
1230// Set ratio
1231pstate->ratio = computePstateRatio(cpu->max_ratio_as_cfg, cpu->min_ratio, cpu->turbo_available, cpu->pkg_pstates.num_pstates, index);
1232
1233// Compute frequency based on ratio
1234if ((index != 0) || (cpu->turbo_available == 0))
1235pstate->frequency = pstate->ratio * get_bclk();
1236else
1237pstate->frequency = ((pstate->ratio - 1) * get_bclk()) + 1;
1238
1239// Compute power based on ratio and other data
1240if (pstate->ratio >= cpu->max_ratio_as_mfg)
1241// Use max power in mW
1242pstate->power = TDP * 1000;
1243else
1244{
1245pstate->power = compute_pstate_power(cpu, pstate->ratio, TDP);
1246
1247// Convert to mW
1248pstate->power*= 1000;
1249}
1250}
1251}
1252
1253return (1);
1254}
1255#else
1256/*
1257 //-----------------------------------------------------------------------------
1258 static U32 BuildCoreIPstateInfo(CPU_DETAILS * cpu)
1259 {
1260 // Build P-state table info based on verified options
1261
1262 // Compute the number of p-states based on the ratio range
1263 cpu->pkg_pstates.num_pstates = computeNumPstates(cpu->max_ratio_as_cfg, cpu->min_ratio, cpu->turbo_available, MAX_PSTATES);
1264
1265 if (!cpu->pkg_pstates.num_pstates)
1266 {
1267 return (0);
1268 }
1269
1270 // Compute pstate data
1271 {
1272 #ifdef pstate_power_support
1273 U32 TDP = compute_tdp(cpu);
1274 #endif
1275
1276 U32 index;
1277 for (index=0; index < cpu->pkg_pstates.num_pstates; index ++)
1278 {
1279 PSTATE * pstate = &cpu->pkg_pstates.pstate[index];
1280
1281 // Set ratio
1282 pstate->ratio = computePstateRatio(cpu->max_ratio_as_cfg, cpu->min_ratio, cpu->turbo_available, cpu->pkg_pstates.num_pstates, index);
1283
1284 // Compute frequency based on ratio
1285 if ((index != 0) || (cpu->turbo_available == 0))
1286 pstate->frequency = pstate->ratio * get_bclk();
1287 else
1288 pstate->frequency = ((pstate->ratio - 1) * get_bclk()) + 1;
1289
1290 #ifdef pstate_power_support
1291 // Compute power based on ratio and other data
1292 if (pstate->ratio >= cpu->max_ratio_as_mfg)
1293 // Use max power in mW
1294 pstate->power = TDP * 1000;
1295 else
1296 {
1297 pstate->power = compute_pstate_power(cpu, pstate->ratio, TDP);
1298
1299 // Convert to mW
1300 pstate->power*= 1000;
1301 }
1302 #else
1303 pstate->power = 0;
1304 #endif
1305 }
1306 }
1307
1308 return (1);
1309 }
1310 */
1311//-----------------------------------------------------------------------------
1312static U32 BuildPstateInfo(CPU_DETAILS * cpu)
1313{
1314
1315struct p_state p_states[32];
1316U8 p_states_count = 0;
1317
1318 if (!cpu)
1319 {
1320 return (0);
1321 }
1322
1323{
1324#if UNUSED
1325struct p_state initial;
1326#endif
1327struct p_state maximum, minimum;
1328// Retrieving P-States, ported from code by superhai (c)
1329switch (Platform.CPU.Family)
1330{
1331case 0x06:
1332{
1333switch (Platform.CPU.Model)
1334{
1335case CPUID_MODEL_DOTHAN:
1336case CPUID_MODEL_YONAH: // Yonah
1337case CPUID_MODEL_MEROM: // Merom
1338case CPUID_MODEL_PENRYN: // Penryn
1339case CPUID_MODEL_ATOM: // Intel Atom (45nm)
1340{
1341bool cpu_dynamic_fsb = false;
1342
1343if (rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 27))
1344{
1345wrmsr64(MSR_IA32_EXT_CONFIG, (rdmsr64(MSR_IA32_EXT_CONFIG) | (1 << 28)));
1346delay(1);
1347cpu_dynamic_fsb = rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 28);
1348}
1349
1350bool cpu_noninteger_bus_ratio = (rdmsr64(MSR_IA32_PERF_STATUS) & (1ULL << 46));
1351#if UNUSED
1352//initial.Control = rdmsr64(MSR_IA32_PERF_STATUS);
1353#endif
1354maximum.Control = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 32) & 0x1F3F) | (0x4000 * cpu_noninteger_bus_ratio);
1355maximum.CID = ((maximum.FID & 0x1F) << 1) | cpu_noninteger_bus_ratio;
1356
1357minimum.FID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 24) & 0x1F) | (0x80 * cpu_dynamic_fsb);
1358minimum.VID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 48) & 0x3F);
1359
1360if (minimum.FID == 0)
1361{
1362U64 msr;
1363U8 i;
1364// Probe for lowest fid
1365for (i = maximum.FID; i >= 0x6; i--)
1366{
1367msr = rdmsr64(MSR_IA32_PERF_CONTROL);
1368wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (i << 8) | minimum.VID);
1369intel_waitforsts();
1370minimum.FID = (rdmsr64(MSR_IA32_PERF_STATUS) >> 8) & 0x1F;
1371delay(1);
1372}
1373
1374msr = rdmsr64(MSR_IA32_PERF_CONTROL);
1375wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
1376intel_waitforsts();
1377}
1378
1379if (minimum.VID == maximum.VID)
1380{
1381U64 msr;
1382U8 i;
1383// Probe for lowest vid
1384for (i = maximum.VID; i > 0xA; i--)
1385{
1386msr = rdmsr64(MSR_IA32_PERF_CONTROL);
1387wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (minimum.FID << 8) | i);
1388intel_waitforsts();
1389minimum.VID = rdmsr64(MSR_IA32_PERF_STATUS) & 0x3F;
1390delay(1);
1391}
1392
1393msr = rdmsr64(MSR_IA32_PERF_CONTROL);
1394wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
1395intel_waitforsts();
1396}
1397
1398minimum.CID = ((minimum.FID & 0x1F) << 1) >> cpu_dynamic_fsb;
1399
1400// Sanity check
1401if (maximum.CID < minimum.CID)
1402{
1403DBG("Insane FID values!");
1404p_states_count = 0;
1405}
1406else
1407{
1408// Finalize P-States
1409// Find how many P-States machine supports
1410p_states_count = maximum.CID - minimum.CID + 1;
1411
1412if (p_states_count > MAX_PSTATES) // was 32
1413p_states_count = MAX_PSTATES; // was 32
1414
1415U8 vidstep;
1416U8 i = 0, u, invalid = 0;
1417
1418vidstep = ((maximum.VID << 2) - (minimum.VID << 2)) / (p_states_count - 1);
1419
1420 U32 fsb = (U32)divU64byU64(Platform.CPU.FSBFrequency , 1000000 , NULL);
1421
1422for (u = 0; u < p_states_count; u++)
1423{
1424i = u - invalid;
1425
1426p_states[i].CID = maximum.CID - u;
1427p_states[i].FID = (p_states[i].CID >> 1);
1428
1429if (p_states[i].FID < 0x6)
1430{
1431if (cpu_dynamic_fsb)
1432p_states[i].FID = (p_states[i].FID << 1) | 0x80;
1433}
1434else if (cpu_noninteger_bus_ratio)
1435{
1436p_states[i].FID = p_states[i].FID | (0x40 * (p_states[i].CID & 0x1));
1437}
1438
1439if (i && p_states[i].FID == p_states[i-1].FID)
1440invalid++;
1441
1442p_states[i].VID = ((maximum.VID << 2) - (vidstep * u)) >> 2;
1443
1444U32 multiplier = p_states[i].FID & 0x1f;// = 0x08
1445bool half = p_states[i].FID & 0x40;// = 0x01
1446bool dfsb = p_states[i].FID & 0x80;// = 0x00
1447//U32 fsb = (U32)get_env(envFSBFreq) / 1000000; // = 400
1448U32 halffsb = (fsb + 1) >> 1;// = 200
1449U32 frequency = (multiplier * fsb);// = 3200
1450
1451p_states[i].Frequency = (frequency + (half * halffsb)) >> dfsb;// = 3200 + 200 = 3400
1452}
1453
1454p_states_count -= invalid;
1455}
1456break;
1457}
1458case CPUID_MODEL_FIELDS:
1459case CPUID_MODEL_DALES:
1460case CPUID_MODEL_DALES_32NM:
1461case CPUID_MODEL_NEHALEM:
1462case CPUID_MODEL_NEHALEM_EX:
1463case CPUID_MODEL_WESTMERE:
1464case CPUID_MODEL_WESTMERE_EX:
1465case CPUID_MODEL_SANDYBRIDGE:
1466case CPUID_MODEL_JAKETOWN:
1467{
1468
1469maximum.Control = rdmsr64(MSR_IA32_PERF_STATUS) & 0xff; // Seems it always contains maximum multiplier value (with turbo, that's we need)...
1470minimum.Control = (rdmsr64(MSR_PLATFORM_INFO) >> 40) & 0xff;
1471
1472DBG("P-States: min 0x%x, max 0x%x\n", minimum.Control, maximum.Control);
1473
1474// Sanity check
1475if (maximum.Control < minimum.Control)
1476{
1477DBG("Insane control values!");
1478p_states_count = 0;
1479}
1480else
1481{
1482U8 i;
1483p_states_count = 0;
1484U32 fsb = (U32)divU64byU64(Platform.CPU.FSBFrequency , 1000000, NULL) ;
1485for (i = maximum.Control; i >= minimum.Control; i--)
1486{
1487p_states[p_states_count].Control = i;
1488p_states[p_states_count].CID = p_states[p_states_count].Control << 1;
1489p_states[p_states_count].Frequency = (U32)fsb * i;
1490p_states_count++;
1491if (p_states_count >= MAX_PSTATES) { // was 32
1492
1493if (p_states_count > MAX_PSTATES) // was 32
1494p_states_count = MAX_PSTATES; // was 32
1495
1496break;
1497}
1498}
1499}
1500
1501/*
1502 U32 sta = BuildCoreIPstateInfo(cpu);
1503 if (sta)
1504 {
1505 DBG("_PSS PGK generated successfully\n");
1506 return (1);
1507
1508 }
1509 else
1510 {
1511 verbose("CoreI _PSS Generation failed !!\n");
1512 return (0);
1513 }
1514 */
1515break;
1516}
1517default:
1518verbose ("Unsupported CPU: P-States will not be generated !!!\n");
1519return (0);
1520break;
1521}
1522}
1523default:
1524break;
1525}
1526}
1527
1528// Generating Pstate PKG
1529if (p_states_count > 0)
1530{
1531 U32 fsb = (U32)Platform.CPU.FSBFrequency;
1532U8 minPSratio = divU64byU64(p_states[p_states_count-1].Frequency , divU64byU64(fsb , 10000000 , NULL ) , NULL);
1533U8 maxPSratio = divU64byU64(p_states[0].Frequency , divU64byU64(fsb , 10000000 , NULL ) , NULL);
1534U8 cpu_ratio = 0;
1535
1536{
1537U8 cpu_div = (U8)Platform.CPU.CurrDiv;
1538U8 cpu_coef = (U8)Platform.CPU.CurrCoef;
1539
1540if (cpu_div)
1541cpu_ratio = (cpu_coef * 10) + 5;
1542else
1543cpu_ratio = cpu_coef * 10;
1544}
1545
1546
1547{
1548int user_max_ratio = 0;
1549getIntForKey(kMaxRatio, &user_max_ratio, &bootInfo->chameleonConfig);
1550if (user_max_ratio >= minPSratio && maxPSratio >= user_max_ratio)
1551{
1552
1553U8 maxcurrdiv = 0, maxcurrcoef = (int)divU64byU64(user_max_ratio , 10, NULL);
1554
1555U8 maxdiv = user_max_ratio - (maxcurrcoef * 10);
1556if (maxdiv > 0)
1557maxcurrdiv = 1;
1558
1559if (maxcurrdiv)
1560cpu_ratio = (maxcurrcoef * 10) + 5;
1561else
1562cpu_ratio = maxcurrcoef * 10;
1563}
1564}
1565
1566{
1567int user_min_ratio = 0;
1568getIntForKey(kMinRatio, &user_min_ratio, &bootInfo->chameleonConfig);
1569if (user_min_ratio >= minPSratio && cpu_ratio >= user_min_ratio)
1570{
1571
1572U8 mincurrdiv = 0, mincurrcoef = (int)divU64byU64(user_min_ratio , 10 , NULL);
1573
1574U8 mindiv = user_min_ratio - (mincurrcoef * 10);
1575
1576if (mindiv > 0)
1577mincurrdiv = 1;
1578
1579if (mincurrdiv)
1580minPSratio = (mincurrcoef * 10) + 5;
1581else
1582minPSratio = mincurrcoef * 10;
1583
1584}
1585}
1586
1587
1588if (maxPSratio >= cpu_ratio && cpu_ratio >= minPSratio)maxPSratio = cpu_ratio;
1589
1590{
1591int base = 16;
1592U8 expert = 0; /* Default: 0 , mean mixed mode
1593 * expert mode : 1 , mean add only p-states found in boot.plist
1594 */
1595
1596 TagPtr PstateTag;
1597 U32 pstate_tag_count = 0;
1598
1599{
1600
1601
1602 if (bootInfo->chameleonConfig.dictionary)
1603 {
1604 PstateTag = XMLCastDict(XMLGetProperty(bootInfo->chameleonConfig.dictionary, (const char*)"P-States"));
1605 if (PstateTag) pstate_tag_count = XMLTagCount(PstateTag) ;
1606 }
1607
1608 if (!pstate_tag_count)
1609 if ((PstateTag = XMLCastDict(XMLGetProperty(bootInfo->chameleonConfig.dictionary, (const char*)"P-States")))) pstate_tag_count = XMLTagCount(PstateTag);
1610
1611
1612if ((pstate_tag_count > 0) && PstateTag)
1613{
1614char *tmpstr = XMLCastString(XMLGetProperty(PstateTag, (const char*)"Mode"));
1615
1616if (strcmp(tmpstr,"Expert") == 0)
1617{
1618p_states_count = pstate_tag_count - 1 ; // - 1 = - ("Mode" tag)
1619expert = 1;
1620}
1621
1622
1623if ((tmpstr = XMLCastString(XMLGetProperty(PstateTag, (const char*)"Base"))))
1624{
1625
1626if (expert) p_states_count--; // -= ("Base" tag)
1627
1628int mybase = strtol(tmpstr, NULL, 10);
1629
1630if (mybase == 8 || mybase == 10 || mybase == 16 )
1631base = mybase;
1632}
1633}
1634
1635}
1636
1637{
1638U32 dropPSS = 0, Pstatus = 0;
1639char MatchStat[5];
1640#ifdef pstate_power_support
1641U32 TDP = compute_tdp(cpu);
1642#endif
1643U32 i;
1644 U32 fsb = (U32)Platform.CPU.FSBFrequency;
1645for (i = 0; i < p_states_count; i++)
1646{
1647char *Lat1 = NULL, *clk = NULL, *Pw = NULL, *Lat2 = NULL, *Ctrl = NULL ;
1648
1649if ((pstate_tag_count > 0) && PstateTag)
1650{
1651sprintf(MatchStat, "%d",i);
1652TagPtr match_Status = XMLGetProperty(PstateTag, (const char*)MatchStat);
1653
1654if (match_Status && (XMLTagCount(match_Status) > 0))
1655{
1656
1657clk = XMLCastString(XMLGetProperty(match_Status, (const char*)"CoreFreq"));
1658Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power"));
1659Lat1 = XMLCastString(XMLGetProperty(match_Status, (const char*)"Transition Latency"));
1660Lat2 = XMLCastString(XMLGetProperty(match_Status, (const char*)"Bus Master Latency"));
1661Ctrl = XMLCastString(XMLGetProperty(match_Status, (const char*)"Control"));
1662
1663
1664} else if (expert)
1665continue;
1666}
1667
1668unsigned long Frequency = 0x00000000;
1669
1670if (!expert || !pstate_tag_count) Frequency = p_states[i].Frequency;
1671
1672if (clk)
1673Frequency = strtoul((const char *)clk, NULL,base);
1674
1675if (!Frequency || Frequency > p_states[0].Frequency ) continue;
1676
1677U8 curr_ratio = (U8)divU64byU64(Frequency , divU64byU64(fsb , 10000000, NULL ), NULL);
1678
1679
1680 {
1681U8 fixed_ratio = (U8)divU64byU64(Frequency , divU64byU64(fsb , 1000000 , NULL ) , NULL) * 10;
1682U8 diff = curr_ratio - fixed_ratio ;
1683
1684if (diff)
1685{
1686if (diff < 5)
1687{
1688curr_ratio = fixed_ratio;
1689}
1690else
1691{
1692curr_ratio = fixed_ratio + 5;
1693}
1694}
1695
1696}
1697
1698if (curr_ratio > maxPSratio || minPSratio > curr_ratio)
1699goto dropPstate;
1700
1701{
1702PSTATE * pstate = &cpu->pkg_pstates.pstate[Pstatus];
1703
1704pstate->ratio = curr_ratio;
1705
1706pstate->frequency = Frequency; // CoreFreq (in MHz).
1707
1708U32 power = 0x00000000;
1709#ifdef pstate_power_support
1710// Compute power based on ratio and other data
1711if (pstate->ratio >= cpu->max_ratio_as_mfg)
1712// Use max power in mW
1713power = TDP * 1000;
1714else
1715{
1716power = compute_pstate_power(cpu, pstate->ratio, TDP);
1717
1718// Convert to mW
1719power*= 1000;
1720}
1721#endif
1722pstate->power = resolve_pss(power, Pw, base); // Power (in milliWatts)
1723pstate->translatency = resolve_pss(0x0000000A, Lat1, base); // Transition Latency (in microseconds).
1724pstate->bmlatency = resolve_pss(0x0000000A, Lat2, base); // Bus Master Latency (in microseconds).
1725
1726{
1727U32 Control = 0 /*encode_pstate(curr_ratio)*/ ;
1728if (!expert || !pstate_tag_count) Control = p_states[i].Control;
1729pstate->control = resolve_pss(Control, Ctrl, base); // Control
1730}
1731
1732pstate->status = Pstatus+1; // Status
1733
1734DBG("state :: frequency :%d power: %d translatency: %d bmlatency: %d control: %d status: %d ratio :%d :: registred !! \n",pstate->frequency,pstate->power,
1735 pstate->translatency,pstate->bmlatency,pstate->control,pstate->status,pstate->ratio );
1736}
1737
1738
1739Pstatus++;
1740continue;
1741
1742dropPstate:
1743DBG("state with cpu frequency :%d and ratio :%d will be dropped\n",p_states[i].Frequency,curr_ratio);
1744dropPSS++;
1745
1746
1747}
1748
1749if (Pstatus == 0)
1750{
1751verbose("No suitable P-states found, P-States will not be generated !!!\n");
1752return (0);
1753}
1754cpu->pkg_pstates.num_pstates = Pstatus;
1755}
1756}
1757}
1758else
1759{
1760verbose("ACPI CPUs not found: P-States will not be generated !!!\n");
1761return (0);
1762}
1763
1764DBG("_PSS PGK generated successfully\n");
1765return (1);
1766}
1767#endif // BETA
1768
1769//-----------------------------------------------------------------------------
1770static U32 BuildCstateInfo(CPU_DETAILS * cpu, U32 pmbase)
1771{
1772{
1773
1774TagPtr CstateTag = NULL;
1775U32 entry_count = 0;
1776
1777 if (bootInfo->chameleonConfig.dictionary)
1778 {
1779CstateTag = XMLCastDict(XMLGetProperty(bootInfo->chameleonConfig.dictionary, (const char*)"C-States"));
1780 }
1781
1782if (CstateTag)
1783{
1784int base = 16;
1785
1786entry_count = XMLTagCount(CstateTag);
1787
1788if (entry_count > 0)
1789{
1790 {
1791 char *tmpstr;
1792
1793 if ((tmpstr = XMLCastString(XMLGetProperty(CstateTag, (const char*)"Base"))))
1794 {
1795
1796 entry_count--; // -= ("Base" tag)
1797
1798 int mybase = strtol(tmpstr, NULL, 10);
1799
1800 if (mybase == 8 || mybase == 10 || mybase == 16 )
1801 base = mybase;
1802 }
1803 }
1804
1805cpu->pkg_io_cstates.num_cstates = 0;
1806cpu->pkg_mwait_cstates.num_cstates = 0;
1807U32 num_cstates = 0;
1808
1809{
1810U32 i;
1811char MatchStat[5];
1812
1813for (i = 0; i < 32 ; i++)
1814{
1815char *Lat = NULL, *Pw = NULL, *BWidth= NULL, *BOffset= NULL, *Address= NULL, *AccessSize= NULL, *index= NULL;
1816
1817sprintf(MatchStat, "C%d",i);
1818TagPtr match_Status = XMLGetProperty(CstateTag, (const char*)MatchStat);
1819if (match_Status)
1820{
1821Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power"));
1822Lat = XMLCastString(XMLGetProperty(match_Status, (const char*)"Latency"));
1823BWidth= XMLCastString(XMLGetProperty(match_Status, (const char*)"BitWidth"));
1824
1825BOffset = XMLCastString(XMLGetProperty(match_Status, (const char*)"BitOffset"));
1826Address = XMLCastString(XMLGetProperty(match_Status, (const char*)"Latency"));
1827AccessSize = XMLCastString(XMLGetProperty(match_Status, (const char*)"AccessSize"));
1828index = XMLCastString(XMLGetProperty(match_Status, (const char*)"index"));
1829
1830if (Pw && Lat && BWidth && BOffset && Address && AccessSize && index)
1831{
1832U32 bw= strtoul((const char *)BWidth, NULL,base);
1833U32 boff= strtoul((const char *)BOffset, NULL,base);
1834U32 acs= strtoul((const char *)AccessSize, NULL,base);
1835U32 addr= strtoul((const char *)Address, NULL,base);
1836U32 idx= strtoul((const char *)index, NULL,base);
1837U32 lat= strtoul((const char *)Lat, NULL,base);
1838U32 pw= strtoul((const char *)Pw, NULL,base);
1839
1840ACPI_GENERIC_ADDRESS mwait_gas = {GAS_TYPE_FFH,bw,boff,acs,addr};
1841ACPI_GENERIC_ADDRESS io_gas = {(i == 1) ? GAS_TYPE_FFH : GAS_TYPE_SYSTEM_IO,bw,boff,acs,addr};
1842
1843CSTATE mwait_cstate = {idx,lat,pw};
1844CSTATE io_cstate = {idx,lat,pw};
1845
1846{
1847cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate;
1848cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas;
1849cpu->pkg_mwait_cstates.num_cstates++;
1850}
1851
1852{
1853cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate;
1854cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas;
1855cpu->pkg_io_cstates.num_cstates++;
1856}
1857num_cstates++;
1858
1859if (num_cstates >= MAX_CSTATES)
1860{
1861break;
1862}
1863}
1864}
1865}
1866}
1867
1868if (num_cstates)
1869{
1870return (1);
1871}
1872}
1873}
1874}
1875
1876{
1877static const ACPI_GENERIC_ADDRESS mwait_gas[] = {
1878{GAS_TYPE_FFH,1,2,1,0x00}, // processor C1
1879{GAS_TYPE_FFH,1,2,1,0x10}, // processor C3 as ACPI C2
1880{GAS_TYPE_FFH,1,2,1,0x10}, // processor C3 as ACPI C3
1881{GAS_TYPE_FFH,1,2,1,0x10}, // processor C3 as ACPI C4
1882{GAS_TYPE_FFH,1,2,1,0x20}, // processor C6
1883{GAS_TYPE_FFH,1,2,1,0x30}, // processor C7
1884};
1885
1886static const ACPI_GENERIC_ADDRESS io_gas[] = {
1887{GAS_TYPE_FFH, 0,0,0,0x00}, // processor C1
1888{GAS_TYPE_SYSTEM_IO,8,0,0,0x14}, // processor C3 as ACPI C2 or processor C2
1889{GAS_TYPE_SYSTEM_IO,8,0,0,0x14}, // processor C3 as ACPI C3
1890{GAS_TYPE_SYSTEM_IO,8,0,0,0x15}, // processor C4 as ACPI C4
1891{GAS_TYPE_SYSTEM_IO,8,0,0,0x15}, // processor C6
1892{GAS_TYPE_SYSTEM_IO,8,0,0,0x16}, // processor C7
1893};
1894
1895static const CSTATE mwait_cstate [] = {
1896{1,0x01,0x3e8}, // processor C1
1897{2,0x40,0x1f4}, // processor C3 as ACPI C2 or processor C2
1898{3,0x40,0x1f4}, // processor C3 as ACPI C3
1899{4,0x40,0x1f4}, // processor C4
1900{6/*was 3*/,0x60,0x15e}, // processor C6
1901{7/*was 3*/,0x60,0x0c8}, // processor C7
1902};
1903
1904static const CSTATE io_cstate [] = {
1905{1,0x01,0x3e8}, // processor C1
1906{2,0x40,0x1f4}, // processor C3 as ACPI C2 or processor C2
1907{3,0x40,0x1f4}, // processor C3 as ACPI C3
1908{4,0x40,0x1f4}, // processor C4
1909{6/*was 3*/,0x60,0x15e}, // processor C6
1910{7/*was 3*/,0x60,0x0c8}, // processor C7
1911};
1912
1913static const U32 cstate_2_index [] = {0,0,0,1,2,3,4,5};
1914
1915// Build C-state table info based on verified options
1916
1917// Desired state for the processor core C3 state included in the _CST as an
1918// ACPI C2 state.
1919// 1= processor core C3 can be used as an ACPI C2 state
1920// 0= processor core C3 cannot be used as an ACPI C2 state
1921int c2_enabled = 0;
1922
1923// Desired state for the processor core C3 state included in the _CST
1924// 0= processor core C3 cannot be used as an ACPI C state
1925// 2= processor core C3 can be used as an ACPI C2 state
1926// 3= processor core C3 can be used as an ACPI C3 state
1927// 4= processor core C3 can be used as an ACPI C2 state
1928// if Invariant APIC Timer detected, else not used as ACPI C state
1929// 5= processor core C3 can be used as an ACPI C2 state
1930// if Invariant APIC Timer detected, else APIC C3 state
1931// 6= processor core C3 can be used as an ACPI C4 state
1932int c3_enabled = 3;
1933
1934// Desired state for the processor core C3 state included in the _CST as an
1935// ACPI C4 state.
1936// 1= processor core C3 can be used as an ACPI C4 state
1937// 0= processor core C3 cannot be used as an ACPI C4 state
1938int c4_enabled = 0;
1939
1940// Desired state for the processor core C6 state included in the _CST as an
1941// ACPI C3 state.
1942// 1= processor core C6 can be used as an ACPI C3 state
1943// 0= processor core C6 cannot be used as an ACPI C3 state
1944int c6_enabled = 0;
1945
1946// Desired state for the processor core C7 state included in the _CST as an
1947// ACPI C3 state.
1948// 1= processor core C7 can be used as an ACPI C7 state
1949// 0= processor core C7 cannot be used as an ACPI C7 state
1950int c7_enabled = 0;
1951
1952{
1953bool tmpval;
1954
1955
1956if (getBoolForKey(kEnableC2State, &tmpval, &bootInfo->chameleonConfig))
1957{
1958c2_enabled = tmpval;
1959}
1960
1961if (!getIntForKey("C3StateOption", &c3_enabled, &bootInfo->chameleonConfig))
1962{
1963c3_enabled = (getBoolForKey(kEnableC3State, &tmpval, &bootInfo->chameleonConfig)&&tmpval) ? 3 : 0;
1964}
1965if (c3_enabled == 6)
1966{
1967c4_enabled = 1;
1968}
1969else
1970{
1971c4_enabled = (getBoolForKey(kEnableC4State, &tmpval, &bootInfo->chameleonConfig)&&tmpval) ? 1 : 0;
1972}
1973c6_enabled = (getBoolForKey(kEnableC6State, &tmpval, &bootInfo->chameleonConfig)&&tmpval) ? 1 : 0;
1974c7_enabled = (getBoolForKey(kEnableC7State, &tmpval, &bootInfo->chameleonConfig)&&tmpval) ? 1 : 0;
1975}
1976
1977cpu->pkg_mwait_cstates.num_cstates = 0;
1978{
1979{
1980cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C1]];
1981cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C1]];
1982cpu->pkg_mwait_cstates.num_cstates++;
1983}
1984if (((cpu->core_c3_supported || cpu->core_c2_supported) && (c2_enabled)) && ((c3_enabled == 2) ||
1985 ((c3_enabled == 4) && cpu->invariant_apic_timer_flag)))
1986{
1987cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C3_ACPI_C2]];
1988cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C3_ACPI_C2]];
1989cpu->pkg_mwait_cstates.num_cstates++;
1990}
1991if (cpu->core_c4_supported && c4_enabled)
1992{
1993
1994cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C4]];
1995cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C4]];
1996cpu->pkg_mwait_cstates.num_cstates++;
1997
1998}
1999else
2000{
2001
2002if (cpu->core_c3_supported && ((c3_enabled == 3) ||
2003 ((c3_enabled == 4) && !cpu->invariant_apic_timer_flag)))
2004{
2005cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C3_ACPI_C3]];
2006cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C3_ACPI_C3]];
2007cpu->pkg_mwait_cstates.num_cstates++;
2008}
2009}
2010
2011
2012if (cpu->core_c6_supported && c6_enabled)
2013{
2014cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C6]];
2015cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C6]];
2016cpu->pkg_mwait_cstates.num_cstates++;
2017}
2018if (cpu->core_c7_supported && c7_enabled)
2019{
2020cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C7]];
2021cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C7]];
2022cpu->pkg_mwait_cstates.num_cstates++;
2023}
2024}
2025
2026cpu->pkg_io_cstates.num_cstates = 0;
2027{
2028{
2029cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C1]];
2030cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C1]];
2031cpu->pkg_io_cstates.num_cstates++;
2032}
2033if ((cpu->core_c3_supported || cpu->core_c2_supported) && (c2_enabled || (c3_enabled == 2) ||
2034 ((c3_enabled == 4) && cpu->invariant_apic_timer_flag)))
2035{
2036cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C3_ACPI_C2]];
2037cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C3_ACPI_C2]];
2038cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase;
2039cpu->pkg_io_cstates.num_cstates++;
2040}
2041if (cpu->core_c4_supported && c4_enabled)
2042{
2043
2044cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C4]];
2045cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C4]];
2046cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase;
2047cpu->pkg_io_cstates.num_cstates++;
2048
2049}
2050else
2051{
2052
2053if (cpu->core_c3_supported && ((c3_enabled == 3) ||
2054 ((c3_enabled == 4) && !cpu->invariant_apic_timer_flag)))
2055{
2056cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C3_ACPI_C3]];
2057cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C3_ACPI_C3]];
2058cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase;
2059cpu->pkg_io_cstates.num_cstates++;
2060}
2061}
2062
2063if (cpu->core_c6_supported && c6_enabled)
2064{
2065cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C6]];
2066cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C6]];
2067cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase;
2068cpu->pkg_io_cstates.num_cstates++;
2069}
2070if (cpu->core_c7_supported && c7_enabled)
2071{
2072cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C7]];
2073cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C7]];
2074cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase;
2075cpu->pkg_io_cstates.num_cstates++;
2076}
2077}
2078}
2079
2080return (1);
2081}
2082
2083#if BUILD_ACPI_TSS
2084//-----------------------------------------------------------------------------
2085static U32 BuildTstateInfo(CPU_DETAILS * cpu)
2086{
2087 // Coarse grained clock modulation is available if cpuid.6.eax[5] = 0
2088 // Max of 8 T-states using 12.5% increments
2089 static const TSTATE tstate_coarse_grain [] = {
2090 {100,0,0,0x00,0},
2091 { 88,0,0,0x1e,0},
2092 { 75,0,0,0x1c,0},
2093 { 63,0,0,0x1a,0},
2094 { 50,0,0,0x18,0},
2095 { 38,0,0,0x16,0},
2096 { 25,0,0,0x14,0},
2097 { 13,0,0,0x12,0},
2098 };
2099
2100 // Fine grained clock modulation is available if cpuid.6.eax[5] = 1
2101 // Max of 15 T-states using 6.25% increments
2102 static const TSTATE tstate_fine_grain [] = {
2103 {100,0,0,0x00,0},
2104 { 94,0,0,0x1f,0},
2105 { 88,0,0,0x1e,0},
2106 { 81,0,0,0x1d,0},
2107 { 75,0,0,0x1c,0},
2108 { 69,0,0,0x1b,0},
2109 { 63,0,0,0x1a,0},
2110 { 56,0,0,0x19,0},
2111 { 50,0,0,0x18,0},
2112 { 44,0,0,0x17,0},
2113 { 38,0,0,0x16,0},
2114 { 31,0,0,0x15,0},
2115 { 25,0,0,0x14,0},
2116 { 19,0,0,0x13,0},
2117 { 13,0,0,0x12,0},
2118 };
2119
2120 // Build T-state table info based on verified options
2121 U32 num_cpu;
2122 const TSTATE * tstate;
2123 U32 num_tstates;
2124
2125 for (num_cpu = 0; num_cpu < cpu_map_count; num_cpu ++)
2126 {
2127 // Check if fine or coarse grained clock modulation is available
2128 if (get_env(envFineGrainClockMod))
2129 {
2130 // Fine grain thermal throttling is available
2131 num_tstates = 15;
2132 tstate = tstate_fine_grain;
2133 }
2134 else
2135 {
2136 // Coarse grain thermal throttling is available
2137 num_tstates = 8;
2138 tstate = tstate_coarse_grain;
2139 }
2140
2141 cpu->pkg_tstates.num_tstates = num_tstates;
2142 {
2143 U32 index;
2144 for (index = 0; index < num_tstates; index++)
2145 {
2146 cpu->pkg_tstates.tstate[index] = tstate[index];
2147 cpu->pkg_tstates.tstate[index].power = 1000 * (compute_tdp(cpu) * (num_tstates - index)) / num_tstates;
2148 }
2149 }
2150
2151
2152 }
2153 return (1);
2154}
2155#endif // BUILD_ACPI_TSS
2156
2157//-----------------------------------------------------------------------------
2158U32 ProcessMadt(ACPI_TABLE_MADT * madt, MADT_INFO * madt_info, void * buffer, U32 bufferSize, U32 nb_cpu)
2159{
2160 void *current;
2161 void *currentOut;
2162 void *end;
2163 void * endOut;
2164
2165 U32 LOCAL_APIC_NMI_CNT = 0, LOCAL_SAPIC_CNT = 0, INT_SRC_CNT = 0, Length = 0;
2166
2167 // Quick sanity check for a valid MADT
2168 if (madt == 0ul || !nb_cpu)
2169 return (0);
2170
2171 // Confirm a valid MADT buffer was provided
2172 if (!buffer)
2173 {
2174 printf("Error: Invalid Buffer Address for MADT\n");
2175 return(0);
2176 }
2177
2178 // Confirm a valid MADT buffer length was provided
2179 if (!bufferSize)
2180 {
2181 printf("Error: Invalid Buffer Length for MADT\n");
2182 return(0);
2183 }
2184
2185 madt_info->lapic_count = 0;
2186
2187 memcpy(buffer, madt, sizeof(ACPI_TABLE_MADT));
2188
2189 // Search MADT for Sub-tables with needed data
2190 current = madt + 1;
2191 currentOut = buffer + sizeof(ACPI_TABLE_MADT) ;
2192
2193 end = (U8 *) madt + madt->Header.Length;
2194 endOut = (U8 *)buffer + bufferSize;
2195
2196 // Check to confirm no MADT buffer overflow
2197 if ( (U8 *)currentOut > (U8 *)endOut )
2198 {
2199 printf("Error: MADT Buffer Length exceeded available space \n");
2200 return(0);
2201 }
2202
2203 Length += sizeof(ACPI_TABLE_MADT);
2204
2205 while (current < end)
2206{
2207 ACPI_SUBTABLE_HEADER *subtable = current;
2208 ACPI_SUBTABLE_HEADER *subtableOut = currentOut;
2209
2210
2211 switch (subtable->Type)
2212{
2213
2214case ACPI_MADT_TYPE_LOCAL_APIC:
2215 {
2216
2217 // Process sub-tables with Type as 0: Processor Local APIC
2218 ACPI_MADT_LOCAL_APIC *lapic = current;
2219 current = lapic + 1;
2220
2221 if (!(lapic->LapicFlags & ACPI_MADT_ENABLED))
2222 continue;
2223
2224 if (madt_info->lapic_count >= nb_cpu)
2225 continue;
2226
2227 // copy subtable
2228 {
2229
2230 memcpy(currentOut, lapic, lapic->Header.Length);
2231
2232 currentOut = currentOut + lapic->Header.Length;
2233
2234 // Check to confirm no MADT buffer overflow
2235 if ( (U8 *)currentOut > (U8 *)endOut )
2236 {
2237 printf("Error: MADT Buffer Length exceeded available space \n");
2238 return(0);
2239 }
2240 }
2241
2242 {
2243 LAPIC_INFO *lapic_info = &madt_info->lapic[madt_info->lapic_count];
2244
2245 lapic_info->processorId = lapic->ProcessorId;
2246 lapic_info->apicId = lapic->Id;
2247 lapic_info->madt_type = ACPI_MADT_TYPE_LOCAL_APIC;
2248 }
2249
2250 madt_info->lapic_count++;
2251
2252 Length += lapic->Header.Length;
2253
2254 // Sanity check to verify compile time limit for max logical CPU is not exceeded
2255 if (madt_info->lapic_count > MAX_LOGICAL_CPU)
2256 return (0);
2257
2258 break;
2259 }
2260
2261case ACPI_MADT_TYPE_X2APIC:
2262 {
2263
2264 // Process sub-tables with Type as 9: Processor X2APIC
2265 ACPI_MADT_X2APIC *x2apic = current;
2266 current = x2apic + 1;
2267
2268 if (!(x2apic->x2apicFlags & ACPI_MADT_ENABLED))
2269 continue;
2270
2271 if (madt_info->lapic_count >= nb_cpu)
2272 continue;
2273
2274 // copy subtable
2275 {
2276 memcpy(currentOut, x2apic, x2apic->Header.Length);
2277
2278 currentOut = currentOut + x2apic->Header.Length;
2279
2280 // Check to confirm no MADT buffer overflow
2281 if ( (U8 *)currentOut > (U8 *)endOut )
2282 {
2283 printf("Error: MADT Buffer Length exceeded available space \n");
2284 return(0);
2285 }
2286
2287 }
2288
2289 {
2290 LAPIC_INFO *lapic_info = &madt_info->lapic[madt_info->lapic_count];
2291
2292 lapic_info->uid = x2apic->UID;
2293 lapic_info->apicId = x2apic->x2apicId;
2294 lapic_info->madt_type = ACPI_MADT_TYPE_X2APIC;
2295 }
2296
2297 madt_info->lapic_count++;
2298
2299 Length += x2apic->Header.Length;
2300
2301 // Sanity check to verify compile time limit for max logical CPU is not exceeded
2302 if (madt_info->lapic_count > MAX_LOGICAL_CPU)
2303 return (0);
2304
2305 break;
2306 }
2307
2308 case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
2309 {
2310 // Process sub-tables with Type as 4: Local APIC NMI
2311 ACPI_MADT_LOCAL_APIC_NMI *nmi = current;
2312 current = nmi + 1;
2313 /*
2314 if (!(nmi->IntiFlags & ACPI_MADT_ENABLED))
2315 continue;
2316 */
2317 if (LOCAL_APIC_NMI_CNT >= nb_cpu)
2318 continue;
2319
2320 memcpy(currentOut, nmi, nmi->Header.Length);
2321
2322 currentOut = currentOut + nmi->Header.Length;
2323
2324 // Check to confirm no MADT buffer overflow
2325 if ( (U8 *)currentOut > (U8 *)endOut )
2326 {
2327 printf("Error: MADT Buffer Length exceeded available space \n");
2328 return(0);
2329 }
2330
2331
2332 LOCAL_APIC_NMI_CNT++;
2333
2334 Length += nmi->Header.Length;
2335
2336 // Sanity check to verify compile time limit for max logical CPU is not exceeded
2337 if (LOCAL_APIC_NMI_CNT > MAX_LOGICAL_CPU)
2338 return (0);
2339
2340 break;
2341 }
2342
2343 case ACPI_MADT_TYPE_LOCAL_SAPIC:
2344 {
2345 // Process sub-tables with Type as 7: Local Sapic
2346 ACPI_MADT_LOCAL_SAPIC *sapic = current;
2347 current = sapic + 1;
2348 /*
2349 if (!(sapic->LapicFlags & ACPI_MADT_ENABLED))
2350 continue;
2351 */
2352 if (LOCAL_SAPIC_CNT >= nb_cpu)
2353 continue;
2354
2355 memcpy(currentOut, sapic, sapic->Header.Length);
2356
2357 currentOut = currentOut + sapic->Header.Length;
2358
2359 // Check to confirm no MADT buffer overflow
2360 if ( (U8 *)currentOut > (U8 *)endOut )
2361 {
2362 printf("Error: MADT Buffer Length exceeded available space \n");
2363 return(0);
2364 }
2365
2366
2367 LOCAL_SAPIC_CNT++;
2368
2369 Length += sapic->Header.Length;
2370
2371 // Sanity check to verify compile time limit for max logical CPU is not exceeded
2372 if (LOCAL_SAPIC_CNT > MAX_LOGICAL_CPU)
2373 return (0);
2374
2375 break;
2376 }
2377
2378 case ACPI_MADT_TYPE_INTERRUPT_SOURCE:
2379 {
2380 // Process sub-tables with Type as 8: Platform Interrupt Source
2381 ACPI_MADT_INTERRUPT_SOURCE *intsrc = current;
2382 current = intsrc + 1;
2383 /*
2384 if (!(intsrc->IntiFlags & ACPI_MADT_ENABLED))
2385 continue;
2386 */
2387 if (INT_SRC_CNT >= nb_cpu)
2388 continue;
2389
2390 memcpy(currentOut, intsrc, intsrc->Header.Length);
2391
2392 currentOut = currentOut + intsrc->Header.Length;
2393
2394 // Check to confirm no MADT buffer overflow
2395 if ( (U8 *)currentOut > (U8 *)endOut )
2396 {
2397 printf("Error: MADT Buffer Length exceeded available space \n");
2398 return(0);
2399 }
2400
2401
2402 INT_SRC_CNT++;
2403
2404 Length += intsrc->Header.Length;
2405
2406 // Sanity check to verify compile time limit for max logical CPU is not exceeded
2407 if (INT_SRC_CNT > MAX_LOGICAL_CPU)
2408 return (0);
2409
2410 break;
2411 }
2412
2413default:
2414 {
2415
2416 // Process all other sub-tables
2417 current = (U8 *) subtable + subtable->Length;
2418 currentOut = (U8 *) subtableOut + subtable->Length;
2419
2420 memcpy(subtableOut, subtable, subtable->Length);
2421
2422 // Check to confirm no MADT buffer overflow
2423 if ( (U8 *)currentOut > (U8 *)endOut )
2424 {
2425 printf("Error: MADT Buffer Length exceeded available space \n");
2426 return(0);
2427 }
2428
2429 Length += subtable->Length;
2430
2431 break;
2432 }
2433 } // switch
2434
2435 } // while
2436
2437 {
2438 ACPI_TABLE_MADT * new_madt = (ACPI_TABLE_MADT * )buffer;
2439
2440 // Update the Lenght of the new MADT table
2441 new_madt->Header.Length = Length;
2442
2443 // Update the checksum of the new MADT table
2444SetChecksum(&new_madt->Header);
2445 }
2446
2447 return (1);
2448}
2449
2450static U32 buildMADT(U32 * new_table_list, ACPI_TABLE_DSDT *dsdt, MADT_INFO * madt_info)
2451{
2452 DBG("Build MADT\n");
2453
2454ACPI_TABLE_MADT * madt_file = (void*)0ul;
2455ACPI_TABLE_MADT * MadtPointer = (void*)0ul;
2456 bool oem_apic=false;
2457 U8 new_table_index = 0;
2458
2459 // Check that we have a valid cpu_map (if it's not already done, it will try to generate it)
2460 if (generate_cpu_map_from_acpi(dsdt) != 0)
2461 {
2462 return(0);
2463 }
2464
2465 {
2466bool tmpval;
2467oem_apic=getBoolForKey(kOEMAPIC, &tmpval, &bootInfo->chameleonConfig)&&tmpval;
2468}
2469
2470 if (oem_apic == true)
2471 {
2472 return(0);
2473 }
2474
2475 if ((madt_file = (ACPI_TABLE_MADT *)get_new_table_in_list(new_table_list, NAMESEG("APIC"), &new_table_index)) != (void *)0ul)
2476{
2477 MadtPointer = (ACPI_TABLE_MADT *)madt_file;
2478
2479 new_table_list[new_table_index] = 0ul; // This way, the non-patched table will not be added in our new rsdt/xsdt table list
2480}
2481 else
2482 {
2483 MadtPointer = (acpi_tables.MadtPointer64 != (void*)0ul) ? (ACPI_TABLE_MADT *)acpi_tables.MadtPointer64 : (ACPI_TABLE_MADT *)acpi_tables.MadtPointer;
2484
2485 new_table_index = get_0ul_index_in_list(new_table_list, true);
2486
2487 // Check to confirm space is available
2488 if (new_table_index == ACPI_TABLE_LIST_FULL)
2489 {
2490 printf("Error: not enought reserved space in the new acpi list for the MADT table,\n ");
2491 printf(" please increase the RESERVED_AERA\n");
2492 return(0);
2493 }
2494 }
2495
2496 // Create buffer for MADT
2497 //U8 memory_for_madt[2 * 1024]; // seems to bug with xcode4, need to found out what is going on (not enough memory in the stack ?)
2498 U8 *memory_for_madt = (U8*)AllocateKernelMemory(2 * 1024);
2499
2500 // Build the new MADT
2501 if ( (ProcessMadt(MadtPointer, madt_info, memory_for_madt, 2 * 1024, cpu_map_count))== 0)
2502{
2503printf("Error: Failed to build MADT table\n");
2504return (0);
2505}
2506
2507// insert MADT in the new_table_list
2508{
2509// Create pointer to MADT just built in the stack buffer
2510ACPI_TABLE_MADT * old_madt = (ACPI_TABLE_MADT *)memory_for_madt;
2511
2512// Reserved kernel memory for the madt table
2513ACPI_TABLE_MADT *new_madt = (ACPI_TABLE_MADT *)AllocateKernelMemory(old_madt->Header.Length);
2514
2515if (!new_madt)
2516{
2517printf("Unable to allocate kernel memory for MADT ");
2518return (0);
2519}
2520// Move the old stack buffer to kernel memory
2521memcpy(new_madt, old_madt, old_madt->Header.Length);
2522
2523// Add the new madt into an empty space of the new_table_list
2524new_table_list[new_table_index] = (U32)new_madt;
2525}
2526
2527 verbose ("MADT table successfully patched\n");
2528return(1);
2529}
2530
2531static U32 ProcessSsdt(U32 * new_table_list, ACPI_TABLE_DSDT *dsdt, MADT_INFO * madt_info, bool enable_cstates, bool enable_pstates, bool enable_tstates )
2532{
2533DBG("Processing SSDT\n");
2534
2535// Check we are on an intel platform
2536if (Platform.CPU.Vendor != CPUID_VENDOR_INTEL) {
2537verbose ("Not an Intel platform: SSDT will not be generated !!!\n");
2538return(0);
2539}
2540
2541// Check for the msr feature flag
2542if (!(Platform.CPU.Features & CPU_FEATURE_MSR)) {
2543verbose ("Unsupported CPU: SSDT will not be generated !!!\n");
2544return(0);
2545}
2546
2547if (dsdt == (void *)0ul) {
2548verbose ("DSDT not found: SSDT will not be generated !!!\n");
2549return (0);
2550}
2551
2552// Get an empty space in the new_talbe_list (true = allow reserved space)
2553U8 empty = get_0ul_index_in_list(new_table_list, true);
2554
2555// Check to confirm space is available
2556if (empty == ACPI_TABLE_LIST_FULL)
2557{
2558printf("Error: not enought reserved space in the new acpi list for the SSDT table,\n ");
2559printf(" please increase the RESERVED_AERA\n");
2560return(0);
2561}
2562
2563// Create buffer for SSDT
2564//U8 memory_for_ssdt[20 * 1024];// seems to bug with xcode4, need to found out what is going on (not enough memory in the stack ?)
2565U8 *memory_for_ssdt =(U8*)AllocateKernelMemory(20 * 1024);
2566
2567// Build the SSDT
2568if ( (BuildSsdt(madt_info, dsdt, memory_for_ssdt, 20 * 1024 /*sizeof(memory_for_ssdt)*/, enable_cstates, enable_pstates, enable_tstates)) == 0)
2569{
2570printf("Error: Failed to build SSDT table\n");
2571return (0);
2572}
2573
2574// insert SSDT in the new_table_list
2575{
2576// Create pointer to SSDT just built in the stack buffer
2577ACPI_TABLE_SSDT * old_ssdt = (ACPI_TABLE_SSDT *)memory_for_ssdt;
2578
2579// Reserved kernel memory for the ssdt table
2580ACPI_TABLE_SSDT *new_ssdt = (ACPI_TABLE_SSDT *)AllocateKernelMemory(old_ssdt->Header.Length);
2581
2582if (!new_ssdt)
2583{
2584printf("Unable to allocate kernel memory for SSDT ");
2585return (0);
2586}
2587// Move the old stack buffer to kernel memory
2588memcpy(new_ssdt, old_ssdt, old_ssdt->Header.Length);
2589
2590// Add the new ssdt into an empty space of the new_table_list
2591new_table_list[empty] = (U32)new_ssdt;
2592}
2593
2594verbose ("SSDT table generated successfully\n");
2595return(1);
2596}
2597
2598//-----------------------------------------------------------------------------
2599static void * buildCpuScope (void * current, U32 cpu_namespace, PROCESSOR_NUMBER_TO_NAMESEG * aslCpuNamePath)
2600{
2601ACPI_SCOPE * scope = current;
2602current = scope + 1;
2603
2604scope->scopeOpcode = AML_SCOPE_OP;
2605scope->rootChar = AML_ROOT_PREFIX;
2606
2607if (aslCpuNamePath->seg_count == 1)
2608{
2609DUAL_NAME_PATH * dualNamePath = current;
2610current = dualNamePath + 1;
2611dualNamePath->prefix = AML_DUAL_NAME_PREFIX;
2612dualNamePath->nameseg[0] = cpu_namespace;
2613dualNamePath->nameseg[1] = aslCpuNamePath->nameseg[0];
2614}
2615else
2616{
2617MULTI_NAME_PATH * multiNamePath = current;
2618current = multiNamePath + 1;
2619multiNamePath->prefix = AML_MULTI_NAME_PREFIX;
2620// the nameseg count includes the root prefix and all other namesegs
2621multiNamePath->segCount = (U8) aslCpuNamePath->seg_count+1;
2622multiNamePath->nameseg[0] = cpu_namespace;
2623{
2624U32 i;
2625for (i=0; i<aslCpuNamePath->seg_count; i++)
2626multiNamePath->nameseg[i+1] = aslCpuNamePath->nameseg[i];
2627}
2628}
2629return (current);
2630}
2631//-----------------------------------------------------------------------------
2632static void * buildPDC(void * current)
2633{
2634ACPI_METHOD * pdc = current;
2635current = buildMethod(current, NAMESEG("_PDC"), 1);
2636
2637// CreateDWordField (Arg0, 0x08, CAPA)
2638current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2639current = buildOpCode(current, AML_ARG0_OP);
2640current = buildByteConst(current, 0x08);
2641current = buildNameSeg(current, NAMESEG("CAPA"));
2642
2643// Store (CAPA, TYPE)
2644current = buildOpCode(current, AML_STORE_OP);
2645current = buildNameSeg(current, NAMESEG("CAPA"));
2646current = buildNameSeg(current, NAMESEG("TYPE"));
2647
2648// CreateDWordField (Arg0, 0x00, REVS)
2649current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2650current = buildOpCode(current, AML_ARG0_OP);
2651current = buildByteConst(current, 0x00);
2652current = buildNameSeg(current, NAMESEG("REVS"));
2653
2654// CreateDWordField (Arg0, 0x04, SIZE)
2655current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2656current = buildOpCode(current, AML_ARG0_OP);
2657current = buildByteConst(current, 0x04);
2658current = buildNameSeg(current, NAMESEG("SIZE"));
2659
2660// Store(SizeOf(Arg0), Local0)
2661current = buildOpCode(current, AML_STORE_OP);
2662current = buildOpCode(current, AML_SIZEOF_OP);
2663current = buildOpCode(current, AML_ARG0_OP);
2664current = buildOpCode(current, AML_LOCAL0_OP);
2665
2666// Store(Subtract(Local0, 0x08),Local1)
2667current = buildOpCode(current, AML_STORE_OP);
2668current = buildOpCode(current, AML_SUBTRACT_OP);
2669current = buildOpCode(current, AML_LOCAL0_OP);
2670current = buildByteConst(current, 0x08);
2671current = buildOpCode(current, AML_ZERO_OP);
2672current = buildOpCode(current, AML_LOCAL1_OP);
2673
2674// CreateField (Arg0, 0x40, Multiply (Local1, 0x08), TEMP)
2675current = buildOpCode(current, AML_EXT_OP_PREFIX);
2676current = buildOpCode(current, AML_CREATE_FIELD_OP);
2677current = buildOpCode(current, AML_ARG0_OP);
2678current = buildByteConst(current, 0x40);
2679current = buildOpCode(current, AML_MULTIPLY_OP);
2680current = buildOpCode(current, AML_LOCAL1_OP);
2681current = buildByteConst(current, 0x08);
2682current = buildOpCode(current, AML_ZERO_OP);
2683current = buildNameSeg(current, NAMESEG("TEMP"));
2684
2685// Name (STS0, Buffer (0x04) {0x00, 0x00, 0x00, 0x00})
2686// Create STS0 as named buffer
2687current = buildNamePath(current, NAMESEG("STS0"));
2688{
2689ACPI_SMALL_BUFFER * buff = current;
2690current = buildSmallBuffer(current);
2691
2692// count of buffer elements
2693current = buildByteConst(current, 4);
2694
2695current = buildOpCode(current, AML_ZERO_OP);
2696current = buildOpCode(current, AML_ZERO_OP);
2697current = buildOpCode(current, AML_ZERO_OP);
2698current = buildOpCode(current, AML_ZERO_OP);
2699{
2700U32 length = (U8 *)current - (U8 *)buff;
2701buff->packageLength = (U8)length - 1;
2702}
2703}
2704
2705//Concatenate (STS0, TEMP, Local2)
2706current = buildOpCode(current, AML_CONCAT_OP);
2707current = buildNameSeg(current, NAMESEG("STS0"));
2708current = buildNameSeg(current, NAMESEG("TEMP"));
2709current = buildOpCode(current, AML_LOCAL2_OP);
2710
2711//_OSC (Buffer (0x10)
2712// {
2713// /* 0000 */ 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47,
2714// /* 0008 */ 0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53
2715// }, REVS, SIZE, Local2)
2716current = buildNameSeg(current, NAMESEG("_OSC"));
2717{
2718ACPI_SMALL_BUFFER * buff = current;
2719current = buildSmallBuffer(current);
2720
2721// count of buffer elements
2722current = buildByteConst(current, 0x10);
2723
2724current = buildOpCode(current, 0x16);
2725current = buildOpCode(current, 0xa6);
2726current = buildOpCode(current, 0x77);
2727current = buildOpCode(current, 0x40);
2728current = buildOpCode(current, 0x0c);
2729current = buildOpCode(current, 0x29);
2730current = buildOpCode(current, 0xbe);
2731current = buildOpCode(current, 0x47);
2732current = buildOpCode(current, 0x9e);
2733current = buildOpCode(current, 0xbd);
2734current = buildOpCode(current, 0xd8);
2735current = buildOpCode(current, 0x70);
2736current = buildOpCode(current, 0x58);
2737current = buildOpCode(current, 0x71);
2738current = buildOpCode(current, 0x39);
2739current = buildOpCode(current, 0x53);
2740{
2741U32 length = (U8 *)current - (U8 *)buff;
2742buff->packageLength = (U8)length - 1;
2743}
2744}
2745current = buildNameSeg(current, NAMESEG("REVS"));
2746current = buildNameSeg(current, NAMESEG("SIZE"));
2747current = buildOpCode(current, AML_LOCAL2_OP);
2748
2749// Update package length in PDC object
2750//pdc->packageLength = (U8)((U8 *)current - (U8 *)&pdc->packageLength);
2751setPackageLength(&pdc->pkgLength, (U8 *)current - (U8 *)&pdc->pkgLength);
2752
2753return(current);
2754}
2755
2756//-----------------------------------------------------------------------------
2757static void * buildOSC(void * current)
2758{
2759//
2760//
2761ACPI_METHOD * osc = current;
2762current = buildMethod(current, NAMESEG("_OSC"), 4);
2763
2764// CreateDWordField (Arg3, 0x04, CAPA)
2765current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2766current = buildOpCode(current, AML_ARG3_OP);
2767current = buildByteConst(current, 0x04);
2768current = buildNameSeg(current, NAMESEG("CAPA"));
2769
2770// Store (CAPA, TYPE)
2771current = buildOpCode(current, AML_STORE_OP);
2772current = buildNameSeg(current, NAMESEG("CAPA"));
2773current = buildNameSeg(current, NAMESEG("TYPE"));
2774
2775// CreateDWordField (Arg3, 0x00, STS0)
2776current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2777current = buildOpCode(current, AML_ARG3_OP);
2778current = buildByteConst(current, 0x00);
2779current = buildNameSeg(current, NAMESEG("STS0"));
2780
2781// CreateDWordField (Arg3, 0x04, CAP0)
2782current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2783current = buildOpCode(current, AML_ARG3_OP);
2784current = buildByteConst(current, 0x04);
2785current = buildNameSeg(current, NAMESEG("CAP0"));
2786
2787// CreateDWordField (Arg0, 0x00, IID0)
2788current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2789current = buildOpCode(current, AML_ARG0_OP);
2790current = buildByteConst(current, 0x00);
2791current = buildNameSeg(current, NAMESEG("IID0"));
2792
2793// CreateDWordField (Arg0, 0x04, IID1)
2794current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2795current = buildOpCode(current, AML_ARG0_OP);
2796current = buildByteConst(current, 0x04);
2797current = buildNameSeg(current, NAMESEG("IID1"));
2798
2799// CreateDWordField (Arg0, 0x08, IID2)
2800current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2801current = buildOpCode(current, AML_ARG0_OP);
2802current = buildByteConst(current, 0x08);
2803current = buildNameSeg(current, NAMESEG("IID2"));
2804
2805// CreateDWordField (Arg0, 0x0C, IID3)
2806current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2807current = buildOpCode(current, AML_ARG0_OP);
2808current = buildByteConst(current, 0x0C);
2809current = buildNameSeg(current, NAMESEG("IID3"));
2810
2811// Name (UID0, Buffer (0x10)
2812// {
2813// 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47,
2814// 0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53
2815// })
2816current = buildNamePath(current, NAMESEG("UID0"));
2817{
2818ACPI_SMALL_BUFFER * buff = current;
2819current = buildSmallBuffer(current);
2820
2821// count of buffer elements
2822current = buildByteConst(current, 0x10);
2823
2824current = buildOpCode(current, 0x16);
2825current = buildOpCode(current, 0xa6);
2826current = buildOpCode(current, 0x77);
2827current = buildOpCode(current, 0x40);
2828current = buildOpCode(current, 0x0c);
2829current = buildOpCode(current, 0x29);
2830current = buildOpCode(current, 0xbe);
2831current = buildOpCode(current, 0x47);
2832current = buildOpCode(current, 0x9e);
2833current = buildOpCode(current, 0xbd);
2834current = buildOpCode(current, 0xd8);
2835current = buildOpCode(current, 0x70);
2836current = buildOpCode(current, 0x58);
2837current = buildOpCode(current, 0x71);
2838current = buildOpCode(current, 0x39);
2839current = buildOpCode(current, 0x53);
2840
2841{
2842U32 length = (U8 *)current - (U8 *)buff;
2843buff->packageLength = (U8)length - 1;
2844}
2845}
2846
2847// CreateDWordField (UID0, 0x00, EID0)
2848current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2849current = buildOpCode(current, AML_ARG0_OP);
2850current = buildByteConst(current, 0x00);
2851current = buildNameSeg(current, NAMESEG("EID0"));
2852
2853// CreateDWordField (UID0, 0x04, EID1)
2854current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2855current = buildOpCode(current, AML_ARG0_OP);
2856current = buildByteConst(current, 0x04);
2857current = buildNameSeg(current, NAMESEG("EID1"));
2858
2859// CreateDWordField (UID0, 0x08, EID2)
2860current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2861current = buildOpCode(current, AML_ARG0_OP);
2862current = buildByteConst(current, 0x08);
2863current = buildNameSeg(current, NAMESEG("EID2"));
2864
2865// CreateDWordField (UID0, 0x0C, EID3)
2866current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2867current = buildOpCode(current, AML_ARG0_OP);
2868current = buildByteConst(current, 0x0C);
2869current = buildNameSeg(current, NAMESEG("EID3"));
2870
2871// If (LNot (LAnd (LAnd (LEqual (IID0, EID0), LEqual (IID1, EID1)),
2872// LAnd (LEqual (IID2, EID2), LEqual (IID3, EID3)))))
2873// {
2874// Store (0x06, Index (STS0, 0x00))
2875// Return (Arg3)
2876// }
2877{
2878current = buildOpCode(current, AML_IF_OP);
2879{
2880ACPI_PACKAGE_LENGTH * packageLength = current;
2881current = buildPackageLength(current, 0);
2882
2883current = buildOpCode(current, AML_LNOT_OP);
2884current = buildOpCode(current, AML_LAND_OP);
2885current = buildOpCode(current, AML_LAND_OP);
2886current = buildOpCode(current, AML_LEQUAL_OP);
2887current = buildNameSeg(current, NAMESEG("IID0"));
2888current = buildNameSeg(current, NAMESEG("EID0"));
2889
2890current = buildOpCode(current, AML_LEQUAL_OP);
2891current = buildNameSeg(current, NAMESEG("IID1"));
2892current = buildNameSeg(current, NAMESEG("EID1"));
2893
2894current = buildOpCode(current, AML_LAND_OP);
2895current = buildOpCode(current, AML_LEQUAL_OP);
2896current = buildNameSeg(current, NAMESEG("IID2"));
2897current = buildNameSeg(current, NAMESEG("EID2"));
2898
2899current = buildOpCode(current, AML_LEQUAL_OP);
2900current = buildNameSeg(current, NAMESEG("IID3"));
2901current = buildNameSeg(current, NAMESEG("EID3"));
2902
2903// Store (0x06, Index (STS0, 0x00))
2904current = buildOpCode(current, AML_STORE_OP);
2905current = buildByteConst(current, 0x06);
2906current = buildOpCode(current, AML_INDEX_OP);
2907current = buildNameSeg(current, NAMESEG("STS0"));
2908current = buildByteConst(current, 0x00);
2909current = buildOpCode(current, AML_ZERO_OP);
2910
2911// Return (Arg3)
2912current = buildReturnOpcode(current, AML_ARG3_OP);
2913
2914setPackageLength(packageLength,
2915 (U8 *)current - (U8 *)packageLength);
2916}
2917}
2918
2919// If (LNotEqual (Arg1, 0x01))
2920// {
2921// Store (0x0A, Index (STS0, 0x00))
2922// Return (Arg3)
2923// }
2924{
2925current = buildOpCode(current, AML_IF_OP);
2926{
2927ACPI_PACKAGE_LENGTH * packageLength = current;
2928current = buildPackageLength(current, 0);
2929
2930// If ("LNotEqual (Arg1, 0x01)")
2931current = buildOpCode(current, AML_LNOT_OP);
2932current = buildOpCode(current, AML_LEQUAL_OP);
2933current = buildOpCode(current, AML_ARG1_OP);
2934current = buildByteConst(current, 0x01);
2935
2936// Store (0x0A, Index (STS0, 0x00))
2937current = buildOpCode(current, AML_STORE_OP);
2938current = buildByteConst(current, 0x0A);
2939current = buildOpCode(current, AML_INDEX_OP);
2940current = buildNameSeg(current, NAMESEG("STS0"));
2941current = buildByteConst(current, 0x00);
2942current = buildOpCode(current, AML_ZERO_OP);
2943
2944// Return (Arg3)
2945current = buildReturnOpcode(current, AML_ARG3_OP);
2946
2947setPackageLength(packageLength,
2948 (U8 *)current - (U8 *)packageLength);
2949}
2950}
2951
2952// If (And (STS0, 0x01))
2953// {
2954// And (CAP0, 0x0BFF, CAP0)
2955// Return (Arg3)
2956// }
2957{
2958current = buildOpCode(current, AML_IF_OP);
2959{
2960ACPI_PACKAGE_LENGTH * packageLength = current;
2961current = buildPackageLength(current, 0);
2962
2963// If ("And (STS0, 0x01)")
2964current = buildOpCode(current, AML_AND_OP);
2965current = buildNameSeg(current, NAMESEG("STS0"));
2966current = buildByteConst(current, 0x01);
2967current = buildOpCode(current, AML_ZERO_OP);
2968
2969// And (CAP0, 0x0BFF, CAP0)
2970current = buildOpCode(current, AML_AND_OP);
2971current = buildNameSeg(current, NAMESEG("CAP0"));
2972current = buildWordConst(current, 0x0BFF);
2973current = buildNameSeg(current, NAMESEG("CAP0"));
2974
2975// Return (Arg3)
2976current = buildReturnOpcode(current, AML_ARG3_OP);
2977
2978setPackageLength(packageLength,
2979 (U8 *)current - (U8 *)packageLength);
2980}
2981}
2982
2983// And (CAP0, 0x0BFF, CAP0)
2984current = buildOpCode(current, AML_AND_OP);
2985current = buildNameSeg(current, NAMESEG("CAP0"));
2986current = buildWordConst(current, 0x0BFF);
2987current = buildNameSeg(current, NAMESEG("CAP0"));
2988
2989// Store (CAP0, TYPE)
2990current = buildOpCode(current, AML_STORE_OP);
2991current = buildNameSeg(current, NAMESEG("CAP0"));
2992current = buildNameSeg(current, NAMESEG("TYPE"));
2993
2994// Return (Arg3)
2995current = buildReturnOpcode(current, AML_ARG3_OP);
2996
2997// Set package length for the OSC object
2998setPackageLength(&osc->pkgLength, (U8 *)current - (U8 *)&osc->pkgLength);
2999
3000return(current);
3001}
3002
3003//-----------------------------------------------------------------------------
3004static void * buildPSS(void * current, PKG_PSTATES * pkg_pstates)
3005{
3006//
3007// IF (PSEN)
3008// {
3009// Return (Package of Pstate Packages)
3010// }
3011// Return(Zero)
3012//
3013ACPI_METHOD * pss = current;
3014current = buildMethod(current, NAMESEG("_PSS"), 0);
3015
3016{
3017// "IF" (PSEN) -- IF Opcode
3018current = buildOpCode(current, AML_IF_OP);
3019{
3020ACPI_PACKAGE_LENGTH * packageLength = current;
3021current = buildPackageLength(current, 0);
3022
3023// IF "(PSEN)" -- IF Predicate
3024current = buildNameSeg(current, NAMESEG("PSEN"));
3025
3026{
3027ACPI_RETURN_PACKAGE * returnPkg = current;
3028current = buildReturnPackage(current, (U8)pkg_pstates->num_pstates);
3029
3030// (3.3.3) For each P-state
3031{
3032U32 pstateIndex = 0;
3033for (pstateIndex=0; pstateIndex < pkg_pstates->num_pstates; pstateIndex++)
3034{
3035// (3.3.3.1) Create P-state package
3036ACPI_PSTATE_PACKAGE * pstate = current;
3037current = pstate + 1;
3038
3039setSmallPackage(&pstate->package, 6);
3040pstate->package.packageLength = (U8)(sizeof(ACPI_PSTATE_PACKAGE) - 1);
3041
3042setDwordConst(&pstate->CoreFreq, pkg_pstates->pstate[pstateIndex].frequency);// CoreFreq (in MHz).
3043setDwordConst(&pstate->Power, pkg_pstates->pstate[pstateIndex].power);// Power (in milliWatts).
3044setDwordConst(&pstate->TransLatency, pkg_pstates->pstate[pstateIndex].translatency);// Transition Latency (in microseconds).
3045setDwordConst(&pstate->BMLatency, pkg_pstates->pstate[pstateIndex].bmlatency);// Bus Master Latency (in microseconds).
3046setDwordConst(&pstate->Control, pkg_pstates->pstate[pstateIndex].control); // Control.
3047
3048setDwordConst(&pstate->Status, encode_pstate(pkg_pstates->pstate[pstateIndex].ratio));// Status.
3049} // for
3050} // for block
3051
3052// (3.3.4) Update package length in return package
3053setPackageLength(&returnPkg->package.pkgLength, (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3054}
3055
3056// "IF (PSEN) and its body" -- Set package length
3057setPackageLength(packageLength,
3058 (U8 *)current - (U8 *)packageLength);
3059}
3060// "Return (ZERO)"
3061current = buildReturnZero(current);
3062}
3063// Set package length for the _PSS object
3064setPackageLength(&pss->pkgLength, (U8 *)current - (U8 *)&pss->pkgLength);
3065
3066return(current);
3067}
3068
3069//-----------------------------------------------------------------------------
3070static void * buildPSD(void * current, U32 domain, U32 cpusInDomain, U32 pstate_coordination)
3071{
3072// If (And(TYPE, 0x0820))
3073// {
3074// Return (PSD Package)
3075// }
3076// Return(Zero)
3077
3078ACPI_METHOD * psdMethod = current;
3079current = buildMethod(current, NAMESEG("_PSD"), 0);
3080{
3081// "IF" (And(TYPE, 0x0820)) -- IF Opcode
3082current = buildOpCode(current, AML_IF_OP);
3083{
3084ACPI_PACKAGE_LENGTH * packageLength = current;
3085current = buildPackageLength(current, 0);
3086
3087// IF ("And"(TYPE, 0x820)) -- AND Opcode
3088current = buildOpCode(current, AML_AND_OP);
3089
3090// IF (And("TYPE", 0x820)) -- TYPE Term
3091current = buildNameSeg(current, NAMESEG("TYPE"));
3092
3093// IF (And(TYPE, "0x0820")) -- DWORD Value Term
3094current = buildDwordConst(current, 0x820);
3095
3096// IF ("And(TYPE, 0x200)") -- Target for And term (unused)
3097current = buildOpCode(current, AML_ZERO_OP);
3098
3099// Build return package containing PSD package
3100{
3101ACPI_RETURN_PACKAGE * returnPkg = current;
3102current = buildReturnPackage(current, 1);
3103
3104{
3105// Create PSD package
3106ACPI_PSD_PACKAGE * psd = current;
3107current = psd + 1;
3108
3109setSmallPackage(&psd->package, 5);
3110psd->package.packageLength = (U8)(sizeof(ACPI_PSD_PACKAGE) - 1);
3111
3112setByteConst(&psd->NumberOfEntries, 5);
3113setByteConst(&psd->Revision, 0);
3114setDwordConst(&psd->Domain, domain);
3115setDwordConst(&psd->CoordType, pstate_coordination);
3116setDwordConst(&psd->NumProcessors, cpusInDomain);
3117
3118} // PSD package
3119
3120setPackageLength(&returnPkg->package.pkgLength,
3121 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3122}
3123setPackageLength(packageLength, (U8 *)current - (U8 *)packageLength);
3124}
3125// "Return (ZERO)"
3126current = buildReturnZero(current);
3127}
3128// Update length in _PSD method
3129setPackageLength(&psdMethod->pkgLength, (U8 *)current - (U8 *)&psdMethod->pkgLength);
3130
3131return(current);
3132}
3133
3134//-----------------------------------------------------------------------------
3135static void * buildPPC(void * current/*, U8 valueToReturn*/)
3136{
3137ACPI_SMALL_METHOD * ppc = current;
3138current = buildSmallMethod(current, NAMESEG("_PPC"), 0);
3139
3140current = buildReturnZero(current);
3141
3142//current = buildReturnOpcode(current, valueToReturn);
3143
3144// Update package length in PPC object
3145ppc->packageLength = (U8) ( (U8 *)current - (U8 *)&ppc->packageLength );
3146
3147return(current);
3148}
3149
3150#if UNUSED
3151//-----------------------------------------------------------------------------
3152static void * buildPDL(void * current, U8 valueToReturn)
3153{
3154ACPI_SMALL_METHOD * pdl = current;
3155current = buildSmallMethod(current, NAMESEG("_PDL"), 0);
3156
3157current = buildReturnOpcode(current, valueToReturn);
3158
3159// Update package length in PDL object
3160pdl->packageLength = (U8) ( (U8 *)current - (U8 *)&pdl->packageLength );
3161
3162return(current);
3163}
3164#endif
3165
3166//-----------------------------------------------------------------------------
3167static void * buildPCT(void * current)
3168{
3169static const ACPI_GENERIC_ADDRESS pct_gas[] = {
3170{0x7f,0x40,0,0,0x199},
3171{0x7f,0x10,0,0,0x198},
3172};
3173
3174ACPI_SMALL_METHOD * pct = current;
3175current = buildSmallMethod(current, NAMESEG("_PCT"), 0);
3176
3177{
3178ACPI_RETURN_PACKAGE * returnPkg = current;
3179current = buildReturnPackage(current, 2);
3180
3181{
3182ACPI_SMALL_BUFFER * buff = current;
3183current = buildSmallBuffer(current);
3184
3185current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) );
3186current = buildGenericRegister(current, &pct_gas[0]);
3187current = buildEndTag(current);
3188
3189{
3190U32 length = (U8 *)current - (U8 *)buff;
3191buff->packageLength = (U8)length - 1;
3192}
3193}
3194{
3195ACPI_SMALL_BUFFER * buff = current;
3196current = buildSmallBuffer(current);
3197
3198current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) );
3199current = buildGenericRegister(current, &pct_gas[1]);
3200current = buildEndTag(current);
3201
3202{
3203U32 length = (U8 *)current - (U8 *)buff;
3204buff->packageLength = (U8)length - 1;
3205}
3206
3207}
3208
3209setPackageLength(&returnPkg->package.pkgLength,
3210 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3211}
3212
3213// Update package length in PCT object
3214pct->packageLength = (U8)((U8 *)current - (U8 *)&pct->packageLength);
3215
3216return(current);
3217}
3218
3219//-----------------------------------------------------------------------------
3220static void * buildCstate(void * current, ACPI_GENERIC_ADDRESS * gas, CSTATE * cstate)
3221{
3222//
3223// Build a C-state
3224//
3225ACPI_SMALL_PACKAGE * pkg1 = current;
3226current = buildSmallPackage(current, 4);
3227
3228{
3229{
3230ACPI_SMALL_BUFFER * buffer = current;
3231current = buildSmallBuffer(current);
3232
3233{
3234// Buffer length
3235current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) );
3236current = buildGenericRegister(current, gas);
3237current = buildEndTag(current);
3238}
3239{
3240U32 length = (U8 *)current - (U8 *)buffer;
3241buffer->packageLength = (U8)length - 1;
3242}
3243}
3244
3245{
3246current = buildByteConst(current, cstate->type);
3247current = buildWordConst(current, cstate->latency);
3248current = buildDwordConst(current, cstate->power);
3249}
3250}
3251pkg1->packageLength = (U8)((U8 *)current - (U8 *)&pkg1->packageLength);
3252
3253return(current);
3254}
3255
3256//-----------------------------------------------------------------------------
3257static void * buildReturnPackageCST(void * current, PKG_CSTATES * pkg_cstates)
3258{
3259// Create package returning C-states
3260ACPI_RETURN_PACKAGE * returnPkg = current;
3261current = buildReturnPackage(current, (U8)pkg_cstates->num_cstates + 1);
3262
3263{
3264// Include number of C-states
3265current = buildByteConst(current, (U8)pkg_cstates->num_cstates);
3266
3267{
3268U32 cstateIndex = 0;
3269for (cstateIndex=0; cstateIndex < pkg_cstates->num_cstates; cstateIndex++)
3270// Build C-state
3271current = buildCstate(current, &pkg_cstates->gas[cstateIndex], &pkg_cstates->cstate[cstateIndex]);
3272}
3273}
3274
3275// Update package length in return package
3276setPackageLength(&returnPkg->package.pkgLength,
3277 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3278
3279return(current);
3280}
3281
3282//-----------------------------------------------------------------------------
3283static void * buildCST(void * current, PKG_CSTATES * mwait_pkg_cstates, PKG_CSTATES * io_pkg_cstates)
3284{
3285//
3286// IF (CSEN)
3287// {
3288// IF (LAnd(MWOS, And(TYPE, 0x200)))
3289// {
3290// Return package containing MWAIT C-states
3291// }
3292// Return package containing IO C-states
3293// }
3294// Return(Zero)
3295//
3296ACPI_METHOD * cst = current;
3297current = buildMethod(current, NAMESEG("_CST"), 0);
3298{
3299// "IF" CSEN -- IF Opcode
3300current = buildOpCode(current, AML_IF_OP);
3301{
3302ACPI_PACKAGE_LENGTH * packageLength1 = current;
3303current = buildPackageLength(current, 0);
3304
3305// IF "(CSEN)" -- IF Predicate
3306current = buildNameSeg(current, NAMESEG("CSEN"));
3307
3308// "IF" (LAnd(MWOS, And(TYPE, 0x200))) -- IF Opcode
3309current = buildOpCode(current, AML_IF_OP);
3310{
3311ACPI_PACKAGE_LENGTH * packageLength2 = current;
3312current = buildPackageLength(current, 0);
3313
3314// IF ("LAnd"(MWOS, And(TYPE, 0x200))) -- LAND Opcode
3315current = buildOpCode(current, AML_LAND_OP);
3316
3317// IF (LAnd("MWOS", And(TYPE, 0x200))) -- MWOS Term
3318current = buildNameSeg(current, NAMESEG("MWOS"));
3319
3320// IF (LAnd(MWOS, "And"(TYPE, 0x200))) -- AND Opcode