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_32)
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 (LOCAL_APIC_NMI_CNT >= nb_cpu)
2872 continue;
2873
2874 memcpy(currentOut, nmi, nmi->Header.Length);
2875
2876 currentOut = currentOut + nmi->Header.Length;
2877
2878 // Check to confirm no MADT buffer overflow
2879 if ( (U8 *)currentOut > (U8 *)endOut )
2880 {
2881 printf("Error: MADT Buffer Length exceeded available space \n");
2882 return(0);
2883 }
2884
2885
2886 LOCAL_APIC_NMI_CNT++;
2887
2888 Length += nmi->Header.Length;
2889
2890 // Sanity check to verify compile time limit for max logical CPU is not exceeded
2891 if (LOCAL_APIC_NMI_CNT > MAX_LOGICAL_CPU)
2892 return (0);
2893
2894 break;
2895 }
2896
2897 case ACPI_MADT_TYPE_LOCAL_SAPIC:
2898 {
2899 // Process sub-tables with Type as 7: Local Sapic
2900 ACPI_MADT_LOCAL_SAPIC *sapic = current;
2901 current = sapic + 1;
2902
2903 if (LOCAL_SAPIC_CNT >= nb_cpu)
2904 continue;
2905
2906 memcpy(currentOut, sapic, sapic->Header.Length);
2907
2908 currentOut = currentOut + sapic->Header.Length;
2909
2910 // Check to confirm no MADT buffer overflow
2911 if ( (U8 *)currentOut > (U8 *)endOut )
2912 {
2913 printf("Error: MADT Buffer Length exceeded available space \n");
2914 return(0);
2915 }
2916
2917
2918 LOCAL_SAPIC_CNT++;
2919
2920 Length += sapic->Header.Length;
2921
2922 // Sanity check to verify compile time limit for max logical CPU is not exceeded
2923 if (LOCAL_SAPIC_CNT > MAX_LOGICAL_CPU)
2924 return (0);
2925
2926 break;
2927 }
2928
2929 case ACPI_MADT_TYPE_INTERRUPT_SOURCE:
2930 {
2931 // Process sub-tables with Type as 8: Platform Interrupt Source
2932 ACPI_MADT_INTERRUPT_SOURCE *intsrc = current;
2933 current = intsrc + 1;
2934
2935 if (INT_SRC_CNT >= nb_cpu)
2936 continue;
2937
2938 memcpy(currentOut, intsrc, intsrc->Header.Length);
2939
2940 currentOut = currentOut + intsrc->Header.Length;
2941
2942 // Check to confirm no MADT buffer overflow
2943 if ( (U8 *)currentOut > (U8 *)endOut )
2944 {
2945 printf("Error: MADT Buffer Length exceeded available space \n");
2946 return(0);
2947 }
2948
2949
2950 INT_SRC_CNT++;
2951
2952 Length += intsrc->Header.Length;
2953
2954 // Sanity check to verify compile time limit for max logical CPU is not exceeded
2955 if (INT_SRC_CNT > MAX_LOGICAL_CPU)
2956 return (0);
2957
2958 break;
2959 }
2960
2961default:
2962 {
2963
2964 // Process all other sub-tables
2965 current = (U8 *) subtable + subtable->Length;
2966 currentOut = (U8 *) subtableOut + subtable->Length;
2967
2968 memcpy(subtableOut, subtable, subtable->Length);
2969
2970 // Check to confirm no MADT buffer overflow
2971 if ( (U8 *)currentOut > (U8 *)endOut )
2972 {
2973 printf("Error: MADT Buffer Length exceeded available space \n");
2974 return(0);
2975 }
2976
2977 Length += subtable->Length;
2978
2979 break;
2980 }
2981 } // switch
2982
2983 } // while
2984
2985 {
2986 ACPI_TABLE_MADT * new_madt = (ACPI_TABLE_MADT * )buffer;
2987
2988 // Update the Lenght of the new MADT table
2989 new_madt->Header.Length = Length;
2990
2991 // Update the checksum of the new MADT table
2992SetChecksum(&new_madt->Header);
2993 }
2994
2995 return (1);
2996}
2997
2998static U32 buildMADT(U32 * new_table_list, ACPI_TABLE_DSDT *dsdt, MADT_INFO * madt_info)
2999{
3000 DBG("Build MADT\n");
3001
3002ACPI_TABLE_MADT * madt_file = (void*)0ul;
3003ACPI_TABLE_MADT * MadtPointer = (void*)0ul;
3004 bool oem_apic=false;
3005 U8 new_table_index = 0;
3006
3007 // Check that we have a valid cpu_map (if it's not already done, it will try to generate it)
3008 if (generate_cpu_map_from_acpi(dsdt) != 0)
3009 {
3010 return(0);
3011 }
3012
3013 {
3014bool tmpval;
3015oem_apic=getBoolForKey(kOEMAPIC, &tmpval, &bootInfo->bootConfig)&&tmpval;
3016}
3017
3018 if (oem_apic == true)
3019 {
3020 return(0);
3021 }
3022
3023 if ((madt_file = (ACPI_TABLE_MADT *)get_new_table_in_list(new_table_list, NAMESEG("APIC"), &new_table_index)) != (void *)0ul)
3024{
3025 MadtPointer = (ACPI_TABLE_MADT *)madt_file;
3026
3027 new_table_list[new_table_index] = 0ul; // This way, the non-patched table will not be added in our new rsdt/xsdt table list // note: for now we don't patch this table
3028}
3029 else
3030 {
3031 MadtPointer = (acpi_tables.MadtPointer64 != (void*)0ul) ? (ACPI_TABLE_MADT *)acpi_tables.MadtPointer64 : (ACPI_TABLE_MADT *)acpi_tables.MadtPointer;
3032
3033 new_table_index = get_0ul_index_in_list(new_table_list, true);
3034
3035 // Check to confirm space is available
3036 if (new_table_index == ACPI_TABLE_LIST_FULL)
3037 {
3038 printf("Error: not enought reserved space in the new acpi list for the MADT table,\n ");
3039 printf(" please increase the RESERVED_AERA\n");
3040 return(0);
3041 }
3042 }
3043
3044 // Create buffer for MADT
3045 U8 memory_for_madt[2 * 1024];
3046
3047
3048 // Build the new MADT
3049 if ( (ProcessMadt(MadtPointer, madt_info, memory_for_madt, sizeof(memory_for_madt), cpu_map_count))== 0)
3050{
3051printf("Error: Failed to build MADT table\n");
3052return (0);
3053}
3054
3055// insert MADT in the new_table_list
3056{
3057// Create pointer to MADT just built in the stack buffer
3058ACPI_TABLE_MADT * old_madt = (ACPI_TABLE_MADT *)memory_for_madt;
3059
3060// Reserved kernel memory for the madt table
3061ACPI_TABLE_MADT *new_madt = (ACPI_TABLE_MADT *)AllocateKernelMemory(old_madt->Header.Length);
3062
3063if (!new_madt)
3064{
3065printf("Unable to allocate kernel memory for MADT ");
3066return (0);
3067}
3068// Move the old stack buffer to kernel memory
3069memcpy(new_madt, old_madt, old_madt->Header.Length);
3070
3071// Add the new madt into an empty space of the new_table_list
3072new_table_list[new_table_index] = (U32)new_madt;
3073}
3074
3075 verbose ("MADT table successfully patched\n");
3076return(1);
3077}
3078
3079static U32 ProcessSsdt(U32 * new_table_list, ACPI_TABLE_DSDT *dsdt, MADT_INFO * madt_info, bool enable_cstates, bool enable_pstates, bool enable_tstates )
3080{
3081DBG("Processing SSDT\n");
3082
3083if (Platform->CPU.Vendor != 0x756E6547) {
3084verbose ("Not an Intel platform: SSDT will not be generated !!!\n");
3085return(0);
3086}
3087
3088if (!(Platform->CPU.Features & CPUID_FEATURE_MSR)) {
3089verbose ("Unsupported CPU: SSDT will not be generated !!!\n");
3090return(0);
3091}
3092
3093if (dsdt == (void *)0ul) {
3094verbose ("DSDT not found: SSDT will not be generated !!!\n");
3095return (0);
3096}
3097
3098// Get an empty space in the new_talbe_list (true = allow reserved space)
3099U8 empty = get_0ul_index_in_list(new_table_list, true);
3100
3101// Check to confirm space is available
3102if (empty == ACPI_TABLE_LIST_FULL)
3103{
3104printf("Error: not enought reserved space in the new acpi list for the SSDT table,\n ");
3105printf(" please increase the RESERVED_AERA\n");
3106return(0);
3107}
3108
3109// Create buffer for SSDT
3110U8 memory_for_ssdt[20 * 1024];
3111
3112// Build the SSDT
3113if ( (BuildSsdt(madt_info, dsdt, memory_for_ssdt, sizeof(memory_for_ssdt), enable_cstates, enable_pstates, enable_tstates)) == 0)
3114{
3115printf("Error: Failed to build SSDT table\n");
3116return (0);
3117}
3118
3119// insert SSDT in the new_table_list
3120{
3121// Create pointer to SSDT just built in the stack buffer
3122ACPI_TABLE_SSDT * old_ssdt = (ACPI_TABLE_SSDT *)memory_for_ssdt;
3123
3124// Reserved kernel memory for the ssdt table
3125ACPI_TABLE_SSDT *new_ssdt = (ACPI_TABLE_SSDT *)AllocateKernelMemory(old_ssdt->Header.Length);
3126
3127if (!new_ssdt)
3128{
3129printf("Unable to allocate kernel memory for SSDT ");
3130return (0);
3131}
3132// Move the old stack buffer to kernel memory
3133memcpy(new_ssdt, old_ssdt, old_ssdt->Header.Length);
3134
3135// Add the new ssdt into an empty space of the new_table_list
3136new_table_list[empty] = (U32)new_ssdt;
3137}
3138
3139verbose ("SSDT table generated successfully\n");
3140return(1);
3141}
3142
3143//-----------------------------------------------------------------------------
3144static void * buildCpuScope (void * current, U32 cpu_namespace, PROCESSOR_NUMBER_TO_NAMESEG * aslCpuNamePath)
3145{
3146ACPI_SCOPE * scope = current;
3147current = scope + 1;
3148
3149scope->scopeOpcode = AML_SCOPE_OP;
3150scope->rootChar = AML_ROOT_PREFIX;
3151
3152if (aslCpuNamePath->seg_count == 1)
3153{
3154DUAL_NAME_PATH * dualNamePath = current;
3155current = dualNamePath + 1;
3156dualNamePath->prefix = AML_DUAL_NAME_PREFIX;
3157dualNamePath->nameseg[0] = cpu_namespace;
3158dualNamePath->nameseg[1] = aslCpuNamePath->nameseg[0];
3159}
3160else
3161{
3162MULTI_NAME_PATH * multiNamePath = current;
3163current = multiNamePath + 1;
3164multiNamePath->prefix = AML_MULTI_NAME_PREFIX;
3165// the nameseg count includes the root prefix and all other namesegs
3166multiNamePath->segCount = (U8) aslCpuNamePath->seg_count+1;
3167multiNamePath->nameseg[0] = cpu_namespace;
3168{
3169U32 i;
3170for (i=0; i<aslCpuNamePath->seg_count; i++)
3171multiNamePath->nameseg[i+1] = aslCpuNamePath->nameseg[i];
3172}
3173}
3174return (current);
3175}
3176//-----------------------------------------------------------------------------
3177static void * buildPDC(void * current)
3178{
3179ACPI_METHOD * pdc = current;
3180current = buildMethod(current, NAMESEG("_PDC"), 1);
3181
3182// CreateDWordField (Arg0, 0x08, CAPA)
3183current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
3184current = buildOpCode(current, AML_ARG0_OP);
3185current = buildByteConst(current, 0x08);
3186current = buildNameSeg(current, NAMESEG("CAPA"));
3187
3188// Store (CAPA, TYPE)
3189current = buildOpCode(current, AML_STORE_OP);
3190current = buildNameSeg(current, NAMESEG("CAPA"));
3191current = buildNameSeg(current, NAMESEG("TYPE"));
3192
3193// CreateDWordField (Arg0, 0x00, REVS)
3194current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
3195current = buildOpCode(current, AML_ARG0_OP);
3196current = buildByteConst(current, 0x00);
3197current = buildNameSeg(current, NAMESEG("REVS"));
3198
3199// CreateDWordField (Arg0, 0x04, SIZE)
3200current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
3201current = buildOpCode(current, AML_ARG0_OP);
3202current = buildByteConst(current, 0x04);
3203current = buildNameSeg(current, NAMESEG("SIZE"));
3204
3205// Store(SizeOf(Arg0), Local0)
3206current = buildOpCode(current, AML_STORE_OP);
3207current = buildOpCode(current, AML_SIZEOF_OP);
3208current = buildOpCode(current, AML_ARG0_OP);
3209current = buildOpCode(current, AML_LOCAL0_OP);
3210
3211// Store(Subtract(Local0, 0x08),Local1)
3212current = buildOpCode(current, AML_STORE_OP);
3213current = buildOpCode(current, AML_SUBTRACT_OP);
3214current = buildOpCode(current, AML_LOCAL0_OP);
3215current = buildByteConst(current, 0x08);
3216current = buildOpCode(current, AML_ZERO_OP);
3217current = buildOpCode(current, AML_LOCAL1_OP);
3218
3219// CreateField (Arg0, 0x40, Multiply (Local1, 0x08), TEMP)
3220current = buildOpCode(current, AML_EXT_OP_PREFIX);
3221current = buildOpCode(current, AML_CREATE_FIELD_OP);
3222current = buildOpCode(current, AML_ARG0_OP);
3223current = buildByteConst(current, 0x40);
3224current = buildOpCode(current, AML_MULTIPLY_OP);
3225current = buildOpCode(current, AML_LOCAL1_OP);
3226current = buildByteConst(current, 0x08);
3227current = buildOpCode(current, AML_ZERO_OP);
3228current = buildNameSeg(current, NAMESEG("TEMP"));
3229
3230// Name (STS0, Buffer (0x04) {0x00, 0x00, 0x00, 0x00})
3231// Create STS0 as named buffer
3232current = buildNamePath(current, NAMESEG("STS0"));
3233{
3234ACPI_SMALL_BUFFER * buff = current;
3235current = buildSmallBuffer(current);
3236
3237// count of buffer elements
3238current = buildByteConst(current, 4);
3239
3240current = buildOpCode(current, AML_ZERO_OP);
3241current = buildOpCode(current, AML_ZERO_OP);
3242current = buildOpCode(current, AML_ZERO_OP);
3243current = buildOpCode(current, AML_ZERO_OP);
3244{
3245U32 length = (U8 *)current - (U8 *)buff;
3246buff->packageLength = (U8)length - 1;
3247}
3248}
3249
3250//Concatenate (STS0, TEMP, Local2)
3251current = buildOpCode(current, AML_CONCAT_OP);
3252current = buildNameSeg(current, NAMESEG("STS0"));
3253current = buildNameSeg(current, NAMESEG("TEMP"));
3254current = buildOpCode(current, AML_LOCAL2_OP);
3255
3256//_OSC (Buffer (0x10)
3257// {
3258// /* 0000 */ 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47,
3259// /* 0008 */ 0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53
3260// }, REVS, SIZE, Local2)
3261current = buildNameSeg(current, NAMESEG("_OSC"));
3262{
3263ACPI_SMALL_BUFFER * buff = current;
3264current = buildSmallBuffer(current);
3265
3266// count of buffer elements
3267current = buildByteConst(current, 0x10);
3268
3269current = buildOpCode(current, 0x16);
3270current = buildOpCode(current, 0xa6);
3271current = buildOpCode(current, 0x77);
3272current = buildOpCode(current, 0x40);
3273current = buildOpCode(current, 0x0c);
3274current = buildOpCode(current, 0x29);
3275current = buildOpCode(current, 0xbe);
3276current = buildOpCode(current, 0x47);
3277current = buildOpCode(current, 0x9e);
3278current = buildOpCode(current, 0xbd);
3279current = buildOpCode(current, 0xd8);
3280current = buildOpCode(current, 0x70);
3281current = buildOpCode(current, 0x58);
3282current = buildOpCode(current, 0x71);
3283current = buildOpCode(current, 0x39);
3284current = buildOpCode(current, 0x53);
3285{
3286U32 length = (U8 *)current - (U8 *)buff;
3287buff->packageLength = (U8)length - 1;
3288}
3289}
3290current = buildNameSeg(current, NAMESEG("REVS"));
3291current = buildNameSeg(current, NAMESEG("SIZE"));
3292current = buildOpCode(current, AML_LOCAL2_OP);
3293
3294// Update package length in PDC object
3295//pdc->packageLength = (U8)((U8 *)current - (U8 *)&pdc->packageLength);
3296setPackageLength(&pdc->pkgLength, (U8 *)current - (U8 *)&pdc->pkgLength);
3297
3298return(current);
3299}
3300
3301//-----------------------------------------------------------------------------
3302static void * buildOSC(void * current)
3303{
3304//
3305//
3306ACPI_METHOD * osc = current;
3307current = buildMethod(current, NAMESEG("_OSC"), 4);
3308
3309// CreateDWordField (Arg3, 0x04, CAPA)
3310current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
3311current = buildOpCode(current, AML_ARG3_OP);
3312current = buildByteConst(current, 0x04);
3313current = buildNameSeg(current, NAMESEG("CAPA"));
3314
3315// Store (CAPA, TYPE)
3316current = buildOpCode(current, AML_STORE_OP);
3317current = buildNameSeg(current, NAMESEG("CAPA"));
3318current = buildNameSeg(current, NAMESEG("TYPE"));
3319
3320// CreateDWordField (Arg3, 0x00, STS0)
3321current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
3322current = buildOpCode(current, AML_ARG3_OP);
3323current = buildByteConst(current, 0x00);
3324current = buildNameSeg(current, NAMESEG("STS0"));
3325
3326// CreateDWordField (Arg3, 0x04, CAP0)
3327current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
3328current = buildOpCode(current, AML_ARG3_OP);
3329current = buildByteConst(current, 0x04);
3330current = buildNameSeg(current, NAMESEG("CAP0"));
3331
3332// CreateDWordField (Arg0, 0x00, IID0)
3333current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
3334current = buildOpCode(current, AML_ARG0_OP);
3335current = buildByteConst(current, 0x00);
3336current = buildNameSeg(current, NAMESEG("IID0"));
3337
3338// CreateDWordField (Arg0, 0x04, IID1)
3339current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
3340current = buildOpCode(current, AML_ARG0_OP);
3341current = buildByteConst(current, 0x04);
3342current = buildNameSeg(current, NAMESEG("IID1"));
3343
3344// CreateDWordField (Arg0, 0x08, IID2)
3345current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
3346current = buildOpCode(current, AML_ARG0_OP);
3347current = buildByteConst(current, 0x08);
3348current = buildNameSeg(current, NAMESEG("IID2"));
3349
3350// CreateDWordField (Arg0, 0x0C, IID3)
3351current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
3352current = buildOpCode(current, AML_ARG0_OP);
3353current = buildByteConst(current, 0x0C);
3354current = buildNameSeg(current, NAMESEG("IID3"));
3355
3356// Name (UID0, Buffer (0x10)
3357// {
3358// 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47,
3359// 0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53
3360// })
3361current = buildNamePath(current, NAMESEG("UID0"));
3362{
3363ACPI_SMALL_BUFFER * buff = current;
3364current = buildSmallBuffer(current);
3365
3366// count of buffer elements
3367current = buildByteConst(current, 0x10);
3368
3369current = buildOpCode(current, 0x16);
3370current = buildOpCode(current, 0xa6);
3371current = buildOpCode(current, 0x77);
3372current = buildOpCode(current, 0x40);
3373current = buildOpCode(current, 0x0c);
3374current = buildOpCode(current, 0x29);
3375current = buildOpCode(current, 0xbe);
3376current = buildOpCode(current, 0x47);
3377current = buildOpCode(current, 0x9e);
3378current = buildOpCode(current, 0xbd);
3379current = buildOpCode(current, 0xd8);
3380current = buildOpCode(current, 0x70);
3381current = buildOpCode(current, 0x58);
3382current = buildOpCode(current, 0x71);
3383current = buildOpCode(current, 0x39);
3384current = buildOpCode(current, 0x53);
3385
3386{
3387U32 length = (U8 *)current - (U8 *)buff;
3388buff->packageLength = (U8)length - 1;
3389}
3390}
3391
3392// CreateDWordField (UID0, 0x00, EID0)
3393current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
3394current = buildOpCode(current, AML_ARG0_OP);
3395current = buildByteConst(current, 0x00);
3396current = buildNameSeg(current, NAMESEG("EID0"));
3397
3398// CreateDWordField (UID0, 0x04, EID1)
3399current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
3400current = buildOpCode(current, AML_ARG0_OP);
3401current = buildByteConst(current, 0x04);
3402current = buildNameSeg(current, NAMESEG("EID1"));
3403
3404// CreateDWordField (UID0, 0x08, EID2)
3405current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
3406current = buildOpCode(current, AML_ARG0_OP);
3407current = buildByteConst(current, 0x08);
3408current = buildNameSeg(current, NAMESEG("EID2"));
3409
3410// CreateDWordField (UID0, 0x0C, EID3)
3411current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
3412current = buildOpCode(current, AML_ARG0_OP);
3413current = buildByteConst(current, 0x0C);
3414current = buildNameSeg(current, NAMESEG("EID3"));
3415
3416// If (LNot (LAnd (LAnd (LEqual (IID0, EID0), LEqual (IID1, EID1)),
3417// LAnd (LEqual (IID2, EID2), LEqual (IID3, EID3)))))
3418// {
3419// Store (0x06, Index (STS0, 0x00))
3420// Return (Arg3)
3421// }
3422{
3423current = buildOpCode(current, AML_IF_OP);
3424{
3425ACPI_PACKAGE_LENGTH * packageLength = current;
3426current = buildPackageLength(current, 0);
3427
3428current = buildOpCode(current, AML_LNOT_OP);
3429current = buildOpCode(current, AML_LAND_OP);
3430current = buildOpCode(current, AML_LAND_OP);
3431current = buildOpCode(current, AML_LEQUAL_OP);
3432current = buildNameSeg(current, NAMESEG("IID0"));
3433current = buildNameSeg(current, NAMESEG("EID0"));
3434
3435current = buildOpCode(current, AML_LEQUAL_OP);
3436current = buildNameSeg(current, NAMESEG("IID1"));
3437current = buildNameSeg(current, NAMESEG("EID1"));
3438
3439current = buildOpCode(current, AML_LAND_OP);
3440current = buildOpCode(current, AML_LEQUAL_OP);
3441current = buildNameSeg(current, NAMESEG("IID2"));
3442current = buildNameSeg(current, NAMESEG("EID2"));
3443
3444current = buildOpCode(current, AML_LEQUAL_OP);
3445current = buildNameSeg(current, NAMESEG("IID3"));
3446current = buildNameSeg(current, NAMESEG("EID3"));
3447
3448// Store (0x06, Index (STS0, 0x00))
3449current = buildOpCode(current, AML_STORE_OP);
3450current = buildByteConst(current, 0x06);
3451current = buildOpCode(current, AML_INDEX_OP);
3452current = buildNameSeg(current, NAMESEG("STS0"));
3453current = buildByteConst(current, 0x00);
3454current = buildOpCode(current, AML_ZERO_OP);
3455
3456// Return (Arg3)
3457current = buildReturnOpcode(current, AML_ARG3_OP);
3458
3459setPackageLength(packageLength,
3460 (U8 *)current - (U8 *)packageLength);
3461}
3462}
3463
3464// If (LNotEqual (Arg1, 0x01))
3465// {
3466// Store (0x0A, Index (STS0, 0x00))
3467// Return (Arg3)
3468// }
3469{
3470current = buildOpCode(current, AML_IF_OP);
3471{
3472ACPI_PACKAGE_LENGTH * packageLength = current;
3473current = buildPackageLength(current, 0);
3474
3475// If ("LNotEqual (Arg1, 0x01)")
3476current = buildOpCode(current, AML_LNOT_OP);
3477current = buildOpCode(current, AML_LEQUAL_OP);
3478current = buildOpCode(current, AML_ARG1_OP);
3479current = buildByteConst(current, 0x01);
3480
3481// Store (0x0A, Index (STS0, 0x00))
3482current = buildOpCode(current, AML_STORE_OP);
3483current = buildByteConst(current, 0x0A);
3484current = buildOpCode(current, AML_INDEX_OP);
3485current = buildNameSeg(current, NAMESEG("STS0"));
3486current = buildByteConst(current, 0x00);
3487current = buildOpCode(current, AML_ZERO_OP);
3488
3489// Return (Arg3)
3490current = buildReturnOpcode(current, AML_ARG3_OP);
3491
3492setPackageLength(packageLength,
3493 (U8 *)current - (U8 *)packageLength);
3494}
3495}
3496
3497// If (And (STS0, 0x01))
3498// {
3499// And (CAP0, 0x0BFF, CAP0)
3500// Return (Arg3)
3501// }
3502{
3503current = buildOpCode(current, AML_IF_OP);
3504{
3505ACPI_PACKAGE_LENGTH * packageLength = current;
3506current = buildPackageLength(current, 0);
3507
3508// If ("And (STS0, 0x01)")
3509current = buildOpCode(current, AML_AND_OP);
3510current = buildNameSeg(current, NAMESEG("STS0"));
3511current = buildByteConst(current, 0x01);
3512current = buildOpCode(current, AML_ZERO_OP);
3513
3514// And (CAP0, 0x0BFF, CAP0)
3515current = buildOpCode(current, AML_AND_OP);
3516current = buildNameSeg(current, NAMESEG("CAP0"));
3517current = buildWordConst(current, 0x0BFF);
3518current = buildNameSeg(current, NAMESEG("CAP0"));
3519
3520// Return (Arg3)
3521current = buildReturnOpcode(current, AML_ARG3_OP);
3522
3523setPackageLength(packageLength,
3524 (U8 *)current - (U8 *)packageLength);
3525}
3526}
3527
3528// And (CAP0, 0x0BFF, CAP0)
3529current = buildOpCode(current, AML_AND_OP);
3530current = buildNameSeg(current, NAMESEG("CAP0"));
3531current = buildWordConst(current, 0x0BFF);
3532current = buildNameSeg(current, NAMESEG("CAP0"));
3533
3534// Store (CAP0, TYPE)
3535current = buildOpCode(current, AML_STORE_OP);
3536current = buildNameSeg(current, NAMESEG("CAP0"));
3537current = buildNameSeg(current, NAMESEG("TYPE"));
3538
3539// Return (Arg3)
3540current = buildReturnOpcode(current, AML_ARG3_OP);
3541
3542// Set package length for the OSC object
3543setPackageLength(&osc->pkgLength, (U8 *)current - (U8 *)&osc->pkgLength);
3544
3545return(current);
3546}
3547
3548//-----------------------------------------------------------------------------
3549static void * buildPSS(void * current, PKG_PSTATES * pkg_pstates)
3550{
3551//
3552// IF (PSEN)
3553// {
3554// Return (Package of Pstate Packages)
3555// }
3556// Return(Zero)
3557//
3558ACPI_METHOD * pss = current;
3559current = buildMethod(current, NAMESEG("_PSS"), 0);
3560
3561{
3562// "IF" (PSEN) -- IF Opcode
3563current = buildOpCode(current, AML_IF_OP);
3564{
3565ACPI_PACKAGE_LENGTH * packageLength = current;
3566current = buildPackageLength(current, 0);
3567
3568// IF "(PSEN)" -- IF Predicate
3569current = buildNameSeg(current, NAMESEG("PSEN"));
3570
3571{
3572ACPI_RETURN_PACKAGE * returnPkg = current;
3573current = buildReturnPackage(current, (U8)pkg_pstates->num_pstates);
3574
3575// (3.3.3) For each P-state
3576{
3577U32 pstateIndex = 0;
3578for (pstateIndex=0; pstateIndex < pkg_pstates->num_pstates; pstateIndex++)
3579{
3580// (3.3.3.1) Create P-state package
3581ACPI_PSTATE_PACKAGE * pstate = current;
3582current = pstate + 1;
3583
3584setSmallPackage(&pstate->package, 6);
3585pstate->package.packageLength = (U8)(sizeof(ACPI_PSTATE_PACKAGE) - 1);
3586
3587setDwordConst(&pstate->CoreFreq, pkg_pstates->pstate[pstateIndex].frequency);// CoreFreq (in MHz).
3588setDwordConst(&pstate->Power, pkg_pstates->pstate[pstateIndex].power);// Power (in milliWatts).
3589setDwordConst(&pstate->TransLatency, pkg_pstates->pstate[pstateIndex].translatency);// Transition Latency (in microseconds).
3590setDwordConst(&pstate->BMLatency, pkg_pstates->pstate[pstateIndex].bmlatency);// Bus Master Latency (in microseconds).
3591setDwordConst(&pstate->Control, pkg_pstates->pstate[pstateIndex].control); // Control.
3592
3593setDwordConst(&pstate->Status, encode_pstate(pkg_pstates->pstate[pstateIndex].ratio));// Status.
3594} // for
3595} // for block
3596
3597// (3.3.4) Update package length in return package
3598setPackageLength(&returnPkg->package.pkgLength, (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3599}
3600
3601// "IF (PSEN) and its body" -- Set package length
3602setPackageLength(packageLength,
3603 (U8 *)current - (U8 *)packageLength);
3604}
3605// "Return (ZERO)"
3606current = buildReturnZero(current);
3607}
3608// Set package length for the _PSS object
3609setPackageLength(&pss->pkgLength, (U8 *)current - (U8 *)&pss->pkgLength);
3610
3611return(current);
3612}
3613
3614//-----------------------------------------------------------------------------
3615static void * buildPSD(void * current, U32 domain, U32 cpusInDomain, U32 pstate_coordination)
3616{
3617// If (And(TYPE, 0x0820))
3618// {
3619// Return (PSD Package)
3620// }
3621// Return(Zero)
3622
3623ACPI_METHOD * psdMethod = current;
3624current = buildMethod(current, NAMESEG("_PSD"), 0);
3625{
3626// "IF" (And(TYPE, 0x0820)) -- IF Opcode
3627current = buildOpCode(current, AML_IF_OP);
3628{
3629ACPI_PACKAGE_LENGTH * packageLength = current;
3630current = buildPackageLength(current, 0);
3631
3632// IF ("And"(TYPE, 0x820)) -- AND Opcode
3633current = buildOpCode(current, AML_AND_OP);
3634
3635// IF (And("TYPE", 0x820)) -- TYPE Term
3636current = buildNameSeg(current, NAMESEG("TYPE"));
3637
3638// IF (And(TYPE, "0x0820")) -- DWORD Value Term
3639current = buildDwordConst(current, 0x820);
3640
3641// IF ("And(TYPE, 0x200)") -- Target for And term (unused)
3642current = buildOpCode(current, AML_ZERO_OP);
3643
3644// Build return package containing PSD package
3645{
3646ACPI_RETURN_PACKAGE * returnPkg = current;
3647current = buildReturnPackage(current, 1);
3648
3649{
3650// Create PSD package
3651ACPI_PSD_PACKAGE * psd = current;
3652current = psd + 1;
3653
3654setSmallPackage(&psd->package, 5);
3655psd->package.packageLength = (U8)(sizeof(ACPI_PSD_PACKAGE) - 1);
3656
3657setByteConst(&psd->NumberOfEntries, 5);
3658setByteConst(&psd->Revision, 0);
3659setDwordConst(&psd->Domain, domain);
3660setDwordConst(&psd->CoordType, pstate_coordination);
3661setDwordConst(&psd->NumProcessors, cpusInDomain);
3662
3663} // PSD package
3664
3665setPackageLength(&returnPkg->package.pkgLength,
3666 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3667}
3668setPackageLength(packageLength, (U8 *)current - (U8 *)packageLength);
3669}
3670// "Return (ZERO)"
3671current = buildReturnZero(current);
3672}
3673// Update length in _PSD method
3674setPackageLength(&psdMethod->pkgLength, (U8 *)current - (U8 *)&psdMethod->pkgLength);
3675
3676return(current);
3677}
3678
3679//-----------------------------------------------------------------------------
3680static void * buildPPC(void * current/*, U8 valueToReturn*/)
3681{
3682ACPI_SMALL_METHOD * ppc = current;
3683current = buildSmallMethod(current, NAMESEG("_PPC"), 0);
3684
3685current = buildReturnZero(current);
3686
3687//current = buildReturnOpcode(current, valueToReturn);
3688
3689// Update package length in PPC object
3690ppc->packageLength = (U8) ( (U8 *)current - (U8 *)&ppc->packageLength );
3691
3692return(current);
3693}
3694
3695#if UNUSED
3696//-----------------------------------------------------------------------------
3697static void * buildPDL(void * current, U8 valueToReturn)
3698{
3699ACPI_SMALL_METHOD * pdl = current;
3700current = buildSmallMethod(current, NAMESEG("_PDL"), 0);
3701
3702current = buildReturnOpcode(current, valueToReturn);
3703
3704// Update package length in PDL object
3705pdl->packageLength = (U8) ( (U8 *)current - (U8 *)&pdl->packageLength );
3706
3707return(current);
3708}
3709#endif
3710
3711//-----------------------------------------------------------------------------
3712static void * buildPCT(void * current)
3713{
3714static const ACPI_GENERIC_ADDRESS pct_gas[] = {
3715{0x7f,0x40,0,0,0x199},
3716{0x7f,0x10,0,0,0x198},
3717};
3718
3719ACPI_SMALL_METHOD * pct = current;
3720current = buildSmallMethod(current, NAMESEG("_PCT"), 0);
3721
3722{
3723ACPI_RETURN_PACKAGE * returnPkg = current;
3724current = buildReturnPackage(current, 2);
3725
3726{
3727ACPI_SMALL_BUFFER * buff = current;
3728current = buildSmallBuffer(current);
3729
3730current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) );
3731current = buildGenericRegister(current, &pct_gas[0]);
3732current = buildEndTag(current);
3733
3734{
3735U32 length = (U8 *)current - (U8 *)buff;
3736buff->packageLength = (U8)length - 1;
3737}
3738}
3739{
3740ACPI_SMALL_BUFFER * buff = current;
3741current = buildSmallBuffer(current);
3742
3743current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) );
3744current = buildGenericRegister(current, &pct_gas[1]);
3745current = buildEndTag(current);
3746
3747{
3748U32 length = (U8 *)current - (U8 *)buff;
3749buff->packageLength = (U8)length - 1;
3750}
3751
3752}
3753
3754setPackageLength(&returnPkg->package.pkgLength,
3755 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3756}
3757
3758// Update package length in PCT object
3759pct->packageLength = (U8)((U8 *)current - (U8 *)&pct->packageLength);
3760
3761return(current);
3762}
3763
3764//-----------------------------------------------------------------------------
3765static void * buildCstate(void * current, ACPI_GENERIC_ADDRESS * gas, CSTATE * cstate)
3766{
3767//
3768// Build a C-state
3769//
3770ACPI_SMALL_PACKAGE * pkg1 = current;
3771current = buildSmallPackage(current, 4);
3772
3773{
3774{
3775ACPI_SMALL_BUFFER * buffer = current;
3776current = buildSmallBuffer(current);
3777
3778{
3779// Buffer length
3780current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) );
3781current = buildGenericRegister(current, gas);
3782current = buildEndTag(current);
3783}
3784{
3785U32 length = (U8 *)current - (U8 *)buffer;
3786buffer->packageLength = (U8)length - 1;
3787}
3788}
3789
3790{
3791current = buildByteConst(current, cstate->type);
3792current = buildWordConst(current, cstate->latency);
3793current = buildDwordConst(current, cstate->power);
3794}
3795}
3796pkg1->packageLength = (U8)((U8 *)current - (U8 *)&pkg1->packageLength);
3797
3798return(current);
3799}
3800
3801//-----------------------------------------------------------------------------
3802static void * buildReturnPackageCST(void * current, PKG_CSTATES * pkg_cstates)
3803{
3804// Create package returning C-states
3805ACPI_RETURN_PACKAGE * returnPkg = current;
3806current = buildReturnPackage(current, (U8)pkg_cstates->num_cstates + 1);
3807
3808{
3809// Include number of C-states
3810current = buildByteConst(current, (U8)pkg_cstates->num_cstates);
3811
3812{
3813U32 cstateIndex = 0;
3814for (cstateIndex=0; cstateIndex < pkg_cstates->num_cstates; cstateIndex++)
3815// Build C-state
3816current = buildCstate(current, &pkg_cstates->gas[cstateIndex], &pkg_cstates->cstate[cstateIndex]);
3817}
3818}
3819
3820// Update package length in return package
3821setPackageLength(&returnPkg->package.pkgLength,
3822 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3823
3824return(current);
3825}
3826
3827//-----------------------------------------------------------------------------
3828static void * buildCST(void * current, PKG_CSTATES * mwait_pkg_cstates, PKG_CSTATES * io_pkg_cstates)
3829{
3830//
3831// IF (CSEN)
3832// {
3833// IF (LAnd(MWOS, And(TYPE, 0x200)))
3834// {
3835// Return package containing MWAIT C-states
3836// }
3837// Return package containing IO C-states
3838// }
3839// Return(Zero)
3840//
3841ACPI_METHOD * cst = current;
3842current = buildMethod(current, NAMESEG("_CST"), 0);
3843{
3844// "IF" CSEN -- IF Opcode
3845current = buildOpCode(current, AML_IF_OP);
3846{
3847ACPI_PACKAGE_LENGTH * packageLength1 = current;
3848current = buildPackageLength(current, 0);
3849
3850// IF "(CSEN)" -- IF Predicate
3851current = buildNameSeg(current, NAMESEG("CSEN"));
3852
3853// "IF" (LAnd(MWOS, And(TYPE, 0x200))) -- IF Opcode
3854current = buildOpCode(current, AML_IF_OP);
3855{
3856ACPI_PACKAGE_LENGTH * packageLength2 = current;
3857current = buildPackageLength(current, 0);
3858
3859// IF ("LAnd"(MWOS, And(TYPE, 0x200))) -- LAND Opcode
3860current = buildOpCode(current, AML_LAND_OP);
3861
3862// IF (LAnd("MWOS", And(TYPE, 0x200))) -- MWOS Term
3863current = buildNameSeg(current, NAMESEG("MWOS"));
3864
3865// IF (LAnd(MWOS, "And"(TYPE, 0x200))) -- AND Opcode
3866current = buildOpCode(current, AML_AND_OP);
3867
3868// IF (LAnd(MWOS, And("TYPE", 0x200))) -- TYPE Term
3869current = buildNameSeg(current, NAMESEG("TYPE"));
3870
3871// IF (LAnd(MWOS, And(TYPE, "0x200"))) -- DWORD Value Term
3872current = buildWordConst(current, 0x200);
3873
3874// IF (LAnd(MWOS, "And(TYPE, 0x200)")) -- Target for And term (unused)
3875current = buildOpCode(current, AML_ZERO_OP);
3876
3877// Build return package for mwait c-states
3878current = buildReturnPackageCST(current, mwait_pkg_cstates);
3879
3880setPackageLength(packageLength2,
3881 (U8 *)current - (U8 *)packageLength2);
3882}
3883
3884// Build return package for io c-states
3885current = buildReturnPackageCST(current, io_pkg_cstates);
3886
3887setPackageLength(packageLength1,
3888 (U8 *)current - (U8 *)packageLength1);
3889}
3890// "Return (ZERO)"
3891current = buildReturnZero(current);
3892}
3893// Update length in _CST method
3894setPackageLength(&cst->pkgLength, (U8 *)current - (U8 *)&cst->pkgLength);
3895
3896return(current);
3897}
3898
3899#if BUILD_ACPI_CSD
3900//-----------------------------------------------------------------------------
3901static void * buildCSD(void * current, U32 domain, U32 cpusInDomain, PKG_CSTATES * pkg_cstates)
3902{
3903 // If (And(TYPE, 0x0040))
3904 // {
3905 // Return (CSD Package)
3906 // }
3907 // Return(Zero)
3908
3909 ACPI_METHOD * csdMethod = current;
3910 current = buildMethod(current, NAMESEG("_CSD"), 0);
3911 {
3912 // "IF" (And(TYPE, 0x0040)) -- IF Opcode
3913 current = buildOpCode(current, AML_IF_OP);
3914 {
3915 ACPI_PACKAGE_LENGTH * packageLength = current;
3916 current = buildPackageLength(current, 0);
3917
3918 // IF ("And"(TYPE, 0x0040)) -- AND Opcode
3919 current = buildOpCode(current, AML_AND_OP);
3920
3921 // IF (And("TYPE", 0x0040)) -- TYPE Term
3922 current = buildNameSeg(current, NAMESEG("TYPE"));
3923
3924 // IF (And(TYPE, "0x0040")) -- DWORD Value Term
3925 current = buildDwordConst(current, 0x0040);
3926
3927 // IF ("And(TYPE, 0x0040)") -- Target for And term (unused)
3928 current = buildOpCode(current, AML_ZERO_OP);
3929
3930 // Build return package containing CSD package(s)
3931 {
3932 ACPI_RETURN_PACKAGE * returnPkg = current;
3933 current = buildReturnPackage(current, (U8)pkg_cstates->num_cstates - 1);
3934
3935 {
3936 U32 cstateIndex;
3937 for (cstateIndex=1; cstateIndex < pkg_cstates->num_cstates; cstateIndex++)
3938 {
3939 // Build CSD for this C-state
3940
3941 // Create CSD package
3942 ACPI_CSD_PACKAGE * csd = current;
3943 current = csd + 1;
3944
3945 setSmallPackage(&csd->package, 6);
3946 csd->package.packageLength = (U8)(sizeof(ACPI_CSD_PACKAGE) - 1);
3947
3948 setByteConst(&csd->NumberOfEntries, 6);
3949 setByteConst(&csd->Revision, 0);
3950 setDwordConst(&csd->Domain, domain);
3951 setDwordConst(&csd->CoordType, ACPI_COORD_TYPE_HW_ALL);
3952 setDwordConst(&csd->NumProcessors, cpusInDomain);
3953 setDwordConst(&csd->Index, cstateIndex);
3954 }
3955 }
3956
3957 setPackageLength(&returnPkg->package.pkgLength,
3958 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3959 }
3960
3961 setPackageLength(packageLength, (U8 *)current - (U8 *)packageLength);
3962 }
3963 // "Return (ZERO)"
3964 current = buildReturnZero(current);
3965 }
3966 // Update length in _CSD method
3967 setPackageLength(&csdMethod->pkgLength, (U8 *)current - (U8 *)&csdMethod->pkgLength);
3968
3969 return(current);
3970}
3971#endif
3972
3973#if BUILD_ACPI_TSS
3974//-----------------------------------------------------------------------------
3975static void * buildTPC(void * current)
3976{
3977 ACPI_SMALL_METHOD * tpc = current;
3978 current = buildSmallMethod(current, NAMESEG("_TPC"), 0);
3979
3980 current = buildReturnZero(current);
3981
3982 // Update package length in PPC object
3983 tpc->packageLength = (U8) ( (U8 *)current - (U8 *)&tpc->packageLength );
3984
3985 return(current);
3986}
3987
3988//-----------------------------------------------------------------------------
3989static void * buildPTC(void * current)
3990{
3991 static const ACPI_GENERIC_ADDRESS ptc_gas[] = {
3992 {0x7f,0x00,0,0,0},
3993 {0x7f,0x00,0,0,0},
3994 };
3995
3996 ACPI_SMALL_METHOD * ptc = current;
3997 current = buildSmallMethod(current, NAMESEG("_PTC"), 0);
3998
3999 {
4000 ACPI_RETURN_PACKAGE * returnPkg = current;
4001 current = buildReturnPackage(current, 2);
4002
4003 {
4004 ACPI_SMALL_BUFFER * buff = current;
4005 current = buildSmallBuffer(current);
4006
4007 current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) );
4008 current = buildGenericRegister(current, &ptc_gas[0]);
4009 current = buildEndTag(current);
4010
4011 {
4012 U32 length = (U8 *)current - (U8 *)buff;
4013 buff->packageLength = (U8)length - 1;
4014 }
4015 }
4016 {
4017 ACPI_SMALL_BUFFER * buff = current;
4018 current = buildSmallBuffer(current);
4019
4020 current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) );
4021 current = buildGenericRegister(current, &ptc_gas[1]);
4022 current = buildEndTag(current);
4023
4024 {
4025 U32 length = (U8 *)current - (U8 *)buff;
4026 buff->packageLength = (U8)length - 1;
4027 }
4028 }
4029
4030 setPackageLength(&returnPkg->package.pkgLength,
4031 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
4032 }
4033
4034 // Update package length in PTC object
4035 ptc->packageLength = (U8)((U8 *)current - (U8 *)&ptc->packageLength);
4036
4037 return(current);
4038}
4039
4040//-----------------------------------------------------------------------------
4041static void * buildTSS(void * current, PKG_TSTATES * pkg_tstates)
4042{
4043 //
4044 // IF (LAnd(TSEN, And(TYPE,4)))
4045 // {
4046 // Return (Package of Tstate Packages)
4047 // }
4048 // Return(Zero)
4049 //
4050 ACPI_METHOD * tss = current;
4051 current = buildMethod(current, NAMESEG("_TSS"), 0);
4052
4053 {
4054 // "IF" (LAnd(TSEN, And(TYPE,4))) -- IF Opcode
4055 current = buildOpCode(current, AML_IF_OP);
4056 {
4057 ACPI_PACKAGE_LENGTH * packageLength = current;
4058 current = buildPackageLength(current, 0);
4059
4060 // IF ("LAnd"(TSEN, And(TYPE, 4))) -- LAND Opcode
4061 current = buildOpCode(current, AML_LAND_OP);
4062
4063 // IF (LAnd("TSEN", And(TYPE, 4))) -- TSEN Term
4064 current = buildNameSeg(current, NAMESEG("TSEN"));
4065
4066 // IF (LAnd(TSEN, "And"(TYPE, 4))) -- AND Opcode
4067 current = buildOpCode(current, AML_AND_OP);
4068
4069 // IF (LAnd(TSEN, And("TYPE", 4))) -- TYPE Term
4070 current = buildNameSeg(current, NAMESEG("TYPE"));
4071
4072 // IF (LAnd(TSEN, And(TYPE, "4"))) -- DWORD Value Term
4073 current = buildWordConst(current, 4);
4074
4075 // IF (LAnd(MWOS, "And(TYPE, 4)")) -- Target for And term (unused)
4076 current = buildOpCode(current, AML_ZERO_OP);
4077
4078 // Return (Package of Tstate Packages)
4079 {
4080 ACPI_RETURN_PACKAGE * returnPkg = current;
4081 current = buildReturnPackage(current, (U8)pkg_tstates->num_tstates);
4082
4083 // (3.3.3) For each T-state
4084 {
4085 U32 tstateIndex = 0;
4086 for (tstateIndex=0; tstateIndex < pkg_tstates->num_tstates; tstateIndex++)
4087 {
4088 // (3.3.3.1) Create T-state package
4089 ACPI_TSTATE_PACKAGE * tstate = current;
4090 current = tstate + 1;
4091
4092 setSmallPackage(&tstate->package, 5);
4093 tstate->package.packageLength = (U8)(sizeof(ACPI_TSTATE_PACKAGE) - 1);
4094
4095 setDwordConst(&tstate->FreqPercent, pkg_tstates->tstate[tstateIndex].freqpercent);
4096 setDwordConst(&tstate->Power, pkg_tstates->tstate[tstateIndex].power);
4097 setDwordConst(&tstate->TransLatency, pkg_tstates->tstate[tstateIndex].latency);
4098 setDwordConst(&tstate->Control, pkg_tstates->tstate[tstateIndex].control);
4099 setDwordConst(&tstate->Status, pkg_tstates->tstate[tstateIndex].status);
4100 } // for
4101 } // for block
4102
4103 // (3.3.4) Update package length in return package
4104 setPackageLength(&returnPkg->package.pkgLength, (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
4105 }
4106
4107 // "IF (LAnd(TSEN, And(TYPE,4))) and its body" -- Set package length
4108 setPackageLength(packageLength, (U8 *)current - (U8 *)packageLength);
4109 }
4110 // "Return (ZERO)"
4111 current = buildReturnZero(current);
4112 }
4113 // Set package length for the _TSS object
4114 setPackageLength(&tss->pkgLength, (U8 *)current - (U8 *)&tss->pkgLength);
4115
4116 return(current);
4117}
4118
4119//-----------------------------------------------------------------------------
4120static void * buildTSD(void * current, U32 domain, U32 cpusInDomain)
4121{
4122 // If (And(TYPE, 0x0080))
4123 // {
4124 // Return (Package containing TSD package)
4125 // }
4126 // Return(Zero)
4127
4128 ACPI_METHOD * tsdMethod = current;
4129 current = buildMethod(current, NAMESEG("_TSD"), 0);
4130 {
4131 // "IF" (And(TYPE, 0x0080)) -- IF Opcode
4132 current = buildOpCode(current, AML_IF_OP);
4133 {
4134 ACPI_PACKAGE_LENGTH * packageLength = current;
4135 current = buildPackageLength(current, 0);
4136
4137 // IF ("And"(TYPE, 0x0080)) -- AND Opcode
4138 current = buildOpCode(current, AML_AND_OP);
4139
4140 // IF (And("TYPE", 0x0080)) -- TYPE Term
4141 current = buildNameSeg(current, NAMESEG("TYPE"));
4142
4143 // IF (And(TYPE, "0x0080")) -- DWORD Value Term
4144 current = buildDwordConst(current, 0x0080);
4145
4146 // IF ("And(TYPE, 0x0080)") -- Target for And term (unused)
4147 current = buildOpCode(current, AML_ZERO_OP);
4148
4149 // Build package containing TSD package
4150 {
4151 ACPI_RETURN_PACKAGE * returnPkg = current;
4152 current = buildReturnPackage(current, 1);
4153
4154 {
4155 // Create PSD package
4156 ACPI_TSD_PACKAGE * tsd = current;
4157 current = tsd + 1;
4158
4159 setSmallPackage(&tsd->package, 5);
4160 tsd->package.packageLength = (U8)(sizeof(ACPI_TSD_PACKAGE) - 1);
4161
4162 setByteConst(&tsd->NumberOfEntries, 5);
4163 setByteConst(&tsd->Revision, 0);
4164 setDwordConst(&tsd->Domain, domain);
4165 setDwordConst(&tsd->CoordType, ACPI_COORD_TYPE_SW_ANY);
4166 setDwordConst(&tsd->NumProcessors, cpusInDomain);
4167
4168 } // TSD package
4169
4170 setPackageLength(&returnPkg->package.pkgLength,
4171 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
4172 }
4173
4174 setPackageLength(packageLength, (U8 *)current - (U8 *)packageLength);
4175 }
4176 // "Return (ZERO)"
4177 current = buildReturnZero(current);
4178 }
4179 // Update length in _TSD method
4180 setPackageLength(&tsdMethod->pkgLength, (U8 *)current - (U8 *)&tsdMethod->pkgLength);
4181
4182 return(current);
4183}
4184#endif
4185
4186//-----------------------------------------------------------------------------
4187static U32 BuildSsdt(MADT_INFO * madt_info, ACPI_TABLE_DSDT *dsdt, void * buffer, U32 bufferSize, bool enable_cstates, bool enable_pstates, bool enable_tstates)
4188{
4189// Build SSDT
4190{
4191// (1) Setup pointers to SSDT memory location
4192// (2) Create SSDT Definition Block
4193// (2.1) Save pointer to SSDT package length and checksum fields
4194// (2.2) Create variables in SSDT scope
4195// (3) For each logical processor CPUn
4196// (3.1) Create scope for CPUn
4197// (3.2) Create variables in CPU scope
4198// (3.3) Create _OSC and/or _PDC Methods
4199// (3.4) Create P-state related structures
4200// (3.4.1) Create _PSS Method
4201// (3.4.2) Create _PCT Object
4202// (3.4.3) Create _PPC Method
4203// (3.4.4) Create _PSD Object
4204// (3.5) Create C-state related structures
4205// (3.5.1) Create _CST Method
4206// (3.5.2) Create _CSD Method
4207// (3.6) Create T-state related structures (Optional)
4208// (3.6.1) Create _TPC Method
4209// (3.6.2) Create _PTC Method
4210// (3.6.3) Create _TSS Method
4211// (3.6.4) Create _TSD Method
4212// (3.7) Update length in CPUn Scope
4213// (4) Update length and checksum in SSDT Definition Block
4214DBG("Attempting to build SSDT\n");
4215
4216U32 pstates_enabled = 0;
4217U32 cstates_enabled = 0;
4218CPU_DETAILS cpu;
4219U8 ACPI_COORD_TYPE = ACPI_COORD_TYPE_SW_ANY; // default
4220ACPI_TABLE_SSDT *SsdtPointer = (void*)0ul;
4221
4222// Desired state for providing alternate ACPI _CST structure using MWAIT
4223// extensions
4224// 1= Alternate _CST using MWAIT extension is enabled for OSPM use
4225// 0= Alternate _CST using MWAIT extension is disabled for OSPM use
4226bool enable_mwait = 1;
4227
4228// (1) Setup pointers to SSDT memory location
4229void * current = buffer;
4230void * end = (U8 *)buffer + bufferSize;
4231
4232// Confirm a valid SSDT buffer was provided
4233if (!buffer)
4234{
4235printf("Error: Invalid Buffer Address for SSDT\n");
4236return(0);
4237}
4238
4239// Confirm a valid SSDT buffer length was provided
4240if (!bufferSize)
4241{
4242printf("Error: Invalid Buffer Length for SSDT\n");
4243return(0);
4244}
4245
4246if (madt_info == (void*) 0ul)
4247{
4248return(0);
4249}
4250
4251if (dsdt == (void*) 0ul)
4252{
4253return(0);
4254}
4255
4256// Check that we have a valid cpu_map (if it's not already done, it will try to generate it)
4257if (generate_cpu_map_from_acpi(dsdt) != 0)
4258{
4259return(0);
4260}
4261
4262collect_cpu_info(&cpu);
4263
4264if (enable_cstates && pmbase)
4265{
4266DBG("Building Cstate Info\n");
4267
4268cstates_enabled = BuildCstateInfo(&cpu, pmbase);
4269if (cstates_enabled)
4270{
4271getBoolForKey(KEnableMwait, &enable_mwait, &bootInfo->bootConfig);
4272}
4273}
4274
4275if (enable_pstates)
4276{
4277DBG("Building Pstate Info\n");
4278
4279pstates_enabled = BuildPstateInfo(&cpu);
4280if (pstates_enabled)
4281{
4282const char *str = getStringForKey(KAcpiCoordType, &bootInfo->bootConfig);
4283U8 tmp = (U8)strtoul(str, NULL,16);
4284if ((tmp == ACPI_COORD_TYPE_SW_ALL) || (tmp == ACPI_COORD_TYPE_SW_ANY) || (tmp == ACPI_COORD_TYPE_HW_ALL) )
4285{
4286ACPI_COORD_TYPE = tmp;
4287}
4288}
4289}
4290#if BUILD_ACPI_TSS
4291 U32 tstates_enabled = 0;
4292 if (enable_tstates)
4293{
4294DBG("Building Pstate Info\n");
4295
4296tstates_enabled = BuildTstateInfo(&cpu);
4297}
4298#endif
4299
4300SsdtPointer = (ACPI_TABLE_SSDT *)buffer;
4301
4302// (2) Create SSDT Definition Block
4303// (2.1) Save pointer to SSDT package length and checksum fields
4304current = buildTableHeader(current, NAMESEG("SSDT"), NAMESEG64("PPM RCM "));
4305
4306// Check to confirm no SSDT buffer overflow
4307if ( (U8 *)current > (U8 *)end )
4308{
4309printf("Error: SSDT Buffer Length exceeded available space \n");
4310return(0);
4311}
4312
4313// (3) For each logical processor CPUn
4314// We will use the dsdt datas in place of madt,for the cpu(s) detection.
4315// 'Cause most users use the dsdt table to change the numbers of cpu(s) that the OS and the bootloader should use,
4316// Note also that due to chameleon limit we use the same package per each cpu(s) for all objects and methods
4317// (package detection for each cpu(s) is still in progress)
4318{
4319U32 lapic_index;
4320for (lapic_index=0; lapic_index < cpu_map_count; lapic_index++)
4321{
4322// (3.1) Create scope for CPUn
4323ACPI_SCOPE * scope = current;
4324
4325{
4326DBG("Building CPU Scope\n");
4327U32 cpu_namespace = (cpuNamespace == CPU_NAMESPACE_SB) ? NAMESEG("_SB_") : NAMESEG("_PR_");
4328PROCESSOR_NUMBER_TO_NAMESEG * namepath = &cpu_map[lapic_index];
4329current = buildCpuScope (current, cpu_namespace, namepath );
4330}
4331
4332// Check to confirm no SSDT buffer overflow
4333if ( (U8 *)current > (U8 *)end )
4334{
4335printf("Error: SSDT Buffer Length exceeded available space \n");
4336return(0);
4337}
4338
4339// (3.2) Create variables in CPU scope
4340DBG("Creating variables in CPU scope\n");// Build Type variable used to store PDC capabilities
4341current = buildNamedDword(current, NAMESEG("TYPE"), 0);
4342
4343// Build PSEN variable used to store state of P-State Enable setup option
4344current = buildNamedDword(current, NAMESEG("PSEN"), pstates_enabled);
4345
4346// Build CSEN variable used to store state of C-State Enable setup option
4347current = buildNamedDword(current, NAMESEG("CSEN"), cstates_enabled);
4348
4349// Build MWOS variable used to store state of MWAIT OS setup option
4350current = buildNamedDword(current, NAMESEG("MWOS"), (U32)(enable_mwait&&cpu.mwait_supported));
4351
4352// (3.3) Create _OSC and/or _PDC Methods
4353{
4354// Build _PDC method
4355DBG("Building PDC method\n");
4356current = buildPDC(current);
4357
4358// Check to confirm no SSDT buffer overflow
4359if ( (U8 *)current > (U8 *)end )
4360{
4361printf("Error: SSDT Buffer Length exceeded available space \n");
4362return(0);
4363}
4364
4365// Build _OSC method
4366DBG("Building _OSC method\n");
4367current = buildOSC(current);
4368
4369// Check to confirm no SSDT buffer overflow
4370if ( (U8 *)current > (U8 *)end )
4371{
4372printf("Error: SSDT Buffer Length exceeded available space \n");
4373return(0);
4374}
4375}
4376
4377// (3.4) Create P-state related structures
4378if (pstates_enabled == 1)
4379{
4380// (3.4.1) Create _PSS Method
4381{
4382DBG("Building _PSS method\n");
4383PKG_PSTATES * pkg_pstates = &cpu.pkg_pstates;
4384current = buildPSS(current, pkg_pstates);
4385}
4386
4387// Check to confirm no SSDT buffer overflow
4388if ( (U8 *)(current) > (U8 *)end )
4389{
4390printf("Error: SSDT Buffer Length exceeded available space \n");
4391return(0);
4392}
4393
4394// (3.4.2) Create _PCT Object
4395DBG("Building _PCT Object\n");
4396current = buildPCT(current);
4397
4398// Check to confirm no SSDT buffer overflow
4399if ( (U8 *)(current) > (U8 *)end )
4400{
4401printf("Error: SSDT Buffer Length exceeded available space \n");
4402return(0);
4403}
4404
4405// (3.4.3) Create _PPC Method
4406DBG("Building _PPC Method\n");
4407current = buildPPC(current);
4408
4409// Check to confirm no SSDT buffer overflow
4410if ( (U8 *)(current) > (U8 *)end )
4411{
4412printf("Error: SSDT Buffer Length exceeded available space \n");
4413return(0);
4414}
4415
4416// (3.4.4) Create PSD with hardware coordination
4417{
4418DBG("Building _PSD Method\n");
4419U32 domain = madt_info->lapic[lapic_index].pkg_index;
4420
4421 // In this (bad?) implementation we use the nb of cpu found in the dsdt
4422U32 cpusInDomain = cpu_map_count;
4423current = buildPSD(current, domain, cpusInDomain, ACPI_COORD_TYPE);
4424}
4425
4426// Check to confirm no SSDT buffer overflow
4427if ( (U8 *)(current) > (U8 *)end )
4428{
4429printf("Error: SSDT Buffer Length exceeded available space \n");
4430return(0);
4431}
4432}
4433
4434// (3.5) Create C-state related structures
4435if (cstates_enabled == 1)
4436{
4437{
4438PKG_CSTATES * mwait_pkg_cstates = &cpu.pkg_mwait_cstates;
4439PKG_CSTATES * io_pkg_cstates = &cpu.pkg_io_cstates;
4440
4441// Build CST
4442DBG("Building _CST Method\n");
4443current = buildCST(current, mwait_pkg_cstates, io_pkg_cstates);
4444}
4445
4446#if BUILD_ACPI_CSD
4447 {
4448 // Use core_apic_id as domain
4449 U32 domain = lapic->core_apic_id;
4450
4451 // In this (bad?) implementation we use the nb of cpu found in the dsdt
4452 U32 cpusInDomain = cpu_map_count;
4453
4454 // Create CSD
4455 current = buildCSD(current, domain, cpusInDomain, io_pkg_cstates);
4456 }
4457#endif
4458
4459// Check to confirm no SSDT buffer overflow
4460if ( (U8 *)(current) > (U8 *)end )
4461{
4462printf("Error: SSDT Buffer Length exceeded available space \n");
4463return(0);
4464}
4465}
4466#if BUILD_ACPI_TSS
4467 // (3.6) Create T-state related structures
4468 if (tstates_enabled == 1)
4469 {
4470 // (3.6.1) Create _TPC Method
4471 current = buildTPC(current);
4472
4473 // (3.6.2) Create _PTC Method
4474 current = buildPTC(current);
4475
4476 // (3.6.3) Create _TSS Method
4477 {
4478 PKG_TSTATES * pkg_tstates = &cpu.pkg_tstates;
4479 current = buildTSS(current, pkg_tstates);
4480 }
4481
4482 // (3.6.4) Create _TSD Method
4483 {
4484 LAPIC_INFO * lapic = &madt_info.lapic[lapic_index];
4485
4486 // Use core_apic_id as domain
4487 U32 domain = lapic->core_apic_id;
4488
4489 // In this (bad?) implementation we use the nb of cpu found in the dsdt
4490 U32 cpusInDomain = cpu_map_count;
4491
4492 current = buildTSD(current, domain, cpusInDomain);
4493 }
4494 }
4495#endif
4496// (3.7) Update length in CPUn Scope
4497setPackageLength(&scope->pkgLength, (U8 *)current - (U8 *)&scope->pkgLength);
4498
4499} // End for
4500
4501// (4) Update length and checksum in SSDT Definition Block
4502{
4503DBG("Updating length and checksum in SSDT Definition Block\n");
4504
4505SsdtPointer->Header.Length = (U8 *)current - (U8 *)SsdtPointer;
4506SetChecksum(&SsdtPointer->Header);
4507}
4508
4509// Check to confirm no SSDT buffer overflow
4510if ( (U8 *)current > (U8 *)end )
4511{
4512printf("Error: SSDT Buffer Length exceeded available space \n");
4513return(0);
4514}
4515
4516} // End build SSDT
4517
4518} // SSDT
4519
4520return(1);
4521}
4522#endif
4523
4524#if UNUSED
4525static ACPI_TABLE_FACS* generate_facs(bool updatefacs )
4526{
4527 ACPI_TABLE_FACS* facs_mod=(ACPI_TABLE_FACS *)AllocateKernelMemory(sizeof(ACPI_TABLE_FACS));
4528if (!facs_mod)
4529{
4530printf("Unable to allocate kernel memory for facs mod\n");
4531return (void*)0ul;
4532}
4533 bzero(facs_mod, sizeof(ACPI_TABLE_FACS));
4534
4535ACPI_TABLE_FACS * FacsPointer =(acpi_tables.FacsPointer64 != (void *)0ul) ?
4536(ACPI_TABLE_FACS *)acpi_tables.FacsPointer64 : (ACPI_TABLE_FACS *)acpi_tables.FacsPointer;
4537
4538 memcpy(facs_mod, FacsPointer , FacsPointer->Length);
4539 facs_mod->Length = sizeof(ACPI_TABLE_FACS);
4540
4541if (FacsPointer->Length < sizeof(ACPI_TABLE_FACS))
4542{
4543facs_mod->FirmwareWakingVector = 0;
4544facs_mod->GlobalLock = 0;
4545facs_mod->Flags = 0;
4546}
4547
4548 if (updatefacs && FacsPointer->Version < 2)
4549{
4550if (FacsPointer->Version > 0)
4551{
4552facs_mod->XFirmwareWakingVector = FacsPointer->XFirmwareWakingVector;
4553}
4554else
4555{
4556facs_mod->XFirmwareWakingVector = (U64)facs_mod->FirmwareWakingVector;
4557}
4558
4559facs_mod->Version = 2; /* ACPI 1.0: 0, ACPI 2.0/3.0: 1, ACPI 4.0: 2 */
4560
4561}
4562
4563 return facs_mod;
4564}
4565#endif
4566
4567static ACPI_GENERIC_ADDRESS FillGASStruct(U32 Address, U8 Length)
4568{
4569ACPI_GENERIC_ADDRESS TmpGAS;
4570
4571TmpGAS.SpaceId = 1; /* I/O Address */
4572
4573if (Address == 0)
4574{
4575TmpGAS.BitWidth = 0;
4576}
4577else
4578{
4579TmpGAS.BitWidth = Length * 8;
4580}
4581
4582TmpGAS.BitOffset = 0;
4583TmpGAS.AccessWidth = 0; /* Not set for Legacy reasons... */
4584TmpGAS.Address = (U64)Address;
4585
4586return (TmpGAS);
4587}
4588
4589static ACPI_TABLE_FADT *
4590patch_fadt(ACPI_TABLE_FADT *fadt, ACPI_TABLE_DSDT *new_dsdt, bool UpdateFADT)
4591{
4592ACPI_TABLE_FADT *fadt_mod = (void*)0;
4593bool fadt_rev2_needed = false;
4594bool fix_restart = false;
4595const char * value;
4596
4597// Restart Fix
4598if (Platform->CPU.Vendor == 0x756E6547) /* Intel */
4599{
4600fix_restart = true;
4601getBoolForKey(kRestartFix, &fix_restart, &bootInfo->bootConfig);
4602
4603} else {
4604verbose ("Not an Intel platform: Restart Fix disabled !!!\n");
4605}
4606
4607if (fix_restart)
4608fadt_rev2_needed = true;
4609
4610// Allocate new fadt table
4611if (UpdateFADT)
4612{
4613 if (fadt->Header.Length < 0xF4)
4614 {
4615 fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(0xF4);
4616 if (!fadt_mod)
4617 {
4618 printf("Unable to allocate kernel memory for fadt mod\n");
4619 return (void*)0ul;
4620 }
4621 bzero(fadt_mod, 0xF4);
4622 memcpy(fadt_mod, fadt, fadt->Header.Length);
4623 fadt_mod->Header.Length = 0xF4;
4624
4625}
4626else
4627{
4628fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(fadt->Header.Length);
4629if (!fadt_mod)
4630{
4631printf("Unable to allocate kernel memory for fadt mod\n");
4632return (void*)0ul;
4633}
4634memcpy(fadt_mod, fadt, fadt->Header.Length);
4635}
4636
4637
4638//fadt_mod->Header.Revision = 0x04; // FADT rev 4
4639fadt_mod->ResetRegister = FillGASStruct(0, 0);
4640fadt_mod->ResetValue = 0;
4641fadt_mod->Reserved4[0] = 0;
4642fadt_mod->Reserved4[1] = 0;
4643fadt_mod->Reserved4[2] = 0;
4644
4645 fadt_mod->XPm1aEventBlock = FillGASStruct(fadt_mod->Pm1aEventBlock, fadt_mod->Pm1EventLength);
4646fadt_mod->XPm1bEventBlock = FillGASStruct(fadt_mod->Pm1bEventBlock, fadt_mod->Pm1EventLength);
4647fadt_mod->XPm1aControlBlock = FillGASStruct(fadt_mod->Pm1aControlBlock, fadt_mod->Pm1ControlLength);
4648fadt_mod->XPm1bControlBlock = FillGASStruct(fadt_mod->Pm1bControlBlock, fadt_mod->Pm1ControlLength);
4649fadt_mod->XPm2ControlBlock = FillGASStruct(fadt_mod->Pm2ControlBlock, fadt_mod->Pm2ControlLength);
4650fadt_mod->XPmTimerBlock = FillGASStruct(fadt_mod->PmTimerBlock, fadt_mod->PmTimerLength);
4651fadt_mod->XGpe0Block = FillGASStruct(fadt_mod->Gpe0Block, fadt_mod->Gpe0BlockLength);
4652fadt_mod->XGpe1Block = FillGASStruct(fadt_mod->Gpe1Block, fadt_mod->Gpe1BlockLength);
4653 if (fadt->Header.Revision < 4)
4654{
4655fadt_mod->Header.Revision = 0x04; // FADT rev 4
4656verbose("Converted ACPI V%d FADT to ACPI V4 FADT\n", fadt->Header.Revision);
4657
4658}
4659}
4660else
4661{
4662
4663if (fadt_rev2_needed)
4664{
4665if (fadt->Header.Length < 0x84 )
4666{
4667fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(0x84);
4668if (!fadt_mod)
4669{
4670printf("Unable to allocate kernel memory for fadt mod\n");
4671return (void*)0ul;
4672}
4673bzero(fadt_mod, 0x84);
4674memcpy(fadt_mod, fadt, fadt->Header.Length);
4675fadt_mod->Header.Length = 0x84;
4676}
4677else
4678{
4679fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(fadt->Header.Length);
4680if (!fadt_mod)
4681{
4682printf("Unable to allocate kernel memory for fadt mod\n");
4683return (void*)0ul;
4684}
4685memcpy(fadt_mod, fadt, fadt->Header.Length);
4686}
4687
4688if (fadt->Header.Revision < 2)
4689{
4690fadt_mod->Header.Revision = 0x02; // FADT rev 2 (ACPI 1.0B MS extensions)
4691verbose("Converted ACPI V%d FADT to ACPI V2 FADT\n", fadt->Header.Revision );
4692}
4693}
4694else
4695{
4696if (fadt->Header.Length < 0x74 )
4697{
4698fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(0x74);
4699if (!fadt_mod)
4700{
4701printf("Unable to allocate kernel memory for fadt mod\n");
4702return (void*)0ul;
4703}
4704bzero(fadt_mod, 0x74);
4705memcpy(fadt_mod, fadt, fadt->Header.Length);
4706fadt_mod->Header.Length = 0x74;
4707fadt_mod->Header.Revision = 0x01;
4708verbose("Warning: ACPI FADT length was < 0x74 which is the minimum for the ACPI FADT V1 specification, \n", fadt->Header.Revision );
4709verbose(" trying to convert it to Version 1. \n");
4710
4711}
4712else
4713{
4714fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(fadt->Header.Length);
4715if (!fadt_mod)
4716{
4717printf("Unable to allocate kernel memory for fadt mod\n");
4718return (void*)0ul;
4719}
4720memcpy(fadt_mod, fadt, fadt->Header.Length);
4721}
4722}
4723}
4724bool intelfadtspec = true;
4725U8 Type = PMProfileError;
4726// Determine system type / PM_Model
4727
4728// Fix System-type if needed (should never happen)
4729if (Platform->Type > MaxSupportedPMProfile)
4730{
4731if(fadt_mod->PreferredProfile <= MaxSupportedPMProfile)
4732Platform->Type = fadt_mod->PreferredProfile; // get the fadt if correct
4733else
4734Platform->Type = 1;/* Set a fixed value (Desktop) */
4735}
4736
4737// If needed, set System-type from PM_Profile (if valid) else set PM_Profile with a fixed the System-type
4738// Give prior to the FADT pm profile, allow to also control this value with a patched FADT table
4739if (fadt_mod->PreferredProfile != Platform->Type)
4740{
4741bool val = false;
4742getBoolForKey("PreferInternalProfileDetect", &val, &bootInfo->bootConfig); // if true Give prior to the profile resolved trought the CPU model
4743
4744val = Platform->CPU.isServer ;
4745
4746if (fadt_mod->PreferredProfile <= MaxSupportedPMProfile && !val)
4747{
4748Platform->Type = fadt_mod->PreferredProfile;
4749}
4750else
4751{
4752fadt_mod->PreferredProfile = Platform->Type;
4753}
4754
4755}
4756
4757// Set PM_Profile and System-type if user wanted this value to be forced
4758if ( (value=getStringForKey("SystemType", &bootInfo->bootConfig))!=NULL)
4759{
4760if ((Type = (unsigned char) strtoul(value, NULL, 10) ) <= MaxSupportedPMProfile)
4761{
4762if (fadt_mod->PreferredProfile != Type)
4763{
4764verbose("FADT: changing Preferred_PM_Profile from %d to %d\n", fadt->PreferredProfile, Type);
4765fadt_mod->PreferredProfile = Platform->Type = Type;
4766}
4767else
4768{
4769DBG("FADT: Preferred_PM_Profile was already set to %d, no need to be changed\n",Type);
4770}
4771
4772} else printf("Error: system-type must be 0..6. Defaulting to %d !\n", Platform->Type);
4773}
4774
4775getBoolForKey(KIntelFADT, &intelfadtspec, &bootInfo->bootConfig);
4776if ((pmbase == 0) && (cpu_map_error == 0) && (intelfadtspec == true))
4777{
4778ACPI_TABLE_DSDT *DsdtPointer ;
4779if (new_dsdt != (void*)0ul)
4780DsdtPointer = new_dsdt;
4781else if ((fadt_mod->Header.Revision >= 3) && (fadt_mod->XDsdt != 0ul))
4782DsdtPointer = (ACPI_TABLE_DSDT *)((U32)fadt_mod->XDsdt);
4783else
4784DsdtPointer = (ACPI_TABLE_DSDT *)fadt_mod->Dsdt;
4785
4786generate_cpu_map_from_acpi(DsdtPointer);
4787}
4788
4789// Patch DSDT Address if we have loaded a DSDT table
4790if(new_dsdt != (void*)0ul)
4791fadt_mod->Dsdt=(U32)new_dsdt;
4792
4793fadt_mod->Facs= fadt->Facs;
4794//fadt_mod->Facs=(U32)generate_facs(false);
4795
4796// Patch FADT to fix restart
4797if (fadt_mod->Header.Revision >= 2 && fix_restart)
4798{
4799 fadt_mod->Flags|= 0x400;
4800
4801int type = PCI_RESET_TYPE;
4802getIntForKey(KResetType, &type, &bootInfo->bootConfig);
4803if (type == KEYBOARD_RESET_TYPE)
4804{
4805//Azi: keyboard reset; http://forum.voodooprojects.org/index.php/topic,1056.msg9802.html#msg9802
4806fadt_mod->ResetRegister = FillGASStruct(0x64, 1);
4807fadt_mod->ResetValue = 0xfe;
4808}
4809else
4810{
4811fadt_mod->ResetRegister = FillGASStruct(0x0cf9, 1);
4812fadt_mod->ResetValue = 0x06;
4813}
4814verbose("FADT: Restart Fix applied (Type : %s) !\n", (type == 0) ? "PCI": "KEYBOARD");
4815}
4816
4817 if (fadt_mod->Header.Revision >= 3)
4818{
4819
4820
4821 if (UpdateFADT)
4822{
4823
4824//fadt_mod->XFacs= (U64)((U32)generate_facs(true));
4825 fadt_mod->XFacs=(U64)fadt->Facs;
4826
4827 }
4828else
4829{
4830fadt_mod->XFacs=(U64)fadt->XFacs;
4831}
4832
4833
4834 if(new_dsdt != (void*)0ul)
4835 fadt_mod->XDsdt=((U64)(U32)new_dsdt);
4836else if (UpdateFADT)
4837fadt_mod->XDsdt=(U64)fadt_mod->Dsdt;
4838
4839
4840 Platform->hardware_signature = ((ACPI_TABLE_FACS *)((U32)fadt_mod->XFacs))->HardwareSignature;
4841
4842 }
4843else
4844{
4845
4846 Platform->hardware_signature = ((ACPI_TABLE_FACS *)fadt_mod->Facs)->HardwareSignature;
4847
4848 }
4849
4850
4851DBG("setting hardware_signature to %x \n",Platform->hardware_signature);
4852
4853
4854
4855if (pmbase && (intelfadtspec == true))
4856ProcessFadt(fadt_mod, pmbase); // The checksum correction will be done by ProcessFadt
4857else
4858SetChecksum(&fadt_mod->Header); // Correct the checksum
4859
4860return fadt_mod;
4861}
4862
4863static U32 process_xsdt (ACPI_TABLE_RSDP *rsdp_mod , U32 *new_table_list)
4864{
4865TagPtr DropTables_p = XMLCastDict(XMLGetProperty(bootInfo->bootConfig.dictionary, (const char*)"ACPIDropTables"));
4866U32 new_table = 0ul;
4867U8 new_table_index = 0, table_added = 0;
4868ACPI_TABLE_XSDT *xsdt = (void*)0ul, *xsdt_mod = (void*)0ul;
4869ACPI_TABLE_RSDT *rsdt_conv= (void *)0ul;
4870
4871// FIXME: handle 64-bit address correctly
4872
4873xsdt=(ACPI_TABLE_XSDT *)acpi_tables.XsdtPointer;
4874
4875verbose("* Processing XSDT: \n");
4876
4877DBG(" XSDT @%x, Length=%d\n", (U32)xsdt,
4878xsdt->Header.Length);
4879
4880if (xsdt != (void *)0ul)
4881{
4882U32 dropoffset=0, index;
4883table_added = 0;
4884
4885xsdt_mod=(ACPI_TABLE_XSDT *)AllocateKernelMemory(xsdt->Header.Length);
4886if (!xsdt_mod)
4887{
4888printf("Unable to allocate kernel memory for xsdt mod\n");
4889return (0);
4890}
4891bzero(xsdt_mod, xsdt->Header.Length);
4892memcpy(&xsdt_mod->Header, &xsdt->Header, sizeof(ACPI_TABLE_HEADER));
4893
4894U32 num_tables=get_num_tables64(xsdt);
4895
4896for (index = 0; index < num_tables; index++)
4897{
4898
4899U64 ptr = xsdt->TableOffsetEntry[index];
4900
4901{
4902if (ptr > ULONG_MAX_32)
4903{
4904#if DEBUG_ACPI
4905printf("Warning xsdt->TableOffsetEntry[%d]: Beyond addressable memory in this CPU mode, ignored !!!\n",index);
4906#endif
4907continue;
4908}
4909
4910bool unsafe = false;
4911getBoolForKey(kUnsafeACPI, &unsafe, &bootInfo->bootConfig);
4912
4913if (!unsafe)
4914{
4915if (GetChecksum(((ACPI_TABLE_HEADER *) (unsigned long)ptr),
4916((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Length) != 0)
4917{
4918#if DEBUG_ACPI
4919printf("Warning xsdt->TableOffsetEntry[%d]: Invalide checksum, ignored !!!\n",index);
4920#endif
4921continue;
4922}
4923}
4924
4925}
4926
4927xsdt_mod->TableOffsetEntry[index-dropoffset]=ptr;
4928
4929char tableSig[4];
4930
4931strlcpy(tableSig, (char*)((U32)ptr), sizeof(tableSig)+1);
4932
4933DBG("** Processing %s,", tableSig );
4934
4935DBG(" @%x, Length=%d\n", (U32)ptr,
4936((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Length);
4937
4938{
4939bool oem = false;
4940char oemOption[OEMOPT_SIZE];
4941sprintf(oemOption, "oem%s",tableSig );
4942if (getBoolForKey(oemOption, &oem, &bootInfo->bootConfig) && oem) // This method don't work for DSDT and FACS
4943{
4944
4945DBG(" %s required\n", oemOption);
4946
4947if (get_new_table_in_list(new_table_list,(*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature), &new_table_index) != (void*)0ul)
4948new_table_list[new_table_index] = 0ul; // This way new table will not be added to the new rsdt list !!
4949
4950continue;
4951}
4952}
4953
4954{
4955TagPtr match_drop = XMLGetProperty(DropTables_p, (const char*)tableSig);
4956if ( match_drop )
4957{
4958char *tmp = XMLCastString(match_drop);
4959if (strcmp(tmp,"No") != 0)
4960{
4961dropoffset++;
4962DBG(" %s table dropped\n",tableSig);
4963continue;
4964}
4965}
4966}
4967
4968{
4969if ((new_table = (U32)get_new_table_in_list(new_table_list,(*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature), &new_table_index)) != 0ul)
4970{
4971DBG(" Found replacement for table %s\n",tableSig);
4972xsdt_mod->TableOffsetEntry[index-dropoffset]=(U64)new_table;
4973new_table_list[new_table_index] = 0ul; // table replaced !!
4974continue;
4975}
4976}
4977
4978}
4979
4980
4981{
4982U8 i;
4983for (i = 0; i< (MAX_ACPI_TABLE + RESERVED_AERA); i++)
4984{
4985if (new_table_list[i] != 0ul)
4986{
4987#if DEBUG_ACPI
4988ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;
4989printf("Adding table : ");
4990print_nameseg(*(U32 *) (table_array[i]->Signature));
4991printf("\n");
4992#endif
4993xsdt_mod->TableOffsetEntry[index-dropoffset]=(U64)new_table_list[i];
4994table_added++;
4995index++;
4996}
4997}
4998}
4999
5000// Correct the checksum of XSDT
5001xsdt_mod->Header.Length-=8*dropoffset;
5002xsdt_mod->Header.Length+=8*table_added;
5003
5004SetChecksum(&xsdt_mod->Header);
5005
5006update_rsdp_with_xsdt(rsdp_mod, xsdt_mod);
5007
5008verbose("* Creating new RSDT from XSDT table\n");
5009
5010rsdt_conv = (ACPI_TABLE_RSDT *)gen_alloc_rsdt_from_xsdt(xsdt_mod);
5011
5012if (rsdt_conv != (void*)0ul)
5013{
5014#if DEBUG_ACPI
5015DBG("Attempting to update RSDP with RSDT \n");
5016{
5017U32 ret = update_rsdp_with_rsdt(rsdp_mod, rsdt_conv);
5018if (ret)
5019DBG("RSDP update with RSDT successfully !!! \n");
5020}
5021#else
5022update_rsdp_with_rsdt(rsdp_mod, rsdt_conv);
5023#endif
5024}
5025
5026}
5027else
5028{
5029DBG("About to drop XSDT\n");
5030
5031/*FIXME: Now we just hope that if MacOS doesn't find XSDT it reverts to RSDT.
5032 * A Better strategy would be to generate
5033 */
5034
5035rsdp_mod->XsdtPhysicalAddress=0xffffffffffffffffLL;
5036verbose("XSDT not found or XSDT incorrect\n");
5037}
5038return (1);
5039
5040}
5041
5042static U32 process_rsdt(ACPI_TABLE_RSDP *rsdp_mod , bool gen_xsdt, U32 *new_table_list)
5043{
5044TagPtr DropTables_p = XMLCastDict(XMLGetProperty(bootInfo->bootConfig.dictionary, (const char*)"ACPIDropTables"));
5045U32 new_table = 0ul;
5046U8 new_table_index = 0, table_added = 0;
5047U32 dropoffset=0, index;
5048ACPI_TABLE_RSDT *rsdt = (void *)0ul, *rsdt_mod= (void *)0ul;
5049ACPI_TABLE_XSDT *xsdt_conv = (void *)0ul;
5050
5051rsdt=(ACPI_TABLE_RSDT *)acpi_tables.RsdtPointer;
5052
5053rsdt_mod=(ACPI_TABLE_RSDT *)AllocateKernelMemory(rsdt->Header.Length);
5054
5055if (!rsdt_mod)
5056{
5057printf("Unable to allocate kernel memory for rsdt mod\n");
5058return (0);
5059}
5060
5061bzero(rsdt_mod, rsdt->Header.Length);
5062memcpy (&rsdt_mod->Header, &rsdt->Header, sizeof(ACPI_TABLE_HEADER));
5063
5064U32 num_tables = get_num_tables(rsdt);
5065
5066verbose("* Processing RSDT: \n");
5067
5068DBG(" RSDT @%x, Length %d\n",rsdt, rsdt->Header.Length);
5069
5070ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) rsdt->TableOffsetEntry;
5071
5072// Compute number of table pointers included in RSDT
5073num_tables = get_num_tables(rsdt);
5074
5075for (index = 0; index < num_tables; index++)
5076{
5077
5078{
5079
5080bool unsafe = false;
5081getBoolForKey(kUnsafeACPI, &unsafe, &bootInfo->bootConfig);
5082
5083if (!unsafe)
5084{
5085if (GetChecksum(table_array[index], table_array[index]->Length) != 0)
5086{
5087#if DEBUG_ACPI
5088printf("Warning rsdt->TableOffsetEntry[%d]: Invalide checksum, ignored !!!\n",index);
5089#endif
5090continue;
5091}
5092}
5093
5094}
5095
5096rsdt_mod->TableOffsetEntry[index-dropoffset]=rsdt->TableOffsetEntry[index];
5097
5098char tableSig[4];
5099
5100strlcpy(tableSig, (char*)(rsdt->TableOffsetEntry[index]), sizeof(tableSig)+1);
5101
5102DBG("** Processing %s,", tableSig );
5103
5104DBG(" @%x, Length=%d\n", (U32)table_array[index],
5105table_array[index]->Length);
5106
5107{
5108bool oem = false;
5109char oemOption[OEMOPT_SIZE];
5110sprintf(oemOption, "oem%s",tableSig );
5111if (getBoolForKey(oemOption, &oem, &bootInfo->bootConfig) && oem) // This method don't work for DSDT and FACS
5112{
5113DBG(" %s required\n", oemOption);
5114
5115if (get_new_table_in_list(new_table_list,(*(U32 *) (table_array[index]->Signature)), &new_table_index) != (void*)0ul )
5116new_table_list[new_table_index] = 0ul; // This way new table will not be added to the new rsdt list !!
5117
5118continue;
5119}
5120}
5121
5122{
5123TagPtr match_drop = XMLGetProperty(DropTables_p, (const char*)tableSig);
5124if ( match_drop )
5125{
5126char *tmp = XMLCastString(match_drop);
5127if (strcmp(tmp,"No") != 0)
5128{
5129dropoffset++;
5130DBG(" %s table dropped\n",tableSig);
5131continue;
5132}
5133}
5134}
5135
5136{
5137if ((new_table = (U32)get_new_table_in_list(new_table_list,(*(U32 *) (table_array[index]->Signature)), &new_table_index)) != 0ul)
5138{
5139DBG(" Found replacement for table %s\n",tableSig);
5140
5141rsdt_mod->TableOffsetEntry[index-dropoffset]=new_table;
5142new_table_list[new_table_index] = 0ul; // table replaced !!
5143continue;
5144}
5145}
5146//}
5147}
5148DBG("\n");
5149
5150{
5151U8 i;
5152for (i = 0; i< (MAX_ACPI_TABLE + RESERVED_AERA); i++)
5153{
5154if (new_table_list[i] != 0ul)
5155{
5156#if DEBUG_ACPI
5157ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;
5158printf("Adding table : ");
5159print_nameseg(*(U32 *) (table_array[i]->Signature));
5160printf("\n");
5161#endif
5162rsdt_mod->TableOffsetEntry[index-dropoffset]=new_table_list[i];
5163table_added++;
5164index++;
5165}
5166}
5167}
5168
5169// Correct the checksum of RSDT
5170rsdt_mod->Header.Length-=4*dropoffset;
5171rsdt_mod->Header.Length+=4*table_added;
5172
5173DBG("RSDT: Original checksum %d\n", rsdt_mod->Header.Checksum);
5174
5175SetChecksum(&rsdt_mod->Header);
5176
5177DBG("New checksum %d at %x\n", rsdt_mod->Header.Checksum,rsdt_mod);
5178
5179update_rsdp_with_rsdt(rsdp_mod, rsdt_mod);
5180
5181if (gen_xsdt)
5182{
5183verbose("* Creating new XSDT from RSDT table\n");
5184xsdt_conv = (ACPI_TABLE_XSDT *)gen_alloc_xsdt_from_rsdt(rsdt_mod);
5185
5186if (xsdt_conv != (void *)0ul )
5187{
5188#if DEBUG_ACPI
5189DBG("Attempting to update RSDP with XSDT \n");
5190{
5191U32 ret = update_rsdp_with_xsdt(rsdp_mod, xsdt_conv);
5192if (ret)
5193DBG("RSDP update with XSDT successfully !!! \n");
5194}
5195#else
5196update_rsdp_with_xsdt(rsdp_mod, xsdt_conv);
5197#endif
5198
5199}
5200
5201}
5202return (1);
5203}
5204
5205EFI_STATUS setupAcpi(void)
5206{
5207U8 Revision = 0;
5208
5209 cpu_map_error = 0;
5210 cpu_map_count = 0;
5211 pmbase = 0;
5212
5213 EFI_STATUS Status = EFI_ABORTED;
5214
5215U32 new_table_list[MAX_ACPI_TABLE + RESERVED_AERA]; //max table + reserved aera
5216U8 new_table_index = 0;
5217
5218ACPI_TABLE_DSDT* DsdtPtr = (void *)0ul; // a Pointer to the dsdt table present in fadt_mod
5219
5220ACPI_TABLE_DSDT *new_dsdt = (void *)0ul;// a Pointer to the dsdt file
5221ACPI_TABLE_FADT *fadt_mod = (void *)0ul; // a Pointer to the patched FACP table
5222ACPI_TABLE_FADT *fadt_file = (void *)0ul; // a Pointer to the (non-patched) fadt file
5223ACPI_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
5224ACPI_TABLE_RSDP *rsdp_mod = (void *)0ul, *rsdp_conv= (void *)0ul;
5225
5226U32 rsdplength;
5227
5228bool update_acpi=false, gen_xsdt=false;
5229
5230bool gen_csta=false, gen_psta=false, speed_step=false;
5231#if !OLD_SSDT
5232bool gen_ssdt=false; // will force to generate ssdt even if gen_csta and gen_psta = false
5233 bool gen_tsta=false;
5234#endif
5235bool oem_dsdt=false, oem_fadt=false;
5236
5237// Find original rsdp
5238if (!FindAcpiTables(&acpi_tables))
5239{
5240printf("Error: AcpiCodec Failed to detect ACPI tables.\n");
5241getc();
5242return EFI_NOT_FOUND;
5243}
5244
5245{
5246U8 i;
5247
5248for (i=0; i<(MAX_ACPI_TABLE + RESERVED_AERA); i++)
5249{
5250new_table_list[i] = 0ul;
5251}
5252bool tmpval;
5253
5254oem_dsdt=getBoolForKey(kOEMDSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
5255oem_fadt=getBoolForKey(kOEMFADT, &tmpval, &bootInfo->bootConfig)&&tmpval;
5256
5257gen_csta=getBoolForKey(kGenerateCStates, &tmpval, &bootInfo->bootConfig)&&tmpval;
5258gen_psta=getBoolForKey(kGeneratePStates, &tmpval, &bootInfo->bootConfig)&&tmpval;
5259#if !OLD_SSDT
5260gen_ssdt=getBoolForKey(KForceSSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
5261#endif
5262update_acpi=getBoolForKey(kUpdateACPI, &tmpval, &bootInfo->bootConfig)&&tmpval;
5263
5264speed_step=getBoolForKey(kSpeedstep, &tmpval, &bootInfo->bootConfig)&&tmpval;
5265#if !OLD_SSDT
5266turbo_enabled=(U32)getBoolForKey(kCoreTurbo, &tmpval, &bootInfo->bootConfig)&&tmpval;
5267#endif
5268#if BUILD_ACPI_TSS
5269gen_tsta=(U32)getBoolForKey(kGenerateTStates, &tmpval, &bootInfo->bootConfig)&&tmpval;
5270#endif
5271}
5272
5273{
5274char* name;
5275long flags;
5276long time;
5277long ret = -1;
5278U8 i = 0;
5279char dirspec[512];
5280bool acpidir_found = false;
5281
5282ret = GetFileInfo("rd(0,0)/Extra/", "Acpi", &flags, &time);
5283 if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory))
5284{
5285 sprintf(dirspec, "rd(0,0)/Extra/Acpi/");
5286 acpidir_found = true;
5287
5288 }
5289else
5290{
5291
5292 ret = GetFileInfo("/Extra/", "Acpi", &flags, &time);
5293 if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory))
5294{
5295 sprintf(dirspec, "/Extra/Acpi/");
5296 acpidir_found = true;
5297
5298 }
5299else
5300{
5301 ret = GetFileInfo("bt(0,0)/Extra/", "Acpi", &flags, &time);
5302 if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory))
5303{
5304 sprintf(dirspec, "bt(0,0)/Extra/Acpi/");
5305 acpidir_found = true;
5306
5307 }
5308 }
5309 }
5310
5311if (acpidir_found == true)
5312{
5313struct dirstuff* moduleDir = opendir(dirspec);
5314while(readdir(moduleDir, (const char**)&name, &flags, &time) >= 0)
5315{
5316if((strcmp(&name[strlen(name) - sizeof("aml")], ".aml") == 0) && ((strlen(dirspec)+strlen(name)) < 512))
5317{
5318// Some simple verifications to save time in case of those tables simply named as follow:
5319if ((strncmp(name, "RSDT", 4) == 0) || (strncmp(name, "rsdt", 4) == 0) ||
5320(strncmp(name, "XSDT", 4) == 0) || (strncmp(name, "xsdt", 4) == 0) ||
5321(strncmp(name, "RSDP", 4) == 0) || (strncmp(name, "rsdp", 4) == 0))
5322{
5323continue;
5324}
5325
5326if ((strncmp(name, "FACS", 4) == 0) || (strncmp(name, "facs", 4) == 0)) // FACS is not supported
5327{
5328continue;
5329}
5330
5331DBG("* Attempting to load acpi table: %s\n", name);
5332if ( (new_table_list[i]=(U32)loadACPITable(dirspec,name)))
5333{
5334if (i < MAX_ACPI_TABLE)
5335{
5336i++;
5337}
5338else
5339{
5340break;
5341}
5342}
5343
5344}
5345#if DEBUG_ACPI
5346else
5347{
5348DBG("Ignoring %s\n", name);
5349}
5350#endif
5351
5352}
5353
5354if (i)
5355{
5356//sanitize the new tables list
5357sanitize_new_table_list(new_table_list);
5358
5359//move to kernel memory
5360move_table_list_to_kmem(new_table_list);
5361
5362DBG("New ACPI tables Loaded in memory\n");
5363}
5364}
5365
5366}
5367#if HARDCODED_DSDT
5368 do {
5369#include "dsdt_PRLSACPI.h"
5370
5371 U8 index = 0;
5372
5373 if ((get_new_table_in_list(new_table_list, NAMESEG("DSDT"), &new_table_index)) != (void*)0ul )
5374 {
5375 index = new_table_index;
5376 }
5377 else
5378 {
5379 U8 empty = get_0ul_index_in_list(new_table_list, false);
5380 if (empty != ACPI_TABLE_LIST_FULL_NON_RESERVED)
5381 {
5382 index = empty;
5383 }
5384 else
5385 {
5386 printf("Error: not enought reserved space in the new acpi list for the Harcoded DSDT table,\n ");
5387 printf(" please increase the RESERVED_AERA\n");
5388
5389 break;
5390 }
5391 }
5392
5393if (index)
5394{
5395
5396ACPI_TABLE_DSDT *tmp = (ACPI_TABLE_DSDT *)DsdtAmlCode;
5397ACPI_TABLE_DSDT *hardcoded_dsdt = (void *)0ul;
5398
5399hardcoded_dsdt = (ACPI_TABLE_DSDT *)AllocateKernelMemory(tmp->Header.Length);
5400memcpy(hardcoded_dsdt, tmp, tmp->Header.Length);
5401new_table_list[index] = (U32)hardcoded_dsdt; // add the patched table to the list
5402}
5403else
5404{
5405printf("Error: not enought reserved space in the new acpi list for the Harcoded DSDT table,\n ");
5406printf(" please increase the RESERVED_AERA\n");
5407
5408break;
5409}
5410 } while (0);
5411#endif
5412if (speed_step)
5413{
5414gen_psta= true;
5415gen_csta= true;
5416}
5417
5418
5419ACPI_TABLE_RSDP *rsdp=(ACPI_TABLE_RSDP *)acpi_tables.RsdPointer;
5420
5421if (rsdp == (void*)0ul || (GetChecksum(rsdp, (rsdp->Revision == 0) ? ACPI_RSDP_REV0_SIZE:sizeof(ACPI_TABLE_RSDP)) != 0) )
5422{
5423printf("Error : ACPI RSD PTR Revision %d checksum is incorrect or table not found \n",rsdp->Revision );
5424return EFI_UNSUPPORTED;
5425}
5426
5427if ((update_acpi) && (rsdp->Revision == 0))
5428{
5429
5430rsdp_conv = (ACPI_TABLE_RSDP *)gen_alloc_rsdp_v2_from_v1(rsdp);
5431if (rsdp_conv != (void *)0ul)
5432{
5433gen_xsdt = true;
5434rsdp = rsdp_conv;
5435verbose("Converted ACPI RSD PTR Revision 0 to Revision 2\n");
5436}
5437
5438}
5439
5440Revision = rsdp->Revision ;
5441rsdplength=(Revision == 2)?rsdp->Length:ACPI_RSDP_REV0_SIZE;
5442
5443DBG("RSDP Revision %d found @%x. Length=%d\n",Revision,rsdp,rsdplength);
5444
5445if (gen_xsdt)
5446{
5447rsdp_mod=rsdp_conv;
5448}
5449else
5450{
5451rsdp_mod=(ACPI_TABLE_RSDP *) AllocateKernelMemory(rsdplength);
5452
5453if (!rsdp_mod) return EFI_OUT_OF_RESOURCES;
5454
5455memcpy(rsdp_mod, rsdp, rsdplength);
5456}
5457
5458
5459if ((fadt_file = (ACPI_TABLE_FADT *)get_new_table_in_list(new_table_list, NAMESEG("FACP"), &new_table_index)) != (void *)0ul)
5460{
5461
5462if (oem_fadt == false)
5463FacpPointer = (ACPI_TABLE_FADT *)fadt_file;
5464
5465new_table_list[new_table_index] = 0ul; // This way, the non-patched table will not be added in our new rsdt/xsdt table list
5466
5467} else
5468FacpPointer = (acpi_tables.FacpPointer64 != (void *)0ul) ?
5469(ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer;
5470
5471#if DEBUG_ACPI
5472if ((FacpPointer != (void *)0ul) || (oem_fadt == false))
5473{
5474printf("FADT found @%x, Length %d\n",FacpPointer, FacpPointer->Header.Length);
5475printf("Attempting to patch FADT entry of %s\n",(acpi_tables.FacpPointer64 != (void *)0ul) ? ACPI_SIG_XSDT : ACPI_SIG_RSDT);
5476}
5477else if (oem_fadt == true)
5478{
5479ACPI_TABLE_FADT * FacpPtr = (acpi_tables.FacpPointer64 != (void *)0ul) ?
5480(ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer;
5481
5482printf("FADT found @%x ( Length %d ) in %s \n",FacpPtr, FacpPtr->Header.Length, (acpi_tables.FacpPointer64 != (void *)0ul) ? ACPI_SIG_XSDT : ACPI_SIG_RSDT);
5483}
5484#endif
5485
5486if ((new_dsdt = (ACPI_TABLE_DSDT *)get_new_table_in_list(new_table_list, NAMESEG("DSDT"), &new_table_index)) != (void*)0ul )
5487{
5488new_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
5489}
5490
5491if (oem_fadt == false)
5492{
5493
5494fadt_mod = patch_fadt(FacpPointer, (oem_dsdt == false) ? new_dsdt : (void*)0ul , (acpi_tables.FacpPointer64 != (void *)0ul ));
5495
5496if (fadt_mod != (void*)0ul)
5497{
5498DsdtPtr = ((fadt_mod->Header.Revision >= 3) && (fadt_mod->XDsdt != 0)) ? (ACPI_TABLE_DSDT*)((U32)fadt_mod->XDsdt):(ACPI_TABLE_DSDT*)fadt_mod->Dsdt;
5499
5500U8 empty = get_0ul_index_in_list(new_table_list,true);
5501if (empty != ACPI_TABLE_LIST_FULL)
5502{
5503new_table_list[empty] = (U32)fadt_mod; // add the patched table to the list
5504}
5505else
5506{
5507printf("Error: not enought reserved space in the new acpi list for the Patched FACP table,\n ");
5508printf(" please increase the RESERVED_AERA\n");
5509}
5510
5511}
5512else
5513{
5514printf("Error: Failed to patch the FADT Table, trying fallback to the FADT original pointer\n");
5515fadt_mod = (acpi_tables.FacpPointer64 != (void *)0ul) ?
5516(ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer;
5517
5518DsdtPtr = ((fadt_mod->Header.Revision >= 3) && (fadt_mod->XDsdt != 0)) ? (ACPI_TABLE_DSDT*)((U32)fadt_mod->XDsdt):(ACPI_TABLE_DSDT*)fadt_mod->Dsdt;
5519
5520U8 empty = get_0ul_index_in_list(new_table_list,true);
5521if (empty != ACPI_TABLE_LIST_FULL)
5522{
5523new_table_list[empty] = (U32)fadt_mod;
5524}
5525else
5526{
5527printf("Error: not enought reserved space in the new acpi list for the FACP table,\n ");
5528printf(" please increase the RESERVED_AERA\n");
5529}
5530}
5531
5532if (oem_dsdt == false)
5533{
5534if (generate_cpu_map_from_acpi(DsdtPtr) == 0)
5535{
5536U8 new_uid = (U8)getPciRootUID();
5537
5538/* WARNING: THIS METHOD WORK PERFECTLY BUT IT CAN RESULT TO AN INCORRECT CHECKSUM */
5539
5540if (ProcessDsdt(DsdtPtr, UIDPointer, new_uid))
5541{
5542printf("PCI0 _UID patched to %d in the DSDT table\n", new_uid);
5543}
5544
5545}
5546}
5547
5548
5549}
5550else
5551{
5552
5553// here we use the variable fadt_mod only for SSDT Generation
5554
5555fadt_mod = (acpi_tables.FacpPointer64 != (void *)0ul) ?
5556(ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer;
5557
5558DsdtPtr = ((fadt_mod->Header.Revision >= 3) && (fadt_mod->XDsdt != 0)) ? (ACPI_TABLE_DSDT*)((U32)fadt_mod->XDsdt)
5559:(ACPI_TABLE_DSDT*)fadt_mod->Dsdt;
5560}
5561#if OLD_SSDT
5562if (get_needed_symbols())
5563{
5564if (speed_step || gen_csta || gen_psta)
5565{
5566U8 empty = get_0ul_index_in_list(new_table_list, true);
5567
5568// Generate _CST SSDT
5569if ( speed_step || gen_csta)
5570{
5571if (empty != ACPI_TABLE_LIST_FULL)
5572{
5573if (new_table_list[empty] =(U32)generate_cst_ssdt(fadt_mod))
5574{
5575if (speed_step || gen_psta)
5576empty = get_0ul_index_in_list(new_table_list,true);
5577}
5578}
5579else
5580{
5581printf("Error: not enought reserved space in the new acpi list for the _CST SSDT table,\n ");
5582printf(" please increase the RESERVED_AERA\n");
5583}
5584}
5585
5586
5587// Generating _PSS SSDT
5588if (speed_step || gen_psta)
5589{
5590if (empty != ACPI_TABLE_LIST_FULL)
5591{
5592
5593new_table_list[empty] =(U32)generate_pss_ssdt(DsdtPtr);
5594
5595}
5596else
5597{
5598printf("Error: not enought reserved space in the new acpi list for the _PSS SSDT table,\n ");
5599printf(" please increase the RESERVED_AERA\n");
5600}
5601}
5602}
5603}
5604#else
5605 {
5606 MADT_INFO madt_info;
5607 bool strip_madt = true;
5608
5609 getBoolForKey(kSTRIPAPIC, &strip_madt, &bootInfo->bootConfig);
5610
5611 if ((strip_madt == false) || (!buildMADT(new_table_list, DsdtPtr, &madt_info )))
5612 {
5613
5614 ACPI_TABLE_MADT * madt_file = (void*)0ul;
5615 ACPI_TABLE_MADT * MadtPointer = (void*)0ul;
5616 bool oem_apic=false;
5617
5618 {
5619 bool tmpval;
5620 oem_apic=getBoolForKey(kOEMAPIC, &tmpval, &bootInfo->bootConfig)&&tmpval;
5621 }
5622
5623 if ((madt_file = (ACPI_TABLE_MADT *)get_new_table_in_list(new_table_list, NAMESEG("APIC"), &new_table_index)) != (void *)0ul)
5624 {
5625 if (oem_apic == false)
5626 {
5627 MadtPointer = (ACPI_TABLE_MADT *)madt_file;
5628 }
5629
5630 } else
5631 MadtPointer = (acpi_tables.MadtPointer64 != (void*)0ul) ? (ACPI_TABLE_MADT *)acpi_tables.MadtPointer64 : (ACPI_TABLE_MADT *)acpi_tables.MadtPointer;
5632
5633 ProcessMadtInfo(MadtPointer, &madt_info);
5634
5635 }
5636
5637 if (gen_ssdt || gen_csta || gen_psta || gen_tsta)
5638 {
5639 ProcessSsdt(new_table_list, DsdtPtr, &madt_info, gen_csta, gen_psta, gen_tsta );
5640 }
5641 }
5642#endif
5643
5644if ((rsdp_mod != (void *)0ul) && (rsdp_mod->Length >= ACPI_RSDP_REV0_SIZE) )
5645{
5646if ((rsdp_mod->Revision == 0) || (gen_xsdt == true))
5647{
5648process_rsdt(rsdp_mod, gen_xsdt, new_table_list);
5649goto out;
5650}
5651
5652}
5653else
5654{
5655printf("Error: Incorect ACPI RSD PTR or not found \n");
5656return EFI_UNSUPPORTED;
5657}
5658
5659if ((GetChecksum(rsdp_mod, sizeof(ACPI_TABLE_RSDP)) == 0) &&
5660(Revision == 2) &&
5661(rsdplength == sizeof(ACPI_TABLE_RSDP)))
5662{
5663process_xsdt(rsdp_mod, new_table_list);
5664
5665}
5666else
5667{
5668printf("Warning : ACPI RSD PTR Revision 2 is incorrect, \n");
5669printf(" trying to fallback to Revision 1\n");
5670if ((rsdp_mod != (void *)0ul) && (rsdp_mod->Length >= ACPI_RSDP_REV0_SIZE) )
5671{
5672process_rsdt(rsdp_mod, false, new_table_list);
5673
5674}
5675else
5676{
5677printf("Error: Incorect ACPI RSD PTR or not found \n");
5678return EFI_UNSUPPORTED;
5679}
5680}
5681
5682out:
5683// Correct the checksum of RSDP
5684
5685DBG("RSDP: Original checksum %d\n", rsdp_mod->Checksum);
5686
5687setRsdpchecksum(rsdp_mod);
5688
5689DBG("New checksum %d\n", rsdp_mod->Checksum);
5690
5691if (Revision == 2)
5692{
5693DBG("RSDP: Original extended checksum %d\n", rsdp_mod->ExtendedChecksum);
5694
5695setRsdpXchecksum(rsdp_mod);
5696
5697DBG("New extended checksum %d\n", rsdp_mod->ExtendedChecksum);
5698
5699}
5700
5701verbose("ACPI Revision %d successfully patched\n", Revision);
5702
5703if (Revision == 2)
5704{
5705rsd_p = ((U64)((U32)rsdp_mod));
5706if (rsd_p)
5707Status = addConfigurationTable(&gEfiAcpi20TableGuid, &rsd_p, "ACPI_20");
5708}
5709else
5710{
5711rsd_p = ((U64)((U32)rsdp_mod));
5712if (rsd_p)
5713Status = addConfigurationTable(&gEfiAcpiTableGuid, &rsd_p, "ACPI");
5714
5715}
5716
5717#if DEBUG_ACPI==2
5718printf("Press a key to continue... (DEBUG_ACPI)\n");
5719getc();
5720#endif
5721return Status;
5722}
5723

Archive Download this file

Revision: 1667