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

Archive Download this file

Revision: 1704