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, fallback to fadt original 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 == NULL) goto Failed;
717
718aml_add_buffer = (void*)lookup_all_symbols("_aml_add_buffer");
719if (aml_add_buffer == NULL) goto Failed;
720
721aml_add_byte = (void*)lookup_all_symbols("_aml_add_byte");
722if (aml_add_byte == NULL) goto Failed;
723
724aml_add_word = (void*)lookup_all_symbols("_aml_add_word");
725if (aml_add_word == NULL) goto Failed;
726
727aml_add_dword = (void*)lookup_all_symbols("_aml_add_dword");
728if (aml_add_dword == NULL) goto Failed;
729
730aml_add_qword = (void*)lookup_all_symbols("_aml_add_qword");
731if (aml_add_qword == NULL) goto Failed;
732
733aml_add_scope = (void*)lookup_all_symbols("_aml_add_scope");
734if (aml_add_scope == NULL) goto Failed;
735
736aml_add_name = (void*)lookup_all_symbols("_aml_add_name");
737if (aml_add_name == NULL) goto Failed;
738
739aml_add_package = (void*)lookup_all_symbols("_aml_add_package");
740if (aml_add_package == NULL) goto Failed;
741
742aml_add_alias = (void*)lookup_all_symbols("_aml_add_alias");
743if (aml_add_alias == NULL) goto Failed;
744
745aml_destroy_node = (void*)lookup_all_symbols("_aml_destroy_node");
746if (aml_destroy_node == NULL) goto Failed;
747
748aml_calculate_size = (void*)lookup_all_symbols("_aml_calculate_size");
749if (aml_calculate_size == NULL) goto Failed;
750
751aml_write_node = (void*)lookup_all_symbols("_aml_write_node");
752if (aml_write_node == NULL) goto Failed;
753
754aml_add_to_parent = (void*)lookup_all_symbols("_aml_add_to_parent");
755if (aml_add_to_parent == NULL) 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("turbo_available : %d\n",cpu->turbo_available);
1768
1769printf("core_c1_supported : %d\n",cpu->core_c1_supported);
1770printf("core_c3_supported : %d\n",cpu->core_c3_supported);
1771printf("core_c6_supported : %d\n",cpu->core_c6_supported);
1772printf("core_c7_supported : %d\n",cpu->core_c7_supported);
1773printf("mwait_supported : %d\n",cpu->mwait_supported);
1774
1775 printf("turbo_available : %d\n",cpu->turbo_available);
1776
1777printf("core_c1_supported : %d\n",cpu->core_c1_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
2243if (curr_ratio > maxPSratio || minPSratio > curr_ratio)
2244goto dropPstate;
2245
2246{
2247PSTATE * pstate = &cpu->pkg_pstates.pstate[Pstatus];
2248
2249pstate->ratio = curr_ratio;
2250
2251pstate->frequency = Frequency; // CoreFreq (in MHz).
2252
2253U32 power = 0x00000000;
2254#ifdef pstate_power_support
2255// Compute power based on ratio and other data
2256if (pstate->ratio >= cpu->max_ratio_as_mfg)
2257// Use max power in mW
2258power = TDP * 1000;
2259else
2260{
2261power = compute_pstate_power(cpu, pstate->ratio, TDP);
2262
2263// Convert to mW
2264power*= 1000;
2265}
2266#endif
2267pstate->power = resolve_pss(power, Pw, base); // Power (in milliWatts)
2268pstate->translatency = resolve_pss(0x0000000A, Lat1, base); // Transition Latency (in microseconds).
2269pstate->bmlatency = resolve_pss(0x0000000A, Lat2, base); // Bus Master Latency (in microseconds).
2270
2271{
2272U32 Control = 0 /*encode_pstate(curr_ratio)*/ ;
2273if (!expert || !personality) Control = p_states[i].Control;
2274pstate->control = resolve_pss(Control, Ctrl, base); // Control
2275}
2276
2277pstate->status = Pstatus+1; // Status
2278
2279DBG("state :: frequency :%d power: %d translatency: %d bmlatency: %d control: %d status: %d ratio :%d :: registred !! \n",pstate->frequency,pstate->power,
2280pstate->translatency,pstate->bmlatency,pstate->control,pstate->status,pstate->ratio );
2281}
2282
2283
2284Pstatus++;
2285continue;
2286
2287dropPstate:
2288DBG("state with cpu frequency :%d and ratio :%d will be dropped\n",p_states[i].Frequency,curr_ratio);
2289dropPSS++;
2290
2291
2292}
2293
2294if (Pstatus == 0)
2295{
2296verbose("No suitable P-states found, P-States will not be generated !!!\n");
2297return (0);
2298}
2299cpu->pkg_pstates.num_pstates = Pstatus;
2300}
2301}
2302}
2303else
2304{
2305verbose("ACPI CPUs not found: P-States will not be generated !!!\n");
2306return (0);
2307}
2308
2309DBG("_PSS PGK generated successfully\n");
2310return (1);
2311}
2312#endif
2313
2314//-----------------------------------------------------------------------------
2315static U32 BuildCstateInfo(CPU_DETAILS * cpu, U32 pmbase)
2316{
2317{
2318TagPtr personality = XMLCastDict(XMLGetProperty(bootInfo->bootConfig.dictionary, (const char*)"C-States"));
2319
2320if (personality)
2321{
2322int base = 16;
2323
2324U32 entry_count = XMLTagCount(personality);
2325char *tmpstr =NULL;
2326
2327if ((tmpstr = XMLCastString(XMLGetProperty(personality, (const char*)"Base"))))
2328{
2329
2330entry_count--; // -= ("Base" tag)
2331
2332int mybase = strtol(tmpstr, NULL, 10);
2333
2334if (mybase == 8 || mybase == 10 || mybase == 16 )
2335base = mybase;
2336}
2337
2338if (entry_count)
2339{
2340
2341cpu->pkg_io_cstates.num_cstates = 0;
2342cpu->pkg_mwait_cstates.num_cstates = 0;
2343U32 num_cstates = 0;
2344
2345{
2346U32 i;
2347char MatchStat[5];
2348
2349for (i = 0; i < 32 ; i++)
2350{
2351char *Lat = NULL, *Pw = NULL, *BWidth= NULL, *BOffset= NULL, *Address= NULL, *AccessSize= NULL, *index= NULL;
2352
2353sprintf(MatchStat, "C%d",i);
2354TagPtr match_Status = XMLGetProperty(personality, (const char*)MatchStat);
2355if (match_Status)
2356{
2357Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power"));
2358Lat = XMLCastString(XMLGetProperty(match_Status, (const char*)"Latency"));
2359BWidth= XMLCastString(XMLGetProperty(match_Status, (const char*)"BitWidth"));
2360
2361BOffset = XMLCastString(XMLGetProperty(match_Status, (const char*)"BitOffset"));
2362Address = XMLCastString(XMLGetProperty(match_Status, (const char*)"Latency"));
2363AccessSize = XMLCastString(XMLGetProperty(match_Status, (const char*)"AccessSize"));
2364index = XMLCastString(XMLGetProperty(match_Status, (const char*)"index"));
2365
2366if (Pw && Lat && BWidth && BOffset && Address && AccessSize && index)
2367{
2368U32 bw= strtoul((const char *)BWidth, NULL,base);
2369U32 boff= strtoul((const char *)BOffset, NULL,base);
2370U32 acs= strtoul((const char *)AccessSize, NULL,base);
2371U32 addr= strtoul((const char *)Address, NULL,base);
2372U32 idx= strtoul((const char *)index, NULL,base);
2373U32 lat= strtoul((const char *)Lat, NULL,base);
2374U32 pw= strtoul((const char *)Pw, NULL,base);
2375
2376ACPI_GENERIC_ADDRESS mwait_gas = {GAS_TYPE_FFH,bw,boff,acs,addr};
2377ACPI_GENERIC_ADDRESS io_gas = {(i == 1) ? GAS_TYPE_FFH : GAS_TYPE_SYSTEM_IO,bw,boff,acs,addr};
2378
2379CSTATE mwait_cstate = {idx,lat,pw};
2380CSTATE io_cstate = {idx,lat,pw};
2381
2382{
2383cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate;
2384cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas;
2385cpu->pkg_mwait_cstates.num_cstates++;
2386}
2387
2388{
2389cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate;
2390cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas;
2391cpu->pkg_io_cstates.num_cstates++;
2392}
2393num_cstates++;
2394
2395if (num_cstates >= MAX_CSTATES)
2396{
2397break;
2398}
2399}
2400}
2401}
2402}
2403
2404if (num_cstates)
2405{
2406return (1);
2407}
2408}
2409}
2410}
2411
2412{
2413static const ACPI_GENERIC_ADDRESS mwait_gas[] = {
2414{GAS_TYPE_FFH,1,2,1,0x00}, // processor C1
2415{GAS_TYPE_FFH,1,2,1,0x10}, // processor C3 as ACPI C2
2416{GAS_TYPE_FFH,1,2,1,0x10}, // processor C3 as ACPI C3
2417{GAS_TYPE_FFH,1,2,1,0x10}, // processor C3 as ACPI C4
2418{GAS_TYPE_FFH,1,2,1,0x20}, // processor C6
2419{GAS_TYPE_FFH,1,2,1,0x30}, // processor C7
2420};
2421
2422static const ACPI_GENERIC_ADDRESS io_gas[] = {
2423{GAS_TYPE_FFH, 0,0,0,0x00}, // processor C1
2424{GAS_TYPE_SYSTEM_IO,8,0,0,0x14}, // processor C3 as ACPI C2 or processor C2
2425{GAS_TYPE_SYSTEM_IO,8,0,0,0x14}, // processor C3 as ACPI C3
2426{GAS_TYPE_SYSTEM_IO,8,0,0,0x15}, // processor C4 as ACPI C4
2427{GAS_TYPE_SYSTEM_IO,8,0,0,0x15}, // processor C6
2428{GAS_TYPE_SYSTEM_IO,8,0,0,0x16}, // processor C7
2429};
2430
2431static const CSTATE mwait_cstate [] = {
2432{1,0x01,0x3e8}, // processor C1
2433{2,0x40,0x1f4}, // processor C3 as ACPI C2 or processor C2
2434{3,0x40,0x1f4}, // processor C3 as ACPI C3
2435{4,0x40,0x1f4}, // processor C4
2436{6/*was 3*/,0x60,0x15e}, // processor C6
2437{7/*was 3*/,0x60,0x0c8}, // processor C7
2438};
2439
2440static const CSTATE io_cstate [] = {
2441{1,0x01,0x3e8}, // processor C1
2442{2,0x40,0x1f4}, // processor C3 as ACPI C2 or processor C2
2443{3,0x40,0x1f4}, // processor C3 as ACPI C3
2444{4,0x40,0x1f4}, // processor C4
2445{6/*was 3*/,0x60,0x15e}, // processor C6
2446{7/*was 3*/,0x60,0x0c8}, // processor C7
2447};
2448
2449static const U32 cstate_2_index [] = {0,0,0,1,2,3,4,5};
2450
2451// Build C-state table info based on verified options
2452
2453// Desired state for the processor core C3 state included in the _CST as an
2454// ACPI C2 state.
2455// 1= processor core C3 can be used as an ACPI C2 state
2456// 0= processor core C3 cannot be used as an ACPI C2 state
2457int c2_enabled = 0;
2458
2459// Desired state for the processor core C3 state included in the _CST
2460// 0= processor core C3 cannot be used as an ACPI C state
2461// 2= processor core C3 can be used as an ACPI C2 state
2462// 3= processor core C3 can be used as an ACPI C3 state
2463// 4= processor core C3 can be used as an ACPI C2 state
2464// if Invariant APIC Timer detected, else not used as ACPI C state
2465// 5= processor core C3 can be used as an ACPI C2 state
2466// if Invariant APIC Timer detected, else APIC C3 state
2467// 6= processor core C3 can be used as an ACPI C4 state
2468int c3_enabled = 3;
2469
2470// Desired state for the processor core C3 state included in the _CST as an
2471// ACPI C4 state.
2472// 1= processor core C3 can be used as an ACPI C4 state
2473// 0= processor core C3 cannot be used as an ACPI C4 state
2474int c4_enabled = 0;
2475
2476// Desired state for the processor core C6 state included in the _CST as an
2477// ACPI C3 state.
2478// 1= processor core C6 can be used as an ACPI C3 state
2479// 0= processor core C6 cannot be used as an ACPI C3 state
2480int c6_enabled = 0;
2481
2482// Desired state for the processor core C7 state included in the _CST as an
2483// ACPI C3 state.
2484// 1= processor core C7 can be used as an ACPI C7 state
2485// 0= processor core C7 cannot be used as an ACPI C7 state
2486int c7_enabled = 0;
2487
2488{
2489bool tmpval;
2490
2491
2492if (getBoolForKey(kEnableC2State, &tmpval, &bootInfo->bootConfig))
2493{
2494c2_enabled = tmpval;
2495}
2496
2497if (!getIntForKey("C3StateOption", &c3_enabled, &bootInfo->bootConfig))
2498{
2499c3_enabled = (getBoolForKey(kEnableC3State, &tmpval, &bootInfo->bootConfig)&&tmpval) ? 3 : 0;
2500}
2501if (c3_enabled == 6)
2502{
2503c4_enabled = 1;
2504}
2505else
2506{
2507c4_enabled = (getBoolForKey(kEnableC4State, &tmpval, &bootInfo->bootConfig)&&tmpval) ? 1 : 0;
2508}
2509c6_enabled = (getBoolForKey(kEnableC6State, &tmpval, &bootInfo->bootConfig)&&tmpval) ? 1 : 0;
2510c7_enabled = (getBoolForKey(kEnableC7State, &tmpval, &bootInfo->bootConfig)&&tmpval) ? 1 : 0;
2511}
2512
2513cpu->pkg_mwait_cstates.num_cstates = 0;
2514{
2515{
2516cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C1]];
2517cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C1]];
2518cpu->pkg_mwait_cstates.num_cstates++;
2519}
2520if (((cpu->core_c3_supported || cpu->core_c2_supported) && (c2_enabled)) && ((c3_enabled == 2) ||
2521 ((c3_enabled == 4) && cpu->invariant_apic_timer_flag)))
2522{
2523cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C3_ACPI_C2]];
2524cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C3_ACPI_C2]];
2525cpu->pkg_mwait_cstates.num_cstates++;
2526}
2527if (cpu->core_c4_supported && c4_enabled)
2528{
2529
2530cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C4]];
2531cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C4]];
2532cpu->pkg_mwait_cstates.num_cstates++;
2533
2534}
2535else
2536{
2537
2538if (cpu->core_c3_supported && ((c3_enabled == 3) ||
2539 ((c3_enabled == 4) && !cpu->invariant_apic_timer_flag)))
2540{
2541cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C3_ACPI_C3]];
2542cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C3_ACPI_C3]];
2543cpu->pkg_mwait_cstates.num_cstates++;
2544}
2545}
2546
2547
2548if (cpu->core_c6_supported && c6_enabled)
2549{
2550cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C6]];
2551cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C6]];
2552cpu->pkg_mwait_cstates.num_cstates++;
2553}
2554if (cpu->core_c7_supported && c7_enabled)
2555{
2556cpu->pkg_mwait_cstates.cstate[cpu->pkg_mwait_cstates.num_cstates] = mwait_cstate[cstate_2_index[CPU_C7]];
2557cpu->pkg_mwait_cstates.gas[cpu->pkg_mwait_cstates.num_cstates] = mwait_gas[cstate_2_index[CPU_C7]];
2558cpu->pkg_mwait_cstates.num_cstates++;
2559}
2560}
2561
2562cpu->pkg_io_cstates.num_cstates = 0;
2563{
2564{
2565cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C1]];
2566cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C1]];
2567cpu->pkg_io_cstates.num_cstates++;
2568}
2569if ((cpu->core_c3_supported || cpu->core_c2_supported) && (c2_enabled || (c3_enabled == 2) ||
2570 ((c3_enabled == 4) && cpu->invariant_apic_timer_flag)))
2571{
2572cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C3_ACPI_C2]];
2573cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C3_ACPI_C2]];
2574cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase;
2575cpu->pkg_io_cstates.num_cstates++;
2576}
2577if (cpu->core_c4_supported && c4_enabled)
2578{
2579
2580cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C4]];
2581cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C4]];
2582cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase;
2583cpu->pkg_io_cstates.num_cstates++;
2584
2585}
2586else
2587{
2588
2589if (cpu->core_c3_supported && ((c3_enabled == 3) ||
2590 ((c3_enabled == 4) && !cpu->invariant_apic_timer_flag)))
2591{
2592cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C3_ACPI_C3]];
2593cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C3_ACPI_C3]];
2594cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase;
2595cpu->pkg_io_cstates.num_cstates++;
2596}
2597}
2598
2599if (cpu->core_c6_supported && c6_enabled)
2600{
2601cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C6]];
2602cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C6]];
2603cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase;
2604cpu->pkg_io_cstates.num_cstates++;
2605}
2606if (cpu->core_c7_supported && c7_enabled)
2607{
2608cpu->pkg_io_cstates.cstate[cpu->pkg_io_cstates.num_cstates] = io_cstate[cstate_2_index[CPU_C7]];
2609cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates] = io_gas[cstate_2_index[CPU_C7]];
2610cpu->pkg_io_cstates.gas[cpu->pkg_io_cstates.num_cstates].Address += pmbase;
2611cpu->pkg_io_cstates.num_cstates++;
2612}
2613}
2614}
2615
2616return (1);
2617}
2618
2619#if BUILD_ACPI_TSS
2620//-----------------------------------------------------------------------------
2621static U32 BuildTstateInfo(CPU_DETAILS * cpu)
2622{
2623 // Coarse grained clock modulation is available if cpuid.6.eax[5] = 0
2624 // Max of 8 T-states using 12.5% increments
2625 static const TSTATE tstate_coarse_grain [] = {
2626 {100,0,0,0x00,0},
2627 { 88,0,0,0x1e,0},
2628 { 75,0,0,0x1c,0},
2629 { 63,0,0,0x1a,0},
2630 { 50,0,0,0x18,0},
2631 { 38,0,0,0x16,0},
2632 { 25,0,0,0x14,0},
2633 { 13,0,0,0x12,0},
2634 };
2635
2636 // Fine grained clock modulation is available if cpuid.6.eax[5] = 1
2637 // Max of 15 T-states using 6.25% increments
2638 static const TSTATE tstate_fine_grain [] = {
2639 {100,0,0,0x00,0},
2640 { 94,0,0,0x1f,0},
2641 { 88,0,0,0x1e,0},
2642 { 81,0,0,0x1d,0},
2643 { 75,0,0,0x1c,0},
2644 { 69,0,0,0x1b,0},
2645 { 63,0,0,0x1a,0},
2646 { 56,0,0,0x19,0},
2647 { 50,0,0,0x18,0},
2648 { 44,0,0,0x17,0},
2649 { 38,0,0,0x16,0},
2650 { 31,0,0,0x15,0},
2651 { 25,0,0,0x14,0},
2652 { 19,0,0,0x13,0},
2653 { 13,0,0,0x12,0},
2654 };
2655
2656 // Build T-state table info based on verified options
2657 U32 num_cpu;
2658 const TSTATE * tstate;
2659 U32 num_tstates;
2660
2661 for (num_cpu = 0; num_cpu < cpu_map_count; num_cpu ++)
2662 {
2663 // Check if fine or coarse grained clock modulation is available
2664 if (Platform->CPU.fine_grain_clock_mod)
2665 {
2666 // Fine grain thermal throttling is available
2667 num_tstates = 15;
2668 tstate = tstate_fine_grain;
2669 }
2670 else
2671 {
2672 // Coarse grain thermal throttling is available
2673 num_tstates = 8;
2674 tstate = tstate_coarse_grain;
2675 }
2676
2677 cpu->pkg_tstates.num_tstates = num_tstates;
2678 {
2679 U32 index;
2680 for (index = 0; index < num_tstates; index++)
2681 {
2682 cpu->pkg_tstates.tstate[index] = tstate[index];
2683 cpu->pkg_tstates.tstate[index].power = 1000 * (compute_tdp(cpu) * (num_tstates - index)) / num_tstates;
2684 }
2685 }
2686
2687
2688 }
2689 return (1);
2690}
2691#endif
2692
2693static U32 ProcessSsdt(U32 * new_table_list, ACPI_TABLE_DSDT *dsdt, bool enable_cstates, bool enable_pstates, bool enable_tstates )
2694{
2695DBG("Processing SSDT\n");
2696
2697ACPI_TABLE_MADT * madt_file = (void*)0ul;
2698ACPI_TABLE_MADT * MadtPointer = (void*)0ul;
2699U8 new_table_index = 0;
2700bool oem_apic=false;
2701
2702if (Platform->CPU.Vendor != 0x756E6547) {
2703verbose ("Not an Intel platform: SSDT will not be generated !!!\n");
2704return(0);
2705}
2706
2707if (!(Platform->CPU.Features & CPUID_FEATURE_MSR)) {
2708verbose ("Unsupported CPU: SSDT will not be generated !!!\n");
2709return(0);
2710}
2711
2712if (dsdt == (void *)0ul) {
2713verbose ("DSDT not found: SSDT will not be generated !!!\n");
2714return (0);
2715}
2716
2717{
2718bool tmpval;
2719oem_apic=getBoolForKey(kOEMAPIC, &tmpval, &bootInfo->bootConfig)&&tmpval;
2720}
2721
2722// Get an empty space in the new_talbe_list (true = allow reserved space)
2723U8 empty = get_0ul_index_in_list(new_table_list, true);
2724
2725// Check to confirm space is available
2726if (empty == ACPI_TABLE_LIST_FULL)
2727{
2728printf("Error: not enought reserved space in the new acpi list for the SSDT table,\n ");
2729printf(" please increase the RESERVED_AERA\n");
2730return(0);
2731}
2732
2733if ((madt_file = (ACPI_TABLE_MADT *)get_new_table_in_list(new_table_list, NAMESEG("APIC"), &new_table_index)) != (void *)0ul)
2734{
2735if (oem_apic == false)
2736{
2737MadtPointer = (ACPI_TABLE_MADT *)madt_file;
2738//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
2739}
2740
2741} else
2742MadtPointer = (acpi_tables.MadtPointer64 != (void*)0ul) ? (ACPI_TABLE_MADT *)acpi_tables.MadtPointer64 : (ACPI_TABLE_MADT *)acpi_tables.MadtPointer;
2743
2744// Create buffer for SSDT
2745U8 memory_for_ssdt[20 * 1024];
2746
2747// Build the SSDT
2748if ( (BuildSsdt(MadtPointer, dsdt, memory_for_ssdt, sizeof(memory_for_ssdt), enable_cstates, enable_pstates, enable_tstates)) == 0)
2749{
2750printf("Error: Failed to build SSDT table\n");
2751return (0);
2752}
2753
2754// insert SSDT in the new_table_list
2755{
2756// Create pointer to SSDT just built in the stack buffer
2757ACPI_TABLE_SSDT * old_ssdt = (ACPI_TABLE_SSDT *)memory_for_ssdt;
2758
2759// Reserved kernel memory for the ssdt table
2760ACPI_TABLE_SSDT *new_ssdt = (ACPI_TABLE_SSDT *)AllocateKernelMemory(old_ssdt->Header.Length);
2761
2762if (!new_ssdt)
2763{
2764printf("Unable to allocate kernel memory for SSDT ");
2765return (0);
2766}
2767// Move the old stack buffer to kernel memory
2768memcpy(new_ssdt, old_ssdt, old_ssdt->Header.Length);
2769
2770// Add the new ssdt into an empty space of the new_table_list
2771new_table_list[empty] = (U32)new_ssdt;
2772}
2773
2774verbose ("SSDT table generated successfully\n");
2775return(1);
2776}
2777
2778//-----------------------------------------------------------------------------
2779static void * buildCpuScope (void * current, U32 cpu_namespace, PROCESSOR_NUMBER_TO_NAMESEG * aslCpuNamePath)
2780{
2781ACPI_SCOPE * scope = current;
2782current = scope + 1;
2783
2784scope->scopeOpcode = AML_SCOPE_OP;
2785scope->rootChar = AML_ROOT_PREFIX;
2786
2787if (aslCpuNamePath->seg_count == 1)
2788{
2789DUAL_NAME_PATH * dualNamePath = current;
2790current = dualNamePath + 1;
2791dualNamePath->prefix = AML_DUAL_NAME_PREFIX;
2792dualNamePath->nameseg[0] = cpu_namespace;
2793dualNamePath->nameseg[1] = aslCpuNamePath->nameseg[0];
2794}
2795else
2796{
2797MULTI_NAME_PATH * multiNamePath = current;
2798current = multiNamePath + 1;
2799multiNamePath->prefix = AML_MULTI_NAME_PREFIX;
2800// the nameseg count includes the root prefix and all other namesegs
2801multiNamePath->segCount = (U8) aslCpuNamePath->seg_count+1;
2802multiNamePath->nameseg[0] = cpu_namespace;
2803{
2804U32 i;
2805for (i=0; i<aslCpuNamePath->seg_count; i++)
2806multiNamePath->nameseg[i+1] = aslCpuNamePath->nameseg[i];
2807}
2808}
2809return (current);
2810}
2811//-----------------------------------------------------------------------------
2812static void * buildPDC(void * current)
2813{
2814ACPI_METHOD * pdc = current;
2815current = buildMethod(current, NAMESEG("_PDC"), 1);
2816
2817// CreateDWordField (Arg0, 0x08, CAPA)
2818current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2819current = buildOpCode(current, AML_ARG0_OP);
2820current = buildByteConst(current, 0x08);
2821current = buildNameSeg(current, NAMESEG("CAPA"));
2822
2823// Store (CAPA, TYPE)
2824current = buildOpCode(current, AML_STORE_OP);
2825current = buildNameSeg(current, NAMESEG("CAPA"));
2826current = buildNameSeg(current, NAMESEG("TYPE"));
2827
2828// CreateDWordField (Arg0, 0x00, REVS)
2829current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2830current = buildOpCode(current, AML_ARG0_OP);
2831current = buildByteConst(current, 0x00);
2832current = buildNameSeg(current, NAMESEG("REVS"));
2833
2834// CreateDWordField (Arg0, 0x04, SIZE)
2835current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2836current = buildOpCode(current, AML_ARG0_OP);
2837current = buildByteConst(current, 0x04);
2838current = buildNameSeg(current, NAMESEG("SIZE"));
2839
2840// Store(SizeOf(Arg0), Local0)
2841current = buildOpCode(current, AML_STORE_OP);
2842current = buildOpCode(current, AML_SIZEOF_OP);
2843current = buildOpCode(current, AML_ARG0_OP);
2844current = buildOpCode(current, AML_LOCAL0_OP);
2845
2846// Store(Subtract(Local0, 0x08),Local1)
2847current = buildOpCode(current, AML_STORE_OP);
2848current = buildOpCode(current, AML_SUBTRACT_OP);
2849current = buildOpCode(current, AML_LOCAL0_OP);
2850current = buildByteConst(current, 0x08);
2851current = buildOpCode(current, AML_ZERO_OP);
2852current = buildOpCode(current, AML_LOCAL1_OP);
2853
2854// CreateField (Arg0, 0x40, Multiply (Local1, 0x08), TEMP)
2855current = buildOpCode(current, AML_EXT_OP_PREFIX);
2856current = buildOpCode(current, AML_CREATE_FIELD_OP);
2857current = buildOpCode(current, AML_ARG0_OP);
2858current = buildByteConst(current, 0x40);
2859current = buildOpCode(current, AML_MULTIPLY_OP);
2860current = buildOpCode(current, AML_LOCAL1_OP);
2861current = buildByteConst(current, 0x08);
2862current = buildOpCode(current, AML_ZERO_OP);
2863current = buildNameSeg(current, NAMESEG("TEMP"));
2864
2865// Name (STS0, Buffer (0x04) {0x00, 0x00, 0x00, 0x00})
2866// Create STS0 as named buffer
2867current = buildNamePath(current, NAMESEG("STS0"));
2868{
2869ACPI_SMALL_BUFFER * buff = current;
2870current = buildSmallBuffer(current);
2871
2872// count of buffer elements
2873current = buildByteConst(current, 4);
2874
2875current = buildOpCode(current, AML_ZERO_OP);
2876current = buildOpCode(current, AML_ZERO_OP);
2877current = buildOpCode(current, AML_ZERO_OP);
2878current = buildOpCode(current, AML_ZERO_OP);
2879{
2880U32 length = (U8 *)current - (U8 *)buff;
2881buff->packageLength = (U8)length - 1;
2882}
2883}
2884
2885//Concatenate (STS0, TEMP, Local2)
2886current = buildOpCode(current, AML_CONCAT_OP);
2887current = buildNameSeg(current, NAMESEG("STS0"));
2888current = buildNameSeg(current, NAMESEG("TEMP"));
2889current = buildOpCode(current, AML_LOCAL2_OP);
2890
2891//_OSC (Buffer (0x10)
2892// {
2893// /* 0000 */ 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47,
2894// /* 0008 */ 0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53
2895// }, REVS, SIZE, Local2)
2896current = buildNameSeg(current, NAMESEG("_OSC"));
2897{
2898ACPI_SMALL_BUFFER * buff = current;
2899current = buildSmallBuffer(current);
2900
2901// count of buffer elements
2902current = buildByteConst(current, 0x10);
2903
2904current = buildOpCode(current, 0x16);
2905current = buildOpCode(current, 0xa6);
2906current = buildOpCode(current, 0x77);
2907current = buildOpCode(current, 0x40);
2908current = buildOpCode(current, 0x0c);
2909current = buildOpCode(current, 0x29);
2910current = buildOpCode(current, 0xbe);
2911current = buildOpCode(current, 0x47);
2912current = buildOpCode(current, 0x9e);
2913current = buildOpCode(current, 0xbd);
2914current = buildOpCode(current, 0xd8);
2915current = buildOpCode(current, 0x70);
2916current = buildOpCode(current, 0x58);
2917current = buildOpCode(current, 0x71);
2918current = buildOpCode(current, 0x39);
2919current = buildOpCode(current, 0x53);
2920{
2921U32 length = (U8 *)current - (U8 *)buff;
2922buff->packageLength = (U8)length - 1;
2923}
2924}
2925current = buildNameSeg(current, NAMESEG("REVS"));
2926current = buildNameSeg(current, NAMESEG("SIZE"));
2927current = buildOpCode(current, AML_LOCAL2_OP);
2928
2929// Update package length in PDC object
2930//pdc->packageLength = (U8)((U8 *)current - (U8 *)&pdc->packageLength);
2931setPackageLength(&pdc->pkgLength, (U8 *)current - (U8 *)&pdc->pkgLength);
2932
2933return(current);
2934}
2935
2936//-----------------------------------------------------------------------------
2937static void * buildOSC(void * current)
2938{
2939//
2940//
2941ACPI_METHOD * osc = current;
2942current = buildMethod(current, NAMESEG("_OSC"), 4);
2943
2944// CreateDWordField (Arg3, 0x04, CAPA)
2945current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2946current = buildOpCode(current, AML_ARG3_OP);
2947current = buildByteConst(current, 0x04);
2948current = buildNameSeg(current, NAMESEG("CAPA"));
2949
2950// Store (CAPA, TYPE)
2951current = buildOpCode(current, AML_STORE_OP);
2952current = buildNameSeg(current, NAMESEG("CAPA"));
2953current = buildNameSeg(current, NAMESEG("TYPE"));
2954
2955// CreateDWordField (Arg3, 0x00, STS0)
2956current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2957current = buildOpCode(current, AML_ARG3_OP);
2958current = buildByteConst(current, 0x00);
2959current = buildNameSeg(current, NAMESEG("STS0"));
2960
2961// CreateDWordField (Arg3, 0x04, CAP0)
2962current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2963current = buildOpCode(current, AML_ARG3_OP);
2964current = buildByteConst(current, 0x04);
2965current = buildNameSeg(current, NAMESEG("CAP0"));
2966
2967// CreateDWordField (Arg0, 0x00, IID0)
2968current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2969current = buildOpCode(current, AML_ARG0_OP);
2970current = buildByteConst(current, 0x00);
2971current = buildNameSeg(current, NAMESEG("IID0"));
2972
2973// CreateDWordField (Arg0, 0x04, IID1)
2974current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2975current = buildOpCode(current, AML_ARG0_OP);
2976current = buildByteConst(current, 0x04);
2977current = buildNameSeg(current, NAMESEG("IID1"));
2978
2979// CreateDWordField (Arg0, 0x08, IID2)
2980current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2981current = buildOpCode(current, AML_ARG0_OP);
2982current = buildByteConst(current, 0x08);
2983current = buildNameSeg(current, NAMESEG("IID2"));
2984
2985// CreateDWordField (Arg0, 0x0C, IID3)
2986current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
2987current = buildOpCode(current, AML_ARG0_OP);
2988current = buildByteConst(current, 0x0C);
2989current = buildNameSeg(current, NAMESEG("IID3"));
2990
2991// Name (UID0, Buffer (0x10)
2992// {
2993// 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47,
2994// 0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53
2995// })
2996current = buildNamePath(current, NAMESEG("UID0"));
2997{
2998ACPI_SMALL_BUFFER * buff = current;
2999current = buildSmallBuffer(current);
3000
3001// count of buffer elements
3002current = buildByteConst(current, 0x10);
3003
3004current = buildOpCode(current, 0x16);
3005current = buildOpCode(current, 0xa6);
3006current = buildOpCode(current, 0x77);
3007current = buildOpCode(current, 0x40);
3008current = buildOpCode(current, 0x0c);
3009current = buildOpCode(current, 0x29);
3010current = buildOpCode(current, 0xbe);
3011current = buildOpCode(current, 0x47);
3012current = buildOpCode(current, 0x9e);
3013current = buildOpCode(current, 0xbd);
3014current = buildOpCode(current, 0xd8);
3015current = buildOpCode(current, 0x70);
3016current = buildOpCode(current, 0x58);
3017current = buildOpCode(current, 0x71);
3018current = buildOpCode(current, 0x39);
3019current = buildOpCode(current, 0x53);
3020
3021{
3022U32 length = (U8 *)current - (U8 *)buff;
3023buff->packageLength = (U8)length - 1;
3024}
3025}
3026
3027// CreateDWordField (UID0, 0x00, EID0)
3028current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
3029current = buildOpCode(current, AML_ARG0_OP);
3030current = buildByteConst(current, 0x00);
3031current = buildNameSeg(current, NAMESEG("EID0"));
3032
3033// CreateDWordField (UID0, 0x04, EID1)
3034current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
3035current = buildOpCode(current, AML_ARG0_OP);
3036current = buildByteConst(current, 0x04);
3037current = buildNameSeg(current, NAMESEG("EID1"));
3038
3039// CreateDWordField (UID0, 0x08, EID2)
3040current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
3041current = buildOpCode(current, AML_ARG0_OP);
3042current = buildByteConst(current, 0x08);
3043current = buildNameSeg(current, NAMESEG("EID2"));
3044
3045// CreateDWordField (UID0, 0x0C, EID3)
3046current = buildOpCode(current, AML_CREATE_DWORD_FIELD_OP);
3047current = buildOpCode(current, AML_ARG0_OP);
3048current = buildByteConst(current, 0x0C);
3049current = buildNameSeg(current, NAMESEG("EID3"));
3050
3051// If (LNot (LAnd (LAnd (LEqual (IID0, EID0), LEqual (IID1, EID1)),
3052// LAnd (LEqual (IID2, EID2), LEqual (IID3, EID3)))))
3053// {
3054// Store (0x06, Index (STS0, 0x00))
3055// Return (Arg3)
3056// }
3057{
3058current = buildOpCode(current, AML_IF_OP);
3059{
3060ACPI_PACKAGE_LENGTH * packageLength = current;
3061current = buildPackageLength(current, 0);
3062
3063current = buildOpCode(current, AML_LNOT_OP);
3064current = buildOpCode(current, AML_LAND_OP);
3065current = buildOpCode(current, AML_LAND_OP);
3066current = buildOpCode(current, AML_LEQUAL_OP);
3067current = buildNameSeg(current, NAMESEG("IID0"));
3068current = buildNameSeg(current, NAMESEG("EID0"));
3069
3070current = buildOpCode(current, AML_LEQUAL_OP);
3071current = buildNameSeg(current, NAMESEG("IID1"));
3072current = buildNameSeg(current, NAMESEG("EID1"));
3073
3074current = buildOpCode(current, AML_LAND_OP);
3075current = buildOpCode(current, AML_LEQUAL_OP);
3076current = buildNameSeg(current, NAMESEG("IID2"));
3077current = buildNameSeg(current, NAMESEG("EID2"));
3078
3079current = buildOpCode(current, AML_LEQUAL_OP);
3080current = buildNameSeg(current, NAMESEG("IID3"));
3081current = buildNameSeg(current, NAMESEG("EID3"));
3082
3083// Store (0x06, Index (STS0, 0x00))
3084current = buildOpCode(current, AML_STORE_OP);
3085current = buildByteConst(current, 0x06);
3086current = buildOpCode(current, AML_INDEX_OP);
3087current = buildNameSeg(current, NAMESEG("STS0"));
3088current = buildByteConst(current, 0x00);
3089current = buildOpCode(current, AML_ZERO_OP);
3090
3091// Return (Arg3)
3092current = buildReturnOpcode(current, AML_ARG3_OP);
3093
3094setPackageLength(packageLength,
3095 (U8 *)current - (U8 *)packageLength);
3096}
3097}
3098
3099// If (LNotEqual (Arg1, 0x01))
3100// {
3101// Store (0x0A, Index (STS0, 0x00))
3102// Return (Arg3)
3103// }
3104{
3105current = buildOpCode(current, AML_IF_OP);
3106{
3107ACPI_PACKAGE_LENGTH * packageLength = current;
3108current = buildPackageLength(current, 0);
3109
3110// If ("LNotEqual (Arg1, 0x01)")
3111current = buildOpCode(current, AML_LNOT_OP);
3112current = buildOpCode(current, AML_LEQUAL_OP);
3113current = buildOpCode(current, AML_ARG1_OP);
3114current = buildByteConst(current, 0x01);
3115
3116// Store (0x0A, Index (STS0, 0x00))
3117current = buildOpCode(current, AML_STORE_OP);
3118current = buildByteConst(current, 0x0A);
3119current = buildOpCode(current, AML_INDEX_OP);
3120current = buildNameSeg(current, NAMESEG("STS0"));
3121current = buildByteConst(current, 0x00);
3122current = buildOpCode(current, AML_ZERO_OP);
3123
3124// Return (Arg3)
3125current = buildReturnOpcode(current, AML_ARG3_OP);
3126
3127setPackageLength(packageLength,
3128 (U8 *)current - (U8 *)packageLength);
3129}
3130}
3131
3132// If (And (STS0, 0x01))
3133// {
3134// And (CAP0, 0x0BFF, CAP0)
3135// Return (Arg3)
3136// }
3137{
3138current = buildOpCode(current, AML_IF_OP);
3139{
3140ACPI_PACKAGE_LENGTH * packageLength = current;
3141current = buildPackageLength(current, 0);
3142
3143// If ("And (STS0, 0x01)")
3144current = buildOpCode(current, AML_AND_OP);
3145current = buildNameSeg(current, NAMESEG("STS0"));
3146current = buildByteConst(current, 0x01);
3147current = buildOpCode(current, AML_ZERO_OP);
3148
3149// And (CAP0, 0x0BFF, CAP0)
3150current = buildOpCode(current, AML_AND_OP);
3151current = buildNameSeg(current, NAMESEG("CAP0"));
3152current = buildWordConst(current, 0x0BFF);
3153current = buildNameSeg(current, NAMESEG("CAP0"));
3154
3155// Return (Arg3)
3156current = buildReturnOpcode(current, AML_ARG3_OP);
3157
3158setPackageLength(packageLength,
3159 (U8 *)current - (U8 *)packageLength);
3160}
3161}
3162
3163// And (CAP0, 0x0BFF, CAP0)
3164current = buildOpCode(current, AML_AND_OP);
3165current = buildNameSeg(current, NAMESEG("CAP0"));
3166current = buildWordConst(current, 0x0BFF);
3167current = buildNameSeg(current, NAMESEG("CAP0"));
3168
3169// Store (CAP0, TYPE)
3170current = buildOpCode(current, AML_STORE_OP);
3171current = buildNameSeg(current, NAMESEG("CAP0"));
3172current = buildNameSeg(current, NAMESEG("TYPE"));
3173
3174// Return (Arg3)
3175current = buildReturnOpcode(current, AML_ARG3_OP);
3176
3177// Set package length for the OSC object
3178setPackageLength(&osc->pkgLength, (U8 *)current - (U8 *)&osc->pkgLength);
3179
3180return(current);
3181}
3182
3183//-----------------------------------------------------------------------------
3184static void * buildPSS(void * current, PKG_PSTATES * pkg_pstates)
3185{
3186//
3187// IF (PSEN)
3188// {
3189// Return (Package of Pstate Packages)
3190// }
3191// Return(Zero)
3192//
3193ACPI_METHOD * pss = current;
3194current = buildMethod(current, NAMESEG("_PSS"), 0);
3195
3196{
3197// "IF" (PSEN) -- IF Opcode
3198current = buildOpCode(current, AML_IF_OP);
3199{
3200ACPI_PACKAGE_LENGTH * packageLength = current;
3201current = buildPackageLength(current, 0);
3202
3203// IF "(PSEN)" -- IF Predicate
3204current = buildNameSeg(current, NAMESEG("PSEN"));
3205
3206{
3207ACPI_RETURN_PACKAGE * returnPkg = current;
3208current = buildReturnPackage(current, (U8)pkg_pstates->num_pstates);
3209
3210// (3.3.3) For each P-state
3211{
3212U32 pstateIndex = 0;
3213for (pstateIndex=0; pstateIndex < pkg_pstates->num_pstates; pstateIndex++)
3214{
3215// (3.3.3.1) Create P-state package
3216ACPI_PSTATE_PACKAGE * pstate = current;
3217current = pstate + 1;
3218
3219setSmallPackage(&pstate->package, 6);
3220pstate->package.packageLength = (U8)(sizeof(ACPI_PSTATE_PACKAGE) - 1);
3221
3222setDwordConst(&pstate->CoreFreq, pkg_pstates->pstate[pstateIndex].frequency);// CoreFreq (in MHz).
3223setDwordConst(&pstate->Power, pkg_pstates->pstate[pstateIndex].power);// Power (in milliWatts).
3224setDwordConst(&pstate->TransLatency, pkg_pstates->pstate[pstateIndex].translatency);// Transition Latency (in microseconds).
3225setDwordConst(&pstate->BMLatency, pkg_pstates->pstate[pstateIndex].bmlatency);// Bus Master Latency (in microseconds).
3226setDwordConst(&pstate->Control, pkg_pstates->pstate[pstateIndex].control); // Control.
3227
3228setDwordConst(&pstate->Status, encode_pstate(pkg_pstates->pstate[pstateIndex].ratio));// Status.
3229} // for
3230} // for block
3231
3232// (3.3.4) Update package length in return package
3233setPackageLength(&returnPkg->package.pkgLength, (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3234}
3235
3236// "IF (PSEN) and its body" -- Set package length
3237setPackageLength(packageLength,
3238 (U8 *)current - (U8 *)packageLength);
3239}
3240// "Return (ZERO)"
3241current = buildReturnZero(current);
3242}
3243// Set package length for the _PSS object
3244setPackageLength(&pss->pkgLength, (U8 *)current - (U8 *)&pss->pkgLength);
3245
3246return(current);
3247}
3248
3249//-----------------------------------------------------------------------------
3250static void * buildPSD(void * current, U32 domain, U32 cpusInDomain, U32 pstate_coordination)
3251{
3252// If (And(TYPE, 0x0820))
3253// {
3254// Return (PSD Package)
3255// }
3256// Return(Zero)
3257
3258ACPI_METHOD * psdMethod = current;
3259current = buildMethod(current, NAMESEG("_PSD"), 0);
3260{
3261// "IF" (And(TYPE, 0x0820)) -- IF Opcode
3262current = buildOpCode(current, AML_IF_OP);
3263{
3264ACPI_PACKAGE_LENGTH * packageLength = current;
3265current = buildPackageLength(current, 0);
3266
3267// IF ("And"(TYPE, 0x820)) -- AND Opcode
3268current = buildOpCode(current, AML_AND_OP);
3269
3270// IF (And("TYPE", 0x820)) -- TYPE Term
3271current = buildNameSeg(current, NAMESEG("TYPE"));
3272
3273// IF (And(TYPE, "0x0820")) -- DWORD Value Term
3274current = buildDwordConst(current, 0x820);
3275
3276// IF ("And(TYPE, 0x200)") -- Target for And term (unused)
3277current = buildOpCode(current, AML_ZERO_OP);
3278
3279// Build return package containing PSD package
3280{
3281ACPI_RETURN_PACKAGE * returnPkg = current;
3282current = buildReturnPackage(current, 1);
3283
3284{
3285// Create PSD package
3286ACPI_PSD_PACKAGE * psd = current;
3287current = psd + 1;
3288
3289setSmallPackage(&psd->package, 5);
3290psd->package.packageLength = (U8)(sizeof(ACPI_PSD_PACKAGE) - 1);
3291
3292setByteConst(&psd->NumberOfEntries, 5);
3293setByteConst(&psd->Revision, 0);
3294setDwordConst(&psd->Domain, domain);
3295setDwordConst(&psd->CoordType, pstate_coordination);
3296setDwordConst(&psd->NumProcessors, cpusInDomain);
3297
3298} // PSD package
3299
3300setPackageLength(&returnPkg->package.pkgLength,
3301 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3302}
3303setPackageLength(packageLength, (U8 *)current - (U8 *)packageLength);
3304}
3305// "Return (ZERO)"
3306current = buildReturnZero(current);
3307}
3308// Update length in _PSD method
3309setPackageLength(&psdMethod->pkgLength, (U8 *)current - (U8 *)&psdMethod->pkgLength);
3310
3311return(current);
3312}
3313
3314//-----------------------------------------------------------------------------
3315static void * buildPPC(void * current)
3316{
3317ACPI_SMALL_METHOD * ppc = current;
3318current = buildSmallMethod(current, NAMESEG("_PPC"), 0);
3319
3320current = buildReturnZero(current);
3321
3322// Update package length in PPC object
3323ppc->packageLength = (U8) ( (U8 *)current - (U8 *)&ppc->packageLength );
3324
3325return(current);
3326}
3327
3328//-----------------------------------------------------------------------------
3329static void * buildPCT(void * current)
3330{
3331static const ACPI_GENERIC_ADDRESS pct_gas[] = {
3332{0x7f,0x40,0,0,0x199},
3333{0x7f,0x10,0,0,0x198},
3334};
3335
3336ACPI_SMALL_METHOD * pct = current;
3337current = buildSmallMethod(current, NAMESEG("_PCT"), 0);
3338
3339{
3340ACPI_RETURN_PACKAGE * returnPkg = current;
3341current = buildReturnPackage(current, 2);
3342
3343{
3344ACPI_SMALL_BUFFER * buff = current;
3345current = buildSmallBuffer(current);
3346
3347current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) );
3348current = buildGenericRegister(current, &pct_gas[0]);
3349current = buildEndTag(current);
3350
3351{
3352U32 length = (U8 *)current - (U8 *)buff;
3353buff->packageLength = (U8)length - 1;
3354}
3355}
3356{
3357ACPI_SMALL_BUFFER * buff = current;
3358current = buildSmallBuffer(current);
3359
3360current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) );
3361current = buildGenericRegister(current, &pct_gas[1]);
3362current = buildEndTag(current);
3363
3364{
3365U32 length = (U8 *)current - (U8 *)buff;
3366buff->packageLength = (U8)length - 1;
3367}
3368
3369}
3370
3371setPackageLength(&returnPkg->package.pkgLength,
3372 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3373}
3374
3375// Update package length in PCT object
3376pct->packageLength = (U8)((U8 *)current - (U8 *)&pct->packageLength);
3377
3378return(current);
3379}
3380
3381//-----------------------------------------------------------------------------
3382static void * buildCstate(void * current, ACPI_GENERIC_ADDRESS * gas, CSTATE * cstate)
3383{
3384//
3385// Build a C-state
3386//
3387ACPI_SMALL_PACKAGE * pkg1 = current;
3388current = buildSmallPackage(current, 4);
3389
3390{
3391{
3392ACPI_SMALL_BUFFER * buffer = current;
3393current = buildSmallBuffer(current);
3394
3395{
3396// Buffer length
3397current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) );
3398current = buildGenericRegister(current, gas);
3399current = buildEndTag(current);
3400}
3401{
3402U32 length = (U8 *)current - (U8 *)buffer;
3403buffer->packageLength = (U8)length - 1;
3404}
3405}
3406
3407{
3408current = buildByteConst(current, cstate->type);
3409current = buildWordConst(current, cstate->latency);
3410current = buildDwordConst(current, cstate->power);
3411}
3412}
3413pkg1->packageLength = (U8)((U8 *)current - (U8 *)&pkg1->packageLength);
3414
3415return(current);
3416}
3417
3418//-----------------------------------------------------------------------------
3419static void * buildReturnPackageCST(void * current, PKG_CSTATES * pkg_cstates)
3420{
3421// Create package returning C-states
3422ACPI_RETURN_PACKAGE * returnPkg = current;
3423current = buildReturnPackage(current, (U8)pkg_cstates->num_cstates + 1);
3424
3425{
3426// Include number of C-states
3427current = buildByteConst(current, (U8)pkg_cstates->num_cstates);
3428
3429{
3430U32 cstateIndex = 0;
3431for (cstateIndex=0; cstateIndex < pkg_cstates->num_cstates; cstateIndex++)
3432// Build C-state
3433current = buildCstate(current, &pkg_cstates->gas[cstateIndex], &pkg_cstates->cstate[cstateIndex]);
3434}
3435}
3436
3437// Update package length in return package
3438setPackageLength(&returnPkg->package.pkgLength,
3439 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3440
3441return(current);
3442}
3443
3444//-----------------------------------------------------------------------------
3445static void * buildCST(void * current, PKG_CSTATES * mwait_pkg_cstates, PKG_CSTATES * io_pkg_cstates)
3446{
3447//
3448// IF (CSEN)
3449// {
3450// IF (LAnd(MWOS, And(TYPE, 0x200)))
3451// {
3452// Return package containing MWAIT C-states
3453// }
3454// Return package containing IO C-states
3455// }
3456// Return(Zero)
3457//
3458ACPI_METHOD * cst = current;
3459current = buildMethod(current, NAMESEG("_CST"), 0);
3460{
3461// "IF" CSEN -- IF Opcode
3462current = buildOpCode(current, AML_IF_OP);
3463{
3464ACPI_PACKAGE_LENGTH * packageLength1 = current;
3465current = buildPackageLength(current, 0);
3466
3467// IF "(CSEN)" -- IF Predicate
3468current = buildNameSeg(current, NAMESEG("CSEN"));
3469
3470// "IF" (LAnd(MWOS, And(TYPE, 0x200))) -- IF Opcode
3471current = buildOpCode(current, AML_IF_OP);
3472{
3473ACPI_PACKAGE_LENGTH * packageLength2 = current;
3474current = buildPackageLength(current, 0);
3475
3476// IF ("LAnd"(MWOS, And(TYPE, 0x200))) -- LAND Opcode
3477current = buildOpCode(current, AML_LAND_OP);
3478
3479// IF (LAnd("MWOS", And(TYPE, 0x200))) -- MWOS Term
3480current = buildNameSeg(current, NAMESEG("MWOS"));
3481
3482// IF (LAnd(MWOS, "And"(TYPE, 0x200))) -- AND Opcode
3483current = buildOpCode(current, AML_AND_OP);
3484
3485// IF (LAnd(MWOS, And("TYPE", 0x200))) -- TYPE Term
3486current = buildNameSeg(current, NAMESEG("TYPE"));
3487
3488// IF (LAnd(MWOS, And(TYPE, "0x200"))) -- DWORD Value Term
3489current = buildWordConst(current, 0x200);
3490
3491// IF (LAnd(MWOS, "And(TYPE, 0x200)")) -- Target for And term (unused)
3492current = buildOpCode(current, AML_ZERO_OP);
3493
3494// Build return package for mwait c-states
3495current = buildReturnPackageCST(current, mwait_pkg_cstates);
3496
3497setPackageLength(packageLength2,
3498 (U8 *)current - (U8 *)packageLength2);
3499}
3500
3501// Build return package for io c-states
3502current = buildReturnPackageCST(current, io_pkg_cstates);
3503
3504setPackageLength(packageLength1,
3505 (U8 *)current - (U8 *)packageLength1);
3506}
3507// "Return (ZERO)"
3508current = buildReturnZero(current);
3509}
3510// Update length in _CST method
3511setPackageLength(&cst->pkgLength, (U8 *)current - (U8 *)&cst->pkgLength);
3512
3513return(current);
3514}
3515
3516#if BUILD_ACPI_CSD
3517//-----------------------------------------------------------------------------
3518static void * buildCSD(void * current, U32 domain, U32 cpusInDomain, PKG_CSTATES * pkg_cstates)
3519{
3520 // If (And(TYPE, 0x0040))
3521 // {
3522 // Return (CSD Package)
3523 // }
3524 // Return(Zero)
3525
3526 ACPI_METHOD * csdMethod = current;
3527 current = buildMethod(current, NAMESEG("_CSD"), 0);
3528 {
3529 // "IF" (And(TYPE, 0x0040)) -- IF Opcode
3530 current = buildOpCode(current, AML_IF_OP);
3531 {
3532 ACPI_PACKAGE_LENGTH * packageLength = current;
3533 current = buildPackageLength(current, 0);
3534
3535 // IF ("And"(TYPE, 0x0040)) -- AND Opcode
3536 current = buildOpCode(current, AML_AND_OP);
3537
3538 // IF (And("TYPE", 0x0040)) -- TYPE Term
3539 current = buildNameSeg(current, NAMESEG("TYPE"));
3540
3541 // IF (And(TYPE, "0x0040")) -- DWORD Value Term
3542 current = buildDwordConst(current, 0x0040);
3543
3544 // IF ("And(TYPE, 0x0040)") -- Target for And term (unused)
3545 current = buildOpCode(current, AML_ZERO_OP);
3546
3547 // Build return package containing CSD package(s)
3548 {
3549 ACPI_RETURN_PACKAGE * returnPkg = current;
3550 current = buildReturnPackage(current, (U8)pkg_cstates->num_cstates - 1);
3551
3552 {
3553 U32 cstateIndex;
3554 for (cstateIndex=1; cstateIndex < pkg_cstates->num_cstates; cstateIndex++)
3555 {
3556 // Build CSD for this C-state
3557
3558 // Create CSD package
3559 ACPI_CSD_PACKAGE * csd = current;
3560 current = csd + 1;
3561
3562 setSmallPackage(&csd->package, 6);
3563 csd->package.packageLength = (U8)(sizeof(ACPI_CSD_PACKAGE) - 1);
3564
3565 setByteConst(&csd->NumberOfEntries, 6);
3566 setByteConst(&csd->Revision, 0);
3567 setDwordConst(&csd->Domain, domain);
3568 setDwordConst(&csd->CoordType, ACPI_COORD_TYPE_HW_ALL);
3569 setDwordConst(&csd->NumProcessors, cpusInDomain);
3570 setDwordConst(&csd->Index, cstateIndex);
3571 }
3572 }
3573
3574 setPackageLength(&returnPkg->package.pkgLength,
3575 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3576 }
3577
3578 setPackageLength(packageLength, (U8 *)current - (U8 *)packageLength);
3579 }
3580 // "Return (ZERO)"
3581 current = buildReturnZero(current);
3582 }
3583 // Update length in _CSD method
3584 setPackageLength(&csdMethod->pkgLength, (U8 *)current - (U8 *)&csdMethod->pkgLength);
3585
3586 return(current);
3587}
3588#endif
3589
3590#if BUILD_ACPI_TSS
3591//-----------------------------------------------------------------------------
3592static void * buildTPC(void * current)
3593{
3594 ACPI_SMALL_METHOD * tpc = current;
3595 current = buildSmallMethod(current, NAMESEG("_TPC"), 0);
3596
3597 current = buildReturnZero(current);
3598
3599 // Update package length in PPC object
3600 tpc->packageLength = (U8) ( (U8 *)current - (U8 *)&tpc->packageLength );
3601
3602 return(current);
3603}
3604
3605//-----------------------------------------------------------------------------
3606static void * buildPTC(void * current)
3607{
3608 static const ACPI_GENERIC_ADDRESS ptc_gas[] = {
3609 {0x7f,0x00,0,0,0},
3610 {0x7f,0x00,0,0,0},
3611 };
3612
3613 ACPI_SMALL_METHOD * ptc = current;
3614 current = buildSmallMethod(current, NAMESEG("_PTC"), 0);
3615
3616 {
3617 ACPI_RETURN_PACKAGE * returnPkg = current;
3618 current = buildReturnPackage(current, 2);
3619
3620 {
3621 ACPI_SMALL_BUFFER * buff = current;
3622 current = buildSmallBuffer(current);
3623
3624 current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) );
3625 current = buildGenericRegister(current, &ptc_gas[0]);
3626 current = buildEndTag(current);
3627
3628 {
3629 U32 length = (U8 *)current - (U8 *)buff;
3630 buff->packageLength = (U8)length - 1;
3631 }
3632 }
3633 {
3634 ACPI_SMALL_BUFFER * buff = current;
3635 current = buildSmallBuffer(current);
3636
3637 current = buildByteConst(current, sizeof(ACPI_GENERIC_REGISTER) + sizeof(ACPI_END_TAG) );
3638 current = buildGenericRegister(current, &ptc_gas[1]);
3639 current = buildEndTag(current);
3640
3641 {
3642 U32 length = (U8 *)current - (U8 *)buff;
3643 buff->packageLength = (U8)length - 1;
3644 }
3645 }
3646
3647 setPackageLength(&returnPkg->package.pkgLength,
3648 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3649 }
3650
3651 // Update package length in PTC object
3652 ptc->packageLength = (U8)((U8 *)current - (U8 *)&ptc->packageLength);
3653
3654 return(current);
3655}
3656
3657//-----------------------------------------------------------------------------
3658static void * buildTSS(void * current, PKG_TSTATES * pkg_tstates)
3659{
3660 //
3661 // IF (LAnd(TSEN, And(TYPE,4)))
3662 // {
3663 // Return (Package of Tstate Packages)
3664 // }
3665 // Return(Zero)
3666 //
3667 ACPI_METHOD * tss = current;
3668 current = buildMethod(current, NAMESEG("_TSS"), 0);
3669
3670 {
3671 // "IF" (LAnd(TSEN, And(TYPE,4))) -- IF Opcode
3672 current = buildOpCode(current, AML_IF_OP);
3673 {
3674 ACPI_PACKAGE_LENGTH * packageLength = current;
3675 current = buildPackageLength(current, 0);
3676
3677 // IF ("LAnd"(TSEN, And(TYPE, 4))) -- LAND Opcode
3678 current = buildOpCode(current, AML_LAND_OP);
3679
3680 // IF (LAnd("TSEN", And(TYPE, 4))) -- TSEN Term
3681 current = buildNameSeg(current, NAMESEG("TSEN"));
3682
3683 // IF (LAnd(TSEN, "And"(TYPE, 4))) -- AND Opcode
3684 current = buildOpCode(current, AML_AND_OP);
3685
3686 // IF (LAnd(TSEN, And("TYPE", 4))) -- TYPE Term
3687 current = buildNameSeg(current, NAMESEG("TYPE"));
3688
3689 // IF (LAnd(TSEN, And(TYPE, "4"))) -- DWORD Value Term
3690 current = buildWordConst(current, 4);
3691
3692 // IF (LAnd(MWOS, "And(TYPE, 4)")) -- Target for And term (unused)
3693 current = buildOpCode(current, AML_ZERO_OP);
3694
3695 // Return (Package of Tstate Packages)
3696 {
3697 ACPI_RETURN_PACKAGE * returnPkg = current;
3698 current = buildReturnPackage(current, (U8)pkg_tstates->num_tstates);
3699
3700 // (3.3.3) For each T-state
3701 {
3702 U32 tstateIndex = 0;
3703 for (tstateIndex=0; tstateIndex < pkg_tstates->num_tstates; tstateIndex++)
3704 {
3705 // (3.3.3.1) Create T-state package
3706 ACPI_TSTATE_PACKAGE * tstate = current;
3707 current = tstate + 1;
3708
3709 setSmallPackage(&tstate->package, 5);
3710 tstate->package.packageLength = (U8)(sizeof(ACPI_TSTATE_PACKAGE) - 1);
3711
3712 setDwordConst(&tstate->FreqPercent, pkg_tstates->tstate[tstateIndex].freqpercent);
3713 setDwordConst(&tstate->Power, pkg_tstates->tstate[tstateIndex].power);
3714 setDwordConst(&tstate->TransLatency, pkg_tstates->tstate[tstateIndex].latency);
3715 setDwordConst(&tstate->Control, pkg_tstates->tstate[tstateIndex].control);
3716 setDwordConst(&tstate->Status, pkg_tstates->tstate[tstateIndex].status);
3717 } // for
3718 } // for block
3719
3720 // (3.3.4) Update package length in return package
3721 setPackageLength(&returnPkg->package.pkgLength, (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3722 }
3723
3724 // "IF (LAnd(TSEN, And(TYPE,4))) and its body" -- Set package length
3725 setPackageLength(packageLength, (U8 *)current - (U8 *)packageLength);
3726 }
3727 // "Return (ZERO)"
3728 current = buildReturnZero(current);
3729 }
3730 // Set package length for the _TSS object
3731 setPackageLength(&tss->pkgLength, (U8 *)current - (U8 *)&tss->pkgLength);
3732
3733 return(current);
3734}
3735
3736//-----------------------------------------------------------------------------
3737static void * buildTSD(void * current, U32 domain, U32 cpusInDomain)
3738{
3739 // If (And(TYPE, 0x0080))
3740 // {
3741 // Return (Package containing TSD package)
3742 // }
3743 // Return(Zero)
3744
3745 ACPI_METHOD * tsdMethod = current;
3746 current = buildMethod(current, NAMESEG("_TSD"), 0);
3747 {
3748 // "IF" (And(TYPE, 0x0080)) -- IF Opcode
3749 current = buildOpCode(current, AML_IF_OP);
3750 {
3751 ACPI_PACKAGE_LENGTH * packageLength = current;
3752 current = buildPackageLength(current, 0);
3753
3754 // IF ("And"(TYPE, 0x0080)) -- AND Opcode
3755 current = buildOpCode(current, AML_AND_OP);
3756
3757 // IF (And("TYPE", 0x0080)) -- TYPE Term
3758 current = buildNameSeg(current, NAMESEG("TYPE"));
3759
3760 // IF (And(TYPE, "0x0080")) -- DWORD Value Term
3761 current = buildDwordConst(current, 0x0080);
3762
3763 // IF ("And(TYPE, 0x0080)") -- Target for And term (unused)
3764 current = buildOpCode(current, AML_ZERO_OP);
3765
3766 // Build package containing TSD package
3767 {
3768 ACPI_RETURN_PACKAGE * returnPkg = current;
3769 current = buildReturnPackage(current, 1);
3770
3771 {
3772 // Create PSD package
3773 ACPI_TSD_PACKAGE * tsd = current;
3774 current = tsd + 1;
3775
3776 setSmallPackage(&tsd->package, 5);
3777 tsd->package.packageLength = (U8)(sizeof(ACPI_TSD_PACKAGE) - 1);
3778
3779 setByteConst(&tsd->NumberOfEntries, 5);
3780 setByteConst(&tsd->Revision, 0);
3781 setDwordConst(&tsd->Domain, domain);
3782 setDwordConst(&tsd->CoordType, ACPI_COORD_TYPE_SW_ANY);
3783 setDwordConst(&tsd->NumProcessors, cpusInDomain);
3784
3785 } // TSD package
3786
3787 setPackageLength(&returnPkg->package.pkgLength,
3788 (U8 *)current - (U8 *)&returnPkg->package.pkgLength);
3789 }
3790
3791 setPackageLength(packageLength, (U8 *)current - (U8 *)packageLength);
3792 }
3793 // "Return (ZERO)"
3794 current = buildReturnZero(current);
3795 }
3796 // Update length in _TSD method
3797 setPackageLength(&tsdMethod->pkgLength, (U8 *)current - (U8 *)&tsdMethod->pkgLength);
3798
3799 return(current);
3800}
3801#endif
3802
3803//-----------------------------------------------------------------------------
3804static U32 BuildSsdt(ACPI_TABLE_MADT * madt, ACPI_TABLE_DSDT *dsdt, void * buffer, U32 bufferSize, bool enable_cstates, bool enable_pstates, bool enable_tstates)
3805{
3806// Build SSDT
3807{
3808// (1) Setup pointers to SSDT memory location
3809// (2) Create SSDT Definition Block
3810// (2.1) Save pointer to SSDT package length and checksum fields
3811// (2.2) Create variables in SSDT scope
3812// (3) For each logical processor CPUn
3813// (3.1) Create scope for CPUn
3814// (3.2) Create variables in CPU scope
3815// (3.3) Create _OSC and/or _PDC Methods
3816// (3.4) Create P-state related structures
3817// (3.4.1) Create _PSS Method
3818// (3.4.2) Create _PCT Object
3819// (3.4.3) Create _PPC Method
3820// (3.4.4) Create _PSD Object
3821// (3.5) Create C-state related structures
3822// (3.5.1) Create _CST Method
3823// (3.5.2) Create _CSD Method
3824// (3.6) Create T-state related structures (Optional)
3825// (3.6.1) Create _TPC Method
3826// (3.6.2) Create _PTC Method
3827// (3.6.3) Create _TSS Method
3828// (3.6.4) Create _TSD Method
3829// (3.7) Update length in CPUn Scope
3830// (4) Update length and checksum in SSDT Definition Block
3831DBG("Attempting to build SSDT\n");
3832
3833U32 pstates_enabled = 0;
3834U32 cstates_enabled = 0;
3835CPU_DETAILS cpu;
3836MADT_INFO madt_info;
3837U8 ACPI_COORD_TYPE = ACPI_COORD_TYPE_SW_ANY; // default
3838ACPI_TABLE_SSDT *SsdtPointer = (void*)0ul;
3839
3840// Desired state for providing alternate ACPI _CST structure using MWAIT
3841// extensions
3842// 1= Alternate _CST using MWAIT extension is enabled for OSPM use
3843// 0= Alternate _CST using MWAIT extension is disabled for OSPM use
3844bool enable_mwait = 1;
3845
3846// (1) Setup pointers to SSDT memory location
3847void * current = buffer;
3848void * end = (U8 *)buffer + bufferSize;
3849
3850// Confirm a valid SSDT buffer was provided
3851if (!buffer)
3852{
3853printf("Error: Invalid Buffer Address for SSDT\n");
3854return(0);
3855}
3856
3857// Confirm a valid SSDT buffer length was provided
3858if (!bufferSize)
3859{
3860printf("Error: Invalid Buffer Length for SSDT\n");
3861return(0);
3862}
3863
3864if (madt == (void*) 0ul)
3865{
3866return(0);
3867}
3868
3869if (dsdt == (void*) 0ul)
3870{
3871return(0);
3872}
3873
3874// Check that we have a valid cpu_map (if it's not already done, it will try to generate it)
3875if (generate_cpu_map_from_acpi(dsdt) != 0)
3876{
3877return(0);
3878}
3879
3880collect_cpu_info(&cpu);
3881ProcessMadt(madt, &madt_info);
3882
3883if (enable_cstates && pmbase)
3884{
3885DBG("Building Cstate Info\n");
3886
3887cstates_enabled = BuildCstateInfo(&cpu, pmbase);
3888if (cstates_enabled)
3889{
3890getBoolForKey(KEnableMwait, &enable_mwait, &bootInfo->bootConfig);
3891}
3892}
3893
3894if (enable_pstates)
3895{
3896DBG("Building Pstate Info\n");
3897
3898pstates_enabled = BuildPstateInfo(&cpu);
3899if (pstates_enabled)
3900{
3901const char *str = getStringForKey(KAcpiCoordType, &bootInfo->bootConfig);
3902U8 tmp = (U8)strtoul(str, NULL,16);
3903if ((tmp == ACPI_COORD_TYPE_SW_ALL) || (tmp == ACPI_COORD_TYPE_SW_ANY) || (tmp == ACPI_COORD_TYPE_HW_ALL) )
3904{
3905ACPI_COORD_TYPE = tmp;
3906}
3907}
3908}
3909#if BUILD_ACPI_TSS
3910 U32 tstates_enabled = 0;
3911 if (enable_tstates)
3912{
3913DBG("Building Pstate Info\n");
3914
3915tstates_enabled = BuildTstateInfo(&cpu);
3916}
3917#endif
3918
3919SsdtPointer = (ACPI_TABLE_SSDT *)buffer;
3920
3921// (2) Create SSDT Definition Block
3922// (2.1) Save pointer to SSDT package length and checksum fields
3923current = buildTableHeader(current, NAMESEG("SSDT"), NAMESEG64("PPM RCM "));
3924
3925// Check to confirm no SSDT buffer overflow
3926if ( (U8 *)current > (U8 *)end )
3927{
3928printf("Error: SSDT Buffer Length exceeded available space \n");
3929return(0);
3930}
3931
3932// (3) For each logical processor CPUn
3933// We will use the dsdt datas in place of madt,for the cpu(s) detection.
3934// Most users use the dsdt table to change the numbers of cpu(s) that the OS and the bootloader should use,
3935// (MADT patch to sync the nb of cpu(s) with DSDT is still in progress,
3936// 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,
3937// then the number of core cpu detected by cpu.c, then the dsdt )
3938// Note also that due to chameleon limit we use the same package per each cpu(s) for all objects and methods
3939// (package detection for each cpu(s) is still in progress)
3940{
3941U32 lapic_index;
3942for (lapic_index=0; lapic_index < cpu_map_count; lapic_index++)
3943{
3944// (3.1) Create scope for CPUn
3945ACPI_SCOPE * scope = current;
3946
3947{
3948DBG("Building CPU Scope\n");
3949U32 cpu_namespace = (cpuNamespace == CPU_NAMESPACE_SB) ? NAMESEG("_SB_") : NAMESEG("_PR_");
3950PROCESSOR_NUMBER_TO_NAMESEG * namepath = &cpu_map[lapic_index];
3951current = buildCpuScope (current, cpu_namespace, namepath );
3952}
3953
3954// Check to confirm no SSDT buffer overflow
3955if ( (U8 *)current > (U8 *)end )
3956{
3957printf("Error: SSDT Buffer Length exceeded available space \n");
3958return(0);
3959}
3960
3961// (3.2) Create variables in CPU scope
3962DBG("Creating variables in CPU scope\n");// Build Type variable used to store PDC capabilities
3963current = buildNamedDword(current, NAMESEG("TYPE"), 0);
3964
3965// Build PSEN variable used to store state of P-State Enable setup option
3966current = buildNamedDword(current, NAMESEG("PSEN"), pstates_enabled);
3967
3968// Build CSEN variable used to store state of C-State Enable setup option
3969current = buildNamedDword(current, NAMESEG("CSEN"), cstates_enabled);
3970
3971// Build MWOS variable used to store state of MWAIT OS setup option
3972current = buildNamedDword(current, NAMESEG("MWOS"), (U32)(enable_mwait&&cpu.mwait_supported));
3973
3974// (3.3) Create _OSC and/or _PDC Methods
3975{
3976// Build _PDC method
3977DBG("Building PDC method\n");
3978current = buildPDC(current);
3979
3980// Check to confirm no SSDT buffer overflow
3981if ( (U8 *)current > (U8 *)end )
3982{
3983printf("Error: SSDT Buffer Length exceeded available space \n");
3984return(0);
3985}
3986
3987// Build _OSC method
3988DBG("Building _OSC method\n");
3989current = buildOSC(current);
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
3999// (3.4) Create P-state related structures
4000if (pstates_enabled == 1)
4001{
4002// (3.4.1) Create _PSS Method
4003{
4004DBG("Building _PSS method\n");
4005PKG_PSTATES * pkg_pstates = &cpu.pkg_pstates;
4006current = buildPSS(current, pkg_pstates);
4007}
4008
4009// Check to confirm no SSDT buffer overflow
4010if ( (U8 *)(current) > (U8 *)end )
4011{
4012printf("Error: SSDT Buffer Length exceeded available space \n");
4013return(0);
4014}
4015
4016// (3.4.2) Create _PCT Object
4017DBG("Building _PCT Object\n");
4018current = buildPCT(current);
4019
4020// Check to confirm no SSDT buffer overflow
4021if ( (U8 *)(current) > (U8 *)end )
4022{
4023printf("Error: SSDT Buffer Length exceeded available space \n");
4024return(0);
4025}
4026
4027// (3.4.3) Create _PPC Method
4028DBG("Building _PPC Method\n");
4029current = buildPPC(current);
4030
4031// Check to confirm no SSDT buffer overflow
4032if ( (U8 *)(current) > (U8 *)end )
4033{
4034printf("Error: SSDT Buffer Length exceeded available space \n");
4035return(0);
4036}
4037
4038// (3.4.4) Create PSD with hardware coordination
4039{
4040DBG("Building _PSD Method\n");
4041U32 domain = madt_info.lapic[lapic_index].pkg_index;
4042
4043 // In this (bad?) implementation we use the nb of cpu found in the dsdt
4044U32 cpusInDomain = cpu_map_count;
4045current = buildPSD(current, domain, cpusInDomain, ACPI_COORD_TYPE);
4046}
4047
4048// Check to confirm no SSDT buffer overflow
4049if ( (U8 *)(current) > (U8 *)end )
4050{
4051printf("Error: SSDT Buffer Length exceeded available space \n");
4052return(0);
4053}
4054}
4055
4056// (3.5) Create C-state related structures
4057if (cstates_enabled == 1)
4058{
4059{
4060PKG_CSTATES * mwait_pkg_cstates = &cpu.pkg_mwait_cstates;
4061PKG_CSTATES * io_pkg_cstates = &cpu.pkg_io_cstates;
4062
4063// Build CST
4064DBG("Building _CST Method\n");
4065current = buildCST(current, mwait_pkg_cstates, io_pkg_cstates);
4066}
4067
4068#if BUILD_ACPI_CSD
4069 {
4070 // Use core_apic_id as domain
4071 U32 domain = lapic->core_apic_id;
4072
4073 // In this (bad?) implementation we use the nb of cpu found in the dsdt
4074 U32 cpusInDomain = cpu_map_count;
4075
4076 // Create CSD
4077 current = buildCSD(current, domain, cpusInDomain, io_pkg_cstates);
4078 }
4079#endif
4080
4081// Check to confirm no SSDT buffer overflow
4082if ( (U8 *)(current) > (U8 *)end )
4083{
4084printf("Error: SSDT Buffer Length exceeded available space \n");
4085return(0);
4086}
4087}
4088#if BUILD_ACPI_TSS
4089 // (3.6) Create T-state related structures
4090 if (tstates_enabled == 1)
4091 {
4092 // (3.6.1) Create _TPC Method
4093 current = buildTPC(current);
4094
4095 // (3.6.2) Create _PTC Method
4096 current = buildPTC(current);
4097
4098 // (3.6.3) Create _TSS Method
4099 {
4100 PKG_TSTATES * pkg_tstates = &cpu.pkg_tstates;
4101 current = buildTSS(current, pkg_tstates);
4102 }
4103
4104 // (3.6.4) Create _TSD Method
4105 {
4106 LAPIC_INFO * lapic = &madt_info.lapic[lapic_index];
4107
4108 // Use core_apic_id as domain
4109 U32 domain = lapic->core_apic_id;
4110
4111 // In this (bad?) implementation we use the nb of cpu found in the dsdt
4112 U32 cpusInDomain = cpu_map_count;
4113
4114 current = buildTSD(current, domain, cpusInDomain);
4115 }
4116 }
4117#endif
4118// (3.7) Update length in CPUn Scope
4119setPackageLength(&scope->pkgLength, (U8 *)current - (U8 *)&scope->pkgLength);
4120
4121} // End for
4122
4123// (4) Update length and checksum in SSDT Definition Block
4124{
4125DBG("Updating length and checksum in SSDT Definition Block\n");
4126
4127SsdtPointer->Header.Length = (U8 *)current - (U8 *)SsdtPointer;
4128SetChecksum(&SsdtPointer->Header);
4129}
4130
4131// Check to confirm no SSDT buffer overflow
4132if ( (U8 *)current > (U8 *)end )
4133{
4134printf("Error: SSDT Buffer Length exceeded available space \n");
4135return(0);
4136}
4137
4138} // End build SSDT
4139
4140} // SSDT
4141
4142return(1);
4143}
4144#endif
4145
4146#if UNUSED
4147static ACPI_TABLE_FACS* generate_facs(bool updatefacs )
4148{
4149 ACPI_TABLE_FACS* facs_mod=(ACPI_TABLE_FACS *)AllocateKernelMemory(sizeof(ACPI_TABLE_FACS));
4150if (!facs_mod)
4151{
4152printf("Unable to allocate kernel memory for facs mod\n");
4153return (void*)0ul;
4154}
4155 bzero(facs_mod, sizeof(ACPI_TABLE_FACS));
4156
4157ACPI_TABLE_FACS * FacsPointer =(acpi_tables.FacsPointer64 != (void *)0ul) ?
4158(ACPI_TABLE_FACS *)acpi_tables.FacsPointer64 : (ACPI_TABLE_FACS *)acpi_tables.FacsPointer;
4159
4160 memcpy(facs_mod, FacsPointer , FacsPointer->Length);
4161 facs_mod->Length = sizeof(ACPI_TABLE_FACS);
4162
4163if (FacsPointer->Length < sizeof(ACPI_TABLE_FACS))
4164{
4165facs_mod->FirmwareWakingVector = 0;
4166facs_mod->GlobalLock = 0;
4167facs_mod->Flags = 0;
4168}
4169
4170 if (updatefacs && FacsPointer->Version < 2)
4171{
4172if (FacsPointer->Version > 0)
4173{
4174facs_mod->XFirmwareWakingVector = FacsPointer->XFirmwareWakingVector;
4175}
4176else
4177{
4178facs_mod->XFirmwareWakingVector = (U64)facs_mod->FirmwareWakingVector;
4179}
4180
4181facs_mod->Version = 2; /* ACPI 1.0: 0, ACPI 2.0/3.0: 1, ACPI 4.0: 2 */
4182
4183}
4184
4185 return facs_mod;
4186}
4187#endif
4188
4189static ACPI_GENERIC_ADDRESS FillGASStruct(U32 Address, U8 Length)
4190{
4191ACPI_GENERIC_ADDRESS TmpGAS;
4192
4193TmpGAS.SpaceId = 1; /* I/O Address */
4194
4195if (Address == 0)
4196{
4197TmpGAS.BitWidth = 0;
4198}
4199else
4200{
4201TmpGAS.BitWidth = Length * 8;
4202}
4203
4204TmpGAS.BitOffset = 0;
4205TmpGAS.AccessWidth = 0; /* Not set for Legacy reasons... */
4206TmpGAS.Address = (U64)Address;
4207
4208return (TmpGAS);
4209}
4210
4211static ACPI_TABLE_FADT *
4212patch_fadt(ACPI_TABLE_FADT *fadt, ACPI_TABLE_DSDT *new_dsdt, bool UpdateFADT)
4213{
4214ACPI_TABLE_FADT *fadt_mod = (void*)0;
4215bool fadt_rev2_needed = false;
4216bool fix_restart = false;
4217const char * value;
4218
4219// Restart Fix
4220if (Platform->CPU.Vendor == 0x756E6547) /* Intel */
4221{
4222fix_restart = true;
4223getBoolForKey(kRestartFix, &fix_restart, &bootInfo->bootConfig);
4224
4225} else {
4226verbose ("Not an Intel platform: Restart Fix disabled !!!\n");
4227}
4228
4229if (fix_restart)
4230fadt_rev2_needed = true;
4231
4232// Allocate new fadt table
4233if (UpdateFADT)
4234{
4235 if (fadt->Header.Length < 0xF4)
4236 {
4237 fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(0xF4);
4238 if (!fadt_mod)
4239 {
4240 printf("Unable to allocate kernel memory for fadt mod\n");
4241 return (void*)0ul;
4242 }
4243 bzero(fadt_mod, 0xF4);
4244 memcpy(fadt_mod, fadt, fadt->Header.Length);
4245 fadt_mod->Header.Length = 0xF4;
4246
4247}
4248else
4249{
4250fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(fadt->Header.Length);
4251if (!fadt_mod)
4252{
4253printf("Unable to allocate kernel memory for fadt mod\n");
4254return (void*)0ul;
4255}
4256memcpy(fadt_mod, fadt, fadt->Header.Length);
4257}
4258
4259
4260//fadt_mod->Header.Revision = 0x04; // FADT rev 4
4261fadt_mod->ResetRegister = FillGASStruct(0, 0);
4262fadt_mod->ResetValue = 0;
4263fadt_mod->Reserved4[0] = 0;
4264fadt_mod->Reserved4[1] = 0;
4265fadt_mod->Reserved4[2] = 0;
4266
4267 fadt_mod->XPm1aEventBlock = FillGASStruct(fadt_mod->Pm1aEventBlock, fadt_mod->Pm1EventLength);
4268fadt_mod->XPm1bEventBlock = FillGASStruct(fadt_mod->Pm1bEventBlock, fadt_mod->Pm1EventLength);
4269fadt_mod->XPm1aControlBlock = FillGASStruct(fadt_mod->Pm1aControlBlock, fadt_mod->Pm1ControlLength);
4270fadt_mod->XPm1bControlBlock = FillGASStruct(fadt_mod->Pm1bControlBlock, fadt_mod->Pm1ControlLength);
4271fadt_mod->XPm2ControlBlock = FillGASStruct(fadt_mod->Pm2ControlBlock, fadt_mod->Pm2ControlLength);
4272fadt_mod->XPmTimerBlock = FillGASStruct(fadt_mod->PmTimerBlock, fadt_mod->PmTimerLength);
4273fadt_mod->XGpe0Block = FillGASStruct(fadt_mod->Gpe0Block, fadt_mod->Gpe0BlockLength);
4274fadt_mod->XGpe1Block = FillGASStruct(fadt_mod->Gpe1Block, fadt_mod->Gpe1BlockLength);
4275 if (fadt->Header.Revision < 4)
4276{
4277fadt_mod->Header.Revision = 0x04; // FADT rev 4
4278verbose("Converted ACPI V%d FADT to ACPI V4 FADT\n", fadt->Header.Revision);
4279
4280}
4281}
4282else
4283{
4284
4285if (fadt_rev2_needed)
4286{
4287if (fadt->Header.Length < 0x84 )
4288{
4289fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(0x84);
4290if (!fadt_mod)
4291{
4292printf("Unable to allocate kernel memory for fadt mod\n");
4293return (void*)0ul;
4294}
4295bzero(fadt_mod, 0x84);
4296memcpy(fadt_mod, fadt, fadt->Header.Length);
4297fadt_mod->Header.Length = 0x84;
4298}
4299else
4300{
4301fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(fadt->Header.Length);
4302if (!fadt_mod)
4303{
4304printf("Unable to allocate kernel memory for fadt mod\n");
4305return (void*)0ul;
4306}
4307memcpy(fadt_mod, fadt, fadt->Header.Length);
4308}
4309
4310if (fadt->Header.Revision < 2)
4311{
4312fadt_mod->Header.Revision = 0x02; // FADT rev 2 (ACPI 1.0B MS extensions)
4313verbose("Converted ACPI V%d FADT to ACPI V2 FADT\n", fadt->Header.Revision );
4314}
4315}
4316else
4317{
4318if (fadt->Header.Length < 0x74 )
4319{
4320fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(0x74);
4321if (!fadt_mod)
4322{
4323printf("Unable to allocate kernel memory for fadt mod\n");
4324return (void*)0ul;
4325}
4326bzero(fadt_mod, 0x74);
4327memcpy(fadt_mod, fadt, fadt->Header.Length);
4328fadt_mod->Header.Length = 0x74;
4329fadt_mod->Header.Revision = 0x01;
4330verbose("Warning: ACPI FADT length was < 0x74 which is the minimum for the ACPI FADT V1 specification, \n", fadt->Header.Revision );
4331verbose(" trying to convert it to Version 1. \n");
4332
4333}
4334else
4335{
4336fadt_mod=(ACPI_TABLE_FADT *)AllocateKernelMemory(fadt->Header.Length);
4337if (!fadt_mod)
4338{
4339printf("Unable to allocate kernel memory for fadt mod\n");
4340return (void*)0ul;
4341}
4342memcpy(fadt_mod, fadt, fadt->Header.Length);
4343}
4344}
4345}
4346bool intelfadtspec = true;
4347U8 Type = PMProfileError;
4348// Determine system type / PM_Model
4349
4350// Fix System-type if needed (should never happen)
4351if (Platform->Type > MaxSupportedPMProfile)
4352{
4353if(fadt_mod->PreferredProfile <= MaxSupportedPMProfile)
4354Platform->Type = fadt_mod->PreferredProfile; // get the fadt if correct
4355else
4356Platform->Type = 1;/* Set a fixed value (Desktop) */
4357}
4358
4359// If needed, set System-type from PM_Profile (if valid) else set PM_Profile with a fixed the System-type
4360// Give prior to the FADT pm profile, allow to also control this value with a patched FADT table
4361if (fadt_mod->PreferredProfile != Platform->Type)
4362{
4363bool val = false;
4364getBoolForKey("PreferInternalProfileDetect", &val, &bootInfo->bootConfig); // if true Give prior to the profile resolved trought the CPU model
4365
4366val = Platform->CPU.isServer ;
4367
4368if (fadt_mod->PreferredProfile <= MaxSupportedPMProfile && !val)
4369{
4370Platform->Type = fadt_mod->PreferredProfile;
4371}
4372else
4373{
4374fadt_mod->PreferredProfile = Platform->Type;
4375}
4376
4377}
4378
4379// Set PM_Profile and System-type if user wanted this value to be forced
4380if ( (value=getStringForKey("SystemType", &bootInfo->bootConfig))!=NULL)
4381{
4382if ((Type = (unsigned char) strtoul(value, NULL, 10) ) <= MaxSupportedPMProfile)
4383{
4384if (fadt_mod->PreferredProfile != Type)
4385{
4386verbose("FADT: changing Preferred_PM_Profile from %d to %d\n", fadt->PreferredProfile, Type);
4387fadt_mod->PreferredProfile = Platform->Type = Type;
4388}
4389else
4390{
4391DBG("FADT: Preferred_PM_Profile was already set to %d, no need to be changed\n",Type);
4392}
4393
4394} else printf("Error: system-type must be 0..6. Defaulting to %d !\n", Platform->Type);
4395}
4396
4397getBoolForKey(KIntelFADT, &intelfadtspec, &bootInfo->bootConfig);
4398if ((pmbase == 0) && (cpu_map_error == 0) && (intelfadtspec == true))
4399{
4400ACPI_TABLE_DSDT *DsdtPointer ;
4401if (new_dsdt != (void*)0ul)
4402DsdtPointer = new_dsdt;
4403else if ((fadt_mod->Header.Revision >= 3) && (fadt_mod->XDsdt != 0ul))
4404DsdtPointer = (ACPI_TABLE_DSDT *)((U32)fadt_mod->XDsdt);
4405else
4406DsdtPointer = (ACPI_TABLE_DSDT *)fadt_mod->Dsdt;
4407
4408generate_cpu_map_from_acpi(DsdtPointer);
4409}
4410
4411// Patch DSDT Address if we have loaded a DSDT table
4412if(new_dsdt != (void*)0ul)
4413fadt_mod->Dsdt=(U32)new_dsdt;
4414
4415fadt_mod->Facs= fadt->Facs;
4416//fadt_mod->Facs=(U32)generate_facs(false);
4417
4418// Patch FADT to fix restart
4419if (fadt_mod->Header.Revision >= 2 && fix_restart)
4420{
4421 fadt_mod->Flags|= 0x400;
4422
4423int type = PCI_RESET_TYPE;
4424getIntForKey(KResetType, &type, &bootInfo->bootConfig);
4425if (type == KEYBOARD_RESET_TYPE)
4426{
4427//Azi: keyboard reset; http://forum.voodooprojects.org/index.php/topic,1056.msg9802.html#msg9802
4428fadt_mod->ResetRegister = FillGASStruct(0x64, 1);
4429fadt_mod->ResetValue = 0xfe;
4430}
4431else
4432{
4433fadt_mod->ResetRegister = FillGASStruct(0x0cf9, 1);
4434fadt_mod->ResetValue = 0x06;
4435}
4436verbose("FADT: Restart Fix applied (Type : %s) !\n", (type == 0) ? "PCI": "KEYBOARD");
4437}
4438
4439 if (fadt_mod->Header.Revision >= 3)
4440{
4441
4442
4443 if (UpdateFADT)
4444{
4445
4446//fadt_mod->XFacs= (U64)((U32)generate_facs(true));
4447 fadt_mod->XFacs=(U64)fadt->Facs;
4448
4449 }
4450else
4451{
4452fadt_mod->XFacs=(U64)fadt->XFacs;
4453}
4454
4455
4456 if(new_dsdt != (void*)0ul)
4457 fadt_mod->XDsdt=((U64)(U32)new_dsdt);
4458else if (UpdateFADT)
4459fadt_mod->XDsdt=(U64)fadt_mod->Dsdt;
4460
4461
4462 Platform->hardware_signature = ((ACPI_TABLE_FACS *)((U32)fadt_mod->XFacs))->HardwareSignature;
4463
4464 }
4465else
4466{
4467
4468 Platform->hardware_signature = ((ACPI_TABLE_FACS *)fadt_mod->Facs)->HardwareSignature;
4469
4470 }
4471
4472
4473DBG("setting hardware_signature to %x \n",Platform->hardware_signature);
4474
4475
4476
4477if (pmbase && (intelfadtspec == true))
4478ProcessFadt(fadt_mod, pmbase); // The checksum correction will be done by ProcessFadt
4479else
4480SetChecksum(&fadt_mod->Header); // Correct the checksum
4481
4482return fadt_mod;
4483}
4484
4485static U32 process_xsdt (ACPI_TABLE_RSDP *rsdp_mod , U32 *new_table_list)
4486{
4487TagPtr DropTables_p = XMLCastDict(XMLGetProperty(bootInfo->bootConfig.dictionary, (const char*)"ACPIDropTables"));
4488U32 new_table = 0ul;
4489U8 new_table_index = 0, table_added = 0;
4490ACPI_TABLE_XSDT *xsdt = (void*)0ul, *xsdt_mod = (void*)0ul;
4491ACPI_TABLE_RSDT *rsdt_conv= (void *)0ul;
4492
4493// FIXME: handle 64-bit address correctly
4494
4495xsdt=(ACPI_TABLE_XSDT *)acpi_tables.XsdtPointer;
4496
4497verbose("* Processing XSDT: \n");
4498
4499DBG(" XSDT @%x, Length=%d\n", (U32)xsdt,
4500xsdt->Header.Length);
4501
4502if (xsdt != (void *)0ul)
4503{
4504U32 dropoffset=0, index;
4505table_added = 0;
4506
4507xsdt_mod=(ACPI_TABLE_XSDT *)AllocateKernelMemory(xsdt->Header.Length);
4508if (!xsdt_mod)
4509{
4510printf("Unable to allocate kernel memory for xsdt mod\n");
4511return (0);
4512}
4513bzero(xsdt_mod, xsdt->Header.Length);
4514memcpy(&xsdt_mod->Header, &xsdt->Header, sizeof(ACPI_TABLE_HEADER));
4515
4516U32 num_tables=get_num_tables64(xsdt);
4517
4518for (index = 0; index < num_tables; index++)
4519{
4520
4521U64 ptr = xsdt->TableOffsetEntry[index];
4522
4523{
4524if (ptr > ULONG_MAX_32)
4525{
4526#if DEBUG_ACPI
4527printf("Warning xsdt->TableOffsetEntry[%d]: Beyond addressable memory in this CPU mode, ignored !!!\n",index);
4528#endif
4529continue;
4530}
4531
4532bool unsafe = false;
4533getBoolForKey(kUnsafeACPI, &unsafe, &bootInfo->bootConfig);
4534
4535if (!unsafe)
4536{
4537if (GetChecksum(((ACPI_TABLE_HEADER *) (unsigned long)ptr),
4538((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Length) != 0)
4539{
4540#if DEBUG_ACPI
4541printf("Warning xsdt->TableOffsetEntry[%d]: Invalide checksum, ignored !!!\n",index);
4542#endif
4543continue;
4544}
4545}
4546
4547}
4548
4549xsdt_mod->TableOffsetEntry[index-dropoffset]=ptr;
4550
4551char tableSig[4];
4552
4553strlcpy(tableSig, (char*)((U32)ptr), sizeof(tableSig)+1);
4554
4555DBG("** Processing %s,", tableSig );
4556
4557DBG(" @%x, Length=%d\n", (U32)ptr,
4558((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Length);
4559
4560{
4561bool oem = false;
4562char oemOption[OEMOPT_SIZE];
4563sprintf(oemOption, "oem%s",tableSig );
4564if (getBoolForKey(oemOption, &oem, &bootInfo->bootConfig) && oem) // This method don't work for DSDT and FACS
4565{
4566
4567DBG(" %s required\n", oemOption);
4568
4569if (get_new_table_in_list(new_table_list,(*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature), &new_table_index) != (void*)0ul)
4570new_table_list[new_table_index] = 0ul; // This way new table will not be added to the new rsdt list !!
4571
4572continue;
4573}
4574}
4575
4576{
4577TagPtr match_drop = XMLGetProperty(DropTables_p, (const char*)tableSig);
4578if ( match_drop )
4579{
4580char *tmp = XMLCastString(match_drop);
4581if (strcmp(tmp,"No") != 0)
4582{
4583dropoffset++;
4584DBG(" %s table dropped\n",tableSig);
4585continue;
4586}
4587}
4588}
4589
4590{
4591if ((new_table = (U32)get_new_table_in_list(new_table_list,(*(U32 *) ((ACPI_TABLE_HEADER *) (unsigned long)ptr)->Signature), &new_table_index)) != 0ul)
4592{
4593DBG(" Found replacement for table %s\n",tableSig);
4594xsdt_mod->TableOffsetEntry[index-dropoffset]=(U64)new_table;
4595new_table_list[new_table_index] = 0ul; // table replaced !!
4596continue;
4597}
4598}
4599
4600}
4601
4602
4603{
4604U8 i;
4605for (i = 0; i< (MAX_ACPI_TABLE + RESERVED_AERA); i++)
4606{
4607if (new_table_list[i] != 0ul)
4608{
4609#if DEBUG_ACPI
4610ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;
4611printf("Adding table : ");
4612print_nameseg(*(U32 *) (table_array[i]->Signature));
4613printf("\n");
4614#endif
4615xsdt_mod->TableOffsetEntry[index-dropoffset]=(U64)new_table_list[i];
4616table_added++;
4617index++;
4618}
4619}
4620}
4621
4622// Correct the checksum of XSDT
4623xsdt_mod->Header.Length-=8*dropoffset;
4624xsdt_mod->Header.Length+=8*table_added;
4625
4626SetChecksum(&xsdt_mod->Header);
4627
4628update_rsdp_with_xsdt(rsdp_mod, xsdt_mod);
4629
4630verbose("* Creating new RSDT from XSDT table\n");
4631
4632rsdt_conv = (ACPI_TABLE_RSDT *)gen_alloc_rsdt_from_xsdt(xsdt_mod);
4633
4634if (rsdt_conv != (void*)0ul)
4635{
4636#if DEBUG_ACPI
4637DBG("Attempting to update RSDP with RSDT \n");
4638{
4639U32 ret = update_rsdp_with_rsdt(rsdp_mod, rsdt_conv);
4640if (ret)
4641DBG("RSDP update with RSDT successfully !!! \n");
4642}
4643#else
4644update_rsdp_with_rsdt(rsdp_mod, rsdt_conv);
4645#endif
4646}
4647
4648}
4649else
4650{
4651DBG("About to drop XSDT\n");
4652
4653/*FIXME: Now we just hope that if MacOS doesn't find XSDT it reverts to RSDT.
4654 * A Better strategy would be to generate
4655 */
4656
4657rsdp_mod->XsdtPhysicalAddress=0xffffffffffffffffLL;
4658verbose("XSDT not found or XSDT incorrect\n");
4659}
4660return (1);
4661
4662}
4663
4664static U32 process_rsdt(ACPI_TABLE_RSDP *rsdp_mod , bool gen_xsdt, U32 *new_table_list)
4665{
4666TagPtr DropTables_p = XMLCastDict(XMLGetProperty(bootInfo->bootConfig.dictionary, (const char*)"ACPIDropTables"));
4667U32 new_table = 0ul;
4668U8 new_table_index = 0, table_added = 0;
4669U32 dropoffset=0, index;
4670ACPI_TABLE_RSDT *rsdt = (void *)0ul, *rsdt_mod= (void *)0ul;
4671ACPI_TABLE_XSDT *xsdt_conv = (void *)0ul;
4672
4673rsdt=(ACPI_TABLE_RSDT *)acpi_tables.RsdtPointer;
4674
4675rsdt_mod=(ACPI_TABLE_RSDT *)AllocateKernelMemory(rsdt->Header.Length);
4676
4677if (!rsdt_mod)
4678{
4679printf("Unable to allocate kernel memory for rsdt mod\n");
4680return (0);
4681}
4682
4683bzero(rsdt_mod, rsdt->Header.Length);
4684memcpy (&rsdt_mod->Header, &rsdt->Header, sizeof(ACPI_TABLE_HEADER));
4685
4686U32 num_tables = get_num_tables(rsdt);
4687
4688verbose("* Processing RSDT: \n");
4689
4690DBG(" RSDT @%x, Length %d\n",rsdt, rsdt->Header.Length);
4691
4692ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) rsdt->TableOffsetEntry;
4693
4694// Compute number of table pointers included in RSDT
4695num_tables = get_num_tables(rsdt);
4696
4697for (index = 0; index < num_tables; index++)
4698{
4699
4700{
4701
4702bool unsafe = false;
4703getBoolForKey(kUnsafeACPI, &unsafe, &bootInfo->bootConfig);
4704
4705if (!unsafe)
4706{
4707if (GetChecksum(table_array[index], table_array[index]->Length) != 0)
4708{
4709#if DEBUG_ACPI
4710printf("Warning rsdt->TableOffsetEntry[%d]: Invalide checksum, ignored !!!\n",index);
4711#endif
4712continue;
4713}
4714}
4715
4716}
4717
4718rsdt_mod->TableOffsetEntry[index-dropoffset]=rsdt->TableOffsetEntry[index];
4719
4720char tableSig[4];
4721
4722strlcpy(tableSig, (char*)(rsdt->TableOffsetEntry[index]), sizeof(tableSig)+1);
4723
4724DBG("** Processing %s,", tableSig );
4725
4726DBG(" @%x, Length=%d\n", (U32)table_array[index],
4727table_array[index]->Length);
4728
4729{
4730bool oem = false;
4731char oemOption[OEMOPT_SIZE];
4732sprintf(oemOption, "oem%s",tableSig );
4733if (getBoolForKey(oemOption, &oem, &bootInfo->bootConfig) && oem) // This method don't work for DSDT and FACS
4734{
4735DBG(" %s required\n", oemOption);
4736
4737if (get_new_table_in_list(new_table_list,(*(U32 *) (table_array[index]->Signature)), &new_table_index) != (void*)0ul )
4738new_table_list[new_table_index] = 0ul; // This way new table will not be added to the new rsdt list !!
4739
4740continue;
4741}
4742}
4743
4744{
4745TagPtr match_drop = XMLGetProperty(DropTables_p, (const char*)tableSig);
4746if ( match_drop )
4747{
4748char *tmp = XMLCastString(match_drop);
4749if (strcmp(tmp,"No") != 0)
4750{
4751dropoffset++;
4752DBG(" %s table dropped\n",tableSig);
4753continue;
4754}
4755}
4756}
4757
4758{
4759if ((new_table = (U32)get_new_table_in_list(new_table_list,(*(U32 *) (table_array[index]->Signature)), &new_table_index)) != 0ul)
4760{
4761DBG(" Found replacement for table %s\n",tableSig);
4762
4763rsdt_mod->TableOffsetEntry[index-dropoffset]=new_table;
4764new_table_list[new_table_index] = 0ul; // table replaced !!
4765continue;
4766}
4767}
4768//}
4769}
4770DBG("\n");
4771
4772{
4773U8 i;
4774for (i = 0; i< (MAX_ACPI_TABLE + RESERVED_AERA); i++)
4775{
4776if (new_table_list[i] != 0ul)
4777{
4778#if DEBUG_ACPI
4779ACPI_TABLE_HEADER **table_array = (ACPI_TABLE_HEADER **) new_table_list;
4780printf("Adding table : ");
4781print_nameseg(*(U32 *) (table_array[i]->Signature));
4782printf("\n");
4783#endif
4784rsdt_mod->TableOffsetEntry[index-dropoffset]=new_table_list[i];
4785table_added++;
4786index++;
4787}
4788}
4789}
4790
4791// Correct the checksum of RSDT
4792rsdt_mod->Header.Length-=4*dropoffset;
4793rsdt_mod->Header.Length+=4*table_added;
4794
4795DBG("RSDT: Original checksum %d\n", rsdt_mod->Header.Checksum);
4796
4797SetChecksum(&rsdt_mod->Header);
4798
4799DBG("New checksum %d at %x\n", rsdt_mod->Header.Checksum,rsdt_mod);
4800
4801update_rsdp_with_rsdt(rsdp_mod, rsdt_mod);
4802
4803if (gen_xsdt)
4804{
4805verbose("* Creating new XSDT from RSDT table\n");
4806xsdt_conv = (ACPI_TABLE_XSDT *)gen_alloc_xsdt_from_rsdt(rsdt_mod);
4807
4808if (xsdt_conv != (void *)0ul )
4809{
4810#if DEBUG_ACPI
4811DBG("Attempting to update RSDP with XSDT \n");
4812{
4813U32 ret = update_rsdp_with_xsdt(rsdp_mod, xsdt_conv);
4814if (ret)
4815DBG("RSDP update with XSDT successfully !!! \n");
4816}
4817#else
4818update_rsdp_with_xsdt(rsdp_mod, xsdt_conv);
4819#endif
4820
4821}
4822
4823}
4824return (1);
4825}
4826
4827EFI_STATUS setupAcpi(void)
4828{
4829U8 Revision = 0;
4830
4831 cpu_map_error = 0;
4832 cpu_map_count = 0;
4833 pmbase = 0;
4834
4835 EFI_STATUS Status = EFI_ABORTED;
4836
4837U32 new_table_list[MAX_ACPI_TABLE + RESERVED_AERA]; //max table + reserved aera
4838U8 new_table_index = 0;
4839
4840ACPI_TABLE_DSDT* DsdtPtr = (void *)0ul; // a Pointer to the dsdt table present in fadt_mod
4841
4842ACPI_TABLE_DSDT *new_dsdt = (void *)0ul;// a Pointer to the dsdt file
4843ACPI_TABLE_FADT *fadt_mod = (void *)0ul; // a Pointer to the patched FACP table
4844ACPI_TABLE_FADT *fadt_file = (void *)0ul; // a Pointer to the (non-patched) fadt file
4845ACPI_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
4846ACPI_TABLE_RSDP *rsdp_mod = (void *)0ul, *rsdp_conv= (void *)0ul;
4847
4848
4849U32 rsdplength;
4850
4851bool update_acpi=false, gen_xsdt=false;
4852
4853bool gen_csta=false, gen_psta=false, speed_step=false;
4854#if !OLD_SSDT
4855bool gen_ssdt=false; // will force to generate ssdt even if gen_csta and gen_psta = false
4856 bool gen_tsta=false;
4857#endif
4858bool oem_dsdt=false, oem_fadt=false;
4859
4860// Find original rsdp
4861if (!FindAcpiTables(&acpi_tables))
4862{
4863printf("Error: AcpiCodec Failed to detect ACPI tables.\n");
4864getc();
4865return EFI_NOT_FOUND;
4866}
4867
4868{
4869U8 i;
4870
4871for (i=0; i<(MAX_ACPI_TABLE + RESERVED_AERA); i++)
4872{
4873new_table_list[i] = 0ul;
4874}
4875bool tmpval;
4876
4877oem_dsdt=getBoolForKey(kOEMDSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
4878oem_fadt=getBoolForKey(kOEMFADT, &tmpval, &bootInfo->bootConfig)&&tmpval;
4879
4880
4881gen_csta=getBoolForKey(kGenerateCStates, &tmpval, &bootInfo->bootConfig)&&tmpval;
4882gen_psta=getBoolForKey(kGeneratePStates, &tmpval, &bootInfo->bootConfig)&&tmpval;
4883#if !OLD_SSDT
4884gen_ssdt=getBoolForKey(KForceSSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
4885#endif
4886update_acpi=getBoolForKey(kUpdateACPI, &tmpval, &bootInfo->bootConfig)&&tmpval;
4887
4888speed_step=getBoolForKey(kSpeedstep, &tmpval, &bootInfo->bootConfig)&&tmpval;
4889#if !OLD_SSDT
4890turbo_enabled=(U32)getBoolForKey(kCoreTurbo, &tmpval, &bootInfo->bootConfig)&&tmpval;
4891#endif
4892#if BUILD_ACPI_TSS
4893gen_tsta=(U32)getBoolForKey(kGenerateTStates, &tmpval, &bootInfo->bootConfig)&&tmpval;
4894#endif
4895}
4896
4897{
4898char* name;
4899long flags;
4900long time;
4901long ret = -1;
4902U8 i = 0;
4903char dirspec[512];
4904bool acpidir_found = false;
4905
4906ret = GetFileInfo("rd(0,0)/Extra/", "Acpi", &flags, &time);
4907 if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory))
4908{
4909 sprintf(dirspec, "rd(0,0)/Extra/Acpi/");
4910 acpidir_found = true;
4911
4912 }
4913else
4914{
4915
4916 ret = GetFileInfo("/Extra/", "Acpi", &flags, &time);
4917 if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory))
4918{
4919 sprintf(dirspec, "/Extra/Acpi/");
4920 acpidir_found = true;
4921
4922 }
4923else
4924{
4925 ret = GetFileInfo("bt(0,0)/Extra/", "Acpi", &flags, &time);
4926 if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory))
4927{
4928 sprintf(dirspec, "bt(0,0)/Extra/Acpi/");
4929 acpidir_found = true;
4930
4931 }
4932 }
4933 }
4934
4935if (acpidir_found == true)
4936{
4937struct dirstuff* moduleDir = opendir(dirspec);
4938while(readdir(moduleDir, (const char**)&name, &flags, &time) >= 0)
4939{
4940if((strcmp(&name[strlen(name) - sizeof("aml")], ".aml") == 0) && ((strlen(dirspec)+strlen(name)) < 512))
4941{
4942// Some simple verifications to save time in case of those tables simply named as follow:
4943if ((strncmp(name, "RSDT", 4) == 0) || (strncmp(name, "rsdt", 4) == 0) ||
4944(strncmp(name, "XSDT", 4) == 0) || (strncmp(name, "xsdt", 4) == 0) ||
4945(strncmp(name, "RSDP", 4) == 0) || (strncmp(name, "rsdp", 4) == 0))
4946{
4947continue;
4948}
4949
4950if ((strncmp(name, "FACS", 4) == 0) || (strncmp(name, "facs", 4) == 0)) // FACS is not supported
4951{
4952continue;
4953}
4954
4955DBG("* Attempting to load acpi table: %s\n", name);
4956if ( (new_table_list[i]=(U32)loadACPITable(dirspec,name)))
4957{
4958if (i < MAX_ACPI_TABLE)
4959{
4960i++;
4961}
4962else
4963{
4964break;
4965}
4966}
4967
4968}
4969#if DEBUG_ACPI
4970else
4971{
4972DBG("Ignoring %s\n", name);
4973}
4974#endif
4975
4976}
4977
4978if (i)
4979{
4980//sanitize the new tables list
4981sanitize_new_table_list(new_table_list);
4982
4983//move to kernel memory
4984move_table_list_to_kmem(new_table_list);
4985
4986DBG("New ACPI tables Loaded in memory\n");
4987}
4988}
4989
4990}
4991
4992if (speed_step)
4993{
4994gen_psta= true;
4995gen_csta= true;
4996}
4997
4998
4999ACPI_TABLE_RSDP *rsdp=(ACPI_TABLE_RSDP *)acpi_tables.RsdPointer;
5000
5001if (rsdp == (void*)0ul || (GetChecksum(rsdp, (rsdp->Revision == 0) ? ACPI_RSDP_REV0_SIZE:sizeof(ACPI_TABLE_RSDP)) != 0) )
5002{
5003printf("Error : ACPI RSD PTR Revision %d checksum is incorrect or table not found \n",rsdp->Revision );
5004return EFI_UNSUPPORTED;
5005}
5006
5007if ((update_acpi) && (rsdp->Revision == 0))
5008{
5009
5010rsdp_conv = (ACPI_TABLE_RSDP *)gen_alloc_rsdp_v2_from_v1(rsdp);
5011if (rsdp_conv != (void *)0ul)
5012{
5013gen_xsdt = true;
5014rsdp = rsdp_conv;
5015verbose("Converted ACPI RSD PTR Revision 0 to Revision 2\n");
5016}
5017
5018}
5019
5020Revision = rsdp->Revision ;
5021rsdplength=(Revision == 2)?rsdp->Length:ACPI_RSDP_REV0_SIZE;
5022
5023DBG("RSDP Revision %d found @%x. Length=%d\n",Revision,rsdp,rsdplength);
5024
5025if (gen_xsdt)
5026{
5027rsdp_mod=rsdp_conv;
5028}
5029else
5030{
5031rsdp_mod=(ACPI_TABLE_RSDP *) AllocateKernelMemory(rsdplength);
5032
5033if (!rsdp_mod) return EFI_OUT_OF_RESOURCES;
5034
5035memcpy(rsdp_mod, rsdp, rsdplength);
5036}
5037
5038
5039if ((fadt_file = (ACPI_TABLE_FADT *)get_new_table_in_list(new_table_list, NAMESEG("FACP"), &new_table_index)) != (void *)0ul)
5040{
5041
5042if (oem_fadt == false)
5043FacpPointer = (ACPI_TABLE_FADT *)fadt_file;
5044
5045new_table_list[new_table_index] = 0ul; // This way, the non-patched table will not be added in our new rsdt/xsdt table list
5046
5047} else
5048FacpPointer = (acpi_tables.FacpPointer64 != (void *)0ul) ?
5049(ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer;
5050
5051#if DEBUG_ACPI
5052if ((FacpPointer != (void *)0ul) || (oem_fadt == false))
5053{
5054printf("FADT found @%x, Length %d\n",FacpPointer, FacpPointer->Header.Length);
5055printf("Attempting to patch FADT entry of %s\n",(acpi_tables.FacpPointer64 != (void *)0ul) ? ACPI_SIG_XSDT : ACPI_SIG_RSDT);
5056}
5057else if (oem_fadt == true)
5058{
5059ACPI_TABLE_FADT * FacpPtr = (acpi_tables.FacpPointer64 != (void *)0ul) ?
5060(ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer;
5061
5062printf("FADT found @%x ( Length %d ) in %s \n",FacpPtr, FacpPtr->Header.Length, (acpi_tables.FacpPointer64 != (void *)0ul) ? ACPI_SIG_XSDT : ACPI_SIG_RSDT);
5063}
5064#endif
5065
5066if ((new_dsdt = (ACPI_TABLE_DSDT *)get_new_table_in_list(new_table_list, NAMESEG("DSDT"), &new_table_index)) != (void*)0ul )
5067{
5068new_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
5069}
5070
5071if (oem_fadt == false)
5072{
5073
5074fadt_mod = patch_fadt(FacpPointer, (oem_dsdt == false) ? new_dsdt : (void*)0ul , (acpi_tables.FacpPointer64 != (void *)0ul ));
5075
5076if (fadt_mod != (void*)0ul)
5077{
5078DsdtPtr = ((fadt_mod->Header.Revision >= 3) && (fadt_mod->XDsdt != 0)) ? (ACPI_TABLE_DSDT*)((U32)fadt_mod->XDsdt):(ACPI_TABLE_DSDT*)fadt_mod->Dsdt;
5079
5080U8 empty = get_0ul_index_in_list(new_table_list,true);
5081if (empty != ACPI_TABLE_LIST_FULL)
5082{
5083new_table_list[empty] = (U32)fadt_mod; // add the patched table to the list
5084}
5085else
5086{
5087printf("Error: not enought reserved space in the new acpi list for the Patched FACP table,\n ");
5088printf(" please increase the RESERVED_AERA\n");
5089}
5090
5091}
5092else
5093{
5094printf("Error: Failed to patch the FADT Table, trying fallback to the FADT original pointer\n");
5095fadt_mod = (acpi_tables.FacpPointer64 != (void *)0ul) ?
5096(ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer;
5097
5098DsdtPtr = ((fadt_mod->Header.Revision >= 3) && (fadt_mod->XDsdt != 0)) ? (ACPI_TABLE_DSDT*)((U32)fadt_mod->XDsdt):(ACPI_TABLE_DSDT*)fadt_mod->Dsdt;
5099
5100U8 empty = get_0ul_index_in_list(new_table_list,true);
5101if (empty != ACPI_TABLE_LIST_FULL)
5102{
5103new_table_list[empty] = (U32)fadt_mod;
5104}
5105else
5106{
5107printf("Error: not enought reserved space in the new acpi list for the FACP table,\n ");
5108printf(" please increase the RESERVED_AERA\n");
5109}
5110}
5111
5112if (oem_dsdt == false)
5113{
5114if (generate_cpu_map_from_acpi(DsdtPtr) == 0)
5115{
5116U8 new_uid = (U8)getPciRootUID();
5117
5118/* WARNING: THIS METHOD WORK PERFECTLY BUT IT CAN RESULT TO AN INCORRECT CHECKSUM */
5119
5120if (ProcessDsdt(DsdtPtr, UIDPointer, new_uid))
5121{
5122printf("PCI0 _UID patched to %d in the DSDT table\n", new_uid);
5123}
5124
5125}
5126}
5127
5128
5129}
5130else
5131{
5132
5133// here we use the variable fadt_mod only for SSDT Generation
5134
5135fadt_mod = (acpi_tables.FacpPointer64 != (void *)0ul) ?
5136(ACPI_TABLE_FADT *)acpi_tables.FacpPointer64 : (ACPI_TABLE_FADT *)acpi_tables.FacpPointer;
5137
5138DsdtPtr = ((fadt_mod->Header.Revision >= 3) && (fadt_mod->XDsdt != 0)) ? (ACPI_TABLE_DSDT*)((U32)fadt_mod->XDsdt)
5139:(ACPI_TABLE_DSDT*)fadt_mod->Dsdt;
5140}
5141#if OLD_SSDT
5142if (get_needed_symbols())
5143{
5144if (speed_step || gen_csta || gen_psta)
5145{
5146U8 empty = get_0ul_index_in_list(new_table_list, true);
5147
5148// Generate _CST SSDT
5149if ( speed_step || gen_csta)
5150{
5151if (empty != ACPI_TABLE_LIST_FULL)
5152{
5153if (new_table_list[empty] =(U32)generate_cst_ssdt(fadt_mod))
5154{
5155if (speed_step || gen_psta)
5156empty = get_0ul_index_in_list(new_table_list,true);
5157}
5158}
5159else
5160{
5161printf("Error: not enought reserved space in the new acpi list for the _CST SSDT table,\n ");
5162printf(" please increase the RESERVED_AERA\n");
5163}
5164}
5165
5166
5167// Generating _PSS SSDT
5168if (speed_step || gen_psta)
5169{
5170if (empty != ACPI_TABLE_LIST_FULL)
5171{
5172
5173new_table_list[empty] =(U32)generate_pss_ssdt(DsdtPtr);
5174
5175}
5176else
5177{
5178printf("Error: not enought reserved space in the new acpi list for the _PSS SSDT table,\n ");
5179printf(" please increase the RESERVED_AERA\n");
5180}
5181}
5182}
5183}
5184#else
5185if (gen_ssdt || gen_csta || gen_psta || gen_tsta)
5186{
5187ProcessSsdt(new_table_list, DsdtPtr, gen_csta, gen_psta, gen_tsta );
5188}
5189#endif
5190
5191if ((rsdp_mod != (void *)0ul) && (rsdp_mod->Length >= ACPI_RSDP_REV0_SIZE) )
5192{
5193if ((rsdp_mod->Revision == 0) || (gen_xsdt == true))
5194{
5195process_rsdt(rsdp_mod, gen_xsdt, new_table_list);
5196goto out;
5197}
5198
5199}
5200else
5201{
5202printf("Error: Incorect ACPI RSD PTR or not found \n");
5203return EFI_UNSUPPORTED;
5204}
5205
5206if ((GetChecksum(rsdp_mod, sizeof(ACPI_TABLE_RSDP)) == 0) &&
5207(Revision == 2) &&
5208(rsdplength == sizeof(ACPI_TABLE_RSDP)))
5209{
5210process_xsdt(rsdp_mod, new_table_list);
5211
5212}
5213else
5214{
5215printf("Warning : ACPI RSD PTR Revision 2 is incorrect, \n");
5216printf(" trying to fallback to Revision 1\n");
5217if ((rsdp_mod != (void *)0ul) && (rsdp_mod->Length >= ACPI_RSDP_REV0_SIZE) )
5218{
5219process_rsdt(rsdp_mod, false, new_table_list);
5220
5221}
5222else
5223{
5224printf("Error: Incorect ACPI RSD PTR or not found \n");
5225return EFI_UNSUPPORTED;
5226}
5227}
5228
5229out:
5230// Correct the checksum of RSDP
5231
5232DBG("RSDP: Original checksum %d\n", rsdp_mod->Checksum);
5233
5234setRsdpchecksum(rsdp_mod);
5235
5236DBG("New checksum %d\n", rsdp_mod->Checksum);
5237
5238if (Revision == 2)
5239{
5240DBG("RSDP: Original extended checksum %d\n", rsdp_mod->ExtendedChecksum);
5241
5242setRsdpXchecksum(rsdp_mod);
5243
5244DBG("New extended checksum %d\n", rsdp_mod->ExtendedChecksum);
5245
5246}
5247
5248verbose("ACPI Revision %d successfully patched\n", Revision);
5249
5250if (Revision == 2)
5251{
5252rsd_p = ((U64)((U32)rsdp_mod));
5253if (rsd_p)
5254Status = addConfigurationTable(&gEfiAcpi20TableGuid, &rsd_p, "ACPI_20");
5255}
5256else
5257{
5258rsd_p = ((U64)((U32)rsdp_mod));
5259if (rsd_p)
5260Status = addConfigurationTable(&gEfiAcpiTableGuid, &rsd_p, "ACPI");
5261
5262}
5263
5264#if DEBUG_ACPI==2
5265printf("Press a key to continue... (DEBUG_ACPI)\n");
5266getc();
5267#endif
5268return Status;
5269}
5270

Archive Download this file

Revision: 1525