Chameleon Applications

Chameleon Applications Svn Source Tree

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

Source at commit 214 created 13 years 5 months ago.
By ifabio, update to chameleon trunk 630, and now the pakage folder is the same as blackosx branch, also add Icon "building" into buildpkg script, and add mint theme info into the English localizable.strings.
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;
93char dirSpec[512] = "";
94
95// Try finding 'filename' in the usual places
96// Start searching any potential location for ACPI Table
97sprintf(dirSpec, "%s", filename);
98fd = open(dirSpec, 0);
99if (fd < 0)
100{
101sprintf(dirSpec, "/Extra/%s", filename);
102fd = open(dirSpec, 0);
103if (fd < 0)
104{
105sprintf(dirSpec, "bt(0,0)/Extra/%s", filename);
106fd = open(dirSpec, 0);
107}
108}
109
110if (fd < 0)
111{
112// NOT FOUND:
113verbose("ACPI table not found: %s\n", filename);
114*dirSpec = '\0';
115}
116
117if (outDirspec) *outDirspec = dirSpec;
118return fd;
119}
120
121
122void *loadACPITable (const char * filename)
123{
124void *tableAddr;
125const char * dirspec=NULL;
126
127int fd = search_and_get_acpi_fd(filename, &dirspec);
128
129if (fd>=0)
130{
131tableAddr=(void*)AllocateKernelMemory(file_size (fd));
132if (tableAddr)
133{
134if (read (fd, tableAddr, file_size (fd))!=file_size (fd))
135{
136printf("Couldn't read table %s\n",dirspec);
137free (tableAddr);
138close (fd);
139return NULL;
140}
141
142DBG("Table %s read and stored at: %x\n", dirspec, tableAddr);
143close (fd);
144return tableAddr;
145}
146close (fd);
147printf("Couldn't allocate memory for table \n", dirspec);
148}
149//printf("Couldn't find table %s\n", filename);
150return NULL;
151}
152
153uint8_tacpi_cpu_count = 0;
154char* acpi_cpu_name[32];
155
156void get_acpi_cpu_names(unsigned char* dsdt, uint32_t length)
157{
158uint32_t i;
159
160for (i=0; i<length-7; i++)
161{
162if (dsdt[i] == 0x5B && dsdt[i+1] == 0x83) // ProcessorOP
163{
164uint32_t offset = i + 3 + (dsdt[i+2] >> 6);
165
166bool add_name = true;
167
168uint8_t j;
169
170for (j=0; j<4; j++)
171{
172char c = dsdt[offset+j];
173
174if (!aml_isvalidchar(c))
175{
176add_name = false;
177verbose("Invalid character found in ProcessorOP 0x%x!\n", c);
178break;
179}
180}
181
182if (add_name)
183{
184acpi_cpu_name[acpi_cpu_count] = malloc(4);
185memcpy(acpi_cpu_name[acpi_cpu_count], dsdt+offset, 4);
186i = offset + 5;
187
188verbose("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]);
189
190if (++acpi_cpu_count == 32) return;
191}
192}
193}
194}
195
196struct acpi_2_ssdt *generate_cst_ssdt(struct acpi_2_fadt* fadt)
197{
198char ssdt_header[] =
199{
2000x53, 0x53, 0x44, 0x54, 0xE7, 0x00, 0x00, 0x00, /* SSDT.... */
2010x01, 0x17, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x41, /* ..PmRefA */
2020x43, 0x70, 0x75, 0x43, 0x73, 0x74, 0x00, 0x00, /* CpuCst.. */
2030x00, 0x10, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* ....INTL */
2040x31, 0x03, 0x10, 0x20 /* 1.._*/
205};
206
207char cstate_resource_template[] =
208{
2090x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00, 0x7F,
2100x01, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
2110x00, 0x00, 0x00, 0x79, 0x00
212};
213
214if (Platform.CPU.Vendor != 0x756E6547) {
215verbose ("Not an Intel platform: C-States will not be generated !!!\n");
216return NULL;
217}
218
219if (fadt == NULL) {
220verbose ("FACP not exists: C-States will not be generated !!!\n");
221return NULL;
222}
223
224struct acpi_2_dsdt* dsdt = (void*)fadt->DSDT;
225
226if (dsdt == NULL) {
227verbose ("DSDT not found: C-States will not be generated !!!\n");
228return NULL;
229}
230
231if (acpi_cpu_count == 0)
232get_acpi_cpu_names((void*)dsdt, dsdt->Length);
233
234if (acpi_cpu_count > 0)
235{
236bool c2_enabled = false;
237bool c3_enabled = false;
238bool c4_enabled = false;
239
240getBoolForKey(kEnableC2States, &c2_enabled, &bootInfo->bootConfig);
241getBoolForKey(kEnableC3States, &c3_enabled, &bootInfo->bootConfig);
242getBoolForKey(kEnableC4States, &c4_enabled, &bootInfo->bootConfig);
243
244c2_enabled = c2_enabled | (fadt->C2_Latency < 100);
245c3_enabled = c3_enabled | (fadt->C3_Latency < 1000);
246
247unsigned char cstates_count = 1 + (c2_enabled ? 1 : 0) + (c3_enabled ? 1 : 0);
248
249struct aml_chunk* root = aml_create_node(NULL);
250aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header
251struct aml_chunk* scop = aml_add_scope(root, "\\_PR_");
252struct aml_chunk* name = aml_add_name(scop, "CST_");
253struct aml_chunk* pack = aml_add_package(name);
254aml_add_byte(pack, cstates_count);
255
256struct aml_chunk* tmpl = aml_add_package(pack);
257cstate_resource_template[11] = 0x00; // C1
258aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
259aml_add_byte(tmpl, 0x01); // C1
260aml_add_byte(tmpl, 0x01); // Latency
261aml_add_word(tmpl, 0x03e8); // Power
262
263// C2
264if (c2_enabled)
265{
266tmpl = aml_add_package(pack);
267cstate_resource_template[11] = 0x10; // C2
268aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
269aml_add_byte(tmpl, 0x02); // C2
270aml_add_byte(tmpl, fadt->C2_Latency);
271aml_add_word(tmpl, 0x01f4); // Power
272}
273// C4
274if (c4_enabled)
275{
276tmpl = aml_add_package(pack);
277cstate_resource_template[11] = 0x30; // C4
278aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
279aml_add_byte(tmpl, 0x04); // C4
280aml_add_word(tmpl, fadt->C3_Latency / 2); // TODO: right latency for C4
281aml_add_byte(tmpl, 0xfa); // Power
282}
283else
284// C3
285if (c3_enabled)
286{
287tmpl = aml_add_package(pack);
288cstate_resource_template[11] = 0x20; // C3
289aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
290aml_add_byte(tmpl, 0x03); // C3
291aml_add_word(tmpl, fadt->C3_Latency);
292aml_add_word(tmpl, 0x015e); // Power
293}
294
295
296// Aliaces
297int i;
298for (i = 0; i < acpi_cpu_count; i++)
299{
300char name[9];
301sprintf(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]);
302
303scop = aml_add_scope(root, name);
304aml_add_alias(scop, "CST_", "_CST");
305}
306
307aml_calculate_size(root);
308
309struct acpi_2_ssdt *ssdt = (struct acpi_2_ssdt *)AllocateKernelMemory(root->Size);
310
311aml_write_node(root, (void*)ssdt, 0);
312
313ssdt->Length = root->Size;
314ssdt->Checksum = 0;
315ssdt->Checksum = 256 - checksum8(ssdt, ssdt->Length);
316
317aml_destroy_node(root);
318
319//dumpPhysAddr("C-States SSDT content: ", ssdt, ssdt->Length);
320
321verbose ("SSDT with CPU C-States generated successfully\n");
322
323return ssdt;
324}
325else
326{
327verbose ("ACPI CPUs not found: C-States not generated !!!\n");
328}
329
330return NULL;
331}
332
333struct acpi_2_ssdt *generate_pss_ssdt(struct acpi_2_dsdt* dsdt)
334{
335char ssdt_header[] =
336{
3370x53, 0x53, 0x44, 0x54, 0x7E, 0x00, 0x00, 0x00, /* SSDT.... */
3380x01, 0x6A, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x00, /* ..PmRef. */
3390x43, 0x70, 0x75, 0x50, 0x6D, 0x00, 0x00, 0x00, /* CpuPm... */
3400x00, 0x30, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* .0..INTL */
3410x31, 0x03, 0x10, 0x20,/* 1.._*/
342};
343
344if (Platform.CPU.Vendor != 0x756E6547) {
345verbose ("Not an Intel platform: P-States will not be generated !!!\n");
346return NULL;
347}
348
349if (!(Platform.CPU.Features & CPU_FEATURE_MSR)) {
350verbose ("Unsupported CPU: P-States will not be generated !!!\n");
351return NULL;
352}
353
354if (acpi_cpu_count == 0)
355get_acpi_cpu_names((void*)dsdt, dsdt->Length);
356
357if (acpi_cpu_count > 0)
358{
359struct p_state initial, maximum, minimum, p_states[32];
360uint8_t p_states_count = 0;
361
362// Retrieving P-States, ported from code by superhai (c)
363switch (Platform.CPU.Family) {
364case 0x06:
365{
366switch (Platform.CPU.Model)
367{
368case 0x0D: // ?
369case CPU_MODEL_YONAH: // Yonah
370case CPU_MODEL_MEROM: // Merom
371case CPU_MODEL_PENRYN: // Penryn
372case CPU_MODEL_ATOM: // Intel Atom (45nm)
373{
374bool cpu_dynamic_fsb = false;
375
376if (rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 27))
377{
378wrmsr64(MSR_IA32_EXT_CONFIG, (rdmsr64(MSR_IA32_EXT_CONFIG) | (1 << 28)));
379delay(1);
380cpu_dynamic_fsb = rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 28);
381}
382
383bool cpu_noninteger_bus_ratio = (rdmsr64(MSR_IA32_PERF_STATUS) & (1ULL << 46));
384
385initial.Control = rdmsr64(MSR_IA32_PERF_STATUS);
386
387maximum.Control = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 32) & 0x1F3F) | (0x4000 * cpu_noninteger_bus_ratio);
388maximum.CID = ((maximum.FID & 0x1F) << 1) | cpu_noninteger_bus_ratio;
389
390minimum.FID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 24) & 0x1F) | (0x80 * cpu_dynamic_fsb);
391minimum.VID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 48) & 0x3F);
392
393if (minimum.FID == 0)
394{
395uint64_t msr;
396uint8_t i;
397// Probe for lowest fid
398for (i = maximum.FID; i >= 0x6; i--)
399{
400msr = rdmsr64(MSR_IA32_PERF_CONTROL);
401wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (i << 8) | minimum.VID);
402intel_waitforsts();
403minimum.FID = (rdmsr64(MSR_IA32_PERF_STATUS) >> 8) & 0x1F;
404delay(1);
405}
406
407msr = rdmsr64(MSR_IA32_PERF_CONTROL);
408wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
409intel_waitforsts();
410}
411
412if (minimum.VID == maximum.VID)
413{
414uint64_t msr;
415uint8_t i;
416// Probe for lowest vid
417for (i = maximum.VID; i > 0xA; i--)
418{
419msr = rdmsr64(MSR_IA32_PERF_CONTROL);
420wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (minimum.FID << 8) | i);
421intel_waitforsts();
422minimum.VID = rdmsr64(MSR_IA32_PERF_STATUS) & 0x3F;
423delay(1);
424}
425
426msr = rdmsr64(MSR_IA32_PERF_CONTROL);
427wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
428intel_waitforsts();
429}
430
431minimum.CID = ((minimum.FID & 0x1F) << 1) >> cpu_dynamic_fsb;
432
433// Sanity check
434if (maximum.CID < minimum.CID)
435{
436DBG("Insane FID values!");
437p_states_count = 0;
438}
439else
440{
441// Finalize P-States
442// Find how many P-States machine supports
443p_states_count = maximum.CID - minimum.CID + 1;
444
445if (p_states_count > 32)
446p_states_count = 32;
447
448uint8_t vidstep;
449uint8_t i = 0, u, invalid = 0;
450
451vidstep = ((maximum.VID << 2) - (minimum.VID << 2)) / (p_states_count - 1);
452
453for (u = 0; u < p_states_count; u++)
454{
455i = u - invalid;
456
457p_states[i].CID = maximum.CID - u;
458p_states[i].FID = (p_states[i].CID >> 1);
459
460if (p_states[i].FID < 0x6)
461{
462if (cpu_dynamic_fsb)
463p_states[i].FID = (p_states[i].FID << 1) | 0x80;
464}
465else if (cpu_noninteger_bus_ratio)
466{
467p_states[i].FID = p_states[i].FID | (0x40 * (p_states[i].CID & 0x1));
468}
469
470if (i && p_states[i].FID == p_states[i-1].FID)
471invalid++;
472
473p_states[i].VID = ((maximum.VID << 2) - (vidstep * u)) >> 2;
474
475uint32_t multiplier = p_states[i].FID & 0x1f;// = 0x08
476bool half = p_states[i].FID & 0x40;// = 0x01
477bool dfsb = p_states[i].FID & 0x80;// = 0x00
478uint32_t fsb = Platform.CPU.FSBFrequency / 1000000; // = 400
479uint32_t halffsb = (fsb + 1) >> 1;// = 200
480uint32_t frequency = (multiplier * fsb);// = 3200
481
482p_states[i].Frequency = (frequency + (half * halffsb)) >> dfsb;// = 3200 + 200 = 3400
483}
484
485p_states_count -= invalid;
486}
487
488break;
489}
490case CPU_MODEL_FIELDS:
491case CPU_MODEL_DALES:
492case CPU_MODEL_DALES_32NM:
493case CPU_MODEL_NEHALEM:
494case CPU_MODEL_NEHALEM_EX:
495case CPU_MODEL_WESTMERE:
496case CPU_MODEL_WESTMERE_EX:
497{
498maximum.Control = rdmsr64(MSR_IA32_PERF_STATUS) & 0xff; // Seems it always contains maximum multiplier value (with turbo, that's we need)...
499
500/*uint8_t i;
501// Probe for lowest fid
502for (i = maximum.Control; i >= 0x7; i--)
503{
504wrmsr64(MSR_IA32_PERF_CONTROL, i);
505delay(1);
506minimum.Control = rdmsr64(MSR_IA32_PERF_STATUS);
507delay(1);
508}*/
509
510if (!minimum.Control)
511{
512// fix me: dirty method to get lowest multiplier... Hardcoded value!
513if (strstr(Platform.CPU.BrandString, "Core(TM) i7"))
514minimum.Control = 0x07;
515else
516minimum.Control = 0x09;
517}
518
519verbose("P-States: min 0x%x, max 0x%x\n", minimum.Control, maximum.Control);
520
521// Sanity check
522if (maximum.Control < minimum.Control)
523{
524DBG("Insane control values!");
525p_states_count = 0;
526}
527else
528{
529uint8_t i;
530p_states_count = 0;
531
532for (i = maximum.Control; i >= minimum.Control; i--)
533{
534p_states[p_states_count].Control = i;
535p_states[p_states_count].CID = p_states[p_states_count].Control << 1;
536p_states[p_states_count].Frequency = (Platform.CPU.FSBFrequency / 1000000) * i;
537p_states_count++;
538}
539}
540
541break;
542}
543default:
544verbose ("Unsupported CPU: P-States not generated !!!\n");
545break;
546}
547}
548}
549
550// Generating SSDT
551if (p_states_count > 0)
552{
553int i;
554
555struct aml_chunk* root = aml_create_node(NULL);
556aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header
557struct aml_chunk* scop = aml_add_scope(root, "\\_PR_");
558struct aml_chunk* name = aml_add_name(scop, "PSS_");
559struct aml_chunk* pack = aml_add_package(name);
560
561for (i = 0; i < p_states_count; i++)
562{
563struct aml_chunk* pstt = aml_add_package(pack);
564
565aml_add_dword(pstt, p_states[i].Frequency);
566aml_add_dword(pstt, 0x00000000); // Power
567aml_add_dword(pstt, 0x0000000A); // Latency
568aml_add_dword(pstt, 0x0000000A); // Latency
569aml_add_dword(pstt, p_states[i].Control);
570aml_add_dword(pstt, i+1); // Status
571}
572
573// Add aliaces
574for (i = 0; i < acpi_cpu_count; i++)
575{
576char name[9];
577sprintf(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]);
578
579scop = aml_add_scope(root, name);
580aml_add_alias(scop, "PSS_", "_PSS");
581}
582
583aml_calculate_size(root);
584
585struct acpi_2_ssdt *ssdt = (struct acpi_2_ssdt *)AllocateKernelMemory(root->Size);
586
587aml_write_node(root, (void*)ssdt, 0);
588
589ssdt->Length = root->Size;
590ssdt->Checksum = 0;
591ssdt->Checksum = 256 - checksum8(ssdt, ssdt->Length);
592
593aml_destroy_node(root);
594
595//dumpPhysAddr("P-States SSDT content: ", ssdt, ssdt->Length);
596
597verbose ("SSDT with CPU P-States generated successfully\n");
598
599return ssdt;
600}
601}
602else
603{
604verbose ("ACPI CPUs not found: P-States not generated !!!\n");
605}
606
607return NULL;
608}
609
610struct acpi_2_fadt *patch_fadt(struct acpi_2_fadt *fadt, struct acpi_2_dsdt *new_dsdt)
611{
612extern void setupSystemType();
613
614struct acpi_2_fadt *fadt_mod;
615bool fadt_rev2_needed = false;
616bool fix_restart;
617const char * value;
618
619// Restart Fix
620if (Platform.CPU.Vendor == 0x756E6547) {/* Intel */
621fix_restart = true;
622getBoolForKey(kRestartFix, &fix_restart, &bootInfo->bootConfig);
623} else {
624verbose ("Not an Intel platform: Restart Fix not applied !!!\n");
625fix_restart = false;
626}
627
628if (fix_restart) fadt_rev2_needed = true;
629
630// Allocate new fadt table
631if (fadt->Length < 0x84 && fadt_rev2_needed)
632{
633fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(0x84);
634memcpy(fadt_mod, fadt, fadt->Length);
635fadt_mod->Length = 0x84;
636fadt_mod->Revision = 0x02; // FADT rev 2 (ACPI 1.0B MS extensions)
637}
638else
639{
640fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(fadt->Length);
641memcpy(fadt_mod, fadt, fadt->Length);
642}
643// Determine system type / PM_Model
644if ( (value=getStringForKey(kSystemType, &bootInfo->bootConfig))!=NULL)
645{
646if (Platform.Type > 6)
647{
648if(fadt_mod->PM_Profile<=6)
649Platform.Type = fadt_mod->PM_Profile; // get the fadt if correct
650else
651Platform.Type = 1;/* Set a fixed value (Desktop) */
652verbose("Error: system-type must be 0..6. Defaulting to %d !\n", Platform.Type);
653}
654else
655Platform.Type = (unsigned char) strtoul(value, NULL, 10);
656}
657// Set PM_Profile from System-type if only user wanted this value to be forced
658if (fadt_mod->PM_Profile != Platform.Type)
659{
660 if (value)
661{ // user has overriden the SystemType so take care of it in FACP
662verbose("FADT: changing PM_Profile from 0x%02x to 0x%02x\n", fadt_mod->PM_Profile, Platform.Type);
663fadt_mod->PM_Profile = Platform.Type;
664 }
665 else
666 { // PM_Profile has a different value and no override has been set, so reflect the user value to ioregs
667Platform.Type = fadt_mod->PM_Profile <= 6 ? fadt_mod->PM_Profile : 1;
668 }
669}
670// We now have to write the systemm-type in ioregs: we cannot do it before in setupDeviceTree()
671// because we need to take care of facp original content, if it is correct.
672setupSystemType();
673
674// Patch FADT to fix restart
675if (fix_restart)
676{
677fadt_mod->Flags|= 0x400;
678fadt_mod->Reset_SpaceID= 0x01; // System I/O
679fadt_mod->Reset_BitWidth= 0x08; // 1 byte
680fadt_mod->Reset_BitOffset= 0x00; // Offset 0
681fadt_mod->Reset_AccessWidth= 0x01; // Byte access
682fadt_mod->Reset_Address= 0x0cf9; // Address of the register
683fadt_mod->Reset_Value= 0x06; // Value to write to reset the system
684verbose("FADT: Restart Fix applied!\n");
685}
686
687// Patch DSDT Address if we have loaded DSDT.aml
688if(new_dsdt)
689{
690DBG("DSDT: Old @%x,%x, ",fadt_mod->DSDT,fadt_mod->X_DSDT);
691
692fadt_mod->DSDT=(uint32_t)new_dsdt;
693if ((uint32_t)(&(fadt_mod->X_DSDT))-(uint32_t)fadt_mod+8<=fadt_mod->Length)
694fadt_mod->X_DSDT=(uint32_t)new_dsdt;
695
696DBG("New @%x,%x\n",fadt_mod->DSDT,fadt_mod->X_DSDT);
697
698verbose("FADT: Using custom DSDT!\n");
699}
700
701// Correct the checksum
702fadt_mod->Checksum=0;
703fadt_mod->Checksum=256-checksum8(fadt_mod,fadt_mod->Length);
704
705return fadt_mod;
706}
707
708/* Setup ACPI without replacing DSDT. */
709int setupAcpiNoMod()
710{
711//addConfigurationTable(&gEfiAcpiTableGuid, getAddressOfAcpiTable(), "ACPI");
712//addConfigurationTable(&gEfiAcpi20TableGuid, getAddressOfAcpi20Table(), "ACPI_20");
713/* XXX aserebln why uint32 cast if pointer is uint64 ? */
714acpi10_p = (uint32_t)getAddressOfAcpiTable();
715acpi20_p = (uint32_t)getAddressOfAcpi20Table();
716addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
717if(acpi20_p) addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
718return 1;
719}
720
721/* Setup ACPI. Replace DSDT if DSDT.aml is found */
722int setupAcpi(void)
723{
724int version;
725void *new_dsdt;
726
727const char *filename;
728char dirSpec[128];
729int len = 0;
730
731// Try using the file specified with the DSDT option
732if (getValueForKey(kDSDT, &filename, &len, &bootInfo->bootConfig))
733{
734sprintf(dirSpec, filename);
735}
736else
737{
738sprintf(dirSpec, "DSDT.aml");
739}
740
741// Load replacement DSDT
742new_dsdt = loadACPITable(dirSpec);
743// Mozodojo: going to patch FACP and load SSDT's even if DSDT.aml is not present
744/*if (!new_dsdt)
745 {
746 return setupAcpiNoMod();
747 }*/
748
749// Mozodojo: Load additional SSDTs
750struct acpi_2_ssdt *new_ssdt[32]; // 30 + 2 additional tables for pss & cst
751int ssdt_count=0;
752
753// SSDT Options
754bool drop_ssdt=false, generate_pstates=false, generate_cstates=false;
755
756getBoolForKey(kDropSSDT, &drop_ssdt, &bootInfo->bootConfig);
757getBoolForKey(kGeneratePStates, &generate_pstates, &bootInfo->bootConfig);
758getBoolForKey(kGenerateCStates, &generate_cstates, &bootInfo->bootConfig);
759
760{
761int i;
762
763for (i=0; i<30; i++)
764{
765char filename[512];
766
767sprintf(filename, i>0?"SSDT-%d.aml":"SSDT.aml", i);
768
769if(new_ssdt[ssdt_count] = loadACPITable(filename))
770{
771ssdt_count++;
772}
773else
774{
775break;
776}
777}
778}
779
780// Do the same procedure for both versions of ACPI
781for (version=0; version<2; version++) {
782struct acpi_2_rsdp *rsdp, *rsdp_mod;
783struct acpi_2_rsdt *rsdt, *rsdt_mod;
784int rsdplength;
785
786// Find original rsdp
787rsdp=(struct acpi_2_rsdp *)(version?getAddressOfAcpi20Table():getAddressOfAcpiTable());
788if (!rsdp)
789{
790DBG("No ACPI version %d found. Ignoring\n", version+1);
791if (version)
792addConfigurationTable(&gEfiAcpi20TableGuid, NULL, "ACPI_20");
793else
794addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI");
795continue;
796}
797rsdplength=version?rsdp->Length:20;
798
799DBG("RSDP version %d found @%x. Length=%d\n",version+1,rsdp,rsdplength);
800
801/* FIXME: no check that memory allocation succeeded
802 * Copy and patch RSDP,RSDT, XSDT and FADT
803 * For more info see ACPI Specification pages 110 and following
804 */
805
806rsdp_mod=(struct acpi_2_rsdp *) AllocateKernelMemory(rsdplength);
807memcpy(rsdp_mod, rsdp, rsdplength);
808rsdt=(struct acpi_2_rsdt *)(rsdp->RsdtAddress);
809
810DBG("RSDT @%x, Length %d\n",rsdt, rsdt->Length);
811
812if (rsdt && (uint32_t)rsdt !=0xffffffff && rsdt->Length<0x10000)
813{
814uint32_t *rsdt_entries;
815int rsdt_entries_num;
816int dropoffset=0, i;
817
818// mozo: using malloc cos I didn't found how to free already allocated kernel memory
819rsdt_mod=(struct acpi_2_rsdt *)malloc(rsdt->Length);
820memcpy (rsdt_mod, rsdt, rsdt->Length);
821rsdp_mod->RsdtAddress=(uint32_t)rsdt_mod;
822rsdt_entries_num=(rsdt_mod->Length-sizeof(struct acpi_2_rsdt))/4;
823rsdt_entries=(uint32_t *)(rsdt_mod+1);
824for (i=0;i<rsdt_entries_num;i++)
825{
826char *table=(char *)(rsdt_entries[i]);
827if (!table)
828continue;
829
830DBG("TABLE %c%c%c%c,",table[0],table[1],table[2],table[3]);
831
832rsdt_entries[i-dropoffset]=rsdt_entries[i];
833
834if (drop_ssdt && tableSign(table, "SSDT"))
835{
836dropoffset++;
837continue;
838}
839if (tableSign(table, "DSDT"))
840{
841DBG("DSDT found\n");
842
843if(new_dsdt)
844rsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;
845
846continue;
847}
848if (tableSign(table, "FACP"))
849{
850struct acpi_2_fadt *fadt, *fadt_mod;
851fadt=(struct acpi_2_fadt *)rsdt_entries[i];
852
853DBG("FADT found @%x, Length %d\n",fadt, fadt->Length);
854
855if (!fadt || (uint32_t)fadt == 0xffffffff || fadt->Length>0x10000)
856{
857printf("FADT incorrect. Not modified\n");
858continue;
859}
860
861fadt_mod = patch_fadt(fadt, new_dsdt);
862rsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;
863
864// Generate _CST SSDT
865if (generate_cstates && (new_ssdt[ssdt_count] = generate_cst_ssdt(fadt_mod)))
866{
867generate_cstates = false; // Generate SSDT only once!
868ssdt_count++;
869}
870
871// Generating _PSS SSDT
872if (generate_pstates && (new_ssdt[ssdt_count] = generate_pss_ssdt((void*)fadt_mod->DSDT)))
873{
874generate_pstates = false; // Generate SSDT only once!
875ssdt_count++;
876}
877
878continue;
879}
880}
881DBG("\n");
882
883// Allocate rsdt in Kernel memory area
884rsdt_mod->Length += 4*ssdt_count - 4*dropoffset;
885struct acpi_2_rsdt *rsdt_copy = (struct acpi_2_rsdt *)AllocateKernelMemory(rsdt_mod->Length);
886memcpy (rsdt_copy, rsdt_mod, rsdt_mod->Length);
887free(rsdt_mod); rsdt_mod = rsdt_copy;
888rsdp_mod->RsdtAddress=(uint32_t)rsdt_mod;
889rsdt_entries_num=(rsdt_mod->Length-sizeof(struct acpi_2_rsdt))/4;
890rsdt_entries=(uint32_t *)(rsdt_mod+1);
891
892// Mozodojo: Insert additional SSDTs into RSDT
893if(ssdt_count>0)
894{
895int j;
896
897for (j=0; j<ssdt_count; j++)
898rsdt_entries[i-dropoffset+j]=(uint32_t)new_ssdt[j];
899
900verbose("RSDT: Added %d SSDT table(s)\n", ssdt_count);
901}
902
903// Correct the checksum of RSDT
904DBG("RSDT: Original checksum %d, ", rsdt_mod->Checksum);
905
906rsdt_mod->Checksum=0;
907rsdt_mod->Checksum=256-checksum8(rsdt_mod,rsdt_mod->Length);
908
909DBG("New checksum %d at %x\n", rsdt_mod->Checksum,rsdt_mod);
910}
911else
912{
913rsdp_mod->RsdtAddress=0;
914printf("RSDT not found or RSDT incorrect\n");
915}
916
917if (version)
918{
919struct acpi_2_xsdt *xsdt, *xsdt_mod;
920
921// FIXME: handle 64-bit address correctly
922
923xsdt=(struct acpi_2_xsdt*) ((uint32_t)rsdp->XsdtAddress);
924DBG("XSDT @%x;%x, Length=%d\n", (uint32_t)(rsdp->XsdtAddress>>32),(uint32_t)rsdp->XsdtAddress,
925xsdt->Length);
926if (xsdt && (uint64_t)rsdp->XsdtAddress<0xffffffff && xsdt->Length<0x10000)
927{
928uint64_t *xsdt_entries;
929int xsdt_entries_num, i;
930int dropoffset=0;
931
932// mozo: using malloc cos I didn't found how to free already allocated kernel memory
933xsdt_mod=(struct acpi_2_xsdt*)malloc(xsdt->Length);
934memcpy(xsdt_mod, xsdt, xsdt->Length);
935rsdp_mod->XsdtAddress=(uint32_t)xsdt_mod;
936xsdt_entries_num=(xsdt_mod->Length-sizeof(struct acpi_2_xsdt))/8;
937xsdt_entries=(uint64_t *)(xsdt_mod+1);
938for (i=0;i<xsdt_entries_num;i++)
939{
940char *table=(char *)((uint32_t)(xsdt_entries[i]));
941if (!table)
942continue;
943
944xsdt_entries[i-dropoffset]=xsdt_entries[i];
945
946if (drop_ssdt && tableSign(table, "SSDT"))
947{
948dropoffset++;
949continue;
950}
951if (tableSign(table, "DSDT"))
952{
953DBG("DSDT found\n");
954
955if (new_dsdt)
956xsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;
957
958DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
959
960continue;
961}
962if (tableSign(table, "FACP"))
963{
964struct acpi_2_fadt *fadt, *fadt_mod;
965fadt=(struct acpi_2_fadt *)(uint32_t)xsdt_entries[i];
966
967DBG("FADT found @%x,%x, Length %d\n",(uint32_t)(xsdt_entries[i]>>32),fadt,
968fadt->Length);
969
970if (!fadt || (uint64_t)xsdt_entries[i] >= 0xffffffff || fadt->Length>0x10000)
971{
972verbose("FADT incorrect or after 4GB. Dropping XSDT\n");
973goto drop_xsdt;
974}
975
976fadt_mod = patch_fadt(fadt, new_dsdt);
977xsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;
978
979DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
980
981// Generate _CST SSDT
982if (generate_cstates && (new_ssdt[ssdt_count] = generate_cst_ssdt(fadt_mod)))
983{
984generate_cstates = false; // Generate SSDT only once!
985ssdt_count++;
986}
987
988// Generating _PSS SSDT
989if (generate_pstates && (new_ssdt[ssdt_count] = generate_pss_ssdt((void*)fadt_mod->DSDT)))
990{
991generate_pstates = false; // Generate SSDT only once!
992ssdt_count++;
993}
994
995continue;
996}
997
998DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
999
1000}
1001
1002// Allocate xsdt in Kernel memory area
1003xsdt_mod->Length += 8*ssdt_count - 8*dropoffset;
1004struct acpi_2_xsdt *xsdt_copy = (struct acpi_2_xsdt *)AllocateKernelMemory(xsdt_mod->Length);
1005memcpy(xsdt_copy, xsdt_mod, xsdt_mod->Length);
1006free(xsdt_mod); xsdt_mod = xsdt_copy;
1007rsdp_mod->XsdtAddress=(uint32_t)xsdt_mod;
1008xsdt_entries_num=(xsdt_mod->Length-sizeof(struct acpi_2_xsdt))/8;
1009xsdt_entries=(uint64_t *)(xsdt_mod+1);
1010
1011// Mozodojo: Insert additional SSDTs into XSDT
1012if(ssdt_count>0)
1013{
1014int j;
1015
1016for (j=0; j<ssdt_count; j++)
1017xsdt_entries[i-dropoffset+j]=(uint32_t)new_ssdt[j];
1018
1019verbose("Added %d SSDT table(s) into XSDT\n", ssdt_count);
1020}
1021
1022// Correct the checksum of XSDT
1023xsdt_mod->Checksum=0;
1024xsdt_mod->Checksum=256-checksum8(xsdt_mod,xsdt_mod->Length);
1025}
1026else
1027{
1028drop_xsdt:
1029
1030DBG("About to drop XSDT\n");
1031
1032/*FIXME: Now we just hope that if MacOS doesn't find XSDT it reverts to RSDT.
1033 * A Better strategy would be to generate
1034 */
1035
1036rsdp_mod->XsdtAddress=0xffffffffffffffffLL;
1037verbose("XSDT not found or XSDT incorrect\n");
1038}
1039}
1040
1041// Correct the checksum of RSDP
1042
1043DBG("RSDP: Original checksum %d, ", rsdp_mod->Checksum);
1044
1045rsdp_mod->Checksum=0;
1046rsdp_mod->Checksum=256-checksum8(rsdp_mod,20);
1047
1048DBG("New checksum %d\n", rsdp_mod->Checksum);
1049
1050if (version)
1051{
1052DBG("RSDP: Original extended checksum %d", rsdp_mod->ExtendedChecksum);
1053
1054rsdp_mod->ExtendedChecksum=0;
1055rsdp_mod->ExtendedChecksum=256-checksum8(rsdp_mod,rsdp_mod->Length);
1056
1057DBG("New extended checksum %d\n", rsdp_mod->ExtendedChecksum);
1058
1059}
1060
1061//verbose("Patched ACPI version %d DSDT\n", version+1);
1062if (version)
1063{
1064/* XXX aserebln why uint32 cast if pointer is uint64 ? */
1065acpi20_p = (uint32_t)rsdp_mod;
1066addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
1067}
1068else
1069{
1070/* XXX aserebln why uint32 cast if pointer is uint64 ? */
1071acpi10_p = (uint32_t)rsdp_mod;
1072addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
1073}
1074}
1075#if DEBUG_ACPI
1076printf("Press a key to continue... (DEBUG_ACPI)\n");
1077getc();
1078#endif
1079return 1;
1080}
1081

Archive Download this file

Revision: 214