Chameleon

Chameleon Svn Source Tree

Root/trunk/i386/libsaio/acpi_patcher.c

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
28// Slice: New signature compare function
29boolean_t tableSign(char *table, const char *sgn)
30{
31int i;
32for (i=0; i<4; i++) {
33if ((table[i] &~0x20) != (sgn[i] &~0x20)) {
34return FALSE;
35}
36}
37return TRUE;
38}
39
40/* Gets the ACPI 1.0 RSDP address */
41static struct acpi_2_rsdp* getAddressOfAcpiTable()
42{
43 /* TODO: Before searching the BIOS space we are supposed to search the first 1K of the EBDA */
44
45 void *acpi_addr = (void*)ACPI_RANGE_START;
46 for(; acpi_addr <= (void*)ACPI_RANGE_END; acpi_addr += 16)
47 {
48 if(*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE)
49 {
50 uint8_t csum = checksum8(acpi_addr, 20);
51 if(csum == 0)
52 {
53 // Only return the table if it is a true version 1.0 table (Revision 0)
54 if(((struct acpi_2_rsdp*)acpi_addr)->Revision == 0)
55 return acpi_addr;
56 }
57 }
58 }
59 return NULL;
60}
61
62/* Gets the ACPI 2.0 RSDP address */
63static struct acpi_2_rsdp* getAddressOfAcpi20Table()
64{
65 /* TODO: Before searching the BIOS space we are supposed to search the first 1K of the EBDA */
66
67 void *acpi_addr = (void*)ACPI_RANGE_START;
68 for(; acpi_addr <= (void*)ACPI_RANGE_END; acpi_addr += 16)
69 {
70 if(*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE)
71 {
72 uint8_t csum = checksum8(acpi_addr, 20);
73
74 /* Only assume this is a 2.0 or better table if the revision is greater than 0
75 * NOTE: ACPI 3.0 spec only seems to say that 1.0 tables have revision 1
76 * and that the current revision is 2.. I am going to assume that rev > 0 is 2.0.
77 */
78
79 if(csum == 0 && (((struct acpi_2_rsdp*)acpi_addr)->Revision > 0))
80 {
81 uint8_t csum2 = checksum8(acpi_addr, sizeof(struct acpi_2_rsdp));
82 if(csum2 == 0)
83 return acpi_addr;
84 }
85 }
86 }
87 return NULL;
88}
89/** The folowing ACPI Table search algo. should be reused anywhere needed:*/
90int search_and_get_acpi_fd(const char * filename, const char ** outDirspec)
91{
92int fd=0;
93const char * overriden_pathname=NULL;
94static char dirspec[512]="";
95static bool first_time =true;
96int len=0;
97
98/// Take in accound user overriding if it's DSDT only
99if (strstr(filename, "DSDT") &&
100getValueForKey(kDSDT, &overriden_pathname, &len,
101 &bootInfo->bootConfig))
102 {
103sprintf(dirspec, "%s", overriden_pathname);
104fd=open (dirspec,0);
105if (fd>=0) goto success_fd;
106 }
107// Check that dirspec is not already assigned with a path
108if (!first_time && *dirspec)
109{ // it is so start searching this cached patch first
110//extract path
111for (len=strlen(dirspec)-1; len; len--)
112if (dirspec[len]=='/' || len==0)
113{
114dirspec[len]='\0';
115break;
116}
117// now concat with the filename
118strncat(dirspec, "/", sizeof(dirspec));
119strncat(dirspec, filename, sizeof(dirspec));
120// and test to see if we don't have our big boy here:
121fd=open (dirspec,0);
122if (fd>=0)
123{
124// printf("ACPI file search cache hit: file found at %s\n", dirspec);
125goto success_fd;
126}
127}
128// Start searching any potential location for ACPI Table
129// search the Extra folders first
130sprintf(dirspec,"/Extra/%s",filename);
131fd=open (dirspec,0);
132if (fd>=0) goto success_fd;
133
134sprintf(dirspec,"bt(0,0)/Extra/%s",filename);
135fd=open (dirspec,0);
136if (fd>=0) goto success_fd;
137
138sprintf(dirspec, "%s", filename); // search current dir
139fd=open (dirspec,0);
140if (fd>=0) goto success_fd;
141
142sprintf(dirspec, "/%s", filename); // search root
143fd=open (dirspec,0);
144if (fd>=0) goto success_fd;
145
146// NOT FOUND:
147//verbose("ACPI Table not found: %s\n", filename);
148if (outDirspec) *outDirspec = "";
149first_time = false;
150return -1;
151// FOUND
152success_fd:
153first_time = false;
154if (outDirspec) *outDirspec = dirspec;
155return fd;
156}
157
158void *loadACPITable (const char * filename)
159{
160void *tableAddr;
161const char * dirspec=NULL;
162
163int fd = search_and_get_acpi_fd(filename, &dirspec);
164
165if (fd>=0)
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}
182close (fd);
183printf("Couldn't allocate memory for table \n", dirspec);
184}
185//printf("Couldn't find table %s\n", filename);
186return NULL;
187}
188
189uint8_tacpi_cpu_count = 0;
190char* acpi_cpu_name[32];
191
192void find_acpi_cpu_names(unsigned char* dsdt, int length)
193{
194int i;
195
196for (i=0; i<length-7; i++)
197{
198if (dsdt[i] == 0x83 && dsdt[i+1] == 0x0B && dsdt[i+6] < 32)
199{
200acpi_cpu_name[acpi_cpu_count] = malloc(5);
201
202int j;
203for (j=0; j<4; j++)
204{
205if (aml_isvalidchar(dsdt[i+2+j]))
206{
207acpi_cpu_name[acpi_cpu_count][j] = dsdt[i+2+j];
208}
209else
210{
211verbose("Invalid characters found in ProcessorOP!");
212free(acpi_cpu_name[acpi_cpu_count]);
213continue;
214}
215}
216
217verbose("Found %c%c%c%c (from DSDT)\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]);
218
219acpi_cpu_count++;
220}
221}
222}
223
224struct acpi_2_ssdt *generate_cst_ssdt(struct acpi_2_fadt* fadt)
225{
226char ssdt_header[] =
227{
2280x53, 0x53, 0x44, 0x54, 0xE7, 0x00, 0x00, 0x00, /* SSDT.... */
2290x01, 0x17, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x41, /* ..PmRefA */
2300x43, 0x70, 0x75, 0x43, 0x73, 0x74, 0x00, 0x00, /* CpuCst.. */
2310x00, 0x10, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* ....INTL */
2320x31, 0x03, 0x10, 0x20 /* 1.._*/
233};
234
235char chunk_name_body[] =
236{
2370x5C, 0x5F, 0x50, 0x52, 0x5F, 0x08, 0x43, 0x53, /* \_PR_.CS */
2380x54, 0x5F/* T_*/
239};
240
241char chunk_c1[] =
242{
2430x12, 0x1C, 0x04, 0x11, 0x14, 0x0A, 0x11, 0x82,
2440x0C, 0x00, 0x7F, 0x01, 0x02, 0x01, 0x00, 0x00,
2450x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00,
2460x01, 0x01, 0x0B, 0xE8, 0x03
247};
248
249char chunk_c2[] =
250{
2510x12, 0x1E, 0x04, 0x11, 0x14, 0x0A, 0x11, 0x82,
2520x0C, 0x00, 0x7F, 0x01, 0x02, 0x01, 0x10, 0x00,
2530x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00,
2540x0A, 0x02, 0x0A, 0x40, 0x0B, 0xF4, 0x01
255};
256
257char chunk_c3[] =
258{
2590x12, 0x1F, 0x04, 0x11, 0x14, 0x0A, 0x11, 0x82,
2600x0C, 0x00, 0x7F, 0x01, 0x02, 0x01, 0x20, 0x00,
2610x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00,
2620x0A, 0x03, 0x0B, 0x60, 0x03, 0x0B, 0x5E, 0x01
263};
264
265char chunk_alias[] =
266{
2670x10, 0x14, 0x5C, 0x2E, 0x5F, 0x50, 0x52, 0x5F, /* ..\._PR_ */
2680x43, 0x50, 0x55, 0x30, 0x06, 0x43, 0x53, 0x54, /* CPU0.CST */
2690x5F, 0x5F, 0x43, 0x53, 0x54/* __CST*/
270};
271
272if (fadt == NULL) {
273verbose ("FACP not exists: C-States not generated !!!\n");
274return NULL;
275}
276
277struct acpi_2_dsdt* dsdt = (void*)fadt->DSDT;
278
279if (dsdt == NULL) {
280verbose ("DSDT not found: C-States not generated !!!\n");
281return NULL;
282}
283
284if (acpi_cpu_count == 0)
285find_acpi_cpu_names((void*)dsdt, dsdt->Length);
286
287if (acpi_cpu_count > 0) {
288bool c2_enabled = fadt->C2_Latency < 100, c3_enabled = fadt->C3_Latency < 1000;
289
290// Setup C2 Latency
291if (c2_enabled)
292chunk_c2[27] = fadt->C2_Latency & 0xff;
293
294// Setup C3 Latency
295if (c3_enabled) {
296chunk_c3[27] = fadt->C3_Latency & 0xff;
297chunk_c3[28] = (fadt->C3_Latency >> 8) & 0xff;
298}
299
300// Generating SSDT
301uint32_t package_length =
3024 +
303sizeof(chunk_c1) +
304c2_enabled * sizeof(chunk_c2) +
305c3_enabled * sizeof(chunk_c3);
306
307if (package_length > 0x3f)
308package_length++;
309
310uint32_t name_length =
3111 +
312sizeof(chunk_name_body) +
3131 + package_length;
314
315if (name_length > 0x3f)
316name_length++;
317
318uint32_t ssdt_size =
319sizeof(ssdt_header) +
3201 + name_length +
321acpi_cpu_count * sizeof(chunk_alias);
322
323struct acpi_2_ssdt *ssdt = (void*)AllocateKernelMemory(ssdt_size);
324int fd = openmem((char*)ssdt, ssdt_size);
325
326// Header
327write(fd, ssdt_header, sizeof(ssdt_header));
328
329// Scope (\_PR) { Name (CST
330writebyte(fd, 0x10); // id
331if (name_length > 0x3f)
332{
333writebyte(fd, 0x40 | (name_length & 0xf)); // lo half-byte
334writebyte(fd, name_length >> 4); // hi byte
335}
336else
337{
338writebyte(fd, name_length); // length
339}
340write(fd, chunk_name_body, sizeof(chunk_name_body));
341
342//Package (0x04) { 0x03,
343writebyte(fd, 0x12); // id
344if (package_length > 0x3f)
345{
346writebyte(fd, 0x40 | (package_length & 0xf)); // lo half-byte
347writebyte(fd, package_length >> 4); // hi byte
348}
349else
350{
351writebyte(fd, package_length); // length
352}
353uint8_t cstates_count = 1 + c2_enabled + c3_enabled;
354writebyte(fd, cstates_count + 1);
355writebyte(fd, 0x0A); // first entry - number of c-states
356writebyte(fd, cstates_count);
357
358// C1
359write(fd, chunk_c1, sizeof(chunk_c1));
360
361// C2
362if (c2_enabled)
363write(fd, chunk_c2, sizeof(chunk_c2));
364
365// C3
366if (c3_enabled)
367write(fd, chunk_c3, sizeof(chunk_c3));
368
369// Write aliases
370int i;
371for (i = 0; i < acpi_cpu_count; i++) {
372int j;
373for (j = 0; j < 4; j++)
374chunk_alias[8+j] = acpi_cpu_name[i][j];
375write(fd, chunk_alias, sizeof(chunk_alias));
376}
377
378close(fd);
379
380ssdt->Length = ssdt_size;
381ssdt->Checksum = 0;
382ssdt->Checksum = 256 - checksum8(ssdt, ssdt->Length);
383
384//dumpPhysAddr("C-States SSDT content: ", ssdt, ssdt_size);
385
386verbose ("SSDT with CPU C-States generated successfully\n");
387
388return ssdt;
389}
390else {
391verbose ("DSDT CPUs not found: C-States not generated !!!\n");
392}
393
394return NULL;
395}
396
397struct acpi_2_ssdt *generate_pss_ssdt(struct acpi_2_dsdt* dsdt)
398{
399char ssdt_header[] =
400{
4010x53, 0x53, 0x44, 0x54, 0x7E, 0x00, 0x00, 0x00, /* SSDT.... */
4020x01, 0x6A, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x00, /* ..PmRef. */
4030x43, 0x70, 0x75, 0x50, 0x6D, 0x00, 0x00, 0x00, /* CpuPm... */
4040x00, 0x30, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* .0..INTL */
4050x31, 0x03, 0x10, 0x20,/* 1.._*/
406};
407
408char chunk_name_body[] =
409{
4100x5C, 0x5F, 0x50, 0x52, 0x5F, 0x08, 0x50, 0x53, /* \_PR_.PS */
4110x53, 0x5F/* S_*/
412};
413
414char chunk_alias[] =
415{
4160x10, 0x14, 0x5C, 0x2E, 0x5F, 0x50, 0x52, 0x5F, /* ..\._PR_ */
4170x43, 0x50, 0x55, 0x30, 0x06, 0x50, 0x53, 0x53, /* CPU0.PSS */
4180x5F, 0x5F, 0x50, 0x53, 0x53/* __PSS*/
419};
420
421if (Platform.CPU.Vendor != 0x756E6547) {
422verbose ("Not an Intel platform: P-States will not be generated !!!\n");
423return NULL;
424}
425
426if (!(Platform.CPU.Features & CPU_FEATURE_MSR)) {
427verbose ("Unsupported CPU: P-States will not be generated !!!\n");
428return NULL;
429}
430
431if (acpi_cpu_count == 0)
432find_acpi_cpu_names((void*)dsdt, dsdt->Length);
433
434if (acpi_cpu_count > 0)
435{
436bool cpu_dynamic_fsb = false, cpu_noninteger_bus_ratio = (rdmsr64(MSR_IA32_PERF_STATUS) & (1ULL << 46));
437struct p_state initial, maximum, minimum, p_states[32];
438uint8_t p_states_count;
439
440// Retrieving P-States, ported from code by superhai (c)
441
442
443
444switch (Platform.CPU.Family) {
445case 0x06:
446{
447switch (Platform.CPU.Model)
448{
449case 0x0F: // Intel Core (65nm)
450case 0x17: // Intel Core (45nm)
451case 0x1C: // Intel Atom (45nm)
452case 0x1A: // Intel Core i7 LGA1366 (45nm)
453case 0x1E: // Intel Core i5, i7 LGA1156 (45nm)
454case 0x25: // Intel Core i3, i5, i7 LGA1156 (32nm)
455case 0x2C: // Intel Core i7 LGA1366 (32nm) 6 Core
456if (rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 27))
457{
458wrmsr64(MSR_IA32_EXT_CONFIG, (rdmsr64(MSR_IA32_EXT_CONFIG) | (1 << 28)));
459delay(1);
460cpu_dynamic_fsb = rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 28);
461}
462break;
463}
464}
465}
466
467initial.Control = rdmsr64(MSR_IA32_PERF_STATUS);
468
469maximum.Control = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 32) & 0x1F3F) | (0x4000 * cpu_noninteger_bus_ratio);
470maximum.CID = ((maximum.FID & 0x1F) << 1) | cpu_noninteger_bus_ratio;
471
472minimum.FID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 24) & 0x1F) | (0x80 * cpu_dynamic_fsb);
473minimum.VID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 48) & 0x3F);
474
475if (minimum.FID == 0)
476{
477uint8_t i;
478// Probe for lowest fid
479for (i = maximum.FID; i >= 0x6; i--)
480{
481wrmsr64(MSR_IA32_PERF_CONTROL, (rdmsr64(MSR_IA32_PERF_CONTROL) & 0xFFFFFFFFFFFF0000ULL) | (i << 8) | minimum.VID);
482intel_waitforsts();
483minimum.FID = (rdmsr64(MSR_IA32_PERF_STATUS) >> 8) & 0x1F;
484delay(1);
485}
486
487wrmsr64(MSR_IA32_PERF_CONTROL, (rdmsr64(MSR_IA32_PERF_CONTROL) & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
488intel_waitforsts();
489}
490
491if (minimum.VID == maximum.VID)
492{
493uint8_t i;
494// Probe for lowest vid
495for (i = maximum.VID; i > 0xA; i--)
496{
497wrmsr64(MSR_IA32_PERF_CONTROL, (rdmsr64(MSR_IA32_PERF_CONTROL) & 0xFFFFFFFFFFFF0000ULL) | (minimum.FID << 8) | i);
498intel_waitforsts();
499minimum.VID = rdmsr64(MSR_IA32_PERF_STATUS) & 0x3F;
500delay(1);
501}
502
503wrmsr64(MSR_IA32_PERF_CONTROL, (rdmsr64(MSR_IA32_PERF_CONTROL) & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
504intel_waitforsts();
505}
506
507minimum.CID = ((minimum.FID & 0x1F) << 1) >> cpu_dynamic_fsb;
508
509// Sanity check
510if (maximum.CID < minimum.CID)
511{
512DBG("Insane FID values!");
513p_states_count = 1;
514}
515else
516{
517// Finalize P-States
518// Find how many P-States machine supports
519p_states_count = maximum.CID - minimum.CID + 1;
520
521if (p_states_count > 32)
522p_states_count = 32;
523
524uint8_t vidstep;
525uint8_t i = 0, u, invalid = 0;
526
527vidstep = ((maximum.VID << 2) - (minimum.VID << 2)) / (p_states_count - 1);
528
529for (u = 0; u < p_states_count; u++)
530{
531i = u - invalid;
532
533p_states[i].CID = maximum.CID - u;
534p_states[i].FID = (p_states[i].CID >> 1);
535
536if (p_states[i].FID < 0x6)
537{
538if (cpu_dynamic_fsb)
539p_states[i].FID = (p_states[i].FID << 1) | 0x80;
540}
541else if (cpu_noninteger_bus_ratio)
542{
543p_states[i].FID = p_states[i].FID | (0x40 * (p_states[i].CID & 0x1));
544}
545
546if (i && p_states[i].FID == p_states[i-1].FID)
547invalid++;
548
549p_states[i].VID = ((maximum.VID << 2) - (vidstep * u)) >> 2;
550
551uint32_t multiplier = p_states[i].FID & 0x1f;// = 0x08
552bool half = p_states[i].FID & 0x40;// = 0x01
553bool dfsb = p_states[i].FID & 0x80;// = 0x00
554uint32_t fsb = Platform.CPU.FSBFrequency / 1000000; // = 400
555uint32_t halffsb = (fsb + 1) >> 1;// = 200
556uint32_t frequency = (multiplier * fsb);// = 3200
557
558p_states[i].Frequency = (frequency + (half * halffsb)) >> dfsb;// = 3200 + 200 = 3400
559}
560
561p_states_count -= invalid;
562}
563
564// Generating SSDT
565
566if (p_states_count > 0)
567{
568uint32_t i, pss_entries_size = 33 * p_states_count, pss_package_length = pss_entries_size + 2;
569
570if (pss_package_length > 0x3f) pss_package_length++; // for chunks > 0x3f bytes length have 2 bytes encoding
571
572uint32_t pss_name_length = (1 /* id=0x12 */ + pss_package_length) + (1 + 10);
573
574if (pss_name_length > 0x3f) pss_name_length++;
575
576uint32_t ssdt_size = 36 + (1 /* id=0x10 */ + pss_name_length) + acpi_cpu_count * sizeof(chunk_alias);
577
578struct acpi_2_ssdt *ssdt = (void*)AllocateKernelMemory(ssdt_size);
579int fd = openmem((char*)ssdt, ssdt_size);
580
581// write header
582write(fd, ssdt_header, sizeof(ssdt_header));
583
584// write Scope (\_PR) {Name (PSS, ...
585writebyte(fd, 0x10); // id
586if (pss_name_length > 0x3f)
587{
588writebyte(fd, 0x40 | (pss_name_length & 0xf)); // lo half-byte
589writebyte(fd, pss_name_length >> 4); // hi byte
590}
591else
592{
593writebyte(fd, pss_name_length); // length
594}
595write(fd, chunk_name_body, sizeof(chunk_name_body));
596
597// write Package(p_states_count) { ...
598writebyte(fd, 0x12); // id
599if (pss_package_length > 0x3f)
600{
601writebyte(fd, 0x40 | (pss_package_length & 0xf)); // lo half-byte
602writebyte(fd, pss_package_length >> 4); // hi byte
603}
604else
605{
606writebyte(fd, pss_package_length); // length
607}
608writebyte(fd, p_states_count); // entries
609
610for (i = 0; i < p_states_count; i++)
611{
612DBG("P-State: Frequency %d MHz, FID 0x%x, VID 0x%x\n", p_states[i].Frequency, p_states[i].FID, p_states[i].VID);
613
614writebyte(fd, 0x12); // chunk id
615writebyte(fd, 32); // chunk length without id
616writebyte(fd, 6); // entries
617
618writebyte(fd, 0x0C); /* id */ writeint(fd, p_states[i].Frequency); // value
619writebyte(fd, 0x0C); /* id */ writeint(fd, 0x00000000); // value
620writebyte(fd, 0x0C); /* id */ writeint(fd, 0x0000000A); // value
621writebyte(fd, 0x0C); /* id */ writeint(fd, 0x0000000A); // value
622writebyte(fd, 0x0C); /* id */ writeint(fd, p_states[i].Control); // value
623writebyte(fd, 0x0C); /* id */ writeint(fd, i + 1); // value
624}
625
626// Write aliases
627for (i = 0; i < acpi_cpu_count; i++) {
628int j;
629for (j = 0; j < 4; j++)
630chunk_alias[8+j] = acpi_cpu_name[i][j];
631write(fd, chunk_alias, sizeof(chunk_alias));
632}
633
634ssdt->Length = ssdt_size;
635ssdt->Checksum = 0;
636ssdt->Checksum = 256 - checksum8(ssdt, ssdt->Length);
637
638//dumpPhysAddr("P-States SSDT content: ", ssdt, ssdt_size);
639verbose ("SSDT with CPU P-States generated successfully\n");
640
641return ssdt;
642}
643}
644else {
645verbose ("DSDT CPUs not found: P-States not generated !!!\n");
646}
647
648return NULL;
649}
650
651struct acpi_2_fadt *patch_fadt(struct acpi_2_fadt *fadt, struct acpi_2_dsdt *new_dsdt)
652{
653extern void setupSystemType();
654
655struct acpi_2_fadt *fadt_mod;
656bool fadt_rev2_needed = false;
657bool fix_restart;
658const char * value;
659
660// Restart Fix
661if (Platform.CPU.Vendor == 0x756E6547) {/* Intel */
662fix_restart = true;
663getBoolForKey(kRestartFix, &fix_restart, &bootInfo->bootConfig);
664} else {
665verbose ("Not an Intel platform: Restart Fix not applied !!!\n");
666fix_restart = false;
667}
668
669if (fix_restart) fadt_rev2_needed = true;
670
671// Allocate new fadt table
672if (fadt->Length < 0x84 && fadt_rev2_needed)
673{
674fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(0x84);
675memcpy(fadt_mod, fadt, fadt->Length);
676fadt_mod->Length = 0x84;
677fadt_mod->Revision = 0x02; // FADT rev 2 (ACPI 1.0B MS extensions)
678}
679else
680{
681fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(fadt->Length);
682memcpy(fadt_mod, fadt, fadt->Length);
683}
684// Determine system type / PM_Model
685if ( (value=getStringForKey(kSystemType, &bootInfo->bootConfig))!=NULL)
686{
687if (Platform.Type > 6)
688{
689if(fadt_mod->PM_Profile<=6)
690Platform.Type = fadt_mod->PM_Profile; // get the fadt if correct
691else
692Platform.Type = 1;/* Set a fixed value (Desktop) */
693verbose("Error: system-type must be 0..6. Defaulting to %d !\n", Platform.Type);
694}
695else
696Platform.Type = (unsigned char) strtoul(value, NULL, 10);
697}
698// Set PM_Profile from System-type if only if user wanted this value to be forced
699if (fadt_mod->PM_Profile != Platform.Type)
700{
701 if (value)
702{ // user has overriden the SystemType so take care of it in FACP
703verbose("FADT: changing PM_Profile from 0x%02x to 0x%02x\n", fadt_mod->PM_Profile, Platform.Type);
704fadt_mod->PM_Profile = Platform.Type;
705 }
706 else
707 { // PM_Profile has a different value and no override has been set, so reflect the user value to ioregs
708Platform.Type = fadt_mod->PM_Profile <= 6 ? fadt_mod->PM_Profile : 1;
709 }
710}
711// We now have to write the systemm-type in ioregs: we cannot do it before in setupDeviceTree()
712// because we need to take care of facp original content, if it is correct.
713setupSystemType();
714
715// Patch FADT to fix restart
716if (fix_restart)
717{
718fadt_mod->Flags|= 0x400;
719fadt_mod->Reset_SpaceID= 0x01; // System I/O
720fadt_mod->Reset_BitWidth= 0x08; // 1 byte
721fadt_mod->Reset_BitOffset= 0x00; // Offset 0
722fadt_mod->Reset_AccessWidth= 0x01; // Byte access
723fadt_mod->Reset_Address= 0x0cf9; // Address of the register
724fadt_mod->Reset_Value= 0x06; // Value to write to reset the system
725verbose("FADT: Restart Fix applied!\n");
726}
727
728// Patch DSDT Address if we have loaded DSDT.aml
729if(new_dsdt)
730{
731DBG("DSDT: Old @%x,%x, ",fadt_mod->DSDT,fadt_mod->X_DSDT);
732
733fadt_mod->DSDT=(uint32_t)new_dsdt;
734if ((uint32_t)(&(fadt_mod->X_DSDT))-(uint32_t)fadt_mod+8<=fadt_mod->Length)
735fadt_mod->X_DSDT=(uint32_t)new_dsdt;
736
737DBG("New @%x,%x\n",fadt_mod->DSDT,fadt_mod->X_DSDT);
738
739verbose("FADT: Using custom DSDT!\n");
740}
741
742// Correct the checksum
743fadt_mod->Checksum=0;
744fadt_mod->Checksum=256-checksum8(fadt_mod,fadt_mod->Length);
745
746return fadt_mod;
747}
748
749/* Setup ACPI without replacing DSDT. */
750int setupAcpiNoMod()
751{
752//addConfigurationTable(&gEfiAcpiTableGuid, getAddressOfAcpiTable(), "ACPI");
753//addConfigurationTable(&gEfiAcpi20TableGuid, getAddressOfAcpi20Table(), "ACPI_20");
754/* XXX aserebln why uint32 cast if pointer is uint64 ? */
755acpi10_p = (uint32_t)getAddressOfAcpiTable();
756acpi20_p = (uint32_t)getAddressOfAcpi20Table();
757addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
758if(acpi20_p) addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
759return 1;
760}
761
762/* Setup ACPI. Replace DSDT if DSDT.aml is found */
763int setupAcpi(void)
764{
765int version;
766void *new_dsdt;
767
768// Load replacement DSDT
769new_dsdt=loadACPITable("DSDT.aml");
770// Mozodojo: going to patch FACP and load SSDT's even if DSDT.aml is not present
771/*if (!new_dsdt)
772 {
773 return setupAcpiNoMod();
774 }*/
775
776// Mozodojo: Load additional SSDTs
777struct acpi_2_ssdt *new_ssdt[32]; // 30 + 2 additional tables for pss & cst
778struct acpi_2_fadt *fadt; // will be used in CST generator
779int ssdt_count=0;
780bool drop_ssdt=false, generate_pstates=false, generate_cstates=false;
781
782getBoolForKey(kDropSSDT, &drop_ssdt, &bootInfo->bootConfig);
783getBoolForKey(kGeneratePStates, &generate_pstates, &bootInfo->bootConfig);
784getBoolForKey(kGenerateCStates, &generate_cstates, &bootInfo->bootConfig);
785
786{
787int i;
788
789for (i=0; i<30; i++)
790{
791char *filename[512];
792
793sprintf(filename, i>0?"SSDT-%d.aml":"SSDT.aml", i);
794
795if(new_ssdt[ssdt_count] = loadACPITable(filename))
796{
797ssdt_count++;
798}
799else
800{
801break;
802}
803}
804}
805
806// Do the same procedure for both versions of ACPI
807for (version=0; version<2; version++) {
808struct acpi_2_rsdp *rsdp, *rsdp_mod;
809struct acpi_2_rsdt *rsdt, *rsdt_mod;
810int rsdplength;
811
812// Find original rsdp
813rsdp=(struct acpi_2_rsdp *)(version?getAddressOfAcpi20Table():getAddressOfAcpiTable());
814if (!rsdp)
815{
816DBG("No ACPI version %d found. Ignoring\n", version+1);
817if (version)
818addConfigurationTable(&gEfiAcpi20TableGuid, NULL, "ACPI_20");
819else
820addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI");
821continue;
822}
823rsdplength=version?rsdp->Length:20;
824
825DBG("RSDP version %d found @%x. Length=%d\n",version+1,rsdp,rsdplength);
826
827/* FIXME: no check that memory allocation succeeded
828 * Copy and patch RSDP,RSDT, XSDT and FADT
829 * For more info see ACPI Specification pages 110 and following
830 */
831
832rsdp_mod=(struct acpi_2_rsdp *) AllocateKernelMemory(rsdplength);
833memcpy(rsdp_mod, rsdp, rsdplength);
834rsdt=(struct acpi_2_rsdt *)(rsdp->RsdtAddress);
835
836DBG("RSDT @%x, Length %d\n",rsdt, rsdt->Length);
837
838if (rsdt && (uint32_t)rsdt !=0xffffffff && rsdt->Length<0x10000)
839{
840uint32_t *rsdt_entries;
841int rsdt_entries_num;
842int dropoffset=0, i;
843
844rsdt_mod=(struct acpi_2_rsdt *)AllocateKernelMemory(rsdt->Length);
845memcpy (rsdt_mod, rsdt, rsdt->Length);
846rsdp_mod->RsdtAddress=(uint32_t)rsdt_mod;
847rsdt_entries_num=(rsdt_mod->Length-sizeof(struct acpi_2_rsdt))/4;
848rsdt_entries=(uint32_t *)(rsdt_mod+1);
849for (i=0;i<rsdt_entries_num;i++)
850{
851char *table=(char *)(rsdt_entries[i]);
852if (!table)
853continue;
854
855DBG("TABLE %c%c%c%c,",table[0],table[1],table[2],table[3]);
856
857rsdt_entries[i-dropoffset]=rsdt_entries[i];
858
859if (drop_ssdt && tableSign(table, "SSDT"))
860{
861dropoffset++;
862continue;
863}
864if (tableSign(table, "DSDT"))
865{
866DBG("DSDT found\n");
867
868if(new_dsdt)
869rsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;
870
871continue;
872}
873if (tableSign(table, "FACP"))
874{
875struct acpi_2_fadt *fadt_mod;
876fadt=(struct acpi_2_fadt *)rsdt_entries[i];
877
878DBG("FADT found @%x, Length %d\n",fadt, fadt->Length);
879
880if (!fadt || (uint32_t)fadt == 0xffffffff || fadt->Length>0x10000)
881{
882printf("FADT incorrect. Not modified\n");
883continue;
884}
885
886fadt_mod = patch_fadt(fadt, new_dsdt);
887rsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;
888
889// Generate _CST SSDT
890if (generate_cstates && (new_ssdt[ssdt_count] = generate_cst_ssdt(fadt_mod)))
891ssdt_count++;
892
893// Generating _PSS SSDT
894if (generate_pstates && (new_ssdt[ssdt_count] = generate_pss_ssdt((void*)fadt_mod->DSDT)))
895ssdt_count++;
896
897continue;
898}
899}
900DBG("\n");
901
902// Mozodojo: Insert additional SSDTs into RSDT
903if(ssdt_count>0)
904{
905uint32_t j = rsdt_mod->Length;
906bool add_new_ssdt = TRUE;
907
908rsdt_mod->Length+=4*ssdt_count-4*dropoffset;
909
910if (rsdt_mod->Length > j)
911{
912struct acpi_2_rsdt *rsdt_copy = (struct acpi_2_rsdt *)AllocateKernelMemory(rsdt_mod->Length);
913if (rsdt_copy)
914{
915memcpy (rsdt_copy, rsdt_mod, rsdt_mod->Length);
916free(rsdt_mod); rsdt_mod = rsdt_copy;
917rsdp_mod->RsdtAddress=(uint32_t)rsdt_mod;
918rsdt_entries_num=(rsdt_mod->Length-sizeof(struct acpi_2_rsdt))/4;
919rsdt_entries=(uint32_t *)(rsdt_mod+1);
920}
921else
922{
923verbose("RSDT: Couldn't allocate memory for additional SSDT tables!\n");
924add_new_ssdt = FALSE;
925}
926}
927
928if (add_new_ssdt)
929{
930for (j=0; j<ssdt_count; j++)
931rsdt_entries[i-dropoffset+j]=(uint32_t)new_ssdt[j];
932
933verbose("RSDT: Added %d SSDT table(s)\n", ssdt_count);
934}
935}
936else
937{
938rsdt_mod->Length-=4*dropoffset;
939}
940
941// Correct the checksum of RSDT
942DBG("RSDT: Original checksum %d, ", rsdt_mod->Checksum);
943
944rsdt_mod->Checksum=0;
945rsdt_mod->Checksum=256-checksum8(rsdt_mod,rsdt_mod->Length);
946
947DBG("New checksum %d at %x\n", rsdt_mod->Checksum,rsdt_mod);
948}
949else
950{
951rsdp_mod->RsdtAddress=0;
952printf("RSDT not found or RSDT incorrect\n");
953}
954
955if (version)
956{
957struct acpi_2_xsdt *xsdt, *xsdt_mod;
958
959// FIXME: handle 64-bit address correctly
960
961xsdt=(struct acpi_2_xsdt*) ((uint32_t)rsdp->XsdtAddress);
962DBG("XSDT @%x;%x, Length=%d\n", (uint32_t)(rsdp->XsdtAddress>>32),(uint32_t)rsdp->XsdtAddress,
963xsdt->Length);
964if (xsdt && (uint64_t)rsdp->XsdtAddress<0xffffffff && xsdt->Length<0x10000)
965{
966uint64_t *xsdt_entries;
967int xsdt_entries_num, i;
968int dropoffset=0;
969
970xsdt_mod=(struct acpi_2_xsdt*)AllocateKernelMemory(xsdt->Length);
971memcpy(xsdt_mod, xsdt, xsdt->Length);
972rsdp_mod->XsdtAddress=(uint32_t)xsdt_mod;
973xsdt_entries_num=(xsdt_mod->Length-sizeof(struct acpi_2_xsdt))/8;
974xsdt_entries=(uint64_t *)(xsdt_mod+1);
975for (i=0;i<xsdt_entries_num;i++)
976{
977char *table=(char *)((uint32_t)(xsdt_entries[i]));
978if (!table)
979continue;
980
981xsdt_entries[i-dropoffset]=xsdt_entries[i];
982
983if (drop_ssdt && tableSign(table, "SSDT"))
984{
985dropoffset++;
986continue;
987}
988if (tableSign(table, "DSDT"))
989{
990DBG("DSDT found\n");
991
992if (new_dsdt)
993xsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;
994
995DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
996
997continue;
998}
999if (tableSign(table, "FACP"))
1000{
1001struct acpi_2_fadt *fadt_mod;
1002fadt=(struct acpi_2_fadt *)(uint32_t)xsdt_entries[i];
1003
1004DBG("FADT found @%x,%x, Length %d\n",(uint32_t)(xsdt_entries[i]>>32),fadt,
1005fadt->Length);
1006
1007if (!fadt || (uint64_t)xsdt_entries[i] >= 0xffffffff || fadt->Length>0x10000)
1008{
1009verbose("FADT incorrect or after 4GB. Dropping XSDT\n");
1010goto drop_xsdt;
1011}
1012
1013fadt_mod = patch_fadt(fadt, new_dsdt);
1014xsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;
1015
1016DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
1017
1018// Generate _CST SSDT
1019if (generate_cstates && (new_ssdt[ssdt_count] = generate_cst_ssdt(fadt_mod)))
1020ssdt_count++;
1021
1022// Generating _PSS SSDT
1023if (generate_pstates && (new_ssdt[ssdt_count] = generate_pss_ssdt((void*)fadt_mod->DSDT)))
1024ssdt_count++;
1025
1026continue;
1027}
1028
1029DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
1030
1031}
1032
1033// Mozodojo: Insert additional SSDTs into XSDT
1034if(ssdt_count>0)
1035{
1036int j = xsdt_mod->Length;
1037bool add_new_ssdt = TRUE;
1038
1039xsdt_mod->Length+=8*ssdt_count-8*dropoffset;
1040
1041if (xsdt_mod->Length > j)
1042{
1043struct acpi_2_xsdt *xsdt_copy = (struct acpi_2_xsdt *)AllocateKernelMemory(xsdt_mod->Length);
1044
1045if (xsdt_copy)
1046{
1047memcpy(xsdt_copy, xsdt_mod, xsdt_mod->Length);
1048free(xsdt_mod); xsdt_mod = xsdt_copy;
1049rsdp_mod->XsdtAddress=(uint32_t)xsdt_mod;
1050xsdt_entries_num=(xsdt_mod->Length-sizeof(struct acpi_2_xsdt))/8;
1051xsdt_entries=(uint64_t *)(xsdt_mod+1);
1052}
1053else
1054{
1055verbose("RSDT: Couldn't allocate memory for additional SSDT tables!\n");
1056add_new_ssdt = FALSE;
1057}
1058}
1059
1060if (add_new_ssdt)
1061{
1062for (j=0; j<ssdt_count; j++)
1063xsdt_entries[i-dropoffset+j]=(uint32_t)new_ssdt[j];
1064
1065verbose("Added %d SSDT table(s) into XSDT\n", ssdt_count);
1066}
1067}
1068else
1069{
1070xsdt_mod->Length-=8*dropoffset;
1071}
1072
1073// Correct the checksum of XSDT
1074xsdt_mod->Checksum=0;
1075xsdt_mod->Checksum=256-checksum8(xsdt_mod,xsdt_mod->Length);
1076}
1077else
1078{
1079drop_xsdt:
1080
1081DBG("About to drop XSDT\n");
1082
1083/*FIXME: Now we just hope that if MacOS doesn't find XSDT it reverts to RSDT.
1084 * A Better strategy would be to generate
1085 */
1086
1087rsdp_mod->XsdtAddress=0xffffffffffffffffLL;
1088verbose("XSDT not found or XSDT incorrect\n");
1089}
1090}
1091
1092// Correct the checksum of RSDP
1093
1094DBG("RSDP: Original checksum %d, ", rsdp_mod->Checksum);
1095
1096rsdp_mod->Checksum=0;
1097rsdp_mod->Checksum=256-checksum8(rsdp_mod,20);
1098
1099DBG("New checksum %d\n", rsdp_mod->Checksum);
1100
1101if (version)
1102{
1103DBG("RSDP: Original extended checksum %d", rsdp_mod->ExtendedChecksum);
1104
1105rsdp_mod->ExtendedChecksum=0;
1106rsdp_mod->ExtendedChecksum=256-checksum8(rsdp_mod,rsdp_mod->Length);
1107
1108DBG("New extended checksum %d\n", rsdp_mod->ExtendedChecksum);
1109
1110}
1111
1112//verbose("Patched ACPI version %d DSDT\n", version+1);
1113if (version)
1114{
1115/* XXX aserebln why uint32 cast if pointer is uint64 ? */
1116acpi20_p = (uint32_t)rsdp_mod;
1117addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
1118}
1119else
1120{
1121/* XXX aserebln why uint32 cast if pointer is uint64 ? */
1122acpi10_p = (uint32_t)rsdp_mod;
1123addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
1124}
1125}
1126#if DEBUG_ACPI
1127printf("Press a key to continue... (DEBUG_ACPI)\n");
1128getc();
1129#endif
1130return 1;
1131}
1132

Archive Download this file

Revision: 192