Chameleon

Chameleon Svn Source Tree

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

1/*
2 * Copyright 2008 mackerintel
3 */
4
5/*
6 * cparm : cleaned, moved into a module
7 */
8
9#include "libsaio.h"
10#include "boot.h"
11#include "bootstruct.h"
12#include "acpi.h"
13#include "efi_tables.h"
14#include "fake_efi.h"
15#include "acpi_patcher.h"
16#include "platform.h"
17#include "cpu.h"
18#include "aml_generator.h"
19#include "modules.h"
20#include "xml.h"
21
22#ifndef DEBUG_ACPI
23#define DEBUG_ACPI 0
24#endif
25
26#if DEBUG_ACPI==2
27#define DBG(x...) {printf(x); sleep(1);}
28#elif DEBUG_ACPI==1
29#define DBG(x...) printf(x)
30#else
31#define DBG(x...)
32#endif
33
34
35extern uint64_t acpi10_p;
36extern uint64_t acpi20_p;
37extern EFI_STATUS addConfigurationTable();
38
39extern EFI_GUID gEfiAcpiTableGuid;
40extern EFI_GUID gEfiAcpi20TableGuid;
41
42
43#define __RES(s, u)\
44static inline unsigned u\
45resolve_##s(unsigned u defaultentry, char *str, int base) \
46{\
47unsigned u entry = defaultentry;\
48if (str && (strcmp(str,"Default") != 0)) {\
49entry = strtoul((const char *)str, NULL,base);\
50}\
51return entry;\
52}
53
54__RES(pss, long)
55__RES(cst, int)
56
57#define tableSign(table, sgn) (table[0]==sgn[0] && table[1]==sgn[1] && table[2]==sgn[2] && table[3]==sgn[3])
58
59void *loadSSDTTable(int ssdt_number)
60{
61int fd = -1;
62char dirspec[512];
63char filename[512];
64const char * overriden_pathname=NULL;
65int len=0;
66
67// Check booting partition
68
69// Rek: if user specified a full path name then take it in consideration
70if (getValueForKey(kSSDT, &overriden_pathname, &len,
71 &bootInfo->bootConfig))
72{
73sprintf(filename, "%s-%d.aml", overriden_pathname, ssdt_number); // start searching root
74}
75else
76sprintf(filename, "SSDT-%d.aml", ssdt_number);
77
78sprintf(dirspec, "/%s", filename); // start searching root
79
80fd=open (dirspec,0);
81
82if (fd<0)
83{// Check Extra on booting partition
84sprintf(dirspec,"/Extra/%s",filename);
85fd=open (dirspec,0);
86if (fd<0)
87{// Fall back to booter partition
88sprintf(dirspec,"bt(0,0)/Extra/%s",filename);
89fd=open (dirspec,0);
90if (fd<0)
91{
92DBG("SSDT Table not found: %s\n", filename);
93return NULL;
94}
95}
96}
97
98void *tableAddr=(void*)AllocateKernelMemory(file_size (fd));
99if (tableAddr)
100{
101if (read (fd, tableAddr, file_size (fd))!=file_size (fd))
102{
103printf("Couldn't read table %s\n",dirspec);
104free (tableAddr);
105close (fd);
106return NULL;
107}
108
109printf("Valid SSDT Table found: %s\n", filename);
110DBG("Table %s read and stored at: %x\n", dirspec, tableAddr);
111close (fd);
112return tableAddr;
113}
114
115printf("Couldn't allocate memory for table %s\n", dirspec);
116close (fd);
117
118return NULL;
119}
120
121void *loadACPITable(char *key)
122{
123int fd = -1;
124char dirspec[512];
125char filename[512];
126const char * overriden_pathname=NULL;
127int len=0;
128
129DBG("Searching for %s.aml file ...\n", key);
130// Check booting partition
131
132// Rek: if user specified a full path name then take it in consideration
133if (getValueForKey(key, &overriden_pathname, &len,
134 &bootInfo->bootConfig))
135{
136sprintf(filename, "%s", overriden_pathname);
137}
138else
139sprintf(filename, "%s.aml", key);
140
141
142sprintf(dirspec, "/%s", filename); // start searching root
143
144fd=open (dirspec,0);
145
146if (fd<0)
147{
148// Check Extra on booting partition
149sprintf(dirspec,"/Extra/%s",filename);
150fd=open (dirspec,0);
151if (fd<0)
152{// Fall back to booter partition
153sprintf(dirspec,"bt(0,0)/Extra/%s",filename);
154fd=open (dirspec,0);
155if (fd<0)
156{
157DBG("ACPI Table not found: %s\n", key);
158return NULL;
159}
160
161}
162
163}
164
165void *tableAddr=(void*)AllocateKernelMemory(file_size (fd));
166if (tableAddr)
167{
168if (read (fd, tableAddr, file_size (fd))!=file_size (fd))
169{
170printf("Couldn't read table %s\n",key);
171free (tableAddr);
172close (fd);
173return NULL;
174}
175verbose("Valid ACPI Table found: %s\n", key);
176DBG("Table %s read and stored at: %x\n", key, tableAddr);
177close (fd);
178return tableAddr;
179}
180
181printf("Couldn't allocate memory for table %s\n", key);
182close (fd);
183
184return NULL;
185}
186
187uint8_tacpi_cpu_count = 0;
188char* acpi_cpu_name[32];
189
190void get_acpi_cpu_names(unsigned char* dsdt, uint32_t length)
191{
192uint32_t i;
193
194for (i=0; i<length-7; i++)
195{
196if (dsdt[i] == 0x5B && dsdt[i+1] == 0x83) // ProcessorOP
197{
198uint32_t offset = i + 3 + (dsdt[i+2] >> 6);
199
200bool add_name = true;
201
202uint8_t j;
203
204for (j=0; j<4; j++)
205{
206char c = dsdt[offset+j];
207
208if (!aml_isvalidchar(c))
209{
210add_name = false;
211verbose("Invalid character found in ProcessorOP 0x%x!\n", c);
212break;
213}
214}
215
216if (add_name)
217{
218acpi_cpu_name[acpi_cpu_count] = malloc(4);
219memcpy(acpi_cpu_name[acpi_cpu_count], dsdt+offset, 4);
220i = offset + 5;
221
222verbose("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]);
223
224if (++acpi_cpu_count == 32) return;
225}
226}
227}
228}
229
230
231struct acpi_2_ssdt *generate_cst_ssdt(struct acpi_2_fadt* fadt)
232{
233char ssdt_header[] =
234{
2350x53, 0x53, 0x44, 0x54, 0xE7, 0x00, 0x00, 0x00, /* SSDT.... */
2360x01, 0x17, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x41, /* ..PmRefA */
2370x43, 0x70, 0x75, 0x43, 0x73, 0x74, 0x00, 0x00, /* CpuCst.. */
2380x00, 0x10, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* ....INTL */
2390x31, 0x03, 0x10, 0x20 /* 1.._*/
240};
241
242char cstate_resource_template[] =
243{
2440x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00, 0x7F,
2450x01, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
2460x00, 0x00, 0x00, 0x79, 0x00
247};
248
249if (Platform->CPU.Vendor != 0x756E6547) {
250verbose ("Not an Intel platform: C-States will not be generated !!!\n");
251return NULL;
252}
253
254if (fadt == NULL) {
255verbose ("FACP not exists: C-States will not be generated !!!\n");
256return NULL;
257}
258
259struct acpi_2_dsdt* dsdt = (void*)fadt->DSDT;
260
261if (dsdt == NULL) {
262verbose ("DSDT not found: C-States will not be generated !!!\n");
263return NULL;
264}
265
266if (acpi_cpu_count == 0)
267get_acpi_cpu_names((void*)dsdt, dsdt->Length);
268
269if (acpi_cpu_count > 0)
270{
271bool c2_enabled = fadt->C2_Latency < 100;
272bool c3_enabled = fadt->C3_Latency < 1000;
273bool c4_enabled = false;
274
275getBoolForKey(kEnableC4State, &c4_enabled, &bootInfo->bootConfig);
276
277unsigned char cstates_count = 1 + (c2_enabled ? 1 : 0) + ((c3_enabled || c4_enabled) ? 1 : 0);
278char *Lat = NULL, *Pw = NULL, *tmpstr =NULL;
279int base = 16;
280TagPtr personality = XMLCastDict(XMLGetProperty(bootInfo->bootConfig.dictionary, (const char*)"C-States"));
281
282if (tmpstr = XMLCastString(XMLGetProperty(personality, (const char*)"Base"))) {
283
284int mybase = strtol(tmpstr, NULL, 10);
285
286if (mybase == 8 || mybase == 10 || mybase == 16 )
287base = mybase;
288}
289
290struct aml_chunk* root = aml_create_node(NULL);
291aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header
292struct aml_chunk* scop = aml_add_scope(root, "\\_PR_");
293struct aml_chunk* name = aml_add_name(scop, "CST_");
294struct aml_chunk* pack = aml_add_package(name);
295aml_add_byte(pack, cstates_count);
296
297struct aml_chunk* tmpl = aml_add_package(pack);
298TagPtr match_Status = XMLGetProperty(personality, (const char*)"C1");
299if (match_Status) {
300Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power"));
301Lat = XMLCastString(XMLGetProperty(match_Status, (const char*)"Latency"));
302}
303cstate_resource_template[11] = 0x00; // C1
304aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
305aml_add_byte(tmpl, 0x01); // C1
306aml_add_byte(tmpl, (unsigned char)resolve_cst(0x01, Lat, base)); // Latency
307aml_add_word(tmpl, resolve_cst(0x03e8, Pw, base)); // Power
308// C2
309if (c2_enabled)
310{
311tmpl = aml_add_package(pack);
312Lat = NULL;
313Pw = NULL;
314match_Status = XMLGetProperty(personality, (const char*)"C2");
315if (match_Status) {
316Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power"));
317Lat = XMLCastString(XMLGetProperty(match_Status, (const char*)"Latency"));
318}
319
320cstate_resource_template[11] = 0x10; // C2
321aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
322aml_add_byte(tmpl, 0x02); // C2
323aml_add_word(tmpl, resolve_cst(fadt->C2_Latency, Lat, base)); // Latency
324aml_add_word(tmpl, resolve_cst(0x01f4, Pw, base)); // Power
325}
326
327// C4
328if (c4_enabled)
329{
330tmpl = aml_add_package(pack);
331Lat = NULL;
332Pw = NULL;
333match_Status = XMLGetProperty(personality, (const char*)"C4");
334if (match_Status) {
335Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power"));
336Lat = XMLCastString(XMLGetProperty(match_Status, (const char*)"Latency"));
337}
338cstate_resource_template[11] = 0x30; // C4
339aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
340aml_add_byte(tmpl, 0x04); // C4
341aml_add_word(tmpl, resolve_cst(fadt->C3_Latency / 2, Lat, base)); // TODO: right latency for C4
342aml_add_word(tmpl, resolve_cst(0xfa, Pw, base)); // Power
343
344}
345// C3
346else if (c3_enabled)
347{
348tmpl = aml_add_package(pack);
349Lat = NULL;
350Pw = NULL;
351match_Status = XMLGetProperty(personality, (const char*)"C3");
352if (match_Status) {
353Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power"));
354Lat = XMLCastString(XMLGetProperty(match_Status, (const char*)"Latency"));
355}
356cstate_resource_template[11] = 0x20; // C3
357aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
358aml_add_byte(tmpl, 0x03); // C3
359aml_add_word(tmpl, resolve_cst(fadt->C3_Latency , Lat, base));
360aml_add_word(tmpl, resolve_cst(0x015e, Pw, base)); // Power
361
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
388verbose ("SSDT with CPU C-States generated successfully\n");
389
390return ssdt;
391}
392else
393{
394verbose ("ACPI CPUs not found: C-States not generated !!!\n");
395}
396
397return NULL;
398}
399
400struct acpi_2_ssdt *generate_pss_ssdt(struct acpi_2_dsdt* dsdt)
401{
402
403char ssdt_header[] =
404{
4050x53, 0x53, 0x44, 0x54, 0x7E, 0x00, 0x00, 0x00, /* SSDT.... */
4060x01, 0x6A, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x00, /* ..PmRef. */
4070x43, 0x70, 0x75, 0x50, 0x6D, 0x00, 0x00, 0x00, /* CpuPm... */
4080x00, 0x30, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* .0..INTL */
4090x31, 0x03, 0x10, 0x20,/* 1.._*/
410};
411
412if (Platform->CPU.Vendor != 0x756E6547) {
413verbose ("Not an Intel platform: P-States will not be generated !!!\n");
414return NULL;
415}
416
417if (!(Platform->CPU.Features & CPU_FEATURE_MSR)) {
418verbose ("Unsupported CPU: P-States will not be generated !!!\n");
419return NULL;
420}
421
422if (acpi_cpu_count == 0)
423get_acpi_cpu_names((void*)dsdt, dsdt->Length);
424
425if (acpi_cpu_count > 0)
426{
427struct p_state initial, maximum, minimum, p_states[32];
428uint8_t p_states_count = 0;
429
430// Retrieving P-States, ported from code by superhai (c)
431switch (Platform->CPU.Family) {
432case 0x06:
433{
434switch (Platform->CPU.Model)
435{
436case 0x0D: // ?
437case CPU_MODEL_YONAH: // Yonah
438case CPU_MODEL_MEROM: // Merom
439case CPU_MODEL_PENRYN: // Penryn
440case CPU_MODEL_ATOM: // Intel Atom (45nm)
441{
442bool cpu_dynamic_fsb = false;
443
444if (rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 27))
445{
446wrmsr64(MSR_IA32_EXT_CONFIG, (rdmsr64(MSR_IA32_EXT_CONFIG) | (1 << 28)));
447delay(1);
448cpu_dynamic_fsb = rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 28);
449}
450
451bool cpu_noninteger_bus_ratio = (rdmsr64(MSR_IA32_PERF_STATUS) & (1ULL << 46));
452
453initial.Control = rdmsr64(MSR_IA32_PERF_STATUS);
454
455maximum.Control = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 32) & 0x1F3F) | (0x4000 * cpu_noninteger_bus_ratio);
456maximum.CID = ((maximum.FID & 0x1F) << 1) | cpu_noninteger_bus_ratio;
457
458minimum.FID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 24) & 0x1F) | (0x80 * cpu_dynamic_fsb);
459minimum.VID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 48) & 0x3F);
460
461if (minimum.FID == 0)
462{
463uint64_t msr;
464uint8_t i;
465// Probe for lowest fid
466for (i = maximum.FID; i >= 0x6; i--)
467{
468msr = rdmsr64(MSR_IA32_PERF_CONTROL);
469wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (i << 8) | minimum.VID);
470intel_waitforsts();
471minimum.FID = (rdmsr64(MSR_IA32_PERF_STATUS) >> 8) & 0x1F;
472delay(1);
473}
474
475msr = rdmsr64(MSR_IA32_PERF_CONTROL);
476wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
477intel_waitforsts();
478}
479
480if (minimum.VID == maximum.VID)
481{
482uint64_t msr;
483uint8_t i;
484// Probe for lowest vid
485for (i = maximum.VID; i > 0xA; i--)
486{
487msr = rdmsr64(MSR_IA32_PERF_CONTROL);
488wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (minimum.FID << 8) | i);
489intel_waitforsts();
490minimum.VID = rdmsr64(MSR_IA32_PERF_STATUS) & 0x3F;
491delay(1);
492}
493
494msr = rdmsr64(MSR_IA32_PERF_CONTROL);
495wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
496intel_waitforsts();
497}
498
499minimum.CID = ((minimum.FID & 0x1F) << 1) >> cpu_dynamic_fsb;
500
501// Sanity check
502if (maximum.CID < minimum.CID)
503{
504DBG("Insane FID values!");
505p_states_count = 0;
506}
507else
508{
509// Finalize P-States
510// Find how many P-States machine supports
511p_states_count = maximum.CID - minimum.CID + 1;
512
513if (p_states_count > 32)
514p_states_count = 32;
515
516uint8_t vidstep;
517uint8_t i = 0, u, invalid = 0;
518
519vidstep = ((maximum.VID << 2) - (minimum.VID << 2)) / (p_states_count - 1);
520
521for (u = 0; u < p_states_count; u++)
522{
523i = u - invalid;
524
525p_states[i].CID = maximum.CID - u;
526p_states[i].FID = (p_states[i].CID >> 1);
527
528if (p_states[i].FID < 0x6)
529{
530if (cpu_dynamic_fsb)
531p_states[i].FID = (p_states[i].FID << 1) | 0x80;
532}
533else if (cpu_noninteger_bus_ratio)
534{
535p_states[i].FID = p_states[i].FID | (0x40 * (p_states[i].CID & 0x1));
536}
537
538if (i && p_states[i].FID == p_states[i-1].FID)
539invalid++;
540
541p_states[i].VID = ((maximum.VID << 2) - (vidstep * u)) >> 2;
542
543uint32_t multiplier = p_states[i].FID & 0x1f;// = 0x08
544bool half = p_states[i].FID & 0x40;// = 0x01
545bool dfsb = p_states[i].FID & 0x80;// = 0x00
546uint32_t fsb = Platform->CPU.FSBFrequency / 1000000; // = 400
547uint32_t halffsb = (fsb + 1) >> 1;// = 200
548uint32_t frequency = (multiplier * fsb);// = 3200
549
550p_states[i].Frequency = (frequency + (half * halffsb)) >> dfsb;// = 3200 + 200 = 3400
551}
552
553p_states_count -= invalid;
554}
555break;
556}
557case CPU_MODEL_FIELDS:
558case CPU_MODEL_DALES:
559case CPU_MODEL_DALES_32NM:
560case CPU_MODEL_NEHALEM:
561case CPU_MODEL_NEHALEM_EX:
562case CPU_MODEL_WESTMERE:
563case CPU_MODEL_WESTMERE_EX:
564{
565maximum.Control = rdmsr64(MSR_IA32_PERF_STATUS) & 0xff; // Seems it always contains maximum multiplier value (with turbo, that's we need)...
566minimum.Control = (rdmsr64(MSR_PLATFORM_INFO) >> 40) & 0xff;
567
568verbose("P-States: min 0x%x, max 0x%x\n", minimum.Control, maximum.Control);
569
570// Sanity check
571if (maximum.Control < minimum.Control)
572{
573DBG("Insane control values!");
574p_states_count = 0;
575}
576else
577{
578uint8_t i;
579p_states_count = 0;
580
581for (i = maximum.Control; i >= minimum.Control; i--)
582{
583p_states[p_states_count].Control = i;
584p_states[p_states_count].CID = p_states[p_states_count].Control << 1;
585p_states[p_states_count].Frequency = (Platform->CPU.FSBFrequency / 1000000) * i;
586p_states_count++;
587}
588}
589
590break;
591}
592default:
593verbose ("Unsupported CPU: P-States not generated !!!\n");
594break;
595}
596}
597}
598
599// Generating SSDT
600if (p_states_count)
601{
602int i;
603
604struct aml_chunk* root = aml_create_node(NULL);
605aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header
606struct aml_chunk* scop = aml_add_scope(root, "\\_PR_");
607struct aml_chunk* name = aml_add_name(scop, "PSS_");
608struct aml_chunk* pack = aml_add_package(name);
609
610uint8_t minPSratio = (p_states[p_states_count-1].Frequency / (Platform->CPU.FSBFrequency / 10000000 ));
611uint8_t maxPSratio = (p_states[0].Frequency / (Platform->CPU.FSBFrequency / 10000000 ));
612
613uint8_t cpu_div = Platform->CPU.CurrDiv;
614uint8_t cpu_ratio = 0;
615
616if (cpu_div)
617cpu_ratio = (Platform->CPU.CurrCoef * 10) + 5;
618else
619cpu_ratio = Platform->CPU.CurrCoef * 10;
620
621
622int user_max_ratio = 0;
623getIntForKey(kMaxRatio, &user_max_ratio, &bootInfo->bootConfig);
624if (user_max_ratio >= minPSratio && maxPSratio >= user_max_ratio) {
625
626uint8_t maxcurrdiv = 0, maxcurrcoef = (int)(user_max_ratio / 10);
627
628uint8_t maxdiv = user_max_ratio - (maxcurrcoef * 10);
629if (maxdiv > 0)
630maxcurrdiv = 1;
631
632if (maxcurrdiv)
633cpu_ratio = (maxcurrcoef * 10) + 5;
634else
635cpu_ratio = maxcurrcoef * 10;
636}
637
638int user_min_ratio = 0;
639getIntForKey(kMinRatio, &user_min_ratio, &bootInfo->bootConfig);
640if (user_min_ratio >= minPSratio && cpu_ratio >= user_min_ratio) {
641
642uint8_t mincurrdiv = 0, mincurrcoef = (int)(user_min_ratio / 10);
643
644uint8_t mindiv = user_min_ratio - (mincurrcoef * 10);
645
646if (mindiv > 0)
647mincurrdiv = 1;
648
649if (mincurrdiv)
650minPSratio = (mincurrcoef * 10) + 5;
651else
652minPSratio = mincurrcoef * 10;
653
654}
655
656if (maxPSratio >= cpu_ratio && cpu_ratio >= minPSratio)maxPSratio = cpu_ratio;
657
658TagPtr personality = XMLCastDict(XMLGetProperty(bootInfo->bootConfig.dictionary, (const char*)"P-States"));
659char* MatchStat = 0;
660int dropPSS = 0, Pstatus = 0, base = 16;
661int expert = 0;/* Default: 0 , mean mixed mode | expert mode : 1 , mean add only p-states found in boot.plist*/
662char *tmpstr = XMLCastString(XMLGetProperty(personality, (const char*)"Mode"));
663
664if (strcmp(tmpstr,"Expert") == 0) {
665p_states_count = (XMLTagCount(personality)) - 1 ; // - 1 = - ("Mode" tag)
666expert = 1;
667}
668
669
670if (tmpstr = XMLCastString(XMLGetProperty(personality, (const char*)"Base"))) {
671
672if (expert) p_states_count--; // -= ("Base" tag)
673
674int mybase = strtol(tmpstr, NULL, 10);
675
676if (mybase == 8 || mybase == 10 || mybase == 16 )
677base = mybase;
678}
679
680for (i = 0; i < p_states_count; i++)
681{
682sprintf(MatchStat, "%d",i);
683TagPtr match_Status = XMLGetProperty(personality, (const char*)MatchStat);
684
685char *Lat1 = NULL, *clk = NULL, *Pw = NULL, *Lat2 = NULL, *Ctrl = NULL ;
686
687if (match_Status) {
688
689clk = XMLCastString(XMLGetProperty(match_Status, (const char*)"CoreFreq"));
690Pw = XMLCastString(XMLGetProperty(match_Status, (const char*)"Power"));
691Lat1 = XMLCastString(XMLGetProperty(match_Status, (const char*)"Transition Latency"));
692Lat2 = XMLCastString(XMLGetProperty(match_Status, (const char*)"Bus Master Latency"));
693Ctrl = XMLCastString(XMLGetProperty(match_Status, (const char*)"Control"));
694
695
696} else if (expert)
697continue;
698
699
700unsigned long Frequency = 0x00000000;
701
702if (!expert) Frequency = p_states[i].Frequency;
703
704if (clk)
705Frequency = strtoul((const char *)clk, NULL,base);
706
707if (!Frequency || Frequency > p_states[0].Frequency ) continue;
708
709uint8_t curr_ratio = (Frequency / (Platform->CPU.FSBFrequency / 10000000 ));
710
711if (curr_ratio > maxPSratio || minPSratio > curr_ratio)
712goto dropPstate;
713
714struct aml_chunk* pstt = aml_add_package(pack);
715aml_add_dword(pstt, Frequency); // CoreFreq (in MHz).
716aml_add_dword(pstt, resolve_pss(0x00000000, Pw, base)); // Power (in milliWatts)
717aml_add_dword(pstt, resolve_pss(0x0000000A, Lat1, base)); // Transition Latency (in microseconds).
718aml_add_dword(pstt, resolve_pss(0x0000000A, Lat2, base)); // Bus Master Latency (in microseconds).
719unsigned long Control = 0x00000000;
720if (!expert) Control = p_states[i].Control;
721aml_add_dword(pstt, resolve_pss(Control, Ctrl, base)); // Control
722Pstatus++;
723aml_add_dword(pstt, Pstatus); // Status
724continue;
725dropPstate:
726#if DEBUG_ACPI
727verbose("state with cpu frequency :%d and ratio :%d will be dropped\n",p_states[i].Frequency,curr_ratio);
728#endif
729dropPSS++;
730
731
732}
733
734// Add aliaces
735for (i = 0; i < acpi_cpu_count; i++)
736{
737char name[9];
738sprintf(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]);
739
740scop = aml_add_scope(root, name);
741aml_add_alias(scop, "PSS_", "_PSS");
742}
743
744aml_calculate_size(root);
745
746struct acpi_2_ssdt *ssdt = (struct acpi_2_ssdt *)AllocateKernelMemory(root->Size);
747
748aml_write_node(root, (void*)ssdt, 0);
749
750ssdt->Length = root->Size;
751ssdt->Checksum = 0;
752ssdt->Checksum = 256 - checksum8(ssdt, ssdt->Length);
753
754aml_destroy_node(root);
755
756verbose ("SSDT with CPU P-States generated successfully");
757
758if (dropPSS)
759verbose(", %d P-state(s) dropped",dropPSS);
760
761verbose("\n");
762
763return ssdt;
764}
765}
766else
767{
768verbose ("ACPI CPUs not found: P-States not generated !!!\n");
769}
770
771return NULL;
772}
773
774static
775struct acpi_2_gas FillGASStruct(uint32_t Address, uint8_t Length)
776{
777struct acpi_2_gas TmpGAS;
778
779TmpGAS.Address_Space_ID = 1; /* I/O Address */
780
781if (Address == 0)
782{
783TmpGAS.Register_Bit_Width = 0;
784} else {
785TmpGAS.Register_Bit_Width = Length * 8;
786}
787
788TmpGAS.Register_Bit_Offset = 0;
789TmpGAS.Access_Size = 0; /* Not set for Legacy reasons... */
790TmpGAS.Address = (uint64_t)Address;
791
792return(TmpGAS);
793}
794
795struct acpi_2_fadt *
796patch_fadt(struct acpi_2_fadt *fadt, struct acpi_2_facs *new_facs, struct acpi_2_dsdt *new_dsdt, bool UpdateFADT)
797{
798 extern void setupSystemType();
799
800struct acpi_2_fadt *fadt_mod;
801struct acpi_2_fadt *fadt_file = (struct acpi_2_fadt *)loadACPITable(kFADT);
802bool fadt_rev2_needed = false;
803bool fix_restart = false;
804const char * value;
805
806// Restart Fix
807if (Platform->CPU.Vendor == 0x756E6547) {/* Intel */
808fix_restart = true;
809getBoolForKey(kRestartFix, &fix_restart, &bootInfo->bootConfig);
810} else {
811verbose ("Not an Intel platform: Restart Fix not applied !!!\n");
812}
813
814if (fix_restart)
815fadt_rev2_needed = true;
816
817// Allocate new fadt table
818if ((UpdateFADT) && (((fadt_file) && (fadt_file->Length < sizeof(struct acpi_2_fadt))) ||
819 ((!fadt_file) && (fadt->Length < sizeof(struct acpi_2_fadt)))))
820{
821if (fadt_file)
822{
823if (fadt_file->Length < 0xF4)
824{
825fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(0xF4);
826memcpy(fadt_mod, fadt_file, fadt_file->Length);
827fadt_mod->Length = 0xF4;
828}
829else
830{
831
832fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(fadt_file->Length);
833memcpy(fadt_mod, fadt_file, fadt_file->Length);
834}
835}
836else
837{
838if (fadt->Length < 0xF4)
839{
840fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(0xF4);
841memcpy(fadt_mod, fadt, fadt->Length);
842fadt_mod->Length = 0xF4;
843}
844else
845{
846
847fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(fadt->Length);
848memcpy(fadt_mod, fadt, fadt->Length);
849}
850}
851
852fadt_mod->Revision = 0x04; // FADT rev 4
853fadt_mod->RESET_REG = FillGASStruct(0, 0);
854fadt_mod->Reset_Value = 0;
855fadt_mod->Reserved[0] = 0;
856fadt_mod->Reserved[1] = 0;
857fadt_mod->Reserved[2] = 0;
858fadt_mod->X_PM1a_EVT_BLK = FillGASStruct(fadt_mod->PM1A_Event_Block_Address, fadt_mod->PM1_Event_Block_Length);
859fadt_mod->X_PM1b_EVT_BLK = FillGASStruct(fadt_mod->PM1B_Event_Block_Address, fadt_mod->PM1_Event_Block_Length);
860fadt_mod->X_PM1a_CNT_BLK = FillGASStruct(fadt_mod->PM1A_Control_Block_Address, fadt_mod->PM1_Control_Block_Length);
861fadt_mod->X_PM1b_CNT_BLK = FillGASStruct(fadt_mod->PM1B_Control_Block_Address, fadt_mod->PM1_Control_Block_Length);
862fadt_mod->X_PM2_CNT_BLK = FillGASStruct(fadt_mod->PM2_Control_Block_Address, fadt_mod->PM2_Control_Block_Length);
863fadt_mod->X_PM_TMR_BLK = FillGASStruct(fadt_mod->PM_Timer_Block_Address, fadt_mod->PM_Timer_Block_Length);
864fadt_mod->X_GPE0_BLK = FillGASStruct(fadt_mod->GPE0_Block_Address, fadt_mod->GPE0_Block_Length);
865fadt_mod->X_GPE1_BLK = FillGASStruct(fadt_mod->GPE1_Block_Address, fadt_mod->GPE1_Block_Length);
866verbose("Converted ACPI V%d FADT to ACPI V4 FADT\n", (fadt) ? fadt->Revision : fadt->Revision);
867} else {
868
869if (fadt_file) {
870if (fadt_file->Length < 0x84 && fadt_rev2_needed)
871{
872fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(0x84);
873memcpy(fadt_mod, fadt_file, fadt_file->Length);
874fadt_mod->Length = 0x84;
875fadt_mod->Revision = 0x02; // FADT rev 2 (ACPI 1.0B MS extensions)
876} else {
877fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(fadt_file->Length);
878memcpy(fadt_mod, fadt_file, fadt_file->Length);
879}
880
881} else {
882if (fadt->Length < 0x84 && fadt_rev2_needed)
883{
884fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(0x84);
885memcpy(fadt_mod, fadt, fadt->Length);
886fadt_mod->Length = 0x84;
887fadt_mod->Revision = 0x02; // FADT rev 2 (ACPI 1.0B MS extensions)
888} else {
889fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(fadt->Length);
890memcpy(fadt_mod, fadt, fadt->Length);
891}
892
893}
894}
895
896uint8_t Type = PMProfileError;
897// Determine system type / PM_Model
898
899// Fix System-type if needed (should never happen)
900if (Platform->Type > MaxSupportedPMProfile)
901{
902if(fadt_mod->PM_Profile <= MaxSupportedPMProfile)
903Platform->Type = fadt_mod->PM_Profile; // get the fadt if correct
904else
905Platform->Type = 1;/* Set a fixed value (Desktop) */
906}
907
908// If needed, set System-type from PM_Profile (if valid) else set PM_Profile with a fixed the System-type
909// Give prior to the FADT pm profile, allow to also control this value with a patched FADT table
910if (fadt_mod->PM_Profile != Platform->Type)
911{
912bool val = false;
913getBoolForKey("PreferInternalProfileDetect", &val, &bootInfo->bootConfig); // if true Give prior to the profile resolved trought the CPU model
914
915if (fadt_mod->PM_Profile <= MaxSupportedPMProfile && !val) {
916Platform->Type = fadt_mod->PM_Profile;
917} else {
918fadt_mod->PM_Profile = Platform->Type;
919}
920
921}
922
923// Set PM_Profile and System-type if user wanted this value to be forced
924if ( (value=getStringForKey("SystemType", &bootInfo->bootConfig))!=NULL)
925if ((Type = (unsigned char) strtoul(value, NULL, 10) ) <= MaxSupportedPMProfile)
926{
927verbose("FADT: changing Preferred_PM_Profile from 0x%02x to 0x%02x\n", fadt->PM_Profile, Type);
928fadt_mod->PM_Profile = Platform->Type = Type;
929} else verbose("Error: system-type must be 0..6. Defaulting to %d !\n", Platform->Type);
930
931
932// Patch FADT to fix restart
933if (fix_restart)
934{
935fadt_mod->Flags|= 0x400;
936fadt_mod->RESET_REG = FillGASStruct(0x0cf9, 1);
937fadt_mod->Reset_Value = 0x06;
938verbose("FADT: Restart Fix applied !\n");
939}
940
941bool aspm = false;
942if (getBoolForKey(kEnableASPM, &aspm, &bootInfo->bootConfig) && aspm) {
943fadt_mod->Boot_Flags = 0x0000;
944}
945
946
947// Patch FACS Address
948if (new_facs) {
949fadt_mod->FIRMWARE_CTRL=(uint32_t)new_facs;
950if ((uint32_t)(&(fadt_mod->X_FIRMWARE_CTRL))-(uint32_t)fadt_mod+8<=fadt_mod->Length)
951fadt_mod->X_FIRMWARE_CTRL=(uint32_t)new_facs;
952Platform->hardware_signature = new_facs->hardware_signature;
953} else {
954fadt_mod->FIRMWARE_CTRL=(uint32_t)fadt->FIRMWARE_CTRL;
955if ((uint32_t)(&(fadt_mod->X_FIRMWARE_CTRL))-(uint32_t)fadt_mod+8<=fadt_mod->Length)
956fadt_mod->X_FIRMWARE_CTRL=(uint32_t)fadt->FIRMWARE_CTRL;
957
958Platform->hardware_signature = ((struct acpi_2_facs *)fadt->FIRMWARE_CTRL)->hardware_signature;
959}
960DBG("setting hardware_signature to %x \n",Platform->hardware_signature);
961
962
963
964// Patch DSDT Address if we have loaded a DSDT table
965if(new_dsdt)
966{
967
968fadt_mod->DSDT=(uint32_t)new_dsdt;
969if ((uint32_t)(&(fadt_mod->X_DSDT))-(uint32_t)fadt_mod+8<=fadt_mod->Length)
970fadt_mod->X_DSDT=(uint32_t)new_dsdt;
971
972}
973
974// Correct the checksum
975fadt_mod->Checksum=0;
976fadt_mod->Checksum=256-checksum8(fadt_mod,fadt_mod->Length);
977
978return fadt_mod;
979}
980
981static uint32_t const MACH_SIG_MP= 0x00000200;
982static uint32_t const MACH_SIG_ZERO= 0x00000000;
983
984struct acpi_2_facs* generate_facs(bool updatefacs)
985{
986struct acpi_2_facs *facs_mod=(struct acpi_2_facs *)AllocateKernelMemory(sizeof(struct acpi_2_facs));
987bzero(facs_mod, sizeof(struct acpi_2_facs));
988
989memcpy(facs_mod->Signature, "FACS", 4);
990facs_mod->Length = sizeof(struct acpi_2_facs);
991
992if (!gPlatformName)
993local_readSMBIOS(1);
994
995//TODO : populate
996if (strstr("MacPro", gPlatformName) == 0) {
997facs_mod->hardware_signature = MACH_SIG_MP;
998}
999else {
1000facs_mod->hardware_signature = MACH_SIG_ZERO;
1001}
1002facs_mod->firmware_waking_vector = 0;
1003facs_mod->global_lock = 0;
1004facs_mod->flags = 0;
1005facs_mod->x_firmware_waking_vector = 0;
1006
1007facs_mod->version = updatefacs; /* ACPI 1.0: 0, ACPI 2.0/3.0: 1, ACPI 4.0: 2 */
1008return facs_mod;
1009}
1010
1011/* Setup ACPI. Replace DSDT if DSDT.aml is found */
1012int setupAcpi(void)
1013{
1014int version;
1015void *new_dsdt=NULL, *new_hpet=NULL, *new_sbst=NULL, *new_ecdt=NULL, *new_asft=NULL, *new_dmar=NULL, *new_apic=NULL, *new_mcfg=NULL, *new_facs=NULL, *new_ssdts[14];
1016
1017struct acpi_2_ssdt *new_ssdt[17]; // 15 + 2 additional tables for pss & cst
1018struct acpi_2_fadt *fadt; // will be used in CST generator
1019
1020bool oem_facs=false, oem_dsdt=false, oem_ssdt=false, oem_hpet=false, oem_sbst=false, oem_ecdt=false, oem_asft=false, oem_dmar=false, oem_apic=false, oem_mcfg=false;
1021bool update_acpi=false, gen_xsdt=false;
1022bool hpet_replaced=false, sbst_replaced=false, ecdt_replaced=false, asft_replaced=false, dmar_replaced=false, apic_replaced=false, mcfg_replaced=false;
1023bool hpet_added=false, sbst_added=false, ecdt_added=false, asft_added=false, dmar_added=false, apic_added=false, mcfg_added=false;
1024bool gen_facs=false, gen_csta=false, gen_psta=false, speed_step=false;
1025
1026bool quick_ssdt= false;
1027// Quick ssdt search,
1028// first try to find ssdt-0.aml, if the file do not exist we
1029// stop searching here, else ssdt-0.aml is loaded and we try
1030// to find ssdt-1.aml, etc .........
1031
1032int curssdt=0, loadtotssdt=0, totssdt=0, newtotssdt=0;
1033
1034{
1035bool tmpval;
1036
1037oem_dsdt=getBoolForKey(kOEMDSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1038oem_ssdt=getBoolForKey(kOEMSSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1039oem_hpet=getBoolForKey(kOEMHPET, &tmpval, &bootInfo->bootConfig)&&tmpval;
1040oem_sbst=getBoolForKey(kOEMSBST, &tmpval, &bootInfo->bootConfig)&&tmpval;
1041oem_ecdt=getBoolForKey(kOEMECDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1042oem_asft=getBoolForKey(kOEMASFT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1043oem_dmar=getBoolForKey(kOEMDMAR, &tmpval, &bootInfo->bootConfig)&&tmpval;
1044oem_apic=getBoolForKey(kOEMAPIC, &tmpval, &bootInfo->bootConfig)&&tmpval;
1045oem_mcfg=getBoolForKey(kOEMMCFG, &tmpval, &bootInfo->bootConfig)&&tmpval;
1046oem_facs=getBoolForKey(kOEMFACS, &tmpval, &bootInfo->bootConfig)&&tmpval;
1047
1048gen_csta=getBoolForKey(kGenerateCStates, &tmpval, &bootInfo->bootConfig)&&tmpval;
1049gen_psta=getBoolForKey(kGeneratePStates, &tmpval, &bootInfo->bootConfig)&&tmpval;
1050gen_facs=getBoolForKey(kGenerateFACS, &tmpval, &bootInfo->bootConfig)&&tmpval;
1051
1052update_acpi=getBoolForKey(kUpdateACPI, &tmpval, &bootInfo->bootConfig)&&tmpval;
1053
1054quick_ssdt=getBoolForKey(kQSSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1055
1056speed_step=getBoolForKey(kSpeedstep, &tmpval, &bootInfo->bootConfig)&&tmpval;
1057
1058}
1059
1060if (speed_step) {
1061gen_psta= true;
1062gen_csta= true;
1063}
1064
1065// Load replacement ACPI tables
1066if (!oem_dsdt)
1067new_dsdt=loadACPITable(kDSDT);
1068
1069
1070if (!oem_hpet)
1071new_hpet=loadACPITable(kHPET);
1072
1073
1074if (!oem_sbst)
1075new_sbst=loadACPITable(kSBST);
1076
1077
1078if (!oem_ecdt)
1079new_ecdt=loadACPITable(kECDT);
1080
1081
1082if (!oem_asft)
1083new_asft=loadACPITable(kASFT);
1084
1085
1086if (!oem_dmar)
1087new_dmar=loadACPITable(kDMAR);
1088
1089
1090if (!oem_apic)
1091new_apic=loadACPITable(kAPIC);
1092
1093
1094if (!oem_mcfg)
1095new_mcfg=loadACPITable(kMCFG);
1096
1097if (!oem_facs)
1098new_facs=loadACPITable(kFACS);
1099
1100if (!new_facs && gen_facs) new_facs = generate_facs(update_acpi);
1101
1102
1103if (!oem_ssdt)
1104{
1105
1106for (curssdt=0;curssdt<15;curssdt++)
1107{
1108new_ssdt[curssdt]=loadSSDTTable(curssdt);
1109
1110if (new_ssdt[curssdt])
1111loadtotssdt++;
1112else if (quick_ssdt)
1113break;
1114
1115}
1116
1117curssdt=0;
1118
1119}
1120
1121DBG("New ACPI tables Loaded in memory\n");
1122TagPtr DropTables_p = XMLCastDict(XMLGetProperty(bootInfo->bootConfig.dictionary, (const char*)"ACPIDropTables"));
1123// Do the same procedure for both versions of ACPI
1124for (version=0; version<2; version++) {
1125struct acpi_2_rsdp *rsdp_mod, *rsdp_conv=(struct acpi_2_rsdp *)0;
1126struct acpi_2_rsdt *rsdt, *rsdt_mod;
1127struct acpi_2_xsdt *xsdt_conv = (struct acpi_2_xsdt *)0;
1128int rsdplength;
1129
1130// Find original rsdp
1131struct acpi_2_rsdp *rsdp=(struct acpi_2_rsdp *)(version?((struct acpi_2_rsdp *)(uint32_t)acpi20_p):((struct acpi_2_rsdp *)(uint32_t)acpi10_p));
1132
1133if ((update_acpi) && (rsdp->Revision == 0))
1134{
1135rsdp_conv = (struct acpi_2_rsdp *)AllocateKernelMemory(sizeof(struct acpi_2_rsdp));
1136memcpy(rsdp_conv, rsdp, 20);
1137
1138/* Add/change fields */
1139rsdp_conv->Revision = 2; /* ACPI version 3 */
1140rsdp_conv->Length = sizeof(struct acpi_2_rsdp);
1141
1142/* Correct checksums */
1143rsdp_conv->Checksum = 0;
1144rsdp_conv->Checksum = 256-checksum8(rsdp_conv, 20);
1145rsdp_conv->ExtendedChecksum = 0;
1146rsdp_conv->ExtendedChecksum = 256-checksum8(rsdp_conv, rsdp_conv->Length);
1147
1148rsdp = rsdp_conv;
1149
1150gen_xsdt = true;
1151version = 1;
1152
1153addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI");
1154
1155verbose("Converted ACPI RSD PTR version 1 to version 3\n");
1156}
1157if (!rsdp)
1158{
1159DBG("No ACPI version %d found. Ignoring\n", version+1);
1160if (version)
1161addConfigurationTable(&gEfiAcpi20TableGuid, NULL, "ACPI_20");
1162else
1163addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI");
1164continue;
1165}
1166rsdplength=version?rsdp->Length:20;
1167
1168DBG("RSDP version %d found @%x. Length=%d\n",version+1,rsdp,rsdplength);
1169
1170/* FIXME: no check that memory allocation succeeded
1171 * Copy and patch RSDP,RSDT, XSDT and FADT
1172 * For more info see ACPI Specification pages 110 and following
1173 */
1174
1175if (gen_xsdt)
1176{
1177rsdp_mod=rsdp_conv;
1178} else {
1179rsdp_mod=(struct acpi_2_rsdp *) AllocateKernelMemory(rsdplength);
1180memcpy(rsdp_mod, rsdp, rsdplength);
1181}
1182
1183rsdt=(struct acpi_2_rsdt *)(rsdp->RsdtAddress);
1184
1185DBG("RSDT @%x, Length %d\n",rsdt, rsdt->Length);
1186
1187if (rsdt && (uint32_t)rsdt !=0xffffffff && rsdt->Length<0x10000)
1188{
1189int dropoffset=0, i;
1190
1191rsdt_mod=(struct acpi_2_rsdt *)AllocateKernelMemory(rsdt->Length);
1192memcpy (rsdt_mod, rsdt, rsdt->Length);
1193rsdp_mod->RsdtAddress=(uint32_t)rsdt_mod;
1194
1195int rsdt_entries_num=(rsdt_mod->Length-sizeof(struct acpi_2_rsdt))/4;
1196uint32_t *rsdt_entries=(uint32_t *)(rsdt_mod+1);
1197
1198if (gen_xsdt)
1199{
1200xsdt_conv=(struct acpi_2_xsdt *)AllocateKernelMemory(sizeof(struct acpi_2_xsdt)+(rsdt_entries_num * 8));
1201memcpy(xsdt_conv, rsdt, sizeof(struct acpi_2_rsdt));
1202
1203xsdt_conv->Signature[0] = 'X';
1204xsdt_conv->Signature[1] = 'S';
1205xsdt_conv->Signature[2] = 'D';
1206xsdt_conv->Signature[3] = 'T';
1207xsdt_conv->Length = sizeof(struct acpi_2_xsdt)+(rsdt_entries_num * 8);
1208
1209uint64_t *xsdt_conv_entries=(uint64_t *)(xsdt_conv+1);
1210
1211for (i=0;i<rsdt_entries_num;i++)
1212{
1213xsdt_conv_entries[i] = (uint64_t)rsdt_entries[i];
1214}
1215
1216xsdt_conv->Checksum = 0;
1217xsdt_conv->Checksum = 256-checksum8(xsdt_conv, xsdt_conv->Length);
1218
1219rsdp->XsdtAddress = (uint32_t)xsdt_conv;
1220
1221rsdp->ExtendedChecksum = 0;
1222rsdp->ExtendedChecksum = 256-checksum8(rsdp, rsdp->Length);
1223
1224verbose("Converted RSDT table to XSDT table\n");
1225}
1226
1227for (i=0;i<rsdt_entries_num;i++)
1228{
1229char *table=(char *)(rsdt_entries[i]);
1230if (!table)
1231continue;
1232
1233DBG("TABLE %c%c%c%c,",table[0],table[1],table[2],table[3]);
1234
1235rsdt_entries[i-dropoffset]=rsdt_entries[i];
1236
1237char table4[4];
1238strlcpy(table4, table, sizeof(table4)+1);
1239TagPtr match_drop = XMLGetProperty(DropTables_p, (const char*)table4);
1240if ( match_drop ) {
1241char *tmpstr = XMLCastString(match_drop);
1242if (strcmp(tmpstr,"No") != 0) {
1243dropoffset++;
1244DBG("%s table dropped\n",table4);
1245continue;
1246}
1247}
1248
1249if ((!(oem_hpet)) && tableSign(table, "HPET"))
1250{
1251DBG("HPET found\n");
1252if (new_hpet)
1253{
1254rsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
1255hpet_replaced=true;
1256}
1257continue;
1258}
1259if ((!(oem_sbst)) && tableSign(table, "SBST"))
1260{
1261DBG("SBST found\n");
1262if (new_sbst)
1263{
1264rsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
1265sbst_replaced=true;
1266}
1267continue;
1268}
1269if ((!(oem_ecdt)) && tableSign(table, "ECDT"))
1270{
1271DBG("ECDT found\n");
1272
1273if (new_ecdt)
1274{
1275rsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
1276ecdt_replaced=true;
1277}
1278
1279continue;
1280}
1281if ((!(oem_asft)) && tableSign(table, "ASF!"))
1282{
1283DBG("ASF! found\n");
1284if (new_asft)
1285{
1286rsdt_entries[i-dropoffset]=(uint32_t)new_asft;
1287asft_replaced=true;
1288}
1289continue;
1290}
1291if ((!(oem_dmar)) && tableSign(table, "DMAR"))
1292{
1293DBG("DMAR found\n");
1294if (new_dmar)
1295{
1296rsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
1297dmar_replaced=true;
1298}
1299continue;
1300}
1301if ((!(oem_apic)) && tableSign(table, "APIC"))
1302{
1303DBG("APIC found\n");
1304if (new_apic)
1305{
1306rsdt_entries[i-dropoffset]=(uint32_t)new_apic;
1307apic_replaced=true;
1308}
1309continue;
1310}
1311if ((!(oem_mcfg)) && tableSign(table, "MCFG"))
1312{
1313DBG("MCFG found\n");
1314if (new_mcfg)
1315{
1316rsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
1317mcfg_replaced=true;
1318}
1319continue;
1320}
1321if ((!(oem_ssdt)) && tableSign(table, "SSDT"))
1322{
1323DBG("SSDT %d found", curssdt);
1324if (new_ssdts[curssdt])
1325{
1326DBG(" and replaced");
1327rsdt_entries[i-dropoffset]=(uint32_t)new_ssdts[curssdt];
1328totssdt++;
1329}
1330DBG("\n");
1331curssdt++;
1332continue;
1333}
1334if ((!(oem_dsdt)) && tableSign(table, "DSDT"))
1335{
1336DBG("DSDT found\n");
1337rsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;
1338continue;
1339}
1340if (tableSign(table, "FACP"))
1341{
1342fadt=(struct acpi_2_fadt *)rsdt_entries[i];
1343
1344DBG("FADT found @%x, Length %d\n",fadt, fadt->Length);
1345
1346if (!fadt || (uint32_t)fadt == 0xffffffff || fadt->Length>0x10000)
1347{
1348printf("FADT incorrect. Not modified\n");
1349continue;
1350}
1351verbose("Attempting to patch FADT entry of RSDT\n");
1352struct acpi_2_fadt *fadt_mod = patch_fadt(fadt, new_facs, new_dsdt, update_acpi);
1353
1354rsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;
1355
1356if (!oem_ssdt)
1357{
1358// Generate _CST SSDT
1359if ( gen_csta && (new_ssdt[loadtotssdt] = generate_cst_ssdt(fadt_mod)))
1360{
1361gen_csta= false;
1362loadtotssdt++;
1363}
1364
1365// Generating _PSS SSDT
1366 if (gen_psta && (new_ssdt[loadtotssdt] = generate_pss_ssdt((void*)fadt_mod->DSDT)))
1367 {
1368 gen_psta= false;
1369 loadtotssdt++;
1370 }
1371
1372}
1373
1374continue;
1375}
1376}
1377DBG("\n");
1378
1379if ((!oem_hpet) && (!hpet_replaced))
1380{
1381if (new_hpet)
1382{
1383rsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
1384hpet_added=true;
1385i++;
1386}
1387}
1388
1389if ((!oem_sbst) && (!sbst_replaced))
1390{
1391if (new_sbst)
1392{
1393rsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
1394sbst_added=true;
1395i++;
1396}
1397}
1398
1399if ((!oem_ecdt) && (!ecdt_replaced))
1400{
1401if (new_ecdt)
1402{
1403rsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
1404ecdt_added=true;
1405i++;
1406}
1407}
1408
1409if ((!oem_asft) && (!asft_replaced))
1410{
1411if (new_asft)
1412{
1413rsdt_entries[i-dropoffset]=(uint32_t)new_asft;
1414asft_added=true;
1415i++;
1416}
1417}
1418
1419if ((!oem_dmar) && (!dmar_replaced))
1420{
1421if (new_dmar)
1422{
1423rsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
1424dmar_added=true;
1425i++;
1426}
1427}
1428
1429if ((!oem_apic) && (!apic_replaced))
1430{
1431if (new_apic)
1432{
1433rsdt_entries[i-dropoffset]=(uint32_t)new_apic;
1434apic_added=true;
1435i++;
1436}
1437}
1438
1439if ((!oem_mcfg) && (!mcfg_replaced))
1440{
1441if (new_mcfg)
1442{
1443rsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
1444mcfg_added=true;
1445i++;
1446}
1447}
1448
1449if (!oem_ssdt)
1450{
1451while ((totssdt < loadtotssdt) && (curssdt < 17))
1452{
1453if (new_ssdt[curssdt])
1454{
1455DBG("adding SSDT %d\n", curssdt);
1456rsdt_entries[i-dropoffset]=(uint32_t)new_ssdt[curssdt];
1457totssdt++;
1458newtotssdt++;
1459i++;
1460} else if (quick_ssdt) {
1461break;
1462}
1463
1464curssdt++;
1465}
1466}
1467
1468// Correct the checksum of RSDT
1469rsdt_mod->Length-=4*dropoffset;
1470rsdt_mod->Length+=4*newtotssdt;
1471if (hpet_added)
1472rsdt_mod->Length+=4;
1473if (sbst_added)
1474rsdt_mod->Length+=4;
1475if (ecdt_added)
1476rsdt_mod->Length+=4;
1477if (asft_added)
1478rsdt_mod->Length+=4;
1479if (dmar_added)
1480rsdt_mod->Length+=4;
1481if (apic_added)
1482rsdt_mod->Length+=4;
1483if (mcfg_added)
1484rsdt_mod->Length+=4;
1485
1486DBG("RSDT: Original checksum %d, ", rsdt_mod->Checksum);
1487
1488rsdt_mod->Checksum=0;
1489rsdt_mod->Checksum=256-checksum8(rsdt_mod,rsdt_mod->Length);
1490
1491DBG("New checksum %d at %x\n", rsdt_mod->Checksum,rsdt_mod);
1492
1493}
1494else
1495{
1496rsdp_mod->RsdtAddress=0;
1497printf("RSDT not found or RSDT incorrect\n");
1498}
1499
1500if (version)
1501{
1502struct acpi_2_xsdt *xsdt, *xsdt_mod;
1503
1504// FIXME: handle 64-bit address correctly
1505
1506if (gen_xsdt)
1507xsdt=xsdt_conv;
1508else
1509xsdt=(struct acpi_2_xsdt*) ((uint32_t)rsdp->XsdtAddress);
1510
1511DBG("XSDT @%x;%x, Length=%d\n", (uint32_t)(rsdp->XsdtAddress>>32),(uint32_t)rsdp->XsdtAddress,
1512xsdt->Length);
1513if (xsdt && (uint64_t)rsdp->XsdtAddress<0xffffffff && xsdt->Length<0x10000)
1514{
1515int dropoffset=0, i;
1516curssdt=0, totssdt=0, newtotssdt=0;
1517hpet_replaced=false, hpet_added=false;
1518sbst_replaced=false, sbst_added=false;
1519ecdt_replaced=false, ecdt_added=false;
1520asft_replaced=false, asft_added=false;
1521dmar_replaced=false, dmar_added=false;
1522apic_replaced=false, apic_added=false;
1523mcfg_replaced=false, mcfg_added=false;
1524
1525if (gen_xsdt)
1526xsdt_mod=xsdt;
1527else
1528{
1529xsdt_mod=(struct acpi_2_xsdt*)AllocateKernelMemory(xsdt->Length);
1530memcpy(xsdt_mod, xsdt, xsdt->Length);
1531}
1532
1533rsdp_mod->XsdtAddress=(uint32_t)xsdt_mod;
1534int xsdt_entries_num=(xsdt_mod->Length-sizeof(struct acpi_2_xsdt))/8;
1535uint64_t *xsdt_entries=(uint64_t *)(xsdt_mod+1);
1536for (i=0;i<xsdt_entries_num;i++)
1537{
1538char *table=(char *)((uint32_t)(xsdt_entries[i]));
1539if (!table)
1540continue;
1541
1542xsdt_entries[i-dropoffset]=xsdt_entries[i];
1543
1544char table4[4];
1545strlcpy(table4, table, sizeof(table4)+1);
1546TagPtr match_drop = XMLGetProperty(DropTables_p, (const char*)table4);
1547if ( match_drop ) {
1548char *tmpstr = XMLCastString(match_drop);
1549if (strcmp(tmpstr,"No") != 0) {
1550dropoffset++;
1551DBG("%s table dropped\n",table4);
1552continue;
1553}
1554}
1555
1556if ((!(oem_hpet)) && tableSign(table, "HPET"))
1557{
1558DBG("HPET found\n");
1559if (new_hpet)
1560{
1561xsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
1562hpet_replaced=true;
1563}
1564continue;
1565}
1566if ((!(oem_sbst)) && tableSign(table, "SBST"))
1567{
1568DBG("SBST found\n");
1569if (new_sbst)
1570{
1571xsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
1572sbst_replaced=true;
1573}
1574continue;
1575}
1576if ((!(oem_ecdt)) && tableSign(table, "ECDT"))
1577{
1578DBG("ECDT found\n");
1579
1580if (new_ecdt)
1581{
1582xsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
1583ecdt_replaced=true;
1584}
1585
1586continue;
1587}
1588if ((!(oem_asft)) && tableSign(table, "ASF!"))
1589{
1590DBG("ASF! found\n");
1591if (new_asft)
1592{
1593xsdt_entries[i-dropoffset]=(uint32_t)new_asft;
1594asft_replaced=true;
1595}
1596continue;
1597}
1598if ((!(oem_dmar)) && tableSign(table, "DMAR"))
1599{
1600DBG("DMAR found\n");
1601if (new_dmar)
1602{
1603xsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
1604dmar_replaced=true;
1605}
1606continue;
1607}
1608if ((!(oem_apic)) && tableSign(table, "APIC"))
1609{
1610DBG("APIC found\n");
1611if (new_apic)
1612{
1613xsdt_entries[i-dropoffset]=(uint32_t)new_apic;
1614apic_replaced=true;
1615}
1616continue;
1617}
1618if ((!(oem_mcfg)) && tableSign(table, "MCFG"))
1619{
1620DBG("MCFG found\n");
1621if (new_mcfg)
1622{
1623xsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
1624mcfg_replaced=true;
1625}
1626continue;
1627}
1628if ((!(oem_ssdt)) && tableSign(table, "SSDT"))
1629{
1630DBG("SSDT %d found", curssdt);
1631if (new_ssdts[curssdt])
1632{
1633DBG(" and replaced");
1634xsdt_entries[i-dropoffset]=(uint32_t)new_ssdts[curssdt];
1635totssdt++;
1636}
1637DBG("\n");
1638curssdt++;
1639continue;
1640}
1641if ((!(oem_dsdt)) && tableSign(table, "DSDT"))
1642{
1643DBG("DSDT found\n");
1644
1645xsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;
1646
1647DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
1648
1649continue;
1650
1651}
1652if (tableSign(table, "FACP"))
1653{
1654fadt=(struct acpi_2_fadt *)(uint32_t)xsdt_entries[i];
1655
1656DBG("FADT found @%x,%x, Length %d\n",(uint32_t)(xsdt_entries[i]>>32),fadt,
1657fadt->Length);
1658
1659if (!fadt || (uint64_t)xsdt_entries[i] >= 0xffffffff || fadt->Length>0x10000)
1660{
1661verbose("FADT incorrect or after 4GB. Dropping XSDT\n");
1662goto drop_xsdt;
1663}
1664verbose("Attempting to patch FADT entry of XSDT\n");
1665struct acpi_2_fadt *fadt_mod = patch_fadt(fadt, new_facs, new_dsdt, update_acpi);
1666
1667
1668xsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;
1669
1670DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
1671
1672if (!oem_ssdt)
1673 {
1674 // Generate _CST SSDT
1675 if ( gen_csta && (new_ssdt[loadtotssdt] = generate_cst_ssdt(fadt_mod)))
1676 {
1677gen_csta= false;
1678loadtotssdt++;
1679 }
1680
1681 // Generating _PSS SSDT
1682 if (gen_psta && (new_ssdt[loadtotssdt] = generate_pss_ssdt((void*)fadt_mod->DSDT)))
1683 {
1684gen_psta= false;
1685loadtotssdt++;
1686 }
1687 }
1688
1689
1690continue;
1691}
1692
1693DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
1694
1695}
1696
1697if ((!oem_hpet) && (!hpet_replaced))
1698{
1699if (new_hpet)
1700{
1701xsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
1702hpet_added=true;
1703i++;
1704}
1705}
1706
1707if ((!oem_sbst) && (!sbst_replaced))
1708{
1709if (new_sbst)
1710{
1711xsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
1712sbst_added=true;
1713i++;
1714}
1715}
1716
1717if ((!oem_ecdt) && (!ecdt_replaced))
1718{
1719if (new_ecdt)
1720{
1721
1722xsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
1723ecdt_added=true;
1724i++;
1725}
1726}
1727
1728if ((!oem_asft) && (!asft_replaced))
1729{
1730if (new_asft)
1731{
1732xsdt_entries[i-dropoffset]=(uint32_t)new_asft;
1733asft_added=true;
1734i++;
1735}
1736}
1737
1738if ((!oem_dmar) && (!dmar_replaced))
1739{
1740if (new_dmar)
1741{
1742xsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
1743dmar_added=true;
1744i++;
1745}
1746}
1747
1748if ((!oem_apic) && (!apic_replaced))
1749{
1750if (new_apic)
1751{
1752xsdt_entries[i-dropoffset]=(uint32_t)new_apic;
1753apic_added=true;
1754i++;
1755}
1756}
1757
1758if ((!oem_mcfg) && (!mcfg_replaced))
1759{
1760if (new_mcfg)
1761{
1762xsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
1763mcfg_added=true;
1764i++;
1765}
1766}
1767
1768if (!oem_ssdt)
1769{
1770while ((totssdt < loadtotssdt) && (curssdt < 17))
1771{
1772if (new_ssdt[curssdt])
1773{
1774DBG("adding SSDT %d\n", curssdt);
1775xsdt_entries[i-dropoffset]=(uint32_t)new_ssdt[curssdt];
1776totssdt++;
1777newtotssdt++;
1778i++;
1779} else if (quick_ssdt){
1780break;
1781}
1782
1783curssdt++;
1784}
1785}
1786
1787// Correct the checksum of XSDT
1788xsdt_mod->Length-=8*dropoffset;
1789xsdt_mod->Length+=8*newtotssdt;
1790if (hpet_added)
1791xsdt_mod->Length+=8;
1792if (sbst_added)
1793xsdt_mod->Length+=8;
1794if (ecdt_added)
1795xsdt_mod->Length+=8;
1796if (asft_added)
1797xsdt_mod->Length+=8;
1798if (dmar_added)
1799xsdt_mod->Length+=8;
1800if (apic_added)
1801xsdt_mod->Length+=8;
1802if (mcfg_added)
1803xsdt_mod->Length+=8;
1804
1805xsdt_mod->Checksum=0;
1806xsdt_mod->Checksum=256-checksum8(xsdt_mod,xsdt_mod->Length);
1807}
1808else
1809{
1810drop_xsdt:
1811
1812DBG("About to drop XSDT\n");
1813
1814/*FIXME: Now we just hope that if MacOS doesn't find XSDT it reverts to RSDT.
1815 * A Better strategy would be to generate
1816 */
1817
1818rsdp_mod->XsdtAddress=0xffffffffffffffffLL;
1819verbose("XSDT not found or XSDT incorrect\n");
1820}
1821}
1822
1823// Correct the checksum of RSDP
1824
1825DBG("RSDP: Original checksum %d, ", rsdp_mod->Checksum);
1826
1827rsdp_mod->Checksum=0;
1828rsdp_mod->Checksum=256-checksum8(rsdp_mod,20);
1829
1830DBG("New checksum %d\n", rsdp_mod->Checksum);
1831
1832if (version)
1833{
1834DBG("RSDP: Original extended checksum %d", rsdp_mod->ExtendedChecksum);
1835
1836rsdp_mod->ExtendedChecksum=0;
1837rsdp_mod->ExtendedChecksum=256-checksum8(rsdp_mod,rsdp_mod->Length);
1838
1839DBG("New extended checksum %d\n", rsdp_mod->ExtendedChecksum);
1840
1841}
1842
1843verbose("Patched ACPI version %d\n", version+1);
1844if (version)
1845{
1846/* XXX aserebln why uint32 cast if pointer is uint64 ? */
1847acpi20_p = (uint32_t)rsdp_mod;
1848addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
1849}
1850else
1851{
1852/* XXX aserebln why uint32 cast if pointer is uint64 ? */
1853acpi10_p = (uint32_t)rsdp_mod;
1854addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
1855}
1856}
1857#if DEBUG_DSDT
1858printf("Press a key to continue... (DEBUG_DSDT)\n");
1859getc();
1860#endif
1861return 1;
1862
1863}

Archive Download this file

Revision: 789