Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 1714