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, 0x02,/* 0._PCT., */
5760x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00, 0x7F,/* ........ */
5770x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
5780x00, 0x00, 0x00, 0x79, 0x00, 0x11, 0x14, 0x0A, /* ....y... */
5790x11, 0x82, 0x0C, 0x00, 0x7F, 0x00, 0x00, 0x00, /* ........ */
5800x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
5810x79, 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
965/*valv: to be uncommented when finished ;)
966struct acpi_2_ssdt *generate_tss_ssdt(struct acpi_2_dsdt* dsdt)
967{
968char ssdt_header[] =
969{
970 0x53, 0x53, 0x44, 0x54, 0xE7, 0x00, 0x00, 0x00,
971 0x01, 0x17, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x42,
972 0x43, 0x70, 0x75, 0x54, 0x73, 0x74, 0x00, 0x00,
973 0x00, 0x10, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C,
974 0x31, 0x03, 0x10, 0x20
975};
976
977char ssdt_ptc[] =
978{
9790x08, 0x5F, 0x50, 0x54, 0x43, 0x12, 0x2C, 0x02,
9800x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00, 0x7F,
9810x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9820x00, 0x00, 0x00, 0x79, 0x00, 0x11, 0x14, 0x0A,
9830x11, 0x82, 0x0C, 0x00, 0x7F, 0x00, 0x00, 0x00,
9840x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9850x79, 0x00
986};
987}*/
988
989void *loadSSDTTable(int ssdt_number)
990{
991void *tableAddr;
992int fd = -1;
993char dirspec[512];
994char filename[512];
995const char * overriden_pathname=NULL;
996int len=0;
997
998sprintf(filename, "SSDT-%d.aml", ssdt_number);
999
1000// Check booting partition
1001
1002// Rek: if user specified a full path name then take it in consideration
1003if (getValueForKey(kSSDT, &overriden_pathname, &len, &bootInfo->bootConfig))
1004{
1005sprintf(dirspec, "%s-%d.aml", overriden_pathname, ssdt_number); // start searching root
1006//printf("Using custom %s path %s\n", key, dirspec);
1007//getc();
1008}
1009else
1010sprintf(dirspec, "/%s", filename); // start searching root
1011
1012fd=open (dirspec,0);
1013
1014if (fd<0)
1015{// Check Extra on booting partition
1016//verbose("Searching for %s.aml file ...\n", key);
1017sprintf(dirspec,"/Extra/%s",filename);
1018fd=open (dirspec,0);
1019if (fd<0)
1020{// Fall back to booter partition
1021sprintf(dirspec,"bt(0,0)/Extra/%s",filename);
1022fd=open (dirspec,0);
1023if (fd<0)
1024{
1025//verbose("SSDT Table not found: %s\n", filename);
1026return NULL;
1027}
1028}
1029}
1030
1031tableAddr=(void*)AllocateKernelMemory(file_size (fd));
1032if (tableAddr)
1033{
1034if (read (fd, tableAddr, file_size (fd))!=file_size (fd))
1035{
1036printf("Couldn't read table %s\n",dirspec);
1037free (tableAddr);
1038close (fd);
1039return NULL;
1040}
1041
1042DBG("Table %s read and stored at: %x\n", dirspec, tableAddr);
1043close (fd);
1044return tableAddr;
1045}
1046
1047printf("Couldn't allocate memory for table %s\n", dirspec);
1048close (fd);
1049
1050return NULL;
1051}
1052
1053struct acpi_2_gas FillGASStruct(uint32_t Address, uint8_t Length)
1054{
1055struct acpi_2_gas TmpGAS;
1056
1057TmpGAS.Address_Space_ID = 1; /* I/O Address */
1058
1059if (Address == 0)
1060{
1061TmpGAS.Register_Bit_Width = 0;
1062} else {
1063TmpGAS.Register_Bit_Width = Length * 8;
1064}
1065
1066TmpGAS.Register_Bit_Offset = 0;
1067TmpGAS.Access_Size = 0; /* Not set for Legacy reasons... */
1068TmpGAS.Address = (uint64_t)Address;
1069
1070return(TmpGAS);
1071}
1072
1073struct acpi_2_fadt *patch_fadt(struct acpi_2_fadt *fadt, void *new_dsdt, bool UpdateFADT)
1074{
1075 extern void setupSystemType();
1076
1077struct acpi_2_fadt *fadt_mod;
1078struct acpi_2_fadt *fadt_file = (struct acpi_2_fadt *)loadACPITable(kFADT);
1079bool fadt_rev2_needed = false;
1080bool fix_restart;
1081const char * value;
1082
1083// Restart Fix
1084if (Platform.CPU.Vendor == 0x756E6547) {/* Intel */
1085fix_restart = true;
1086getBoolForKey(kRestartFix, &fix_restart, &bootInfo->bootConfig);
1087} else {
1088verbose ("Not an Intel platform: Restart Fix not applied !!!\n");
1089fix_restart = false;
1090}
1091
1092if (fix_restart)
1093fadt_rev2_needed = true;
1094
1095// Allocate new fadt table
1096if ((UpdateFADT) && (((fadt_file) && (fadt_file->Length < sizeof(struct acpi_2_fadt))) ||
1097 ((!fadt_file) && (fadt->Length < sizeof(struct acpi_2_fadt)))))
1098{
1099fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(sizeof(struct acpi_2_fadt));
1100
1101if (fadt_file)
1102memcpy(fadt_mod, fadt_file, fadt_file->Length);
1103else
1104memcpy(fadt_mod, fadt, fadt->Length);
1105
1106fadt_mod->Length = sizeof(struct acpi_2_fadt);
1107fadt_mod->Revision = 0x04; // FADT rev 4
1108fadt_mod->RESET_REG = FillGASStruct(0, 0);
1109fadt_mod->RESET_VALUE = 0;
1110fadt_mod->Reserved2[0] = 0;
1111fadt_mod->Reserved2[1] = 0;
1112fadt_mod->Reserved2[2] = 0;
1113fadt_mod->X_PM1a_EVT_BLK = FillGASStruct(fadt_mod->PM1a_EVT_BLK, fadt_mod->PM1_EVT_LEN);
1114fadt_mod->X_PM1b_EVT_BLK = FillGASStruct(fadt_mod->PM1b_EVT_BLK, fadt_mod->PM1_EVT_LEN);
1115fadt_mod->X_PM1a_CNT_BLK = FillGASStruct(fadt_mod->PM1a_CNT_BLK, fadt_mod->PM1_CNT_LEN);
1116fadt_mod->X_PM1b_CNT_BLK = FillGASStruct(fadt_mod->PM1b_CNT_BLK, fadt_mod->PM1_CNT_LEN);
1117fadt_mod->X_PM2_CNT_BLK = FillGASStruct(fadt_mod->PM2_CNT_BLK, fadt_mod->PM2_CNT_LEN);
1118fadt_mod->X_PM_TMR_BLK = FillGASStruct(fadt_mod->PM_TMR_BLK, fadt_mod->PM_TMR_LEN);
1119fadt_mod->X_GPE0_BLK = FillGASStruct(fadt_mod->GPE0_BLK, fadt_mod->GPE0_BLK_LEN);
1120fadt_mod->X_GPE1_BLK = FillGASStruct(fadt_mod->GPE1_BLK, fadt_mod->GPE1_BLK_LEN);
1121verbose("Converted ACPI V%d FADT to ACPI V4 FADT\n", (fadt_file) ? fadt_file->Revision : fadt->Revision);
1122} else {
1123if (((!fadt_file) && ((fadt->Length < 0x84) && (fadt_rev2_needed))) ||
1124 ((fadt_file) && ((fadt_file->Length < 0x84) && (fadt_rev2_needed))))
1125{
1126fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(0x84);
1127
1128if (fadt_file)
1129memcpy(fadt_mod, fadt_file, fadt_file->Length);
1130else
1131memcpy(fadt_mod, fadt, fadt->Length);
1132
1133fadt_mod->Length = 0x84;
1134fadt_mod->Revision = 0x02; // FADT rev 2 (ACPI 1.0B MS extensions)
1135}
1136else
1137{
1138if (fadt_file)
1139{
1140fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(fadt_file->Length);
1141memcpy(fadt_mod, fadt_file, fadt_file->Length);
1142} else {
1143fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(fadt->Length);
1144memcpy(fadt_mod, fadt, fadt->Length);
1145}
1146}
1147}
1148// Determine system type / PM_Model
1149if ( (value=getStringForKey(kSystemType, &bootInfo->bootConfig))!=NULL)
1150{
1151 if (Platform.Type > 6)
1152 {
1153 if(fadt_mod->Preferred_PM_Profile<=6)
1154 Platform.Type = fadt_mod->Preferred_PM_Profile; // get the fadt if correct
1155 else
1156 Platform.Type = 1;/* Set a fixed value (Desktop) */
1157 verbose("Error: system-type must be 0..6. Defaulting to %d !\n", Platform.Type);
1158 }
1159 else
1160 Platform.Type = (unsigned char) strtoul(value, NULL, 10);
1161}
1162// Set Preferred_PM_Profile from System-type only if user wanted this value to be forced
1163if (fadt_mod->Preferred_PM_Profile != Platform.Type)
1164{
1165 if (value)
1166 { // user has overriden the SystemType so take care of it in FACP
1167verbose("FADT: changing Preferred_PM_Profile from 0x%02x to 0x%02x\n", fadt_mod->Preferred_PM_Profile, Platform.Type);
1168fadt_mod->Preferred_PM_Profile = Platform.Type;
1169 }
1170 else
1171 { // Preferred_PM_Profile has a different value and no override has been set, so reflect the user value to ioregs
1172 Platform.Type = fadt_mod->Preferred_PM_Profile <= 6 ? fadt_mod->Preferred_PM_Profile : 1;
1173 }
1174}
1175// We now have to write the systemm-type in ioregs: we cannot do it before in setupDeviceTree()
1176// because we need to take care of facp original content, if it is correct.
1177setupSystemType();
1178
1179// Patch FADT to fix restart
1180if (fix_restart)
1181{
1182fadt_mod->Flags|= 0x400;
1183fadt_mod->RESET_REG = FillGASStruct(0x0cf9, 1);
1184fadt_mod->RESET_VALUE = 0x06;
1185
1186verbose("FADT: Restart Fix applied !\n");
1187}
1188
1189// Patch FACS Address
1190fadt_mod->FIRMWARE_CTRL=(uint32_t)fadt->FIRMWARE_CTRL;
1191if ((uint32_t)(&(fadt_mod->X_FIRMWARE_CTRL))-(uint32_t)fadt_mod+8<=fadt_mod->Length)
1192fadt_mod->X_FIRMWARE_CTRL=(uint32_t)fadt->FIRMWARE_CTRL;
1193
1194// Patch DSDT Address if we have one loaded
1195if(new_dsdt)
1196{
1197fadt_mod->DSDT=(uint32_t)new_dsdt;
1198if ((uint32_t)(&(fadt_mod->X_DSDT))-(uint32_t)fadt_mod+8<=fadt_mod->Length)
1199fadt_mod->X_DSDT=(uint32_t)new_dsdt;
1200}
1201
1202
1203// Correct the checksum
1204fadt_mod->Checksum=0;
1205fadt_mod->Checksum=256-checksum8(fadt_mod,fadt_mod->Length);
1206
1207return fadt_mod;
1208}
1209#if UNUSED
1210/* Setup ACPI without replacing DSDT. */
1211int setupAcpiNoMod()
1212{
1213//addConfigurationTable(&gEfiAcpiTableGuid, getAddressOfAcpiTable(), "ACPI");
1214//addConfigurationTable(&gEfiAcpi20TableGuid, getAddressOfAcpi20Table(), "ACPI_20");
1215/* XXX aserebln why uint32 cast if pointer is uint64 ? */
1216acpi10_p = (uint32_t)getAddressOfAcpiTable();
1217acpi20_p = (uint32_t)getAddressOfAcpi20Table();
1218addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
1219if(acpi20_p) addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
1220return 1;
1221}
1222#endif
1223
1224/* Setup ACPI. Replace DSDT if DSDT.aml is found */
1225int setupAcpi(void)
1226{
1227int version;
1228void *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];
1229
1230struct acpi_2_ssdt *new_ssdt[16]; // 2 additional tables for pss/tss & cst
1231struct acpi_2_fadt *fadt; // will be used in CST generator
1232
1233bool 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;
1234bool drop_ssdt=false, drop_hpet=false, drop_slic=false, drop_sbst=false, drop_ecdt=false, drop_asft=false, drop_dmar=false;
1235bool update_acpi=false, gen_xsdt=false;
1236bool hpet_replaced=false, sbst_replaced=false, ecdt_replaced=false, asft_replaced=false, dmar_replaced=false, apic_replaced=false, mcfg_replaced=false;
1237bool hpet_added=false, sbst_added=false, ecdt_added=false, asft_added=false, dmar_added=false, apic_added=false, mcfg_added=false;
1238bool gen_cst=false, gen_pss=false;//, gen_tss=false;
1239
1240int curssdt=0, loadtotssdt=0, totssdt=0, newtotssdt=0;
1241
1242{
1243bool tmpval, tmpval2, tmpval3, tmpval4, tmpval6;
1244
1245drop_ssdt = getBoolForKey(kDropSSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1246drop_hpet = getBoolForKey(kDropHPET, &tmpval, &bootInfo->bootConfig)&&tmpval;
1247drop_slic = getBoolForKey(kDropSLIC, &tmpval, &bootInfo->bootConfig)&&tmpval;
1248drop_sbst = getBoolForKey(kDropSBST, &tmpval, &bootInfo->bootConfig)&&tmpval;
1249drop_ecdt = getBoolForKey(kDropECDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1250drop_asft = getBoolForKey(kDropASFT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1251drop_dmar = getBoolForKey(kDropDMAR, &tmpval, &bootInfo->bootConfig)&&tmpval;
1252
1253oem_dsdt = getBoolForKey(kOEMDSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1254oem_ssdt = getBoolForKey(kOEMSSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1255oem_hpet = getBoolForKey(kOEMHPET, &tmpval, &bootInfo->bootConfig)&&tmpval;
1256oem_sbst = getBoolForKey(kOEMSBST, &tmpval, &bootInfo->bootConfig)&&tmpval;
1257oem_ecdt = getBoolForKey(kOEMECDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1258oem_asft = getBoolForKey(kOEMASFT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1259oem_dmar = getBoolForKey(kOEMDMAR, &tmpval, &bootInfo->bootConfig)&&tmpval;
1260oem_apic = getBoolForKey(kOEMAPIC, &tmpval, &bootInfo->bootConfig)&&tmpval;
1261oem_mcfg = getBoolForKey(kOEMMCFG, &tmpval, &bootInfo->bootConfig)&&tmpval;
1262
1263gen_cst = (getBoolForKey(kGenerateCStates, &tmpval, &bootInfo->bootConfig)&&tmpval)
1264| (getBoolForKey(kEnableC2State, &tmpval2, &bootInfo->bootConfig)&&tmpval2)
1265| (getBoolForKey(kEnableC3State, &tmpval3, &bootInfo->bootConfig)&&tmpval3)
1266| (getBoolForKey(kEnableC4State, &tmpval4, &bootInfo->bootConfig)&&tmpval4)
1267| (getBoolForKey(kEnableC6State, &tmpval6, &bootInfo->bootConfig)&&tmpval6);
1268
1269gen_pss = getBoolForKey(kGeneratePStates, &tmpval, &bootInfo->bootConfig)&&tmpval;
1270
1271//gen_tss = getBoolForKey(kGenerateTStates, &tmpval, &bootInfo->bootConfig)&&tmpval;
1272
1273update_acpi = getBoolForKey(kUpdateACPI, &tmpval, &bootInfo->bootConfig)&&tmpval;
1274}
1275
1276// Load replacement ACPI tables
1277if (!oem_dsdt)
1278new_dsdt=loadACPITable(kDSDT);
1279
1280if (!oem_hpet)
1281new_hpet=loadACPITable(kHPET);
1282
1283if (!oem_sbst)
1284new_sbst=loadACPITable(kSBST);
1285
1286if (!oem_ecdt)
1287new_ecdt=loadACPITable(kECDT);
1288
1289if (!oem_asft)
1290new_asft=loadACPITable(kASFT);
1291
1292if (!oem_dmar)
1293new_dmar=loadACPITable(kDMAR);
1294
1295if (!oem_apic)
1296new_apic=loadACPITable(kAPIC);
1297
1298if (!oem_mcfg)
1299new_mcfg=loadACPITable(kMCFG);
1300
1301if (gen_cst || gen_pss/* || gen_tss*/) oem_ssdt = false;
1302
1303if (!oem_ssdt)
1304{
1305for (curssdt=0;curssdt<14;curssdt++)
1306{
1307new_ssdt[curssdt]=loadSSDTTable(curssdt);
1308if (new_ssdt[curssdt])
1309loadtotssdt++;
1310}
1311curssdt=0;
1312}
1313/*
1314if (!new_dsdt)
1315return setupAcpiNoMod();
1316*/
1317DBG("New ACPI tables Loaded in memory\n");
1318
1319// Do the same procedure for both versions of ACPI
1320for (version=0; version<2; version++) {
1321struct acpi_2_rsdp *rsdp, *rsdp_mod, *rsdp_conv=(struct acpi_2_rsdp *)0;
1322struct acpi_2_rsdt *rsdt, *rsdt_mod;
1323struct acpi_2_xsdt *xsdt_conv = (struct acpi_2_xsdt *)0;
1324int rsdplength;
1325
1326// Find original rsdp
1327rsdp=(struct acpi_2_rsdp *)(version?getAddressOfAcpi20Table():getAddressOfAcpiTable());
1328if ((update_acpi) && (rsdp->Revision == 0))
1329{
1330rsdp_conv = (struct acpi_2_rsdp *)AllocateKernelMemory(sizeof(struct acpi_2_rsdp));
1331memcpy(rsdp_conv, rsdp, 20);
1332
1333/* Add/change fields */
1334strncpy(rsdp->OEMID, "Apple ", 6);
1335rsdp_conv->Revision = 2; /* ACPI version 3 */
1336rsdp_conv->Length = sizeof(struct acpi_2_rsdp);
1337
1338/* Correct checksums */
1339rsdp_conv->Checksum = 0;
1340rsdp_conv->Checksum = 256-checksum8(rsdp_conv, 20);
1341rsdp_conv->ExtendedChecksum = 0;
1342rsdp_conv->ExtendedChecksum = 256-checksum8(rsdp_conv, rsdp_conv->Length);
1343
1344rsdp = rsdp_conv;
1345
1346gen_xsdt = true;
1347version = 1;
1348
1349addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI");
1350
1351verbose("Converted ACPI RSD PTR version 1 to version 3\n");
1352}
1353if (!rsdp)
1354{
1355DBG("No ACPI version %d found. Ignoring\n", version+1);
1356if (version)
1357addConfigurationTable(&gEfiAcpi20TableGuid, NULL, "ACPI_20");
1358else
1359addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI");
1360continue;
1361}
1362rsdplength=version?rsdp->Length:20;
1363
1364DBG("RSDP version %d found @%x. Length=%d\n",version+1,rsdp,rsdplength);
1365
1366/* FIXME: no check that memory allocation succeeded
1367 * Copy and patch RSDP,RSDT, XSDT and FADT
1368 * For more info see ACPI Specification pages 110 and following
1369 */
1370
1371if (gen_xsdt)
1372{
1373rsdp_mod=rsdp_conv;
1374} else {
1375rsdp_mod=(struct acpi_2_rsdp *) AllocateKernelMemory(rsdplength);
1376memcpy(rsdp_mod, rsdp, rsdplength);
1377}
1378
1379rsdt=(struct acpi_2_rsdt *)(rsdp->RsdtAddress);
1380
1381DBG("RSDT @%x, Length %d\n",rsdt, rsdt->Length);
1382
1383if (rsdt && (uint32_t)rsdt !=0xffffffff && rsdt->Length<0x10000)
1384{
1385uint32_t *rsdt_entries;
1386int rsdt_entries_num;
1387int dropoffset=0, i;
1388
1389rsdt_mod=(struct acpi_2_rsdt *)AllocateKernelMemory(rsdt->Length);
1390memcpy (rsdt_mod, rsdt, rsdt->Length);
1391rsdp_mod->RsdtAddress=(uint32_t)rsdt_mod;
1392rsdt_entries_num=(rsdt_mod->Length-sizeof(struct acpi_2_rsdt))/4;
1393rsdt_entries=(uint32_t *)(rsdt_mod+1);
1394
1395if (gen_xsdt)
1396{
1397uint64_t *xsdt_conv_entries;
1398
1399xsdt_conv=(struct acpi_2_xsdt *)AllocateKernelMemory(sizeof(struct acpi_2_xsdt)+(rsdt_entries_num * 8));
1400memcpy(xsdt_conv, rsdt, sizeof(struct acpi_2_rsdt));
1401
1402xsdt_conv->Signature[0] = 'X';
1403xsdt_conv->Signature[1] = 'S';
1404xsdt_conv->Signature[2] = 'D';
1405xsdt_conv->Signature[3] = 'T';
1406xsdt_conv->Length = sizeof(struct acpi_2_xsdt)+(rsdt_entries_num * 8);
1407
1408xsdt_conv_entries=(uint64_t *)(xsdt_conv+1);
1409
1410for (i=0;i<rsdt_entries_num;i++)
1411{
1412xsdt_conv_entries[i] = (uint64_t)rsdt_entries[i];
1413}
1414
1415xsdt_conv->Checksum = 0;
1416xsdt_conv->Checksum = 256-checksum8(xsdt_conv, xsdt_conv->Length);
1417
1418rsdp->XsdtAddress = (uint32_t)xsdt_conv;
1419
1420rsdp->ExtendedChecksum = 0;
1421rsdp->ExtendedChecksum = 256-checksum8(rsdp, rsdp->Length);
1422
1423verbose("Converted RSDT table to XSDT table\n");
1424}
1425
1426for (i=0;i<rsdt_entries_num;i++)
1427{
1428char *table=(char *)(rsdt_entries[i]);
1429if (!table)
1430continue;
1431
1432DBG("TABLE %c%c%c%c,",table[0],table[1],table[2],table[3]);
1433
1434rsdt_entries[i-dropoffset]=rsdt_entries[i];
1435if (drop_ssdt && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1436{
1437dropoffset++;
1438continue;
1439}
1440if (drop_hpet && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')
1441{
1442dropoffset++;
1443continue;
1444}
1445if (drop_slic && table[0]=='S' && table[1]=='L' && table[2]=='I' && table[3]=='C')
1446{
1447dropoffset++;
1448continue;
1449}
1450if (drop_sbst && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')
1451{
1452dropoffset++;
1453continue;
1454}
1455if (drop_ecdt && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')
1456{
1457dropoffset++;
1458continue;
1459}
1460if (drop_asft && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')
1461{
1462dropoffset++;
1463continue;
1464}
1465if (drop_dmar && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')
1466{
1467dropoffset++;
1468continue;
1469}
1470if ((!(oem_hpet)) && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')
1471{
1472DBG("HPET found\n");
1473if (new_hpet)
1474{
1475rsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
1476hpet_replaced=true;
1477}
1478continue;
1479}
1480if ((!(oem_sbst)) && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')
1481{
1482DBG("SBST found\n");
1483if (new_sbst)
1484{
1485rsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
1486sbst_replaced=true;
1487}
1488continue;
1489}
1490if ((!(oem_ecdt)) && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')
1491{
1492DBG("ECDT found\n");
1493if (new_ecdt)
1494{
1495rsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
1496ecdt_replaced=true;
1497}
1498continue;
1499}
1500if ((!(oem_asft)) && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')
1501{
1502DBG("ASF! found\n");
1503if (new_asft)
1504{
1505rsdt_entries[i-dropoffset]=(uint32_t)new_asft;
1506asft_replaced=true;
1507}
1508continue;
1509}
1510if ((!(oem_dmar)) && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')
1511{
1512DBG("DMAR found\n");
1513if (new_dmar)
1514{
1515rsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
1516dmar_replaced=true;
1517}
1518continue;
1519}
1520if ((!(oem_apic)) && table[0]=='A' && table[1]=='P' && table[2]=='I' && table[3]=='C')
1521{
1522DBG("APIC found\n");
1523if (new_apic)
1524{
1525rsdt_entries[i-dropoffset]=(uint32_t)new_apic;
1526apic_replaced=true;
1527}
1528continue;
1529}
1530if ((!(oem_mcfg)) && table[0]=='M' && table[1]=='C' && table[2]=='F' && table[3]=='G')
1531{
1532DBG("MCFG found\n");
1533if (new_mcfg)
1534{
1535rsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
1536mcfg_replaced=true;
1537}
1538continue;
1539}
1540if ((!(oem_ssdt)) && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1541{
1542DBG("SSDT %d found", curssdt);
1543if (new_ssdt[curssdt])
1544{
1545DBG(" and replaced");
1546rsdt_entries[i-dropoffset]=(uint32_t)new_ssdt[curssdt];
1547totssdt++;
1548}
1549DBG("\n");
1550curssdt++;
1551continue;
1552}
1553if (table[0]=='D' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1554{
1555DBG("DSDT found\n");
1556rsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;
1557continue;
1558
1559} else {
1560struct acpi_2_rsdt *t = (struct acpi_2_rsdt *)table;
1561strncpy(t->OEMID, "Apple ", 6);
1562strncpy(t->OEMTableId, MacModel, 8);
1563t->OEMRevision = ModelRev;
1564t->Checksum=0;
1565t->Checksum=256-checksum8(t,t->Length);
1566}
1567if (table[0]=='F' && table[1]=='A' && table[2]=='C' && table[3]=='P')
1568{
1569struct acpi_2_fadt *fadt_mod;
1570fadt=(struct acpi_2_fadt *)rsdt_entries[i];
1571
1572DBG("FADT found @%x, Length %d\n",fadt, fadt->Length);
1573
1574if (!fadt || (uint32_t)fadt == 0xffffffff || fadt->Length>0x10000)
1575{
1576printf("FADT incorrect. Not modified\n");
1577continue;
1578}
1579
1580fadt_mod = patch_fadt(fadt, new_dsdt, update_acpi);
1581rsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;
1582
1583if(!oem_ssdt)
1584{
1585// Generate _CST SSDT
1586if ( gen_cst && (new_ssdt[loadtotssdt] = generate_cst_ssdt(fadt_mod)))
1587{
1588gen_cst= false;
1589loadtotssdt++;
1590}
1591
1592// Generating _PSS SSDT
1593if (gen_pss && (new_ssdt[loadtotssdt] = generate_pss_ssdt((void*)fadt_mod->DSDT)))
1594{
1595gen_pss= false;
1596loadtotssdt++;
1597}
1598/*
1599// Generating _TSS SSDT
1600else if (gen_tss && (new_ssdt[loadtotssdt] = generate_tss_ssdt((void*)fadt_mod->DSDT)))
1601{
1602gen_tss= false;
1603loadtotssdt++;
1604}
1605*/}
1606
1607continue;
1608}
1609}
1610DBG("\n");
1611
1612strncpy(rsdt_mod->OEMID, "Apple ", 6);
1613strncpy(rsdt_mod->OEMTableId, MacModel, 8);
1614rsdt_mod->OEMRevision = ModelRev;
1615
1616if ((!oem_hpet) && (!hpet_replaced))
1617{
1618if (new_hpet)
1619{
1620rsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
1621hpet_added=true;
1622i++;
1623}
1624}
1625
1626if ((!oem_sbst) && (!sbst_replaced))
1627{
1628if (new_sbst)
1629{
1630rsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
1631sbst_added=true;
1632i++;
1633}
1634}
1635
1636if ((!oem_ecdt) && (!ecdt_replaced))
1637{
1638if (new_ecdt)
1639{
1640rsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
1641ecdt_added=true;
1642i++;
1643}
1644}
1645
1646if ((!oem_asft) && (!asft_replaced))
1647{
1648if (new_asft)
1649{
1650rsdt_entries[i-dropoffset]=(uint32_t)new_asft;
1651asft_added=true;
1652i++;
1653}
1654}
1655
1656if ((!oem_dmar) && (!dmar_replaced))
1657{
1658if (new_dmar)
1659{
1660rsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
1661dmar_added=true;
1662i++;
1663}
1664}
1665
1666if ((!oem_apic) && (!apic_replaced))
1667{
1668if (new_apic)
1669{
1670rsdt_entries[i-dropoffset]=(uint32_t)new_apic;
1671apic_added=true;
1672i++;
1673}
1674}
1675
1676if ((!oem_mcfg) && (!mcfg_replaced))
1677{
1678if (new_mcfg)
1679{
1680rsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
1681mcfg_added=true;
1682i++;
1683}
1684}
1685
1686if (!oem_ssdt)
1687{
1688while ((totssdt < loadtotssdt) && (curssdt < 14))
1689{
1690if (new_ssdt[curssdt])
1691{
1692DBG("adding SSDT %d\n", curssdt);
1693rsdt_entries[i-dropoffset]=(uint32_t)new_ssdt[curssdt];
1694totssdt++;
1695newtotssdt++;
1696i++;
1697}
1698curssdt++;
1699}
1700}
1701
1702// Correct the checksum of RSDT
1703rsdt_mod->Length-=4*dropoffset;
1704rsdt_mod->Length+=4*newtotssdt;
1705if (hpet_added)
1706rsdt_mod->Length+=4;
1707if (sbst_added)
1708rsdt_mod->Length+=4;
1709if (ecdt_added)
1710rsdt_mod->Length+=4;
1711if (asft_added)
1712rsdt_mod->Length+=4;
1713if (dmar_added)
1714rsdt_mod->Length+=4;
1715if (apic_added)
1716rsdt_mod->Length+=4;
1717if (mcfg_added)
1718rsdt_mod->Length+=4;
1719
1720DBG("RSDT: Original checksum %d, ", rsdt_mod->Checksum);
1721
1722rsdt_mod->Checksum=0;
1723rsdt_mod->Checksum=256-checksum8(rsdt_mod,rsdt_mod->Length);
1724
1725DBG("New checksum %d at %x\n", rsdt_mod->Checksum,rsdt_mod);
1726}
1727else
1728{
1729rsdp_mod->RsdtAddress=0;
1730printf("RSDT not found or RSDT incorrect\n");
1731}
1732
1733if (version)
1734{
1735struct acpi_2_xsdt *xsdt, *xsdt_mod;
1736
1737// FIXME: handle 64-bit address correctly
1738
1739if (gen_xsdt)
1740xsdt=xsdt_conv;
1741else
1742xsdt=(struct acpi_2_xsdt*) ((uint32_t)rsdp->XsdtAddress);
1743
1744DBG("XSDT @%x;%x, Length=%d\n", (uint32_t)(rsdp->XsdtAddress>>32),(uint32_t)rsdp->XsdtAddress, xsdt->Length);
1745if (xsdt && (uint64_t)rsdp->XsdtAddress<0xffffffff && xsdt->Length<0x10000)
1746{
1747uint64_t *xsdt_entries;
1748int xsdt_entries_num, i;
1749int dropoffset=0;
1750curssdt=0, totssdt=0, newtotssdt=0;
1751hpet_replaced=false, hpet_added=false;
1752sbst_replaced=false, sbst_added=false;
1753ecdt_replaced=false, ecdt_added=false;
1754asft_replaced=false, asft_added=false;
1755dmar_replaced=false, dmar_added=false;
1756apic_replaced=false, apic_added=false;
1757mcfg_replaced=false, mcfg_added=false;
1758
1759if (gen_xsdt)
1760xsdt_mod=xsdt;
1761else
1762{
1763xsdt_mod=(struct acpi_2_xsdt*)AllocateKernelMemory(xsdt->Length);
1764memcpy(xsdt_mod, xsdt, xsdt->Length);
1765}
1766
1767rsdp_mod->XsdtAddress=(uint32_t)xsdt_mod;
1768xsdt_entries_num=(xsdt_mod->Length-sizeof(struct acpi_2_xsdt))/8;
1769xsdt_entries=(uint64_t *)(xsdt_mod+1);
1770for (i=0;i<xsdt_entries_num;i++)
1771{
1772char *table=(char *)((uint32_t)(xsdt_entries[i]));
1773if (!table)
1774continue;
1775xsdt_entries[i-dropoffset]=xsdt_entries[i];
1776if (drop_ssdt && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1777{
1778dropoffset++;
1779continue;
1780}
1781if (drop_hpet && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')
1782{
1783dropoffset++;
1784continue;
1785}
1786if (drop_slic && table[0]=='S' && table[1]=='L' && table[2]=='I' && table[3]=='C')
1787{
1788dropoffset++;
1789continue;
1790}
1791if (drop_sbst && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')
1792{
1793dropoffset++;
1794continue;
1795}
1796if (drop_ecdt && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')
1797{
1798dropoffset++;
1799continue;
1800}
1801if (drop_asft && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')
1802{
1803dropoffset++;
1804continue;
1805}
1806if (drop_dmar && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')
1807{
1808dropoffset++;
1809continue;
1810}
1811if ((!(oem_hpet)) && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')
1812{
1813DBG("HPET found\n");
1814if (new_hpet)
1815{
1816xsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
1817hpet_replaced=true;
1818}
1819continue;
1820}
1821if ((!(oem_sbst)) && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')
1822{
1823DBG("SBST found\n");
1824if (new_sbst)
1825{
1826xsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
1827sbst_replaced=true;
1828}
1829continue;
1830}
1831if ((!(oem_ecdt)) && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')
1832{
1833DBG("ECDT found\n");
1834if (new_ecdt)
1835{
1836xsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
1837ecdt_replaced=true;
1838}
1839continue;
1840}
1841if ((!(oem_asft)) && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')
1842{
1843DBG("ASF! found\n");
1844if (new_asft)
1845{
1846xsdt_entries[i-dropoffset]=(uint32_t)new_asft;
1847asft_replaced=true;
1848}
1849continue;
1850}
1851if ((!(oem_dmar)) && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')
1852{
1853DBG("DMAR found\n");
1854if (new_dmar)
1855{
1856xsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
1857dmar_replaced=true;
1858}
1859continue;
1860}
1861if ((!(oem_apic)) && table[0]=='A' && table[1]=='P' && table[2]=='I' && table[3]=='C')
1862{
1863DBG("APIC found\n");
1864if (new_apic)
1865{
1866xsdt_entries[i-dropoffset]=(uint32_t)new_apic;
1867apic_replaced=true;
1868}
1869continue;
1870}
1871if ((!(oem_mcfg)) && table[0]=='M' && table[1]=='C' && table[2]=='F' && table[3]=='G')
1872{
1873DBG("MCFG found\n");
1874if (new_mcfg)
1875{
1876xsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
1877mcfg_replaced=true;
1878}
1879continue;
1880}
1881if ((!(oem_ssdt)) && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1882{
1883DBG("SSDT %d found", curssdt);
1884if (new_ssdt[curssdt])
1885{
1886DBG(" and replaced");
1887xsdt_entries[i-dropoffset]=(uint32_t)new_ssdt[curssdt];
1888totssdt++;
1889}
1890DBG("\n");
1891curssdt++;
1892continue;
1893}
1894if (table[0]=='D' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1895{
1896DBG("DSDT found\n");
1897
1898xsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;
1899
1900DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
1901
1902continue;
1903}
1904
1905struct acpi_2_xsdt* t = (struct acpi_2_xsdt*)table;
1906strncpy(t->OEMID, "Apple ", 6);
1907strncpy(t->OEMTableId, MacModel, 8);
1908t->OEMRevision = ModelRev;
1909
1910if (table[0]=='F' && table[1]=='A' && table[2]=='C' && table[3]=='P')
1911{
1912struct acpi_2_fadt *fadt_mod;
1913fadt=(struct acpi_2_fadt *)(uint32_t)xsdt_entries[i];
1914
1915DBG("FADT found @%x,%x, Length %d\n",(uint32_t)(xsdt_entries[i]>>32),fadt,
1916 fadt->Length);
1917
1918if (!fadt || (uint64_t)xsdt_entries[i] >= 0xffffffff || fadt->Length>0x10000)
1919{
1920verbose("FADT incorrect or after 4GB. Dropping XSDT\n");
1921goto drop_xsdt;
1922}
1923
1924fadt_mod = patch_fadt(fadt, new_dsdt, update_acpi);
1925xsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;
1926
1927DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
1928
1929if (!oem_ssdt)
1930{
1931// Generate _CST SSDT
1932if ( gen_cst && (new_ssdt[loadtotssdt] = generate_cst_ssdt(fadt_mod)))
1933{
1934gen_cst= false;
1935loadtotssdt++;
1936}
1937
1938// Generating _PSS SSDT
1939if (gen_pss && (new_ssdt[loadtotssdt] = generate_pss_ssdt((void*)fadt_mod->DSDT)))
1940{
1941gen_pss= false;
1942loadtotssdt++;
1943}
1944/*
1945// Generating _TSS SSDT
1946else if (gen_tss && (new_ssdt[loadtotssdt] = generate_tss_ssdt((void*)fadt_mod->DSDT)))
1947{
1948gen_tss= false;
1949loadtotssdt++;
1950}
1951*/}
1952
1953continue;
1954}
1955
1956DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
1957
1958}
1959
1960strncpy(xsdt_mod->OEMID, "Apple ", 6);
1961strncpy(xsdt_mod->OEMTableId, MacModel, 8);
1962xsdt_mod->OEMRevision = ModelRev;
1963
1964if ((!oem_hpet) && (!hpet_replaced))
1965{
1966if (new_hpet)
1967{
1968xsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
1969hpet_added=true;
1970i++;
1971}
1972}
1973
1974if ((!oem_sbst) && (!sbst_replaced))
1975{
1976if (new_sbst)
1977{
1978xsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
1979sbst_added=true;
1980i++;
1981}
1982}
1983
1984if ((!oem_ecdt) && (!ecdt_replaced))
1985{
1986if (new_ecdt)
1987{
1988xsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
1989ecdt_added=true;
1990i++;
1991}
1992}
1993
1994if ((!oem_asft) && (!asft_replaced))
1995{
1996if (new_asft)
1997{
1998xsdt_entries[i-dropoffset]=(uint32_t)new_asft;
1999asft_added=true;
2000i++;
2001}
2002}
2003
2004if ((!oem_dmar) && (!dmar_replaced))
2005{
2006if (new_dmar)
2007{
2008xsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
2009dmar_added=true;
2010i++;
2011}
2012}
2013
2014if ((!oem_apic) && (!apic_replaced))
2015{
2016if (new_apic)
2017{
2018xsdt_entries[i-dropoffset]=(uint32_t)new_apic;
2019apic_added=true;
2020i++;
2021}
2022}
2023
2024if ((!oem_mcfg) && (!mcfg_replaced))
2025{
2026if (new_mcfg)
2027{
2028xsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
2029mcfg_added=true;
2030i++;
2031}
2032}
2033
2034if (!oem_ssdt)
2035{
2036while ((totssdt < loadtotssdt) && (curssdt < 14))
2037{
2038if (new_ssdt[curssdt])
2039{
2040DBG("adding SSDT %d\n", curssdt);
2041xsdt_entries[i-dropoffset]=(uint32_t)new_ssdt[curssdt];
2042totssdt++;
2043newtotssdt++;
2044i++;
2045}
2046curssdt++;
2047}
2048}
2049
2050// Correct the checksum of XSDT
2051xsdt_mod->Length-=8*dropoffset;
2052xsdt_mod->Length+=8*newtotssdt;
2053if (hpet_added)
2054xsdt_mod->Length+=8;
2055if (sbst_added)
2056xsdt_mod->Length+=8;
2057if (ecdt_added)
2058xsdt_mod->Length+=8;
2059if (asft_added)
2060xsdt_mod->Length+=8;
2061if (dmar_added)
2062xsdt_mod->Length+=8;
2063if (apic_added)
2064xsdt_mod->Length+=8;
2065if (mcfg_added)
2066xsdt_mod->Length+=8;
2067
2068xsdt_mod->Checksum=0;
2069xsdt_mod->Checksum=256-checksum8(xsdt_mod,xsdt_mod->Length);
2070}
2071else
2072{
2073drop_xsdt:
2074
2075DBG("About to drop XSDT\n");
2076
2077/*FIXME: Now we just hope that if MacOS doesn't find XSDT it reverts to RSDT.
2078 * A Better strategy would be to generate
2079 */
2080
2081rsdp_mod->XsdtAddress=0xffffffffffffffffLL;
2082verbose("XSDT not found or XSDT incorrect\n");
2083}
2084}
2085
2086// Correct the checksum of RSDP
2087
2088DBG("RSDP: Original checksum %d, ", rsdp_mod->Checksum);
2089
2090rsdp_mod->Checksum=0;
2091rsdp_mod->Checksum=256-checksum8(rsdp_mod,20);
2092
2093DBG("New checksum %d\n", rsdp_mod->Checksum);
2094
2095if (version)
2096{
2097DBG("RSDP: Original extended checksum %d", rsdp_mod->ExtendedChecksum);
2098
2099rsdp_mod->ExtendedChecksum=0;
2100rsdp_mod->ExtendedChecksum=256-checksum8(rsdp_mod,rsdp_mod->Length);
2101
2102DBG("New extended checksum %d\n", rsdp_mod->ExtendedChecksum);
2103
2104}
2105
2106verbose("Patched ACPI version %d DSDT\n", version+1);
2107if (version)
2108{
2109/* XXX aserebln why uint32 cast if pointer is uint64 ? */
2110acpi20_p = (uint32_t)rsdp_mod;
2111acpi10_p = (uint32_t)rsdp_mod;
2112addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
2113addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
2114}
2115else
2116{
2117/* XXX aserebln why uint32 cast if pointer is uint64 ? */
2118acpi10_p = (uint32_t)rsdp_mod;
2119addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
2120}
2121}
2122#if DEBUG_ACPI
2123printf("Press a key to continue... (DEBUG_ACPI)\n");
2124getc();
2125#endif
2126return 1;
2127}
2128

Archive Download this file

Revision: 683