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 ("Not an Intel platform: C-States will not be generated !!!\n");
252return NULL;
253}
254
255if (fadt == NULL) {
256verbose ("FACP not exists: C-States will not be generated !!!\n");
257return NULL;
258}
259
260struct acpi_2_dsdt* dsdt = (void*)fadt->DSDT;
261
262if (dsdt == NULL) {
263verbose ("DSDT not found: C-States will not be generated !!!\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_");
321struct aml_chunk* name = aml_add_name(scop, "CST_");
322struct aml_chunk* pack = aml_add_package(name);
323aml_add_byte(pack, cstates_count);
324struct aml_chunk* tmpl = aml_add_package(pack);
325
326switch (Platform.CPU.Family) {
327case 0x06:
328{
329switch (Platform.CPU.Model)
330{
331case 0x0F: // Core (65nm)
332case 0x1A: // Core i7, Xeon 5500 series - Bloomfield, Gainstown NHM-EP - LGA1366 (45nm)
333case 0x1E: // Core i5, i7 - Clarksfield, Lynnfield, Jasper Forest - LGA1156 (45nm)
334case 0x1F: // Core i5, i7 - Nehalem
335case 0x25: // Core i3, i5, i7 - Westmere Client - Clarkdale, Arrandale - LGA1156 (32nm)
336case 0x2C: // Core i7 - Westmere EP - Gulftown - LGA1366 (32nm) 6 Core
337case 0x2E: // Westmere-Ex Xeon
338case 0x2F: // Westmere-Ex Xeon - Eagelton
339
340// C1
341cstate_resource_template[11] = 0x00; // C1-Nehalem
342aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
343aml_add_byte(tmpl, 0x01); // C1
344aml_add_byte(tmpl, 0x03); // Latency
345aml_add_word(tmpl, 0x03e8); // Power
346verbose ("C1 ");
347
348// C2
349if (c2_enabled)
350{
351tmpl = aml_add_package(pack);
352cstate_resource_template[11] = 0x10; // C3-Nehalem
353aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
354aml_add_byte(tmpl, 0x02); // C2
355aml_add_byte(tmpl, 0x14); // Latency
356aml_add_word(tmpl, 0x01f4); // Power
357verbose ("C3 ");
358}
359
360// C3
361if (c3_enabled)
362{
363tmpl = aml_add_package(pack);
364cstate_resource_template[11] = 0x20; // C6-Nehalem
365aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
366aml_add_byte(tmpl, 0x03); // C3
367aml_add_word(tmpl, 0xc8); // Latency
368aml_add_word(tmpl, 0x015e); // Power
369verbose ("C6");
370}
371verbose("\n");
372
373break;
374
375case 0x1C: // Atom (45nm)
376case 0x26: // Atom Lincroft
377
378// C1
379cstate_resource_template[11] = 0x00; // C1-Atom
380aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
381aml_add_byte(tmpl, 0x01); // C1
382aml_add_byte(tmpl, 0x01); // Latency
383aml_add_word(tmpl, 0x03e8); // Power
384verbose ("C1 ");
385
386// C2
387if (c2_enabled)
388{
389tmpl = aml_add_package(pack);
390cstate_resource_template[11] = 0x10; // C2-Atom
391aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
392aml_add_byte(tmpl, 0x02); // C2
393aml_add_byte(tmpl, fadt->P_LVL2_LAT); // Latency
394aml_add_word(tmpl, 0x01f4); // Power
395verbose ("C2 ");
396}
397
398// C3
399/*if (c3_enabled)
400{
401tmpl = aml_add_package(pack);
402cstate_resource_template[11] = 0x20; // C3-Atom
403aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
404aml_add_byte(tmpl, 0x03); // C3
405aml_add_word(tmpl, fadt->P_LVL3_LAT); // Latency
406aml_add_word(tmpl, 0x015e); // Power
407verbose ("C-State: Added C3\n");
408}*/
409
410// C4
411if (c4_enabled)
412{
413tmpl = aml_add_package(pack);
414cstate_resource_template[11] = 0x30; // C4-Atom
415aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
416aml_add_byte(tmpl, 0x03); // C4
417aml_add_word(tmpl, 0x64); // Latency
418aml_add_word(tmpl, 0x00fa); // Power
419verbose ("C4 ");
420}
421
422// C6
423if (c6_enabled)
424{
425tmpl = aml_add_package(pack);
426cstate_resource_template[11] = 0x40; // C6-Atom
427aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
428aml_add_byte(tmpl, 0x03); // C6
429aml_add_word(tmpl, 0xC8); // Latency
430aml_add_word(tmpl, 0x0096); // Power
431verbose ("C6 ");
432}
433verbose("\n");
434
435break;
436
437case 0x17:
438default:
439
440// C1
441cstate_resource_template[11] = 0x00; // C1
442aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
443aml_add_byte(tmpl, 0x01); // C1
444aml_add_byte(tmpl, 0x01); // Latency
445aml_add_word(tmpl, 0x03e8); // Power 1000
446verbose ("C1 ");
447
448// C2
449if (c2_enabled)
450{
451tmpl = aml_add_package(pack);
452cstate_resource_template[11] = 0x10; // C2
453aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
454aml_add_byte(tmpl, 0x02); // C2
455aml_add_byte(tmpl, 0x14); // Latency 20
456aml_add_word(tmpl, 0x01f4); // Power 500
457verbose ("C2 ");
458}
459
460// C3
461if (c3_enabled)
462{
463tmpl = aml_add_package(pack);
464cstate_resource_template[11] = 0x20; // C3
465aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
466aml_add_byte(tmpl, 0x03); // C3
467aml_add_word(tmpl, 0x28); // Latency 40
468aml_add_word(tmpl, 0x015e); // Power 350
469verbose ("C3 ");
470}
471
472// C4
473if (c4_enabled)
474{
475tmpl = aml_add_package(pack);
476cstate_resource_template[11] = 0x30; // C4
477aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
478aml_add_byte(tmpl, 0x03); // C4
479aml_add_word(tmpl, 0x64); // Latency 100
480aml_add_word(tmpl, 0x00fa); // Power 250
481verbose ("C4 ");
482}
483
484// C6
485if (c6_enabled)
486{
487tmpl = aml_add_package(pack);
488cstate_resource_template[11] = 0x40; // C6
489aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
490aml_add_byte(tmpl, 0x03); // C6
491aml_add_word(tmpl, 0xc8); // Latency 200
492aml_add_word(tmpl, 0x0096); // Power 150
493verbose ("C6");
494}
495verbose("\n");
496
497break;
498}
499}
500}
501
502// Aliaces
503int i;
504for (i = 0; i < acpi_cpu_count; i++)
505{
506char name[9];
507sprintf(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]);
508
509scop = aml_add_scope(root, name);
510aml_add_alias(scop, "CST_", "_CST");
511}
512
513
514aml_calculate_size(root);
515
516struct acpi_2_ssdt *ssdt = (struct acpi_2_ssdt *)AllocateKernelMemory(root->Size);
517
518aml_write_node(root, (void*)ssdt, 0);
519
520ssdt->Length = root->Size;
521ssdt->Checksum = 0;
522ssdt->Checksum = 256 - checksum8(ssdt, ssdt->Length);
523
524aml_destroy_node(root);
525
526//dumpPhysAddr("C-States SSDT content: ", ssdt, ssdt->Length);
527
528//verbose ("SSDT with CPU C-States generated successfully\n");
529
530return ssdt;
531}
532else
533{
534verbose ("ACPI CPUs not found: C-States not generated !!!\n");
535}
536
537return NULL;
538}
539
540uint8_t mV_to_VID(uint16_t mv) {
541if (Platform.CPU.Vendor == 0x756E6547)
542{
543if ((Platform.CPU.Family == 0x06) && (Platform.CPU.Model == 0x17))
544return ((mv * 10) - 7125) / 125;
545else
546return (mv - 700) / 16;
547}
548return 0;
549}
550
551uint16_t VID_to_mV(uint8_t VID) {
552if (Platform.CPU.Vendor == 0x756E6547)
553{
554if ((Platform.CPU.Family == 0x06) && (Platform.CPU.Model == 0x17))
555return (((int)VID * 125) + 7125) / 10;
556else
557return (((int)VID * 16) + 700);
558}
559return 0;
560}
561
562struct acpi_2_ssdt *generate_pss_ssdt(struct acpi_2_dsdt* dsdt)
563{
564char ssdt_header[] =
565{
5660x53, 0x53, 0x44, 0x54, 0x7E, 0x00, 0x00, 0x00, /* SSDT.... */
5670x01, 0x6A, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x00, /* ..PmRef. */
5680x43, 0x70, 0x75, 0x50, 0x6D, 0x00, 0x00, 0x00, /* CpuPm... */
5690x00, 0x30, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* .0..INTL */
5700x31, 0x03, 0x10, 0x20,/* 1.._*/
571};
572
573char ssdt_pct[] =
574{
5750x08, 0x5F, 0x50, 0x43, 0x54, 0x12, 0x2C,/* 00000030 "0._PCT.," */
5760x02, 0x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00,/* 00000038 "........" */
5770x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,/* 00000040 "........" */
5780x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x11, 0x14,/* 00000048 "....y..." */
5790x0A, 0x11, 0x82, 0x0C, 0x00, 0x7F, 0x00, 0x00,/* 00000050 "........" */
5800x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,/* 00000058 "........" */
5810x00, 0x79, 0x00
582};
583
584if (Platform.CPU.Vendor != 0x756E6547) {
585verbose ("Not an Intel platform: P-States will not be generated !!!\n");
586return NULL;
587}
588
589if (!(platformCPUFeature(CPU_FEATURE_MSR))) {
590verbose ("Unsupported CPU: P-States will not be generated !!!\n");
591return NULL;
592}
593
594if (acpi_cpu_count == 0)
595get_acpi_cpu_names((void*)dsdt, dsdt->Length);
596
597if (acpi_cpu_count > 0)
598{
599
600struct p_state initial, maximum, minimum, p_states[32];
601uint8_t p_states_count = 0;
602
603//TODO: make use of minimum & friends instead, (busratios, freqs ...)
604int busratio_min = Platform.CPU.MinRatio;
605int busratio_max = Platform.CPU.MaxRatio;
606
607int freq_max = ((Platform.CPU.FSBFrequency / 1000000) * busratio_max) / 10;
608int freq_min = ((Platform.CPU.FSBFrequency / 1000000) * busratio_min) / 10;
609int p = ((busratio_max - busratio_min) * 2) / 10;
610int f_step = (freq_max - freq_min) / p;
611if (Platform.CPU.SLFM) freq_min = (busratio_min * f_step) / 10;
612freq_max = (((Platform.CPU.FSBFrequency / 1000000) + 1) * busratio_max) / 10;
613
614//valv: minimum instead of current
615//initial.Control = rdmsr64(MSR_IA32_PERF_STATUS);
616initial.Control = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 48) & 0x1F3F);
617maximum.Control = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 32) & 0x1F3F) | (0x4000 * Platform.CPU.MaxDiv);
618
619maximum.FID = (busratio_max / 0xA) & 0x1F | (0x40 * Platform.CPU.MaxDiv);
620maximum.CID = ((maximum.FID & 0x1F) << 1) | Platform.CPU.MaxDiv;
621
622// current isn't always minimum
623//minimum.FID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 24) & 0x1F) | (0x80 * cpu_dynamic_fsb);
624minimum.FID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 56) & 0x1F) | (0x80 * Platform.CPU.SLFM);
625// this may not be valid when slfm (did) is enabled. Rely on vmin instead
626minimum.VID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 48) & 0x3F);
627
628int umaxVolt, uminVolt, moreVolt, lessVolt, vstate;
629int maxVolt_limit = VID_to_mV(maximum.VID) + 250;
630int minVolt_limit = VID_to_mV(minimum.VID) - 250;
631uint8_t vstep = 0;
632
633if((getIntForKey(kmaxVoltage, &umaxVolt, &bootInfo->bootConfig)) && (umaxVolt <= maxVolt_limit))
634{
635uint8_t vmax = mV_to_VID(umaxVolt);
636maximum.Control = (((busratio_max / 0xA) & 0x1F) * 0x100 | vmax) | (0x4000 * Platform.CPU.MaxDiv);
637maximum.VID = vmax & 0x3F;
638}
639if((getIntForKey(kminVoltage, &uminVolt, &bootInfo->bootConfig)) && (uminVolt >= minVolt_limit))
640{
641uint8_t vmin = mV_to_VID(uminVolt);
642minimum.VID = vmin & 0x3F;
643}
644
645if (minimum.FID == 0)
646{
647uint64_t msr;
648uint8_t i;
649// Probe for lowest fid
650// this is for requested FID, and not forcibly the lowest
651for (i = maximum.FID; i >= 0x6; i--)
652{
653msr = rdmsr64(MSR_IA32_PERF_CONTROL);
654wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (i << 8) | minimum.VID);
655intel_waitforsts();
656minimum.FID = (rdmsr64(MSR_IA32_PERF_STATUS) >> 8) & 0x1F;
657delay(1);
658}
659
660msr = rdmsr64(MSR_IA32_PERF_CONTROL);
661wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
662intel_waitforsts();
663}
664
665if (minimum.VID == maximum.VID)
666{
667uint64_t msr;
668uint8_t i;
669// Probe for lowest vid
670for (i = maximum.VID; i > 0xA; i--)
671{
672msr = rdmsr64(MSR_IA32_PERF_CONTROL);
673wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (minimum.FID << 8) | i);
674intel_waitforsts();
675minimum.VID = rdmsr64(MSR_IA32_PERF_STATUS) & 0x3F;
676delay(1);
677}
678
679msr = rdmsr64(MSR_IA32_PERF_CONTROL);
680wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
681intel_waitforsts();
682}
683
684minimum.CID = ((minimum.FID & 0x1F) << 1) >> Platform.CPU.SLFM;
685
686// Sanity check
687if (maximum.CID < minimum.CID)
688{
689DBG("Insane FID values!");
690p_states_count = 1;
691}
692else
693{
694// Print the voltage to be used
695int minVoltage = VID_to_mV(minimum.VID);
696int maxVoltage = VID_to_mV(maximum.VID);
697verbose("Voltage: min= %dmV, max= %dmV\n", minVoltage, maxVoltage);
698
699// Finalize P-States
700// Find how many P-States machine supports
701
702p_states_count = maximum.CID - minimum.CID + 1;
703
704if (p_states_count > 32)
705p_states_count = 32;
706
707uint8_t vidstep;
708uint8_t i = 0, u, invalid = 0;
709
710vidstep = ((maximum.VID << 2) - (minimum.VID << 2)) / (p_states_count - 1);
711for (u = 0; u < p_states_count; u++)
712{
713i = u - invalid;
714
715p_states[i].CID = maximum.CID - u;
716p_states[i].FID = (p_states[i].CID >> 1);
717
718if (i && p_states[i].FID < 0x6)
719{
720if (Platform.CPU.SLFM)
721{
722p_states[i].FID = (p_states[i].FID << 1) | 0x80;
723}
724// intel doesn't allow FIDs lower that 6 on core, core2 and eventually core-i
725else invalid++;
726}
727
728// 6.5 isn't selectable
729else if (Platform.CPU.MaxDiv && p_states[i].FID > 0x6)
730{
731// first state only!?
732//p_states[0].FID = p_states[0].FID | (0x40 * (p_states[0].CID & 0x1));
733p_states[i].FID = p_states[i].FID | (0x40 * (p_states[i].CID & 0x1));
734}
735
736if (i && p_states[i].FID == p_states[i-1].FID)
737invalid++;
738
739p_states[i].VID = ((maximum.VID << 2) - (vidstep * u)) >> 2;
740
741if(getIntForKey(klessVoltage, &lessVolt, &bootInfo->bootConfig))
742{
743vstate = (VID_to_mV(p_states[i].VID)) - lessVolt;
744vstep = mV_to_VID(vstate);
745p_states[i].VID = vstep & 0x3F;
746}
747else if(getIntForKey(kmoreVoltage, &moreVolt, &bootInfo->bootConfig))
748{
749vstate = (VID_to_mV(p_states[i].VID)) + moreVolt;
750vstep = mV_to_VID(vstate);
751p_states[i].VID = vstep & 0x3F;
752}
753
754uint32_t multiplier = p_states[i].FID & 0x1f;// = 0x08
755bool half = p_states[i].FID & 0x40;// = 0x01
756bool dfsb = p_states[i].FID & 0x80;// = 0x00
757uint32_t fsb = Platform.CPU.FSBFrequency / 1000000; // = 400
758uint32_t halffsb = (fsb + 1) >> 1;// = 200
759uint32_t frequency = (multiplier * fsb);// = 3200
760
761p_states[i].Frequency = (frequency + (half * halffsb)) >> dfsb;// = 3200 + 200 = 3400
762}
763p_states_count -= invalid;
764}
765
766//valv: Silly! Isn't it? :)
767int pstates = 0;
768if (getIntForKey(kpstates, &pstates, &bootInfo->bootConfig) && pstates < p_states_count && pstates > 0)
769{
770verbose("P-State: Only the %d highest states will be added\n", pstates);
771pstates = pstates - 1;
772}
773
774int pstart = 0;
775if (getIntForKey(kpstart, &pstart, &bootInfo->bootConfig) && pstart < p_states_count && pstart > 0)
776{
777const char *newratio;
778int len;
779if (getValueForKey(kbusratio, &newratio, &len, &bootInfo->bootConfig))
780{
781verbose("P-State: Already using bus-ratio injection! PStart key will have no effect.\n");
782pstart = 0;
783}
784else verbose("P-State: Starting from state P%d\n", pstart);
785}
786
787// Generating SSDT
788if (p_states_count > 0)
789{
790int i;
791
792struct aml_chunk* root = aml_create_node(NULL);
793aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header
794struct aml_chunk* scop = aml_add_scope(root, "\\_PR_");
795
796aml_add_buffer(scop, ssdt_pct, sizeof(ssdt_pct));
797
798struct aml_chunk* name_psd = aml_add_name(scop, "PSD_");
799struct aml_chunk* pack_psd = aml_add_package(name_psd);
800struct aml_chunk* psd = aml_add_package(pack_psd);
801aml_add_byte(psd, 0x05);
802aml_add_byte(psd, 0x00);
803aml_add_dword(psd, 0x00);
804aml_add_dword(psd, 0xfc);
805aml_add_dword(psd, Platform.CPU.NoCores);
806
807struct aml_chunk* name_pss = aml_add_name(scop, "PSS_");
808struct aml_chunk* pack_pss = aml_add_package(name_pss);
809
810//valv: this should not be
811/*if(Platform.CPU.Turbo)
812{
813int turbo_one = Platform.CPU.Tone;
814int turbo_two = Platform.CPU.Ttwo;
815int turbo_thr = Platform.CPU.Tthr;
816int turbo_for = Platform.CPU.Tfor;
817
818uint8_t TFIDone = (turbo_one & 0x1F);
819uint8_t TFIDtwo = (turbo_two & 0x1F);
820uint8_t TFIDthr = (turbo_thr & 0x1F);
821uint8_t TFIDfor = (turbo_for & 0x1F);
822
823uint32_t fsb = Platform.CPU.FSBFrequency / 1000000;
824uint32_t tfreq_one = (TFIDone * fsb);
825uint32_t tfreq_two = (TFIDtwo * fsb);
826uint32_t tfreq_thr = (TFIDthr * fsb);
827uint32_t tfreq_for = (TFIDfor * fsb);
828
829if(tfreq_one > 0)
830{
831struct aml_chunk* psturbo1 = aml_add_package(pack_pss);
832aml_add_dword(psturbo1, tfreq_one);
833aml_add_dword(psturbo1, 0x00000000); // Power
834aml_add_dword(psturbo1, 0x0000000A); // Latency
835aml_add_dword(psturbo1, 0x0000000A); // Latency
836aml_add_dword(psturbo1, TFIDone);
837aml_add_dword(psturbo1, TFIDone);
838verbose("P-State: Added [TurboFreq %d MHz, FID 0x%x]\n", tfreq_one, TFIDone);
839}
840
841if((tfreq_one != tfreq_two) && (tfreq_two > 0))
842{
843struct aml_chunk* psturbo2 = aml_add_package(pack_pss);
844aml_add_dword(psturbo2, tfreq_two);
845aml_add_dword(psturbo2, 0x00000000); // Power
846aml_add_dword(psturbo2, 0x0000000A); // Latency
847aml_add_dword(psturbo2, 0x0000000A); // Latency
848aml_add_dword(psturbo2, TFIDtwo);
849aml_add_dword(psturbo2, TFIDtwo);
850verbose("P-State: Added [TurboFreq %d MHz, FID 0x%x]\n", tfreq_two, TFIDtwo);
851}
852
853if((tfreq_two != tfreq_thr) && (tfreq_thr > 0))
854{
855struct aml_chunk* psturbo3 = aml_add_package(pack_pss);
856aml_add_dword(psturbo3, tfreq_thr);
857aml_add_dword(psturbo3, 0x00000000); // Power
858aml_add_dword(psturbo3, 0x0000000A); // Latency
859aml_add_dword(psturbo3, 0x0000000A); // Latency
860aml_add_dword(psturbo3, TFIDthr);
861aml_add_dword(psturbo3, TFIDthr);
862verbose("P-State: Added [TurboFreq %d MHz, FID 0x%x]\n", tfreq_thr, TFIDthr);
863}
864
865if((tfreq_thr != tfreq_for) && (tfreq_for > 0))
866{
867struct aml_chunk* psturbo4 = aml_add_package(pack_pss);
868aml_add_dword(psturbo4, tfreq_for);
869aml_add_dword(psturbo4, 0x00000000); // Power
870aml_add_dword(psturbo4, 0x0000000A); // Latency
871aml_add_dword(psturbo4, 0x0000000A); // Latency
872aml_add_dword(psturbo4, TFIDfor);
873aml_add_dword(psturbo4, TFIDfor);
874verbose("P-State: Added [TurboFreq %d MHz, FID 0x%x]\n", tfreq_for, TFIDfor);
875}
876}
877*/
878for (i = pstart; i < p_states_count; i++)
879{
880if ((p_states[i].Frequency <= freq_max) && (p_states[i].Frequency >= freq_min))
881{
882//valv: inspired from cparm's pss-drop; coded by me ;)
883if ((i > pstates) && (pstates > 0))
884{
885if(Platform.CPU.ISerie) verbose("P-State: [Frequency %d MHz, FID 0x%x] is the %dth state. Removed!\n",
886p_states[i].Frequency, p_states[i].FID, (i+1));
887else verbose("P-State: [Frequency %d MHz, FID 0x%x, VID 0x%x] is the %dth state. Removed!\n",
888p_states[i].Frequency, p_states[i].FID, p_states[i].VID, (i+1));
889}
890else
891{
892struct aml_chunk* pstt = aml_add_package(pack_pss);
893
894aml_add_dword(pstt, p_states[i].Frequency);
895aml_add_dword(pstt, 0x00000000); // Power
896aml_add_dword(pstt, 0x0000000A); // Latency
897aml_add_dword(pstt, 0x0000000A); // Latency
898if(Platform.CPU.ISerie)
899{
900aml_add_dword(pstt, p_states[i].FID);
901aml_add_dword(pstt, p_states[i].FID);
902verbose("P-State: Added [Frequency %d MHz, FID 0x%x]\n", p_states[i].Frequency, p_states[i].FID);
903}
904else
905{
906aml_add_dword(pstt, p_states[i].Control);
907aml_add_dword(pstt, p_states[i].Control);
908//aml_add_dword(pstt, i+1); // Status
909verbose("P-State: Added [Frequency %d MHz, FID 0x%x, VID 0x%x]\n",
910p_states[i].Frequency, p_states[i].FID, p_states[i].VID);
911}
912}
913}
914else
915{
916if(Platform.CPU.ISerie) verbose("P-State: [Frequency %d MHz, FID 0x%x] is over the limit. Removed!\n",
917p_states[i].Frequency, p_states[i].FID);
918else verbose("P-State: [Frequency %d MHz, FID 0x%x, VID 0x%x] is over the limit. Removed!\n",
919p_states[i].Frequency, p_states[i].FID, p_states[i].VID);
920}
921}
922
923struct aml_chunk* name_ppc = aml_add_name(scop, "PPC_");
924/*struct aml_chunk* pack_ppc = aml_add_package(name_ppc);
925struct aml_chunk* ppc = aml_add_package(pack_ppc);*/
926aml_add_byte(name_ppc, 0x00);
927
928// Add aliaces
929for (i = 0; i < acpi_cpu_count; i++)
930{
931char name[9];
932sprintf(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]);
933
934scop = aml_add_scope(root, name);
935aml_add_alias(scop, "PCT_", "_PCT");
936aml_add_alias(scop, "PSD_", "_PSD");
937aml_add_alias(scop, "PSS_", "_PSS");
938aml_add_alias(scop, "PPC_", "_PPC");
939}
940
941aml_calculate_size(root);
942
943struct acpi_2_ssdt *ssdt = (struct acpi_2_ssdt *)AllocateKernelMemory(root->Size);
944
945aml_write_node(root, (void*)ssdt, 0);
946
947ssdt->Length = root->Size;
948ssdt->Checksum = 0;
949ssdt->Checksum = 256 - checksum8(ssdt, ssdt->Length);
950
951 aml_destroy_node(root);
952
953//verbose ("SSDT with CPU P-States generated successfully\n");
954
955return ssdt;
956}
957}
958else {
959verbose ("ACPI CPUs not found: P-States not generated !!!\n");
960}
961
962return NULL;
963}
964
965void *loadSSDTTable(int ssdt_number)
966{
967void *tableAddr;
968int fd = -1;
969char dirspec[512];
970char filename[512];
971const char * overriden_pathname=NULL;
972int len=0;
973
974sprintf(filename, "SSDT-%d.aml", ssdt_number);
975
976// Check booting partition
977
978// Rek: if user specified a full path name then take it in consideration
979if (getValueForKey(kSSDT, &overriden_pathname, &len, &bootInfo->bootConfig))
980{
981sprintf(dirspec, "%s-%d.aml", overriden_pathname, ssdt_number); // start searching root
982//printf("Using custom %s path %s\n", key, dirspec);
983//getc();
984}
985else
986sprintf(dirspec, "/%s", filename); // start searching root
987
988fd=open (dirspec,0);
989
990if (fd<0)
991{// Check Extra on booting partition
992//verbose("Searching for %s.aml file ...\n", key);
993sprintf(dirspec,"/Extra/%s",filename);
994fd=open (dirspec,0);
995if (fd<0)
996{// Fall back to booter partition
997sprintf(dirspec,"bt(0,0)/Extra/%s",filename);
998fd=open (dirspec,0);
999if (fd<0)
1000{
1001//verbose("SSDT Table not found: %s\n", filename);
1002return NULL;
1003}
1004}
1005}
1006
1007tableAddr=(void*)AllocateKernelMemory(file_size (fd));
1008if (tableAddr)
1009{
1010if (read (fd, tableAddr, file_size (fd))!=file_size (fd))
1011{
1012printf("Couldn't read table %s\n",dirspec);
1013free (tableAddr);
1014close (fd);
1015return NULL;
1016}
1017
1018DBG("Table %s read and stored at: %x\n", dirspec, tableAddr);
1019close (fd);
1020return tableAddr;
1021}
1022
1023printf("Couldn't allocate memory for table %s\n", dirspec);
1024close (fd);
1025
1026return NULL;
1027}
1028
1029struct acpi_2_gas FillGASStruct(uint32_t Address, uint8_t Length)
1030{
1031struct acpi_2_gas TmpGAS;
1032
1033TmpGAS.Address_Space_ID = 1; /* I/O Address */
1034
1035if (Address == 0)
1036{
1037TmpGAS.Register_Bit_Width = 0;
1038} else {
1039TmpGAS.Register_Bit_Width = Length * 8;
1040}
1041
1042TmpGAS.Register_Bit_Offset = 0;
1043TmpGAS.Access_Size = 0; /* Not set for Legacy reasons... */
1044TmpGAS.Address = (uint64_t)Address;
1045
1046return(TmpGAS);
1047}
1048
1049struct acpi_2_fadt *patch_fadt(struct acpi_2_fadt *fadt, void *new_dsdt, bool UpdateFADT)
1050{
1051 extern void setupSystemType();
1052
1053struct acpi_2_fadt *fadt_mod;
1054struct acpi_2_fadt *fadt_file = (struct acpi_2_fadt *)loadACPITable(kFADT);
1055bool fadt_rev2_needed = false;
1056bool fix_restart;
1057const char * value;
1058
1059// Restart Fix
1060if (Platform.CPU.Vendor == 0x756E6547) {/* Intel */
1061fix_restart = true;
1062getBoolForKey(kRestartFix, &fix_restart, &bootInfo->bootConfig);
1063} else {
1064verbose ("Not an Intel platform: Restart Fix not applied !!!\n");
1065fix_restart = false;
1066}
1067
1068if (fix_restart)
1069fadt_rev2_needed = true;
1070
1071// Allocate new fadt table
1072if ((UpdateFADT) && (((fadt_file) && (fadt_file->Length < sizeof(struct acpi_2_fadt))) ||
1073 ((!fadt_file) && (fadt->Length < sizeof(struct acpi_2_fadt)))))
1074{
1075fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(sizeof(struct acpi_2_fadt));
1076
1077if (fadt_file)
1078memcpy(fadt_mod, fadt_file, fadt_file->Length);
1079else
1080memcpy(fadt_mod, fadt, fadt->Length);
1081
1082fadt_mod->Length = sizeof(struct acpi_2_fadt);
1083fadt_mod->Revision = 0x04; // FADT rev 4
1084fadt_mod->RESET_REG = FillGASStruct(0, 0);
1085fadt_mod->RESET_VALUE = 0;
1086fadt_mod->Reserved2[0] = 0;
1087fadt_mod->Reserved2[1] = 0;
1088fadt_mod->Reserved2[2] = 0;
1089fadt_mod->X_PM1a_EVT_BLK = FillGASStruct(fadt_mod->PM1a_EVT_BLK, fadt_mod->PM1_EVT_LEN);
1090fadt_mod->X_PM1b_EVT_BLK = FillGASStruct(fadt_mod->PM1b_EVT_BLK, fadt_mod->PM1_EVT_LEN);
1091fadt_mod->X_PM1a_CNT_BLK = FillGASStruct(fadt_mod->PM1a_CNT_BLK, fadt_mod->PM1_CNT_LEN);
1092fadt_mod->X_PM1b_CNT_BLK = FillGASStruct(fadt_mod->PM1b_CNT_BLK, fadt_mod->PM1_CNT_LEN);
1093fadt_mod->X_PM2_CNT_BLK = FillGASStruct(fadt_mod->PM2_CNT_BLK, fadt_mod->PM2_CNT_LEN);
1094fadt_mod->X_PM_TMR_BLK = FillGASStruct(fadt_mod->PM_TMR_BLK, fadt_mod->PM_TMR_LEN);
1095fadt_mod->X_GPE0_BLK = FillGASStruct(fadt_mod->GPE0_BLK, fadt_mod->GPE0_BLK_LEN);
1096fadt_mod->X_GPE1_BLK = FillGASStruct(fadt_mod->GPE1_BLK, fadt_mod->GPE1_BLK_LEN);
1097verbose("Converted ACPI V%d FADT to ACPI V4 FADT\n", (fadt_file) ? fadt_file->Revision : fadt->Revision);
1098} else {
1099if (((!fadt_file) && ((fadt->Length < 0x84) && (fadt_rev2_needed))) ||
1100 ((fadt_file) && ((fadt_file->Length < 0x84) && (fadt_rev2_needed))))
1101{
1102fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(0x84);
1103
1104if (fadt_file)
1105memcpy(fadt_mod, fadt_file, fadt_file->Length);
1106else
1107memcpy(fadt_mod, fadt, fadt->Length);
1108
1109fadt_mod->Length = 0x84;
1110fadt_mod->Revision = 0x02; // FADT rev 2 (ACPI 1.0B MS extensions)
1111}
1112else
1113{
1114if (fadt_file)
1115{
1116fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(fadt_file->Length);
1117memcpy(fadt_mod, fadt_file, fadt_file->Length);
1118} else {
1119fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(fadt->Length);
1120memcpy(fadt_mod, fadt, fadt->Length);
1121}
1122}
1123}
1124// Determine system type / PM_Model
1125if ( (value=getStringForKey(kSystemType, &bootInfo->bootConfig))!=NULL)
1126{
1127 if (Platform.Type > 6)
1128 {
1129 if(fadt_mod->Preferred_PM_Profile<=6)
1130 Platform.Type = fadt_mod->Preferred_PM_Profile; // get the fadt if correct
1131 else
1132 Platform.Type = 1;/* Set a fixed value (Desktop) */
1133 verbose("Error: system-type must be 0..6. Defaulting to %d !\n", Platform.Type);
1134 }
1135 else
1136 Platform.Type = (unsigned char) strtoul(value, NULL, 10);
1137}
1138// Set Preferred_PM_Profile from System-type only if user wanted this value to be forced
1139if (fadt_mod->Preferred_PM_Profile != Platform.Type)
1140{
1141 if (value)
1142 { // user has overriden the SystemType so take care of it in FACP
1143verbose("FADT: changing Preferred_PM_Profile from 0x%02x to 0x%02x\n", fadt_mod->Preferred_PM_Profile, Platform.Type);
1144fadt_mod->Preferred_PM_Profile = Platform.Type;
1145 }
1146 else
1147 { // Preferred_PM_Profile has a different value and no override has been set, so reflect the user value to ioregs
1148 Platform.Type = fadt_mod->Preferred_PM_Profile <= 6 ? fadt_mod->Preferred_PM_Profile : 1;
1149 }
1150}
1151// We now have to write the systemm-type in ioregs: we cannot do it before in setupDeviceTree()
1152// because we need to take care of facp original content, if it is correct.
1153setupSystemType();
1154
1155// Patch FADT to fix restart
1156if (fix_restart)
1157{
1158fadt_mod->Flags|= 0x400;
1159fadt_mod->RESET_REG = FillGASStruct(0x0cf9, 1);
1160fadt_mod->RESET_VALUE = 0x06;
1161
1162verbose("FADT: Restart Fix applied !\n");
1163}
1164
1165// Patch FACS Address
1166fadt_mod->FIRMWARE_CTRL=(uint32_t)fadt->FIRMWARE_CTRL;
1167if ((uint32_t)(&(fadt_mod->X_FIRMWARE_CTRL))-(uint32_t)fadt_mod+8<=fadt_mod->Length)
1168fadt_mod->X_FIRMWARE_CTRL=(uint32_t)fadt->FIRMWARE_CTRL;
1169
1170// Patch DSDT Address if we have one loaded
1171if(new_dsdt)
1172{
1173fadt_mod->DSDT=(uint32_t)new_dsdt;
1174if ((uint32_t)(&(fadt_mod->X_DSDT))-(uint32_t)fadt_mod+8<=fadt_mod->Length)
1175fadt_mod->X_DSDT=(uint32_t)new_dsdt;
1176}
1177
1178
1179// Correct the checksum
1180fadt_mod->Checksum=0;
1181fadt_mod->Checksum=256-checksum8(fadt_mod,fadt_mod->Length);
1182
1183return fadt_mod;
1184}
1185#if UNUSED
1186/* Setup ACPI without replacing DSDT. */
1187int setupAcpiNoMod()
1188{
1189//addConfigurationTable(&gEfiAcpiTableGuid, getAddressOfAcpiTable(), "ACPI");
1190//addConfigurationTable(&gEfiAcpi20TableGuid, getAddressOfAcpi20Table(), "ACPI_20");
1191/* XXX aserebln why uint32 cast if pointer is uint64 ? */
1192acpi10_p = (uint32_t)getAddressOfAcpiTable();
1193acpi20_p = (uint32_t)getAddressOfAcpi20Table();
1194addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
1195if(acpi20_p) addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
1196return 1;
1197}
1198#endif
1199
1200/* Setup ACPI. Replace DSDT if DSDT.aml is found */
1201int setupAcpi(void)
1202{
1203int version;
1204void *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];
1205
1206struct acpi_2_ssdt *new_ssdt[16]; // 2 additional tables for pss & cst
1207struct acpi_2_fadt *fadt; // will be used in CST generator
1208
1209bool 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;
1210bool drop_ssdt=false, drop_hpet=false, drop_slic=false, drop_sbst=false, drop_ecdt=false, drop_asft=false, drop_dmar=false;
1211bool update_acpi=false, gen_xsdt=false;
1212bool hpet_replaced=false, sbst_replaced=false, ecdt_replaced=false, asft_replaced=false, dmar_replaced=false, apic_replaced=false, mcfg_replaced=false;
1213bool hpet_added=false, sbst_added=false, ecdt_added=false, asft_added=false, dmar_added=false, apic_added=false, mcfg_added=false;
1214bool gen_cst=false, gen_pss=false;
1215
1216int curssdt=0, loadtotssdt=0, totssdt=0, newtotssdt=0;
1217
1218{
1219bool tmpval, tmpval2, tmpval3, tmpval4, tmpval6;
1220
1221drop_ssdt = getBoolForKey(kDropSSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1222drop_hpet = getBoolForKey(kDropHPET, &tmpval, &bootInfo->bootConfig)&&tmpval;
1223drop_slic = getBoolForKey(kDropSLIC, &tmpval, &bootInfo->bootConfig)&&tmpval;
1224drop_sbst = getBoolForKey(kDropSBST, &tmpval, &bootInfo->bootConfig)&&tmpval;
1225drop_ecdt = getBoolForKey(kDropECDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1226drop_asft = getBoolForKey(kDropASFT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1227drop_dmar = getBoolForKey(kDropDMAR, &tmpval, &bootInfo->bootConfig)&&tmpval;
1228
1229oem_dsdt = getBoolForKey(kOEMDSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1230oem_ssdt = getBoolForKey(kOEMSSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1231oem_hpet = getBoolForKey(kOEMHPET, &tmpval, &bootInfo->bootConfig)&&tmpval;
1232oem_sbst = getBoolForKey(kOEMSBST, &tmpval, &bootInfo->bootConfig)&&tmpval;
1233oem_ecdt = getBoolForKey(kOEMECDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1234oem_asft = getBoolForKey(kOEMASFT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1235oem_dmar = getBoolForKey(kOEMDMAR, &tmpval, &bootInfo->bootConfig)&&tmpval;
1236oem_apic = getBoolForKey(kOEMAPIC, &tmpval, &bootInfo->bootConfig)&&tmpval;
1237oem_mcfg = getBoolForKey(kOEMMCFG, &tmpval, &bootInfo->bootConfig)&&tmpval;
1238
1239gen_cst = (getBoolForKey(kGenerateCStates, &tmpval, &bootInfo->bootConfig)&&tmpval)
1240| (getBoolForKey(kEnableC2State, &tmpval2, &bootInfo->bootConfig)&&tmpval2)
1241| (getBoolForKey(kEnableC3State, &tmpval3, &bootInfo->bootConfig)&&tmpval3)
1242| (getBoolForKey(kEnableC4State, &tmpval4, &bootInfo->bootConfig)&&tmpval4)
1243| (getBoolForKey(kEnableC6State, &tmpval6, &bootInfo->bootConfig)&&tmpval6);
1244
1245gen_pss = getBoolForKey(kGeneratePStates, &tmpval, &bootInfo->bootConfig)&&tmpval;
1246update_acpi = getBoolForKey(kUpdateACPI, &tmpval, &bootInfo->bootConfig)&&tmpval;
1247}
1248
1249// Load replacement ACPI tables
1250if (!oem_dsdt)
1251new_dsdt=loadACPITable(kDSDT);
1252
1253if (!oem_hpet)
1254new_hpet=loadACPITable(kHPET);
1255
1256if (!oem_sbst)
1257new_sbst=loadACPITable(kSBST);
1258
1259if (!oem_ecdt)
1260new_ecdt=loadACPITable(kECDT);
1261
1262if (!oem_asft)
1263new_asft=loadACPITable(kASFT);
1264
1265if (!oem_dmar)
1266new_dmar=loadACPITable(kDMAR);
1267
1268if (!oem_apic)
1269new_apic=loadACPITable(kAPIC);
1270
1271if (!oem_mcfg)
1272new_mcfg=loadACPITable(kMCFG);
1273
1274if (gen_cst || gen_pss) oem_ssdt = false;
1275
1276if (!oem_ssdt)
1277{
1278for (curssdt=0;curssdt<14;curssdt++)
1279{
1280new_ssdt[curssdt]=loadSSDTTable(curssdt);
1281if (new_ssdt[curssdt])
1282loadtotssdt++;
1283}
1284curssdt=0;
1285}
1286/*
1287if (!new_dsdt)
1288return setupAcpiNoMod();
1289*/
1290DBG("New ACPI tables Loaded in memory\n");
1291
1292// Do the same procedure for both versions of ACPI
1293for (version=0; version<2; version++) {
1294struct acpi_2_rsdp *rsdp, *rsdp_mod, *rsdp_conv=(struct acpi_2_rsdp *)0;
1295struct acpi_2_rsdt *rsdt, *rsdt_mod;
1296struct acpi_2_xsdt *xsdt_conv = (struct acpi_2_xsdt *)0;
1297int rsdplength;
1298
1299// Find original rsdp
1300rsdp=(struct acpi_2_rsdp *)(version?getAddressOfAcpi20Table():getAddressOfAcpiTable());
1301if ((update_acpi) && (rsdp->Revision == 0))
1302{
1303rsdp_conv = (struct acpi_2_rsdp *)AllocateKernelMemory(sizeof(struct acpi_2_rsdp));
1304memcpy(rsdp_conv, rsdp, 20);
1305
1306/* Add/change fields */
1307strncpy(rsdp->OEMID, "Apple ", 6);
1308rsdp_conv->Revision = 2; /* ACPI version 3 */
1309rsdp_conv->Length = sizeof(struct acpi_2_rsdp);
1310
1311/* Correct checksums */
1312rsdp_conv->Checksum = 0;
1313rsdp_conv->Checksum = 256-checksum8(rsdp_conv, 20);
1314rsdp_conv->ExtendedChecksum = 0;
1315rsdp_conv->ExtendedChecksum = 256-checksum8(rsdp_conv, rsdp_conv->Length);
1316
1317rsdp = rsdp_conv;
1318
1319gen_xsdt = true;
1320version = 1;
1321
1322addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI");
1323
1324verbose("Converted ACPI RSD PTR version 1 to version 3\n");
1325}
1326if (!rsdp)
1327{
1328DBG("No ACPI version %d found. Ignoring\n", version+1);
1329if (version)
1330addConfigurationTable(&gEfiAcpi20TableGuid, NULL, "ACPI_20");
1331else
1332addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI");
1333continue;
1334}
1335rsdplength=version?rsdp->Length:20;
1336
1337DBG("RSDP version %d found @%x. Length=%d\n",version+1,rsdp,rsdplength);
1338
1339/* FIXME: no check that memory allocation succeeded
1340 * Copy and patch RSDP,RSDT, XSDT and FADT
1341 * For more info see ACPI Specification pages 110 and following
1342 */
1343
1344if (gen_xsdt)
1345{
1346rsdp_mod=rsdp_conv;
1347} else {
1348rsdp_mod=(struct acpi_2_rsdp *) AllocateKernelMemory(rsdplength);
1349memcpy(rsdp_mod, rsdp, rsdplength);
1350}
1351
1352rsdt=(struct acpi_2_rsdt *)(rsdp->RsdtAddress);
1353
1354DBG("RSDT @%x, Length %d\n",rsdt, rsdt->Length);
1355
1356if (rsdt && (uint32_t)rsdt !=0xffffffff && rsdt->Length<0x10000)
1357{
1358uint32_t *rsdt_entries;
1359int rsdt_entries_num;
1360int dropoffset=0, i;
1361
1362rsdt_mod=(struct acpi_2_rsdt *)AllocateKernelMemory(rsdt->Length);
1363memcpy (rsdt_mod, rsdt, rsdt->Length);
1364rsdp_mod->RsdtAddress=(uint32_t)rsdt_mod;
1365rsdt_entries_num=(rsdt_mod->Length-sizeof(struct acpi_2_rsdt))/4;
1366rsdt_entries=(uint32_t *)(rsdt_mod+1);
1367
1368if (gen_xsdt)
1369{
1370uint64_t *xsdt_conv_entries;
1371
1372xsdt_conv=(struct acpi_2_xsdt *)AllocateKernelMemory(sizeof(struct acpi_2_xsdt)+(rsdt_entries_num * 8));
1373memcpy(xsdt_conv, rsdt, sizeof(struct acpi_2_rsdt));
1374
1375xsdt_conv->Signature[0] = 'X';
1376xsdt_conv->Signature[1] = 'S';
1377xsdt_conv->Signature[2] = 'D';
1378xsdt_conv->Signature[3] = 'T';
1379xsdt_conv->Length = sizeof(struct acpi_2_xsdt)+(rsdt_entries_num * 8);
1380
1381xsdt_conv_entries=(uint64_t *)(xsdt_conv+1);
1382
1383for (i=0;i<rsdt_entries_num;i++)
1384{
1385xsdt_conv_entries[i] = (uint64_t)rsdt_entries[i];
1386}
1387
1388xsdt_conv->Checksum = 0;
1389xsdt_conv->Checksum = 256-checksum8(xsdt_conv, xsdt_conv->Length);
1390
1391rsdp->XsdtAddress = (uint32_t)xsdt_conv;
1392
1393rsdp->ExtendedChecksum = 0;
1394rsdp->ExtendedChecksum = 256-checksum8(rsdp, rsdp->Length);
1395
1396verbose("Converted RSDT table to XSDT table\n");
1397}
1398
1399for (i=0;i<rsdt_entries_num;i++)
1400{
1401char *table=(char *)(rsdt_entries[i]);
1402if (!table)
1403continue;
1404
1405DBG("TABLE %c%c%c%c,",table[0],table[1],table[2],table[3]);
1406
1407rsdt_entries[i-dropoffset]=rsdt_entries[i];
1408if (drop_ssdt && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1409{
1410dropoffset++;
1411continue;
1412}
1413if (drop_hpet && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')
1414{
1415dropoffset++;
1416continue;
1417}
1418if (drop_slic && table[0]=='S' && table[1]=='L' && table[2]=='I' && table[3]=='C')
1419{
1420dropoffset++;
1421continue;
1422}
1423if (drop_sbst && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')
1424{
1425dropoffset++;
1426continue;
1427}
1428if (drop_ecdt && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')
1429{
1430dropoffset++;
1431continue;
1432}
1433if (drop_asft && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')
1434{
1435dropoffset++;
1436continue;
1437}
1438if (drop_dmar && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')
1439{
1440dropoffset++;
1441continue;
1442}
1443if ((!(oem_hpet)) && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')
1444{
1445DBG("HPET found\n");
1446if (new_hpet)
1447{
1448rsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
1449hpet_replaced=true;
1450}
1451continue;
1452}
1453if ((!(oem_sbst)) && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')
1454{
1455DBG("SBST found\n");
1456if (new_sbst)
1457{
1458rsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
1459sbst_replaced=true;
1460}
1461continue;
1462}
1463if ((!(oem_ecdt)) && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')
1464{
1465DBG("ECDT found\n");
1466if (new_ecdt)
1467{
1468rsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
1469ecdt_replaced=true;
1470}
1471continue;
1472}
1473if ((!(oem_asft)) && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')
1474{
1475DBG("ASF! found\n");
1476if (new_asft)
1477{
1478rsdt_entries[i-dropoffset]=(uint32_t)new_asft;
1479asft_replaced=true;
1480}
1481continue;
1482}
1483if ((!(oem_dmar)) && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')
1484{
1485DBG("DMAR found\n");
1486if (new_dmar)
1487{
1488rsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
1489dmar_replaced=true;
1490}
1491continue;
1492}
1493if ((!(oem_apic)) && table[0]=='A' && table[1]=='P' && table[2]=='I' && table[3]=='C')
1494{
1495DBG("APIC found\n");
1496if (new_apic)
1497{
1498rsdt_entries[i-dropoffset]=(uint32_t)new_apic;
1499apic_replaced=true;
1500}
1501continue;
1502}
1503if ((!(oem_mcfg)) && table[0]=='M' && table[1]=='C' && table[2]=='F' && table[3]=='G')
1504{
1505DBG("MCFG found\n");
1506if (new_mcfg)
1507{
1508rsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
1509mcfg_replaced=true;
1510}
1511continue;
1512}
1513if ((!(oem_ssdt)) && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1514{
1515DBG("SSDT %d found", curssdt);
1516if (new_ssdt[curssdt])
1517{
1518DBG(" and replaced");
1519rsdt_entries[i-dropoffset]=(uint32_t)new_ssdt[curssdt];
1520totssdt++;
1521}
1522DBG("\n");
1523curssdt++;
1524continue;
1525}
1526if (table[0]=='D' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1527{
1528DBG("DSDT found\n");
1529rsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;
1530continue;
1531
1532} else {
1533struct acpi_2_rsdt *t = (struct acpi_2_rsdt *)table;
1534strncpy(t->OEMID, "Apple ", 6);
1535strncpy(t->OEMTableId, MacModel, 8);
1536t->OEMRevision = ModelRev;
1537t->Checksum=0;
1538t->Checksum=256-checksum8(t,t->Length);
1539}
1540if (table[0]=='F' && table[1]=='A' && table[2]=='C' && table[3]=='P')
1541{
1542struct acpi_2_fadt *fadt_mod;
1543fadt=(struct acpi_2_fadt *)rsdt_entries[i];
1544
1545DBG("FADT found @%x, Length %d\n",fadt, fadt->Length);
1546
1547if (!fadt || (uint32_t)fadt == 0xffffffff || fadt->Length>0x10000)
1548{
1549printf("FADT incorrect. Not modified\n");
1550continue;
1551}
1552
1553fadt_mod = patch_fadt(fadt, new_dsdt, update_acpi);
1554rsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;
1555
1556if(!oem_ssdt)
1557{
1558// Generate _CST SSDT
1559if ( gen_cst && (new_ssdt[loadtotssdt] = generate_cst_ssdt(fadt_mod)))
1560{
1561gen_cst= false;
1562loadtotssdt++;
1563}
1564
1565// Generating _PSS SSDT
1566if (gen_pss && (new_ssdt[loadtotssdt] = generate_pss_ssdt((void*)fadt_mod->DSDT)))
1567{
1568gen_pss= false;
1569loadtotssdt++;
1570}
1571}
1572
1573continue;
1574}
1575}
1576DBG("\n");
1577
1578strncpy(rsdt_mod->OEMID, "Apple ", 6);
1579strncpy(rsdt_mod->OEMTableId, MacModel, 8);
1580rsdt_mod->OEMRevision = ModelRev;
1581
1582if ((!oem_hpet) && (!hpet_replaced))
1583{
1584if (new_hpet)
1585{
1586rsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
1587hpet_added=true;
1588i++;
1589}
1590}
1591
1592if ((!oem_sbst) && (!sbst_replaced))
1593{
1594if (new_sbst)
1595{
1596rsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
1597sbst_added=true;
1598i++;
1599}
1600}
1601
1602if ((!oem_ecdt) && (!ecdt_replaced))
1603{
1604if (new_ecdt)
1605{
1606rsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
1607ecdt_added=true;
1608i++;
1609}
1610}
1611
1612if ((!oem_asft) && (!asft_replaced))
1613{
1614if (new_asft)
1615{
1616rsdt_entries[i-dropoffset]=(uint32_t)new_asft;
1617asft_added=true;
1618i++;
1619}
1620}
1621
1622if ((!oem_dmar) && (!dmar_replaced))
1623{
1624if (new_dmar)
1625{
1626rsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
1627dmar_added=true;
1628i++;
1629}
1630}
1631
1632if ((!oem_apic) && (!apic_replaced))
1633{
1634if (new_apic)
1635{
1636rsdt_entries[i-dropoffset]=(uint32_t)new_apic;
1637apic_added=true;
1638i++;
1639}
1640}
1641
1642if ((!oem_mcfg) && (!mcfg_replaced))
1643{
1644if (new_mcfg)
1645{
1646rsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
1647mcfg_added=true;
1648i++;
1649}
1650}
1651
1652if (!oem_ssdt)
1653{
1654while ((totssdt < loadtotssdt) && (curssdt < 14))
1655{
1656if (new_ssdt[curssdt])
1657{
1658DBG("adding SSDT %d\n", curssdt);
1659rsdt_entries[i-dropoffset]=(uint32_t)new_ssdt[curssdt];
1660totssdt++;
1661newtotssdt++;
1662i++;
1663}
1664curssdt++;
1665}
1666}
1667
1668// Correct the checksum of RSDT
1669rsdt_mod->Length-=4*dropoffset;
1670rsdt_mod->Length+=4*newtotssdt;
1671if (hpet_added)
1672rsdt_mod->Length+=4;
1673if (sbst_added)
1674rsdt_mod->Length+=4;
1675if (ecdt_added)
1676rsdt_mod->Length+=4;
1677if (asft_added)
1678rsdt_mod->Length+=4;
1679if (dmar_added)
1680rsdt_mod->Length+=4;
1681if (apic_added)
1682rsdt_mod->Length+=4;
1683if (mcfg_added)
1684rsdt_mod->Length+=4;
1685
1686DBG("RSDT: Original checksum %d, ", rsdt_mod->Checksum);
1687
1688rsdt_mod->Checksum=0;
1689rsdt_mod->Checksum=256-checksum8(rsdt_mod,rsdt_mod->Length);
1690
1691DBG("New checksum %d at %x\n", rsdt_mod->Checksum,rsdt_mod);
1692}
1693else
1694{
1695rsdp_mod->RsdtAddress=0;
1696printf("RSDT not found or RSDT incorrect\n");
1697}
1698
1699if (version)
1700{
1701struct acpi_2_xsdt *xsdt, *xsdt_mod;
1702
1703// FIXME: handle 64-bit address correctly
1704
1705if (gen_xsdt)
1706xsdt=xsdt_conv;
1707else
1708xsdt=(struct acpi_2_xsdt*) ((uint32_t)rsdp->XsdtAddress);
1709
1710DBG("XSDT @%x;%x, Length=%d\n", (uint32_t)(rsdp->XsdtAddress>>32),(uint32_t)rsdp->XsdtAddress, xsdt->Length);
1711if (xsdt && (uint64_t)rsdp->XsdtAddress<0xffffffff && xsdt->Length<0x10000)
1712{
1713uint64_t *xsdt_entries;
1714int xsdt_entries_num, i;
1715int dropoffset=0;
1716curssdt=0, totssdt=0, newtotssdt=0;
1717hpet_replaced=false, hpet_added=false;
1718sbst_replaced=false, sbst_added=false;
1719ecdt_replaced=false, ecdt_added=false;
1720asft_replaced=false, asft_added=false;
1721dmar_replaced=false, dmar_added=false;
1722apic_replaced=false, apic_added=false;
1723mcfg_replaced=false, mcfg_added=false;
1724
1725if (gen_xsdt)
1726xsdt_mod=xsdt;
1727else
1728{
1729xsdt_mod=(struct acpi_2_xsdt*)AllocateKernelMemory(xsdt->Length);
1730memcpy(xsdt_mod, xsdt, xsdt->Length);
1731}
1732
1733rsdp_mod->XsdtAddress=(uint32_t)xsdt_mod;
1734xsdt_entries_num=(xsdt_mod->Length-sizeof(struct acpi_2_xsdt))/8;
1735xsdt_entries=(uint64_t *)(xsdt_mod+1);
1736for (i=0;i<xsdt_entries_num;i++)
1737{
1738char *table=(char *)((uint32_t)(xsdt_entries[i]));
1739if (!table)
1740continue;
1741xsdt_entries[i-dropoffset]=xsdt_entries[i];
1742if (drop_ssdt && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1743{
1744dropoffset++;
1745continue;
1746}
1747if (drop_hpet && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')
1748{
1749dropoffset++;
1750continue;
1751}
1752if (drop_slic && table[0]=='S' && table[1]=='L' && table[2]=='I' && table[3]=='C')
1753{
1754dropoffset++;
1755continue;
1756}
1757if (drop_sbst && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')
1758{
1759dropoffset++;
1760continue;
1761}
1762if (drop_ecdt && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')
1763{
1764dropoffset++;
1765continue;
1766}
1767if (drop_asft && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')
1768{
1769dropoffset++;
1770continue;
1771}
1772if (drop_dmar && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')
1773{
1774dropoffset++;
1775continue;
1776}
1777if ((!(oem_hpet)) && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')
1778{
1779DBG("HPET found\n");
1780if (new_hpet)
1781{
1782xsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
1783hpet_replaced=true;
1784}
1785continue;
1786}
1787if ((!(oem_sbst)) && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')
1788{
1789DBG("SBST found\n");
1790if (new_sbst)
1791{
1792xsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
1793sbst_replaced=true;
1794}
1795continue;
1796}
1797if ((!(oem_ecdt)) && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')
1798{
1799DBG("ECDT found\n");
1800if (new_ecdt)
1801{
1802xsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
1803ecdt_replaced=true;
1804}
1805continue;
1806}
1807if ((!(oem_asft)) && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')
1808{
1809DBG("ASF! found\n");
1810if (new_asft)
1811{
1812xsdt_entries[i-dropoffset]=(uint32_t)new_asft;
1813asft_replaced=true;
1814}
1815continue;
1816}
1817if ((!(oem_dmar)) && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')
1818{
1819DBG("DMAR found\n");
1820if (new_dmar)
1821{
1822xsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
1823dmar_replaced=true;
1824}
1825continue;
1826}
1827if ((!(oem_apic)) && table[0]=='A' && table[1]=='P' && table[2]=='I' && table[3]=='C')
1828{
1829DBG("APIC found\n");
1830if (new_apic)
1831{
1832xsdt_entries[i-dropoffset]=(uint32_t)new_apic;
1833apic_replaced=true;
1834}
1835continue;
1836}
1837if ((!(oem_mcfg)) && table[0]=='M' && table[1]=='C' && table[2]=='F' && table[3]=='G')
1838{
1839DBG("MCFG found\n");
1840if (new_mcfg)
1841{
1842xsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
1843mcfg_replaced=true;
1844}
1845continue;
1846}
1847if ((!(oem_ssdt)) && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1848{
1849DBG("SSDT %d found", curssdt);
1850if (new_ssdt[curssdt])
1851{
1852DBG(" and replaced");
1853xsdt_entries[i-dropoffset]=(uint32_t)new_ssdt[curssdt];
1854totssdt++;
1855}
1856DBG("\n");
1857curssdt++;
1858continue;
1859}
1860if (table[0]=='D' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1861{
1862DBG("DSDT found\n");
1863
1864xsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;
1865
1866DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
1867
1868continue;
1869}
1870
1871struct acpi_2_xsdt* t = (struct acpi_2_xsdt*)table;
1872strncpy(t->OEMID, "Apple ", 6);
1873strncpy(t->OEMTableId, MacModel, 8);
1874t->OEMRevision = ModelRev;
1875
1876if (table[0]=='F' && table[1]=='A' && table[2]=='C' && table[3]=='P')
1877{
1878struct acpi_2_fadt *fadt_mod;
1879fadt=(struct acpi_2_fadt *)(uint32_t)xsdt_entries[i];
1880
1881DBG("FADT found @%x,%x, Length %d\n",(uint32_t)(xsdt_entries[i]>>32),fadt,
1882 fadt->Length);
1883
1884if (!fadt || (uint64_t)xsdt_entries[i] >= 0xffffffff || fadt->Length>0x10000)
1885{
1886verbose("FADT incorrect or after 4GB. Dropping XSDT\n");
1887goto drop_xsdt;
1888}
1889
1890fadt_mod = patch_fadt(fadt, new_dsdt, update_acpi);
1891xsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;
1892
1893DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
1894
1895if (!oem_ssdt)
1896{
1897// Generate _CST SSDT
1898if ( gen_cst && (new_ssdt[loadtotssdt] = generate_cst_ssdt(fadt_mod)))
1899{
1900gen_cst= false;
1901loadtotssdt++;
1902}
1903
1904// Generating _PSS SSDT
1905if (gen_pss && (new_ssdt[loadtotssdt] = generate_pss_ssdt((void*)fadt_mod->DSDT)))
1906{
1907gen_pss= false;
1908loadtotssdt++;
1909}
1910}
1911
1912continue;
1913}
1914
1915DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
1916
1917}
1918
1919strncpy(xsdt_mod->OEMID, "Apple ", 6);
1920strncpy(xsdt_mod->OEMTableId, MacModel, 8);
1921xsdt_mod->OEMRevision = ModelRev;
1922
1923if ((!oem_hpet) && (!hpet_replaced))
1924{
1925if (new_hpet)
1926{
1927xsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
1928hpet_added=true;
1929i++;
1930}
1931}
1932
1933if ((!oem_sbst) && (!sbst_replaced))
1934{
1935if (new_sbst)
1936{
1937xsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
1938sbst_added=true;
1939i++;
1940}
1941}
1942
1943if ((!oem_ecdt) && (!ecdt_replaced))
1944{
1945if (new_ecdt)
1946{
1947xsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
1948ecdt_added=true;
1949i++;
1950}
1951}
1952
1953if ((!oem_asft) && (!asft_replaced))
1954{
1955if (new_asft)
1956{
1957xsdt_entries[i-dropoffset]=(uint32_t)new_asft;
1958asft_added=true;
1959i++;
1960}
1961}
1962
1963if ((!oem_dmar) && (!dmar_replaced))
1964{
1965if (new_dmar)
1966{
1967xsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
1968dmar_added=true;
1969i++;
1970}
1971}
1972
1973if ((!oem_apic) && (!apic_replaced))
1974{
1975if (new_apic)
1976{
1977xsdt_entries[i-dropoffset]=(uint32_t)new_apic;
1978apic_added=true;
1979i++;
1980}
1981}
1982
1983if ((!oem_mcfg) && (!mcfg_replaced))
1984{
1985if (new_mcfg)
1986{
1987xsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
1988mcfg_added=true;
1989i++;
1990}
1991}
1992
1993if (!oem_ssdt)
1994{
1995while ((totssdt < loadtotssdt) && (curssdt < 14))
1996{
1997if (new_ssdt[curssdt])
1998{
1999DBG("adding SSDT %d\n", curssdt);
2000xsdt_entries[i-dropoffset]=(uint32_t)new_ssdt[curssdt];
2001totssdt++;
2002newtotssdt++;
2003i++;
2004}
2005curssdt++;
2006}
2007}
2008
2009// Correct the checksum of XSDT
2010xsdt_mod->Length-=8*dropoffset;
2011xsdt_mod->Length+=8*newtotssdt;
2012if (hpet_added)
2013xsdt_mod->Length+=8;
2014if (sbst_added)
2015xsdt_mod->Length+=8;
2016if (ecdt_added)
2017xsdt_mod->Length+=8;
2018if (asft_added)
2019xsdt_mod->Length+=8;
2020if (dmar_added)
2021xsdt_mod->Length+=8;
2022if (apic_added)
2023xsdt_mod->Length+=8;
2024if (mcfg_added)
2025xsdt_mod->Length+=8;
2026
2027xsdt_mod->Checksum=0;
2028xsdt_mod->Checksum=256-checksum8(xsdt_mod,xsdt_mod->Length);
2029}
2030else
2031{
2032drop_xsdt:
2033
2034DBG("About to drop XSDT\n");
2035
2036/*FIXME: Now we just hope that if MacOS doesn't find XSDT it reverts to RSDT.
2037 * A Better strategy would be to generate
2038 */
2039
2040rsdp_mod->XsdtAddress=0xffffffffffffffffLL;
2041verbose("XSDT not found or XSDT incorrect\n");
2042}
2043}
2044
2045// Correct the checksum of RSDP
2046
2047DBG("RSDP: Original checksum %d, ", rsdp_mod->Checksum);
2048
2049rsdp_mod->Checksum=0;
2050rsdp_mod->Checksum=256-checksum8(rsdp_mod,20);
2051
2052DBG("New checksum %d\n", rsdp_mod->Checksum);
2053
2054if (version)
2055{
2056DBG("RSDP: Original extended checksum %d", rsdp_mod->ExtendedChecksum);
2057
2058rsdp_mod->ExtendedChecksum=0;
2059rsdp_mod->ExtendedChecksum=256-checksum8(rsdp_mod,rsdp_mod->Length);
2060
2061DBG("New extended checksum %d\n", rsdp_mod->ExtendedChecksum);
2062
2063}
2064
2065verbose("Patched ACPI version %d DSDT\n", version+1);
2066if (version)
2067{
2068/* XXX aserebln why uint32 cast if pointer is uint64 ? */
2069acpi20_p = (uint32_t)rsdp_mod;
2070acpi10_p = (uint32_t)rsdp_mod;
2071addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
2072addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
2073}
2074else
2075{
2076/* XXX aserebln why uint32 cast if pointer is uint64 ? */
2077acpi10_p = (uint32_t)rsdp_mod;
2078addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
2079}
2080}
2081#if DEBUG_ACPI
2082printf("Press a key to continue... (DEBUG_ACPI)\n");
2083getc();
2084#endif
2085return 1;
2086}
2087

Archive Download this file

Revision: 665