Chameleon

Chameleon Svn Source Tree

Root/branches/valv/i386/libsaio/acpi_patcher.c

  • Property svn:executable set to
1/*
2 * Copyright 2008 mackerintel
3 */
4
5#include "libsaio.h"
6#include "boot.h"
7#include "bootstruct.h"
8#include "acpi.h"
9#include "efi_tables.h"
10#include "fake_efi.h"
11#include "acpi_patcher.h"
12#include "platform.h"
13#include "cpu.h"
14#include "aml_generator.h"
15
16#ifndef DEBUG_ACPI
17#define DEBUG_ACPI 0
18#endif
19
20#if DEBUG_ACPI==2
21#define DBG(x...) {printf(x); sleep(1);}
22#elif DEBUG_ACPI==1
23#define DBG(x...) printf(x)
24#else
25#define DBG(x...)
26#endif
27
28uint64_t acpi10_p;
29uint64_t acpi20_p;
30
31/* Gets the ACPI 1.0 RSDP address */
32static struct acpi_2_rsdp* getAddressOfAcpiTable()
33{
34 /* TODO: Before searching the BIOS space we are supposed to search the first 1K of the EBDA */
35
36 void *acpi_addr = (void*)ACPI_RANGE_START;
37 for(; acpi_addr <= (void*)ACPI_RANGE_END; acpi_addr += 16)
38 {
39 if(*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE)
40 {
41 uint8_t csum = checksum8(acpi_addr, 20);
42 if(csum == 0)
43 {
44 // Only return the table if it is a true version 1.0 table (Revision 0)
45 if(((struct acpi_2_rsdp*)acpi_addr)->Revision == 0)
46 return acpi_addr;
47 }
48 }
49 }
50 return NULL;
51}
52
53/* Gets the ACPI 2.0 RSDP address */
54static struct acpi_2_rsdp* getAddressOfAcpi20Table()
55{
56 /* TODO: Before searching the BIOS space we are supposed to search the first 1K of the EBDA */
57
58 void *acpi_addr = (void*)ACPI_RANGE_START;
59 for(; acpi_addr <= (void*)ACPI_RANGE_END; acpi_addr += 16)
60 {
61 if(*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE)
62 {
63 uint8_t csum = checksum8(acpi_addr, 20);
64
65 /* Only assume this is a 2.0 or better table if the revision is greater than 0
66 * NOTE: ACPI 3.0 spec only seems to say that 1.0 tables have revision 1
67 * and that the current revision is 2.. I am going to assume that rev > 0 is 2.0.
68 */
69
70 if(csum == 0 && (((struct acpi_2_rsdp*)acpi_addr)->Revision > 0))
71 {
72 uint8_t csum2 = checksum8(acpi_addr, sizeof(struct acpi_2_rsdp));
73 if(csum2 == 0)
74 return acpi_addr;
75 }
76 }
77 }
78 return NULL;
79}
80
81/* The folowing ACPI Table search algo. should be reused anywhere needed:*/
82int search_and_get_acpi_fd(const char * filename, const char ** outDirspec)
83{
84int fd=0;
85const char * overriden_pathname=NULL;
86static char dirspec[512]="";
87int len=0;
88
89// Take in accound user overriding if it's DSDT only
90if (strstr(filename, "DSDT") &&
91getValueForKey(kDSDT, &overriden_pathname, &len, &bootInfo->bootConfig))
92 {
93sprintf(dirspec, "%s", overriden_pathname); // start searching root
94fd=open (dirspec,0);
95if (fd>=0) goto success_fd;
96 }
97
98// Start searching any potential location for ACPI Table
99sprintf(dirspec, "/%s", filename); // start searching root
100fd=open (dirspec,0);
101if (fd>=0) goto success_fd;
102
103sprintf(dirspec, "%s", filename); // start current dir
104fd=open (dirspec,0);
105if (fd>=0) goto success_fd;
106
107sprintf(dirspec,"/Extra/%s",filename);
108fd=open (dirspec,0);
109if (fd>=0) goto success_fd;
110
111sprintf(dirspec,"bt(0,0)/Extra/%s",filename);
112fd=open (dirspec,0);
113if (fd>=0) goto success_fd;
114
115// NOT FOUND:
116//verbose("ACPI Table not found: %s\n", filename);
117if (outDirspec) *outDirspec = "";
118return -1;
119// FOUND
120success_fd:
121if (outDirspec) *outDirspec = dirspec;
122return fd;
123}
124
125void *loadACPITable(char *key)
126{
127void *tableAddr;
128int fd = -1;
129char dirspec[512];
130char filename[512];
131const char * overriden_pathname=NULL;
132int len=0;
133
134sprintf(filename, "%s.aml", key);
135
136// Checking boot partition
137
138// Rek: if user specified a full path name then take it in consideration
139if (getValueForKey(key, &overriden_pathname, &len, &bootInfo->bootConfig))
140{
141sprintf(dirspec, "%s", overriden_pathname); // start searching root
142//printf("Using custom %s path %s\n", key, dirspec);
143//getc();
144}
145else
146sprintf(dirspec, "/%s", filename); // start searching root
147
148fd=open (dirspec,0);
149
150if (fd<0)
151{// Check Extra on booting partition
152 //verbose("Searching for %s.aml file ...\n", key);
153sprintf(dirspec,"/Extra/%s",filename);
154fd=open (dirspec,0);
155if (fd<0)
156{// Fall back to booter partition
157sprintf(dirspec,"bt(0,0)/Extra/%s",filename);
158fd=open (dirspec,0);
159if (fd<0)
160{
161//verbose("ACPI Table not found: %s\n", filename);
162return NULL;
163}
164}
165}
166
167tableAddr=(void*)AllocateKernelMemory(file_size (fd));
168if (tableAddr)
169{
170if (read (fd, tableAddr, file_size (fd))!=file_size (fd))
171{
172printf("Couldn't read table %s\n",dirspec);
173free (tableAddr);
174close (fd);
175return NULL;
176}
177
178DBG("Table %s read and stored at: %x\n", dirspec, tableAddr);
179close (fd);
180return tableAddr;
181}
182
183printf("Couldn't allocate memory for table %s\n", dirspec);
184close (fd);
185
186return NULL;
187}
188
189uint8_tacpi_cpu_count = 0;
190char* acpi_cpu_name[32];
191
192void get_acpi_cpu_names(unsigned char* dsdt, uint32_t length)
193{
194uint32_t i;
195
196for (i=0; i<length-7; i++)
197{
198if (dsdt[i] == 0x5B && dsdt[i+1] == 0x83) // ProcessorOP
199{
200uint32_t offset = i + 3 + (dsdt[i+2] >> 6);
201
202bool add_name = true;
203
204uint8_t j;
205
206for (j=0; j<4; j++)
207{
208char c = dsdt[offset+j];
209
210if (!aml_isvalidchar(c))
211{
212add_name = false;
213verbose("Invalid character found in ProcessorOP 0x%x!\n", c);
214break;
215}
216}
217
218if (add_name)
219{
220acpi_cpu_name[acpi_cpu_count] = malloc(4);
221memcpy(acpi_cpu_name[acpi_cpu_count], dsdt+offset, 4);
222i = offset + 5;
223
224verbose("Found ACPI CPU: %c%c%c%c\n", acpi_cpu_name[acpi_cpu_count][0], acpi_cpu_name[acpi_cpu_count][1], acpi_cpu_name[acpi_cpu_count][2], acpi_cpu_name[acpi_cpu_count][3]);
225
226if (++acpi_cpu_count == 32) return;
227}
228}
229}
230}
231
232struct acpi_2_ssdt *generate_cst_ssdt(struct acpi_2_fadt* fadt)
233{
234char ssdt_header[] =
235{
2360x53, 0x53, 0x44, 0x54, 0xE7, 0x00, 0x00, 0x00, /* SSDT.... */
2370x01, 0x17, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x41, /* ..PmRefA */
2380x43, 0x70, 0x75, 0x43, 0x73, 0x74, 0x00, 0x00, /* CpuCst.. */
2390x00, 0x10, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* ....INTL */
2400x31, 0x03, 0x10, 0x20 /* 1.._*/
241};
242
243char cstate_resource_template[] =
244{
2450x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00, 0x7F,
2460x01, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
2470x00, 0x00, 0x00, 0x79, 0x00
248};
249
250if (Platform.CPU.Vendor != 0x756E6547) {
251verbose ("C-States: Not an Intel platform !!!\n");
252return NULL;
253}
254
255if (fadt == NULL) {
256verbose ("C-States: FACP not found !!!\n");
257return NULL;
258}
259
260struct acpi_2_dsdt* dsdt = (void*)fadt->DSDT;
261
262if (dsdt == NULL) {
263verbose ("C-States: DSDT not found !!!\n");
264return NULL;
265}
266
267if (acpi_cpu_count == 0)
268get_acpi_cpu_names((void*)dsdt, dsdt->Length);
269
270if (acpi_cpu_count > 0)
271{
272//valv: c2 & c3 are enabled by default; else don't use EnableCStates
273bool c2_enabled, c3_enabled, c4_enabled, c6_enabled, tmpval2, tmpval3, tmpval4, tmpval6;
274c2_enabled = c3_enabled = c4_enabled = c6_enabled = false;
275unsigned char cstates_count;
276
277c2_enabled = (getBoolForKey(kEnableC2State, &tmpval2, &bootInfo->bootConfig)&&tmpval2) | (fadt->P_LVL2_LAT < 100);
278c3_enabled = (getBoolForKey(kEnableC3State, &tmpval3, &bootInfo->bootConfig)&&tmpval3) | (fadt->P_LVL2_LAT < 1000);
279c4_enabled = getBoolForKey(kEnableC4State, &tmpval4, &bootInfo->bootConfig)&&tmpval4;
280c6_enabled = getBoolForKey(kEnableC6State, &tmpval6, &bootInfo->bootConfig)&&tmpval6;
281
282if(c6_enabled) c4_enabled = true;
283if(c4_enabled) c3_enabled = true;
284if(c3_enabled) c2_enabled = true;
285
286if(Platform.CPU.Family == 0x06)
287{
288int intelCPU = Platform.CPU.Model;
289switch (intelCPU)
290{
291case 0x0F: // Core (65nm)
292case 0x1A: // Core i7, Xeon 5500 series - Bloomfield, Gainstown NHM-EP - LGA1366 (45nm)
293case 0x1E: // Core i5, i7 - Clarksfield, Lynnfield, Jasper Forest - LGA1156 (45nm)
294case 0x1F: // Core i5, i7 - Nehalem
295case 0x25: // Core i3, i5, i7 - Westmere Client - Clarkdale, Arrandale - LGA1156 (32nm)
296case 0x2C: // Core i7 - Westmere EP - Gulftown - LGA1366 (32nm) 6 Core
297case 0x2E: // Westmere-Ex Xeon
298case 0x2F: // Westmere-Ex Xeon - Eagelton
299cstates_count = 1 + (c2_enabled ? 1 : 0) + (c3_enabled ? 1 : 0);
300verbose("C-State: Adding %d states: ", cstates_count);
301break;
302case 0x1C: // Atom (45nm)
303case 0x26: // Atom Lincroft
304cstates_count = 1 + (c2_enabled ? 1 : 0) + (c4_enabled ? 1 : 0) + (c6_enabled ? 1 : 0);
305verbose("C-State: Adding %d states: ", cstates_count);
306break;
307case 0x17:
308cstates_count = 1 + (c2_enabled ? 1 : 0) + (c3_enabled ? 1 : 0) + (c4_enabled ? 1 : 0) + (c6_enabled ? 1 : 0);
309verbose("C-State: Adding %d states: ", cstates_count);
310break;
311default:
312cstates_count = 1 + (c2_enabled ? 1 : 0) + (c3_enabled ? 1 : 0) + (c4_enabled ? 1 : 0);
313break;
314}
315}
316else cstates_count = 1 + (c2_enabled ? 1 : 0) + (c3_enabled ? 1 : 0) + (c4_enabled ? 1 : 0);
317
318struct aml_chunk* root = aml_create_node(NULL);
319aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header
320struct aml_chunk* scop = aml_add_scope(root, "\\_PR_");
321
322struct aml_chunk* name_csd = aml_add_name(scop, "CSD_");
323struct aml_chunk* pack_csd = aml_add_package(name_csd);
324struct aml_chunk* csd = aml_add_package(pack_csd);
325aml_add_byte(csd, 0x05);
326aml_add_byte(csd, 0x00);
327aml_add_dword(csd, 0x00);
328aml_add_dword(csd, 0xfd);
329aml_add_dword(csd, Platform.CPU.NoCores);
330
331struct aml_chunk* name = aml_add_name(scop, "CST_");
332struct aml_chunk* pack = aml_add_package(name);
333aml_add_byte(pack, cstates_count);
334struct aml_chunk* tmpl = aml_add_package(pack);
335
336switch (Platform.CPU.Family) {
337case 0x06:
338{
339switch (Platform.CPU.Model)
340{
341case 0x0F: // Core (65nm)
342case 0x1A: // Core i7, Xeon 5500 series - Bloomfield, Gainstown NHM-EP - LGA1366 (45nm)
343case 0x1E: // Core i5, i7 - Clarksfield, Lynnfield, Jasper Forest - LGA1156 (45nm)
344case 0x1F: // Core i5, i7 - Nehalem
345case 0x25: // Core i3, i5, i7 - Westmere Client - Clarkdale, Arrandale - LGA1156 (32nm)
346case 0x2C: // Core i7 - Westmere EP - Gulftown - LGA1366 (32nm) 6 Core
347case 0x2E: // Westmere-Ex Xeon
348case 0x2F: // Westmere-Ex Xeon - Eagelton
349
350// C1
351cstate_resource_template[11] = 0x00; // C1-Nehalem
352aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
353aml_add_byte(tmpl, 0x01); // C1
354aml_add_byte(tmpl, 0x03); // Latency
355aml_add_word(tmpl, 0x03e8); // Power
356verbose ("C1 ");
357
358// C2
359if (c2_enabled)
360{
361tmpl = aml_add_package(pack);
362cstate_resource_template[11] = 0x10; // C3-Nehalem
363aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
364aml_add_byte(tmpl, 0x02); // C2
365aml_add_byte(tmpl, 0x14); // Latency
366aml_add_word(tmpl, 0x01f4); // Power
367verbose ("C3 ");
368}
369
370// C3
371if (c3_enabled)
372{
373tmpl = aml_add_package(pack);
374cstate_resource_template[11] = 0x20; // C6-Nehalem
375aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
376aml_add_byte(tmpl, 0x03); // C3
377aml_add_word(tmpl, 0xc8); // Latency
378aml_add_word(tmpl, 0x015e); // Power
379verbose ("C6");
380}
381//verbose("\n");
382
383break;
384
385case 0x1C: // Atom (45nm)
386//valv: was 0x26 ??? rely on cpu.c & smbios_patcher.c
387case 0x27: // Atom Lincroft
388
389// C1
390cstate_resource_template[11] = 0x00; // C1-Atom
391aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
392aml_add_byte(tmpl, 0x01); // C1
393aml_add_byte(tmpl, 0x01); // Latency
394aml_add_word(tmpl, 0x03e8); // Power
395verbose ("C1 ");
396
397// C2
398if (c2_enabled)
399{
400tmpl = aml_add_package(pack);
401cstate_resource_template[11] = 0x10; // C2-Atom
402aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
403aml_add_byte(tmpl, 0x02); // C2
404aml_add_byte(tmpl, fadt->P_LVL2_LAT); // Latency
405aml_add_word(tmpl, 0x01f4); // Power
406verbose ("C2 ");
407}
408
409// C3
410/*if (c3_enabled)
411{
412tmpl = aml_add_package(pack);
413cstate_resource_template[11] = 0x20; // C3-Atom
414aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
415aml_add_byte(tmpl, 0x03); // C3
416aml_add_word(tmpl, fadt->P_LVL3_LAT); // Latency
417aml_add_word(tmpl, 0x015e); // Power
418verbose ("C-State: Added C3\n");
419}*/
420
421// C4
422if (c4_enabled)
423{
424tmpl = aml_add_package(pack);
425cstate_resource_template[11] = 0x30; // C4-Atom
426aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
427aml_add_byte(tmpl, 0x03); // C4
428aml_add_word(tmpl, 0x64); // Latency
429aml_add_word(tmpl, 0x00fa); // Power
430verbose ("C4 ");
431}
432
433// C6
434if (c6_enabled)
435{
436tmpl = aml_add_package(pack);
437cstate_resource_template[11] = 0x40; // C6-Atom
438aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
439aml_add_byte(tmpl, 0x03); // C6
440aml_add_word(tmpl, 0xC8); // Latency
441aml_add_word(tmpl, 0x0096); // Power
442verbose ("C6 ");
443}
444//verbose("\n");
445
446break;
447
448case 0x17:
449default:
450
451// C1
452cstate_resource_template[11] = 0x00; // C1
453aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
454aml_add_byte(tmpl, 0x01); // C1
455aml_add_byte(tmpl, 0x01); // Latency
456aml_add_word(tmpl, 0x03e8); // Power 1000
457verbose ("C1 ");
458
459// C2
460if (c2_enabled)
461{
462tmpl = aml_add_package(pack);
463cstate_resource_template[11] = 0x10; // C2
464aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
465aml_add_byte(tmpl, 0x02); // C2
466aml_add_byte(tmpl, 0x14); // Latency 20
467aml_add_word(tmpl, 0x01f4); // Power 500
468verbose ("C2 ");
469}
470
471// C3
472if (c3_enabled)
473{
474tmpl = aml_add_package(pack);
475cstate_resource_template[11] = 0x20; // C3
476aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
477aml_add_byte(tmpl, 0x03); // C3
478aml_add_word(tmpl, 0x28); // Latency 40
479aml_add_word(tmpl, 0x015e); // Power 350
480verbose ("C3 ");
481}
482
483// C4
484if (c4_enabled)
485{
486tmpl = aml_add_package(pack);
487cstate_resource_template[11] = 0x30; // C4
488aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
489aml_add_byte(tmpl, 0x03); // C4
490aml_add_word(tmpl, 0x64); // Latency 100
491aml_add_word(tmpl, 0x00fa); // Power 250
492verbose ("C4 ");
493}
494
495// C6
496if (c6_enabled)
497{
498tmpl = aml_add_package(pack);
499cstate_resource_template[11] = 0x40; // C6
500aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
501aml_add_byte(tmpl, 0x03); // C6
502aml_add_word(tmpl, 0xc8); // Latency 200
503aml_add_word(tmpl, 0x0096); // Power 150
504verbose ("C6");
505}
506//verbose("\n");
507
508break;
509}
510}
511}
512
513// Aliaces
514int i;
515for (i = 0; i < acpi_cpu_count; i++)
516{
517char name[9];
518sprintf(name, "_PR_%c%c%c%c", acpi_cpu_name[i][0], acpi_cpu_name[i][1], acpi_cpu_name[i][2], acpi_cpu_name[i][3]);
519
520scop = aml_add_scope(root, name);
521aml_add_alias(scop, "CST_", "_CST");
522}
523
524
525aml_calculate_size(root);
526
527struct acpi_2_ssdt *ssdt = (struct acpi_2_ssdt *)AllocateKernelMemory(root->Size);
528
529aml_write_node(root, (void*)ssdt, 0);
530
531ssdt->Length = root->Size;
532ssdt->Checksum = 0;
533ssdt->Checksum = 256 - checksum8(ssdt, ssdt->Length);
534
535verbose (" @ %x\n", ssdt);
536aml_destroy_node(root);
537
538//dumpPhysAddr("C-States SSDT content: ", ssdt, ssdt->Length);
539
540return ssdt;
541}
542else
543{
544verbose ("C-States: ACPI CPUs not found !!!\n");
545}
546
547return NULL;
548}
549
550uint8_t mV_to_VID(uint16_t mv) {
551if (Platform.CPU.Vendor == 0x756E6547)
552{
553if ((Platform.CPU.Family == 0x06) && (Platform.CPU.Model == 0x17))
554return ((mv * 10) - 7125) / 125;
555else
556return (mv - 700) / 16;
557}
558return 0;
559}
560
561uint16_t VID_to_mV(uint8_t VID) {
562if (Platform.CPU.Vendor == 0x756E6547)
563{
564if ((Platform.CPU.Family == 0x06) && (Platform.CPU.Model == 0x17))
565return (((int)VID * 125) + 7125) / 10;
566else
567return (((int)VID * 16) + 700);
568}
569return 0;
570}
571
572struct acpi_2_ssdt *generate_pss_ssdt(struct acpi_2_dsdt* dsdt)
573{
574char ssdt_header[] =
575{
5760x53, 0x53, 0x44, 0x54, 0x7E, 0x00, 0x00, 0x00, /* SSDT.... */
5770x01, 0x6A, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x00, /* ..PmRef. */
5780x43, 0x70, 0x75, 0x50, 0x6D, 0x00, 0x00, 0x00, /* CpuPm... */
5790x00, 0x30, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* .0..INTL */
5800x31, 0x03, 0x10, 0x20,/* 1.._*/
581};
582
583char ssdt_pct[] =
584{
5850x08, 0x5F, 0x50, 0x43, 0x54, 0x12, 0x2C, 0x02,/* 0._PCT., */
5860x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00, 0x7F,/* ........ */
5870x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
5880x00, 0x00, 0x00, 0x79, 0x00, 0x11, 0x14, 0x0A, /* ....y... */
5890x11, 0x82, 0x0C, 0x00, 0x7F, 0x00, 0x00, 0x00, /* ........ */
5900x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
5910x79, 0x00
592};
593
594if (Platform.CPU.Vendor != 0x756E6547) {
595verbose ("P-States: Not an Intel platform !!!\n");
596return NULL;
597}
598
599if (!(platformCPUFeature(CPU_FEATURE_MSR))) {
600verbose ("P-States: Unsupported CPU !!!\n");
601return NULL;
602}
603
604if (acpi_cpu_count == 0)
605get_acpi_cpu_names((void*)dsdt, dsdt->Length);
606
607if (acpi_cpu_count > 0)
608{
609
610struct p_state initial, maximum, minimum, p_states[32];
611uint8_t p_states_count = 0;
612
613//TODO: make use of minimum & friends instead, (busratios, freqs ...)
614int busratio_min = Platform.CPU.MinRatio;
615int busratio_max = Platform.CPU.MaxRatio;
616
617int freq_max = ((Platform.CPU.FSBFrequency / 1000000) * busratio_max) / 10;
618int freq_min = ((Platform.CPU.FSBFrequency / 1000000) * busratio_min) / 10;
619int p = ((busratio_max - busratio_min) * 2) / 10;
620int f_step = (freq_max - freq_min) / p;
621if (Platform.CPU.SLFM) freq_min = (busratio_min * f_step) / 10;
622freq_max = (((Platform.CPU.FSBFrequency / 1000000) + 1) * busratio_max) / 10;
623
624//valv: minimum instead of current
625//initial.Control = rdmsr64(MSR_IA32_PERF_STATUS);
626initial.Control = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 48) & 0x1F3F);
627maximum.Control = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 32) & 0x1F3F) | (0x4000 * Platform.CPU.MaxDiv);
628
629maximum.FID = (busratio_max / 0xA) & 0x1F | (0x40 * Platform.CPU.MaxDiv);
630maximum.CID = ((maximum.FID & 0x1F) << 1) | Platform.CPU.MaxDiv;
631
632// current isn't always minimum
633//minimum.FID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 24) & 0x1F) | (0x80 * cpu_dynamic_fsb);
634minimum.FID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 56) & 0x1F) | (0x80 * Platform.CPU.SLFM);
635// this may not be valid when slfm (did) is enabled. Rely on vmin instead
636minimum.VID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 48) & 0x3F);
637
638int umaxVolt, uminVolt, moreVolt, lessVolt, vstate;
639int maxVolt_limit = VID_to_mV(maximum.VID) + 250;
640int minVolt_limit = VID_to_mV(minimum.VID) - 250;
641uint8_t vstep = 0;
642
643if((getIntForKey(kmaxVoltage, &umaxVolt, &bootInfo->bootConfig)) && (umaxVolt <= maxVolt_limit))
644{
645uint8_t vmax = mV_to_VID(umaxVolt);
646maximum.Control = (((busratio_max / 0xA) & 0x1F) * 0x100 | vmax) | (0x4000 * Platform.CPU.MaxDiv);
647maximum.VID = vmax & 0x3F;
648}
649if((getIntForKey(kminVoltage, &uminVolt, &bootInfo->bootConfig)) && (uminVolt >= minVolt_limit))
650{
651uint8_t vmin = mV_to_VID(uminVolt);
652minimum.VID = vmin & 0x3F;
653}
654
655if (minimum.FID == 0)
656{
657uint64_t msr;
658uint8_t i;
659// Probe for lowest fid
660// this is for requested FID, and not forcibly the lowest
661for (i = maximum.FID; i >= 0x6; i--)
662{
663msr = rdmsr64(MSR_IA32_PERF_CONTROL);
664wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (i << 8) | minimum.VID);
665intel_waitforsts();
666minimum.FID = (rdmsr64(MSR_IA32_PERF_STATUS) >> 8) & 0x1F;
667delay(1);
668}
669
670msr = rdmsr64(MSR_IA32_PERF_CONTROL);
671wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
672intel_waitforsts();
673}
674
675if (minimum.VID == maximum.VID)
676{
677uint64_t msr;
678uint8_t i;
679// Probe for lowest vid
680for (i = maximum.VID; i > 0xA; i--)
681{
682msr = rdmsr64(MSR_IA32_PERF_CONTROL);
683wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (minimum.FID << 8) | i);
684intel_waitforsts();
685minimum.VID = rdmsr64(MSR_IA32_PERF_STATUS) & 0x3F;
686delay(1);
687}
688
689msr = rdmsr64(MSR_IA32_PERF_CONTROL);
690wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
691intel_waitforsts();
692}
693
694minimum.CID = ((minimum.FID & 0x1F) << 1) >> Platform.CPU.SLFM;
695
696// Sanity check
697if (maximum.CID < minimum.CID)
698{
699DBG("P-States: Insane FID values!");
700p_states_count = 1;
701}
702else
703{
704// Print the voltage to be used
705int minVoltage = VID_to_mV(minimum.VID);
706int maxVoltage = VID_to_mV(maximum.VID);
707verbose("Voltage: min= %dmV, max= %dmV\n", minVoltage, maxVoltage);
708
709// Finalize P-States
710// Find how many P-States machine supports
711
712p_states_count = maximum.CID - minimum.CID + 1;
713
714if (p_states_count > 32)
715p_states_count = 32;
716
717uint8_t vidstep;
718uint8_t i = 0, u, invalid = 0;
719
720vidstep = ((maximum.VID << 2) - (minimum.VID << 2)) / (p_states_count - 1);
721for (u = 0; u < p_states_count; u++)
722{
723i = u - invalid;
724
725p_states[i].CID = maximum.CID - u;
726p_states[i].FID = (p_states[i].CID >> 1);
727
728if (i && p_states[i].FID < 0x6)
729{
730if (Platform.CPU.SLFM)
731{
732p_states[i].FID = (p_states[i].FID << 1) | 0x80;
733}
734// intel doesn't allow FIDs lower that 6 on core, core2 and eventually core-i
735else invalid++;
736}
737
738// 6.5 isn't selectable
739else if (Platform.CPU.MaxDiv && p_states[i].FID > 0x6)
740{
741// first state only!?
742//p_states[0].FID = p_states[0].FID | (0x40 * (p_states[0].CID & 0x1));
743p_states[i].FID = p_states[i].FID | (0x40 * (p_states[i].CID & 0x1));
744}
745
746if (i && p_states[i].FID == p_states[i-1].FID)
747invalid++;
748
749p_states[i].VID = ((maximum.VID << 2) - (vidstep * u)) >> 2;
750
751if(getIntForKey(klessVoltage, &lessVolt, &bootInfo->bootConfig))
752{
753vstate = (VID_to_mV(p_states[i].VID)) - lessVolt;
754vstep = mV_to_VID(vstate);
755p_states[i].VID = vstep & 0x3F;
756}
757else if(getIntForKey(kmoreVoltage, &moreVolt, &bootInfo->bootConfig))
758{
759vstate = (VID_to_mV(p_states[i].VID)) + moreVolt;
760vstep = mV_to_VID(vstate);
761p_states[i].VID = vstep & 0x3F;
762}
763
764uint32_t multiplier = p_states[i].FID & 0x1f;// = 0x08
765bool half = p_states[i].FID & 0x40;// = 0x01
766bool dfsb = p_states[i].FID & 0x80;// = 0x00
767uint32_t fsb = Platform.CPU.FSBFrequency / 1000000; // = 400
768uint32_t halffsb = (fsb + 1) >> 1;// = 200
769uint32_t frequency = (multiplier * fsb);// = 3200
770
771p_states[i].Frequency = (frequency + (half * halffsb)) >> dfsb;// = 3200 + 200 = 3400
772}
773p_states_count -= invalid;
774}
775
776//valv: Silly! Isn't it? :)
777int pstates = 0;
778if (getIntForKey(kpstates, &pstates, &bootInfo->bootConfig) && pstates < p_states_count && pstates > 0)
779{
780verbose("P-State: Only the %d highest states will be added\n", pstates);
781pstates = pstates - 1;
782}
783
784int pstart = 0;
785if (getIntForKey(kpstart, &pstart, &bootInfo->bootConfig) && pstart < p_states_count && pstart > 0)
786{
787const char *newratio;
788int len;
789if (getValueForKey(kbusratio, &newratio, &len, &bootInfo->bootConfig))
790{
791verbose("P-State: Already using bus-ratio injection! PStart key will have no effect.\n");
792pstart = 0;
793}
794else verbose("P-State: Starting from state P%d\n", pstart);
795}
796
797// Generating SSDT
798if (p_states_count > 0)
799{
800int i;
801//valv: fix p-states number issue on some models.
802verbose("Model detected: %s\n", MacProduct);
803if(!strstr(MacProduct, "applemac2010"))
804{
805if(strstr(MacProduct, "MacBookPro4,1") && ((p_states_count > 9) && ((pstart == 0) && (pstates == 0)))) pstates = 8;
806if(strstr(MacProduct, "MacBookAir1,1") && ((p_states_count > 4) && ((pstart == 0) && (pstates == 0)))) pstates = 3;
807}
808
809struct aml_chunk* root = aml_create_node(NULL);
810aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header
811struct aml_chunk* scop = aml_add_scope(root, "\\_PR_");
812
813aml_add_buffer(scop, ssdt_pct, sizeof(ssdt_pct));
814
815struct aml_chunk* name_psd = aml_add_name(scop, "PSD_");
816struct aml_chunk* pack_psd = aml_add_package(name_psd);
817struct aml_chunk* psd = aml_add_package(pack_psd);
818aml_add_byte(psd, 0x05);
819aml_add_byte(psd, 0x00);
820aml_add_dword(psd, 0x00);
821aml_add_dword(psd, 0xfd);
822aml_add_dword(psd, Platform.CPU.NoCores);
823
824struct aml_chunk* name_pss = aml_add_name(scop, "PSS_");
825struct aml_chunk* pack_pss = aml_add_package(name_pss);
826
827uint8_t p_states_num = 0;
828for (i = pstart; i < p_states_count; i++)
829{
830if ((p_states[i].Frequency <= freq_max) && (p_states[i].Frequency >= freq_min))
831{
832//valv: inspired from cparm's pss-drop; coded by me ;)
833if ((i > pstates) && (pstates > 0))
834{
835if(Platform.CPU.ISerie) verbose("P-State: [Frequency %d MHz\tFID 0x%x] is the %dth state. Removed!\n",
836p_states[i].Frequency, p_states[i].FID, (i+1));
837else verbose("P-State: [Frequency %d MHz\tFID 0x%x \tVID 0x%x] is the %dth state. Removed!\n",
838p_states[i].Frequency, p_states[i].FID, p_states[i].VID, (i+1));
839}
840else
841{
842struct aml_chunk* pstt = aml_add_package(pack_pss);
843
844aml_add_dword(pstt, p_states[i].Frequency);
845aml_add_dword(pstt, 0x00000000); // Power
846aml_add_dword(pstt, 0x0000000A); // Latency
847aml_add_dword(pstt, 0x0000000A); // Latency
848if(Platform.CPU.ISerie)
849{
850aml_add_dword(pstt, p_states[i].FID);
851aml_add_dword(pstt, p_states[i].FID);
852verbose("P-State: Added [Frequency %d MHz\tFID 0x%x]\n", p_states[i].Frequency, p_states[i].FID);
853}
854else
855{
856aml_add_dword(pstt, p_states[i].Control);
857aml_add_dword(pstt, p_states[i].Control);
858//aml_add_dword(pstt, i+1); // Status
859verbose("P-State: Added [Frequency %d MHz\tFID 0x%x \tVID 0x%x]\n",
860p_states[i].Frequency, p_states[i].FID, p_states[i].VID);
861}
862p_states_num++;
863}
864}
865else
866{
867if(Platform.CPU.ISerie) verbose("P-State: [Frequency %d MHz\tFID 0x%x] is over the limit. Removed!\n",
868p_states[i].Frequency, p_states[i].FID);
869else verbose("P-State: [Frequency %d MHz\tFID 0x%x \tVID 0x%x] is over the limit. Removed!\n",
870p_states[i].Frequency, p_states[i].FID, p_states[i].VID);
871}
872}
873
874struct aml_chunk* name_ppc = aml_add_name(scop, "PPC_");
875aml_add_byte(name_ppc, 0x00);
876
877// Add aliaces
878for (i = 0; i < acpi_cpu_count; i++)
879{
880char name[9];
881sprintf(name, "_PR_%c%c%c%c", acpi_cpu_name[i][0], acpi_cpu_name[i][1], acpi_cpu_name[i][2], acpi_cpu_name[i][3]);
882
883scop = aml_add_scope(root, name);
884aml_add_alias(scop, "PCT_", "_PCT");
885aml_add_alias(scop, "PSD_", "_PSD");
886aml_add_alias(scop, "PSS_", "_PSS");
887aml_add_alias(scop, "PPC_", "_PPC");
888}
889
890aml_calculate_size(root);
891
892struct acpi_2_ssdt *ssdt = (struct acpi_2_ssdt *)AllocateKernelMemory(root->Size);
893
894aml_write_node(root, (void*)ssdt, 0);
895
896ssdt->Length = root->Size;
897ssdt->Checksum = 0;
898ssdt->Checksum = 256 - checksum8(ssdt, ssdt->Length);
899
900verbose ("P-States: %d states were succefully generated @ %x\n", p_states_num, ssdt);
901aml_destroy_node(root);
902
903return ssdt;
904}
905}
906else {
907verbose ("P-States: ACPI CPUs not found !!!\n");
908}
909
910return NULL;
911}
912
913struct acpi_2_ssdt *generate_tss_ssdt(struct acpi_2_fadt* fadt)
914{
915char ssdt_header[] =
916{
917 0x53, 0x53, 0x44, 0x54, 0xE7, 0x00, 0x00, 0x00,
918 0x01, 0x17, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x42,
919 0x43, 0x70, 0x75, 0x54, 0x73, 0x74, 0x00, 0x00,
920 0x00, 0x10, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C,
921 0x31, 0x03, 0x10, 0x20
922};
923
924char ssdt_ptc[] =
925{
9260x08, 0x5F, 0x50, 0x54, 0x43, 0x12, 0x2C, 0x02,
9270x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00, 0x7F,
9280x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9290x00, 0x00, 0x00, 0x79, 0x00, 0x11, 0x14, 0x0A,
9300x11, 0x82, 0x0C, 0x00, 0x7F, 0x00, 0x00, 0x00,
9310x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9320x79, 0x00
933};
934
935if (Platform.CPU.Vendor != 0x756E6547) {
936verbose ("T-States: Not an Intel platform !!!\n");
937return NULL;
938}
939
940if (!(platformCPUFeature(CPU_FEATURE_MSR))) {
941verbose ("T-States: Unsupported CPU !!!\n");
942return NULL;
943}
944
945if (fadt == NULL) {
946verbose ("FACP not found: T-States will not be generated !!!\n");
947return NULL;
948}
949
950struct acpi_2_dsdt* dsdt = (void*)fadt->DSDT;
951
952if (dsdt == NULL) {
953verbose ("T-States: DSDT not found !!!\n");
954return NULL;
955}
956
957if (acpi_cpu_count == 0)
958get_acpi_cpu_names((void*)dsdt, dsdt->Length);
959
960if (acpi_cpu_count > 0)
961{
962
963struct t_state t_states[32];
964uint8_t t_states_count = 0, ctrl0 = 0x10, j = 0x01;
965int i, step;
966uint64_t msr;
967uint32_t ext_mod; // *ret = 0;
968
969do_cpuid(6, Platform.CPU.CPUID[CPUID_81]);
970ext_mod = bitfield(Platform.CPU.CPUID[CPUID_81][0], 5, 5);
971
972if(ext_mod == 1)
973{
974verbose("T-States: Unsupported CPU !!!\n");
975return NULL;
976}
977
978msr = rdmsr64(MSR_IA32_CLOCK_MODULATION);
979t_states_count = msr & 0xE;
980
981//if(!fadt->DUTY_WIDTH)
982if(t_states_count == 0)
983{
984verbose("T-States: Unsupported CPU !!!\n");
985return NULL;
986}
987/*
988verbose("T-States: duty_offset=%d, duty_width=%d\n", fadt->DUTY_OFFSET, fadt->DUTY_WIDTH);
989uint8_t duty_cycle = fadt->DUTY_WIDTH + fadt->DUTY_OFFSET;
990
991if(duty_cycle > 4)
992{
993verbose("T-States: Spanning bit 4\n");
994for (i=2; i<21; i++)
995{
996if(duty_cycle > 4)
997{
998verbose("duty_cycle: %d\n", duty_cycle);
999sleep(i);
1000i++;
1001}
1002//return NULL;
1003else
1004{
1005t_states_count = 8;
1006goto nrx;
1007}
1008}
1009}
1010else t_states_count = 1 << fadt->DUTY_WIDTH;
1011
1012nrx:
1013*/
1014step = (1000 / t_states_count);
1015for (i = 1; i < t_states_count; i++)
1016{
1017t_states[i].perf = (1000 - (step * i)) / 10;
1018t_states[i].pwer = 1000 - (step * i);
1019t_states[i].ctrl = ctrl0 - j;
1020j++;
1021}
1022
1023// Generating SSDT
1024if (t_states_count > 0)
1025{
1026struct aml_chunk* root = aml_create_node(NULL);
1027aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header
1028struct aml_chunk* scop = aml_add_scope(root, "\\_PR_");
1029
1030struct aml_chunk* name_tpc = aml_add_name(scop, "TPC_");
1031aml_add_byte(name_tpc, 0x00);
1032
1033aml_add_buffer(scop, ssdt_ptc, sizeof(ssdt_ptc));
1034
1035struct aml_chunk* name_tss = aml_add_name(scop, "TSS_");
1036struct aml_chunk* pack_tss = aml_add_package(name_tss);
1037
1038struct aml_chunk* tssp0 = aml_add_package(pack_tss);
1039aml_add_dword(tssp0, 0x64);// Frequency %
1040aml_add_dword(tssp0, 0x03E8);// Power
1041aml_add_dword(tssp0, 0x00);// Latency
1042aml_add_dword(tssp0, 0x00);// Control; spec says 0x07; apple uses 0;
1043aml_add_dword(tssp0, 0x00);// Status
1044
1045for (i = 1; i < t_states_count; i++)
1046{
1047struct aml_chunk* tssp = aml_add_package(pack_tss);
1048
1049aml_add_dword(tssp, t_states[i].perf);
1050aml_add_dword(tssp, t_states[i].pwer);
1051aml_add_dword(tssp, 0x00);
1052aml_add_dword(tssp, t_states[i].ctrl);
1053aml_add_dword(tssp, 0x00);
1054}
1055
1056struct aml_chunk* name_tsd = aml_add_name(scop, "TSD_");
1057struct aml_chunk* pack_tsd = aml_add_package(name_tsd);
1058struct aml_chunk* tsd = aml_add_package(pack_tsd);
1059aml_add_byte(tsd, 0x05);
1060aml_add_byte(tsd, 0x00);
1061aml_add_dword(tsd, 0x00);
1062aml_add_dword(tsd, 0xfd);
1063aml_add_dword(tsd, Platform.CPU.NoCores);
1064
1065// Add aliaces
1066for (i = 0; i < acpi_cpu_count; i++)
1067{
1068char name[9];
1069sprintf(name, "_PR_%c%c%c%c", acpi_cpu_name[i][0], acpi_cpu_name[i][1], acpi_cpu_name[i][2], acpi_cpu_name[i][3]);
1070
1071scop = aml_add_scope(root, name);
1072aml_add_alias(scop, "TPC_", "_TPC");
1073aml_add_alias(scop, "PTC_", "_PTC");
1074aml_add_alias(scop, "TSS_", "_TSS");
1075aml_add_alias(scop, "TSD_", "_TSD");
1076}
1077
1078aml_calculate_size(root);
1079
1080struct acpi_2_ssdt *ssdt = (struct acpi_2_ssdt *)AllocateKernelMemory(root->Size);
1081
1082aml_write_node(root, (void*)ssdt, 0);
1083
1084ssdt->Length = root->Size;
1085ssdt->Checksum = 0;
1086ssdt->Checksum = 256 - checksum8(ssdt, ssdt->Length);
1087
1088verbose ("T-States: step=%d, %d states were succefully generated @ %x\n", step, t_states_count, ssdt);
1089
1090aml_destroy_node(root);
1091
1092return ssdt;
1093}
1094}
1095else
1096{
1097verbose ("ACPI CPUs not found: T-States not generated !!!\n");
1098}
1099
1100return NULL;
1101}
1102
1103void *loadSSDTTable(int ssdt_number)
1104{
1105void *tableAddr;
1106int fd = -1;
1107char dirspec[512];
1108char filename[512];
1109const char * overriden_pathname=NULL;
1110int len=0;
1111
1112sprintf(filename, "SSDT-%d.aml", ssdt_number);
1113
1114// Check booting partition
1115
1116// Rek: if user specified a full path name then take it in consideration
1117if (getValueForKey(kSSDT, &overriden_pathname, &len, &bootInfo->bootConfig))
1118{
1119sprintf(dirspec, "%s-%d.aml", overriden_pathname, ssdt_number); // start searching root
1120//printf("Using custom %s path %s\n", key, dirspec);
1121//getc();
1122}
1123else
1124sprintf(dirspec, "/%s", filename); // start searching root
1125
1126fd=open (dirspec,0);
1127
1128if (fd<0)
1129{// Check Extra on booting partition
1130//verbose("Searching for %s.aml file ...\n", key);
1131sprintf(dirspec,"/Extra/%s",filename);
1132fd=open (dirspec,0);
1133if (fd<0)
1134{// Fall back to booter partition
1135sprintf(dirspec,"bt(0,0)/Extra/%s",filename);
1136fd=open (dirspec,0);
1137if (fd<0)
1138{
1139//verbose("SSDT Table not found: %s\n", filename);
1140return NULL;
1141}
1142}
1143}
1144
1145tableAddr=(void*)AllocateKernelMemory(file_size (fd));
1146if (tableAddr)
1147{
1148if (read (fd, tableAddr, file_size (fd))!=file_size (fd))
1149{
1150printf("Couldn't read table %s\n",dirspec);
1151free (tableAddr);
1152close (fd);
1153return NULL;
1154}
1155
1156verbose("Table %s read and stored at: %x\n", dirspec, tableAddr);
1157close (fd);
1158return tableAddr;
1159}
1160
1161printf("Couldn't allocate memory for table %s\n", dirspec);
1162close (fd);
1163
1164return NULL;
1165}
1166
1167struct acpi_2_gas FillGASStruct(uint32_t Address, uint8_t Length)
1168{
1169struct acpi_2_gas TmpGAS;
1170
1171TmpGAS.Address_Space_ID = 1; /* I/O Address */
1172
1173if (Address == 0)
1174{
1175TmpGAS.Register_Bit_Width = 0;
1176} else {
1177TmpGAS.Register_Bit_Width = Length * 8;
1178}
1179
1180TmpGAS.Register_Bit_Offset = 0;
1181TmpGAS.Access_Size = 0; /* Not set for Legacy reasons... */
1182TmpGAS.Address = (uint64_t)Address;
1183
1184return(TmpGAS);
1185}
1186
1187struct acpi_2_fadt *patch_fadt(struct acpi_2_fadt *fadt, void *new_dsdt, bool UpdateFADT)
1188{
1189 extern void setupSystemType();
1190
1191struct acpi_2_fadt *fadt_mod;
1192struct acpi_2_fadt *fadt_file = (struct acpi_2_fadt *)loadACPITable(kFADT);
1193bool fadt_rev2_needed = false;
1194bool fix_restart;
1195const char * value;
1196
1197// Restart Fix
1198if (Platform.CPU.Vendor == 0x756E6547) {/* Intel */
1199fix_restart = true;
1200getBoolForKey(kRestartFix, &fix_restart, &bootInfo->bootConfig);
1201} else {
1202verbose ("Not an Intel platform: Restart Fix not applied !!!\n");
1203fix_restart = false;
1204}
1205
1206if (fix_restart)
1207fadt_rev2_needed = true;
1208
1209// Allocate new fadt table
1210if ((UpdateFADT) && (((fadt_file) && (fadt_file->Length < sizeof(struct acpi_2_fadt))) ||
1211 ((!fadt_file) && (fadt->Length < sizeof(struct acpi_2_fadt)))))
1212{
1213fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(sizeof(struct acpi_2_fadt));
1214
1215if (fadt_file)
1216memcpy(fadt_mod, fadt_file, fadt_file->Length);
1217else
1218memcpy(fadt_mod, fadt, fadt->Length);
1219
1220fadt_mod->Length = sizeof(struct acpi_2_fadt);
1221fadt_mod->Revision = 0x04; // FADT rev 4
1222fadt_mod->RESET_REG = FillGASStruct(0, 0);
1223fadt_mod->RESET_VALUE = 0;
1224fadt_mod->Reserved2[0] = 0;
1225fadt_mod->Reserved2[1] = 0;
1226fadt_mod->Reserved2[2] = 0;
1227fadt_mod->X_PM1a_EVT_BLK = FillGASStruct(fadt_mod->PM1a_EVT_BLK, fadt_mod->PM1_EVT_LEN);
1228fadt_mod->X_PM1b_EVT_BLK = FillGASStruct(fadt_mod->PM1b_EVT_BLK, fadt_mod->PM1_EVT_LEN);
1229fadt_mod->X_PM1a_CNT_BLK = FillGASStruct(fadt_mod->PM1a_CNT_BLK, fadt_mod->PM1_CNT_LEN);
1230fadt_mod->X_PM1b_CNT_BLK = FillGASStruct(fadt_mod->PM1b_CNT_BLK, fadt_mod->PM1_CNT_LEN);
1231fadt_mod->X_PM2_CNT_BLK = FillGASStruct(fadt_mod->PM2_CNT_BLK, fadt_mod->PM2_CNT_LEN);
1232fadt_mod->X_PM_TMR_BLK = FillGASStruct(fadt_mod->PM_TMR_BLK, fadt_mod->PM_TMR_LEN);
1233fadt_mod->X_GPE0_BLK = FillGASStruct(fadt_mod->GPE0_BLK, fadt_mod->GPE0_BLK_LEN);
1234fadt_mod->X_GPE1_BLK = FillGASStruct(fadt_mod->GPE1_BLK, fadt_mod->GPE1_BLK_LEN);
1235verbose("Converted ACPI V%d FADT to ACPI V4 FADT\n", (fadt_file) ? fadt_file->Revision : fadt->Revision);
1236} else {
1237if (((!fadt_file) && ((fadt->Length < 0x84) && (fadt_rev2_needed))) ||
1238 ((fadt_file) && ((fadt_file->Length < 0x84) && (fadt_rev2_needed))))
1239{
1240fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(0x84);
1241
1242if (fadt_file)
1243memcpy(fadt_mod, fadt_file, fadt_file->Length);
1244else
1245memcpy(fadt_mod, fadt, fadt->Length);
1246
1247fadt_mod->Length = 0x84;
1248fadt_mod->Revision = 0x02; // FADT rev 2 (ACPI 1.0B MS extensions)
1249}
1250else
1251{
1252if (fadt_file)
1253{
1254fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(fadt_file->Length);
1255memcpy(fadt_mod, fadt_file, fadt_file->Length);
1256} else {
1257fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(fadt->Length);
1258memcpy(fadt_mod, fadt, fadt->Length);
1259}
1260}
1261}
1262// Determine system type / PM_Model
1263if ( (value=getStringForKey(kSystemType, &bootInfo->bootConfig))!=NULL)
1264{
1265 if (Platform.Type > 6)
1266 {
1267 if(fadt_mod->Preferred_PM_Profile<=6)
1268 Platform.Type = fadt_mod->Preferred_PM_Profile; // get the fadt if correct
1269 else
1270 Platform.Type = 1;/* Set a fixed value (Desktop) */
1271 verbose("Error: system-type must be 0..6. Defaulting to %d !\n", Platform.Type);
1272 }
1273 else
1274 Platform.Type = (unsigned char) strtoul(value, NULL, 10);
1275}
1276// Set Preferred_PM_Profile from System-type only if user wanted this value to be forced
1277if (fadt_mod->Preferred_PM_Profile != Platform.Type)
1278{
1279 if (value)
1280 { // user has overriden the SystemType so take care of it in FACP
1281verbose("FADT: changing Preferred_PM_Profile from 0x%02x to 0x%02x\n", fadt_mod->Preferred_PM_Profile, Platform.Type);
1282fadt_mod->Preferred_PM_Profile = Platform.Type;
1283 }
1284 else
1285 { // Preferred_PM_Profile has a different value and no override has been set, so reflect the user value to ioregs
1286 Platform.Type = fadt_mod->Preferred_PM_Profile <= 6 ? fadt_mod->Preferred_PM_Profile : 1;
1287 }
1288}
1289// We now have to write the systemm-type in ioregs: we cannot do it before in setupDeviceTree()
1290// because we need to take care of facp original content, if it is correct.
1291setupSystemType();
1292
1293// Patch FADT to fix restart
1294if (fix_restart)
1295{
1296fadt_mod->Flags|= 0x400;
1297fadt_mod->RESET_REG = FillGASStruct(0x0cf9, 1);
1298fadt_mod->RESET_VALUE = 0x06;
1299
1300verbose("FADT: Restart Fix applied !\n");
1301}
1302
1303// Patch FACS Address
1304fadt_mod->FIRMWARE_CTRL=(uint32_t)fadt->FIRMWARE_CTRL;
1305if ((uint32_t)(&(fadt_mod->X_FIRMWARE_CTRL))-(uint32_t)fadt_mod+8<=fadt_mod->Length)
1306fadt_mod->X_FIRMWARE_CTRL=(uint32_t)fadt->FIRMWARE_CTRL;
1307
1308// Patch DSDT Address if we have one loaded
1309if(new_dsdt)
1310{
1311fadt_mod->DSDT=(uint32_t)new_dsdt;
1312if ((uint32_t)(&(fadt_mod->X_DSDT))-(uint32_t)fadt_mod+8<=fadt_mod->Length)
1313fadt_mod->X_DSDT=(uint32_t)new_dsdt;
1314}
1315
1316
1317// Correct the checksum
1318fadt_mod->Checksum=0;
1319fadt_mod->Checksum=256-checksum8(fadt_mod,fadt_mod->Length);
1320
1321return fadt_mod;
1322}
1323#if UNUSED
1324/* Setup ACPI without replacing DSDT. */
1325int setupAcpiNoMod()
1326{
1327//addConfigurationTable(&gEfiAcpiTableGuid, getAddressOfAcpiTable(), "ACPI");
1328//addConfigurationTable(&gEfiAcpi20TableGuid, getAddressOfAcpi20Table(), "ACPI_20");
1329/* XXX aserebln why uint32 cast if pointer is uint64 ? */
1330acpi10_p = (uint32_t)getAddressOfAcpiTable();
1331acpi20_p = (uint32_t)getAddressOfAcpi20Table();
1332addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
1333if(acpi20_p) addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
1334return 1;
1335}
1336#endif
1337
1338/* Setup ACPI. Replace DSDT if DSDT.aml is found */
1339int setupAcpi(void)
1340{
1341int version;
1342void *new_dsdt=NULL, *new_hpet=NULL, *new_sbst=NULL, *new_ecdt=NULL, *new_asft=NULL, *new_dmar=NULL, *new_apic=NULL, *new_mcfg=NULL;//, *new_ssdt[14];
1343
1344struct acpi_2_ssdt *new_ssdt[16]; // 2 additional tables for pss/tss & cst
1345struct acpi_2_fadt *fadt; // will be used in CST generator
1346
1347bool oem_dsdt=false, oem_ssdt=false, oem_hpet=false, oem_sbst=false, oem_ecdt=false, oem_asft=false, oem_dmar=false, oem_apic=false, oem_mcfg=false;
1348bool drop_ssdt=false, drop_hpet=false, drop_slic=false, drop_sbst=false, drop_ecdt=false, drop_asft=false, drop_dmar=false;
1349bool update_acpi=false, gen_xsdt=false;
1350bool hpet_replaced=false, sbst_replaced=false, ecdt_replaced=false, asft_replaced=false, dmar_replaced=false, apic_replaced=false, mcfg_replaced=false;
1351bool hpet_added=false, sbst_added=false, ecdt_added=false, asft_added=false, dmar_added=false, apic_added=false, mcfg_added=false;
1352bool gen_cst=false, gen_pss=false, gen_tss=false;
1353
1354int curssdt=0, loadtotssdt=0, totssdt=0, newtotssdt=0;
1355
1356{
1357bool tmpval, tmpval2, tmpval3, tmpval4, tmpval6;
1358
1359drop_ssdt = getBoolForKey(kDropSSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1360drop_hpet = getBoolForKey(kDropHPET, &tmpval, &bootInfo->bootConfig)&&tmpval;
1361drop_slic = getBoolForKey(kDropSLIC, &tmpval, &bootInfo->bootConfig)&&tmpval;
1362drop_sbst = getBoolForKey(kDropSBST, &tmpval, &bootInfo->bootConfig)&&tmpval;
1363drop_ecdt = getBoolForKey(kDropECDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1364drop_asft = getBoolForKey(kDropASFT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1365drop_dmar = getBoolForKey(kDropDMAR, &tmpval, &bootInfo->bootConfig)&&tmpval;
1366
1367oem_dsdt = getBoolForKey(kOEMDSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1368oem_ssdt = getBoolForKey(kOEMSSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1369oem_hpet = getBoolForKey(kOEMHPET, &tmpval, &bootInfo->bootConfig)&&tmpval;
1370oem_sbst = getBoolForKey(kOEMSBST, &tmpval, &bootInfo->bootConfig)&&tmpval;
1371oem_ecdt = getBoolForKey(kOEMECDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1372oem_asft = getBoolForKey(kOEMASFT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1373oem_dmar = getBoolForKey(kOEMDMAR, &tmpval, &bootInfo->bootConfig)&&tmpval;
1374oem_apic = getBoolForKey(kOEMAPIC, &tmpval, &bootInfo->bootConfig)&&tmpval;
1375oem_mcfg = getBoolForKey(kOEMMCFG, &tmpval, &bootInfo->bootConfig)&&tmpval;
1376
1377gen_cst = (getBoolForKey(kGenerateCStates, &tmpval, &bootInfo->bootConfig)&&tmpval)
1378| (getBoolForKey(kEnableC2State, &tmpval2, &bootInfo->bootConfig)&&tmpval2)
1379| (getBoolForKey(kEnableC3State, &tmpval3, &bootInfo->bootConfig)&&tmpval3)
1380| (getBoolForKey(kEnableC4State, &tmpval4, &bootInfo->bootConfig)&&tmpval4)
1381| (getBoolForKey(kEnableC6State, &tmpval6, &bootInfo->bootConfig)&&tmpval6);
1382
1383gen_pss = getBoolForKey(kGeneratePStates, &tmpval, &bootInfo->bootConfig)&&tmpval;
1384
1385gen_tss = getBoolForKey(kGenerateTStates, &tmpval, &bootInfo->bootConfig)&&tmpval;
1386
1387update_acpi = getBoolForKey(kUpdateACPI, &tmpval, &bootInfo->bootConfig)&&tmpval;
1388}
1389
1390// Load replacement ACPI tables
1391if (!oem_dsdt)
1392new_dsdt=loadACPITable(kDSDT);
1393
1394if (!oem_hpet)
1395new_hpet=loadACPITable(kHPET);
1396
1397if (!oem_sbst)
1398new_sbst=loadACPITable(kSBST);
1399
1400if (!oem_ecdt)
1401new_ecdt=loadACPITable(kECDT);
1402
1403if (!oem_asft)
1404new_asft=loadACPITable(kASFT);
1405
1406if (!oem_dmar)
1407new_dmar=loadACPITable(kDMAR);
1408
1409if (!oem_apic)
1410new_apic=loadACPITable(kAPIC);
1411
1412if (!oem_mcfg)
1413new_mcfg=loadACPITable(kMCFG);
1414
1415if (gen_cst || gen_pss || gen_tss) oem_ssdt = false;
1416
1417if (!oem_ssdt)
1418{
1419for (curssdt=0;curssdt<14;curssdt++)
1420{
1421new_ssdt[curssdt]=loadSSDTTable(curssdt);
1422if (new_ssdt[curssdt])
1423loadtotssdt++;
1424}
1425curssdt=0;
1426}
1427/*
1428if (!new_dsdt)
1429return setupAcpiNoMod();
1430*/
1431DBG("New ACPI tables Loaded in memory\n");
1432
1433// Do the same procedure for both versions of ACPI
1434for (version=0; version<2; version++) {
1435struct acpi_2_rsdp *rsdp, *rsdp_mod, *rsdp_conv=(struct acpi_2_rsdp *)0;
1436struct acpi_2_rsdt *rsdt, *rsdt_mod;
1437struct acpi_2_xsdt *xsdt_conv = (struct acpi_2_xsdt *)0;
1438int rsdplength;
1439
1440// Find original rsdp
1441rsdp=(struct acpi_2_rsdp *)(version?getAddressOfAcpi20Table():getAddressOfAcpiTable());
1442if ((update_acpi) && (rsdp->Revision == 0))
1443{
1444rsdp_conv = (struct acpi_2_rsdp *)AllocateKernelMemory(sizeof(struct acpi_2_rsdp));
1445memcpy(rsdp_conv, rsdp, 20);
1446
1447/* Add/change fields */
1448strncpy(rsdp->OEMID, "Apple ", 6);
1449rsdp_conv->Revision = 2; /* ACPI version 3 */
1450rsdp_conv->Length = sizeof(struct acpi_2_rsdp);
1451
1452/* Correct checksums */
1453rsdp_conv->Checksum = 0;
1454rsdp_conv->Checksum = 256-checksum8(rsdp_conv, 20);
1455rsdp_conv->ExtendedChecksum = 0;
1456rsdp_conv->ExtendedChecksum = 256-checksum8(rsdp_conv, rsdp_conv->Length);
1457
1458rsdp = rsdp_conv;
1459
1460gen_xsdt = true;
1461version = 1;
1462
1463addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI");
1464
1465verbose("Converted ACPI RSD PTR version 1 to version 3\n");
1466}
1467if (!rsdp)
1468{
1469DBG("No ACPI version %d found. Ignoring\n", version+1);
1470if (version)
1471addConfigurationTable(&gEfiAcpi20TableGuid, NULL, "ACPI_20");
1472else
1473addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI");
1474continue;
1475}
1476rsdplength=version?rsdp->Length:20;
1477
1478DBG("RSDP version %d found @%x. Length=%d\n",version+1,rsdp,rsdplength);
1479
1480/* FIXME: no check that memory allocation succeeded
1481 * Copy and patch RSDP,RSDT, XSDT and FADT
1482 * For more info see ACPI Specification pages 110 and following
1483 */
1484
1485if (gen_xsdt)
1486{
1487rsdp_mod=rsdp_conv;
1488} else {
1489rsdp_mod=(struct acpi_2_rsdp *) AllocateKernelMemory(rsdplength);
1490memcpy(rsdp_mod, rsdp, rsdplength);
1491}
1492
1493rsdt=(struct acpi_2_rsdt *)(rsdp->RsdtAddress);
1494
1495DBG("RSDT @%x, Length %d\n",rsdt, rsdt->Length);
1496
1497if (rsdt && (uint32_t)rsdt !=0xffffffff && rsdt->Length<0x10000)
1498{
1499uint32_t *rsdt_entries;
1500int rsdt_entries_num;
1501int dropoffset=0, i;
1502
1503rsdt_mod=(struct acpi_2_rsdt *)AllocateKernelMemory(rsdt->Length);
1504memcpy (rsdt_mod, rsdt, rsdt->Length);
1505rsdp_mod->RsdtAddress=(uint32_t)rsdt_mod;
1506rsdt_entries_num=(rsdt_mod->Length-sizeof(struct acpi_2_rsdt))/4;
1507rsdt_entries=(uint32_t *)(rsdt_mod+1);
1508
1509if (gen_xsdt)
1510{
1511uint64_t *xsdt_conv_entries;
1512
1513xsdt_conv=(struct acpi_2_xsdt *)AllocateKernelMemory(sizeof(struct acpi_2_xsdt)+(rsdt_entries_num * 8));
1514memcpy(xsdt_conv, rsdt, sizeof(struct acpi_2_rsdt));
1515
1516xsdt_conv->Signature[0] = 'X';
1517xsdt_conv->Signature[1] = 'S';
1518xsdt_conv->Signature[2] = 'D';
1519xsdt_conv->Signature[3] = 'T';
1520xsdt_conv->Length = sizeof(struct acpi_2_xsdt)+(rsdt_entries_num * 8);
1521
1522xsdt_conv_entries=(uint64_t *)(xsdt_conv+1);
1523
1524for (i=0;i<rsdt_entries_num;i++)
1525{
1526xsdt_conv_entries[i] = (uint64_t)rsdt_entries[i];
1527}
1528
1529xsdt_conv->Checksum = 0;
1530xsdt_conv->Checksum = 256-checksum8(xsdt_conv, xsdt_conv->Length);
1531
1532rsdp->XsdtAddress = (uint32_t)xsdt_conv;
1533
1534rsdp->ExtendedChecksum = 0;
1535rsdp->ExtendedChecksum = 256-checksum8(rsdp, rsdp->Length);
1536
1537verbose("Converted RSDT table to XSDT table\n");
1538}
1539
1540for (i=0;i<rsdt_entries_num;i++)
1541{
1542char *table=(char *)(rsdt_entries[i]);
1543if (!table)
1544continue;
1545
1546DBG("TABLE %c%c%c%c,",table[0],table[1],table[2],table[3]);
1547
1548rsdt_entries[i-dropoffset]=rsdt_entries[i];
1549if (drop_ssdt && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1550{
1551dropoffset++;
1552continue;
1553}
1554if (drop_hpet && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')
1555{
1556dropoffset++;
1557continue;
1558}
1559if (drop_slic && table[0]=='S' && table[1]=='L' && table[2]=='I' && table[3]=='C')
1560{
1561dropoffset++;
1562continue;
1563}
1564if (drop_sbst && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')
1565{
1566dropoffset++;
1567continue;
1568}
1569if (drop_ecdt && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')
1570{
1571dropoffset++;
1572continue;
1573}
1574if (drop_asft && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')
1575{
1576dropoffset++;
1577continue;
1578}
1579if (drop_dmar && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')
1580{
1581dropoffset++;
1582continue;
1583}
1584if ((!(oem_hpet)) && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')
1585{
1586DBG("HPET found\n");
1587if (new_hpet)
1588{
1589rsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
1590hpet_replaced=true;
1591}
1592continue;
1593}
1594if ((!(oem_sbst)) && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')
1595{
1596DBG("SBST found\n");
1597if (new_sbst)
1598{
1599rsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
1600sbst_replaced=true;
1601}
1602continue;
1603}
1604if ((!(oem_ecdt)) && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')
1605{
1606DBG("ECDT found\n");
1607if (new_ecdt)
1608{
1609rsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
1610ecdt_replaced=true;
1611}
1612continue;
1613}
1614if ((!(oem_asft)) && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')
1615{
1616DBG("ASF! found\n");
1617if (new_asft)
1618{
1619rsdt_entries[i-dropoffset]=(uint32_t)new_asft;
1620asft_replaced=true;
1621}
1622continue;
1623}
1624if ((!(oem_dmar)) && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')
1625{
1626DBG("DMAR found\n");
1627if (new_dmar)
1628{
1629rsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
1630dmar_replaced=true;
1631}
1632continue;
1633}
1634if ((!(oem_apic)) && table[0]=='A' && table[1]=='P' && table[2]=='I' && table[3]=='C')
1635{
1636DBG("APIC found\n");
1637if (new_apic)
1638{
1639rsdt_entries[i-dropoffset]=(uint32_t)new_apic;
1640apic_replaced=true;
1641}
1642continue;
1643}
1644if ((!(oem_mcfg)) && table[0]=='M' && table[1]=='C' && table[2]=='F' && table[3]=='G')
1645{
1646DBG("MCFG found\n");
1647if (new_mcfg)
1648{
1649rsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
1650mcfg_replaced=true;
1651}
1652continue;
1653}
1654if ((!(oem_ssdt)) && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1655{
1656DBG("SSDT %d found", curssdt);
1657if (new_ssdt[curssdt])
1658{
1659DBG(" and replaced");
1660rsdt_entries[i-dropoffset]=(uint32_t)new_ssdt[curssdt];
1661totssdt++;
1662}
1663DBG("\n");
1664curssdt++;
1665continue;
1666}
1667if (table[0]=='D' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1668{
1669DBG("DSDT found\n");
1670rsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;
1671continue;
1672
1673} else {
1674struct acpi_2_rsdt *t = (struct acpi_2_rsdt *)table;
1675strncpy(t->OEMID, "Apple ", 6);
1676strncpy(t->OEMTableId, MacModel, 8);
1677t->OEMRevision = ModelRev;
1678t->Checksum=0;
1679t->Checksum=256-checksum8(t,t->Length);
1680}
1681if (table[0]=='F' && table[1]=='A' && table[2]=='C' && table[3]=='P')
1682{
1683struct acpi_2_fadt *fadt_mod;
1684fadt=(struct acpi_2_fadt *)rsdt_entries[i];
1685
1686DBG("FADT found @%x, Length %d\n",fadt, fadt->Length);
1687
1688if (!fadt || (uint32_t)fadt == 0xffffffff || fadt->Length>0x10000)
1689{
1690printf("FADT incorrect. Not modified\n");
1691continue;
1692}
1693
1694fadt_mod = patch_fadt(fadt, new_dsdt, update_acpi);
1695rsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;
1696
1697if(!oem_ssdt)
1698{
1699// Generate _CST SSDT
1700if ( gen_cst && (new_ssdt[loadtotssdt] = generate_cst_ssdt(fadt_mod)))
1701{
1702gen_cst= false;
1703loadtotssdt++;
1704}
1705
1706// Generating _PSS SSDT
1707if (gen_pss && (new_ssdt[loadtotssdt] = generate_pss_ssdt((void*)fadt_mod->DSDT)))
1708{
1709gen_pss= false;
1710loadtotssdt++;
1711}
1712
1713// Generating _TSS SSDT
1714if (gen_tss && (new_ssdt[loadtotssdt] = generate_tss_ssdt((void*)fadt_mod->DSDT)))
1715{
1716gen_tss= false;
1717loadtotssdt++;
1718}
1719}
1720
1721continue;
1722}
1723}
1724DBG("\n");
1725
1726strncpy(rsdt_mod->OEMID, "Apple ", 6);
1727strncpy(rsdt_mod->OEMTableId, MacModel, 8);
1728rsdt_mod->OEMRevision = ModelRev;
1729
1730if ((!oem_hpet) && (!hpet_replaced))
1731{
1732if (new_hpet)
1733{
1734rsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
1735hpet_added=true;
1736i++;
1737}
1738}
1739
1740if ((!oem_sbst) && (!sbst_replaced))
1741{
1742if (new_sbst)
1743{
1744rsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
1745sbst_added=true;
1746i++;
1747}
1748}
1749
1750if ((!oem_ecdt) && (!ecdt_replaced))
1751{
1752if (new_ecdt)
1753{
1754rsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
1755ecdt_added=true;
1756i++;
1757}
1758}
1759
1760if ((!oem_asft) && (!asft_replaced))
1761{
1762if (new_asft)
1763{
1764rsdt_entries[i-dropoffset]=(uint32_t)new_asft;
1765asft_added=true;
1766i++;
1767}
1768}
1769
1770if ((!oem_dmar) && (!dmar_replaced))
1771{
1772if (new_dmar)
1773{
1774rsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
1775dmar_added=true;
1776i++;
1777}
1778}
1779
1780if ((!oem_apic) && (!apic_replaced))
1781{
1782if (new_apic)
1783{
1784rsdt_entries[i-dropoffset]=(uint32_t)new_apic;
1785apic_added=true;
1786i++;
1787}
1788}
1789
1790if ((!oem_mcfg) && (!mcfg_replaced))
1791{
1792if (new_mcfg)
1793{
1794rsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
1795mcfg_added=true;
1796i++;
1797}
1798}
1799
1800if (!oem_ssdt)
1801{
1802while ((totssdt < loadtotssdt) && (curssdt < 14))
1803{
1804if (new_ssdt[curssdt])
1805{
1806DBG("adding SSDT %d\n", curssdt);
1807rsdt_entries[i-dropoffset]=(uint32_t)new_ssdt[curssdt];
1808totssdt++;
1809newtotssdt++;
1810i++;
1811}
1812curssdt++;
1813}
1814}
1815
1816// Correct the checksum of RSDT
1817rsdt_mod->Length-=4*dropoffset;
1818rsdt_mod->Length+=4*newtotssdt;
1819if (hpet_added)
1820rsdt_mod->Length+=4;
1821if (sbst_added)
1822rsdt_mod->Length+=4;
1823if (ecdt_added)
1824rsdt_mod->Length+=4;
1825if (asft_added)
1826rsdt_mod->Length+=4;
1827if (dmar_added)
1828rsdt_mod->Length+=4;
1829if (apic_added)
1830rsdt_mod->Length+=4;
1831if (mcfg_added)
1832rsdt_mod->Length+=4;
1833
1834DBG("RSDT: Original checksum %d, ", rsdt_mod->Checksum);
1835
1836rsdt_mod->Checksum=0;
1837rsdt_mod->Checksum=256-checksum8(rsdt_mod,rsdt_mod->Length);
1838
1839DBG("New checksum %d at %x\n", rsdt_mod->Checksum,rsdt_mod);
1840}
1841else
1842{
1843rsdp_mod->RsdtAddress=0;
1844printf("RSDT not found or incorrect\n");
1845}
1846
1847if (version)
1848{
1849struct acpi_2_xsdt *xsdt, *xsdt_mod;
1850
1851// FIXME: handle 64-bit address correctly
1852
1853if (gen_xsdt)
1854xsdt=xsdt_conv;
1855else
1856xsdt=(struct acpi_2_xsdt*) ((uint32_t)rsdp->XsdtAddress);
1857
1858DBG("XSDT @%x;%x, Length=%d\n", (uint32_t)(rsdp->XsdtAddress>>32),(uint32_t)rsdp->XsdtAddress, xsdt->Length);
1859if (xsdt && (uint64_t)rsdp->XsdtAddress<0xffffffff && xsdt->Length<0x10000)
1860{
1861uint64_t *xsdt_entries;
1862int xsdt_entries_num, i;
1863int dropoffset=0;
1864curssdt=0, totssdt=0, newtotssdt=0;
1865hpet_replaced=false, hpet_added=false;
1866sbst_replaced=false, sbst_added=false;
1867ecdt_replaced=false, ecdt_added=false;
1868asft_replaced=false, asft_added=false;
1869dmar_replaced=false, dmar_added=false;
1870apic_replaced=false, apic_added=false;
1871mcfg_replaced=false, mcfg_added=false;
1872
1873if (gen_xsdt)
1874xsdt_mod=xsdt;
1875else
1876{
1877xsdt_mod=(struct acpi_2_xsdt*)AllocateKernelMemory(xsdt->Length);
1878memcpy(xsdt_mod, xsdt, xsdt->Length);
1879}
1880
1881rsdp_mod->XsdtAddress=(uint32_t)xsdt_mod;
1882xsdt_entries_num=(xsdt_mod->Length-sizeof(struct acpi_2_xsdt))/8;
1883xsdt_entries=(uint64_t *)(xsdt_mod+1);
1884for (i=0;i<xsdt_entries_num;i++)
1885{
1886char *table=(char *)((uint32_t)(xsdt_entries[i]));
1887if (!table)
1888continue;
1889xsdt_entries[i-dropoffset]=xsdt_entries[i];
1890if (drop_ssdt && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1891{
1892dropoffset++;
1893continue;
1894}
1895if (drop_hpet && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')
1896{
1897dropoffset++;
1898continue;
1899}
1900if (drop_slic && table[0]=='S' && table[1]=='L' && table[2]=='I' && table[3]=='C')
1901{
1902dropoffset++;
1903continue;
1904}
1905if (drop_sbst && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')
1906{
1907dropoffset++;
1908continue;
1909}
1910if (drop_ecdt && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')
1911{
1912dropoffset++;
1913continue;
1914}
1915if (drop_asft && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')
1916{
1917dropoffset++;
1918continue;
1919}
1920if (drop_dmar && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')
1921{
1922dropoffset++;
1923continue;
1924}
1925if ((!(oem_hpet)) && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')
1926{
1927DBG("HPET found\n");
1928if (new_hpet)
1929{
1930xsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
1931hpet_replaced=true;
1932}
1933continue;
1934}
1935if ((!(oem_sbst)) && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')
1936{
1937DBG("SBST found\n");
1938if (new_sbst)
1939{
1940xsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
1941sbst_replaced=true;
1942}
1943continue;
1944}
1945if ((!(oem_ecdt)) && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')
1946{
1947DBG("ECDT found\n");
1948if (new_ecdt)
1949{
1950xsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
1951ecdt_replaced=true;
1952}
1953continue;
1954}
1955if ((!(oem_asft)) && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')
1956{
1957DBG("ASF! found\n");
1958if (new_asft)
1959{
1960xsdt_entries[i-dropoffset]=(uint32_t)new_asft;
1961asft_replaced=true;
1962}
1963continue;
1964}
1965if ((!(oem_dmar)) && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')
1966{
1967DBG("DMAR found\n");
1968if (new_dmar)
1969{
1970xsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
1971dmar_replaced=true;
1972}
1973continue;
1974}
1975if ((!(oem_apic)) && table[0]=='A' && table[1]=='P' && table[2]=='I' && table[3]=='C')
1976{
1977DBG("APIC found\n");
1978if (new_apic)
1979{
1980xsdt_entries[i-dropoffset]=(uint32_t)new_apic;
1981apic_replaced=true;
1982}
1983continue;
1984}
1985if ((!(oem_mcfg)) && table[0]=='M' && table[1]=='C' && table[2]=='F' && table[3]=='G')
1986{
1987DBG("MCFG found\n");
1988if (new_mcfg)
1989{
1990xsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
1991mcfg_replaced=true;
1992}
1993continue;
1994}
1995if ((!(oem_ssdt)) && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1996{
1997DBG("SSDT %d found", curssdt);
1998if (new_ssdt[curssdt])
1999{
2000DBG(" and replaced");
2001xsdt_entries[i-dropoffset]=(uint32_t)new_ssdt[curssdt];
2002totssdt++;
2003}
2004DBG("\n");
2005curssdt++;
2006continue;
2007}
2008if (table[0]=='D' && table[1]=='S' && table[2]=='D' && table[3]=='T')
2009{
2010DBG("DSDT found\n");
2011
2012xsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;
2013
2014DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
2015
2016continue;
2017}
2018
2019struct acpi_2_xsdt* t = (struct acpi_2_xsdt*)table;
2020strncpy(t->OEMID, "Apple ", 6);
2021strncpy(t->OEMTableId, MacModel, 8);
2022t->OEMRevision = ModelRev;
2023
2024if (table[0]=='F' && table[1]=='A' && table[2]=='C' && table[3]=='P')
2025{
2026struct acpi_2_fadt *fadt_mod;
2027fadt=(struct acpi_2_fadt *)(uint32_t)xsdt_entries[i];
2028
2029DBG("FADT found @%x,%x, Length %d\n",(uint32_t)(xsdt_entries[i]>>32),fadt,
2030 fadt->Length);
2031
2032if (!fadt || (uint64_t)xsdt_entries[i] >= 0xffffffff || fadt->Length>0x10000)
2033{
2034verbose("FADT incorrect or after 4GB. Dropping XSDT\n");
2035goto drop_xsdt;
2036}
2037
2038fadt_mod = patch_fadt(fadt, new_dsdt, update_acpi);
2039xsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;
2040
2041DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
2042
2043if (!oem_ssdt)
2044{
2045// Generate _CST SSDT
2046if ( gen_cst && (new_ssdt[loadtotssdt] = generate_cst_ssdt(fadt_mod)))
2047{
2048gen_cst= false;
2049loadtotssdt++;
2050}
2051
2052// Generating _PSS SSDT
2053if (gen_pss && (new_ssdt[loadtotssdt] = generate_pss_ssdt((void*)fadt_mod->DSDT)))
2054{
2055gen_pss= false;
2056loadtotssdt++;
2057}
2058
2059// Generating _TSS SSDT
2060if (gen_tss && (new_ssdt[loadtotssdt] = generate_tss_ssdt((void*)fadt_mod->DSDT)))
2061{
2062gen_tss= false;
2063loadtotssdt++;
2064}
2065}
2066
2067continue;
2068}
2069
2070DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
2071
2072}
2073
2074strncpy(xsdt_mod->OEMID, "Apple ", 6);
2075strncpy(xsdt_mod->OEMTableId, MacModel, 8);
2076xsdt_mod->OEMRevision = ModelRev;
2077
2078if ((!oem_hpet) && (!hpet_replaced))
2079{
2080if (new_hpet)
2081{
2082xsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
2083hpet_added=true;
2084i++;
2085}
2086}
2087
2088if ((!oem_sbst) && (!sbst_replaced))
2089{
2090if (new_sbst)
2091{
2092xsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
2093sbst_added=true;
2094i++;
2095}
2096}
2097
2098if ((!oem_ecdt) && (!ecdt_replaced))
2099{
2100if (new_ecdt)
2101{
2102xsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
2103ecdt_added=true;
2104i++;
2105}
2106}
2107
2108if ((!oem_asft) && (!asft_replaced))
2109{
2110if (new_asft)
2111{
2112xsdt_entries[i-dropoffset]=(uint32_t)new_asft;
2113asft_added=true;
2114i++;
2115}
2116}
2117
2118if ((!oem_dmar) && (!dmar_replaced))
2119{
2120if (new_dmar)
2121{
2122xsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
2123dmar_added=true;
2124i++;
2125}
2126}
2127
2128if ((!oem_apic) && (!apic_replaced))
2129{
2130if (new_apic)
2131{
2132xsdt_entries[i-dropoffset]=(uint32_t)new_apic;
2133apic_added=true;
2134i++;
2135}
2136}
2137
2138if ((!oem_mcfg) && (!mcfg_replaced))
2139{
2140if (new_mcfg)
2141{
2142xsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
2143mcfg_added=true;
2144i++;
2145}
2146}
2147
2148if (!oem_ssdt)
2149{
2150while ((totssdt < loadtotssdt) && (curssdt < 14))
2151{
2152if (new_ssdt[curssdt])
2153{
2154DBG("adding SSDT %d\n", curssdt);
2155xsdt_entries[i-dropoffset]=(uint32_t)new_ssdt[curssdt];
2156totssdt++;
2157newtotssdt++;
2158i++;
2159}
2160curssdt++;
2161}
2162}
2163
2164// Correct the checksum of XSDT
2165xsdt_mod->Length-=8*dropoffset;
2166xsdt_mod->Length+=8*newtotssdt;
2167if (hpet_added)
2168xsdt_mod->Length+=8;
2169if (sbst_added)
2170xsdt_mod->Length+=8;
2171if (ecdt_added)
2172xsdt_mod->Length+=8;
2173if (asft_added)
2174xsdt_mod->Length+=8;
2175if (dmar_added)
2176xsdt_mod->Length+=8;
2177if (apic_added)
2178xsdt_mod->Length+=8;
2179if (mcfg_added)
2180xsdt_mod->Length+=8;
2181
2182xsdt_mod->Checksum=0;
2183xsdt_mod->Checksum=256-checksum8(xsdt_mod,xsdt_mod->Length);
2184}
2185else
2186{
2187drop_xsdt:
2188
2189DBG("About to drop XSDT\n");
2190
2191/*FIXME: Now we just hope that if MacOS doesn't find XSDT it reverts to RSDT.
2192 * A Better strategy would be to generate
2193 */
2194
2195rsdp_mod->XsdtAddress=0xffffffffffffffffLL;
2196verbose("XSDT not found or incorrect\n");
2197}
2198}
2199
2200// Correct the checksum of RSDP
2201
2202DBG("RSDP: Original checksum %d, ", rsdp_mod->Checksum);
2203
2204rsdp_mod->Checksum=0;
2205rsdp_mod->Checksum=256-checksum8(rsdp_mod,20);
2206
2207DBG("New checksum %d\n", rsdp_mod->Checksum);
2208
2209if (version)
2210{
2211DBG("RSDP: Original extended checksum %d", rsdp_mod->ExtendedChecksum);
2212
2213rsdp_mod->ExtendedChecksum=0;
2214rsdp_mod->ExtendedChecksum=256-checksum8(rsdp_mod,rsdp_mod->Length);
2215
2216DBG("New extended checksum %d\n", rsdp_mod->ExtendedChecksum);
2217
2218}
2219
2220verbose("Patched ACPI version %d DSDT\n", version+1);
2221if (version)
2222{
2223/* XXX aserebln why uint32 cast if pointer is uint64 ? */
2224acpi20_p = (uint32_t)rsdp_mod;
2225acpi10_p = (uint32_t)rsdp_mod;
2226addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
2227addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
2228}
2229else
2230{
2231/* XXX aserebln why uint32 cast if pointer is uint64 ? */
2232acpi10_p = (uint32_t)rsdp_mod;
2233addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
2234}
2235}
2236#if DEBUG_ACPI
2237printf("Press a key to continue... (DEBUG_ACPI)\n");
2238getc();
2239#endif
2240return 1;
2241}
2242

Archive Download this file

Revision: 698