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

Archive Download this file

Revision: 1815