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

Archive Download this file

Revision: 1468