Chameleon

Chameleon Svn Source Tree

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

  • Property svn:executable set to
1/*
2 * Copyright 2008 mackerintel
3 */
4
5#include "libsaio.h"
6#include "boot.h"
7#include "bootstruct.h"
8#include "acpi.h"
9#include "efi_tables.h"
10#include "fake_efi.h"
11#include "acpi_patcher.h"
12#include "platform.h"
13#include "cpu.h"
14#include "aml_generator.h"
15
16#ifndef DEBUG_ACPI
17#define DEBUG_ACPI 0
18#endif
19
20#if DEBUG_ACPI==2
21#define DBG(x...) {printf(x); sleep(1);}
22#elif DEBUG_ACPI==1
23#define DBG(x...) printf(x)
24#else
25#define DBG(x...)
26#endif
27
28uint64_t acpi10_p;
29uint64_t acpi20_p;
30
31/* Gets the ACPI 1.0 RSDP address */
32static struct acpi_2_rsdp* getAddressOfAcpiTable()
33{
34 /* TODO: Before searching the BIOS space we are supposed to search the first 1K of the EBDA */
35
36 void *acpi_addr = (void*)ACPI_RANGE_START;
37 for(; acpi_addr <= (void*)ACPI_RANGE_END; acpi_addr += 16)
38 {
39 if(*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE)
40 {
41 uint8_t csum = checksum8(acpi_addr, 20);
42 if(csum == 0)
43 {
44 // Only return the table if it is a true version 1.0 table (Revision 0)
45 if(((struct acpi_2_rsdp*)acpi_addr)->Revision == 0)
46 return acpi_addr;
47 }
48 }
49 }
50 return NULL;
51}
52
53/* Gets the ACPI 2.0 RSDP address */
54static struct acpi_2_rsdp* getAddressOfAcpi20Table()
55{
56 /* TODO: Before searching the BIOS space we are supposed to search the first 1K of the EBDA */
57
58 void *acpi_addr = (void*)ACPI_RANGE_START;
59 for(; acpi_addr <= (void*)ACPI_RANGE_END; acpi_addr += 16)
60 {
61 if(*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE)
62 {
63 uint8_t csum = checksum8(acpi_addr, 20);
64
65 /* Only assume this is a 2.0 or better table if the revision is greater than 0
66 * NOTE: ACPI 3.0 spec only seems to say that 1.0 tables have revision 1
67 * and that the current revision is 2.. I am going to assume that rev > 0 is 2.0.
68 */
69
70 if(csum == 0 && (((struct acpi_2_rsdp*)acpi_addr)->Revision > 0))
71 {
72 uint8_t csum2 = checksum8(acpi_addr, sizeof(struct acpi_2_rsdp));
73 if(csum2 == 0)
74 return acpi_addr;
75 }
76 }
77 }
78 return NULL;
79}
80
81/* The folowing ACPI Table search algo. should be reused anywhere needed:*/
82int search_and_get_acpi_fd(const char * filename, const char ** outDirspec)
83{
84int fd=0;
85const char * overriden_pathname=NULL;
86static char dirspec[512]="";
87int len=0;
88
89// Take in accound user overriding if it's DSDT only
90if (strstr(filename, "DSDT") &&
91getValueForKey(kDSDT, &overriden_pathname, &len, &bootInfo->bootConfig))
92 {
93sprintf(dirspec, "%s", overriden_pathname); // start searching root
94fd=open (dirspec,0);
95if (fd>=0) goto success_fd;
96 }
97
98// Start searching any potential location for ACPI Table
99sprintf(dirspec, "/%s", filename); // start searching root
100fd=open (dirspec,0);
101if (fd>=0) goto success_fd;
102
103sprintf(dirspec, "%s", filename); // start current dir
104fd=open (dirspec,0);
105if (fd>=0) goto success_fd;
106
107sprintf(dirspec,"/Extra/%s",filename);
108fd=open (dirspec,0);
109if (fd>=0) goto success_fd;
110
111sprintf(dirspec,"bt(0,0)/Extra/%s",filename);
112fd=open (dirspec,0);
113if (fd>=0) goto success_fd;
114
115// NOT FOUND:
116//verbose("ACPI Table not found: %s\n", filename);
117if (outDirspec) *outDirspec = "";
118return -1;
119// FOUND
120success_fd:
121if (outDirspec) *outDirspec = dirspec;
122return fd;
123}
124
125void *loadACPITable(char *key)
126{
127void *tableAddr;
128int fd = -1;
129char dirspec[512];
130char filename[512];
131const char * overriden_pathname=NULL;
132int len=0;
133
134sprintf(filename, "%s.aml", key);
135
136// Checking boot partition
137
138// Rek: if user specified a full path name then take it in consideration
139if (getValueForKey(key, &overriden_pathname, &len, &bootInfo->bootConfig))
140{
141sprintf(dirspec, "%s", overriden_pathname); // start searching root
142//printf("Using custom %s path %s\n", key, dirspec);
143//getc();
144}
145else
146sprintf(dirspec, "/%s", filename); // start searching root
147
148fd=open (dirspec,0);
149
150if (fd<0)
151{// Check Extra on booting partition
152 //verbose("Searching for %s.aml file ...\n", key);
153sprintf(dirspec,"/Extra/%s",filename);
154fd=open (dirspec,0);
155if (fd<0)
156{// Fall back to booter partition
157sprintf(dirspec,"bt(0,0)/Extra/%s",filename);
158fd=open (dirspec,0);
159if (fd<0)
160{
161//verbose("ACPI Table not found: %s\n", filename);
162return NULL;
163}
164}
165}
166
167tableAddr=(void*)AllocateKernelMemory(file_size (fd));
168if (tableAddr)
169{
170if (read (fd, tableAddr, file_size (fd))!=file_size (fd))
171{
172printf("Couldn't read table %s\n",dirspec);
173free (tableAddr);
174close (fd);
175return NULL;
176}
177
178DBG("Table %s read and stored at: %x\n", dirspec, tableAddr);
179close (fd);
180return tableAddr;
181}
182
183printf("Couldn't allocate memory for table %s\n", dirspec);
184close (fd);
185
186return NULL;
187}
188
189uint8_tacpi_cpu_count = 0;
190char* acpi_cpu_name[32];
191
192void get_acpi_cpu_names(unsigned char* dsdt, uint32_t length)
193{
194uint32_t i;
195
196for (i=0; i<length-7; i++)
197{
198if (dsdt[i] == 0x5B && dsdt[i+1] == 0x83) // ProcessorOP
199{
200uint32_t offset = i + 3 + (dsdt[i+2] >> 6);
201
202bool add_name = true;
203
204uint8_t j;
205
206for (j=0; j<4; j++)
207{
208char c = dsdt[offset+j];
209
210if (!aml_isvalidchar(c))
211{
212add_name = false;
213verbose("Invalid character found in ProcessorOP 0x%x!\n", c);
214break;
215}
216}
217
218if (add_name)
219{
220acpi_cpu_name[acpi_cpu_count] = malloc(4);
221memcpy(acpi_cpu_name[acpi_cpu_count], dsdt+offset, 4);
222i = offset + 5;
223
224verbose("Found ACPI CPU: %c%c%c%c\n", acpi_cpu_name[acpi_cpu_count][0], acpi_cpu_name[acpi_cpu_count][1], acpi_cpu_name[acpi_cpu_count][2], acpi_cpu_name[acpi_cpu_count][3]);
225
226if (++acpi_cpu_count == 32) return;
227}
228}
229}
230}
231
232struct acpi_2_ssdt *generate_cst_ssdt(struct acpi_2_fadt* fadt)
233{
234char ssdt_header[] =
235{
2360x53, 0x53, 0x44, 0x54, 0xE7, 0x00, 0x00, 0x00, /* SSDT.... */
2370x01, 0x17, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x41, /* ..PmRefA */
2380x43, 0x70, 0x75, 0x43, 0x73, 0x74, 0x00, 0x00, /* CpuCst.. */
2390x00, 0x10, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* ....INTL */
2400x31, 0x03, 0x10, 0x20 /* 1.._*/
241};
242
243char cstate_resource_template[] =
244{
2450x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00, 0x7F,
2460x01, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
2470x00, 0x00, 0x00, 0x79, 0x00
248};
249
250if (Platform.CPU.Vendor != 0x756E6547) {
251verbose ("C-States: Not an Intel platform !!!\n");
252return NULL;
253}
254
255if (fadt == NULL) {
256verbose ("C-States: FACP not found !!!\n");
257return NULL;
258}
259
260struct acpi_2_dsdt* dsdt = (void*)fadt->DSDT;
261
262if (dsdt == NULL) {
263verbose ("C-States: DSDT not found !!!\n");
264return NULL;
265}
266
267if (acpi_cpu_count == 0)
268get_acpi_cpu_names((void*)dsdt, dsdt->Length);
269
270if (acpi_cpu_count > 0)
271{
272//valv: c2 & c3 are enabled by default; else don't use EnableCStates
273bool c2_enabled, c3_enabled, c4_enabled, c6_enabled, tmpval2, tmpval3, tmpval4, tmpval6;
274c2_enabled = c3_enabled = c4_enabled = c6_enabled = false;
275unsigned char cstates_count;
276
277c2_enabled = (getBoolForKey(kEnableC2State, &tmpval2, &bootInfo->bootConfig)&&tmpval2) | (fadt->P_LVL2_LAT < 100);
278c3_enabled = (getBoolForKey(kEnableC3State, &tmpval3, &bootInfo->bootConfig)&&tmpval3) | (fadt->P_LVL2_LAT < 1000);
279c4_enabled = getBoolForKey(kEnableC4State, &tmpval4, &bootInfo->bootConfig)&&tmpval4;
280c6_enabled = getBoolForKey(kEnableC6State, &tmpval6, &bootInfo->bootConfig)&&tmpval6;
281
282if(c6_enabled) c4_enabled = true;
283if(c4_enabled) c3_enabled = true;
284if(c3_enabled) c2_enabled = true;
285
286if(Platform.CPU.Family == 0x06)
287{
288int intelCPU = Platform.CPU.Model;
289switch (intelCPU)
290{
291case 0x0F: // Core (65nm)
292case 0x1A: // Core i7, Xeon 5500 series - Bloomfield, Gainstown NHM-EP - LGA1366 (45nm)
293case 0x1E: // Core i5, i7 - Clarksfield, Lynnfield, Jasper Forest - LGA1156 (45nm)
294case 0x1F: // Core i5, i7 - Nehalem
295case 0x25: // Core i3, i5, i7 - Westmere Client - Clarkdale, Arrandale - LGA1156 (32nm)
296case 0x2C: // Core i7 - Westmere EP - Gulftown - LGA1366 (32nm) 6 Core
297case 0x2E: // Westmere-Ex Xeon
298case 0x2F: // Westmere-Ex Xeon - Eagelton
299cstates_count = 1 + (c2_enabled ? 1 : 0) + (c3_enabled ? 1 : 0);
300verbose("C-State: Adding %d states: ", cstates_count);
301break;
302case 0x1C: // Atom (45nm)
303case 0x26: // Atom Lincroft
304cstates_count = 1 + (c2_enabled ? 1 : 0) + (c4_enabled ? 1 : 0) + (c6_enabled ? 1 : 0);
305verbose("C-State: Adding %d states: ", cstates_count);
306break;
307case 0x17:
308cstates_count = 1 + (c2_enabled ? 1 : 0) + (c3_enabled ? 1 : 0) + (c4_enabled ? 1 : 0) + (c6_enabled ? 1 : 0);
309verbose("C-State: Adding %d states: ", cstates_count);
310break;
311default:
312cstates_count = 1 + (c2_enabled ? 1 : 0) + (c3_enabled ? 1 : 0) + (c4_enabled ? 1 : 0);
313break;
314}
315}
316else cstates_count = 1 + (c2_enabled ? 1 : 0) + (c3_enabled ? 1 : 0) + (c4_enabled ? 1 : 0);
317
318struct aml_chunk* root = aml_create_node(NULL);
319aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header
320struct aml_chunk* scop = aml_add_scope(root, "\\_PR_");
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 ("C-States: ACPI CPUs not found !!!\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 ("P-States: Not an Intel platform !!!\n");
586return NULL;
587}
588
589if (!(platformCPUFeature(CPU_FEATURE_MSR))) {
590verbose ("P-States: Unsupported CPU !!!\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("P-States: 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//valv: fix p-states number issue for some models. TODO: move to top
792if(!strstr(MacProduct, "applemac2010"))
793{
794verbose("Model detected: %s\n", MacProduct);
795if(strstr(MacProduct, "MacBookPro4,1") && ((p_states_count > 9) && ((pstart == 0) && (pstates == 0)))) pstates = 8;
796if(strstr(MacProduct, "MacBookAir1,1") && ((p_states_count > 4) && ((pstart == 0) && (pstates == 0)))) pstates = 3;
797}
798
799struct aml_chunk* root = aml_create_node(NULL);
800aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header
801struct aml_chunk* scop = aml_add_scope(root, "\\_PR_");
802
803aml_add_buffer(scop, ssdt_pct, sizeof(ssdt_pct));
804
805struct aml_chunk* name_psd = aml_add_name(scop, "PSD_");
806struct aml_chunk* pack_psd = aml_add_package(name_psd);
807struct aml_chunk* psd = aml_add_package(pack_psd);
808aml_add_byte(psd, 0x05);
809aml_add_byte(psd, 0x00);
810aml_add_dword(psd, 0x00);
811aml_add_dword(psd, 0xfc);
812aml_add_dword(psd, Platform.CPU.NoCores);
813
814struct aml_chunk* name_pss = aml_add_name(scop, "PSS_");
815struct aml_chunk* pack_pss = aml_add_package(name_pss);
816
817for (i = pstart; i < p_states_count; i++)
818{
819if ((p_states[i].Frequency <= freq_max) && (p_states[i].Frequency >= freq_min))
820{
821//valv: inspired from cparm's pss-drop; coded by me ;)
822if ((i > pstates) && (pstates > 0))
823{
824if(Platform.CPU.ISerie) verbose("P-State: [Frequency %d MHz, FID 0x%x] is the %dth state. Removed!\n",
825p_states[i].Frequency, p_states[i].FID, (i+1));
826else verbose("P-State: [Frequency %d MHz, FID 0x%x, VID 0x%x] is the %dth state. Removed!\n",
827p_states[i].Frequency, p_states[i].FID, p_states[i].VID, (i+1));
828}
829else
830{
831struct aml_chunk* pstt = aml_add_package(pack_pss);
832
833aml_add_dword(pstt, p_states[i].Frequency);
834aml_add_dword(pstt, 0x00000000); // Power
835aml_add_dword(pstt, 0x0000000A); // Latency
836aml_add_dword(pstt, 0x0000000A); // Latency
837if(Platform.CPU.ISerie)
838{
839aml_add_dword(pstt, p_states[i].FID);
840aml_add_dword(pstt, p_states[i].FID);
841verbose("P-State: Added [Frequency %d MHz, FID 0x%x]\n", p_states[i].Frequency, p_states[i].FID);
842}
843else
844{
845aml_add_dword(pstt, p_states[i].Control);
846aml_add_dword(pstt, p_states[i].Control);
847//aml_add_dword(pstt, i+1); // Status
848verbose("P-State: Added [Frequency %d MHz, FID 0x%x, VID 0x%x]\n",
849p_states[i].Frequency, p_states[i].FID, p_states[i].VID);
850}
851}
852}
853else
854{
855if(Platform.CPU.ISerie) verbose("P-State: [Frequency %d MHz, FID 0x%x] is over the limit. Removed!\n",
856p_states[i].Frequency, p_states[i].FID);
857else verbose("P-State: [Frequency %d MHz, FID 0x%x, VID 0x%x] is over the limit. Removed!\n",
858p_states[i].Frequency, p_states[i].FID, p_states[i].VID);
859}
860}
861
862struct aml_chunk* name_ppc = aml_add_name(scop, "PPC_");
863aml_add_byte(name_ppc, 0x00);
864
865// Add aliaces
866for (i = 0; i < acpi_cpu_count; i++)
867{
868char name[9];
869sprintf(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]);
870
871scop = aml_add_scope(root, name);
872aml_add_alias(scop, "PCT_", "_PCT");
873aml_add_alias(scop, "PSD_", "_PSD");
874aml_add_alias(scop, "PSS_", "_PSS");
875aml_add_alias(scop, "PPC_", "_PPC");
876}
877
878aml_calculate_size(root);
879
880struct acpi_2_ssdt *ssdt = (struct acpi_2_ssdt *)AllocateKernelMemory(root->Size);
881
882aml_write_node(root, (void*)ssdt, 0);
883
884ssdt->Length = root->Size;
885ssdt->Checksum = 0;
886ssdt->Checksum = 256 - checksum8(ssdt, ssdt->Length);
887
888 aml_destroy_node(root);
889
890//verbose ("SSDT with CPU P-States generated successfully\n");
891
892return ssdt;
893}
894}
895else {
896verbose ("P-States: ACPI CPUs not found !!!\n");
897}
898
899return NULL;
900}
901
902struct acpi_2_ssdt *generate_tss_ssdt(struct acpi_2_fadt* fadt)
903{
904char ssdt_header[] =
905{
906 0x53, 0x53, 0x44, 0x54, 0xE7, 0x00, 0x00, 0x00,
907 0x01, 0x17, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x42,
908 0x43, 0x70, 0x75, 0x54, 0x73, 0x74, 0x00, 0x00,
909 0x00, 0x10, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C,
910 0x31, 0x03, 0x10, 0x20
911};
912
913char ssdt_ptc[] =
914{
9150x08, 0x5F, 0x50, 0x54, 0x43, 0x12, 0x2C, 0x02,
9160x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00, 0x7F,
9170x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9180x00, 0x00, 0x00, 0x79, 0x00, 0x11, 0x14, 0x0A,
9190x11, 0x82, 0x0C, 0x00, 0x7F, 0x00, 0x00, 0x00,
9200x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9210x79, 0x00
922};
923
924if (Platform.CPU.Vendor != 0x756E6547) {
925verbose ("T-States: Not an Intel platform !!!\n");
926return NULL;
927}
928
929if (!(platformCPUFeature(CPU_FEATURE_MSR))) {
930verbose ("T-States: Unsupported CPU !!!\n");
931return NULL;
932}
933
934if (fadt == NULL) {
935verbose ("FACP not found: T-States will not be generated !!!\n");
936return NULL;
937}
938
939struct acpi_2_dsdt* dsdt = (void*)fadt->DSDT;
940
941if (dsdt == NULL) {
942verbose ("T-States: DSDT not found !!!\n");
943return NULL;
944}
945
946if (acpi_cpu_count == 0)
947get_acpi_cpu_names((void*)dsdt, dsdt->Length);
948
949if (acpi_cpu_count > 0)
950{
951
952struct t_state t_states[32];
953uint8_t t_states_count = 0, ctrl0 = 0x10, j = 0x01;
954int i, step;
955
956if(!fadt->DUTY_WIDTH)
957{
958verbose("T-States: Unsupported CPU !!!\n");
959return NULL;
960}
961
962verbose("T-States: duty_offset=%d, duty_width=%d", fadt->DUTY_OFFSET, fadt->DUTY_WIDTH);
963uint8_t duty_cycle = fadt->DUTY_WIDTH + fadt->DUTY_OFFSET;
964
965if (duty_cycle > 4)
966{
967verbose(", Spanning bit 4");
968//return NULL;
969t_states_count = 8;
970}
971else t_states_count = 1 << fadt->DUTY_WIDTH;
972
973step = (1000 / t_states_count);
974verbose("\nT-States: step=%d\n", step);
975
976for (i = 1; i < t_states_count; i++)
977{
978t_states[i].perf = (1000 - (step * i)) / 10;
979t_states[i].pwer = 1000 - (step * i);
980t_states[i].ctrl = ctrl0 - j;
981j++;
982}
983
984// Generating SSDT
985if (t_states_count > 0)
986{
987struct aml_chunk* root = aml_create_node(NULL);
988aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header
989struct aml_chunk* scop = aml_add_scope(root, "\\_PR_");
990
991struct aml_chunk* name_tpc = aml_add_name(scop, "TPC_");
992aml_add_byte(name_tpc, 0x00);
993
994aml_add_buffer(scop, ssdt_ptc, sizeof(ssdt_ptc));
995
996struct aml_chunk* name_tss = aml_add_name(scop, "TSS_");
997struct aml_chunk* pack_tss = aml_add_package(name_tss);
998
999struct aml_chunk* tssp0 = aml_add_package(pack_tss);
1000aml_add_dword(tssp0, 0x64);// Frequency %
1001aml_add_dword(tssp0, 0x03E8);// Power
1002aml_add_dword(tssp0, 0x00);// Latency
1003aml_add_dword(tssp0, 0x00);// Control; spec says 0x07; apple uses 0;
1004aml_add_dword(tssp0, 0x00);// Status
1005
1006for (i = 1; i < t_states_count; i++)
1007{
1008struct aml_chunk* tssp = aml_add_package(pack_tss);
1009
1010aml_add_dword(tssp, t_states[i].perf);
1011aml_add_dword(tssp, t_states[i].pwer);
1012aml_add_dword(tssp, 0x00);
1013aml_add_dword(tssp, t_states[i].ctrl);
1014aml_add_dword(tssp, 0x00);
1015}
1016
1017struct aml_chunk* name_tsd = aml_add_name(scop, "TSD_");
1018struct aml_chunk* pack_tsd = aml_add_package(name_tsd);
1019struct aml_chunk* tsd = aml_add_package(pack_tsd);
1020aml_add_byte(tsd, 0x05);
1021aml_add_byte(tsd, 0x00);
1022aml_add_dword(tsd, 0x00);
1023aml_add_dword(tsd, 0xfc);
1024aml_add_dword(tsd, Platform.CPU.NoCores);
1025
1026// Add aliaces
1027for (i = 0; i < acpi_cpu_count; i++)
1028{
1029char name[9];
1030sprintf(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]);
1031
1032scop = aml_add_scope(root, name);
1033aml_add_alias(scop, "TPC_", "_TPC");
1034aml_add_alias(scop, "PTC_", "_PTC");
1035aml_add_alias(scop, "TSS_", "_TSS");
1036aml_add_alias(scop, "TSD_", "_TSD");
1037}
1038
1039aml_calculate_size(root);
1040
1041struct acpi_2_ssdt *ssdt = (struct acpi_2_ssdt *)AllocateKernelMemory(root->Size);
1042
1043aml_write_node(root, (void*)ssdt, 0);
1044
1045ssdt->Length = root->Size;
1046ssdt->Checksum = 0;
1047ssdt->Checksum = 256 - checksum8(ssdt, ssdt->Length);
1048
1049 aml_destroy_node(root);
1050
1051verbose ("T-States: %d states were succefully generated\n");
1052
1053return ssdt;
1054}
1055}
1056else
1057{
1058verbose ("ACPI CPUs not found: T-States not generated !!!\n");
1059}
1060
1061return NULL;
1062}
1063
1064void *loadSSDTTable(int ssdt_number)
1065{
1066void *tableAddr;
1067int fd = -1;
1068char dirspec[512];
1069char filename[512];
1070const char * overriden_pathname=NULL;
1071int len=0;
1072
1073sprintf(filename, "SSDT-%d.aml", ssdt_number);
1074
1075// Check booting partition
1076
1077// Rek: if user specified a full path name then take it in consideration
1078if (getValueForKey(kSSDT, &overriden_pathname, &len, &bootInfo->bootConfig))
1079{
1080sprintf(dirspec, "%s-%d.aml", overriden_pathname, ssdt_number); // start searching root
1081//printf("Using custom %s path %s\n", key, dirspec);
1082//getc();
1083}
1084else
1085sprintf(dirspec, "/%s", filename); // start searching root
1086
1087fd=open (dirspec,0);
1088
1089if (fd<0)
1090{// Check Extra on booting partition
1091//verbose("Searching for %s.aml file ...\n", key);
1092sprintf(dirspec,"/Extra/%s",filename);
1093fd=open (dirspec,0);
1094if (fd<0)
1095{// Fall back to booter partition
1096sprintf(dirspec,"bt(0,0)/Extra/%s",filename);
1097fd=open (dirspec,0);
1098if (fd<0)
1099{
1100//verbose("SSDT Table not found: %s\n", filename);
1101return NULL;
1102}
1103}
1104}
1105
1106tableAddr=(void*)AllocateKernelMemory(file_size (fd));
1107if (tableAddr)
1108{
1109if (read (fd, tableAddr, file_size (fd))!=file_size (fd))
1110{
1111printf("Couldn't read table %s\n",dirspec);
1112free (tableAddr);
1113close (fd);
1114return NULL;
1115}
1116
1117DBG("Table %s read and stored at: %x\n", dirspec, tableAddr);
1118close (fd);
1119return tableAddr;
1120}
1121
1122printf("Couldn't allocate memory for table %s\n", dirspec);
1123close (fd);
1124
1125return NULL;
1126}
1127
1128struct acpi_2_gas FillGASStruct(uint32_t Address, uint8_t Length)
1129{
1130struct acpi_2_gas TmpGAS;
1131
1132TmpGAS.Address_Space_ID = 1; /* I/O Address */
1133
1134if (Address == 0)
1135{
1136TmpGAS.Register_Bit_Width = 0;
1137} else {
1138TmpGAS.Register_Bit_Width = Length * 8;
1139}
1140
1141TmpGAS.Register_Bit_Offset = 0;
1142TmpGAS.Access_Size = 0; /* Not set for Legacy reasons... */
1143TmpGAS.Address = (uint64_t)Address;
1144
1145return(TmpGAS);
1146}
1147
1148struct acpi_2_fadt *patch_fadt(struct acpi_2_fadt *fadt, void *new_dsdt, bool UpdateFADT)
1149{
1150 extern void setupSystemType();
1151
1152struct acpi_2_fadt *fadt_mod;
1153struct acpi_2_fadt *fadt_file = (struct acpi_2_fadt *)loadACPITable(kFADT);
1154bool fadt_rev2_needed = false;
1155bool fix_restart;
1156const char * value;
1157
1158// Restart Fix
1159if (Platform.CPU.Vendor == 0x756E6547) {/* Intel */
1160fix_restart = true;
1161getBoolForKey(kRestartFix, &fix_restart, &bootInfo->bootConfig);
1162} else {
1163verbose ("Not an Intel platform: Restart Fix not applied !!!\n");
1164fix_restart = false;
1165}
1166
1167if (fix_restart)
1168fadt_rev2_needed = true;
1169
1170// Allocate new fadt table
1171if ((UpdateFADT) && (((fadt_file) && (fadt_file->Length < sizeof(struct acpi_2_fadt))) ||
1172 ((!fadt_file) && (fadt->Length < sizeof(struct acpi_2_fadt)))))
1173{
1174fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(sizeof(struct acpi_2_fadt));
1175
1176if (fadt_file)
1177memcpy(fadt_mod, fadt_file, fadt_file->Length);
1178else
1179memcpy(fadt_mod, fadt, fadt->Length);
1180
1181fadt_mod->Length = sizeof(struct acpi_2_fadt);
1182fadt_mod->Revision = 0x04; // FADT rev 4
1183fadt_mod->RESET_REG = FillGASStruct(0, 0);
1184fadt_mod->RESET_VALUE = 0;
1185fadt_mod->Reserved2[0] = 0;
1186fadt_mod->Reserved2[1] = 0;
1187fadt_mod->Reserved2[2] = 0;
1188fadt_mod->X_PM1a_EVT_BLK = FillGASStruct(fadt_mod->PM1a_EVT_BLK, fadt_mod->PM1_EVT_LEN);
1189fadt_mod->X_PM1b_EVT_BLK = FillGASStruct(fadt_mod->PM1b_EVT_BLK, fadt_mod->PM1_EVT_LEN);
1190fadt_mod->X_PM1a_CNT_BLK = FillGASStruct(fadt_mod->PM1a_CNT_BLK, fadt_mod->PM1_CNT_LEN);
1191fadt_mod->X_PM1b_CNT_BLK = FillGASStruct(fadt_mod->PM1b_CNT_BLK, fadt_mod->PM1_CNT_LEN);
1192fadt_mod->X_PM2_CNT_BLK = FillGASStruct(fadt_mod->PM2_CNT_BLK, fadt_mod->PM2_CNT_LEN);
1193fadt_mod->X_PM_TMR_BLK = FillGASStruct(fadt_mod->PM_TMR_BLK, fadt_mod->PM_TMR_LEN);
1194fadt_mod->X_GPE0_BLK = FillGASStruct(fadt_mod->GPE0_BLK, fadt_mod->GPE0_BLK_LEN);
1195fadt_mod->X_GPE1_BLK = FillGASStruct(fadt_mod->GPE1_BLK, fadt_mod->GPE1_BLK_LEN);
1196verbose("Converted ACPI V%d FADT to ACPI V4 FADT\n", (fadt_file) ? fadt_file->Revision : fadt->Revision);
1197} else {
1198if (((!fadt_file) && ((fadt->Length < 0x84) && (fadt_rev2_needed))) ||
1199 ((fadt_file) && ((fadt_file->Length < 0x84) && (fadt_rev2_needed))))
1200{
1201fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(0x84);
1202
1203if (fadt_file)
1204memcpy(fadt_mod, fadt_file, fadt_file->Length);
1205else
1206memcpy(fadt_mod, fadt, fadt->Length);
1207
1208fadt_mod->Length = 0x84;
1209fadt_mod->Revision = 0x02; // FADT rev 2 (ACPI 1.0B MS extensions)
1210}
1211else
1212{
1213if (fadt_file)
1214{
1215fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(fadt_file->Length);
1216memcpy(fadt_mod, fadt_file, fadt_file->Length);
1217} else {
1218fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(fadt->Length);
1219memcpy(fadt_mod, fadt, fadt->Length);
1220}
1221}
1222}
1223// Determine system type / PM_Model
1224if ( (value=getStringForKey(kSystemType, &bootInfo->bootConfig))!=NULL)
1225{
1226 if (Platform.Type > 6)
1227 {
1228 if(fadt_mod->Preferred_PM_Profile<=6)
1229 Platform.Type = fadt_mod->Preferred_PM_Profile; // get the fadt if correct
1230 else
1231 Platform.Type = 1;/* Set a fixed value (Desktop) */
1232 verbose("Error: system-type must be 0..6. Defaulting to %d !\n", Platform.Type);
1233 }
1234 else
1235 Platform.Type = (unsigned char) strtoul(value, NULL, 10);
1236}
1237// Set Preferred_PM_Profile from System-type only if user wanted this value to be forced
1238if (fadt_mod->Preferred_PM_Profile != Platform.Type)
1239{
1240 if (value)
1241 { // user has overriden the SystemType so take care of it in FACP
1242verbose("FADT: changing Preferred_PM_Profile from 0x%02x to 0x%02x\n", fadt_mod->Preferred_PM_Profile, Platform.Type);
1243fadt_mod->Preferred_PM_Profile = Platform.Type;
1244 }
1245 else
1246 { // Preferred_PM_Profile has a different value and no override has been set, so reflect the user value to ioregs
1247 Platform.Type = fadt_mod->Preferred_PM_Profile <= 6 ? fadt_mod->Preferred_PM_Profile : 1;
1248 }
1249}
1250// We now have to write the systemm-type in ioregs: we cannot do it before in setupDeviceTree()
1251// because we need to take care of facp original content, if it is correct.
1252setupSystemType();
1253
1254// Patch FADT to fix restart
1255if (fix_restart)
1256{
1257fadt_mod->Flags|= 0x400;
1258fadt_mod->RESET_REG = FillGASStruct(0x0cf9, 1);
1259fadt_mod->RESET_VALUE = 0x06;
1260
1261verbose("FADT: Restart Fix applied !\n");
1262}
1263
1264// Patch FACS Address
1265fadt_mod->FIRMWARE_CTRL=(uint32_t)fadt->FIRMWARE_CTRL;
1266if ((uint32_t)(&(fadt_mod->X_FIRMWARE_CTRL))-(uint32_t)fadt_mod+8<=fadt_mod->Length)
1267fadt_mod->X_FIRMWARE_CTRL=(uint32_t)fadt->FIRMWARE_CTRL;
1268
1269// Patch DSDT Address if we have one loaded
1270if(new_dsdt)
1271{
1272fadt_mod->DSDT=(uint32_t)new_dsdt;
1273if ((uint32_t)(&(fadt_mod->X_DSDT))-(uint32_t)fadt_mod+8<=fadt_mod->Length)
1274fadt_mod->X_DSDT=(uint32_t)new_dsdt;
1275}
1276
1277
1278// Correct the checksum
1279fadt_mod->Checksum=0;
1280fadt_mod->Checksum=256-checksum8(fadt_mod,fadt_mod->Length);
1281
1282return fadt_mod;
1283}
1284#if UNUSED
1285/* Setup ACPI without replacing DSDT. */
1286int setupAcpiNoMod()
1287{
1288//addConfigurationTable(&gEfiAcpiTableGuid, getAddressOfAcpiTable(), "ACPI");
1289//addConfigurationTable(&gEfiAcpi20TableGuid, getAddressOfAcpi20Table(), "ACPI_20");
1290/* XXX aserebln why uint32 cast if pointer is uint64 ? */
1291acpi10_p = (uint32_t)getAddressOfAcpiTable();
1292acpi20_p = (uint32_t)getAddressOfAcpi20Table();
1293addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
1294if(acpi20_p) addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
1295return 1;
1296}
1297#endif
1298
1299/* Setup ACPI. Replace DSDT if DSDT.aml is found */
1300int setupAcpi(void)
1301{
1302int version;
1303void *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];
1304
1305struct acpi_2_ssdt *new_ssdt[16]; // 2 additional tables for pss/tss & cst
1306struct acpi_2_fadt *fadt; // will be used in CST generator
1307
1308bool 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;
1309bool drop_ssdt=false, drop_hpet=false, drop_slic=false, drop_sbst=false, drop_ecdt=false, drop_asft=false, drop_dmar=false;
1310bool update_acpi=false, gen_xsdt=false;
1311bool hpet_replaced=false, sbst_replaced=false, ecdt_replaced=false, asft_replaced=false, dmar_replaced=false, apic_replaced=false, mcfg_replaced=false;
1312bool hpet_added=false, sbst_added=false, ecdt_added=false, asft_added=false, dmar_added=false, apic_added=false, mcfg_added=false;
1313bool gen_cst=false, gen_pss=false, gen_tss=false;
1314
1315int curssdt=0, loadtotssdt=0, totssdt=0, newtotssdt=0;
1316
1317{
1318bool tmpval, tmpval2, tmpval3, tmpval4, tmpval6;
1319
1320drop_ssdt = getBoolForKey(kDropSSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1321drop_hpet = getBoolForKey(kDropHPET, &tmpval, &bootInfo->bootConfig)&&tmpval;
1322drop_slic = getBoolForKey(kDropSLIC, &tmpval, &bootInfo->bootConfig)&&tmpval;
1323drop_sbst = getBoolForKey(kDropSBST, &tmpval, &bootInfo->bootConfig)&&tmpval;
1324drop_ecdt = getBoolForKey(kDropECDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1325drop_asft = getBoolForKey(kDropASFT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1326drop_dmar = getBoolForKey(kDropDMAR, &tmpval, &bootInfo->bootConfig)&&tmpval;
1327
1328oem_dsdt = getBoolForKey(kOEMDSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1329oem_ssdt = getBoolForKey(kOEMSSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1330oem_hpet = getBoolForKey(kOEMHPET, &tmpval, &bootInfo->bootConfig)&&tmpval;
1331oem_sbst = getBoolForKey(kOEMSBST, &tmpval, &bootInfo->bootConfig)&&tmpval;
1332oem_ecdt = getBoolForKey(kOEMECDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1333oem_asft = getBoolForKey(kOEMASFT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1334oem_dmar = getBoolForKey(kOEMDMAR, &tmpval, &bootInfo->bootConfig)&&tmpval;
1335oem_apic = getBoolForKey(kOEMAPIC, &tmpval, &bootInfo->bootConfig)&&tmpval;
1336oem_mcfg = getBoolForKey(kOEMMCFG, &tmpval, &bootInfo->bootConfig)&&tmpval;
1337
1338gen_cst = (getBoolForKey(kGenerateCStates, &tmpval, &bootInfo->bootConfig)&&tmpval)
1339| (getBoolForKey(kEnableC2State, &tmpval2, &bootInfo->bootConfig)&&tmpval2)
1340| (getBoolForKey(kEnableC3State, &tmpval3, &bootInfo->bootConfig)&&tmpval3)
1341| (getBoolForKey(kEnableC4State, &tmpval4, &bootInfo->bootConfig)&&tmpval4)
1342| (getBoolForKey(kEnableC6State, &tmpval6, &bootInfo->bootConfig)&&tmpval6);
1343
1344gen_pss = getBoolForKey(kGeneratePStates, &tmpval, &bootInfo->bootConfig)&&tmpval;
1345
1346gen_tss = getBoolForKey(kGenerateTStates, &tmpval, &bootInfo->bootConfig)&&tmpval;
1347
1348update_acpi = getBoolForKey(kUpdateACPI, &tmpval, &bootInfo->bootConfig)&&tmpval;
1349}
1350
1351// Load replacement ACPI tables
1352if (!oem_dsdt)
1353new_dsdt=loadACPITable(kDSDT);
1354
1355if (!oem_hpet)
1356new_hpet=loadACPITable(kHPET);
1357
1358if (!oem_sbst)
1359new_sbst=loadACPITable(kSBST);
1360
1361if (!oem_ecdt)
1362new_ecdt=loadACPITable(kECDT);
1363
1364if (!oem_asft)
1365new_asft=loadACPITable(kASFT);
1366
1367if (!oem_dmar)
1368new_dmar=loadACPITable(kDMAR);
1369
1370if (!oem_apic)
1371new_apic=loadACPITable(kAPIC);
1372
1373if (!oem_mcfg)
1374new_mcfg=loadACPITable(kMCFG);
1375
1376if (gen_cst || gen_pss || gen_tss) oem_ssdt = false;
1377
1378if (!oem_ssdt)
1379{
1380for (curssdt=0;curssdt<14;curssdt++)
1381{
1382new_ssdt[curssdt]=loadSSDTTable(curssdt);
1383if (new_ssdt[curssdt])
1384loadtotssdt++;
1385}
1386curssdt=0;
1387}
1388/*
1389if (!new_dsdt)
1390return setupAcpiNoMod();
1391*/
1392DBG("New ACPI tables Loaded in memory\n");
1393
1394// Do the same procedure for both versions of ACPI
1395for (version=0; version<2; version++) {
1396struct acpi_2_rsdp *rsdp, *rsdp_mod, *rsdp_conv=(struct acpi_2_rsdp *)0;
1397struct acpi_2_rsdt *rsdt, *rsdt_mod;
1398struct acpi_2_xsdt *xsdt_conv = (struct acpi_2_xsdt *)0;
1399int rsdplength;
1400
1401// Find original rsdp
1402rsdp=(struct acpi_2_rsdp *)(version?getAddressOfAcpi20Table():getAddressOfAcpiTable());
1403if ((update_acpi) && (rsdp->Revision == 0))
1404{
1405rsdp_conv = (struct acpi_2_rsdp *)AllocateKernelMemory(sizeof(struct acpi_2_rsdp));
1406memcpy(rsdp_conv, rsdp, 20);
1407
1408/* Add/change fields */
1409strncpy(rsdp->OEMID, "Apple ", 6);
1410rsdp_conv->Revision = 2; /* ACPI version 3 */
1411rsdp_conv->Length = sizeof(struct acpi_2_rsdp);
1412
1413/* Correct checksums */
1414rsdp_conv->Checksum = 0;
1415rsdp_conv->Checksum = 256-checksum8(rsdp_conv, 20);
1416rsdp_conv->ExtendedChecksum = 0;
1417rsdp_conv->ExtendedChecksum = 256-checksum8(rsdp_conv, rsdp_conv->Length);
1418
1419rsdp = rsdp_conv;
1420
1421gen_xsdt = true;
1422version = 1;
1423
1424addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI");
1425
1426verbose("Converted ACPI RSD PTR version 1 to version 3\n");
1427}
1428if (!rsdp)
1429{
1430DBG("No ACPI version %d found. Ignoring\n", version+1);
1431if (version)
1432addConfigurationTable(&gEfiAcpi20TableGuid, NULL, "ACPI_20");
1433else
1434addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI");
1435continue;
1436}
1437rsdplength=version?rsdp->Length:20;
1438
1439DBG("RSDP version %d found @%x. Length=%d\n",version+1,rsdp,rsdplength);
1440
1441/* FIXME: no check that memory allocation succeeded
1442 * Copy and patch RSDP,RSDT, XSDT and FADT
1443 * For more info see ACPI Specification pages 110 and following
1444 */
1445
1446if (gen_xsdt)
1447{
1448rsdp_mod=rsdp_conv;
1449} else {
1450rsdp_mod=(struct acpi_2_rsdp *) AllocateKernelMemory(rsdplength);
1451memcpy(rsdp_mod, rsdp, rsdplength);
1452}
1453
1454rsdt=(struct acpi_2_rsdt *)(rsdp->RsdtAddress);
1455
1456DBG("RSDT @%x, Length %d\n",rsdt, rsdt->Length);
1457
1458if (rsdt && (uint32_t)rsdt !=0xffffffff && rsdt->Length<0x10000)
1459{
1460uint32_t *rsdt_entries;
1461int rsdt_entries_num;
1462int dropoffset=0, i;
1463
1464rsdt_mod=(struct acpi_2_rsdt *)AllocateKernelMemory(rsdt->Length);
1465memcpy (rsdt_mod, rsdt, rsdt->Length);
1466rsdp_mod->RsdtAddress=(uint32_t)rsdt_mod;
1467rsdt_entries_num=(rsdt_mod->Length-sizeof(struct acpi_2_rsdt))/4;
1468rsdt_entries=(uint32_t *)(rsdt_mod+1);
1469
1470if (gen_xsdt)
1471{
1472uint64_t *xsdt_conv_entries;
1473
1474xsdt_conv=(struct acpi_2_xsdt *)AllocateKernelMemory(sizeof(struct acpi_2_xsdt)+(rsdt_entries_num * 8));
1475memcpy(xsdt_conv, rsdt, sizeof(struct acpi_2_rsdt));
1476
1477xsdt_conv->Signature[0] = 'X';
1478xsdt_conv->Signature[1] = 'S';
1479xsdt_conv->Signature[2] = 'D';
1480xsdt_conv->Signature[3] = 'T';
1481xsdt_conv->Length = sizeof(struct acpi_2_xsdt)+(rsdt_entries_num * 8);
1482
1483xsdt_conv_entries=(uint64_t *)(xsdt_conv+1);
1484
1485for (i=0;i<rsdt_entries_num;i++)
1486{
1487xsdt_conv_entries[i] = (uint64_t)rsdt_entries[i];
1488}
1489
1490xsdt_conv->Checksum = 0;
1491xsdt_conv->Checksum = 256-checksum8(xsdt_conv, xsdt_conv->Length);
1492
1493rsdp->XsdtAddress = (uint32_t)xsdt_conv;
1494
1495rsdp->ExtendedChecksum = 0;
1496rsdp->ExtendedChecksum = 256-checksum8(rsdp, rsdp->Length);
1497
1498verbose("Converted RSDT table to XSDT table\n");
1499}
1500
1501for (i=0;i<rsdt_entries_num;i++)
1502{
1503char *table=(char *)(rsdt_entries[i]);
1504if (!table)
1505continue;
1506
1507DBG("TABLE %c%c%c%c,",table[0],table[1],table[2],table[3]);
1508
1509rsdt_entries[i-dropoffset]=rsdt_entries[i];
1510if (drop_ssdt && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1511{
1512dropoffset++;
1513continue;
1514}
1515if (drop_hpet && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')
1516{
1517dropoffset++;
1518continue;
1519}
1520if (drop_slic && table[0]=='S' && table[1]=='L' && table[2]=='I' && table[3]=='C')
1521{
1522dropoffset++;
1523continue;
1524}
1525if (drop_sbst && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')
1526{
1527dropoffset++;
1528continue;
1529}
1530if (drop_ecdt && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')
1531{
1532dropoffset++;
1533continue;
1534}
1535if (drop_asft && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')
1536{
1537dropoffset++;
1538continue;
1539}
1540if (drop_dmar && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')
1541{
1542dropoffset++;
1543continue;
1544}
1545if ((!(oem_hpet)) && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')
1546{
1547DBG("HPET found\n");
1548if (new_hpet)
1549{
1550rsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
1551hpet_replaced=true;
1552}
1553continue;
1554}
1555if ((!(oem_sbst)) && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')
1556{
1557DBG("SBST found\n");
1558if (new_sbst)
1559{
1560rsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
1561sbst_replaced=true;
1562}
1563continue;
1564}
1565if ((!(oem_ecdt)) && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')
1566{
1567DBG("ECDT found\n");
1568if (new_ecdt)
1569{
1570rsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
1571ecdt_replaced=true;
1572}
1573continue;
1574}
1575if ((!(oem_asft)) && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')
1576{
1577DBG("ASF! found\n");
1578if (new_asft)
1579{
1580rsdt_entries[i-dropoffset]=(uint32_t)new_asft;
1581asft_replaced=true;
1582}
1583continue;
1584}
1585if ((!(oem_dmar)) && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')
1586{
1587DBG("DMAR found\n");
1588if (new_dmar)
1589{
1590rsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
1591dmar_replaced=true;
1592}
1593continue;
1594}
1595if ((!(oem_apic)) && table[0]=='A' && table[1]=='P' && table[2]=='I' && table[3]=='C')
1596{
1597DBG("APIC found\n");
1598if (new_apic)
1599{
1600rsdt_entries[i-dropoffset]=(uint32_t)new_apic;
1601apic_replaced=true;
1602}
1603continue;
1604}
1605if ((!(oem_mcfg)) && table[0]=='M' && table[1]=='C' && table[2]=='F' && table[3]=='G')
1606{
1607DBG("MCFG found\n");
1608if (new_mcfg)
1609{
1610rsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
1611mcfg_replaced=true;
1612}
1613continue;
1614}
1615if ((!(oem_ssdt)) && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1616{
1617DBG("SSDT %d found", curssdt);
1618if (new_ssdt[curssdt])
1619{
1620DBG(" and replaced");
1621rsdt_entries[i-dropoffset]=(uint32_t)new_ssdt[curssdt];
1622totssdt++;
1623}
1624DBG("\n");
1625curssdt++;
1626continue;
1627}
1628if (table[0]=='D' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1629{
1630DBG("DSDT found\n");
1631rsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;
1632continue;
1633
1634} else {
1635struct acpi_2_rsdt *t = (struct acpi_2_rsdt *)table;
1636strncpy(t->OEMID, "Apple ", 6);
1637strncpy(t->OEMTableId, MacModel, 8);
1638t->OEMRevision = ModelRev;
1639t->Checksum=0;
1640t->Checksum=256-checksum8(t,t->Length);
1641}
1642if (table[0]=='F' && table[1]=='A' && table[2]=='C' && table[3]=='P')
1643{
1644struct acpi_2_fadt *fadt_mod;
1645fadt=(struct acpi_2_fadt *)rsdt_entries[i];
1646
1647DBG("FADT found @%x, Length %d\n",fadt, fadt->Length);
1648
1649if (!fadt || (uint32_t)fadt == 0xffffffff || fadt->Length>0x10000)
1650{
1651printf("FADT incorrect. Not modified\n");
1652continue;
1653}
1654
1655fadt_mod = patch_fadt(fadt, new_dsdt, update_acpi);
1656rsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;
1657
1658if(!oem_ssdt)
1659{
1660// Generate _CST SSDT
1661if ( gen_cst && (new_ssdt[loadtotssdt] = generate_cst_ssdt(fadt_mod)))
1662{
1663gen_cst= false;
1664loadtotssdt++;
1665}
1666
1667// Generating _PSS SSDT
1668if (gen_pss && (new_ssdt[loadtotssdt] = generate_pss_ssdt((void*)fadt_mod->DSDT)))
1669{
1670gen_pss= false;
1671loadtotssdt++;
1672}
1673
1674// Generating _TSS SSDT
1675if (gen_tss && (new_ssdt[loadtotssdt] = generate_tss_ssdt((void*)fadt_mod->DSDT)))
1676{
1677gen_tss= false;
1678loadtotssdt++;
1679}
1680}
1681
1682continue;
1683}
1684}
1685DBG("\n");
1686
1687strncpy(rsdt_mod->OEMID, "Apple ", 6);
1688strncpy(rsdt_mod->OEMTableId, MacModel, 8);
1689rsdt_mod->OEMRevision = ModelRev;
1690
1691if ((!oem_hpet) && (!hpet_replaced))
1692{
1693if (new_hpet)
1694{
1695rsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
1696hpet_added=true;
1697i++;
1698}
1699}
1700
1701if ((!oem_sbst) && (!sbst_replaced))
1702{
1703if (new_sbst)
1704{
1705rsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
1706sbst_added=true;
1707i++;
1708}
1709}
1710
1711if ((!oem_ecdt) && (!ecdt_replaced))
1712{
1713if (new_ecdt)
1714{
1715rsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
1716ecdt_added=true;
1717i++;
1718}
1719}
1720
1721if ((!oem_asft) && (!asft_replaced))
1722{
1723if (new_asft)
1724{
1725rsdt_entries[i-dropoffset]=(uint32_t)new_asft;
1726asft_added=true;
1727i++;
1728}
1729}
1730
1731if ((!oem_dmar) && (!dmar_replaced))
1732{
1733if (new_dmar)
1734{
1735rsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
1736dmar_added=true;
1737i++;
1738}
1739}
1740
1741if ((!oem_apic) && (!apic_replaced))
1742{
1743if (new_apic)
1744{
1745rsdt_entries[i-dropoffset]=(uint32_t)new_apic;
1746apic_added=true;
1747i++;
1748}
1749}
1750
1751if ((!oem_mcfg) && (!mcfg_replaced))
1752{
1753if (new_mcfg)
1754{
1755rsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
1756mcfg_added=true;
1757i++;
1758}
1759}
1760
1761if (!oem_ssdt)
1762{
1763while ((totssdt < loadtotssdt) && (curssdt < 14))
1764{
1765if (new_ssdt[curssdt])
1766{
1767DBG("adding SSDT %d\n", curssdt);
1768rsdt_entries[i-dropoffset]=(uint32_t)new_ssdt[curssdt];
1769totssdt++;
1770newtotssdt++;
1771i++;
1772}
1773curssdt++;
1774}
1775}
1776
1777// Correct the checksum of RSDT
1778rsdt_mod->Length-=4*dropoffset;
1779rsdt_mod->Length+=4*newtotssdt;
1780if (hpet_added)
1781rsdt_mod->Length+=4;
1782if (sbst_added)
1783rsdt_mod->Length+=4;
1784if (ecdt_added)
1785rsdt_mod->Length+=4;
1786if (asft_added)
1787rsdt_mod->Length+=4;
1788if (dmar_added)
1789rsdt_mod->Length+=4;
1790if (apic_added)
1791rsdt_mod->Length+=4;
1792if (mcfg_added)
1793rsdt_mod->Length+=4;
1794
1795DBG("RSDT: Original checksum %d, ", rsdt_mod->Checksum);
1796
1797rsdt_mod->Checksum=0;
1798rsdt_mod->Checksum=256-checksum8(rsdt_mod,rsdt_mod->Length);
1799
1800DBG("New checksum %d at %x\n", rsdt_mod->Checksum,rsdt_mod);
1801}
1802else
1803{
1804rsdp_mod->RsdtAddress=0;
1805printf("RSDT not found or RSDT incorrect\n");
1806}
1807
1808if (version)
1809{
1810struct acpi_2_xsdt *xsdt, *xsdt_mod;
1811
1812// FIXME: handle 64-bit address correctly
1813
1814if (gen_xsdt)
1815xsdt=xsdt_conv;
1816else
1817xsdt=(struct acpi_2_xsdt*) ((uint32_t)rsdp->XsdtAddress);
1818
1819DBG("XSDT @%x;%x, Length=%d\n", (uint32_t)(rsdp->XsdtAddress>>32),(uint32_t)rsdp->XsdtAddress, xsdt->Length);
1820if (xsdt && (uint64_t)rsdp->XsdtAddress<0xffffffff && xsdt->Length<0x10000)
1821{
1822uint64_t *xsdt_entries;
1823int xsdt_entries_num, i;
1824int dropoffset=0;
1825curssdt=0, totssdt=0, newtotssdt=0;
1826hpet_replaced=false, hpet_added=false;
1827sbst_replaced=false, sbst_added=false;
1828ecdt_replaced=false, ecdt_added=false;
1829asft_replaced=false, asft_added=false;
1830dmar_replaced=false, dmar_added=false;
1831apic_replaced=false, apic_added=false;
1832mcfg_replaced=false, mcfg_added=false;
1833
1834if (gen_xsdt)
1835xsdt_mod=xsdt;
1836else
1837{
1838xsdt_mod=(struct acpi_2_xsdt*)AllocateKernelMemory(xsdt->Length);
1839memcpy(xsdt_mod, xsdt, xsdt->Length);
1840}
1841
1842rsdp_mod->XsdtAddress=(uint32_t)xsdt_mod;
1843xsdt_entries_num=(xsdt_mod->Length-sizeof(struct acpi_2_xsdt))/8;
1844xsdt_entries=(uint64_t *)(xsdt_mod+1);
1845for (i=0;i<xsdt_entries_num;i++)
1846{
1847char *table=(char *)((uint32_t)(xsdt_entries[i]));
1848if (!table)
1849continue;
1850xsdt_entries[i-dropoffset]=xsdt_entries[i];
1851if (drop_ssdt && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1852{
1853dropoffset++;
1854continue;
1855}
1856if (drop_hpet && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')
1857{
1858dropoffset++;
1859continue;
1860}
1861if (drop_slic && table[0]=='S' && table[1]=='L' && table[2]=='I' && table[3]=='C')
1862{
1863dropoffset++;
1864continue;
1865}
1866if (drop_sbst && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')
1867{
1868dropoffset++;
1869continue;
1870}
1871if (drop_ecdt && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')
1872{
1873dropoffset++;
1874continue;
1875}
1876if (drop_asft && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')
1877{
1878dropoffset++;
1879continue;
1880}
1881if (drop_dmar && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')
1882{
1883dropoffset++;
1884continue;
1885}
1886if ((!(oem_hpet)) && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')
1887{
1888DBG("HPET found\n");
1889if (new_hpet)
1890{
1891xsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
1892hpet_replaced=true;
1893}
1894continue;
1895}
1896if ((!(oem_sbst)) && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')
1897{
1898DBG("SBST found\n");
1899if (new_sbst)
1900{
1901xsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
1902sbst_replaced=true;
1903}
1904continue;
1905}
1906if ((!(oem_ecdt)) && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')
1907{
1908DBG("ECDT found\n");
1909if (new_ecdt)
1910{
1911xsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
1912ecdt_replaced=true;
1913}
1914continue;
1915}
1916if ((!(oem_asft)) && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')
1917{
1918DBG("ASF! found\n");
1919if (new_asft)
1920{
1921xsdt_entries[i-dropoffset]=(uint32_t)new_asft;
1922asft_replaced=true;
1923}
1924continue;
1925}
1926if ((!(oem_dmar)) && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')
1927{
1928DBG("DMAR found\n");
1929if (new_dmar)
1930{
1931xsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
1932dmar_replaced=true;
1933}
1934continue;
1935}
1936if ((!(oem_apic)) && table[0]=='A' && table[1]=='P' && table[2]=='I' && table[3]=='C')
1937{
1938DBG("APIC found\n");
1939if (new_apic)
1940{
1941xsdt_entries[i-dropoffset]=(uint32_t)new_apic;
1942apic_replaced=true;
1943}
1944continue;
1945}
1946if ((!(oem_mcfg)) && table[0]=='M' && table[1]=='C' && table[2]=='F' && table[3]=='G')
1947{
1948DBG("MCFG found\n");
1949if (new_mcfg)
1950{
1951xsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
1952mcfg_replaced=true;
1953}
1954continue;
1955}
1956if ((!(oem_ssdt)) && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1957{
1958DBG("SSDT %d found", curssdt);
1959if (new_ssdt[curssdt])
1960{
1961DBG(" and replaced");
1962xsdt_entries[i-dropoffset]=(uint32_t)new_ssdt[curssdt];
1963totssdt++;
1964}
1965DBG("\n");
1966curssdt++;
1967continue;
1968}
1969if (table[0]=='D' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1970{
1971DBG("DSDT found\n");
1972
1973xsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;
1974
1975DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
1976
1977continue;
1978}
1979
1980struct acpi_2_xsdt* t = (struct acpi_2_xsdt*)table;
1981strncpy(t->OEMID, "Apple ", 6);
1982strncpy(t->OEMTableId, MacModel, 8);
1983t->OEMRevision = ModelRev;
1984
1985if (table[0]=='F' && table[1]=='A' && table[2]=='C' && table[3]=='P')
1986{
1987struct acpi_2_fadt *fadt_mod;
1988fadt=(struct acpi_2_fadt *)(uint32_t)xsdt_entries[i];
1989
1990DBG("FADT found @%x,%x, Length %d\n",(uint32_t)(xsdt_entries[i]>>32),fadt,
1991 fadt->Length);
1992
1993if (!fadt || (uint64_t)xsdt_entries[i] >= 0xffffffff || fadt->Length>0x10000)
1994{
1995verbose("FADT incorrect or after 4GB. Dropping XSDT\n");
1996goto drop_xsdt;
1997}
1998
1999fadt_mod = patch_fadt(fadt, new_dsdt, update_acpi);
2000xsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;
2001
2002DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
2003
2004if (!oem_ssdt)
2005{
2006// Generate _CST SSDT
2007if ( gen_cst && (new_ssdt[loadtotssdt] = generate_cst_ssdt(fadt_mod)))
2008{
2009gen_cst= false;
2010loadtotssdt++;
2011}
2012
2013// Generating _PSS SSDT
2014if (gen_pss && (new_ssdt[loadtotssdt] = generate_pss_ssdt((void*)fadt_mod->DSDT)))
2015{
2016gen_pss= false;
2017loadtotssdt++;
2018}
2019
2020// Generating _TSS SSDT
2021if (gen_tss && (new_ssdt[loadtotssdt] = generate_tss_ssdt((void*)fadt_mod->DSDT)))
2022{
2023gen_tss= false;
2024loadtotssdt++;
2025}
2026}
2027
2028continue;
2029}
2030
2031DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
2032
2033}
2034
2035strncpy(xsdt_mod->OEMID, "Apple ", 6);
2036strncpy(xsdt_mod->OEMTableId, MacModel, 8);
2037xsdt_mod->OEMRevision = ModelRev;
2038
2039if ((!oem_hpet) && (!hpet_replaced))
2040{
2041if (new_hpet)
2042{
2043xsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
2044hpet_added=true;
2045i++;
2046}
2047}
2048
2049if ((!oem_sbst) && (!sbst_replaced))
2050{
2051if (new_sbst)
2052{
2053xsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
2054sbst_added=true;
2055i++;
2056}
2057}
2058
2059if ((!oem_ecdt) && (!ecdt_replaced))
2060{
2061if (new_ecdt)
2062{
2063xsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
2064ecdt_added=true;
2065i++;
2066}
2067}
2068
2069if ((!oem_asft) && (!asft_replaced))
2070{
2071if (new_asft)
2072{
2073xsdt_entries[i-dropoffset]=(uint32_t)new_asft;
2074asft_added=true;
2075i++;
2076}
2077}
2078
2079if ((!oem_dmar) && (!dmar_replaced))
2080{
2081if (new_dmar)
2082{
2083xsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
2084dmar_added=true;
2085i++;
2086}
2087}
2088
2089if ((!oem_apic) && (!apic_replaced))
2090{
2091if (new_apic)
2092{
2093xsdt_entries[i-dropoffset]=(uint32_t)new_apic;
2094apic_added=true;
2095i++;
2096}
2097}
2098
2099if ((!oem_mcfg) && (!mcfg_replaced))
2100{
2101if (new_mcfg)
2102{
2103xsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
2104mcfg_added=true;
2105i++;
2106}
2107}
2108
2109if (!oem_ssdt)
2110{
2111while ((totssdt < loadtotssdt) && (curssdt < 14))
2112{
2113if (new_ssdt[curssdt])
2114{
2115DBG("adding SSDT %d\n", curssdt);
2116xsdt_entries[i-dropoffset]=(uint32_t)new_ssdt[curssdt];
2117totssdt++;
2118newtotssdt++;
2119i++;
2120}
2121curssdt++;
2122}
2123}
2124
2125// Correct the checksum of XSDT
2126xsdt_mod->Length-=8*dropoffset;
2127xsdt_mod->Length+=8*newtotssdt;
2128if (hpet_added)
2129xsdt_mod->Length+=8;
2130if (sbst_added)
2131xsdt_mod->Length+=8;
2132if (ecdt_added)
2133xsdt_mod->Length+=8;
2134if (asft_added)
2135xsdt_mod->Length+=8;
2136if (dmar_added)
2137xsdt_mod->Length+=8;
2138if (apic_added)
2139xsdt_mod->Length+=8;
2140if (mcfg_added)
2141xsdt_mod->Length+=8;
2142
2143xsdt_mod->Checksum=0;
2144xsdt_mod->Checksum=256-checksum8(xsdt_mod,xsdt_mod->Length);
2145}
2146else
2147{
2148drop_xsdt:
2149
2150DBG("About to drop XSDT\n");
2151
2152/*FIXME: Now we just hope that if MacOS doesn't find XSDT it reverts to RSDT.
2153 * A Better strategy would be to generate
2154 */
2155
2156rsdp_mod->XsdtAddress=0xffffffffffffffffLL;
2157verbose("XSDT not found or XSDT incorrect\n");
2158}
2159}
2160
2161// Correct the checksum of RSDP
2162
2163DBG("RSDP: Original checksum %d, ", rsdp_mod->Checksum);
2164
2165rsdp_mod->Checksum=0;
2166rsdp_mod->Checksum=256-checksum8(rsdp_mod,20);
2167
2168DBG("New checksum %d\n", rsdp_mod->Checksum);
2169
2170if (version)
2171{
2172DBG("RSDP: Original extended checksum %d", rsdp_mod->ExtendedChecksum);
2173
2174rsdp_mod->ExtendedChecksum=0;
2175rsdp_mod->ExtendedChecksum=256-checksum8(rsdp_mod,rsdp_mod->Length);
2176
2177DBG("New extended checksum %d\n", rsdp_mod->ExtendedChecksum);
2178
2179}
2180
2181verbose("Patched ACPI version %d DSDT\n", version+1);
2182if (version)
2183{
2184/* XXX aserebln why uint32 cast if pointer is uint64 ? */
2185acpi20_p = (uint32_t)rsdp_mod;
2186acpi10_p = (uint32_t)rsdp_mod;
2187addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
2188addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
2189}
2190else
2191{
2192/* XXX aserebln why uint32 cast if pointer is uint64 ? */
2193acpi10_p = (uint32_t)rsdp_mod;
2194addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
2195}
2196}
2197#if DEBUG_ACPI
2198printf("Press a key to continue... (DEBUG_ACPI)\n");
2199getc();
2200#endif
2201return 1;
2202}
2203

Archive Download this file

Revision: 688