Chameleon

Chameleon Svn Source Tree

Root/tags/2.0/i386/libsaio/acpi_patcher.c

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

Archive Download this file

Revision: 1808