Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 1679