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 Platform->CPU.Model == CPUID_MODEL_SANDYBRIDGE;
769}
770
771static bool is_jaketown(void)
772{
773 return Platform->CPU.Model == 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 (Platform->CPU.Family)
1040{
1041case 0x06:
1042{
1043switch (Platform->CPU.Model)
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 (Platform->CPU.Model == 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];
2430
2431
2432 // Build the new MADT
2433 if ( (ProcessMadt(MadtPointer, madt_info, memory_for_madt, sizeof(memory_for_madt), 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
2494U8 memory_for_ssdt[20 * 1024];
2495
2496// Build the SSDT
2497if ( (BuildSsdt(madt_info, dsdt, memory_for_ssdt, sizeof(memory_for_ssdt), enable_cstates, enable_pstates, enable_tstates)) == 0)
2498{
2499printf("Error: Failed to build SSDT table\n");
2500return (0);
2501}
2502
2503// insert SSDT in the new_table_list
2504{
2505// Create pointer to SSDT just built in the stack buffer
2506ACPI_TABLE_SSDT * old_ssdt = (ACPI_TABLE_SSDT *)memory_for_ssdt;
2507
2508// Reserved kernel memory for the ssdt table
2509ACPI_TABLE_SSDT *new_ssdt = (ACPI_TABLE_SSDT *)AllocateKernelMemory(old_ssdt->Header.Length);
2510
2511if (!new_ssdt)
2512{
2513printf("Unable to allocate kernel memory for SSDT ");
2514return (0);
2515}
2516// Move the old stack buffer to kernel memory
2517memcpy(new_ssdt, old_ssdt, old_ssdt->Header.Length);
2518
2519// Add the new ssdt into an empty space of the new_table_list
2520new_table_list[empty] = (U32)new_ssdt;
2521}
2522
2523verbose ("SSDT table generated successfully\n");
2524return(1);
2525}
2526
2527//-----------------------------------------------------------------------------
2528static void * buildCpuScope (void * current, U32 cpu_namespace, PROCESSOR_NUMBER_TO_NAMESEG * aslCpuNamePath)
2529{
2530ACPI_SCOPE * scope = current;
2531current = scope + 1;
2532
2533scope->scopeOpcode = AML_SCOPE_OP;
2534scope->rootChar = AML_ROOT_PREFIX;
2535
2536if (aslCpuNamePath->seg_count == 1)
2537{
2538DUAL_NAME_PATH * dualNamePath = current;
2539current = dualNamePath + 1;
2540dualNamePath->prefix = AML_DUAL_NAME_PREFIX;
2541dualNamePath->nameseg[0] = cpu_namespace;
2542dualNamePath->nameseg[1] = aslCpuNamePath->nameseg[0];
2543}
2544else
2545{
2546MULTI_NAME_PATH * multiNamePath = current;
2547current = multiNamePath + 1;
2548multiNamePath->prefix = AML_MULTI_NAME_PREFIX;
2549// the nameseg count includes the root prefix and all other namesegs
2550multiNamePath->segCount = (U8) aslCpuNamePath->seg_count+1;
2551multiNamePath->nameseg[0] = cpu_namespace;
2552{
2553U32 i;
2554for (i=0; i<aslCpuNamePath->seg_count; i++)
2555multiNamePath->nameseg[i+1] = aslCpuNamePath->nameseg[i];
2556}
2557}
2558return (current);
2559}
2560//-----------------------------------------------------------------------------
2561static void * buildPDC(void * current)
2562{
2563ACPI_METHOD * pdc = current;
2564current = buildMethod(current, NAMESEG("_PDC"), 1);
2565
2566// CreateDWordField (Arg0, 0x08, CAPA)
2567current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2568current = buildOpCode(current, AML_ARG0_OP);
2569current = buildByteConst(current, 0x08);
2570current = buildNameSeg(current, NAMESEG("CAPA"));
2571
2572// Store (CAPA, TYPE)
2573current = buildOpCode(current, AML_STORE_OP);
2574current = buildNameSeg(current, NAMESEG("CAPA"));
2575current = buildNameSeg(current, NAMESEG("TYPE"));
2576
2577// CreateDWordField (Arg0, 0x00, REVS)
2578current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2579current = buildOpCode(current, AML_ARG0_OP);
2580current = buildByteConst(current, 0x00);
2581current = buildNameSeg(current, NAMESEG("REVS"));
2582
2583// CreateDWordField (Arg0, 0x04, SIZE)
2584current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2585current = buildOpCode(current, AML_ARG0_OP);
2586current = buildByteConst(current, 0x04);
2587current = buildNameSeg(current, NAMESEG("SIZE"));
2588
2589// Store(SizeOf(Arg0), Local0)
2590current = buildOpCode(current, AML_STORE_OP);
2591current = buildOpCode(current, AML_SIZEOF_OP);
2592current = buildOpCode(current, AML_ARG0_OP);
2593current = buildOpCode(current, AML_LOCAL0_OP);
2594
2595// Store(Subtract(Local0, 0x08),Local1)
2596current = buildOpCode(current, AML_STORE_OP);
2597current = buildOpCode(current, AML_SUBTRACT_OP);
2598current = buildOpCode(current, AML_LOCAL0_OP);
2599current = buildByteConst(current, 0x08);
2600current = buildOpCode(current, AML_ZERO_OP);
2601current = buildOpCode(current, AML_LOCAL1_OP);
2602
2603// CreateField (Arg0, 0x40, Multiply (Local1, 0x08), TEMP)
2604current = buildOpCode(current, AML_EXT_OP_PREFIX);
2605current = buildOpCode(current, AML_CREATE_FIELD_OP);
2606current = buildOpCode(current, AML_ARG0_OP);
2607current = buildByteConst(current, 0x40);
2608current = buildOpCode(current, AML_MULTIPLY_OP);
2609current = buildOpCode(current, AML_LOCAL1_OP);
2610current = buildByteConst(current, 0x08);
2611current = buildOpCode(current, AML_ZERO_OP);
2612current = buildNameSeg(current, NAMESEG("TEMP"));
2613
2614// Name (STS0, Buffer (0x04) {0x00, 0x00, 0x00, 0x00})
2615// Create STS0 as named buffer
2616current = buildNamePath(current, NAMESEG("STS0"));
2617{
2618ACPI_SMALL_BUFFER * buff = current;
2619current = buildSmallBuffer(current);
2620
2621// count of buffer elements
2622current = buildByteConst(current, 4);
2623
2624current = buildOpCode(current, AML_ZERO_OP);
2625current = buildOpCode(current, AML_ZERO_OP);
2626current = buildOpCode(current, AML_ZERO_OP);
2627current = buildOpCode(current, AML_ZERO_OP);
2628{
2629U32 length = (U8 *)current - (U8 *)buff;
2630buff->packageLength = (U8)length - 1;
2631}
2632}
2633
2634//Concatenate (STS0, TEMP, Local2)
2635current = buildOpCode(current, AML_CONCAT_OP);
2636current = buildNameSeg(current, NAMESEG("STS0"));
2637current = buildNameSeg(current, NAMESEG("TEMP"));
2638current = buildOpCode(current, AML_LOCAL2_OP);
2639
2640//_OSC (Buffer (0x10)
2641// {
2642// /* 0000 */ 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47,
2643// /* 0008 */ 0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53
2644// }, REVS, SIZE, Local2)
2645current = buildNameSeg(current, NAMESEG("_OSC"));
2646{
2647ACPI_SMALL_BUFFER * buff = current;
2648current = buildSmallBuffer(current);
2649
2650// count of buffer elements
2651current = buildByteConst(current, 0x10);
2652
2653current = buildOpCode(current, 0x16);
2654current = buildOpCode(current, 0xa6);
2655current = buildOpCode(current, 0x77);
2656current = buildOpCode(current, 0x40);
2657current = buildOpCode(current, 0x0c);
2658current = buildOpCode(current, 0x29);
2659current = buildOpCode(current, 0xbe);
2660current = buildOpCode(current, 0x47);
2661current = buildOpCode(current, 0x9e);
2662current = buildOpCode(current, 0xbd);
2663current = buildOpCode(current, 0xd8);
2664current = buildOpCode(current, 0x70);
2665current = buildOpCode(current, 0x58);
2666current = buildOpCode(current, 0x71);
2667current = buildOpCode(current, 0x39);
2668current = buildOpCode(current, 0x53);
2669{
2670U32 length = (U8 *)current - (U8 *)buff;
2671buff->packageLength = (U8)length - 1;
2672}
2673}
2674current = buildNameSeg(current, NAMESEG("REVS"));
2675current = buildNameSeg(current, NAMESEG("SIZE"));
2676current = buildOpCode(current, AML_LOCAL2_OP);
2677
2678// Update package length in PDC object
2679//pdc->packageLength = (U8)((U8 *)current - (U8 *)&pdc->packageLength);
2680setPackageLength(&pdc->pkgLength, (U8 *)current - (U8 *)&pdc->pkgLength);
2681
2682return(current);
2683}
2684
2685//-----------------------------------------------------------------------------
2686static void * buildOSC(void * current)
2687{
2688//
2689//
2690ACPI_METHOD * osc = current;
2691current = buildMethod(current, NAMESEG("_OSC"), 4);
2692
2693// CreateDWordField (Arg3, 0x04, CAPA)
2694current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2695current = buildOpCode(current, AML_ARG3_OP);
2696current = buildByteConst(current, 0x04);
2697current = buildNameSeg(current, NAMESEG("CAPA"));
2698
2699// Store (CAPA, TYPE)
2700current = buildOpCode(current, AML_STORE_OP);
2701current = buildNameSeg(current, NAMESEG("CAPA"));
2702current = buildNameSeg(current, NAMESEG("TYPE"));
2703
2704// CreateDWordField (Arg3, 0x00, STS0)
2705current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2706current = buildOpCode(current, AML_ARG3_OP);
2707current = buildByteConst(current, 0x00);
2708current = buildNameSeg(current, NAMESEG("STS0"));
2709
2710// CreateDWordField (Arg3, 0x04, CAP0)
2711current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2712current = buildOpCode(current, AML_ARG3_OP);
2713current = buildByteConst(current, 0x04);
2714current = buildNameSeg(current, NAMESEG("CAP0"));
2715
2716// CreateDWordField (Arg0, 0x00, IID0)
2717current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2718current = buildOpCode(current, AML_ARG0_OP);
2719current = buildByteConst(current, 0x00);
2720current = buildNameSeg(current, NAMESEG("IID0"));
2721
2722// CreateDWordField (Arg0, 0x04, IID1)
2723current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2724current = buildOpCode(current, AML_ARG0_OP);
2725current = buildByteConst(current, 0x04);
2726current = buildNameSeg(current, NAMESEG("IID1"));
2727
2728// CreateDWordField (Arg0, 0x08, IID2)
2729current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2730current = buildOpCode(current, AML_ARG0_OP);
2731current = buildByteConst(current, 0x08);
2732current = buildNameSeg(current, NAMESEG("IID2"));
2733
2734// CreateDWordField (Arg0, 0x0C, IID3)
2735current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2736current = buildOpCode(current, AML_ARG0_OP);
2737current = buildByteConst(current, 0x0C);
2738current = buildNameSeg(current, NAMESEG("IID3"));
2739
2740// Name (UID0, Buffer (0x10)
2741// {
2742// 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47,
2743// 0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53
2744// })
2745current = buildNamePath(current, NAMESEG("UID0"));
2746{
2747ACPI_SMALL_BUFFER * buff = current;
2748current = buildSmallBuffer(current);
2749
2750// count of buffer elements
2751current = buildByteConst(current, 0x10);
2752
2753current = buildOpCode(current, 0x16);
2754current = buildOpCode(current, 0xa6);
2755current = buildOpCode(current, 0x77);
2756current = buildOpCode(current, 0x40);
2757current = buildOpCode(current, 0x0c);
2758current = buildOpCode(current, 0x29);
2759current = buildOpCode(current, 0xbe);
2760current = buildOpCode(current, 0x47);
2761current = buildOpCode(current, 0x9e);
2762current = buildOpCode(current, 0xbd);
2763current = buildOpCode(current, 0xd8);
2764current = buildOpCode(current, 0x70);
2765current = buildOpCode(current, 0x58);
2766current = buildOpCode(current, 0x71);
2767current = buildOpCode(current, 0x39);
2768current = buildOpCode(current, 0x53);
2769
2770{
2771U32 length = (U8 *)current - (U8 *)buff;
2772buff->packageLength = (U8)length - 1;
2773}
2774}
2775
2776// CreateDWordField (UID0, 0x00, EID0)
2777current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2778current = buildOpCode(current, AML_ARG0_OP);
2779current = buildByteConst(current, 0x00);
2780current = buildNameSeg(current, NAMESEG("EID0"));
2781
2782// CreateDWordField (UID0, 0x04, EID1)
2783current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2784current = buildOpCode(current, AML_ARG0_OP);
2785current = buildByteConst(current, 0x04);
2786current = buildNameSeg(current, NAMESEG("EID1"));
2787
2788// CreateDWordField (UID0, 0x08, EID2)
2789current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2790current = buildOpCode(current, AML_ARG0_OP);
2791current = buildByteConst(current, 0x08);
2792current = buildNameSeg(current, NAMESEG("EID2"));
2793
2794// CreateDWordField (UID0, 0x0C, EID3)
2795current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2796current = buildOpCode(current, AML_ARG0_OP);
2797current = buildByteConst(current, 0x0C);
2798current = buildNameSeg(current, NAMESEG("EID3"));
2799
2800// If (LNot (LAnd (LAnd (LEqual (IID0, EID0), LEqual (IID1, EID1)),
2801// LAnd (LEqual (IID2, EID2), LEqual (IID3, EID3)))))
2802// {
2803// Store (0x06, Index (STS0, 0x00))
2804// Return (Arg3)
2805// }
2806{
2807current = buildOpCode(current, AML_IF_OP);
2808{
2809ACPI_PACKAGE_LENGTH * packageLength = current;
2810current = buildPackageLength(current, 0);
2811
2812current = buildOpCode(current, AML_LNOT_OP);
2813current = buildOpCode(current, AML_LAND_OP);
2814current = buildOpCode(current, AML_LAND_OP);
2815current = buildOpCode(current, AML_LEQUAL_OP);
2816current = buildNameSeg(current, NAMESEG("IID0"));
2817current = buildNameSeg(current, NAMESEG("EID0"));
2818
2819current = buildOpCode(current, AML_LEQUAL_OP);
2820current = buildNameSeg(current, NAMESEG("IID1"));
2821current = buildNameSeg(current, NAMESEG("EID1"));
2822
2823current = buildOpCode(current, AML_LAND_OP);
2824current = buildOpCode(current, AML_LEQUAL_OP);
2825current = buildNameSeg(current, NAMESEG("IID2"));
2826current = buildNameSeg(current, NAMESEG("EID2"));
2827
2828current = buildOpCode(current, AML_LEQUAL_OP);
2829current = buildNameSeg(current, NAMESEG("IID3"));
2830current = buildNameSeg(current, NAMESEG("EID3"));
2831
2832// Store (0x06, Index (STS0, 0x00))
2833current = buildOpCode(current, AML_STORE_OP);
2834current = buildByteConst(current, 0x06);
2835current = buildOpCode(current, AML_INDEX_OP);
2836current = buildNameSeg(current, NAMESEG("STS0"));
2837current = buildByteConst(current, 0x00);
2838current = buildOpCode(current, AML_ZERO_OP);
2839
2840// Return (Arg3)
2841current = buildReturnOpcode(current, AML_ARG3_OP);
2842
2843setPackageLength(packageLength,
2844 (U8 *)current - (U8 *)packageLength);
2845}
2846}
2847
2848// If (LNotEqual (Arg1, 0x01))
2849// {
2850// Store (0x0A, Index (STS0, 0x00))
2851// Return (Arg3)
2852// }
2853{
2854current = buildOpCode(current, AML_IF_OP);
2855{
2856ACPI_PACKAGE_LENGTH * packageLength = current;
2857current = buildPackageLength(current, 0);
2858
2859// If ("LNotEqual (Arg1, 0x01)")
2860current = buildOpCode(current, AML_LNOT_OP);
2861current = buildOpCode(current, AML_LEQUAL_OP);
2862current = buildOpCode(current, AML_ARG1_OP);
2863current = buildByteConst(current, 0x01);
2864
2865// Store (0x0A, Index (STS0, 0x00))
2866current = buildOpCode(current, AML_STORE_OP);
2867current = buildByteConst(current, 0x0A);
2868current = buildOpCode(current, AML_INDEX_OP);
2869current = buildNameSeg(current, NAMESEG("STS0"));
2870current = buildByteConst(current, 0x00);
2871current = buildOpCode(current, AML_ZERO_OP);
2872
2873// Return (Arg3)
2874current = buildReturnOpcode(current, AML_ARG3_OP);
2875
2876setPackageLength(packageLength,
2877 (U8 *)current - (U8 *)packageLength);
2878}
2879}
2880
2881// If (And (STS0, 0x01))
2882// {
2883// And (CAP0, 0x0BFF, CAP0)
2884// Return (Arg3)
2885// }
2886{
2887current = buildOpCode(current, AML_IF_OP);
2888{
2889ACPI_PACKAGE_LENGTH * packageLength = current;
2890current = buildPackageLength(current, 0);
2891
2892// If ("And (STS0, 0x01)")
2893current = buildOpCode(current, AML_AND_OP);
2894current = buildNameSeg(current, NAMESEG("STS0"));
2895current = buildByteConst(current, 0x01);
2896current = buildOpCode(current, AML_ZERO_OP);
2897
2898// And (CAP0, 0x0BFF, CAP0)
2899current = buildOpCode(current, AML_AND_OP);
2900current = buildNameSeg(current, NAMESEG("CAP0"));
2901current = buildWordConst(current, 0x0BFF);
2902current = buildNameSeg(current, NAMESEG("CAP0"));
2903
2904// Return (Arg3)
2905current = buildReturnOpcode(current, AML_ARG3_OP);
2906
2907setPackageLength(packageLength,
2908 (U8 *)current - (U8 *)packageLength);
2909}
2910}
2911
2912// And (CAP0, 0x0BFF, CAP0)
2913current = buildOpCode(current, AML_AND_OP);
2914current = buildNameSeg(current, NAMESEG("CAP0"));
2915current = buildWordConst(current, 0x0BFF);
2916current = buildNameSeg(current, NAMESEG("CAP0"));
2917
2918// Store (CAP0, TYPE)
2919current = buildOpCode(current, AML_STORE_OP);
2920current = buildNameSeg(current, NAMESEG("CAP0"));
2921current = buildNameSeg(current, NAMESEG("TYPE"));
2922
2923// Return (Arg3)
2924current = buildReturnOpcode(current, AML_ARG3_OP);
2925
2926// Set package length for the OSC object
2927setPackageLength(&osc->pkgLength, (U8 *)current - (U8 *)&osc->pkgLength);
2928
2929return(current);
2930}
2931
2932//-----------------------------------------------------------------------------
2933static void * buildPSS(void * current, PKG_PSTATES * pkg_pstates)
2934{
2935//
2936// IF (PSEN)
2937// {
2938// Return (Package of Pstate Packages)
2939// }
2940// Return(Zero)
2941//
2942ACPI_METHOD * pss = current;
2943current = buildMethod(current, NAMESEG("_PSS"), 0);
2944
2945{
2946// "IF" (PSEN) -- IF Opcode
2947current = buildOpCode(current, AML_IF_OP);
2948{
2949ACPI_PACKAGE_LENGTH * packageLength = current;
2950current = buildPackageLength(current, 0);
2951
2952// IF "(PSEN)" -- IF Predicate
2953current = buildNameSeg(current, NAMESEG("PSEN"));
2954
2955{
2956ACPI_RETURN_PACKAGE * returnPkg = current;
2957current = buildReturnPackage(current, (U8)pkg_pstates->num_pstates);
2958
2959// (3.3.3) For each P-state
2960{
2961U32 pstateIndex = 0;
2962for (pstateIndex=0; pstateIndex < pkg_pstates->num_pstates; pstateIndex++)
2963{
2964// (3.3.3.1) Create P-state package
2965ACPI_PSTATE_PACKAGE * pstate = current;
2966current = pstate + 1;
2967
2968setSmallPackage(&pstate->package, 6);
2969pstate->package.packageLength = (U8)(sizeof(ACPI_PSTATE_PACKAGE) - 1);
2970
2971setDwordConst(&pstate->CoreFreq, pkg_pstates->pstate[pstateIndex].frequency);// CoreFreq (in MHz).
2972setDwordConst(&pstate->Power, pkg_pstates->pstate[pstateIndex].power);// Power (in milliWatts).
2973setDwordConst(&pstate->TransLatency, pkg_pstates->pstate[pstateIndex].translatency);// Transition Latency (in microseconds).
2974setDwordConst(&pstate->BMLatency, pkg_pstates->pstate[pstateIndex].bmlatency);// Bus Master Latency (in microseconds).
2975setDwordConst(&pstate->Control, pkg_pstates->pstate[pstateIndex].control); // Control.
2976
2977setDwordConst(&pstate->Status, encode_pstate(pkg_pstates->pstate[pstateIndex].ratio));// Status.
2978} // for
2979} // for block
2980
2981// (3.3.4) Update package length in return package
2982setPackageLength(&returnPkg->package.pkgLength, (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
2983}
2984
2985// "IF (PSEN) and its body" -- Set package length
2986setPackageLength(packageLength,
2987 (U8 *)current - (U8 *)packageLength);
2988}
2989// "Return (ZERO)"
2990current = buildReturnZero(current);
2991}
2992// Set package length for the _PSS object
2993setPackageLength(&pss->pkgLength, (U8 *)current - (U8 *)&pss->pkgLength);
2994
2995return(current);
2996}
2997
2998//-----------------------------------------------------------------------------
2999static void * buildPSD(void * current, U32 domain, U32 cpusInDomain, U32 pstate_coordination)
3000{
3001// If (And(TYPE, 0x0820))
3002// {
3003// Return (PSD Package)
3004// }
3005// Return(Zero)
3006
3007ACPI_METHOD * psdMethod = current;
3008current = buildMethod(current, NAMESEG("_PSD"), 0);
3009{
3010// "IF" (And(TYPE, 0x0820)) -- IF Opcode
3011current = buildOpCode(current, AML_IF_OP);
3012{
3013ACPI_PACKAGE_LENGTH * packageLength = current;
3014current = buildPackageLength(current, 0);
3015
3016// IF ("And"(TYPE, 0x820)) -- AND Opcode
3017current = buildOpCode(current, AML_AND_OP);
3018
3019// IF (And("TYPE", 0x820)) -- TYPE Term
3020current = buildNameSeg(current, NAMESEG("TYPE"));
3021
3022// IF (And(TYPE, "0x0820")) -- DWORD Value Term
3023current = buildDwordConst(current, 0x820);
3024
3025// IF ("And(TYPE, 0x200)") -- Target for And term (unused)
3026current = buildOpCode(current, AML_ZERO_OP);
3027
3028// Build return package containing PSD package
3029{
3030ACPI_RETURN_PACKAGE * returnPkg = current;
3031current = buildReturnPackage(current, 1);
3032
3033{
3034// Create PSD package
3035ACPI_PSD_PACKAGE * psd = current;
3036current = psd + 1;
3037
3038setSmallPackage(&psd->package, 5);
3039psd->package.packageLength = (U8)(sizeof(ACPI_PSD_PACKAGE) - 1);
3040
3041setByteConst(&psd->NumberOfEntries, 5);
3042setByteConst(&psd->Revision, 0);
3043setDwordConst(&psd->Domain, domain);
3044setDwordConst(&psd->CoordType, pstate_coordination);
3045setDwordConst(&psd->NumProcessors, cpusInDomain);
3046
3047} // PSD package
3048
3049setPackageLength(&returnPkg->package.pkgLength,
3050 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3051}
3052setPackageLength(packageLength, (U8 *)current - (U8 *)packageLength);
3053}
3054// "Return (ZERO)"
3055current = buildReturnZero(current);
3056}
3057// Update length in _PSD method
3058setPackageLength(&psdMethod->pkgLength, (U8 *)current - (U8 *)&psdMethod->pkgLength);
3059
3060return(current);
3061}
3062
3063//-----------------------------------------------------------------------------
3064static void * buildPPC(void * current/*, U8 valueToReturn*/)
3065{
3066ACPI_SMALL_METHOD * ppc = current;
3067current = buildSmallMethod(current, NAMESEG("_PPC"), 0);
3068
3069current = buildReturnZero(current);
3070
3071//current = buildReturnOpcode(current, valueToReturn);
3072
3073// Update package length in PPC object
3074ppc->packageLength = (U8) ( (U8 *)current - (U8 *)&ppc->packageLength );
3075
3076return(current);
3077}
3078
3079#if UNUSED
3080//-----------------------------------------------------------------------------
3081static void * buildPDL(void * current, U8 valueToReturn)
3082{
3083ACPI_SMALL_METHOD * pdl = current;
3084current = buildSmallMethod(current, NAMESEG("_PDL"), 0);
3085
3086current = buildReturnOpcode(current, valueToReturn);
3087
3088// Update package length in PDL object
3089pdl->packageLength = (U8) ( (U8 *)current - (U8 *)&pdl->packageLength );
3090
3091return(current);
3092}
3093#endif
3094
3095//-----------------------------------------------------------------------------
3096static void * buildPCT(void * current)
3097{
3098static const ACPI_GENERIC_ADDRESS pct_gas[] = {
3099{0x7f,0x40,0,0,0x199},
3100{0x7f,0x10,0,0,0x198},
3101};
3102
3103ACPI_SMALL_METHOD * pct = current;
3104current = buildSmallMethod(current, NAMESEG("_PCT"), 0);
3105
3106{
3107ACPI_RETURN_PACKAGE * returnPkg = current;
3108current = buildReturnPackage(current, 2);
3109
3110{
3111ACPI_SMALL_BUFFER * buff = current;
3112current = buildSmallBuffer(current);
3113
3114current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) );
3115current = buildGenericRegister(current, &pct_gas[0]);
3116current = buildEndTag(current);
3117
3118{
3119U32 length = (U8 *)current - (U8 *)buff;
3120buff->packageLength = (U8)length - 1;
3121}
3122}
3123{
3124ACPI_SMALL_BUFFER * buff = current;
3125current = buildSmallBuffer(current);
3126
3127current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) );
3128current = buildGenericRegister(current, &pct_gas[1]);
3129current = buildEndTag(current);
3130
3131{
3132U32 length = (U8 *)current - (U8 *)buff;
3133buff->packageLength = (U8)length - 1;
3134}
3135
3136}
3137
3138setPackageLength(&returnPkg->package.pkgLength,
3139 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3140}
3141
3142// Update package length in PCT object
3143pct->packageLength = (U8)((U8 *)current - (U8 *)&pct->packageLength);
3144
3145return(current);
3146}
3147
3148//-----------------------------------------------------------------------------
3149static void * buildCstate(void * current, ACPI_GENERIC_ADDRESS * gas, CSTATE * cstate)
3150{
3151//
3152// Build a C-state
3153//
3154ACPI_SMALL_PACKAGE * pkg1 = current;
3155current = buildSmallPackage(current, 4);
3156
3157{
3158{
3159ACPI_SMALL_BUFFER * buffer = current;
3160current = buildSmallBuffer(current);
3161
3162{
3163// Buffer length
3164current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) );
3165current = buildGenericRegister(current, gas);
3166current = buildEndTag(current);
3167}
3168{
3169U32 length = (U8 *)current - (U8 *)buffer;
3170buffer->packageLength = (U8)length - 1;
3171}
3172}
3173
3174{
3175current = buildByteConst(current, cstate->type);
3176current = buildWordConst(current, cstate->latency);
3177current = buildDwordConst(current, cstate->power);
3178}
3179}
3180pkg1->packageLength = (U8)((U8 *)current - (U8 *)&pkg1->packageLength);
3181
3182return(current);
3183}
3184
3185//-----------------------------------------------------------------------------
3186static void * buildReturnPackageCST(void * current, PKG_CSTATES * pkg_cstates)
3187{
3188// Create package returning C-states
3189ACPI_RETURN_PACKAGE * returnPkg = current;
3190current = buildReturnPackage(current, (U8)pkg_cstates->num_cstates + 1);
3191
3192{
3193// Include number of C-states
3194current = buildByteConst(current, (U8)pkg_cstates->num_cstates);
3195
3196{
3197U32 cstateIndex = 0;
3198for (cstateIndex=0; cstateIndex < pkg_cstates->num_cstates; cstateIndex++)
3199// Build C-state
3200current = buildCstate(current, &pkg_cstates->gas[cstateIndex], &pkg_cstates->cstate[cstateIndex]);
3201}
3202}
3203
3204// Update package length in return package
3205setPackageLength(&returnPkg->package.pkgLength,
3206 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3207
3208return(current);
3209}
3210
3211//-----------------------------------------------------------------------------
3212static void * buildCST(void * current, PKG_CSTATES * mwait_pkg_cstates, PKG_CSTATES * io_pkg_cstates)
3213{
3214//
3215// IF (CSEN)
3216// {
3217// IF (LAnd(MWOS, And(TYPE, 0x200)))
3218// {
3219// Return package containing MWAIT C-states
3220// }
3221// Return package containing IO C-states
3222// }
3223// Return(Zero)
3224//
3225ACPI_METHOD * cst = current;
3226current = buildMethod(current, NAMESEG("_CST"), 0);
3227{
3228// "IF" CSEN -- IF Opcode
3229current = buildOpCode(current, AML_IF_OP);
3230{
3231ACPI_PACKAGE_LENGTH * packageLength1 = current;
3232current = buildPackageLength(current, 0);
3233
3234// IF "(CSEN)" -- IF Predicate
3235current = buildNameSeg(current, NAMESEG("CSEN"));
3236
3237// "IF" (LAnd(MWOS, And(TYPE, 0x200))) -- IF Opcode
3238current = buildOpCode(current, AML_IF_OP);
3239{
3240ACPI_PACKAGE_LENGTH * packageLength2 = current;
3241current = buildPackageLength(current, 0);
3242
3243// IF ("LAnd"(MWOS, And(TYPE, 0x200))) -- LAND Opcode
3244current = buildOpCode(current, AML_LAND_OP);
3245
3246// IF (LAnd("MWOS", And(TYPE, 0x200))) -- MWOS Term
3247current = buildNameSeg(current, NAMESEG("MWOS"));
3248
3249// IF (LAnd(MWOS, "And"(TYPE, 0x200))) -- AND Opcode
3250current = buildOpCode(current, AML_AND_OP);
3251
3252// IF (LAnd(MWOS, And("TYPE", 0x200))) -- TYPE Term
3253current = buildNameSeg(current, NAMESEG("TYPE"));
3254
3255// IF (LAnd(MWOS, And(TYPE, "0x200"))) -- DWORD Value Term
3256current = buildWordConst(current, 0x200);
3257
3258// IF (LAnd(MWOS, "And(TYPE, 0x200)")) -- Target for And term (unused)
3259current = buildOpCode(current, AML_ZERO_OP);
3260
3261// Build return package for mwait c-states
3262current = buildReturnPackageCST(current, mwait_pkg_cstates);
3263
3264setPackageLength(packageLength2,
3265 (U8 *)current - (U8 *)packageLength2);
3266}
3267
3268// Build return package for io c-states
3269current = buildReturnPackageCST(current, io_pkg_cstates);
3270
3271setPackageLength(packageLength1,
3272 (U8 *)current - (U8 *)packageLength1);
3273}
3274// "Return (ZERO)"
3275current = buildReturnZero(current);
3276}
3277// Update length in _CST method
3278setPackageLength(&cst->pkgLength, (U8 *)current - (U8 *)&cst->pkgLength);
3279
3280return(current);
3281}
3282
3283#if BUILD_ACPI_CSD
3284//-----------------------------------------------------------------------------
3285static void * buildCSD(void * current, U32 domain, U32 cpusInDomain, PKG_CSTATES * pkg_cstates)
3286{
3287 // If (And(TYPE, 0x0040))
3288 // {
3289 // Return (CSD Package)
3290 // }
3291 // Return(Zero)
3292
3293 ACPI_METHOD * csdMethod = current;
3294 current = buildMethod(current, NAMESEG("_CSD"), 0);
3295 {
3296 // "IF" (And(TYPE, 0x0040)) -- IF Opcode
3297 current = buildOpCode(current, AML_IF_OP);
3298 {
3299 ACPI_PACKAGE_LENGTH * packageLength = current;
3300 current = buildPackageLength(current, 0);
3301
3302 // IF ("And"(TYPE, 0x0040)) -- AND Opcode
3303 current = buildOpCode(current, AML_AND_OP);
3304
3305 // IF (And("TYPE", 0x0040)) -- TYPE Term
3306 current = buildNameSeg(current, NAMESEG("TYPE"));
3307
3308 // IF (And(TYPE, "0x0040")) -- DWORD Value Term
3309 current = buildDwordConst(current, 0x0040);
3310
3311 // IF ("And(TYPE, 0x0040)") -- Target for And term (unused)
3312 current = buildOpCode(current, AML_ZERO_OP);
3313
3314 // Build return package containing CSD package(s)
3315 {
3316 ACPI_RETURN_PACKAGE * returnPkg = current;
3317 current = buildReturnPackage(current, (U8)pkg_cstates->num_cstates - 1);
3318
3319 {
3320 U32 cstateIndex;
3321 for (cstateIndex=1; cstateIndex < pkg_cstates->num_cstates; cstateIndex++)
3322 {
3323 // Build CSD for this C-state
3324
3325 // Create CSD package
3326 ACPI_CSD_PACKAGE * csd = current;
3327 current = csd + 1;
3328
3329 setSmallPackage(&csd->package, 6);
3330 csd->package.packageLength = (U8)(sizeof(ACPI_CSD_PACKAGE) - 1);
3331
3332 setByteConst(&csd->NumberOfEntries, 6);
3333 setByteConst(&csd->Revision, 0);
3334 setDwordConst(&csd->Domain, domain);
3335 setDwordConst(&csd->CoordType, ACPI_COORD_TYPE_HW_ALL);
3336 setDwordConst(&csd->NumProcessors, cpusInDomain);
3337 setDwordConst(&csd->Index, cstateIndex);
3338 }
3339 }
3340
3341 setPackageLength(&returnPkg->package.pkgLength,
3342 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3343 }
3344
3345 setPackageLength(packageLength, (U8 *)current - (U8 *)packageLength);
3346 }
3347 // "Return (ZERO)"
3348 current = buildReturnZero(current);
3349 }
3350 // Update length in _CSD method
3351 setPackageLength(&csdMethod->pkgLength, (U8 *)current - (U8 *)&csdMethod->pkgLength);
3352
3353 return(current);
3354}
3355#endif // BUILD_ACPI_CSD
3356
3357#if BUILD_ACPI_TSS
3358//-----------------------------------------------------------------------------
3359static void * buildTPC(void * current)
3360{
3361 ACPI_SMALL_METHOD * tpc = current;
3362 current = buildSmallMethod(current, NAMESEG("_TPC"), 0);
3363
3364 current = buildReturnZero(current);
3365
3366 // Update package length in PPC object
3367 tpc->packageLength = (U8) ( (U8 *)current - (U8 *)&tpc->packageLength );
3368
3369 return(current);
3370}
3371
3372//-----------------------------------------------------------------------------
3373static void * buildPTC(void * current)
3374{
3375 static const ACPI_GENERIC_ADDRESS ptc_gas[] = {
3376 {0x7f,0x00,0,0,0},
3377 {0x7f,0x00,0,0,0},
3378 };
3379
3380 ACPI_SMALL_METHOD * ptc = current;
3381 current = buildSmallMethod(current, NAMESEG("_PTC"), 0);
3382
3383 {
3384 ACPI_RETURN_PACKAGE * returnPkg = current;
3385 current = buildReturnPackage(current, 2);
3386
3387 {
3388 ACPI_SMALL_BUFFER * buff = current;
3389 current = buildSmallBuffer(current);
3390
3391 current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) );
3392 current = buildGenericRegister(current, &ptc_gas[0]);
3393 current = buildEndTag(current);
3394
3395 {
3396 U32 length = (U8 *)current - (U8 *)buff;
3397 buff->packageLength = (U8)length - 1;
3398 }
3399 }
3400 {
3401 ACPI_SMALL_BUFFER * buff = current;
3402 current = buildSmallBuffer(current);
3403
3404 current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) );
3405 current = buildGenericRegister(current, &ptc_gas[1]);
3406 current = buildEndTag(current);
3407
3408 {
3409 U32 length = (U8 *)current - (U8 *)buff;
3410 buff->packageLength = (U8)length - 1;
3411 }
3412 }
3413
3414 setPackageLength(&returnPkg->package.pkgLength,
3415 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3416 }
3417
3418 // Update package length in PTC object
3419 ptc->packageLength = (U8)((U8 *)current - (U8 *)&ptc->packageLength);
3420
3421 return(current);
3422}
3423
3424//-----------------------------------------------------------------------------
3425static void * buildTSS(void * current, PKG_TSTATES * pkg_tstates)
3426{
3427 //
3428 // IF (LAnd(TSEN, And(TYPE,4)))
3429 // {
3430 // Return (Package of Tstate Packages)
3431 // }
3432 // Return(Zero)
3433 //
3434 ACPI_METHOD * tss = current;
3435 current = buildMethod(current, NAMESEG("_TSS"), 0);
3436
3437 {
3438 // "IF" (LAnd(TSEN, And(TYPE,4))) -- IF Opcode
3439 current = buildOpCode(current, AML_IF_OP);
3440 {
3441 ACPI_PACKAGE_LENGTH * packageLength = current;
3442 current = buildPackageLength(current, 0);
3443
3444 // IF ("LAnd"(TSEN, And(TYPE, 4))) -- LAND Opcode
3445 current = buildOpCode(current, AML_LAND_OP);
3446
3447 // IF (LAnd("TSEN", And(TYPE, 4))) -- TSEN Term
3448 current = buildNameSeg(current, NAMESEG("TSEN"));
3449
3450 // IF (LAnd(TSEN, "And"(TYPE, 4))) -- AND Opcode
3451 current = buildOpCode(current, AML_AND_OP);
3452
3453 // IF (LAnd(TSEN, And("TYPE", 4))) -- TYPE Term
3454 current = buildNameSeg(current, NAMESEG("TYPE"));
3455
3456 // IF (LAnd(TSEN, And(TYPE, "4"))) -- DWORD Value Term
3457 current = buildWordConst(current, 4);
3458
3459 // IF (LAnd(MWOS, "And(TYPE, 4)")) -- Target for And term (unused)
3460 current = buildOpCode(current, AML_ZERO_OP);
3461
3462 // Return (Package of Tstate Packages)
3463 {
3464 ACPI_RETURN_PACKAGE * returnPkg = current;
3465 current = buildReturnPackage(current, (U8)pkg_tstates->num_tstates);
3466
3467 // (3.3.3) For each T-state
3468 {
3469 U32 tstateIndex = 0;
3470 for (tstateIndex=0; tstateIndex < pkg_tstates->num_tstates; tstateIndex++)
3471 {
3472 // (3.3.3.1) Create T-state package
3473 ACPI_TSTATE_PACKAGE * tstate = current;
3474 current = tstate + 1;
3475
3476 setSmallPackage(&tstate->package, 5);
3477 tstate->package.packageLength = (U8)(sizeof(ACPI_TSTATE_PACKAGE) - 1);
3478
3479 setDwordConst(&tstate->FreqPercent, pkg_tstates->tstate[tstateIndex].freqpercent);
3480 setDwordConst(&tstate->Power, pkg_tstates->tstate[tstateIndex].power);
3481 setDwordConst(&tstate->TransLatency, pkg_tstates->tstate[tstateIndex].latency);
3482 setDwordConst(&tstate->Control, pkg_tstates->tstate[tstateIndex].control);
3483 setDwordConst(&tstate->Status, pkg_tstates->tstate[tstateIndex].status);
3484 } // for
3485 } // for block
3486
3487 // (3.3.4) Update package length in return package
3488 setPackageLength(&returnPkg->package.pkgLength, (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3489 }
3490
3491 // "IF (LAnd(TSEN, And(TYPE,4))) and its body" -- Set package length
3492 setPackageLength(packageLength, (U8 *)current - (U8 *)packageLength);
3493 }
3494 // "Return (ZERO)"
3495 current = buildReturnZero(current);
3496 }
3497 // Set package length for the _TSS object
3498 setPackageLength(&tss->pkgLength, (U8 *)current - (U8 *)&tss->pkgLength);
3499
3500 return(current);
3501}
3502
3503//-----------------------------------------------------------------------------
3504static void * buildTSD(void * current, U32 domain, U32 cpusInDomain)
3505{
3506 // If (And(TYPE, 0x0080))
3507 // {
3508 // Return (Package containing TSD package)
3509 // }
3510 // Return(Zero)
3511
3512 ACPI_METHOD * tsdMethod = current;
3513 current = buildMethod(current, NAMESEG("_TSD"), 0);
3514 {
3515 // "IF" (And(TYPE, 0x0080)) -- IF Opcode
3516 current = buildOpCode(current, AML_IF_OP);
3517 {
3518 ACPI_PACKAGE_LENGTH * packageLength = current;
3519 current = buildPackageLength(current, 0);
3520
3521 // IF ("And"(TYPE, 0x0080)) -- AND Opcode
3522 current = buildOpCode(current, AML_AND_OP);
3523
3524 // IF (And("TYPE", 0x0080)) -- TYPE Term
3525 current = buildNameSeg(current, NAMESEG("TYPE"));
3526
3527 // IF (And(TYPE, "0x0080")) -- DWORD Value Term
3528 current = buildDwordConst(current, 0x0080);
3529
3530 // IF ("And(TYPE, 0x0080)") -- Target for And term (unused)
3531 current = buildOpCode(current, AML_ZERO_OP);
3532
3533 // Build package containing TSD package
3534 {
3535 ACPI_RETURN_PACKAGE * returnPkg = current;
3536 current = buildReturnPackage(current, 1);
3537
3538 {
3539 // Create PSD package
3540 ACPI_TSD_PACKAGE * tsd = current;
3541 current = tsd + 1;
3542
3543 setSmallPackage(&tsd->package, 5);
3544 tsd->package.packageLength = (U8)(sizeof(ACPI_TSD_PACKAGE) - 1);
3545
3546 setByteConst(&tsd->NumberOfEntries, 5);
3547 setByteConst(&tsd->Revision, 0);
3548 setDwordConst(&tsd->Domain, domain);
3549 setDwordConst(&tsd->CoordType, ACPI_COORD_TYPE_SW_ANY);
3550 setDwordConst(&tsd->NumProcessors, cpusInDomain);
3551
3552 } // TSD package
3553
3554 setPackageLength(&returnPkg->package.pkgLength,
3555 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3556 }
3557
3558 setPackageLength(packageLength, (U8 *)current - (U8 *)packageLength);
3559 }
3560 // "Return (ZERO)"
3561 current = buildReturnZero(current);
3562 }
3563 // Update length in _TSD method
3564 setPackageLength(&tsdMethod->pkgLength, (U8 *)current - (U8 *)&tsdMethod->pkgLength);
3565
3566 return(current);
3567}
3568#endif // BUILD_ACPI_TSS
3569
3570//-----------------------------------------------------------------------------
3571static U32 BuildSsdt(MADT_INFO * madt_info, ACPI_TABLE_DSDT *dsdt, void * buffer, U32 bufferSize, bool enable_cstates, bool enable_pstates, bool enable_tstates)
3572{
3573// Build SSDT
3574{
3575// (1) Setup pointers to SSDT memory location
3576// (2) Create SSDT Definition Block
3577// (2.1) Save pointer to SSDT package length and checksum fields
3578// (2.2) Create variables in SSDT scope
3579// (3) For each logical processor CPUn
3580// (3.1) Create scope for CPUn
3581// (3.2) Create variables in CPU scope
3582// (3.3) Create _OSC and/or _PDC Methods
3583// (3.4) Create P-state related structures
3584// (3.4.1) Create _PSS Method
3585// (3.4.2) Create _PCT Object
3586// (3.4.3) Create _PPC Method
3587// (3.4.4) Create _PSD Object
3588// (3.5) Create C-state related structures
3589// (3.5.1) Create _CST Method
3590// (3.5.2) Create _CSD Method
3591// (3.6) Create T-state related structures (Optional)
3592// (3.6.1) Create _TPC Method
3593// (3.6.2) Create _PTC Method
3594// (3.6.3) Create _TSS Method
3595// (3.6.4) Create _TSD Method
3596// (3.7) Update length in CPUn Scope
3597// (4) Update length and checksum in SSDT Definition Block
3598DBG("Attempting to build SSDT\n");
3599
3600U32 pstates_enabled = 0;
3601U32 cstates_enabled = 0;
3602CPU_DETAILS cpu;
3603U8 ACPI_COORD_TYPE = ACPI_COORD_TYPE_SW_ANY; // default
3604ACPI_TABLE_SSDT *SsdtPointer = (void*)0ul;
3605
3606// Desired state for providing alternate ACPI _CST structure using MWAIT
3607// extensions
3608// 1= Alternate _CST using MWAIT extension is enabled for OSPM use
3609// 0= Alternate _CST using MWAIT extension is disabled for OSPM use
3610bool enable_mwait = 1;
3611
3612// (1) Setup pointers to SSDT memory location
3613void * current = buffer;
3614void * end = (U8 *)buffer + bufferSize;
3615
3616// Confirm a valid SSDT buffer was provided
3617if (!buffer)
3618{
3619printf("Error: Invalid Buffer Address for SSDT\n");
3620return(0);
3621}
3622
3623// Confirm a valid SSDT buffer length was provided
3624if (!bufferSize)
3625{
3626printf("Error: Invalid Buffer Length for SSDT\n");
3627return(0);
3628}
3629
3630if (madt_info == (void*) 0ul)
3631{
3632return(0);
3633}
3634
3635if (dsdt == (void*) 0ul)
3636{
3637return(0);
3638}
3639
3640// Check that we have a valid cpu_map (if it's not already done, it will try to generate it)
3641if (generate_cpu_map_from_acpi(dsdt) != 0)
3642{
3643return(0);
3644}
3645
3646collect_cpu_info(&cpu);
3647
3648if (enable_cstates && pmbase)
3649{
3650DBG("Building Cstate Info\n");
3651
3652cstates_enabled = BuildCstateInfo(&cpu, pmbase);
3653if (cstates_enabled)
3654{
3655getBoolForKey(KEnableMwait, &enable_mwait, &bootInfo->bootConfig);
3656}
3657}
3658
3659if (enable_pstates)
3660{
3661DBG("Building Pstate Info\n");
3662
3663pstates_enabled = BuildPstateInfo(&cpu);
3664if (pstates_enabled)
3665{
3666const char *str = getStringForKey(KAcpiCoordType, &bootInfo->bootConfig);
3667U8 tmp = (U8)strtoul(str, NULL,16);
3668if ((tmp == ACPI_COORD_TYPE_SW_ALL) || (tmp == ACPI_COORD_TYPE_SW_ANY) || (tmp == ACPI_COORD_TYPE_HW_ALL) )
3669{
3670ACPI_COORD_TYPE = tmp;
3671}
3672}
3673}
3674#if BUILD_ACPI_TSS
3675 U32 tstates_enabled = 0;
3676 if (enable_tstates)
3677{
3678DBG("Building Pstate Info\n");
3679
3680tstates_enabled = BuildTstateInfo(&cpu);
3681}
3682#endif
3683
3684SsdtPointer = (ACPI_TABLE_SSDT *)buffer;
3685
3686// (2) Create SSDT Definition Block
3687// (2.1) Save pointer to SSDT package length and checksum fields
3688current = buildTableHeader(current, NAMESEG("SSDT"), NAMESEG64("PPM RCM "));
3689
3690// Check to confirm no SSDT buffer overflow
3691if ( (U8 *)current > (U8 *)end )
3692{
3693printf("Error: SSDT Buffer Length exceeded available space \n");
3694return(0);
3695}
3696
3697// (3) For each logical processor CPUn
3698// We will use the dsdt datas in place of madt,for the cpu(s) detection.
3699// 'Cause most users use the dsdt table to change the numbers of cpu(s) that the OS and the bootloader should use,
3700// Note also that due to chameleon limit we use the same package per each cpu(s) for all objects and methods
3701// (package detection for each cpu(s) is still in progress)
3702{
3703U32 lapic_index;
3704for (lapic_index=0; lapic_index < cpu_map_count; lapic_index++)
3705{
3706// (3.1) Create scope for CPUn
3707ACPI_SCOPE * scope = current;
3708
3709{
3710DBG("Building CPU Scope\n");
3711U32 cpu_namespace = (cpuNamespace == CPU_NAMESPACE_SB) ? NAMESEG("_SB_") : NAMESEG("_PR_");
3712PROCESSOR_NUMBER_TO_NAMESEG * namepath = &cpu_map[lapic_index];
3713current = buildCpuScope (current, cpu_namespace, namepath );
3714}
3715
3716// Check to confirm no SSDT buffer overflow
3717if ( (U8 *)current > (U8 *)end )
3718{
3719printf("Error: SSDT Buffer Length exceeded available space \n");
3720return(0);
3721}
3722
3723// (3.2) Create variables in CPU scope
3724DBG("Creating variables in CPU scope\n");// Build Type variable used to store PDC capabilities
3725current = buildNamedDword(current, NAMESEG("TYPE"), 0);
3726
3727// Build PSEN variable used to store state of P-State Enable setup option
3728current = buildNamedDword(current, NAMESEG("PSEN"), pstates_enabled);
3729
3730// Build CSEN variable used to store state of C-State Enable setup option
3731current = buildNamedDword(current, NAMESEG("CSEN"), cstates_enabled);
3732
3733// Build MWOS variable used to store state of MWAIT OS setup option
3734current = buildNamedDword(current, NAMESEG("MWOS"), (U32)(enable_mwait&&cpu.mwait_supported));
3735
3736// (3.3) Create _OSC and/or _PDC Methods
3737{
3738// Build _PDC method
3739DBG("Building PDC method\n");
3740current = buildPDC(current);
3741
3742// Check to confirm no SSDT buffer overflow
3743if ( (U8 *)current > (U8 *)end )
3744{
3745printf("Error: SSDT Buffer Length exceeded available space \n");
3746return(0);
3747}
3748
3749// Build _OSC method
3750DBG("Building _OSC method\n");
3751current = buildOSC(current);
3752
3753// Check to confirm no SSDT buffer overflow
3754if ( (U8 *)current > (U8 *)end )
3755{
3756printf("Error: SSDT Buffer Length exceeded available space \n");
3757return(0);
3758}
3759}
3760
3761// (3.4) Create P-state related structures
3762if (pstates_enabled == 1)
3763{
3764// (3.4.1) Create _PSS Method
3765{
3766DBG("Building _PSS method\n");
3767PKG_PSTATES * pkg_pstates = &cpu.pkg_pstates;
3768current = buildPSS(current, pkg_pstates);
3769}
3770
3771// Check to confirm no SSDT buffer overflow
3772if ( (U8 *)(current) > (U8 *)end )
3773{
3774printf("Error: SSDT Buffer Length exceeded available space \n");
3775return(0);
3776}
3777
3778// (3.4.2) Create _PCT Object
3779DBG("Building _PCT Object\n");
3780current = buildPCT(current);
3781
3782// Check to confirm no SSDT buffer overflow
3783if ( (U8 *)(current) > (U8 *)end )
3784{
3785printf("Error: SSDT Buffer Length exceeded available space \n");
3786return(0);
3787}
3788
3789// (3.4.3) Create _PPC Method
3790DBG("Building _PPC Method\n");
3791current = buildPPC(current);
3792
3793// Check to confirm no SSDT buffer overflow
3794if ( (U8 *)(current) > (U8 *)end )
3795{
3796printf("Error: SSDT Buffer Length exceeded available space \n");
3797return(0);
3798}
3799
3800// (3.4.4) Create PSD with hardware coordination
3801{
3802DBG("Building _PSD Method\n");
3803U32 domain = madt_info->lapic[lapic_index].pkg_index;
3804
3805 // In this (bad?) implementation we use the nb of cpu found in the dsdt
3806U32 cpusInDomain = cpu_map_count;
3807current = buildPSD(current, domain, cpusInDomain, ACPI_COORD_TYPE);
3808}
3809
3810// Check to confirm no SSDT buffer overflow
3811if ( (U8 *)(current) > (U8 *)end )
3812{
3813printf("Error: SSDT Buffer Length exceeded available space \n");
3814return(0);
3815}
3816}
3817
3818// (3.5) Create C-state related structures
3819if (cstates_enabled == 1)
3820{
3821{
3822PKG_CSTATES * mwait_pkg_cstates = &cpu.pkg_mwait_cstates;
3823PKG_CSTATES * io_pkg_cstates = &cpu.pkg_io_cstates;
3824
3825// Build CST
3826DBG("Building _CST Method\n");
3827current = buildCST(current, mwait_pkg_cstates, io_pkg_cstates);
3828}
3829
3830#if BUILD_ACPI_CSD
3831 {
3832 // Use core_apic_id as domain
3833 U32 domain = lapic->core_apic_id;
3834
3835 // In this (bad?) implementation we use the nb of cpu found in the dsdt
3836 U32 cpusInDomain = cpu_map_count;
3837
3838 // Create CSD
3839 current = buildCSD(current, domain, cpusInDomain, io_pkg_cstates);
3840 }
3841#endif
3842
3843// Check to confirm no SSDT buffer overflow
3844if ( (U8 *)(current) > (U8 *)end )
3845{
3846printf("Error: SSDT Buffer Length exceeded available space \n");
3847return(0);
3848}
3849}
3850#if BUILD_ACPI_TSS
3851 // (3.6) Create T-state related structures
3852 if (tstates_enabled == 1)
3853 {
3854 // (3.6.1) Create _TPC Method
3855 current = buildTPC(current);
3856
3857 // (3.6.2) Create _PTC Method
3858 current = buildPTC(current);
3859
3860 // (3.6.3) Create _TSS Method
3861 {
3862 PKG_TSTATES * pkg_tstates = &cpu.pkg_tstates;
3863 current = buildTSS(current, pkg_tstates);
3864 }
3865
3866 // (3.6.4) Create _TSD Method
3867 {
3868 LAPIC_INFO * lapic = &madt_info.lapic[lapic_index];
3869
3870 // Use core_apic_id as domain
3871 U32 domain = lapic->core_apic_id;
3872
3873 // In this (bad?) implementation we use the nb of cpu found in the dsdt
3874 U32 cpusInDomain = cpu_map_count;
3875
3876 current = buildTSD(current, domain, cpusInDomain);
3877 }
3878 }
3879#endif
3880// (3.7) Update length in CPUn Scope
3881setPackageLength(&scope->pkgLength, (U8 *)current - (U8 *)&scope->pkgLength);
3882
3883} // End for
3884
3885// (4) Update length and checksum in SSDT Definition Block
3886{
3887DBG("Updating length and checksum in SSDT Definition Block\n");
3888
3889SsdtPointer->Header.Length = (U8 *)current - (U8 *)SsdtPointer;
3890SetChecksum(&SsdtPointer->Header);
3891}
3892
3893// Check to confirm no SSDT buffer overflow
3894if ( (U8 *)current > (U8 *)end )
3895{
3896printf("Error: SSDT Buffer Length exceeded available space \n");
3897return(0);
3898}
3899
3900} // End build SSDT
3901
3902} // SSDT
3903
3904return(1);
3905}
3906
3907#if UNUSED
3908static ACPI_TABLE_FACS* generate_facs(bool updatefacs )
3909{
3910 ACPI_TABLE_FACS* facs_mod=(ACPI_TABLE_FACS *)AllocateKernelMemory(sizeof(ACPI_TABLE_FACS));
3911if (!facs_mod)
3912{
3913printf("Unable to allocate kernel memory for facs mod\n");
3914return (void*)0ul;
3915}
3916 bzero(facs_mod, sizeof(ACPI_TABLE_FACS));
3917
3918ACPI_TABLE_FACS * FacsPointer =(acpi_tables.FacsPointer64 != (void *)0ul) ?
3919(ACPI_TABLE_FACS *)acpi_tables.FacsPointer64 : (ACPI_TABLE_FACS *)acpi_tables.FacsPointer;
3920
3921 memcpy(facs_mod, FacsPointer , FacsPointer->Length);
3922 facs_mod->Length = sizeof(ACPI_TABLE_FACS);
3923
3924if (FacsPointer->Length < sizeof(ACPI_TABLE_FACS))
3925{
3926facs_mod->FirmwareWakingVector = 0;
3927facs_mod->GlobalLock = 0;
3928facs_mod->Flags = 0;
3929}
3930
3931 if (updatefacs && FacsPointer->Version < 2)
3932{
3933if (FacsPointer->Version > 0)
3934{
3935facs_mod->XFirmwareWakingVector = FacsPointer->XFirmwareWakingVector;
3936}
3937else
3938{
3939facs_mod->XFirmwareWakingVector = (U64)facs_mod->FirmwareWakingVector;
3940}
3941
3942facs_mod->Version = 2; /* ACPI 1.0: 0, ACPI 2.0/3.0: 1, ACPI 4.0: 2 */
3943
3944}
3945
3946 return facs_mod;
3947}
3948#endif
3949
3950static ACPI_GENERIC_ADDRESS FillGASStruct(U32 Address, U8 Length)
3951{
3952ACPI_GENERIC_ADDRESS TmpGAS;
3953
3954TmpGAS.SpaceId = 1; /* I/O Address */
3955
3956if (Address == 0)
3957{
3958TmpGAS.BitWidth = 0;
3959}
3960else
3961{
3962TmpGAS.BitWidth = Length * 8;
3963}
3964
3965TmpGAS.BitOffset = 0;
3966TmpGAS.AccessWidth = 0; /* Not set for Legacy reasons... */
3967TmpGAS.Address = (U64)Address;
3968
3969return (TmpGAS);
3970}
3971
3972static ACPI_TABLE_FADT *
3973patch_fadt(ACPI_TABLE_FADT *fadt, ACPI_TABLE_DSDT *new_dsdt, bool UpdateFADT)
3974{
3975ACPI_TABLE_FADT *fadt_mod = (void*)0;
3976bool fadt_rev2_needed = false;
3977bool fix_restart = false;
3978const char * value;
3979
3980// Restart Fix
3981if (Platform->CPU.Vendor == 0x756E6547) /* Intel */
3982{
3983fix_restart = true;
3984getBoolForKey(kRestartFix, &fix_restart, &bootInfo->bootConfig);
3985
3986} else {
3987verbose ("Not an Intel platform: Restart Fix disabled !!!\n");
3988}
3989
3990if (fix_restart)
3991fadt_rev2_needed = true;
3992
3993// Allocate new fadt table
3994if (UpdateFADT)
3995{
3996 if (fadt->Header.Length < 0xF4)
3997 {
3998 fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(0xF4);
3999 if (!fadt_mod)
4000 {
4001 printf("Unable to allocate kernel memory for fadt mod\n");
4002 return (void*)0ul;
4003 }
4004 bzero(fadt_mod, 0xF4);
4005 memcpy(fadt_mod, fadt, fadt->Header.Length);
4006 fadt_mod->Header.Length = 0xF4;
4007
4008}
4009else
4010{
4011fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(fadt->Header.Length);
4012if (!fadt_mod)
4013{
4014printf("Unable to allocate kernel memory for fadt mod\n");
4015return (void*)0ul;
4016}
4017memcpy(fadt_mod, fadt, fadt->Header.Length);
4018}
4019
4020
4021//fadt_mod->Header.Revision = 0x04; // FADT rev 4
4022fadt_mod->ResetRegister = FillGASStruct(0, 0);
4023fadt_mod->ResetValue = 0;
4024fadt_mod->Reserved4[0] = 0;
4025fadt_mod->Reserved4[1] = 0;
4026fadt_mod->Reserved4[2] = 0;
4027
4028 fadt_mod->XPm1aEventBlock = FillGASStruct(fadt_mod->Pm1aEventBlock, fadt_mod->Pm1EventLength);
4029fadt_mod->XPm1bEventBlock = FillGASStruct(fadt_mod->Pm1bEventBlock, fadt_mod->Pm1EventLength);
4030fadt_mod->XPm1aControlBlock = FillGASStruct(fadt_mod->Pm1aControlBlock, fadt_mod->Pm1ControlLength);
4031fadt_mod->XPm1bControlBlock = FillGASStruct(fadt_mod->Pm1bControlBlock, fadt_mod->Pm1ControlLength);
4032fadt_mod->XPm2ControlBlock = FillGASStruct(fadt_mod->Pm2ControlBlock, fadt_mod->Pm2ControlLength);
4033fadt_mod->XPmTimerBlock = FillGASStruct(fadt_mod->PmTimerBlock, fadt_mod->PmTimerLength);
4034fadt_mod->XGpe0Block = FillGASStruct(fadt_mod->Gpe0Block, fadt_mod->Gpe0BlockLength);
4035fadt_mod->XGpe1Block = FillGASStruct(fadt_mod->Gpe1Block, fadt_mod->Gpe1BlockLength);
4036 if (fadt->Header.Revision < 4)
4037{
4038fadt_mod->Header.Revision = 0x04; // FADT rev 4
4039verbose("Converted ACPI V%d FADT to ACPI V4 FADT\n", fadt->Header.Revision);
4040
4041}
4042}
4043else
4044{
4045
4046if (fadt_rev2_needed)
4047{
4048if (fadt->Header.Length < 0x84 )
4049{
4050fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(0x84);
4051if (!fadt_mod)
4052{
4053printf("Unable to allocate kernel memory for fadt mod\n");
4054return (void*)0ul;
4055}
4056bzero(fadt_mod, 0x84);
4057memcpy(fadt_mod, fadt, fadt->Header.Length);
4058fadt_mod->Header.Length = 0x84;
4059}
4060else
4061{
4062fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(fadt->Header.Length);
4063if (!fadt_mod)
4064{
4065printf("Unable to allocate kernel memory for fadt mod\n");
4066return (void*)0ul;
4067}
4068memcpy(fadt_mod, fadt, fadt->Header.Length);
4069}
4070
4071if (fadt->Header.Revision < 2)
4072{
4073fadt_mod->Header.Revision = 0x02; // FADT rev 2 (ACPI 1.0B MS extensions)
4074verbose("Converted ACPI V%d FADT to ACPI V2 FADT\n", fadt->Header.Revision );
4075}
4076}
4077else
4078{
4079if (fadt->Header.Length < 0x74 )
4080{
4081fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(0x74);
4082if (!fadt_mod)
4083{
4084printf("Unable to allocate kernel memory for fadt mod\n");
4085return (void*)0ul;
4086}
4087bzero(fadt_mod, 0x74);
4088memcpy(fadt_mod, fadt, fadt->Header.Length);
4089fadt_mod->Header.Length = 0x74;
4090fadt_mod->Header.Revision = 0x01;
4091verbose("Warning: ACPI FADT length was < 0x74 which is the minimum for the ACPI FADT V1 specification, \n", fadt->Header.Revision );
4092verbose(" trying to convert it to Version 1. \n");
4093
4094}
4095else
4096{
4097fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(fadt->Header.Length);
4098if (!fadt_mod)
4099{
4100printf("Unable to allocate kernel memory for fadt mod\n");
4101return (void*)0ul;
4102}
4103memcpy(fadt_mod, fadt, fadt->Header.Length);
4104}
4105}
4106}
4107bool intelfadtspec = true;
4108U8 Type = PMProfileError;
4109// Determine system type / PM_Model
4110
4111// Fix System-type if needed (should never happen)
4112if (Platform->Type > MaxSupportedPMProfile)
4113{
4114if(fadt_mod->PreferredProfile <= MaxSupportedPMProfile)
4115Platform->Type = fadt_mod->PreferredProfile; // get the fadt if correct
4116else
4117Platform->Type = 1;/* Set a fixed value (Desktop) */
4118}
4119
4120// If needed, set System-type from PM_Profile (if valid) else set PM_Profile with a fixed the System-type
4121// Give prior to the FADT pm profile, allow to also control this value with a patched FADT table
4122if (fadt_mod->PreferredProfile != Platform->Type)
4123{
4124bool val = false;
4125getBoolForKey("PreferInternalProfileDetect", &val, &bootInfo->bootConfig); // if true Give prior to the profile resolved trought the CPU model
4126
4127val = Platform->CPU.isServer ;
4128
4129if (fadt_mod->PreferredProfile <= MaxSupportedPMProfile && !val)
4130{
4131Platform->Type = fadt_mod->PreferredProfile;
4132}
4133else
4134{
4135fadt_mod->PreferredProfile = Platform->Type;
4136}
4137
4138}
4139
4140// Set PM_Profile and System-type if user wanted this value to be forced
4141if ( (value=getStringForKey("SystemType", &bootInfo->bootConfig))!=NULL)
4142{
4143if ((Type = (unsigned char) strtoul(value, NULL, 10) ) <= MaxSupportedPMProfile)
4144{
4145if (fadt_mod->PreferredProfile != Type)
4146{
4147verbose("FADT: changing Preferred_PM_Profile from %d to %d\n", fadt->PreferredProfile, Type);
4148fadt_mod->PreferredProfile = Platform->Type = Type;
4149}
4150else
4151{
4152DBG("FADT: Preferred_PM_Profile was already set to %d, no need to be changed\n",Type);
4153}
4154
4155} else printf("Error: system-type must be 0..6. Defaulting to %d !\n", Platform->Type);
4156}
4157
4158getBoolForKey(KIntelFADT, &intelfadtspec, &bootInfo->bootConfig);
4159if ((pmbase == 0) && (cpu_map_error == 0) && (intelfadtspec == true))
4160{
4161ACPI_TABLE_DSDT *DsdtPointer ;
4162if (new_dsdt != (void*)0ul)
4163DsdtPointer = new_dsdt;
4164else if ((fadt_mod->Header.Revision >= 3) && (fadt_mod->XDsdt != 0ul))
4165DsdtPointer = (ACPI_TABLE_DSDT *)((U32)fadt_mod->XDsdt);
4166else
4167DsdtPointer = (ACPI_TABLE_DSDT *)fadt_mod->Dsdt;
4168
4169generate_cpu_map_from_acpi(DsdtPointer);
4170}
4171
4172// Patch DSDT Address if we have loaded a DSDT table
4173if(new_dsdt != (void*)0ul)
4174fadt_mod->Dsdt=(U32)new_dsdt;
4175
4176fadt_mod->Facs= fadt->Facs;
4177//fadt_mod->Facs=(U32)generate_facs(false);
4178
4179// Patch FADT to fix restart
4180if (fadt_mod->Header.Revision >= 2 && fix_restart)
4181{
4182 fadt_mod->Flags|= 0x400;
4183
4184int type = PCI_RESET_TYPE;
4185getIntForKey(KResetType, &type, &bootInfo->bootConfig);
4186if (type == KEYBOARD_RESET_TYPE)
4187{
4188//Azi: keyboard reset; http://forum.voodooprojects.org/index.php/topic,1056.msg9802.html#msg9802
4189fadt_mod->ResetRegister = FillGASStruct(0x64, 1);
4190fadt_mod->ResetValue = 0xfe;
4191}
4192else
4193{
4194fadt_mod->ResetRegister = FillGASStruct(0x0cf9, 1);
4195fadt_mod->ResetValue = 0x06;
4196}
4197verbose("FADT: Restart Fix applied (Type : %s) !\n", (type == 0) ? "PCI": "KEYBOARD");
4198}
4199
4200 if (fadt_mod->Header.Revision >= 3)
4201{
4202
4203
4204 if (UpdateFADT)
4205{
4206
4207//fadt_mod->XFacs= (U64)((U32)generate_facs(true));
4208 fadt_mod->XFacs=(U64)fadt->Facs;
4209
4210 }
4211else
4212{
4213fadt_mod->XFacs=(U64)fadt->XFacs;
4214}
4215
4216
4217 if(new_dsdt != (void*)0ul)
4218 fadt_mod->XDsdt=((U64)(U32)new_dsdt);
4219else if (UpdateFADT)
4220fadt_mod->XDsdt=(U64)fadt_mod->Dsdt;
4221
4222
4223 Platform->hardware_signature = ((ACPI_TABLE_FACS *)((U32)fadt_mod->XFacs))->HardwareSignature;
4224
4225 }
4226else
4227{
4228
4229 Platform->hardware_signature = ((ACPI_TABLE_FACS *)fadt_mod->Facs)->HardwareSignature;
4230
4231 }
4232
4233
4234DBG("setting hardware_signature to %x \n",Platform->hardware_signature);
4235
4236
4237
4238if (pmbase && (intelfadtspec == true))
4239ProcessFadt(fadt_mod, pmbase); // The checksum correction will be done by ProcessFadt
4240else
4241SetChecksum(&fadt_mod->Header); // Correct the checksum
4242
4243return fadt_mod;
4244}
4245
4246static U32 process_xsdt (ACPI_TABLE_RSDP *rsdp_mod , U32 *new_table_list)
4247{
4248TagPtr DropTables_p = XMLCastDict(XMLGetProperty(bootInfo->bootConfig.dictionary, (const char*)"ACPIDropTables"));
4249U32 new_table = 0ul;
4250U8 new_table_index = 0, table_added = 0;
4251ACPI_TABLE_XSDT *xsdt = (void*)0ul, *xsdt_mod = (void*)0ul;
4252ACPI_TABLE_RSDT *rsdt_conv= (void *)0ul;
4253
4254// FIXME: handle 64-bit address correctly
4255
4256xsdt=(ACPI_TABLE_XSDT *)acpi_tables.XsdtPointer;
4257
4258verbose("* Processing XSDT: \n");
4259
4260DBG(" XSDT @%x, Length=%d\n", (U32)xsdt,
4261xsdt->Header.Length);
4262
4263if (xsdt != (void *)0ul)
4264{
4265U32 dropoffset=0, index;
4266table_added = 0;
4267
4268xsdt_mod=(ACPI_TABLE_XSDT *)AllocateKernelMemory(xsdt->Header.Length);
4269if (!xsdt_mod)
4270{
4271printf("Unable to allocate kernel memory for xsdt mod\n");
4272return (0);
4273}
4274bzero(xsdt_mod, xsdt->Header.Length);
4275memcpy(&xsdt_mod->Header, &xsdt->Header, sizeof(ACPI_TABLE_HEADER));
4276
4277U32 num_tables=get_num_tables64(xsdt);
4278
4279for (index = 0; index < num_tables; index++)
4280{
4281
4282U64 ptr = xsdt->TableOffsetEntry[index];
4283
4284{
4285if (ptr > ULONG_MAX)
4286{
4287#if DEBUG_ACPI
4288printf("Warning xsdt->TableOffsetEntry[%d]: Beyond addressable memory in this CPU mode, ignored !!!\n",index);
4289#endif
4290continue;
4291}
4292
4293bool unsafe = false;
4294getBoolForKey(kUnsafeACPI, &unsafe, &bootInfo->bootConfig);
4295
4296if (!unsafe)
4297{
4298if (GetChecksum(((ACPI_TABLE_HEADER *) (unsigned long)ptr),
4299((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Length) != 0)
4300{
4301#if DEBUG_ACPI
4302printf("Warning xsdt->TableOffsetEntry[%d]: Invalide checksum, ignored !!!\n",index);
4303#endif
4304continue;
4305}
4306}
4307
4308}
4309
4310xsdt_mod->TableOffsetEntry[index-dropoffset]=ptr;
4311
4312char tableSig[4];
4313
4314strlcpy(tableSig, (char*)((U32)ptr), sizeof(tableSig)+1);
4315
4316DBG("** Processing %s,", tableSig );
4317
4318DBG(" @%x, Length=%d\n", (U32)ptr,
4319((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Length);
4320
4321{
4322bool oem = false;
4323char oemOption[OEMOPT_SIZE];
4324sprintf(oemOption, "oem%s",tableSig );
4325if (getBoolForKey(oemOption, &oem, &bootInfo->bootConfig) && oem) // This method don't work for DSDT and FACS
4326{
4327
4328DBG(" %s required\n", oemOption);
4329
4330if (get_new_table_in_list(new_table_list,(*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature), &new_table_index) != (void*)0ul)
4331new_table_list[new_table_index] = 0ul; // This way new table will not be added to the new rsdt list !!
4332
4333continue;
4334}
4335}
4336
4337{
4338TagPtr match_drop = XMLGetProperty(DropTables_p, (const char*)tableSig);
4339if ( match_drop )
4340{
4341char *tmp = XMLCastString(match_drop);
4342if (strcmp(tmp,"No") != 0)
4343{
4344dropoffset++;
4345DBG(" %s table dropped\n",tableSig);
4346continue;
4347}
4348}
4349}
4350
4351{
4352if ((new_table = (U32)get_new_table_in_list(new_table_list,(*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature), &new_table_index)) != 0ul)
4353{
4354DBG(" Found replacement for table %s\n",tableSig);
4355xsdt_mod->TableOffsetEntry[index-dropoffset]=(U64)new_table;
4356new_table_list[new_table_index] = 0ul; // table replaced !!
4357continue;
4358}
4359}
4360
4361}
4362
4363
4364{
4365U8 i;
4366for (i = 0; i< (MAX_ACPI_TABLE + RESERVED_AERA); i++)
4367{
4368if (new_table_list[i] != 0ul)
4369{
4370#if DEBUG_ACPI
4371ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;
4372printf("Adding table : ");
4373print_nameseg(*(U32 *) (table_array[i]->Signature));
4374printf("\n");
4375#endif
4376xsdt_mod->TableOffsetEntry[index-dropoffset]=(U64)new_table_list[i];
4377table_added++;
4378index++;
4379}
4380}
4381}
4382
4383// Correct the checksum of XSDT
4384xsdt_mod->Header.Length-=8*dropoffset;
4385xsdt_mod->Header.Length+=8*table_added;
4386
4387SetChecksum(&xsdt_mod->Header);
4388
4389update_rsdp_with_xsdt(rsdp_mod, xsdt_mod);
4390
4391verbose("* Creating new RSDT from XSDT table\n");
4392
4393rsdt_conv = (ACPI_TABLE_RSDT *)gen_alloc_rsdt_from_xsdt(xsdt_mod);
4394
4395if (rsdt_conv != (void*)0ul)
4396{
4397#if DEBUG_ACPI
4398DBG("Attempting to update RSDP with RSDT \n");
4399{
4400U32 ret = update_rsdp_with_rsdt(rsdp_mod, rsdt_conv);
4401if (ret)
4402DBG("RSDP update with RSDT successfully !!! \n");
4403}
4404#else
4405update_rsdp_with_rsdt(rsdp_mod, rsdt_conv);
4406#endif
4407}
4408
4409}
4410else
4411{
4412DBG("About to drop XSDT\n");
4413
4414/*FIXME: Now we just hope that if MacOS doesn't find XSDT it reverts to RSDT.
4415 * A Better strategy would be to generate
4416 */
4417
4418rsdp_mod->XsdtPhysicalAddress=0xffffffffffffffffLL;
4419verbose("XSDT not found or XSDT incorrect\n");
4420}
4421return (1);
4422
4423}
4424
4425static U32 process_rsdt(ACPI_TABLE_RSDP *rsdp_mod , bool gen_xsdt, U32 *new_table_list)
4426{
4427TagPtr DropTables_p = XMLCastDict(XMLGetProperty(bootInfo->bootConfig.dictionary, (const char*)"ACPIDropTables"));
4428U32 new_table = 0ul;
4429U8 new_table_index = 0, table_added = 0;
4430U32 dropoffset=0, index;
4431ACPI_TABLE_RSDT *rsdt = (void *)0ul, *rsdt_mod= (void *)0ul;
4432ACPI_TABLE_XSDT *xsdt_conv = (void *)0ul;
4433
4434rsdt=(ACPI_TABLE_RSDT *)acpi_tables.RsdtPointer;
4435
4436rsdt_mod=(ACPI_TABLE_RSDT *)AllocateKernelMemory(rsdt->Header.Length);
4437
4438if (!rsdt_mod)
4439{
4440printf("Unable to allocate kernel memory for rsdt mod\n");
4441return (0);
4442}
4443
4444bzero(rsdt_mod, rsdt->Header.Length);
4445memcpy (&rsdt_mod->Header, &rsdt->Header, sizeof(ACPI_TABLE_HEADER));
4446
4447U32 num_tables = get_num_tables(rsdt);
4448
4449verbose("* Processing RSDT: \n");
4450
4451DBG(" RSDT @%x, Length %d\n",rsdt, rsdt->Header.Length);
4452
4453ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) rsdt->TableOffsetEntry;
4454
4455// Compute number of table pointers included in RSDT
4456num_tables = get_num_tables(rsdt);
4457
4458for (index = 0; index < num_tables; index++)
4459{
4460
4461{
4462
4463bool unsafe = false;
4464getBoolForKey(kUnsafeACPI, &unsafe, &bootInfo->bootConfig);
4465
4466if (!unsafe)
4467{
4468if (GetChecksum(table_array[index], table_array[index]->Length) != 0)
4469{
4470#if DEBUG_ACPI
4471printf("Warning rsdt->TableOffsetEntry[%d]: Invalide checksum, ignored !!!\n",index);
4472#endif
4473continue;
4474}
4475}
4476
4477}
4478
4479rsdt_mod->TableOffsetEntry[index-dropoffset]=rsdt->TableOffsetEntry[index];
4480
4481char tableSig[4];
4482
4483strlcpy(tableSig, (char*)(rsdt->TableOffsetEntry[index]), sizeof(tableSig)+1);
4484
4485DBG("** Processing %s,", tableSig );
4486
4487DBG(" @%x, Length=%d\n", (U32)table_array[index],
4488table_array[index]->Length);
4489
4490{
4491bool oem = false;
4492char oemOption[OEMOPT_SIZE];
4493sprintf(oemOption, "oem%s",tableSig );
4494if (getBoolForKey(oemOption, &oem, &bootInfo->bootConfig) && oem) // This method don't work for DSDT and FACS
4495{
4496DBG(" %s required\n", oemOption);
4497
4498if (get_new_table_in_list(new_table_list,(*(U32 *) (table_array[index]->Signature)), &new_table_index) != (void*)0ul )
4499new_table_list[new_table_index] = 0ul; // This way new table will not be added to the new rsdt list !!
4500
4501continue;
4502}
4503}
4504
4505{
4506TagPtr match_drop = XMLGetProperty(DropTables_p, (const char*)tableSig);
4507if ( match_drop )
4508{
4509char *tmp = XMLCastString(match_drop);
4510if (strcmp(tmp,"No") != 0)
4511{
4512dropoffset++;
4513DBG(" %s table dropped\n",tableSig);
4514continue;
4515}
4516}
4517}
4518
4519{
4520if ((new_table = (U32)get_new_table_in_list(new_table_list,(*(U32 *) (table_array[index]->Signature)), &new_table_index)) != 0ul)
4521{
4522DBG(" Found replacement for table %s\n",tableSig);
4523
4524rsdt_mod->TableOffsetEntry[index-dropoffset]=new_table;
4525new_table_list[new_table_index] = 0ul; // table replaced !!
4526continue;
4527}
4528}
4529//}
4530}
4531DBG("\n");
4532
4533{
4534U8 i;
4535for (i = 0; i< (MAX_ACPI_TABLE + RESERVED_AERA); i++)
4536{
4537if (new_table_list[i] != 0ul)
4538{
4539#if DEBUG_ACPI
4540ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;
4541printf("Adding table : ");
4542print_nameseg(*(U32 *) (table_array[i]->Signature));
4543printf("\n");
4544#endif
4545rsdt_mod->TableOffsetEntry[index-dropoffset]=new_table_list[i];
4546table_added++;
4547index++;
4548}
4549}
4550}
4551
4552// Correct the checksum of RSDT
4553rsdt_mod->Header.Length-=4*dropoffset;
4554rsdt_mod->Header.Length+=4*table_added;
4555
4556DBG("RSDT: Original checksum %d\n", rsdt_mod->Header.Checksum);
4557
4558SetChecksum(&rsdt_mod->Header);
4559
4560DBG("New checksum %d at %x\n", rsdt_mod->Header.Checksum,rsdt_mod);
4561
4562update_rsdp_with_rsdt(rsdp_mod, rsdt_mod);
4563
4564if (gen_xsdt)
4565{
4566verbose("* Creating new XSDT from RSDT table\n");
4567xsdt_conv = (ACPI_TABLE_XSDT *)gen_alloc_xsdt_from_rsdt(rsdt_mod);
4568
4569if (xsdt_conv != (void *)0ul )
4570{
4571#if DEBUG_ACPI
4572DBG("Attempting to update RSDP with XSDT \n");
4573{
4574U32 ret = update_rsdp_with_xsdt(rsdp_mod, xsdt_conv);
4575if (ret)
4576DBG("RSDP update with XSDT successfully !!! \n");
4577}
4578#else
4579update_rsdp_with_xsdt(rsdp_mod, xsdt_conv);
4580#endif
4581
4582}
4583
4584}
4585return (1);
4586}
4587
4588EFI_STATUS setupAcpi(void)
4589{
4590U8 Revision = 0;
4591
4592 cpu_map_error = 0;
4593 cpu_map_count = 0;
4594 pmbase = 0;
4595
4596 EFI_STATUS Status = EFI_ABORTED;
4597
4598U32 new_table_list[MAX_ACPI_TABLE + RESERVED_AERA]; //max table + reserved aera
4599U8 new_table_index = 0;
4600
4601ACPI_TABLE_DSDT* DsdtPtr = (void *)0ul; // a Pointer to the dsdt table present in fadt_mod
4602
4603ACPI_TABLE_DSDT *new_dsdt = (void *)0ul;// a Pointer to the dsdt file
4604ACPI_TABLE_FADT *fadt_mod = (void *)0ul; // a Pointer to the patched FACP table
4605ACPI_TABLE_FADT *fadt_file = (void *)0ul; // a Pointer to the (non-patched) fadt file
4606ACPI_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
4607ACPI_TABLE_RSDP *rsdp_mod = (void *)0ul, *rsdp_conv= (void *)0ul;
4608
4609U32 rsdplength;
4610
4611bool update_acpi=false, gen_xsdt=false;
4612
4613bool gen_csta=false, gen_psta=false, speed_step=false;
4614bool gen_ssdt=false; // will force to generate ssdt even if gen_csta and gen_psta = false
4615 bool gen_tsta=false;
4616bool oem_dsdt=false, oem_fadt=false;
4617
4618// Find original rsdp
4619if (!FindAcpiTables(&acpi_tables))
4620{
4621printf("Error: AcpiCodec Failed to detect ACPI tables.\n");
4622getc();
4623return EFI_NOT_FOUND;
4624}
4625
4626{
4627U8 i;
4628
4629for (i=0; i<(MAX_ACPI_TABLE + RESERVED_AERA); i++)
4630{
4631new_table_list[i] = 0ul;
4632}
4633bool tmpval;
4634
4635oem_dsdt=getBoolForKey(kOEMDSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
4636oem_fadt=getBoolForKey(kOEMFADT, &tmpval, &bootInfo->bootConfig)&&tmpval;
4637
4638gen_csta=getBoolForKey(kGenerateCStates, &tmpval, &bootInfo->bootConfig)&&tmpval;
4639gen_psta=getBoolForKey(kGeneratePStates, &tmpval, &bootInfo->bootConfig)&&tmpval;
4640gen_ssdt=getBoolForKey(KForceSSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
4641update_acpi=getBoolForKey(kUpdateACPI, &tmpval, &bootInfo->bootConfig)&&tmpval;
4642
4643speed_step=getBoolForKey(kSpeedstep, &tmpval, &bootInfo->bootConfig)&&tmpval;
4644turbo_enabled=(U32)getBoolForKey(kCoreTurbo, &tmpval, &bootInfo->bootConfig)&&tmpval;
4645#if BUILD_ACPI_TSS
4646gen_tsta=(U32)getBoolForKey(kGenerateTStates, &tmpval, &bootInfo->bootConfig)&&tmpval;
4647#endif
4648checkOem=getBoolForKey(kOnlySignedAml, &tmpval, &bootInfo->bootConfig)&&tmpval;
4649}
4650
4651{
4652char* name;
4653long flags;
4654long time;
4655long ret = -1;
4656U8 i = 0;
4657char dirspec[512];
4658bool acpidir_found = false;
4659
4660ret = GetFileInfo("rd(0,0)/Extra/", "Acpi", &flags, &time);
4661 if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory))
4662{
4663 sprintf(dirspec, "rd(0,0)/Extra/Acpi/");
4664 acpidir_found = true;
4665
4666 }
4667else
4668{
4669
4670 ret = GetFileInfo("/Extra/", "Acpi", &flags, &time);
4671 if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory))
4672{
4673 sprintf(dirspec, "/Extra/Acpi/");
4674 acpidir_found = true;
4675
4676 }
4677else
4678{
4679 ret = GetFileInfo("bt(0,0)/Extra/", "Acpi", &flags, &time);
4680 if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory))
4681{
4682 sprintf(dirspec, "bt(0,0)/Extra/Acpi/");
4683 acpidir_found = true;
4684
4685 }
4686 }
4687 }
4688
4689if (acpidir_found == true)
4690{
4691if (checkOem == true)
4692{
4693MakeAcpiSgn();
4694}
4695
4696struct dirstuff* moduleDir = opendir(dirspec);
4697while(readdir(moduleDir, (const char**)&name, &flags, &time) >= 0)
4698{
4699if((strstr(name, ".aml")) && ((strlen(dirspec)+strlen(name)) < 512))
4700{
4701// Some simple verifications to save time in case of those tables simply named as follow:
4702if ((strncmp(name, "RSDT", 4) == 0) || (strncmp(name, "rsdt", 4) == 0) ||
4703(strncmp(name, "XSDT", 4) == 0) || (strncmp(name, "xsdt", 4) == 0) ||
4704(strncmp(name, "RSDP", 4) == 0) || (strncmp(name, "rsdp", 4) == 0))
4705{
4706continue;
4707}
4708
4709if ((strncmp(name, "FACS", 4) == 0) || (strncmp(name, "facs", 4) == 0)) // FACS is not supported
4710{
4711continue;
4712}
4713
4714DBG("* Attempting to load acpi table: %s\n", name);
4715if ( (new_table_list[i]=(U32)loadACPITable(new_table_list,dirspec,name)))
4716{
4717if (i < MAX_ACPI_TABLE)
4718{
4719i++;
4720}
4721else
4722{
4723DBG("Max nb of allowed aml files reached, exiting .");
4724break;
4725}
4726}
4727
4728}
4729#if DEBUG_ACPI
4730else
4731{
4732
4733printf("Ignoring %s\n", name);
4734}
4735#endif
4736
4737}
4738
4739if (i)
4740{
4741//sanitize the new tables list
4742sanitize_new_table_list(new_table_list);
4743
4744//move to kernel memory
4745move_table_list_to_kmem(new_table_list);
4746
4747DBG("New ACPI tables Loaded in memory\n");
4748}
4749}
4750
4751}
4752#if HARDCODED_DSDT
4753 do {
4754#include "dsdt_PRLSACPI.h"
4755
4756 U8 index = 0;
4757
4758 if ((get_new_table_in_list(new_table_list, NAMESEG("DSDT"), &new_table_index)) != (void*)0ul )
4759 {
4760 index = new_table_index;
4761 }
4762 else
4763 {
4764 U8 empty = get_0ul_index_in_list(new_table_list, false);
4765 if (empty != ACPI_TABLE_LIST_FULL_NON_RESERVED)
4766 {
4767 index = empty;
4768 }
4769 else
4770 {
4771 printf("Error: not enought reserved space in the new acpi list for the Harcoded DSDT table,\n ");
4772 printf(" please increase the RESERVED_AERA\n");
4773
4774 break;
4775 }
4776 }
4777
4778if (index)
4779{
4780
4781ACPI_TABLE_DSDT *tmp = (ACPI_TABLE_DSDT *)DsdtAmlCode;
4782ACPI_TABLE_DSDT *hardcoded_dsdt = (void *)0ul;
4783
4784hardcoded_dsdt = (ACPI_TABLE_DSDT *)AllocateKernelMemory(tmp->Header.Length);
4785memcpy(hardcoded_dsdt, tmp, tmp->Header.Length);
4786new_table_list[index] = (U32)hardcoded_dsdt; // add the patched table to the list
4787}
4788else
4789{
4790printf("Error: not enought reserved space in the new acpi list for the Harcoded DSDT table,\n ");
4791printf(" please increase the RESERVED_AERA\n");
4792
4793break;
4794}
4795 } while (0);
4796#endif
4797if (speed_step)
4798{
4799gen_psta= true;
4800gen_csta= true;
4801}
4802
4803
4804ACPI_TABLE_RSDP *rsdp=(ACPI_TABLE_RSDP *)acpi_tables.RsdPointer;
4805
4806if (rsdp == (void*)0ul || (GetChecksum(rsdp, (rsdp->Revision == 0) ? ACPI_RSDP_REV0_SIZE:sizeof(ACPI_TABLE_RSDP)) != 0) )
4807{
4808printf("Error : ACPI RSD PTR Revision %d checksum is incorrect or table not found \n",rsdp->Revision );
4809return EFI_UNSUPPORTED;
4810}
4811
4812if ((update_acpi) && (rsdp->Revision == 0))
4813{
4814
4815rsdp_conv = (ACPI_TABLE_RSDP *)gen_alloc_rsdp_v2_from_v1(rsdp);
4816if (rsdp_conv != (void *)0ul)
4817{
4818gen_xsdt = true;
4819rsdp = rsdp_conv;
4820verbose("Converted ACPI RSD PTR Revision 0 to Revision 2\n");
4821}
4822
4823}
4824
4825Revision = rsdp->Revision ;
4826rsdplength=(Revision == 2)?rsdp->Length:ACPI_RSDP_REV0_SIZE;
4827
4828DBG("RSDP Revision %d found @%x. Length=%d\n",Revision,rsdp,rsdplength);
4829
4830if (gen_xsdt)
4831{
4832rsdp_mod=rsdp_conv;
4833}
4834else
4835{
4836rsdp_mod=(ACPI_TABLE_RSDP *) AllocateKernelMemory(rsdplength);
4837
4838if (!rsdp_mod) return EFI_OUT_OF_RESOURCES;
4839
4840memcpy(rsdp_mod, rsdp, rsdplength);
4841}
4842
4843
4844if ((fadt_file = (ACPI_TABLE_FADT *)get_new_table_in_list(new_table_list, NAMESEG("FACP"), &new_table_index)) != (void *)0ul)
4845{
4846
4847if (oem_fadt == false)
4848FacpPointer = (ACPI_TABLE_FADT *)fadt_file;
4849
4850new_table_list[new_table_index] = 0ul; // This way, the non-patched table will not be added in our new rsdt/xsdt table list
4851
4852} else
4853FacpPointer = (acpi_tables.FacpPointer64 != (void *)0ul) ?
4854(ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer;
4855
4856#if DEBUG_ACPI
4857if ((FacpPointer != (void *)0ul) || (oem_fadt == false))
4858{
4859printf("FADT found @%x, Length %d\n",FacpPointer, FacpPointer->Header.Length);
4860printf("Attempting to patch FADT entry of %s\n",(acpi_tables.FacpPointer64 != (void *)0ul) ? ACPI_SIG_XSDT : ACPI_SIG_RSDT);
4861}
4862else if (oem_fadt == true)
4863{
4864ACPI_TABLE_FADT * FacpPtr = (acpi_tables.FacpPointer64 != (void *)0ul) ?
4865(ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer;
4866
4867printf("FADT found @%x ( Length %d ) in %s \n",FacpPtr, FacpPtr->Header.Length, (acpi_tables.FacpPointer64 != (void *)0ul) ? ACPI_SIG_XSDT : ACPI_SIG_RSDT);
4868}
4869#endif
4870
4871if ((new_dsdt = (ACPI_TABLE_DSDT *)get_new_table_in_list(new_table_list, NAMESEG("DSDT"), &new_table_index)) != (void*)0ul )
4872{
4873new_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
4874}
4875
4876if (oem_fadt == false)
4877{
4878
4879fadt_mod = patch_fadt(FacpPointer, (oem_dsdt == false) ? new_dsdt : (void*)0ul , (acpi_tables.FacpPointer64 != (void *)0ul ));
4880
4881if (fadt_mod != (void*)0ul)
4882{
4883DsdtPtr = ((fadt_mod->Header.Revision >= 3) && (fadt_mod->XDsdt != 0)) ? (ACPI_TABLE_DSDT*)((U32)fadt_mod->XDsdt):(ACPI_TABLE_DSDT*)fadt_mod->Dsdt;
4884
4885U8 empty = get_0ul_index_in_list(new_table_list,true);
4886if (empty != ACPI_TABLE_LIST_FULL)
4887{
4888new_table_list[empty] = (U32)fadt_mod; // add the patched table to the list
4889}
4890else
4891{
4892printf("Error: not enought reserved space in the new acpi list for the Patched FACP table,\n ");
4893printf(" please increase the RESERVED_AERA\n");
4894}
4895
4896}
4897else
4898{
4899printf("Error: Failed to patch the FADT Table, trying fallback to the FADT original pointer\n");
4900fadt_mod = (acpi_tables.FacpPointer64 != (void *)0ul) ?
4901(ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer;
4902
4903DsdtPtr = ((fadt_mod->Header.Revision >= 3) && (fadt_mod->XDsdt != 0)) ? (ACPI_TABLE_DSDT*)((U32)fadt_mod->XDsdt):(ACPI_TABLE_DSDT*)fadt_mod->Dsdt;
4904
4905U8 empty = get_0ul_index_in_list(new_table_list,true);
4906if (empty != ACPI_TABLE_LIST_FULL)
4907{
4908new_table_list[empty] = (U32)fadt_mod;
4909}
4910else
4911{
4912printf("Error: not enought reserved space in the new acpi list for the FACP table,\n ");
4913printf(" please increase the RESERVED_AERA\n");
4914}
4915}
4916
4917if (oem_dsdt == false)
4918{
4919if (generate_cpu_map_from_acpi(DsdtPtr) == 0)
4920{
4921U8 new_uid = (U8)getPciRootUID();
4922
4923/* WARNING: THIS METHOD WORK PERFECTLY BUT IT CAN RESULT TO AN INCORRECT CHECKSUM */
4924
4925if (ProcessDsdt(DsdtPtr, UIDPointer, new_uid))
4926{
4927printf("PCI0 _UID patched to %d in the DSDT table\n", new_uid);
4928}
4929
4930}
4931}
4932
4933
4934}
4935else
4936{
4937
4938// here we use the variable fadt_mod only for SSDT Generation
4939
4940fadt_mod = (acpi_tables.FacpPointer64 != (void *)0ul) ?
4941(ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer;
4942
4943DsdtPtr = ((fadt_mod->Header.Revision >= 3) && (fadt_mod->XDsdt != 0)) ? (ACPI_TABLE_DSDT*)((U32)fadt_mod->XDsdt)
4944:(ACPI_TABLE_DSDT*)fadt_mod->Dsdt;
4945}
4946
4947 {
4948 MADT_INFO madt_info;
4949 bool strip_madt = true;
4950
4951 getBoolForKey(kSTRIPAPIC, &strip_madt, &bootInfo->bootConfig);
4952
4953 if ((strip_madt == false) || (!buildMADT(new_table_list, DsdtPtr, &madt_info )))
4954 {
4955
4956 ACPI_TABLE_MADT * madt_file = (void*)0ul;
4957 ACPI_TABLE_MADT * MadtPointer = (void*)0ul;
4958 bool oem_apic=false;
4959
4960 {
4961 bool tmpval;
4962 oem_apic=getBoolForKey(kOEMAPIC, &tmpval, &bootInfo->bootConfig)&&tmpval;
4963 }
4964
4965 if ((madt_file = (ACPI_TABLE_MADT *)get_new_table_in_list(new_table_list, NAMESEG("APIC"), &new_table_index)) != (void *)0ul)
4966 {
4967 if (oem_apic == false)
4968 {
4969 MadtPointer = (ACPI_TABLE_MADT *)madt_file;
4970 }
4971
4972 } else
4973 MadtPointer = (acpi_tables.MadtPointer64 != (void*)0ul) ? (ACPI_TABLE_MADT *)acpi_tables.MadtPointer64 : (ACPI_TABLE_MADT *)acpi_tables.MadtPointer;
4974
4975 ProcessMadtInfo(MadtPointer, &madt_info);
4976
4977 }
4978
4979 if (gen_ssdt || gen_csta || gen_psta || gen_tsta)
4980 {
4981 ProcessSsdt(new_table_list, DsdtPtr, &madt_info, gen_csta, gen_psta, gen_tsta );
4982 }
4983 }
4984
4985if ((rsdp_mod != (void *)0ul) && (rsdp_mod->Length >= ACPI_RSDP_REV0_SIZE) )
4986{
4987if ((rsdp_mod->Revision == 0) || (gen_xsdt == true))
4988{
4989process_rsdt(rsdp_mod, gen_xsdt, new_table_list);
4990goto out;
4991}
4992
4993}
4994else
4995{
4996printf("Error: Incorect ACPI RSD PTR or not found \n");
4997return EFI_UNSUPPORTED;
4998}
4999
5000if ((GetChecksum(rsdp_mod, sizeof(ACPI_TABLE_RSDP)) == 0) &&
5001(Revision == 2) &&
5002(rsdplength == sizeof(ACPI_TABLE_RSDP)))
5003{
5004process_xsdt(rsdp_mod, new_table_list);
5005
5006}
5007else
5008{
5009printf("Warning : ACPI RSD PTR Revision 2 is incorrect, \n");
5010printf(" trying to fallback to Revision 1\n");
5011if ((rsdp_mod != (void *)0ul) && (rsdp_mod->Length >= ACPI_RSDP_REV0_SIZE) )
5012{
5013process_rsdt(rsdp_mod, false, new_table_list);
5014
5015}
5016else
5017{
5018printf("Error: Incorect ACPI RSD PTR or not found \n");
5019return EFI_UNSUPPORTED;
5020}
5021}
5022
5023out:
5024// Correct the checksum of RSDP
5025
5026DBG("RSDP: Original checksum %d\n", rsdp_mod->Checksum);
5027
5028setRsdpchecksum(rsdp_mod);
5029
5030DBG("New checksum %d\n", rsdp_mod->Checksum);
5031
5032if (Revision == 2)
5033{
5034DBG("RSDP: Original extended checksum %d\n", rsdp_mod->ExtendedChecksum);
5035
5036setRsdpXchecksum(rsdp_mod);
5037
5038DBG("New extended checksum %d\n", rsdp_mod->ExtendedChecksum);
5039
5040}
5041
5042verbose("ACPI Revision %d successfully patched\n", Revision);
5043
5044if (Revision == 2)
5045{
5046rsd_p = ((U64)((U32)rsdp_mod));
5047if (rsd_p)
5048Status = addConfigurationTable(&gEfiAcpi20TableGuid, &rsd_p, "ACPI_20");
5049}
5050else
5051{
5052rsd_p = ((U64)((U32)rsdp_mod));
5053if (rsd_p)
5054Status = addConfigurationTable(&gEfiAcpiTableGuid, &rsd_p, "ACPI");
5055
5056}
5057
5058#if DEBUG_ACPI==2
5059printf("Press a key to continue... (DEBUG_ACPI)\n");
5060getc();
5061#endif
5062return Status;
5063}
5064

Archive Download this file

Revision: 1804