Chameleon

Chameleon Svn Source Tree

Root/branches/meklort/i386/modules/ACPIPatcher/acpi_patcher.c

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

Archive Download this file

Revision: 970