Chameleon Applications

Chameleon Applications Svn Source Tree

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

Source at commit 307 created 12 years 11 months ago.
By ifabio, merge changes from trunk (929). Also merge the module changes from Azimutz branche (fix compile error) Also edited the info.plist into AHCIPortInjector.kext: http://forum.voodooprojects.org/index.php/topic,1170.0.html
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:
497case CPU_MODEL_SANDY:
498case CPU_MODEL_SANDY_XEON:
499{
500maximum.Control = rdmsr64(MSR_IA32_PERF_STATUS) & 0xff; // Seems it always contains maximum multiplier value (with turbo, that's we need)...
501minimum.Control = (rdmsr64(MSR_PLATFORM_INFO) >> 40) & 0xff;
502
503verbose("P-States: min 0x%x, max 0x%x\n", minimum.Control, maximum.Control);
504
505// Sanity check
506if (maximum.Control < minimum.Control)
507{
508DBG("Insane control values!");
509p_states_count = 0;
510}
511else
512{
513uint8_t i;
514p_states_count = 0;
515
516for (i = maximum.Control; i >= minimum.Control; i--)
517{
518p_states[p_states_count].Control = i;
519p_states[p_states_count].CID = p_states[p_states_count].Control << 1;
520p_states[p_states_count].Frequency = (Platform.CPU.FSBFrequency / 1000000) * i;
521p_states_count++;
522}
523}
524
525break;
526}
527default:
528verbose ("Unsupported CPU: P-States not generated !!!\n");
529break;
530}
531}
532}
533
534// Generating SSDT
535if (p_states_count > 0)
536{
537int i;
538
539struct aml_chunk* root = aml_create_node(NULL);
540aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header
541struct aml_chunk* scop = aml_add_scope(root, "\\_PR_");
542struct aml_chunk* name = aml_add_name(scop, "PSS_");
543struct aml_chunk* pack = aml_add_package(name);
544
545for (i = 0; i < p_states_count; i++)
546{
547struct aml_chunk* pstt = aml_add_package(pack);
548
549aml_add_dword(pstt, p_states[i].Frequency);
550aml_add_dword(pstt, 0x00000000); // Power
551aml_add_dword(pstt, 0x0000000A); // Latency
552aml_add_dword(pstt, 0x0000000A); // Latency
553aml_add_dword(pstt, p_states[i].Control);
554aml_add_dword(pstt, i+1); // Status
555}
556
557// Add aliaces
558for (i = 0; i < acpi_cpu_count; i++)
559{
560char name[9];
561sprintf(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]);
562
563scop = aml_add_scope(root, name);
564aml_add_alias(scop, "PSS_", "_PSS");
565}
566
567aml_calculate_size(root);
568
569struct acpi_2_ssdt *ssdt = (struct acpi_2_ssdt *)AllocateKernelMemory(root->Size);
570
571aml_write_node(root, (void*)ssdt, 0);
572
573ssdt->Length = root->Size;
574ssdt->Checksum = 0;
575ssdt->Checksum = 256 - checksum8(ssdt, ssdt->Length);
576
577aml_destroy_node(root);
578
579//dumpPhysAddr("P-States SSDT content: ", ssdt, ssdt->Length);
580
581verbose ("SSDT with CPU P-States generated successfully\n");
582
583return ssdt;
584}
585}
586else
587{
588verbose ("ACPI CPUs not found: P-States not generated !!!\n");
589}
590
591return NULL;
592}
593
594struct acpi_2_fadt *patch_fadt(struct acpi_2_fadt *fadt, struct acpi_2_dsdt *new_dsdt)
595{
596extern void setupSystemType();
597
598struct acpi_2_fadt *fadt_mod;
599bool fadt_rev2_needed = false;
600bool fix_restart;
601const char * value;
602
603// Restart Fix
604if (Platform.CPU.Vendor == 0x756E6547) {/* Intel */
605fix_restart = true;
606getBoolForKey(kRestartFix, &fix_restart, &bootInfo->bootConfig);
607} else {
608verbose ("Not an Intel platform: Restart Fix not applied !!!\n");
609fix_restart = false;
610}
611
612if (fix_restart) fadt_rev2_needed = true;
613
614// Allocate new fadt table
615if (fadt->Length < 0x84 && fadt_rev2_needed)
616{
617fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(0x84);
618memcpy(fadt_mod, fadt, fadt->Length);
619fadt_mod->Length = 0x84;
620fadt_mod->Revision = 0x02; // FADT rev 2 (ACPI 1.0B MS extensions)
621}
622else
623{
624fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(fadt->Length);
625memcpy(fadt_mod, fadt, fadt->Length);
626}
627// Determine system type / PM_Model
628if ( (value=getStringForKey(kSystemType, &bootInfo->bootConfig))!=NULL)
629{
630if (Platform.Type > 6)
631{
632if(fadt_mod->PM_Profile<=6)
633Platform.Type = fadt_mod->PM_Profile; // get the fadt if correct
634else
635Platform.Type = 1;/* Set a fixed value (Desktop) */
636verbose("Error: system-type must be 0..6. Defaulting to %d !\n", Platform.Type);
637}
638else
639Platform.Type = (unsigned char) strtoul(value, NULL, 10);
640}
641// Set PM_Profile from System-type if only user wanted this value to be forced
642if (fadt_mod->PM_Profile != Platform.Type)
643{
644 if (value)
645{ // user has overriden the SystemType so take care of it in FACP
646verbose("FADT: changing PM_Profile from 0x%02x to 0x%02x\n", fadt_mod->PM_Profile, Platform.Type);
647fadt_mod->PM_Profile = Platform.Type;
648 }
649 else
650 { // PM_Profile has a different value and no override has been set, so reflect the user value to ioregs
651Platform.Type = fadt_mod->PM_Profile <= 6 ? fadt_mod->PM_Profile : 1;
652 }
653}
654// We now have to write the systemm-type in ioregs: we cannot do it before in setupDeviceTree()
655// because we need to take care of facp original content, if it is correct.
656setupSystemType();
657
658// Patch FADT to fix restart
659if (fix_restart)
660{
661fadt_mod->Flags|= 0x400;
662fadt_mod->Reset_SpaceID= 0x01; // System I/O
663fadt_mod->Reset_BitWidth= 0x08; // 1 byte
664fadt_mod->Reset_BitOffset= 0x00; // Offset 0
665fadt_mod->Reset_AccessWidth= 0x01; // Byte access
666fadt_mod->Reset_Address= 0x0cf9; // Address of the register
667fadt_mod->Reset_Value= 0x06; // Value to write to reset the system
668verbose("FADT: Restart Fix applied!\n");
669}
670
671// Patch DSDT Address if we have loaded DSDT.aml
672if(new_dsdt)
673{
674DBG("DSDT: Old @%x,%x, ",fadt_mod->DSDT,fadt_mod->X_DSDT);
675
676fadt_mod->DSDT=(uint32_t)new_dsdt;
677if ((uint32_t)(&(fadt_mod->X_DSDT))-(uint32_t)fadt_mod+8<=fadt_mod->Length)
678fadt_mod->X_DSDT=(uint32_t)new_dsdt;
679
680DBG("New @%x,%x\n",fadt_mod->DSDT,fadt_mod->X_DSDT);
681
682verbose("FADT: Using custom DSDT!\n");
683}
684
685// Correct the checksum
686fadt_mod->Checksum=0;
687fadt_mod->Checksum=256-checksum8(fadt_mod,fadt_mod->Length);
688
689return fadt_mod;
690}
691
692/* Setup ACPI without replacing DSDT. */
693int setupAcpiNoMod()
694{
695//addConfigurationTable(&gEfiAcpiTableGuid, getAddressOfAcpiTable(), "ACPI");
696//addConfigurationTable(&gEfiAcpi20TableGuid, getAddressOfAcpi20Table(), "ACPI_20");
697/* XXX aserebln why uint32 cast if pointer is uint64 ? */
698acpi10_p = (uint32_t)getAddressOfAcpiTable();
699acpi20_p = (uint32_t)getAddressOfAcpi20Table();
700addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
701if(acpi20_p) addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
702return 1;
703}
704
705/* Setup ACPI. Replace DSDT if DSDT.aml is found */
706int setupAcpi(void)
707{
708int version;
709void *new_dsdt;
710
711const char *filename;
712char dirSpec[128];
713int len = 0;
714
715// Try using the file specified with the DSDT option
716if (getValueForKey(kDSDT, &filename, &len, &bootInfo->bootConfig))
717{
718sprintf(dirSpec, filename);
719}
720else
721{
722sprintf(dirSpec, "DSDT.aml");
723}
724
725// Load replacement DSDT
726new_dsdt = loadACPITable(dirSpec);
727// Mozodojo: going to patch FACP and load SSDT's even if DSDT.aml is not present
728/*if (!new_dsdt)
729 {
730 return setupAcpiNoMod();
731 }*/
732
733// Mozodojo: Load additional SSDTs
734struct acpi_2_ssdt *new_ssdt[32]; // 30 + 2 additional tables for pss & cst
735int ssdt_count=0;
736
737// SSDT Options
738bool drop_ssdt=false, generate_pstates=false, generate_cstates=false;
739
740getBoolForKey(kDropSSDT, &drop_ssdt, &bootInfo->bootConfig);
741getBoolForKey(kGeneratePStates, &generate_pstates, &bootInfo->bootConfig);
742getBoolForKey(kGenerateCStates, &generate_cstates, &bootInfo->bootConfig);
743
744{
745int i;
746
747for (i=0; i<30; i++)
748{
749char filename[512];
750
751sprintf(filename, i>0?"SSDT-%d.aml":"SSDT.aml", i);
752
753if(new_ssdt[ssdt_count] = loadACPITable(filename))
754{
755ssdt_count++;
756}
757else
758{
759break;
760}
761}
762}
763
764// Do the same procedure for both versions of ACPI
765for (version=0; version<2; version++) {
766struct acpi_2_rsdp *rsdp, *rsdp_mod;
767struct acpi_2_rsdt *rsdt, *rsdt_mod;
768int rsdplength;
769
770// Find original rsdp
771rsdp=(struct acpi_2_rsdp *)(version?getAddressOfAcpi20Table():getAddressOfAcpiTable());
772if (!rsdp)
773{
774DBG("No ACPI version %d found. Ignoring\n", version+1);
775if (version)
776addConfigurationTable(&gEfiAcpi20TableGuid, NULL, "ACPI_20");
777else
778addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI");
779continue;
780}
781rsdplength=version?rsdp->Length:20;
782
783DBG("RSDP version %d found @%x. Length=%d\n",version+1,rsdp,rsdplength);
784
785/* FIXME: no check that memory allocation succeeded
786 * Copy and patch RSDP,RSDT, XSDT and FADT
787 * For more info see ACPI Specification pages 110 and following
788 */
789
790rsdp_mod=(struct acpi_2_rsdp *) AllocateKernelMemory(rsdplength);
791memcpy(rsdp_mod, rsdp, rsdplength);
792rsdt=(struct acpi_2_rsdt *)(rsdp->RsdtAddress);
793
794DBG("RSDT @%x, Length %d\n",rsdt, rsdt->Length);
795
796if (rsdt && (uint32_t)rsdt !=0xffffffff && rsdt->Length<0x10000)
797{
798uint32_t *rsdt_entries;
799int rsdt_entries_num;
800int dropoffset=0, i;
801
802// mozo: using malloc cos I didn't found how to free already allocated kernel memory
803rsdt_mod=(struct acpi_2_rsdt *)malloc(rsdt->Length);
804memcpy (rsdt_mod, rsdt, rsdt->Length);
805rsdp_mod->RsdtAddress=(uint32_t)rsdt_mod;
806rsdt_entries_num=(rsdt_mod->Length-sizeof(struct acpi_2_rsdt))/4;
807rsdt_entries=(uint32_t *)(rsdt_mod+1);
808for (i=0;i<rsdt_entries_num;i++)
809{
810char *table=(char *)(rsdt_entries[i]);
811if (!table)
812continue;
813
814DBG("TABLE %c%c%c%c,",table[0],table[1],table[2],table[3]);
815
816rsdt_entries[i-dropoffset]=rsdt_entries[i];
817
818if (drop_ssdt && tableSign(table, "SSDT"))
819{
820dropoffset++;
821continue;
822}
823if (tableSign(table, "DSDT"))
824{
825DBG("DSDT found\n");
826
827if(new_dsdt)
828rsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;
829
830continue;
831}
832if (tableSign(table, "FACP"))
833{
834struct acpi_2_fadt *fadt, *fadt_mod;
835fadt=(struct acpi_2_fadt *)rsdt_entries[i];
836
837DBG("FADT found @%x, Length %d\n",fadt, fadt->Length);
838
839if (!fadt || (uint32_t)fadt == 0xffffffff || fadt->Length>0x10000)
840{
841printf("FADT incorrect. Not modified\n");
842continue;
843}
844
845fadt_mod = patch_fadt(fadt, new_dsdt);
846rsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;
847
848// Generate _CST SSDT
849if (generate_cstates && (new_ssdt[ssdt_count] = generate_cst_ssdt(fadt_mod)))
850{
851generate_cstates = false; // Generate SSDT only once!
852ssdt_count++;
853}
854
855// Generating _PSS SSDT
856if (generate_pstates && (new_ssdt[ssdt_count] = generate_pss_ssdt((void*)fadt_mod->DSDT)))
857{
858generate_pstates = false; // Generate SSDT only once!
859ssdt_count++;
860}
861
862continue;
863}
864}
865DBG("\n");
866
867// Allocate rsdt in Kernel memory area
868rsdt_mod->Length += 4*ssdt_count - 4*dropoffset;
869struct acpi_2_rsdt *rsdt_copy = (struct acpi_2_rsdt *)AllocateKernelMemory(rsdt_mod->Length);
870memcpy (rsdt_copy, rsdt_mod, rsdt_mod->Length);
871free(rsdt_mod); rsdt_mod = rsdt_copy;
872rsdp_mod->RsdtAddress=(uint32_t)rsdt_mod;
873rsdt_entries_num=(rsdt_mod->Length-sizeof(struct acpi_2_rsdt))/4;
874rsdt_entries=(uint32_t *)(rsdt_mod+1);
875
876// Mozodojo: Insert additional SSDTs into RSDT
877if(ssdt_count>0)
878{
879int j;
880
881for (j=0; j<ssdt_count; j++)
882rsdt_entries[i-dropoffset+j]=(uint32_t)new_ssdt[j];
883
884verbose("RSDT: Added %d SSDT table(s)\n", ssdt_count);
885}
886
887// Correct the checksum of RSDT
888DBG("RSDT: Original checksum %d, ", rsdt_mod->Checksum);
889
890rsdt_mod->Checksum=0;
891rsdt_mod->Checksum=256-checksum8(rsdt_mod,rsdt_mod->Length);
892
893DBG("New checksum %d at %x\n", rsdt_mod->Checksum,rsdt_mod);
894}
895else
896{
897rsdp_mod->RsdtAddress=0;
898printf("RSDT not found or RSDT incorrect\n");
899}
900
901if (version)
902{
903struct acpi_2_xsdt *xsdt, *xsdt_mod;
904
905// FIXME: handle 64-bit address correctly
906
907xsdt=(struct acpi_2_xsdt*) ((uint32_t)rsdp->XsdtAddress);
908DBG("XSDT @%x;%x, Length=%d\n", (uint32_t)(rsdp->XsdtAddress>>32),(uint32_t)rsdp->XsdtAddress,
909xsdt->Length);
910if (xsdt && (uint64_t)rsdp->XsdtAddress<0xffffffff && xsdt->Length<0x10000)
911{
912uint64_t *xsdt_entries;
913int xsdt_entries_num, i;
914int dropoffset=0;
915
916// mozo: using malloc cos I didn't found how to free already allocated kernel memory
917xsdt_mod=(struct acpi_2_xsdt*)malloc(xsdt->Length);
918memcpy(xsdt_mod, xsdt, xsdt->Length);
919rsdp_mod->XsdtAddress=(uint32_t)xsdt_mod;
920xsdt_entries_num=(xsdt_mod->Length-sizeof(struct acpi_2_xsdt))/8;
921xsdt_entries=(uint64_t *)(xsdt_mod+1);
922for (i=0;i<xsdt_entries_num;i++)
923{
924char *table=(char *)((uint32_t)(xsdt_entries[i]));
925if (!table)
926continue;
927
928xsdt_entries[i-dropoffset]=xsdt_entries[i];
929
930if (drop_ssdt && tableSign(table, "SSDT"))
931{
932dropoffset++;
933continue;
934}
935if (tableSign(table, "DSDT"))
936{
937DBG("DSDT found\n");
938
939if (new_dsdt)
940xsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;
941
942DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
943
944continue;
945}
946if (tableSign(table, "FACP"))
947{
948struct acpi_2_fadt *fadt, *fadt_mod;
949fadt=(struct acpi_2_fadt *)(uint32_t)xsdt_entries[i];
950
951DBG("FADT found @%x,%x, Length %d\n",(uint32_t)(xsdt_entries[i]>>32),fadt,
952fadt->Length);
953
954if (!fadt || (uint64_t)xsdt_entries[i] >= 0xffffffff || fadt->Length>0x10000)
955{
956verbose("FADT incorrect or after 4GB. Dropping XSDT\n");
957goto drop_xsdt;
958}
959
960fadt_mod = patch_fadt(fadt, new_dsdt);
961xsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;
962
963DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
964
965// Generate _CST SSDT
966if (generate_cstates && (new_ssdt[ssdt_count] = generate_cst_ssdt(fadt_mod)))
967{
968generate_cstates = false; // Generate SSDT only once!
969ssdt_count++;
970}
971
972// Generating _PSS SSDT
973if (generate_pstates && (new_ssdt[ssdt_count] = generate_pss_ssdt((void*)fadt_mod->DSDT)))
974{
975generate_pstates = false; // Generate SSDT only once!
976ssdt_count++;
977}
978
979continue;
980}
981
982DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
983
984}
985
986// Allocate xsdt in Kernel memory area
987xsdt_mod->Length += 8*ssdt_count - 8*dropoffset;
988struct acpi_2_xsdt *xsdt_copy = (struct acpi_2_xsdt *)AllocateKernelMemory(xsdt_mod->Length);
989memcpy(xsdt_copy, xsdt_mod, xsdt_mod->Length);
990free(xsdt_mod); xsdt_mod = xsdt_copy;
991rsdp_mod->XsdtAddress=(uint32_t)xsdt_mod;
992xsdt_entries_num=(xsdt_mod->Length-sizeof(struct acpi_2_xsdt))/8;
993xsdt_entries=(uint64_t *)(xsdt_mod+1);
994
995// Mozodojo: Insert additional SSDTs into XSDT
996if(ssdt_count>0)
997{
998int j;
999
1000for (j=0; j<ssdt_count; j++)
1001xsdt_entries[i-dropoffset+j]=(uint32_t)new_ssdt[j];
1002
1003verbose("Added %d SSDT table(s) into XSDT\n", ssdt_count);
1004}
1005
1006// Correct the checksum of XSDT
1007xsdt_mod->Checksum=0;
1008xsdt_mod->Checksum=256-checksum8(xsdt_mod,xsdt_mod->Length);
1009}
1010else
1011{
1012drop_xsdt:
1013
1014DBG("About to drop XSDT\n");
1015
1016/*FIXME: Now we just hope that if MacOS doesn't find XSDT it reverts to RSDT.
1017 * A Better strategy would be to generate
1018 */
1019
1020rsdp_mod->XsdtAddress=0xffffffffffffffffLL;
1021verbose("XSDT not found or XSDT incorrect\n");
1022}
1023}
1024
1025// Correct the checksum of RSDP
1026
1027DBG("RSDP: Original checksum %d, ", rsdp_mod->Checksum);
1028
1029rsdp_mod->Checksum=0;
1030rsdp_mod->Checksum=256-checksum8(rsdp_mod,20);
1031
1032DBG("New checksum %d\n", rsdp_mod->Checksum);
1033
1034if (version)
1035{
1036DBG("RSDP: Original extended checksum %d", rsdp_mod->ExtendedChecksum);
1037
1038rsdp_mod->ExtendedChecksum=0;
1039rsdp_mod->ExtendedChecksum=256-checksum8(rsdp_mod,rsdp_mod->Length);
1040
1041DBG("New extended checksum %d\n", rsdp_mod->ExtendedChecksum);
1042
1043}
1044
1045//verbose("Patched ACPI version %d DSDT\n", version+1);
1046if (version)
1047{
1048/* XXX aserebln why uint32 cast if pointer is uint64 ? */
1049acpi20_p = (uint32_t)rsdp_mod;
1050addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
1051}
1052else
1053{
1054/* XXX aserebln why uint32 cast if pointer is uint64 ? */
1055acpi10_p = (uint32_t)rsdp_mod;
1056addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
1057}
1058}
1059#if DEBUG_ACPI
1060printf("Press a key to continue... (DEBUG_ACPI)\n");
1061getc();
1062#endif
1063return 1;
1064}
1065

Archive Download this file

Revision: 307