Chameleon

Chameleon Svn Source Tree

Root/branches/azimutz/Chazi/i386/libsaio/acpi_patcher.c

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

Archive Download this file

Revision: 983