Chameleon

Chameleon Svn Source Tree

Root/branches/valv/i386/libsaio/acpi_patcher.c

  • Property svn:executable set to
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
28uint64_t acpi10_p;
29uint64_t acpi20_p;
30
31/* Gets the ACPI 1.0 RSDP address */
32static struct acpi_2_rsdp* getAddressOfAcpiTable()
33{
34 /* TODO: Before searching the BIOS space we are supposed to search the first 1K of the EBDA */
35
36 void *acpi_addr = (void*)ACPI_RANGE_START;
37 for(; acpi_addr <= (void*)ACPI_RANGE_END; acpi_addr += 16)
38 {
39 if(*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE)
40 {
41 uint8_t csum = checksum8(acpi_addr, 20);
42 if(csum == 0)
43 {
44 // Only return the table if it is a true version 1.0 table (Revision 0)
45 if(((struct acpi_2_rsdp*)acpi_addr)->Revision == 0)
46 return acpi_addr;
47 }
48 }
49 }
50 return NULL;
51}
52
53/* Gets the ACPI 2.0 RSDP address */
54static struct acpi_2_rsdp* getAddressOfAcpi20Table()
55{
56 /* TODO: Before searching the BIOS space we are supposed to search the first 1K of the EBDA */
57
58 void *acpi_addr = (void*)ACPI_RANGE_START;
59 for(; acpi_addr <= (void*)ACPI_RANGE_END; acpi_addr += 16)
60 {
61 if(*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE)
62 {
63 uint8_t csum = checksum8(acpi_addr, 20);
64
65 /* Only assume this is a 2.0 or better table if the revision is greater than 0
66 * NOTE: ACPI 3.0 spec only seems to say that 1.0 tables have revision 1
67 * and that the current revision is 2.. I am going to assume that rev > 0 is 2.0.
68 */
69
70 if(csum == 0 && (((struct acpi_2_rsdp*)acpi_addr)->Revision > 0))
71 {
72 uint8_t csum2 = checksum8(acpi_addr, sizeof(struct acpi_2_rsdp));
73 if(csum2 == 0)
74 return acpi_addr;
75 }
76 }
77 }
78 return NULL;
79}
80
81/* The folowing ACPI Table search algo. should be reused anywhere needed:*/
82int search_and_get_acpi_fd(const char * filename, const char ** outDirspec)
83{
84int fd=0;
85const char * overriden_pathname=NULL;
86static char dirspec[512]="";
87int len=0;
88
89// Take in accound user overriding if it's DSDT only
90if (strstr(filename, "DSDT") &&
91getValueForKey(kDSDT, &overriden_pathname, &len, &bootInfo->bootConfig))
92 {
93sprintf(dirspec, "%s", overriden_pathname); // start searching root
94fd=open (dirspec,0);
95if (fd>=0) goto success_fd;
96 }
97
98// Start searching any potential location for ACPI Table
99sprintf(dirspec, "/%s", filename); // start searching root
100fd=open (dirspec,0);
101if (fd>=0) goto success_fd;
102
103sprintf(dirspec, "%s", filename); // start current dir
104fd=open (dirspec,0);
105if (fd>=0) goto success_fd;
106
107sprintf(dirspec,"/Extra/%s",filename);
108fd=open (dirspec,0);
109if (fd>=0) goto success_fd;
110
111sprintf(dirspec,"bt(0,0)/Extra/%s",filename);
112fd=open (dirspec,0);
113if (fd>=0) goto success_fd;
114
115// NOT FOUND:
116//verbose("ACPI Table not found: %s\n", filename);
117if (outDirspec) *outDirspec = "";
118return -1;
119// FOUND
120success_fd:
121if (outDirspec) *outDirspec = dirspec;
122return fd;
123}
124
125void *loadACPITable(char *key)
126{
127void *tableAddr;
128int fd = -1;
129char dirspec[512];
130char filename[512];
131const char * overriden_pathname=NULL;
132int len=0;
133
134sprintf(filename, "%s.aml", key);
135
136// Checking boot partition
137
138// Rek: if user specified a full path name then take it in consideration
139if (getValueForKey(key, &overriden_pathname, &len, &bootInfo->bootConfig))
140{
141sprintf(dirspec, "%s", overriden_pathname); // start searching root
142//printf("Using custom %s path %s\n", key, dirspec);
143//getc();
144}
145else
146sprintf(dirspec, "/%s", filename); // start searching root
147
148fd=open (dirspec,0);
149
150if (fd<0)
151{// Check Extra on booting partition
152 //verbose("Searching for %s.aml file ...\n", key);
153sprintf(dirspec,"/Extra/%s",filename);
154fd=open (dirspec,0);
155if (fd<0)
156{// Fall back to booter partition
157sprintf(dirspec,"bt(0,0)/Extra/%s",filename);
158fd=open (dirspec,0);
159if (fd<0)
160{
161//verbose("ACPI Table not found: %s\n", filename);
162return NULL;
163}
164}
165}
166
167tableAddr=(void*)AllocateKernelMemory(file_size (fd));
168if (tableAddr)
169{
170if (read (fd, tableAddr, file_size (fd))!=file_size (fd))
171{
172printf("Couldn't read table %s\n",dirspec);
173free (tableAddr);
174close (fd);
175return NULL;
176}
177
178DBG("Table %s read and stored at: %x\n", dirspec, tableAddr);
179close (fd);
180return tableAddr;
181}
182
183printf("Couldn't allocate memory for table %s\n", dirspec);
184close (fd);
185
186return NULL;
187}
188
189uint8_tacpi_cpu_count = 0;
190char* acpi_cpu_name[32];
191
192void get_acpi_cpu_names(unsigned char* dsdt, uint32_t length)
193{
194uint32_t i;
195
196for (i=0; i<length-7; i++)
197{
198if (dsdt[i] == 0x5B && dsdt[i+1] == 0x83) // ProcessorOP
199{
200uint32_t offset = i + 3 + (dsdt[i+2] >> 6);
201
202bool add_name = true;
203
204uint8_t j;
205
206for (j=0; j<4; j++)
207{
208char c = dsdt[offset+j];
209
210if (!aml_isvalidchar(c))
211{
212add_name = false;
213verbose("Invalid character found in ProcessorOP 0x%x!\n", c);
214break;
215}
216}
217
218if (add_name)
219{
220acpi_cpu_name[acpi_cpu_count] = malloc(4);
221memcpy(acpi_cpu_name[acpi_cpu_count], dsdt+offset, 4);
222i = offset + 5;
223
224verbose("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]);
225
226if (++acpi_cpu_count == 32) return;
227}
228}
229}
230}
231
232struct acpi_2_ssdt *generate_cst_ssdt(struct acpi_2_fadt* fadt)
233{
234char ssdt_header[] =
235{
2360x53, 0x53, 0x44, 0x54, 0xE7, 0x00, 0x00, 0x00, /* SSDT.... */
2370x01, 0x17, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x41, /* ..PmRefA */
2380x43, 0x70, 0x75, 0x43, 0x73, 0x74, 0x00, 0x00, /* CpuCst.. */
2390x00, 0x10, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* ....INTL */
2400x31, 0x03, 0x10, 0x20 /* 1.._*/
241};
242
243char cstate_resource_template[] =
244{
2450x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00, 0x7F,
2460x01, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
2470x00, 0x00, 0x00, 0x79, 0x00
248};
249
250if (Platform.CPU.Vendor != 0x756E6547) {
251verbose ("C-States: Not an Intel platform !!!\n");
252return NULL;
253}
254
255if (fadt == NULL) {
256verbose ("C-States: FACP not found !!!\n");
257return NULL;
258}
259
260struct acpi_2_dsdt* dsdt = (void*)fadt->DSDT;
261
262if (dsdt == NULL) {
263verbose ("C-States: DSDT not found !!!\n");
264return NULL;
265}
266
267if (acpi_cpu_count == 0)
268get_acpi_cpu_names((void*)dsdt, dsdt->Length);
269
270if (acpi_cpu_count > 0)
271{
272//valv: c2 & c3 are enabled by default; else don't use EnableCStates
273bool c2_enabled, c3_enabled, c4_enabled, c6_enabled, tmpval2, tmpval3, tmpval4, tmpval6;
274c2_enabled = c3_enabled = c4_enabled = c6_enabled = false;
275unsigned char cstates_count;
276
277c2_enabled = (getBoolForKey(kEnableC2State, &tmpval2, &bootInfo->bootConfig)&&tmpval2) | (fadt->P_LVL2_LAT < 100);
278c3_enabled = (getBoolForKey(kEnableC3State, &tmpval3, &bootInfo->bootConfig)&&tmpval3) | (fadt->P_LVL2_LAT < 1000);
279c4_enabled = getBoolForKey(kEnableC4State, &tmpval4, &bootInfo->bootConfig)&&tmpval4;
280c6_enabled = getBoolForKey(kEnableC6State, &tmpval6, &bootInfo->bootConfig)&&tmpval6;
281
282if(c6_enabled) c4_enabled = true;
283if(c4_enabled) c3_enabled = true;
284if(c3_enabled) c2_enabled = true;
285
286if(Platform.CPU.Family == 0x06)
287{
288int intelCPU = Platform.CPU.Model;
289switch (intelCPU)
290{
291case 0x0C:
292if (strstr(Platform.CPU.BrandString, "Atom")) goto ncst_atm;
293case 0x0F: // Core (65nm)
294case 0x1A: // Core i7, Xeon 5500 series - Bloomfield, Gainstown NHM-EP - LGA1366 (45nm)
295case 0x1E: // Core i5, i7 - Clarksfield, Lynnfield, Jasper Forest - LGA1156 (45nm)
296case 0x1F: // Core i5, i7 - Nehalem
297case 0x25: // Core i3, i5, i7 - Westmere Client - Clarkdale, Arrandale - LGA1156 (32nm)
298case 0x2C: // Core i7 - Westmere EP - Gulftown - LGA1366 (32nm) 6 Core
299case 0x2E: // Westmere-Ex Xeon
300case 0x2F: // Westmere-Ex Xeon - Eagelton
301cstates_count = 1 + (c2_enabled ? 1 : 0) + (c3_enabled ? 1 : 0);
302verbose("C-State: Adding %d states: ", cstates_count);
303break;
304case 0x1C: // Atom (45nm)
305case 0x26: // Atom Lincroft
306ncst_atm:
307cstates_count = 1 + (c2_enabled ? 1 : 0) + (c4_enabled ? 1 : 0) + (c6_enabled ? 1 : 0);
308verbose("C-State: Adding %d states: ", cstates_count);
309break;
310case 0x17:
311cstates_count = 1 + (c2_enabled ? 1 : 0) + (c3_enabled ? 1 : 0) + (c4_enabled ? 1 : 0) + (c6_enabled ? 1 : 0);
312verbose("C-State: Adding %d states: ", cstates_count);
313break;
314default:
315cstates_count = 1 + (c2_enabled ? 1 : 0) + (c3_enabled ? 1 : 0) + (c4_enabled ? 1 : 0);
316break;
317}
318}
319else cstates_count = 1 + (c2_enabled ? 1 : 0) + (c3_enabled ? 1 : 0) + (c4_enabled ? 1 : 0);
320
321struct aml_chunk* root = aml_create_node(NULL);
322aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header
323struct aml_chunk* scop = aml_add_scope(root, "\\_PR_");
324
325struct aml_chunk* name_csd = aml_add_name(scop, "CSD_");
326struct aml_chunk* pack_csd = aml_add_package(name_csd);
327struct aml_chunk* csd = aml_add_package(pack_csd);
328aml_add_byte(csd, 0x05);
329aml_add_byte(csd, 0x00);
330aml_add_dword(csd, 0x00);
331aml_add_dword(csd, 0xfd);
332aml_add_dword(csd, Platform.CPU.NoCores);
333
334struct aml_chunk* name = aml_add_name(scop, "CST_");
335struct aml_chunk* pack = aml_add_package(name);
336aml_add_byte(pack, cstates_count);
337struct aml_chunk* tmpl = aml_add_package(pack);
338
339switch (Platform.CPU.Family) {
340case 0x06:
341{
342switch (Platform.CPU.Model)
343{
344case 0x0C:
345if (strstr(Platform.CPU.BrandString, "Atom")) goto cst_atm;
346case 0x0F: // Core (65nm)
347case 0x1A: // Core i7, Xeon 5500 series - Bloomfield, Gainstown NHM-EP - LGA1366 (45nm)
348case 0x1E: // Core i5, i7 - Clarksfield, Lynnfield, Jasper Forest - LGA1156 (45nm)
349case 0x1F: // Core i5, i7 - Nehalem
350case 0x25: // Core i3, i5, i7 - Westmere Client - Clarkdale, Arrandale - LGA1156 (32nm)
351case 0x2C: // Core i7 - Westmere EP - Gulftown - LGA1366 (32nm) 6 Core
352case 0x2E: // Westmere-Ex Xeon
353case 0x2F: // Westmere-Ex Xeon - Eagelton
354
355// C1
356cstate_resource_template[11] = 0x00; // C1-Nehalem
357aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
358aml_add_byte(tmpl, 0x01); // C1
359aml_add_byte(tmpl, 0x03); // Latency
360aml_add_word(tmpl, 0x03e8); // Power
361verbose ("C1 ");
362
363// C2
364if (c2_enabled)
365{
366tmpl = aml_add_package(pack);
367cstate_resource_template[11] = 0x10; // C3-Nehalem
368aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
369aml_add_byte(tmpl, 0x02); // C2
370aml_add_byte(tmpl, 0x14); // Latency
371aml_add_word(tmpl, 0x01f4); // Power
372verbose ("C3 ");
373}
374
375// C3
376if (c3_enabled)
377{
378tmpl = aml_add_package(pack);
379cstate_resource_template[11] = 0x20; // C6-Nehalem
380aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
381aml_add_byte(tmpl, 0x03); // C3
382aml_add_word(tmpl, 0xc8); // Latency
383aml_add_word(tmpl, 0x015e); // Power
384verbose ("C6");
385}
386//verbose("\n");
387
388break;
389
390case 0x1C: // Atom (45nm)
391//valv: was 0x26 ??? rely on cpu.c & smbios_patcher.c
392case 0x27: // Atom Lincroft
393cst_atm:
394// C1
395cstate_resource_template[11] = 0x00; // C1-Atom
396aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
397aml_add_byte(tmpl, 0x01); // C1
398aml_add_byte(tmpl, 0x01); // Latency
399aml_add_word(tmpl, 0x03e8); // Power
400verbose ("C1 ");
401
402// C2
403if (c2_enabled)
404{
405tmpl = aml_add_package(pack);
406cstate_resource_template[11] = 0x10; // C2-Atom
407aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
408aml_add_byte(tmpl, 0x02); // C2
409aml_add_byte(tmpl, fadt->P_LVL2_LAT); // Latency
410aml_add_word(tmpl, 0x01f4); // Power
411verbose ("C2 ");
412}
413
414// C3
415/*if (c3_enabled)
416{
417tmpl = aml_add_package(pack);
418cstate_resource_template[11] = 0x20; // C3-Atom
419aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
420aml_add_byte(tmpl, 0x03); // C3
421aml_add_word(tmpl, fadt->P_LVL3_LAT); // Latency
422aml_add_word(tmpl, 0x015e); // Power
423verbose ("C-State: Added C3\n");
424}*/
425
426// C4
427if (c4_enabled)
428{
429tmpl = aml_add_package(pack);
430cstate_resource_template[11] = 0x30; // C4-Atom
431aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
432aml_add_byte(tmpl, 0x03); // C4
433aml_add_word(tmpl, 0x64); // Latency
434aml_add_word(tmpl, 0x00fa); // Power
435verbose ("C4 ");
436}
437
438// C6
439if (c6_enabled)
440{
441tmpl = aml_add_package(pack);
442cstate_resource_template[11] = 0x40; // C6-Atom
443aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
444aml_add_byte(tmpl, 0x03); // C6
445aml_add_word(tmpl, 0xC8); // Latency
446aml_add_word(tmpl, 0x0096); // Power
447verbose ("C6 ");
448}
449//verbose("\n");
450
451break;
452
453case 0x17:
454default:
455
456// C1
457cstate_resource_template[11] = 0x00; // C1
458aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
459aml_add_byte(tmpl, 0x01); // C1
460aml_add_byte(tmpl, 0x01); // Latency
461aml_add_word(tmpl, 0x03e8); // Power 1000
462verbose ("C1 ");
463
464// C2
465if (c2_enabled)
466{
467tmpl = aml_add_package(pack);
468cstate_resource_template[11] = 0x10; // C2
469aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
470aml_add_byte(tmpl, 0x02); // C2
471aml_add_byte(tmpl, 0x14); // Latency 20
472aml_add_word(tmpl, 0x01f4); // Power 500
473verbose ("C2 ");
474}
475
476// C3
477if (c3_enabled)
478{
479tmpl = aml_add_package(pack);
480cstate_resource_template[11] = 0x20; // C3
481aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
482aml_add_byte(tmpl, 0x03); // C3
483aml_add_word(tmpl, 0x28); // Latency 40
484aml_add_word(tmpl, 0x015e); // Power 350
485verbose ("C3 ");
486}
487
488// C4
489if (c4_enabled)
490{
491tmpl = aml_add_package(pack);
492cstate_resource_template[11] = 0x30; // C4
493aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
494aml_add_byte(tmpl, 0x03); // C4
495aml_add_word(tmpl, 0x64); // Latency 100
496aml_add_word(tmpl, 0x00fa); // Power 250
497verbose ("C4 ");
498}
499
500// C6
501if (c6_enabled)
502{
503tmpl = aml_add_package(pack);
504cstate_resource_template[11] = 0x40; // C6
505aml_add_buffer(tmpl, cstate_resource_template, sizeof(cstate_resource_template));
506aml_add_byte(tmpl, 0x03); // C6
507aml_add_word(tmpl, 0xc8); // Latency 200
508aml_add_word(tmpl, 0x0096); // Power 150
509verbose ("C6");
510}
511//verbose("\n");
512
513break;
514}
515}
516}
517
518// Aliaces
519int i;
520for (i = 0; i < acpi_cpu_count; i++)
521{
522char name[9];
523sprintf(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]);
524
525scop = aml_add_scope(root, name);
526aml_add_alias(scop, "CST_", "_CST");
527}
528
529
530aml_calculate_size(root);
531
532struct acpi_2_ssdt *ssdt = (struct acpi_2_ssdt *)AllocateKernelMemory(root->Size);
533
534aml_write_node(root, (void*)ssdt, 0);
535
536ssdt->Length = root->Size;
537ssdt->Checksum = 0;
538ssdt->Checksum = 256 - checksum8(ssdt, ssdt->Length);
539
540verbose (" @ %x\n", ssdt);
541aml_destroy_node(root);
542
543//dumpPhysAddr("C-States SSDT content: ", ssdt, ssdt->Length);
544
545return ssdt;
546}
547else
548{
549verbose ("C-States: ACPI CPUs not found !!!\n");
550}
551
552return NULL;
553}
554
555uint8_t mV_to_VID(uint16_t mv) {
556if (Platform.CPU.Vendor == 0x756E6547)
557{
558if ((Platform.CPU.Family == 0x06) && (Platform.CPU.Model == 0x17))
559return ((mv * 10) - 7125) / 125;
560else
561return (mv - 700) / 16;
562}
563return 0;
564}
565
566uint16_t VID_to_mV(uint8_t VID) {
567if (Platform.CPU.Vendor == 0x756E6547)
568{
569if ((Platform.CPU.Family == 0x06) && (Platform.CPU.Model == 0x17))
570return (((int)VID * 125) + 7125) / 10;
571else
572return (((int)VID * 16) + 700);
573}
574return 0;
575}
576
577struct acpi_2_ssdt *generate_pss_ssdt(struct acpi_2_dsdt* dsdt)
578{
579char ssdt_header[] =
580{
5810x53, 0x53, 0x44, 0x54, 0x7E, 0x00, 0x00, 0x00, /* SSDT.... */
5820x01, 0x6A, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x00, /* ..PmRef. */
5830x43, 0x70, 0x75, 0x50, 0x6D, 0x00, 0x00, 0x00, /* CpuPm... */
5840x00, 0x30, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* .0..INTL */
5850x31, 0x03, 0x10, 0x20,/* 1.._*/
586};
587
588char ssdt_pct[] =
589{
5900x08, 0x5F, 0x50, 0x43, 0x54, 0x12, 0x2C, 0x02,/* 0._PCT., */
5910x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00, 0x7F,/* ........ */
5920x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
5930x00, 0x00, 0x00, 0x79, 0x00, 0x11, 0x14, 0x0A, /* ....y... */
5940x11, 0x82, 0x0C, 0x00, 0x7F, 0x00, 0x00, 0x00, /* ........ */
5950x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
5960x79, 0x00
597};
598
599if (Platform.CPU.Vendor != 0x756E6547) {
600verbose ("P-States: Not an Intel platform !!!\n");
601return NULL;
602}
603
604if (!(platformCPUFeature(CPU_FEATURE_MSR))) {
605verbose ("P-States: Unsupported CPU !!!\n");
606return NULL;
607}
608
609if (acpi_cpu_count == 0)
610get_acpi_cpu_names((void*)dsdt, dsdt->Length);
611
612if (acpi_cpu_count > 0)
613{
614
615struct p_state initial, maximum, minimum, p_states[32];
616uint8_t p_states_count = 0;
617
618//TODO: make use of minimum & friends instead, (busratios, freqs ...)
619int busratio_min = Platform.CPU.MinRatio;
620int busratio_max = Platform.CPU.MaxRatio;
621
622int freq_max = ((Platform.CPU.FSBFrequency / 1000000) * busratio_max) / 10;
623int freq_min = ((Platform.CPU.FSBFrequency / 1000000) * busratio_min) / 10;
624int p = ((busratio_max - busratio_min) * 2) / 10;
625int f_step = (freq_max - freq_min) / p;
626if (Platform.CPU.SLFM) freq_min = (busratio_min * f_step) / 10;
627freq_max = (((Platform.CPU.FSBFrequency / 1000000) + 1) * busratio_max) / 10;
628
629//valv: minimum instead of current
630//initial.Control = rdmsr64(MSR_IA32_PERF_STATUS);
631initial.Control = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 48) & 0x1F3F);
632maximum.Control = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 32) & 0x1F3F) | (0x4000 * Platform.CPU.MaxDiv);
633
634maximum.FID = (busratio_max / 0xA) & 0x1F | (0x40 * Platform.CPU.MaxDiv);
635maximum.CID = ((maximum.FID & 0x1F) << 1) | Platform.CPU.MaxDiv;
636
637// current isn't always minimum
638//minimum.FID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 24) & 0x1F) | (0x80 * cpu_dynamic_fsb);
639minimum.FID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 56) & 0x1F) | (0x80 * Platform.CPU.SLFM);
640// this may not be valid when slfm (did) is enabled. Rely on vmin instead
641minimum.VID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 48) & 0x3F);
642
643int umaxVolt, uminVolt, moreVolt, lessVolt, vstate;
644int maxVolt_limit = VID_to_mV(maximum.VID) + 250;
645int minVolt_limit = VID_to_mV(minimum.VID) - 250;
646uint8_t vstep = 0;
647
648if((getIntForKey(kmaxVoltage, &umaxVolt, &bootInfo->bootConfig)) && (umaxVolt <= maxVolt_limit))
649{
650uint8_t vmax = mV_to_VID(umaxVolt);
651maximum.Control = (((busratio_max / 0xA) & 0x1F) * 0x100 | vmax) | (0x4000 * Platform.CPU.MaxDiv);
652maximum.VID = vmax & 0x3F;
653}
654if((getIntForKey(kminVoltage, &uminVolt, &bootInfo->bootConfig)) && (uminVolt >= minVolt_limit))
655{
656uint8_t vmin = mV_to_VID(uminVolt);
657minimum.VID = vmin & 0x3F;
658}
659
660if (minimum.FID == 0)
661{
662uint64_t msr;
663uint8_t i;
664// Probe for lowest fid
665// this is for requested FID, and not forcibly the lowest
666for (i = maximum.FID; i >= 0x6; i--)
667{
668msr = rdmsr64(MSR_IA32_PERF_CONTROL);
669wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (i << 8) | minimum.VID);
670intel_waitforsts();
671minimum.FID = (rdmsr64(MSR_IA32_PERF_STATUS) >> 8) & 0x1F;
672delay(1);
673}
674
675msr = rdmsr64(MSR_IA32_PERF_CONTROL);
676wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
677intel_waitforsts();
678}
679
680if (minimum.VID == maximum.VID)
681{
682uint64_t msr;
683uint8_t i;
684// Probe for lowest vid
685for (i = maximum.VID; i > 0xA; i--)
686{
687msr = rdmsr64(MSR_IA32_PERF_CONTROL);
688wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (minimum.FID << 8) | i);
689intel_waitforsts();
690minimum.VID = rdmsr64(MSR_IA32_PERF_STATUS) & 0x3F;
691delay(1);
692}
693
694msr = rdmsr64(MSR_IA32_PERF_CONTROL);
695wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
696intel_waitforsts();
697}
698
699minimum.CID = ((minimum.FID & 0x1F) << 1) >> Platform.CPU.SLFM;
700
701// Sanity check
702if (maximum.CID < minimum.CID)
703{
704DBG("P-States: Insane FID values!");
705p_states_count = 1;
706}
707else
708{
709// Print the voltage to be used
710int minVoltage = VID_to_mV(minimum.VID);
711int maxVoltage = VID_to_mV(maximum.VID);
712verbose("Voltage: min= %dmV, max= %dmV\n", minVoltage, maxVoltage);
713
714// Finalize P-States
715// Find how many P-States machine supports
716
717p_states_count = maximum.CID - minimum.CID + 1;
718
719if (p_states_count > 32)
720p_states_count = 32;
721
722uint8_t vidstep;
723uint8_t i = 0, u, invalid = 0;
724
725vidstep = ((maximum.VID << 2) - (minimum.VID << 2)) / (p_states_count - 1);
726for (u = 0; u < p_states_count; u++)
727{
728i = u - invalid;
729
730p_states[i].CID = maximum.CID - u;
731p_states[i].FID = (p_states[i].CID >> 1);
732
733if (i && p_states[i].FID < 0x6)
734{
735if (Platform.CPU.SLFM)
736{
737p_states[i].FID = (p_states[i].FID << 1) | 0x80;
738}
739// intel doesn't allow FIDs lower that 6 on core, core2 and eventually core-i
740else invalid++;
741}
742
743// 6.5 isn't selectable
744else if (Platform.CPU.MaxDiv && p_states[i].FID > 0x6)
745{
746// first state only!?
747//p_states[0].FID = p_states[0].FID | (0x40 * (p_states[0].CID & 0x1));
748p_states[i].FID = p_states[i].FID | (0x40 * (p_states[i].CID & 0x1));
749}
750
751if (i && p_states[i].FID == p_states[i-1].FID)
752invalid++;
753
754p_states[i].VID = ((maximum.VID << 2) - (vidstep * u)) >> 2;
755
756if(getIntForKey(klessVoltage, &lessVolt, &bootInfo->bootConfig))
757{
758vstate = (VID_to_mV(p_states[i].VID)) - lessVolt;
759vstep = mV_to_VID(vstate);
760p_states[i].VID = vstep & 0x3F;
761}
762else if(getIntForKey(kmoreVoltage, &moreVolt, &bootInfo->bootConfig))
763{
764vstate = (VID_to_mV(p_states[i].VID)) + moreVolt;
765vstep = mV_to_VID(vstate);
766p_states[i].VID = vstep & 0x3F;
767}
768
769uint32_t multiplier = p_states[i].FID & 0x1f;// = 0x08
770bool half = p_states[i].FID & 0x40;// = 0x01
771bool dfsb = p_states[i].FID & 0x80;// = 0x00
772uint32_t fsb = Platform.CPU.FSBFrequency / 1000000; // = 400
773uint32_t halffsb = (fsb + 1) >> 1;// = 200
774uint32_t frequency = (multiplier * fsb);// = 3200
775
776p_states[i].Frequency = (frequency + (half * halffsb)) >> dfsb;// = 3200 + 200 = 3400
777}
778p_states_count -= invalid;
779}
780
781//valv: Silly! Isn't it? :)
782int pstates = 0;
783if (getIntForKey(kpstates, &pstates, &bootInfo->bootConfig) && pstates < p_states_count && pstates > 0)
784{
785verbose("P-State: Only the %d highest states will be added\n", pstates);
786pstates = pstates - 1;
787}
788
789int pstart = 0;
790if (getIntForKey(kpstart, &pstart, &bootInfo->bootConfig) && pstart < p_states_count && pstart > 0)
791{
792const char *newratio;
793int len;
794if (getValueForKey(kbusratio, &newratio, &len, &bootInfo->bootConfig))
795{
796verbose("P-State: Already using bus-ratio injection! PStart key will have no effect.\n");
797pstart = 0;
798}
799else verbose("P-State: Starting from state P%d\n", pstart);
800}
801
802// Generating SSDT
803if (p_states_count > 0)
804{
805int i;
806//valv: fix p-states number issue on some models.
807verbose("Model detected: %s\n", MacProduct);
808if(!strstr(MacProduct, "applemac2010"))
809{
810if(strstr(MacProduct, "MacBookPro4,1") && ((p_states_count > 9) && ((pstart == 0) && (pstates == 0)))) pstates = 8;
811if(strstr(MacProduct, "MacBookAir1,1") && ((p_states_count > 4) && ((pstart == 0) && (pstates == 0)))) pstates = 3;
812}
813
814struct aml_chunk* root = aml_create_node(NULL);
815aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header
816struct aml_chunk* scop = aml_add_scope(root, "\\_PR_");
817
818aml_add_buffer(scop, ssdt_pct, sizeof(ssdt_pct));
819
820struct aml_chunk* name_psd = aml_add_name(scop, "PSD_");
821struct aml_chunk* pack_psd = aml_add_package(name_psd);
822struct aml_chunk* psd = aml_add_package(pack_psd);
823aml_add_byte(psd, 0x05);
824aml_add_byte(psd, 0x00);
825aml_add_dword(psd, 0x00);
826aml_add_dword(psd, 0xfd);
827aml_add_dword(psd, Platform.CPU.NoCores);
828
829struct aml_chunk* name_pss = aml_add_name(scop, "PSS_");
830struct aml_chunk* pack_pss = aml_add_package(name_pss);
831
832uint8_t p_states_num = 0;
833for (i = pstart; i < p_states_count; i++)
834{
835if ((p_states[i].Frequency <= freq_max) && (p_states[i].Frequency >= freq_min))
836{
837//valv: inspired from cparm's pss-drop; coded by me ;)
838if ((i > pstates) && (pstates > 0))
839{
840if(Platform.CPU.ISerie) verbose("P-State: [Frequency %d MHz\tFID 0x%x] is the %dth state. Removed!\n",
841p_states[i].Frequency, p_states[i].FID, (i+1));
842else verbose("P-State: [Frequency %d MHz\tFID 0x%x \tVID 0x%x] is the %dth state. Removed!\n",
843p_states[i].Frequency, p_states[i].FID, p_states[i].VID, (i+1));
844}
845else
846{
847struct aml_chunk* pstt = aml_add_package(pack_pss);
848
849aml_add_dword(pstt, p_states[i].Frequency);
850aml_add_dword(pstt, 0x00000000); // Power
851aml_add_dword(pstt, 0x0000000A); // Latency
852aml_add_dword(pstt, 0x0000000A); // Latency
853if(Platform.CPU.ISerie)
854{
855aml_add_dword(pstt, p_states[i].FID);
856aml_add_dword(pstt, p_states[i].FID);
857verbose("P-State: Added [Frequency %d MHz\tFID 0x%x]\n", p_states[i].Frequency, p_states[i].FID);
858}
859else
860{
861aml_add_dword(pstt, p_states[i].Control);
862aml_add_dword(pstt, p_states[i].Control);
863//aml_add_dword(pstt, i+1); // Status
864verbose("P-State: Added [Frequency %d MHz\tFID 0x%x \tVID 0x%x]\n",
865p_states[i].Frequency, p_states[i].FID, p_states[i].VID);
866}
867p_states_num++;
868}
869}
870else
871{
872if(Platform.CPU.ISerie) verbose("P-State: [Frequency %d MHz\tFID 0x%x] is over the limit. Removed!\n",
873p_states[i].Frequency, p_states[i].FID);
874else verbose("P-State: [Frequency %d MHz\tFID 0x%x \tVID 0x%x] is over the limit. Removed!\n",
875p_states[i].Frequency, p_states[i].FID, p_states[i].VID);
876}
877}
878
879struct aml_chunk* name_ppc = aml_add_name(scop, "PPC_");
880aml_add_byte(name_ppc, 0x00);
881
882// Add aliaces
883for (i = 0; i < acpi_cpu_count; i++)
884{
885char name[9];
886sprintf(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]);
887
888scop = aml_add_scope(root, name);
889aml_add_alias(scop, "PCT_", "_PCT");
890aml_add_alias(scop, "PSD_", "_PSD");
891aml_add_alias(scop, "PSS_", "_PSS");
892aml_add_alias(scop, "PPC_", "_PPC");
893}
894
895aml_calculate_size(root);
896
897struct acpi_2_ssdt *ssdt = (struct acpi_2_ssdt *)AllocateKernelMemory(root->Size);
898
899aml_write_node(root, (void*)ssdt, 0);
900
901ssdt->Length = root->Size;
902ssdt->Checksum = 0;
903ssdt->Checksum = 256 - checksum8(ssdt, ssdt->Length);
904
905verbose ("P-States: %d states were succefully generated @ %x\n", p_states_num, ssdt);
906aml_destroy_node(root);
907
908return ssdt;
909}
910}
911else {
912verbose ("P-States: ACPI CPUs not found !!!\n");
913}
914
915return NULL;
916}
917
918struct acpi_2_ssdt *generate_tss_ssdt(struct acpi_2_fadt* fadt)
919{
920char ssdt_header[] =
921{
922 0x53, 0x53, 0x44, 0x54, 0xE7, 0x00, 0x00, 0x00,
923 0x01, 0x17, 0x50, 0x6D, 0x52, 0x65, 0x66, 0x42,
924 0x43, 0x70, 0x75, 0x54, 0x73, 0x74, 0x00, 0x00,
925 0x00, 0x10, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C,
926 0x31, 0x03, 0x10, 0x20
927};
928
929char ssdt_ptc[] =
930{
9310x08, 0x5F, 0x50, 0x54, 0x43, 0x12, 0x2C, 0x02,
9320x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00, 0x7F,
9330x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9340x00, 0x00, 0x00, 0x79, 0x00, 0x11, 0x14, 0x0A,
9350x11, 0x82, 0x0C, 0x00, 0x7F, 0x00, 0x00, 0x00,
9360x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9370x79, 0x00
938};
939
940if (Platform.CPU.Vendor != 0x756E6547) {
941verbose ("T-States: Not an Intel platform !!!\n");
942return NULL;
943}
944
945if (!(platformCPUFeature(CPU_FEATURE_MSR))) {
946verbose ("T-States: Unsupported CPU !!!\n");
947return NULL;
948}
949
950if (fadt == NULL) {
951verbose ("FACP not found: T-States will not be generated !!!\n");
952return NULL;
953}
954
955struct acpi_2_dsdt* dsdt = (void*)fadt->DSDT;
956
957if (dsdt == NULL) {
958verbose ("T-States: DSDT not found !!!\n");
959return NULL;
960}
961
962if (acpi_cpu_count == 0)
963get_acpi_cpu_names((void*)dsdt, dsdt->Length);
964
965if (acpi_cpu_count > 0)
966{
967
968struct t_state t_states[32];
969uint8_t t_states_count = 0, ctrl0 = 0x10, j = 0x01;
970int i, step;
971uint64_t msr;
972uint32_t ext_mod; // *ret = 0;
973
974do_cpuid(6, Platform.CPU.CPUID[CPUID_81]);
975ext_mod = bitfield(Platform.CPU.CPUID[CPUID_81][0], 5, 5);
976
977if(ext_mod == 1)
978{
979verbose("T-States: Unsupported CPU !!!\n");
980return NULL;
981}
982
983msr = rdmsr64(MSR_IA32_CLOCK_MODULATION);
984t_states_count = msr & 0xE;
985
986//if(!fadt->DUTY_WIDTH)
987if(t_states_count == 0)
988{
989verbose("T-States: Unsupported CPU !!!\n");
990return NULL;
991}
992/*
993verbose("T-States: duty_offset=%d, duty_width=%d\n", fadt->DUTY_OFFSET, fadt->DUTY_WIDTH);
994uint8_t duty_cycle = fadt->DUTY_WIDTH + fadt->DUTY_OFFSET;
995
996if(duty_cycle > 4)
997{
998verbose("T-States: Spanning bit 4\n");
999for (i=2; i<21; i++)
1000{
1001if(duty_cycle > 4)
1002{
1003verbose("duty_cycle: %d\n", duty_cycle);
1004sleep(i);
1005i++;
1006}
1007//return NULL;
1008else
1009{
1010t_states_count = 8;
1011goto nrx;
1012}
1013}
1014}
1015else t_states_count = 1 << fadt->DUTY_WIDTH;
1016
1017nrx:
1018*/
1019step = (1000 / t_states_count);
1020for (i = 1; i < t_states_count; i++)
1021{
1022t_states[i].perf = (1000 - (step * i)) / 10;
1023t_states[i].pwer = 1000 - (step * i);
1024t_states[i].ctrl = ctrl0 - j;
1025j++;
1026}
1027
1028// Generating SSDT
1029if (t_states_count > 0)
1030{
1031struct aml_chunk* root = aml_create_node(NULL);
1032aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header
1033struct aml_chunk* scop = aml_add_scope(root, "\\_PR_");
1034
1035struct aml_chunk* name_tpc = aml_add_name(scop, "TPC_");
1036aml_add_byte(name_tpc, 0x00);
1037
1038aml_add_buffer(scop, ssdt_ptc, sizeof(ssdt_ptc));
1039
1040struct aml_chunk* name_tss = aml_add_name(scop, "TSS_");
1041struct aml_chunk* pack_tss = aml_add_package(name_tss);
1042
1043struct aml_chunk* tssp0 = aml_add_package(pack_tss);
1044aml_add_dword(tssp0, 0x64);// Frequency %
1045aml_add_dword(tssp0, 0x03E8);// Power
1046aml_add_dword(tssp0, 0x00);// Latency
1047aml_add_dword(tssp0, 0x00);// Control; spec says 0x07; apple uses 0;
1048aml_add_dword(tssp0, 0x00);// Status
1049
1050for (i = 1; i < t_states_count; i++)
1051{
1052struct aml_chunk* tssp = aml_add_package(pack_tss);
1053
1054aml_add_dword(tssp, t_states[i].perf);
1055aml_add_dword(tssp, t_states[i].pwer);
1056aml_add_dword(tssp, 0x00);
1057aml_add_dword(tssp, t_states[i].ctrl);
1058aml_add_dword(tssp, 0x00);
1059}
1060
1061struct aml_chunk* name_tsd = aml_add_name(scop, "TSD_");
1062struct aml_chunk* pack_tsd = aml_add_package(name_tsd);
1063struct aml_chunk* tsd = aml_add_package(pack_tsd);
1064aml_add_byte(tsd, 0x05);
1065aml_add_byte(tsd, 0x00);
1066aml_add_dword(tsd, 0x00);
1067aml_add_dword(tsd, 0xfd);
1068aml_add_dword(tsd, Platform.CPU.NoCores);
1069
1070// Add aliaces
1071for (i = 0; i < acpi_cpu_count; i++)
1072{
1073char name[9];
1074sprintf(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]);
1075
1076scop = aml_add_scope(root, name);
1077aml_add_alias(scop, "TPC_", "_TPC");
1078aml_add_alias(scop, "PTC_", "_PTC");
1079aml_add_alias(scop, "TSS_", "_TSS");
1080aml_add_alias(scop, "TSD_", "_TSD");
1081}
1082
1083aml_calculate_size(root);
1084
1085struct acpi_2_ssdt *ssdt = (struct acpi_2_ssdt *)AllocateKernelMemory(root->Size);
1086
1087aml_write_node(root, (void*)ssdt, 0);
1088
1089ssdt->Length = root->Size;
1090ssdt->Checksum = 0;
1091ssdt->Checksum = 256 - checksum8(ssdt, ssdt->Length);
1092
1093verbose ("T-States: step=%d, %d states were succefully generated @ %x\n", step, t_states_count, ssdt);
1094
1095aml_destroy_node(root);
1096
1097return ssdt;
1098}
1099}
1100else
1101{
1102verbose ("ACPI CPUs not found: T-States not generated !!!\n");
1103}
1104
1105return NULL;
1106}
1107
1108void *loadSSDTTable(int ssdt_number)
1109{
1110void *tableAddr;
1111int fd = -1;
1112char dirspec[512];
1113char filename[512];
1114const char * overriden_pathname=NULL;
1115int len=0;
1116
1117sprintf(filename, "SSDT-%d.aml", ssdt_number);
1118
1119// Check booting partition
1120
1121// Rek: if user specified a full path name then take it in consideration
1122if (getValueForKey(kSSDT, &overriden_pathname, &len, &bootInfo->bootConfig))
1123{
1124sprintf(dirspec, "%s-%d.aml", overriden_pathname, ssdt_number); // start searching root
1125//printf("Using custom %s path %s\n", key, dirspec);
1126//getc();
1127}
1128else
1129sprintf(dirspec, "/%s", filename); // start searching root
1130
1131fd=open (dirspec,0);
1132
1133if (fd<0)
1134{// Check Extra on booting partition
1135//verbose("Searching for %s.aml file ...\n", key);
1136sprintf(dirspec,"/Extra/%s",filename);
1137fd=open (dirspec,0);
1138if (fd<0)
1139{// Fall back to booter partition
1140sprintf(dirspec,"bt(0,0)/Extra/%s",filename);
1141fd=open (dirspec,0);
1142if (fd<0)
1143{
1144//verbose("SSDT Table not found: %s\n", filename);
1145return NULL;
1146}
1147}
1148}
1149
1150tableAddr=(void*)AllocateKernelMemory(file_size (fd));
1151if (tableAddr)
1152{
1153if (read (fd, tableAddr, file_size (fd))!=file_size (fd))
1154{
1155printf("Couldn't read table %s\n",dirspec);
1156free (tableAddr);
1157close (fd);
1158return NULL;
1159}
1160
1161verbose("Table %s read and stored at: %x\n", dirspec, tableAddr);
1162close (fd);
1163return tableAddr;
1164}
1165
1166printf("Couldn't allocate memory for table %s\n", dirspec);
1167close (fd);
1168
1169return NULL;
1170}
1171
1172struct acpi_2_gas FillGASStruct(uint32_t Address, uint8_t Length)
1173{
1174struct acpi_2_gas TmpGAS;
1175
1176TmpGAS.Address_Space_ID = 1; /* I/O Address */
1177
1178if (Address == 0)
1179{
1180TmpGAS.Register_Bit_Width = 0;
1181} else {
1182TmpGAS.Register_Bit_Width = Length * 8;
1183}
1184
1185TmpGAS.Register_Bit_Offset = 0;
1186TmpGAS.Access_Size = 0; /* Not set for Legacy reasons... */
1187TmpGAS.Address = (uint64_t)Address;
1188
1189return(TmpGAS);
1190}
1191
1192struct acpi_2_fadt *patch_fadt(struct acpi_2_fadt *fadt, void *new_dsdt, bool UpdateFADT)
1193{
1194 extern void setupSystemType();
1195
1196struct acpi_2_fadt *fadt_mod;
1197struct acpi_2_fadt *fadt_file = (struct acpi_2_fadt *)loadACPITable(kFADT);
1198bool fadt_rev2_needed = false;
1199bool fix_restart;
1200const char * value;
1201
1202// Restart Fix
1203if (Platform.CPU.Vendor == 0x756E6547) {/* Intel */
1204fix_restart = true;
1205getBoolForKey(kRestartFix, &fix_restart, &bootInfo->bootConfig);
1206} else {
1207verbose ("Not an Intel platform: Restart Fix not applied !!!\n");
1208fix_restart = false;
1209}
1210
1211if (fix_restart)
1212fadt_rev2_needed = true;
1213
1214// Allocate new fadt table
1215if ((UpdateFADT) && (((fadt_file) && (fadt_file->Length < sizeof(struct acpi_2_fadt))) ||
1216 ((!fadt_file) && (fadt->Length < sizeof(struct acpi_2_fadt)))))
1217{
1218fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(sizeof(struct acpi_2_fadt));
1219
1220if (fadt_file)
1221memcpy(fadt_mod, fadt_file, fadt_file->Length);
1222else
1223memcpy(fadt_mod, fadt, fadt->Length);
1224
1225fadt_mod->Length = sizeof(struct acpi_2_fadt);
1226fadt_mod->Revision = 0x04; // FADT rev 4
1227fadt_mod->RESET_REG = FillGASStruct(0, 0);
1228fadt_mod->RESET_VALUE = 0;
1229fadt_mod->Reserved2[0] = 0;
1230fadt_mod->Reserved2[1] = 0;
1231fadt_mod->Reserved2[2] = 0;
1232fadt_mod->X_PM1a_EVT_BLK = FillGASStruct(fadt_mod->PM1a_EVT_BLK, fadt_mod->PM1_EVT_LEN);
1233fadt_mod->X_PM1b_EVT_BLK = FillGASStruct(fadt_mod->PM1b_EVT_BLK, fadt_mod->PM1_EVT_LEN);
1234fadt_mod->X_PM1a_CNT_BLK = FillGASStruct(fadt_mod->PM1a_CNT_BLK, fadt_mod->PM1_CNT_LEN);
1235fadt_mod->X_PM1b_CNT_BLK = FillGASStruct(fadt_mod->PM1b_CNT_BLK, fadt_mod->PM1_CNT_LEN);
1236fadt_mod->X_PM2_CNT_BLK = FillGASStruct(fadt_mod->PM2_CNT_BLK, fadt_mod->PM2_CNT_LEN);
1237fadt_mod->X_PM_TMR_BLK = FillGASStruct(fadt_mod->PM_TMR_BLK, fadt_mod->PM_TMR_LEN);
1238fadt_mod->X_GPE0_BLK = FillGASStruct(fadt_mod->GPE0_BLK, fadt_mod->GPE0_BLK_LEN);
1239fadt_mod->X_GPE1_BLK = FillGASStruct(fadt_mod->GPE1_BLK, fadt_mod->GPE1_BLK_LEN);
1240verbose("Converted ACPI V%d FADT to ACPI V4 FADT\n", (fadt_file) ? fadt_file->Revision : fadt->Revision);
1241} else {
1242if (((!fadt_file) && ((fadt->Length < 0x84) && (fadt_rev2_needed))) ||
1243 ((fadt_file) && ((fadt_file->Length < 0x84) && (fadt_rev2_needed))))
1244{
1245fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(0x84);
1246
1247if (fadt_file)
1248memcpy(fadt_mod, fadt_file, fadt_file->Length);
1249else
1250memcpy(fadt_mod, fadt, fadt->Length);
1251
1252fadt_mod->Length = 0x84;
1253fadt_mod->Revision = 0x02; // FADT rev 2 (ACPI 1.0B MS extensions)
1254}
1255else
1256{
1257if (fadt_file)
1258{
1259fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(fadt_file->Length);
1260memcpy(fadt_mod, fadt_file, fadt_file->Length);
1261} else {
1262fadt_mod=(struct acpi_2_fadt *)AllocateKernelMemory(fadt->Length);
1263memcpy(fadt_mod, fadt, fadt->Length);
1264}
1265}
1266}
1267// Determine system type / PM_Model
1268if ( (value=getStringForKey(kSystemType, &bootInfo->bootConfig))!=NULL)
1269{
1270 if (Platform.Type > 6)
1271 {
1272 if(fadt_mod->Preferred_PM_Profile<=6)
1273 Platform.Type = fadt_mod->Preferred_PM_Profile; // get the fadt if correct
1274 else
1275 Platform.Type = 1;/* Set a fixed value (Desktop) */
1276 verbose("Error: system-type must be 0..6. Defaulting to %d !\n", Platform.Type);
1277 }
1278 else
1279 Platform.Type = (unsigned char) strtoul(value, NULL, 10);
1280}
1281// Set Preferred_PM_Profile from System-type only if user wanted this value to be forced
1282if (fadt_mod->Preferred_PM_Profile != Platform.Type)
1283{
1284 if (value)
1285 { // user has overriden the SystemType so take care of it in FACP
1286verbose("FADT: changing Preferred_PM_Profile from 0x%02x to 0x%02x\n", fadt_mod->Preferred_PM_Profile, Platform.Type);
1287fadt_mod->Preferred_PM_Profile = Platform.Type;
1288 }
1289 else
1290 { // Preferred_PM_Profile has a different value and no override has been set, so reflect the user value to ioregs
1291 Platform.Type = fadt_mod->Preferred_PM_Profile <= 6 ? fadt_mod->Preferred_PM_Profile : 1;
1292 }
1293}
1294// We now have to write the systemm-type in ioregs: we cannot do it before in setupDeviceTree()
1295// because we need to take care of facp original content, if it is correct.
1296setupSystemType();
1297
1298// Patch FADT to fix restart
1299if (fix_restart)
1300{
1301fadt_mod->Flags|= 0x400;
1302fadt_mod->RESET_REG = FillGASStruct(0x0cf9, 1);
1303fadt_mod->RESET_VALUE = 0x06;
1304
1305verbose("FADT: Restart Fix applied !\n");
1306}
1307
1308// Patch FACS Address
1309fadt_mod->FIRMWARE_CTRL=(uint32_t)fadt->FIRMWARE_CTRL;
1310if ((uint32_t)(&(fadt_mod->X_FIRMWARE_CTRL))-(uint32_t)fadt_mod+8<=fadt_mod->Length)
1311fadt_mod->X_FIRMWARE_CTRL=(uint32_t)fadt->FIRMWARE_CTRL;
1312
1313// Patch DSDT Address if we have one loaded
1314if(new_dsdt)
1315{
1316fadt_mod->DSDT=(uint32_t)new_dsdt;
1317if ((uint32_t)(&(fadt_mod->X_DSDT))-(uint32_t)fadt_mod+8<=fadt_mod->Length)
1318fadt_mod->X_DSDT=(uint32_t)new_dsdt;
1319}
1320
1321
1322// Correct the checksum
1323fadt_mod->Checksum=0;
1324fadt_mod->Checksum=256-checksum8(fadt_mod,fadt_mod->Length);
1325
1326return fadt_mod;
1327}
1328#if UNUSED
1329/* Setup ACPI without replacing DSDT. */
1330int setupAcpiNoMod()
1331{
1332//addConfigurationTable(&gEfiAcpiTableGuid, getAddressOfAcpiTable(), "ACPI");
1333//addConfigurationTable(&gEfiAcpi20TableGuid, getAddressOfAcpi20Table(), "ACPI_20");
1334/* XXX aserebln why uint32 cast if pointer is uint64 ? */
1335acpi10_p = (uint32_t)getAddressOfAcpiTable();
1336acpi20_p = (uint32_t)getAddressOfAcpi20Table();
1337addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
1338if(acpi20_p) addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
1339return 1;
1340}
1341#endif
1342
1343/* Setup ACPI. Replace DSDT if DSDT.aml is found */
1344int setupAcpi(void)
1345{
1346int version;
1347void *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_ssdt[14];
1348
1349struct acpi_2_ssdt *new_ssdt[16]; // 2 additional tables for pss/tss & cst
1350struct acpi_2_fadt *fadt; // will be used in CST generator
1351
1352bool 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;
1353bool drop_ssdt=false, drop_hpet=false, drop_slic=false, drop_sbst=false, drop_ecdt=false, drop_asft=false, drop_dmar=false;
1354bool update_acpi=false, gen_xsdt=false;
1355bool hpet_replaced=false, sbst_replaced=false, ecdt_replaced=false, asft_replaced=false, dmar_replaced=false, apic_replaced=false, mcfg_replaced=false;
1356bool hpet_added=false, sbst_added=false, ecdt_added=false, asft_added=false, dmar_added=false, apic_added=false, mcfg_added=false;
1357bool gen_cst=false, gen_pss=false, gen_tss=false;
1358
1359int curssdt=0, loadtotssdt=0, totssdt=0, newtotssdt=0;
1360
1361{
1362bool tmpval, tmpval2, tmpval3, tmpval4, tmpval6;
1363
1364drop_ssdt = getBoolForKey(kDropSSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1365drop_hpet = getBoolForKey(kDropHPET, &tmpval, &bootInfo->bootConfig)&&tmpval;
1366drop_slic = getBoolForKey(kDropSLIC, &tmpval, &bootInfo->bootConfig)&&tmpval;
1367drop_sbst = getBoolForKey(kDropSBST, &tmpval, &bootInfo->bootConfig)&&tmpval;
1368drop_ecdt = getBoolForKey(kDropECDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1369drop_asft = getBoolForKey(kDropASFT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1370drop_dmar = getBoolForKey(kDropDMAR, &tmpval, &bootInfo->bootConfig)&&tmpval;
1371
1372oem_dsdt = getBoolForKey(kOEMDSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1373oem_ssdt = getBoolForKey(kOEMSSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1374oem_hpet = getBoolForKey(kOEMHPET, &tmpval, &bootInfo->bootConfig)&&tmpval;
1375oem_sbst = getBoolForKey(kOEMSBST, &tmpval, &bootInfo->bootConfig)&&tmpval;
1376oem_ecdt = getBoolForKey(kOEMECDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1377oem_asft = getBoolForKey(kOEMASFT, &tmpval, &bootInfo->bootConfig)&&tmpval;
1378oem_dmar = getBoolForKey(kOEMDMAR, &tmpval, &bootInfo->bootConfig)&&tmpval;
1379oem_apic = getBoolForKey(kOEMAPIC, &tmpval, &bootInfo->bootConfig)&&tmpval;
1380oem_mcfg = getBoolForKey(kOEMMCFG, &tmpval, &bootInfo->bootConfig)&&tmpval;
1381
1382gen_cst = (getBoolForKey(kGenerateCStates, &tmpval, &bootInfo->bootConfig)&&tmpval)
1383| (getBoolForKey(kEnableC2State, &tmpval2, &bootInfo->bootConfig)&&tmpval2)
1384| (getBoolForKey(kEnableC3State, &tmpval3, &bootInfo->bootConfig)&&tmpval3)
1385| (getBoolForKey(kEnableC4State, &tmpval4, &bootInfo->bootConfig)&&tmpval4)
1386| (getBoolForKey(kEnableC6State, &tmpval6, &bootInfo->bootConfig)&&tmpval6);
1387
1388gen_pss = getBoolForKey(kGeneratePStates, &tmpval, &bootInfo->bootConfig)&&tmpval;
1389
1390gen_tss = getBoolForKey(kGenerateTStates, &tmpval, &bootInfo->bootConfig)&&tmpval;
1391
1392update_acpi = getBoolForKey(kUpdateACPI, &tmpval, &bootInfo->bootConfig)&&tmpval;
1393}
1394
1395// Load replacement ACPI tables
1396if (!oem_dsdt)
1397new_dsdt=loadACPITable(kDSDT);
1398
1399if (!oem_hpet)
1400new_hpet=loadACPITable(kHPET);
1401
1402if (!oem_sbst)
1403new_sbst=loadACPITable(kSBST);
1404
1405if (!oem_ecdt)
1406new_ecdt=loadACPITable(kECDT);
1407
1408if (!oem_asft)
1409new_asft=loadACPITable(kASFT);
1410
1411if (!oem_dmar)
1412new_dmar=loadACPITable(kDMAR);
1413
1414if (!oem_apic)
1415new_apic=loadACPITable(kAPIC);
1416
1417if (!oem_mcfg)
1418new_mcfg=loadACPITable(kMCFG);
1419
1420if (gen_cst || gen_pss || gen_tss) oem_ssdt = false;
1421
1422if (!oem_ssdt)
1423{
1424for (curssdt=0;curssdt<14;curssdt++)
1425{
1426new_ssdt[curssdt]=loadSSDTTable(curssdt);
1427if (new_ssdt[curssdt])
1428loadtotssdt++;
1429}
1430curssdt=0;
1431}
1432/*
1433if (!new_dsdt)
1434return setupAcpiNoMod();
1435*/
1436DBG("New ACPI tables Loaded in memory\n");
1437
1438// Do the same procedure for both versions of ACPI
1439for (version=0; version<2; version++) {
1440struct acpi_2_rsdp *rsdp, *rsdp_mod, *rsdp_conv=(struct acpi_2_rsdp *)0;
1441struct acpi_2_rsdt *rsdt, *rsdt_mod;
1442struct acpi_2_xsdt *xsdt_conv = (struct acpi_2_xsdt *)0;
1443int rsdplength;
1444
1445// Find original rsdp
1446rsdp=(struct acpi_2_rsdp *)(version?getAddressOfAcpi20Table():getAddressOfAcpiTable());
1447if ((update_acpi) && (rsdp->Revision == 0))
1448{
1449rsdp_conv = (struct acpi_2_rsdp *)AllocateKernelMemory(sizeof(struct acpi_2_rsdp));
1450memcpy(rsdp_conv, rsdp, 20);
1451
1452/* Add/change fields */
1453strncpy(rsdp->OEMID, "Apple ", 6);
1454rsdp_conv->Revision = 2; /* ACPI version 3 */
1455rsdp_conv->Length = sizeof(struct acpi_2_rsdp);
1456
1457/* Correct checksums */
1458rsdp_conv->Checksum = 0;
1459rsdp_conv->Checksum = 256-checksum8(rsdp_conv, 20);
1460rsdp_conv->ExtendedChecksum = 0;
1461rsdp_conv->ExtendedChecksum = 256-checksum8(rsdp_conv, rsdp_conv->Length);
1462
1463rsdp = rsdp_conv;
1464
1465gen_xsdt = true;
1466version = 1;
1467
1468addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI");
1469
1470verbose("Converted ACPI RSD PTR version 1 to version 3\n");
1471}
1472if (!rsdp)
1473{
1474DBG("No ACPI version %d found. Ignoring\n", version+1);
1475if (version)
1476addConfigurationTable(&gEfiAcpi20TableGuid, NULL, "ACPI_20");
1477else
1478addConfigurationTable(&gEfiAcpiTableGuid, NULL, "ACPI");
1479continue;
1480}
1481rsdplength=version?rsdp->Length:20;
1482
1483DBG("RSDP version %d found @%x. Length=%d\n",version+1,rsdp,rsdplength);
1484
1485/* FIXME: no check that memory allocation succeeded
1486 * Copy and patch RSDP,RSDT, XSDT and FADT
1487 * For more info see ACPI Specification pages 110 and following
1488 */
1489
1490if (gen_xsdt)
1491{
1492rsdp_mod=rsdp_conv;
1493} else {
1494rsdp_mod=(struct acpi_2_rsdp *) AllocateKernelMemory(rsdplength);
1495memcpy(rsdp_mod, rsdp, rsdplength);
1496}
1497
1498rsdt=(struct acpi_2_rsdt *)(rsdp->RsdtAddress);
1499
1500DBG("RSDT @%x, Length %d\n",rsdt, rsdt->Length);
1501
1502if (rsdt && (uint32_t)rsdt !=0xffffffff && rsdt->Length<0x10000)
1503{
1504uint32_t *rsdt_entries;
1505int rsdt_entries_num;
1506int dropoffset=0, i;
1507
1508rsdt_mod=(struct acpi_2_rsdt *)AllocateKernelMemory(rsdt->Length);
1509memcpy (rsdt_mod, rsdt, rsdt->Length);
1510rsdp_mod->RsdtAddress=(uint32_t)rsdt_mod;
1511rsdt_entries_num=(rsdt_mod->Length-sizeof(struct acpi_2_rsdt))/4;
1512rsdt_entries=(uint32_t *)(rsdt_mod+1);
1513
1514if (gen_xsdt)
1515{
1516uint64_t *xsdt_conv_entries;
1517
1518xsdt_conv=(struct acpi_2_xsdt *)AllocateKernelMemory(sizeof(struct acpi_2_xsdt)+(rsdt_entries_num * 8));
1519memcpy(xsdt_conv, rsdt, sizeof(struct acpi_2_rsdt));
1520
1521xsdt_conv->Signature[0] = 'X';
1522xsdt_conv->Signature[1] = 'S';
1523xsdt_conv->Signature[2] = 'D';
1524xsdt_conv->Signature[3] = 'T';
1525xsdt_conv->Length = sizeof(struct acpi_2_xsdt)+(rsdt_entries_num * 8);
1526
1527xsdt_conv_entries=(uint64_t *)(xsdt_conv+1);
1528
1529for (i=0;i<rsdt_entries_num;i++)
1530{
1531xsdt_conv_entries[i] = (uint64_t)rsdt_entries[i];
1532}
1533
1534xsdt_conv->Checksum = 0;
1535xsdt_conv->Checksum = 256-checksum8(xsdt_conv, xsdt_conv->Length);
1536
1537rsdp->XsdtAddress = (uint32_t)xsdt_conv;
1538
1539rsdp->ExtendedChecksum = 0;
1540rsdp->ExtendedChecksum = 256-checksum8(rsdp, rsdp->Length);
1541
1542verbose("Converted RSDT table to XSDT table\n");
1543}
1544
1545for (i=0;i<rsdt_entries_num;i++)
1546{
1547char *table=(char *)(rsdt_entries[i]);
1548if (!table)
1549continue;
1550
1551DBG("TABLE %c%c%c%c,",table[0],table[1],table[2],table[3]);
1552
1553rsdt_entries[i-dropoffset]=rsdt_entries[i];
1554if (drop_ssdt && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1555{
1556dropoffset++;
1557continue;
1558}
1559if (drop_hpet && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')
1560{
1561dropoffset++;
1562continue;
1563}
1564if (drop_slic && table[0]=='S' && table[1]=='L' && table[2]=='I' && table[3]=='C')
1565{
1566dropoffset++;
1567continue;
1568}
1569if (drop_sbst && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')
1570{
1571dropoffset++;
1572continue;
1573}
1574if (drop_ecdt && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')
1575{
1576dropoffset++;
1577continue;
1578}
1579if (drop_asft && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')
1580{
1581dropoffset++;
1582continue;
1583}
1584if (drop_dmar && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')
1585{
1586dropoffset++;
1587continue;
1588}
1589if ((!(oem_hpet)) && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')
1590{
1591DBG("HPET found\n");
1592if (new_hpet)
1593{
1594rsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
1595hpet_replaced=true;
1596}
1597continue;
1598}
1599if ((!(oem_sbst)) && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')
1600{
1601DBG("SBST found\n");
1602if (new_sbst)
1603{
1604rsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
1605sbst_replaced=true;
1606}
1607continue;
1608}
1609if ((!(oem_ecdt)) && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')
1610{
1611DBG("ECDT found\n");
1612if (new_ecdt)
1613{
1614rsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
1615ecdt_replaced=true;
1616}
1617continue;
1618}
1619if ((!(oem_asft)) && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')
1620{
1621DBG("ASF! found\n");
1622if (new_asft)
1623{
1624rsdt_entries[i-dropoffset]=(uint32_t)new_asft;
1625asft_replaced=true;
1626}
1627continue;
1628}
1629if ((!(oem_dmar)) && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')
1630{
1631DBG("DMAR found\n");
1632if (new_dmar)
1633{
1634rsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
1635dmar_replaced=true;
1636}
1637continue;
1638}
1639if ((!(oem_apic)) && table[0]=='A' && table[1]=='P' && table[2]=='I' && table[3]=='C')
1640{
1641DBG("APIC found\n");
1642if (new_apic)
1643{
1644rsdt_entries[i-dropoffset]=(uint32_t)new_apic;
1645apic_replaced=true;
1646}
1647continue;
1648}
1649if ((!(oem_mcfg)) && table[0]=='M' && table[1]=='C' && table[2]=='F' && table[3]=='G')
1650{
1651DBG("MCFG found\n");
1652if (new_mcfg)
1653{
1654rsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
1655mcfg_replaced=true;
1656}
1657continue;
1658}
1659if ((!(oem_ssdt)) && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1660{
1661DBG("SSDT %d found", curssdt);
1662if (new_ssdt[curssdt])
1663{
1664DBG(" and replaced");
1665rsdt_entries[i-dropoffset]=(uint32_t)new_ssdt[curssdt];
1666totssdt++;
1667}
1668DBG("\n");
1669curssdt++;
1670continue;
1671}
1672if (table[0]=='D' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1673{
1674DBG("DSDT found\n");
1675rsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;
1676continue;
1677
1678} else {
1679struct acpi_2_rsdt *t = (struct acpi_2_rsdt *)table;
1680strncpy(t->OEMID, "Apple ", 6);
1681strncpy(t->OEMTableId, MacModel, 8);
1682t->OEMRevision = ModelRev;
1683t->Checksum=0;
1684t->Checksum=256-checksum8(t,t->Length);
1685}
1686if (table[0]=='F' && table[1]=='A' && table[2]=='C' && table[3]=='P')
1687{
1688struct acpi_2_fadt *fadt_mod;
1689fadt=(struct acpi_2_fadt *)rsdt_entries[i];
1690
1691DBG("FADT found @%x, Length %d\n",fadt, fadt->Length);
1692
1693if (!fadt || (uint32_t)fadt == 0xffffffff || fadt->Length>0x10000)
1694{
1695printf("FADT incorrect. Not modified\n");
1696continue;
1697}
1698
1699fadt_mod = patch_fadt(fadt, new_dsdt, update_acpi);
1700rsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;
1701
1702if(!oem_ssdt)
1703{
1704// Generate _CST SSDT
1705if ( gen_cst && (new_ssdt[loadtotssdt] = generate_cst_ssdt(fadt_mod)))
1706{
1707gen_cst= false;
1708loadtotssdt++;
1709}
1710
1711// Generating _PSS SSDT
1712if (gen_pss && (new_ssdt[loadtotssdt] = generate_pss_ssdt((void*)fadt_mod->DSDT)))
1713{
1714gen_pss= false;
1715loadtotssdt++;
1716}
1717
1718// Generating _TSS SSDT
1719if (gen_tss && (new_ssdt[loadtotssdt] = generate_tss_ssdt((void*)fadt_mod->DSDT)))
1720{
1721gen_tss= false;
1722loadtotssdt++;
1723}
1724}
1725
1726continue;
1727}
1728}
1729DBG("\n");
1730
1731strncpy(rsdt_mod->OEMID, "Apple ", 6);
1732strncpy(rsdt_mod->OEMTableId, MacModel, 8);
1733rsdt_mod->OEMRevision = ModelRev;
1734
1735if ((!oem_hpet) && (!hpet_replaced))
1736{
1737if (new_hpet)
1738{
1739rsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
1740hpet_added=true;
1741i++;
1742}
1743}
1744
1745if ((!oem_sbst) && (!sbst_replaced))
1746{
1747if (new_sbst)
1748{
1749rsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
1750sbst_added=true;
1751i++;
1752}
1753}
1754
1755if ((!oem_ecdt) && (!ecdt_replaced))
1756{
1757if (new_ecdt)
1758{
1759rsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
1760ecdt_added=true;
1761i++;
1762}
1763}
1764
1765if ((!oem_asft) && (!asft_replaced))
1766{
1767if (new_asft)
1768{
1769rsdt_entries[i-dropoffset]=(uint32_t)new_asft;
1770asft_added=true;
1771i++;
1772}
1773}
1774
1775if ((!oem_dmar) && (!dmar_replaced))
1776{
1777if (new_dmar)
1778{
1779rsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
1780dmar_added=true;
1781i++;
1782}
1783}
1784
1785if ((!oem_apic) && (!apic_replaced))
1786{
1787if (new_apic)
1788{
1789rsdt_entries[i-dropoffset]=(uint32_t)new_apic;
1790apic_added=true;
1791i++;
1792}
1793}
1794
1795if ((!oem_mcfg) && (!mcfg_replaced))
1796{
1797if (new_mcfg)
1798{
1799rsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
1800mcfg_added=true;
1801i++;
1802}
1803}
1804
1805if (!oem_ssdt)
1806{
1807while ((totssdt < loadtotssdt) && (curssdt < 14))
1808{
1809if (new_ssdt[curssdt])
1810{
1811DBG("adding SSDT %d\n", curssdt);
1812rsdt_entries[i-dropoffset]=(uint32_t)new_ssdt[curssdt];
1813totssdt++;
1814newtotssdt++;
1815i++;
1816}
1817curssdt++;
1818}
1819}
1820
1821// Correct the checksum of RSDT
1822rsdt_mod->Length-=4*dropoffset;
1823rsdt_mod->Length+=4*newtotssdt;
1824if (hpet_added)
1825rsdt_mod->Length+=4;
1826if (sbst_added)
1827rsdt_mod->Length+=4;
1828if (ecdt_added)
1829rsdt_mod->Length+=4;
1830if (asft_added)
1831rsdt_mod->Length+=4;
1832if (dmar_added)
1833rsdt_mod->Length+=4;
1834if (apic_added)
1835rsdt_mod->Length+=4;
1836if (mcfg_added)
1837rsdt_mod->Length+=4;
1838
1839DBG("RSDT: Original checksum %d, ", rsdt_mod->Checksum);
1840
1841rsdt_mod->Checksum=0;
1842rsdt_mod->Checksum=256-checksum8(rsdt_mod,rsdt_mod->Length);
1843
1844DBG("New checksum %d at %x\n", rsdt_mod->Checksum,rsdt_mod);
1845}
1846else
1847{
1848rsdp_mod->RsdtAddress=0;
1849printf("RSDT not found or incorrect\n");
1850}
1851
1852if (version)
1853{
1854struct acpi_2_xsdt *xsdt, *xsdt_mod;
1855
1856// FIXME: handle 64-bit address correctly
1857
1858if (gen_xsdt)
1859xsdt=xsdt_conv;
1860else
1861xsdt=(struct acpi_2_xsdt*) ((uint32_t)rsdp->XsdtAddress);
1862
1863DBG("XSDT @%x;%x, Length=%d\n", (uint32_t)(rsdp->XsdtAddress>>32),(uint32_t)rsdp->XsdtAddress, xsdt->Length);
1864if (xsdt && (uint64_t)rsdp->XsdtAddress<0xffffffff && xsdt->Length<0x10000)
1865{
1866uint64_t *xsdt_entries;
1867int xsdt_entries_num, i;
1868int dropoffset=0;
1869curssdt=0, totssdt=0, newtotssdt=0;
1870hpet_replaced=false, hpet_added=false;
1871sbst_replaced=false, sbst_added=false;
1872ecdt_replaced=false, ecdt_added=false;
1873asft_replaced=false, asft_added=false;
1874dmar_replaced=false, dmar_added=false;
1875apic_replaced=false, apic_added=false;
1876mcfg_replaced=false, mcfg_added=false;
1877
1878if (gen_xsdt)
1879xsdt_mod=xsdt;
1880else
1881{
1882xsdt_mod=(struct acpi_2_xsdt*)AllocateKernelMemory(xsdt->Length);
1883memcpy(xsdt_mod, xsdt, xsdt->Length);
1884}
1885
1886rsdp_mod->XsdtAddress=(uint32_t)xsdt_mod;
1887xsdt_entries_num=(xsdt_mod->Length-sizeof(struct acpi_2_xsdt))/8;
1888xsdt_entries=(uint64_t *)(xsdt_mod+1);
1889for (i=0;i<xsdt_entries_num;i++)
1890{
1891char *table=(char *)((uint32_t)(xsdt_entries[i]));
1892if (!table)
1893continue;
1894xsdt_entries[i-dropoffset]=xsdt_entries[i];
1895if (drop_ssdt && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')
1896{
1897dropoffset++;
1898continue;
1899}
1900if (drop_hpet && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')
1901{
1902dropoffset++;
1903continue;
1904}
1905if (drop_slic && table[0]=='S' && table[1]=='L' && table[2]=='I' && table[3]=='C')
1906{
1907dropoffset++;
1908continue;
1909}
1910if (drop_sbst && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')
1911{
1912dropoffset++;
1913continue;
1914}
1915if (drop_ecdt && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')
1916{
1917dropoffset++;
1918continue;
1919}
1920if (drop_asft && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')
1921{
1922dropoffset++;
1923continue;
1924}
1925if (drop_dmar && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')
1926{
1927dropoffset++;
1928continue;
1929}
1930if ((!(oem_hpet)) && table[0]=='H' && table[1]=='P' && table[2]=='E' && table[3]=='T')
1931{
1932DBG("HPET found\n");
1933if (new_hpet)
1934{
1935xsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
1936hpet_replaced=true;
1937}
1938continue;
1939}
1940if ((!(oem_sbst)) && table[0]=='S' && table[1]=='B' && table[2]=='S' && table[3]=='T')
1941{
1942DBG("SBST found\n");
1943if (new_sbst)
1944{
1945xsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
1946sbst_replaced=true;
1947}
1948continue;
1949}
1950if ((!(oem_ecdt)) && table[0]=='E' && table[1]=='C' && table[2]=='D' && table[3]=='T')
1951{
1952DBG("ECDT found\n");
1953if (new_ecdt)
1954{
1955xsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
1956ecdt_replaced=true;
1957}
1958continue;
1959}
1960if ((!(oem_asft)) && table[0]=='A' && table[1]=='S' && table[2]=='F' && table[3]=='!')
1961{
1962DBG("ASF! found\n");
1963if (new_asft)
1964{
1965xsdt_entries[i-dropoffset]=(uint32_t)new_asft;
1966asft_replaced=true;
1967}
1968continue;
1969}
1970if ((!(oem_dmar)) && table[0]=='D' && table[1]=='M' && table[2]=='A' && table[3]=='R')
1971{
1972DBG("DMAR found\n");
1973if (new_dmar)
1974{
1975xsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
1976dmar_replaced=true;
1977}
1978continue;
1979}
1980if ((!(oem_apic)) && table[0]=='A' && table[1]=='P' && table[2]=='I' && table[3]=='C')
1981{
1982DBG("APIC found\n");
1983if (new_apic)
1984{
1985xsdt_entries[i-dropoffset]=(uint32_t)new_apic;
1986apic_replaced=true;
1987}
1988continue;
1989}
1990if ((!(oem_mcfg)) && table[0]=='M' && table[1]=='C' && table[2]=='F' && table[3]=='G')
1991{
1992DBG("MCFG found\n");
1993if (new_mcfg)
1994{
1995xsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
1996mcfg_replaced=true;
1997}
1998continue;
1999}
2000if ((!(oem_ssdt)) && table[0]=='S' && table[1]=='S' && table[2]=='D' && table[3]=='T')
2001{
2002DBG("SSDT %d found", curssdt);
2003if (new_ssdt[curssdt])
2004{
2005DBG(" and replaced");
2006xsdt_entries[i-dropoffset]=(uint32_t)new_ssdt[curssdt];
2007totssdt++;
2008}
2009DBG("\n");
2010curssdt++;
2011continue;
2012}
2013if (table[0]=='D' && table[1]=='S' && table[2]=='D' && table[3]=='T')
2014{
2015DBG("DSDT found\n");
2016
2017xsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;
2018
2019DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
2020
2021continue;
2022}
2023
2024struct acpi_2_xsdt* t = (struct acpi_2_xsdt*)table;
2025strncpy(t->OEMID, "Apple ", 6);
2026strncpy(t->OEMTableId, MacModel, 8);
2027t->OEMRevision = ModelRev;
2028
2029if (table[0]=='F' && table[1]=='A' && table[2]=='C' && table[3]=='P')
2030{
2031struct acpi_2_fadt *fadt_mod;
2032fadt=(struct acpi_2_fadt *)(uint32_t)xsdt_entries[i];
2033
2034DBG("FADT found @%x,%x, Length %d\n",(uint32_t)(xsdt_entries[i]>>32),fadt,
2035 fadt->Length);
2036
2037if (!fadt || (uint64_t)xsdt_entries[i] >= 0xffffffff || fadt->Length>0x10000)
2038{
2039verbose("FADT incorrect or after 4GB. Dropping XSDT\n");
2040goto drop_xsdt;
2041}
2042
2043fadt_mod = patch_fadt(fadt, new_dsdt, update_acpi);
2044xsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;
2045
2046DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
2047
2048if (!oem_ssdt)
2049{
2050// Generate _CST SSDT
2051if ( gen_cst && (new_ssdt[loadtotssdt] = generate_cst_ssdt(fadt_mod)))
2052{
2053gen_cst= false;
2054loadtotssdt++;
2055}
2056
2057// Generating _PSS SSDT
2058if (gen_pss && (new_ssdt[loadtotssdt] = generate_pss_ssdt((void*)fadt_mod->DSDT)))
2059{
2060gen_pss= false;
2061loadtotssdt++;
2062}
2063
2064// Generating _TSS SSDT
2065if (gen_tss && (new_ssdt[loadtotssdt] = generate_tss_ssdt((void*)fadt_mod->DSDT)))
2066{
2067gen_tss= false;
2068loadtotssdt++;
2069}
2070}
2071
2072continue;
2073}
2074
2075DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);
2076
2077}
2078
2079strncpy(xsdt_mod->OEMID, "Apple ", 6);
2080strncpy(xsdt_mod->OEMTableId, MacModel, 8);
2081xsdt_mod->OEMRevision = ModelRev;
2082
2083if ((!oem_hpet) && (!hpet_replaced))
2084{
2085if (new_hpet)
2086{
2087xsdt_entries[i-dropoffset]=(uint32_t)new_hpet;
2088hpet_added=true;
2089i++;
2090}
2091}
2092
2093if ((!oem_sbst) && (!sbst_replaced))
2094{
2095if (new_sbst)
2096{
2097xsdt_entries[i-dropoffset]=(uint32_t)new_sbst;
2098sbst_added=true;
2099i++;
2100}
2101}
2102
2103if ((!oem_ecdt) && (!ecdt_replaced))
2104{
2105if (new_ecdt)
2106{
2107xsdt_entries[i-dropoffset]=(uint32_t)new_ecdt;
2108ecdt_added=true;
2109i++;
2110}
2111}
2112
2113if ((!oem_asft) && (!asft_replaced))
2114{
2115if (new_asft)
2116{
2117xsdt_entries[i-dropoffset]=(uint32_t)new_asft;
2118asft_added=true;
2119i++;
2120}
2121}
2122
2123if ((!oem_dmar) && (!dmar_replaced))
2124{
2125if (new_dmar)
2126{
2127xsdt_entries[i-dropoffset]=(uint32_t)new_dmar;
2128dmar_added=true;
2129i++;
2130}
2131}
2132
2133if ((!oem_apic) && (!apic_replaced))
2134{
2135if (new_apic)
2136{
2137xsdt_entries[i-dropoffset]=(uint32_t)new_apic;
2138apic_added=true;
2139i++;
2140}
2141}
2142
2143if ((!oem_mcfg) && (!mcfg_replaced))
2144{
2145if (new_mcfg)
2146{
2147xsdt_entries[i-dropoffset]=(uint32_t)new_mcfg;
2148mcfg_added=true;
2149i++;
2150}
2151}
2152
2153if (!oem_ssdt)
2154{
2155while ((totssdt < loadtotssdt) && (curssdt < 14))
2156{
2157if (new_ssdt[curssdt])
2158{
2159DBG("adding SSDT %d\n", curssdt);
2160xsdt_entries[i-dropoffset]=(uint32_t)new_ssdt[curssdt];
2161totssdt++;
2162newtotssdt++;
2163i++;
2164}
2165curssdt++;
2166}
2167}
2168
2169// Correct the checksum of XSDT
2170xsdt_mod->Length-=8*dropoffset;
2171xsdt_mod->Length+=8*newtotssdt;
2172if (hpet_added)
2173xsdt_mod->Length+=8;
2174if (sbst_added)
2175xsdt_mod->Length+=8;
2176if (ecdt_added)
2177xsdt_mod->Length+=8;
2178if (asft_added)
2179xsdt_mod->Length+=8;
2180if (dmar_added)
2181xsdt_mod->Length+=8;
2182if (apic_added)
2183xsdt_mod->Length+=8;
2184if (mcfg_added)
2185xsdt_mod->Length+=8;
2186
2187xsdt_mod->Checksum=0;
2188xsdt_mod->Checksum=256-checksum8(xsdt_mod,xsdt_mod->Length);
2189}
2190else
2191{
2192drop_xsdt:
2193
2194DBG("About to drop XSDT\n");
2195
2196/*FIXME: Now we just hope that if MacOS doesn't find XSDT it reverts to RSDT.
2197 * A Better strategy would be to generate
2198 */
2199
2200rsdp_mod->XsdtAddress=0xffffffffffffffffLL;
2201verbose("XSDT not found or incorrect\n");
2202}
2203}
2204
2205// Correct the checksum of RSDP
2206
2207DBG("RSDP: Original checksum %d, ", rsdp_mod->Checksum);
2208
2209rsdp_mod->Checksum=0;
2210rsdp_mod->Checksum=256-checksum8(rsdp_mod,20);
2211
2212DBG("New checksum %d\n", rsdp_mod->Checksum);
2213
2214if (version)
2215{
2216DBG("RSDP: Original extended checksum %d", rsdp_mod->ExtendedChecksum);
2217
2218rsdp_mod->ExtendedChecksum=0;
2219rsdp_mod->ExtendedChecksum=256-checksum8(rsdp_mod,rsdp_mod->Length);
2220
2221DBG("New extended checksum %d\n", rsdp_mod->ExtendedChecksum);
2222
2223}
2224
2225verbose("Patched ACPI version %d DSDT\n", version+1);
2226if (version)
2227{
2228/* XXX aserebln why uint32 cast if pointer is uint64 ? */
2229acpi20_p = (uint32_t)rsdp_mod;
2230acpi10_p = (uint32_t)rsdp_mod;
2231addConfigurationTable(&gEfiAcpi20TableGuid, &acpi20_p, "ACPI_20");
2232addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
2233}
2234else
2235{
2236/* XXX aserebln why uint32 cast if pointer is uint64 ? */
2237acpi10_p = (uint32_t)rsdp_mod;
2238addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");
2239}
2240}
2241#if DEBUG_ACPI
2242printf("Press a key to continue... (DEBUG_ACPI)\n");
2243getc();
2244#endif
2245return 1;
2246}
2247

Archive Download this file

Revision: HEAD