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

Archive Download this file

Revision: 1840