Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 1595