| if(*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE)␊ |
| {␊ |
| uint8_t csum = checksum8(acpi_addr, 20);␊ |
| ␉␉␉␊ |
| ␊ |
| /* Only assume this is a 2.0 or better table if the revision is greater than 0␊ |
| * NOTE: ACPI 3.0 spec only seems to say that 1.0 tables have revision 1␊ |
| * and that the current revision is 2.. I am going to assume that rev > 0 is 2.0.␊ |
| */␊ |
| ␉␉␉␊ |
| ␊ |
| if(csum == 0 && (((struct acpi_2_rsdp*)acpi_addr)->Revision > 0))␊ |
| {␊ |
| uint8_t csum2 = checksum8(acpi_addr, sizeof(struct acpi_2_rsdp));␊ |
|
| }␊ |
| return NULL;␊ |
| }␊ |
| /** The folowing ACPI Table search algo. should be reused anywhere needed:*/␊ |
| ␊ |
| /* The folowing ACPI Table search algo. should be reused anywhere needed:*/␊ |
| int search_and_get_acpi_fd(const char * filename, const char ** outDirspec)␊ |
| {␊ |
| ␉int fd = 0;␊ |
|
| ␉fd = open(dirSpec, 0);␊ |
| ␉if (fd < 0)␊ |
| ␉{␉␊ |
| ␉␉sprintf(dirSpec, "/Extra/%s", filename); ␊ |
| ␉␉sprintf(dirSpec, "/Extra/%s", filename);␊ |
| ␉␉fd = open(dirSpec, 0);␊ |
| ␉␉if (fd < 0)␊ |
| ␉␉{␊ |
|
| ␉return fd;␊ |
| }␊ |
| ␊ |
| ␊ |
| void *loadACPITable (const char * filename)␊ |
| {␊ |
| ␉void *tableAddr;␊ |
| ␉const char * dirspec=NULL;␊ |
| ␉␊ |
| ␊ |
| ␉int fd = search_and_get_acpi_fd(filename, &dirspec);␊ |
| ␉␊ |
| ␊ |
| ␉if (fd>=0)␊ |
| ␉{␊ |
| ␉␉tableAddr=(void*)AllocateKernelMemory(file_size (fd));␊ |
|
| void get_acpi_cpu_names(unsigned char* dsdt, uint32_t length)␊ |
| {␊ |
| ␉uint32_t i;␊ |
| ␊ |
| ␉// DBG("start finding cpu names. length %d\n", length);␊ |
| ␊ |
| ␉for (i=0; i<length-7; i++) ␊ |
| ␉{␊ |
| ␉␉if (dsdt[i] == 0x5B && dsdt[i+1] == 0x83) // ProcessorOP␊ |
|
| ␉␉// DBG("dsdt: %x%x\n", dsdt[i], dsdt[i+1]);␊ |
| ␊ |
| ␉␉␉uint32_t offset = i + 3 + (dsdt[i+2] >> 6);␊ |
| ␉␉␉␊ |
| ␊ |
| ␉␉␉bool add_name = true;␊ |
| ␊ |
| ␉␉␉uint8_t j;␊ |
| ␉␉␉␊ |
| ␊ |
| ␉␉␉for (j=0; j<4; j++) ␊ |
| ␉␉␉{␊ |
| ␉␉␉␉char c = dsdt[offset+j];␊ |
| ␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉if (!aml_isvalidchar(c)) ␊ |
| ␉␉␉␉{␊ |
| ␉␉␉␉␉add_name = false;␊ |
|
| ␉␉␉␉␉break;␊ |
| ␉␉␉␉}␊ |
| ␉␉␉}␊ |
| ␉␉␉␊ |
| ␉␉␉if (add_name) ␊ |
| ␊ |
| ␉␉␉if (add_name)␊ |
| ␉␉␉{␊ |
| ␉␉␉␉acpi_cpu_name[acpi_cpu_count] = malloc(4);␊ |
| ␉␉␉␉memcpy(acpi_cpu_name[acpi_cpu_count], dsdt+offset, 4);␊ |
|
| ␉␉0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,␊ |
| ␉␉0x00, 0x00, 0x01, 0x79, 0x00␊ |
| ␉};␊ |
| ␉␊ |
| ␊ |
| ␉char resource_template_register_systemio[] =␊ |
| ␉{␊ |
| ␉␉0x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00, 0x01,␊ |
| ␉␉0x08, 0x00, 0x00, 0x15, 0x04, 0x00, 0x00, 0x00,␊ |
| ␉␉0x00, 0x00, 0x00, 0x79, 0x00,␊ |
| ␉};␊ |
| ␉␊ |
| ␊ |
| ␉if (Platform.CPU.Vendor != 0x756E6547) {␊ |
| ␉␉verbose ("Not an Intel platform: C-States will not be generated !!!\n");␊ |
| ␉␉return NULL;␊ |
| ␉}␊ |
| ␉␊ |
| ␊ |
| ␉if (fadt == NULL) {␊ |
| ␉␉verbose ("FACP not exists: C-States will not be generated !!!\n");␊ |
| ␉␉return NULL;␊ |
| ␉}␊ |
| ␉␊ |
| ␊ |
| ␉struct acpi_2_dsdt* dsdt = (void*)fadt->DSDT;␊ |
| ␉␊ |
| ␊ |
| ␉if (dsdt == NULL) {␊ |
| ␉␉verbose ("DSDT not found: C-States will not be generated !!!\n");␊ |
| ␉␉return NULL;␊ |
| ␉}␊ |
| ␉␊ |
| ␊ |
| ␉if (acpi_cpu_count == 0)␊ |
| ␉␉get_acpi_cpu_names((void*)dsdt, dsdt->Length);␊ |
| ␉␊ |
| ␊ |
| ␉if (acpi_cpu_count > 0)␊ |
| ␉{␊ |
| ␉␉bool c2_enabled = false;␊ |
| ␉␉bool c3_enabled = false;␊ |
| ␉␉bool c4_enabled = false;␊ |
| ␉␉bool cst_using_systemio = false;␊ |
| ␉␉␊ |
| ␊ |
| ␉␉getBoolForKey(kEnableC2State, &c2_enabled, &bootInfo->chameleonConfig);␊ |
| ␉␉getBoolForKey(kEnableC3State, &c3_enabled, &bootInfo->chameleonConfig);␊ |
| ␉␉getBoolForKey(kEnableC4State, &c4_enabled, &bootInfo->chameleonConfig);␊ |
| ␉␉getBoolForKey(kCSTUsingSystemIO, &cst_using_systemio, &bootInfo->chameleonConfig);␊ |
| ␉␉␊ |
| ␊ |
| ␉␉c2_enabled = c2_enabled | (fadt->C2_Latency < 100);␊ |
| ␉␉c3_enabled = c3_enabled | (fadt->C3_Latency < 1000);␊ |
| ␊ |
| ␉␉unsigned char cstates_count = 1 + (c2_enabled ? 1 : 0) + (c3_enabled ? 1 : 0);␊ |
| ␉␉␊ |
| ␊ |
| ␉␉struct aml_chunk* root = aml_create_node(NULL);␊ |
| ␉␉aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header␊ |
| ␉␉struct aml_chunk* scop = aml_add_scope(root, "\\_PR_");␊ |
| ␉␉struct aml_chunk* name = aml_add_name(scop, "CST_");␊ |
| ␉␉struct aml_chunk* pack = aml_add_package(name);␊ |
| ␉␉aml_add_byte(pack, cstates_count);␊ |
| ␉␉␊ |
| ␊ |
| ␉␉struct aml_chunk* tmpl = aml_add_package(pack);␊ |
| ␉␉if (cst_using_systemio)␊ |
| ␉␉{␊ |
|
| ␉␉␉aml_add_byte(tmpl, 0x01); // C1␊ |
| ␉␉␉aml_add_word(tmpl, 0x0001); // Latency␊ |
| ␉␉␉aml_add_dword(tmpl, 0x000003e8); // Power␊ |
| ␉␉␉␊ |
| ␊ |
| ␉␉␉uint8_t p_blk_lo, p_blk_hi;␊ |
| ␉␉␉␊ |
| ␊ |
| ␉␉␉if (c2_enabled) // C2␊ |
| ␉␉␉{␊ |
| ␉␉␉␉p_blk_lo = acpi_cpu_p_blk + 4;␊ |
| ␉␉␉␉p_blk_hi = (acpi_cpu_p_blk + 4) >> 8;␊ |
| ␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉tmpl = aml_add_package(pack);␊ |
| ␉␉␉␉resource_template_register_systemio[11] = p_blk_lo; // C2␊ |
| ␉␉␉␉resource_template_register_systemio[12] = p_blk_hi; // C2␊ |
|
| ␉␉␉␉aml_add_word(tmpl, 0x0040); // Latency␊ |
| ␉␉␉␉aml_add_dword(tmpl, 0x000001f4); // Power␊ |
| ␉␉␉}␊ |
| ␉␉␉␊ |
| ␊ |
| ␉␉␉if (c4_enabled) // C4␊ |
| ␉␉␉{␊ |
| ␉␉␉␉p_blk_lo = acpi_cpu_p_blk + 5;␊ |
| ␉␉␉␉p_blk_hi = (acpi_cpu_p_blk + 5) >> 8;␊ |
| ␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉tmpl = aml_add_package(pack);␊ |
| ␉␉␉␉resource_template_register_systemio[11] = p_blk_lo; // C4␊ |
| ␉␉␉␉resource_template_register_systemio[12] = p_blk_hi; // C4␊ |
|
| ␉␉␉{␊ |
| ␉␉␉␉p_blk_lo = acpi_cpu_p_blk + 5;␊ |
| ␉␉␉␉p_blk_hi = (acpi_cpu_p_blk + 5) >> 8;␊ |
| ␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉tmpl = aml_add_package(pack);␊ |
| ␉␉␉␉resource_template_register_systemio[11] = p_blk_lo; // C3␊ |
| ␉␉␉␉resource_template_register_systemio[12] = p_blk_hi; // C3␊ |
|
| ␉␉␉aml_add_byte(tmpl, 0x01);␉␉␉// C1␊ |
| ␉␉␉aml_add_word(tmpl, 0x0001);␉␉␉// Latency␊ |
| ␉␉␉aml_add_dword(tmpl, 0x000003e8);␉// Power␊ |
| ␉␉␉␊ |
| ␊ |
| ␉␉␉resource_template_register_fixedhw[18] = 0x03;␊ |
| ␉␉␉␊ |
| ␊ |
| ␉␉␉if (c2_enabled) // C2␊ |
| ␉␉␉{␊ |
| ␉␉␉␉tmpl = aml_add_package(pack);␊ |
|
| ␉␉␉␉aml_add_word(tmpl, 0x0040);␉␉␉// Latency␊ |
| ␉␉␉␉aml_add_dword(tmpl, 0x000001f4);␉// Power␊ |
| ␉␉␉}␊ |
| ␉␉␉␊ |
| ␊ |
| ␉␉␉if (c4_enabled) // C4␊ |
| ␉␉␉{␊ |
| ␉␉␉␉tmpl = aml_add_package(pack);␊ |
|
| ␉␉␉␉aml_add_dword(tmpl, 0x0000015e);␉// Power␊ |
| ␉␉␉}␊ |
| ␉␉}␊ |
| ␉␉␊ |
| ␊ |
| ␉␉// Aliaces␊ |
| ␉␉int i;␊ |
| ␉␉for (i = 0; i < acpi_cpu_count; i++) ␊ |
| ␉␉{␊ |
| ␉␉␉char name[9];␊ |
| ␉␉␉sprintf(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]);␊ |
| ␉␉␉␊ |
| ␊ |
| ␉␉␉scop = aml_add_scope(root, name);␊ |
| ␉␉␉␉aml_add_alias(scop, "CST_", "_CST");␊ |
| ␉␉}␊ |
| ␉␉␊ |
| ␊ |
| ␉␉aml_calculate_size(root);␊ |
| ␉␉␊ |
| ␊ |
| ␉␉struct acpi_2_ssdt *ssdt = (struct acpi_2_ssdt *)AllocateKernelMemory(root->Size);␊ |
| ␉␊ |
| ␊ |
| ␉␉aml_write_node(root, (void*)ssdt, 0);␊ |
| ␉␉␊ |
| ␊ |
| ␉␉ssdt->Length = root->Size;␊ |
| ␉␉ssdt->Checksum = 0;␊ |
| ␉␉ssdt->Checksum = 256 - checksum8(ssdt, ssdt->Length);␊ |
| ␉␉␊ |
| ␊ |
| ␉␉aml_destroy_node(root);␊ |
| ␉␉␊ |
| ␊ |
| ␉␉// dumpPhysAddr("C-States SSDT content: ", ssdt, ssdt->Length);␊ |
| ␉␉␊ |
| ␉␉verbose ("SSDT with CPU C-States generated successfully\n");␊ |
| ␉␉␊ |
| ␊ |
| ␉␉return ssdt;␊ |
| ␉}␊ |
| ␉else␊ |
|
| }␊ |
| ␊ |
| struct acpi_2_ssdt *generate_pss_ssdt(struct acpi_2_dsdt* dsdt)␊ |
| {␉␊ |
| {␊ |
| ␉char ssdt_header[] =␊ |
| ␉{␊ |
| ␉␉0x53, 0x53, 0x44, 0x54, 0x7E, 0x00, 0x00, 0x00, /* SSDT.... */␊ |
|
| ␉␉verbose ("Not an Intel platform: P-States will not be generated !!!\n");␊ |
| ␉␉return NULL;␊ |
| ␉}␊ |
| ␉␊ |
| ␊ |
| ␉if (!(Platform.CPU.Features & CPU_FEATURE_MSR)) {␊ |
| ␉␉verbose ("Unsupported CPU: P-States will not be generated !!! No MSR support\n");␊ |
| ␉␉return NULL;␊ |
| ␉}␊ |
| ␉␊ |
| ␉if (acpi_cpu_count == 0) ␊ |
| ␊ |
| ␉if (acpi_cpu_count == 0)␊ |
| ␉␉get_acpi_cpu_names((void*)dsdt, dsdt->Length);␊ |
| ␉␊ |
| ␉if (acpi_cpu_count > 0) ␊ |
| ␉if (acpi_cpu_count > 0)␊ |
| ␉{␊ |
| ␉␉struct p_state initial, maximum, minimum, p_states[32];␊ |
| ␉␉uint8_t p_states_count = 0;␉␉␊ |
| ␉␉␊ |
| ␉␉uint8_t p_states_count = 0;␊ |
| ␊ |
| ␉␉// Retrieving P-States, ported from code by superhai (c)␊ |
| ␉␉switch (Platform.CPU.Family) {␊ |
| ␉␉␉case 0x06: ␊ |
| ␉␉␉case 0x06:␊ |
| ␉␉␉{␊ |
| ␉␉␉␉switch (Platform.CPU.Model) ␊ |
| ␉␉␉␉{␊ |
|
| ␉␉␉␉␉case CPU_MODEL_ATOM:␉// Intel Atom (45nm)␊ |
| ␉␉␉␉␉{␊ |
| ␉␉␉␉␉␉bool cpu_dynamic_fsb = false;␊ |
| ␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉if (rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 27)) ␊ |
| ␉␉␉␉␉␉{␊ |
| ␉␉␉␉␉␉␉wrmsr64(MSR_IA32_EXT_CONFIG, (rdmsr64(MSR_IA32_EXT_CONFIG) | (1 << 28))); ␊ |
| ␉␉␉␉␉␉␉delay(1);␊ |
| ␉␉␉␉␉␉␉cpu_dynamic_fsb = rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 28);␊ |
| ␉␉␉␉␉␉}␊ |
| ␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉bool cpu_noninteger_bus_ratio = (rdmsr64(MSR_IA32_PERF_STATUS) & (1ULL << 46));␊ |
| ␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉initial.Control = rdmsr64(MSR_IA32_PERF_STATUS);␊ |
| ␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉maximum.Control = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 32) & 0x1F3F) | (0x4000 * cpu_noninteger_bus_ratio);␊ |
| ␉␉␉␉␉␉maximum.CID = ((maximum.FID & 0x1F) << 1) | cpu_noninteger_bus_ratio;␊ |
| ␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉minimum.FID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 24) & 0x1F) | (0x80 * cpu_dynamic_fsb);␊ |
| ␉␉␉␉␉␉minimum.VID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 48) & 0x3F);␊ |
| ␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉if (minimum.FID == 0) ␊ |
| ␉␉␉␉␉␉{␊ |
| ␉␉␉␉␉␉␉uint64_t msr;␊ |
| ␉␉␉␉␉␉␉uint8_t i;␊ |
| ␉␉␉␉␉␉␉// Probe for lowest fid␊ |
| ␉␉␉␉␉␉␉for (i = maximum.FID; i >= 0x6; i--) ␊ |
| ␉␉␉␉␉␉␉for (i = maximum.FID; i >= 0x6; i--)␊ |
| ␉␉␉␉␉␉␉{␊ |
| ␉␉␉␉␉␉␉␉msr = rdmsr64(MSR_IA32_PERF_CONTROL);␊ |
| ␉␉␉␉␉␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (i << 8) | minimum.VID);␊ |
|
| ␉␉␉␉␉␉␉␉minimum.FID = (rdmsr64(MSR_IA32_PERF_STATUS) >> 8) & 0x1F; ␊ |
| ␉␉␉␉␉␉␉␉delay(1);␊ |
| ␉␉␉␉␉␉␉}␊ |
| ␉␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉␉msr = rdmsr64(MSR_IA32_PERF_CONTROL);␊ |
| ␉␉␉␉␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);␊ |
| ␉␉␉␉␉␉␉intel_waitforsts();␊ |
| ␉␉␉␉␉␉}␊ |
| ␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉if (minimum.VID == maximum.VID) ␊ |
| ␉␉␉␉␉␉{␉␊ |
| ␉␉␉␉␉␉{␊ |
| ␉␉␉␉␉␉␉uint64_t msr;␊ |
| ␉␉␉␉␉␉␉uint8_t i;␊ |
| ␉␉␉␉␉␉␉// Probe for lowest vid␊ |
|
| ␉␉␉␉␉␉␉␉minimum.VID = rdmsr64(MSR_IA32_PERF_STATUS) & 0x3F; ␊ |
| ␉␉␉␉␉␉␉␉delay(1);␊ |
| ␉␉␉␉␉␉␉}␊ |
| ␉␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉␉msr = rdmsr64(MSR_IA32_PERF_CONTROL);␊ |
| ␉␉␉␉␉␉␉wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);␊ |
| ␉␉␉␉␉␉␉intel_waitforsts();␊ |
| ␉␉␉␉␉␉}␊ |
| ␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉minimum.CID = ((minimum.FID & 0x1F) << 1) >> cpu_dynamic_fsb;␊ |
| ␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉// Sanity check␊ |
| ␉␉␉␉␉␉if (maximum.CID < minimum.CID) ␊ |
| ␉␉␉␉␉␉{␊ |
| ␉␉␉␉␉␉␉DBG("Insane FID values!");␊ |
| ␉␉␉␉␉␉␉DBG("P-States: Insane FID values!");␊ |
| ␉␉␉␉␉␉␉p_states_count = 0;␊ |
| ␉␉␉␉␉␉}␊ |
| ␉␉␉␉␉␉else␊ |
|
| ␉␉␉␉␉␉␉// Finalize P-States␊ |
| ␉␉␉␉␉␉␉// Find how many P-States machine supports␊ |
| ␉␉␉␉␉␉␉p_states_count = maximum.CID - minimum.CID + 1;␊ |
| ␉␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉␉if (p_states_count > 32) ␊ |
| ␉␉␉␉␉␉␉␉p_states_count = 32;␊ |
| ␉␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉␉uint8_t vidstep;␊ |
| ␉␉␉␉␉␉␉uint8_t i = 0, u, invalid = 0;␊ |
| ␉␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉␉vidstep = ((maximum.VID << 2) - (minimum.VID << 2)) / (p_states_count - 1);␊ |
| ␉␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉␉for (u = 0; u < p_states_count; u++) ␊ |
| ␉␉␉␉␉␉␉{␊ |
| ␉␉␉␉␉␉␉␉i = u - invalid;␊ |
| ␉␉␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉␉␉p_states[i].CID = maximum.CID - u;␊ |
| ␉␉␉␉␉␉␉␉p_states[i].FID = (p_states[i].CID >> 1);␊ |
| ␉␉␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉␉␉if (p_states[i].FID < 0x6) ␊ |
| ␉␉␉␉␉␉␉␉{␊ |
| ␉␉␉␉␉␉␉␉␉if (cpu_dynamic_fsb) ␊ |
| ␉␉␉␉␉␉␉␉␉␉p_states[i].FID = (p_states[i].FID << 1) | 0x80;␊ |
| ␉␉␉␉␉␉␉␉} ␊ |
| ␉␉␉␉␉␉␉␉}␊ |
| ␉␉␉␉␉␉␉␉else if (cpu_noninteger_bus_ratio) ␊ |
| ␉␉␉␉␉␉␉␉{␊ |
| ␉␉␉␉␉␉␉␉␉p_states[i].FID = p_states[i].FID | (0x40 * (p_states[i].CID & 0x1));␊ |
| ␉␉␉␉␉␉␉␉}␊ |
| ␉␉␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉␉␉if (i && p_states[i].FID == p_states[i-1].FID)␊ |
| ␉␉␉␉␉␉␉␉␉invalid++;␊ |
| ␉␉␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉␉␉p_states[i].VID = ((maximum.VID << 2) - (vidstep * u)) >> 2;␊ |
| ␉␉␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉␉␉uint32_t multiplier = p_states[i].FID & 0x1f;␉␉// = 0x08␊ |
| ␉␉␉␉␉␉␉␉bool half = p_states[i].FID & 0x40;␉␉␉␉␉// = 0x01␊ |
| ␉␉␉␉␉␉␉␉bool dfsb = p_states[i].FID & 0x80;␉␉␉␉␉// = 0x00␊ |
| ␉␉␉␉␉␉␉␉uint32_t fsb = Platform.CPU.FSBFrequency / 1000000; // = 400␊ |
| ␉␉␉␉␉␉␉␉uint32_t halffsb = (fsb + 1) >> 1;␉␉␉␉␉// = 200␊ |
| ␉␉␉␉␉␉␉␉uint32_t frequency = (multiplier * fsb);␉␉␉// = 3200␊ |
| ␉␉␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉␉␉p_states[i].Frequency = (frequency + (half * halffsb)) >> dfsb;␉// = 3200 + 200 = 3400␊ |
| ␉␉␉␉␉␉␉}␊ |
| ␉␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉␉p_states_count -= invalid;␊ |
| ␉␉␉␉␉␉}␊ |
| ␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉break;␊ |
| ␉␉␉␉␉} ␊ |
| ␉␉␉␉␉}␊ |
| ␉␉␉␉␉case CPU_MODEL_FIELDS:␉␉// Intel Core i5, i7, Xeon X34xx LGA1156 (45nm)␊ |
| ␉␉␉␉␉case CPU_MODEL_DALES:␉␉␊ |
| ␉␉␉␉␉case CPU_MODEL_DALES_32NM:␉// Intel Core i3, i5 LGA1156 (32nm)␊ |
|
| minimum.Control = (rdmsr64(MSR_PLATFORM_INFO) >> 40) & 0xff;␊ |
| ␊ |
| ␉␉␉␉␉␉verbose("P-States: min 0x%x, max 0x%x\n", minimum.Control, maximum.Control);␉␉␉␊ |
| ␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉// Sanity check␊ |
| ␉␉␉␉␉␉if (maximum.Control < minimum.Control) ␊ |
| ␉␉␉␉␉␉{␊ |
|
| ␉␉␉␉␉␉{␊ |
| ␉␉␉␉␉␉␉uint8_t i;␊ |
| ␉␉␉␉␉␉␉p_states_count = 0;␊ |
| ␉␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉␉for (i = maximum.Control; i >= minimum.Control; i--) ␊ |
| ␉␉␉␉␉␉␉{␊ |
| ␉␉␉␉␉␉␉␉p_states[p_states_count].Control = i;␊ |
|
| ␉␉␉␉␉␉}␊ |
| ␉␉␉␉␉␉␊ |
| ␉␉␉␉␉␉break;␊ |
| ␉␉␉␉␉}␉␊ |
| ␉␉␉␉␉}␊ |
| ␉␉␉␉␉default:␊ |
| ␉␉␉␉␉␉verbose ("Unsupported CPU: P-States not generated !!! Unknown CPU Type\n");␊ |
| ␉␉␉␉␉␉break;␊ |
| ␉␉␉␉}␊ |
| ␉␉␉}␊ |
| ␉␉}␊ |
| ␉␉␊ |
| ␊ |
| ␉␉// Generating SSDT␊ |
| ␉␉if (p_states_count > 0) ␊ |
| ␉␉{␉␊ |
| ␉␉if (p_states_count > 0)␊ |
| ␉␉{␊ |
| ␉␉␉int i;␊ |
| ␉␉␉␊ |
| ␊ |
| ␉␉␉struct aml_chunk* root = aml_create_node(NULL);␊ |
| ␉␉␉␉aml_add_buffer(root, ssdt_header, sizeof(ssdt_header)); // SSDT header␊ |
| ␉␉␉␉␉struct aml_chunk* scop = aml_add_scope(root, "\\_PR_");␊ |
| ␉␉␉␉␉␉struct aml_chunk* name = aml_add_name(scop, "PSS_");␊ |
| ␉␉␉␉␉␉␉struct aml_chunk* pack = aml_add_package(name);␊ |
| ␉␉␉␊ |
| ␉␉␉␉␉␉␉␉for (i = 0; i < p_states_count; i++) ␊ |
| ␉␉␉␉␉␉␉␉for (i = 0; i < p_states_count; i++)␊ |
| ␉␉␉␉␉␉␉␉{␊ |
| ␉␉␉␉␉␉␉␉␉struct aml_chunk* pstt = aml_add_package(pack);␊ |
| ␉␉␉␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉␉␉␉aml_add_dword(pstt, p_states[i].Frequency);␊ |
| ␉␉␉␉␉␉␉␉␉aml_add_dword(pstt, 0x00000000); // Power␊ |
| ␉␉␉␉␉␉␉␉␉aml_add_dword(pstt, 0x0000000A); // Latency␊ |
|
| ␉␉␉␉␉␉␉␉␉aml_add_dword(pstt, p_states[i].Control);␊ |
| ␉␉␉␉␉␉␉␉␉aml_add_dword(pstt, i+1); // Status␊ |
| ␉␉␉␉␉␉␉␉}␊ |
| ␉␉␉␉␊ |
| ␊ |
| ␉␉␉// Add aliaces␊ |
| ␉␉␉for (i = 0; i < acpi_cpu_count; i++) ␊ |
| ␉␉␉{␊ |
| ␉␉␉␉char name[9];␊ |
| ␉␉␉␉sprintf(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]);␊ |
| ␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉scop = aml_add_scope(root, name);␊ |
| ␉␉␉␉aml_add_alias(scop, "PSS_", "_PSS");␊ |
| ␉␉␉}␊ |
| ␉␉␉␊ |
| ␊ |
| ␉␉␉aml_calculate_size(root);␊ |
| ␉␉␉␊ |
| ␊ |
| ␉␉␉struct acpi_2_ssdt *ssdt = (struct acpi_2_ssdt *)AllocateKernelMemory(root->Size);␊ |
| ␉␉␉␊ |
| ␊ |
| ␉␉␉aml_write_node(root, (void*)ssdt, 0);␊ |
| ␉␉␉␊ |
| ␊ |
| ␉␉␉ssdt->Length = root->Size;␊ |
| ␉␉␉ssdt->Checksum = 0;␊ |
| ␉␉␉ssdt->Checksum = 256 - checksum8(ssdt, ssdt->Length);␊ |
| ␉␉␉␊ |
| ␊ |
| ␉␉␉aml_destroy_node(root);␊ |
| ␉␉␉␊ |
| ␊ |
| ␉␉␉//dumpPhysAddr("P-States SSDT content: ", ssdt, ssdt->Length);␊ |
| ␉␉␉␊ |
| ␊ |
| ␉␉␉verbose ("SSDT with CPU P-States generated successfully\n");␊ |
| ␉␉␉␊ |
| ␊ |
| ␉␉␉return ssdt;␊ |
| ␉␉}␊ |
| ␉}␊ |
|
| ␉{␊ |
| ␉␉verbose ("ACPI CPUs not found: P-States not generated !!!\n");␊ |
| ␉}␊ |
| ␉␊ |
| ␊ |
| ␉return NULL;␊ |
| }␊ |
| ␊ |
|
| ␉bool fadt_rev2_needed = false;␊ |
| ␉bool fix_restart;␊ |
| ␉const char * value;␊ |
| ␉␊ |
| ␊ |
| ␉// Restart Fix␊ |
| ␉if (Platform.CPU.Vendor == 0x756E6547) {␉/* Intel */␊ |
| ␉␉fix_restart = true;␊ |
|
| ␉␉verbose ("Not an Intel platform: Restart Fix not applied !!!\n");␊ |
| ␉␉fix_restart = false;␊ |
| ␉}␊ |
| ␉␊ |
| ␊ |
| ␉if (fix_restart) fadt_rev2_needed = true;␊ |
| ␉␊ |
| ␊ |
| ␉// Allocate new fadt table␊ |
| ␉if (fadt->Length < 0x84 && fadt_rev2_needed)␊ |
| ␉{␊ |
|
| ␉if (fadt_mod->PM_Profile != Platform.Type) ␊ |
| ␉{␊ |
| ␉ if (value) ␊ |
| ␉␉{ // user has overriden the SystemType so take care of it in FACP␊ |
| ␉␉␉verbose("FADT: changing PM_Profile from 0x%02x to 0x%02x\n", fadt_mod->PM_Profile, Platform.Type);␊ |
| ␉␉␉fadt_mod->PM_Profile = Platform.Type;␊ |
| ␉ { // user has overriden the SystemType so take care of it in FACP␊ |
| ␉␉verbose("FADT: changing PM_Profile from 0x%02x to 0x%02x\n", fadt_mod->PM_Profile, Platform.Type);␊ |
| ␉␉fadt_mod->PM_Profile = Platform.Type;␊ |
| ␉ }␊ |
| ␉ else␊ |
| ␉ { // PM_Profile has a different value and no override has been set, so reflect the user value to ioregs␊ |
| ␉␉␉Platform.Type = fadt_mod->PM_Profile <= 6 ? fadt_mod->PM_Profile : 1;␊ |
| ␉ Platform.Type = fadt_mod->PM_Profile <= 6 ? fadt_mod->PM_Profile : 1;␊ |
| ␉ } ␊ |
| ␉}␊ |
| ␉// We now have to write the systemm-type in ioregs: we cannot do it before in setupDeviceTree()␊ |
| ␉// because we need to take care of facp original content, if it is correct.␊ |
| ␉setupSystemType();␊ |
| ␉␊ |
| ␊ |
| ␉// Patch FADT to fix restart␊ |
| ␉if (fix_restart)␊ |
| ␉{␊ |
|
| ␉␉fadt_mod->Reset_AccessWidth␉= 0x01; // Byte access␊ |
| ␉␉fadt_mod->Reset_Address␉␉= 0x0cf9; // Address of the register␊ |
| ␉␉fadt_mod->Reset_Value␉␉= 0x06; // Value to write to reset the system␊ |
| ␉␉verbose("FADT: Restart Fix applied!\n");␊ |
| ␉␉verbose("FADT: Restart Fix applied !\n");␊ |
| ␉}␊ |
| ␉␊ |
| ␊ |
| ␉// Patch DSDT Address if we have loaded DSDT.aml␊ |
| ␉if(new_dsdt)␊ |
| ␉{␊ |
| ␉␉DBG("DSDT: Old @%x,%x, ",fadt_mod->DSDT,fadt_mod->X_DSDT);␊ |
| ␉␉␊ |
| ␊ |
| ␉␉fadt_mod->DSDT=(uint32_t)new_dsdt;␊ |
| ␉␉if ((uint32_t)(&(fadt_mod->X_DSDT))-(uint32_t)fadt_mod+8<=fadt_mod->Length)␊ |
| ␉␉␉fadt_mod->X_DSDT=(uint32_t)new_dsdt;␊ |
| ␉␉␊ |
| ␊ |
| ␉␉DBG("New @%x,%x\n",fadt_mod->DSDT,fadt_mod->X_DSDT);␊ |
| ␉␉␊ |
| ␉␉verbose("FADT: Using custom DSDT!\n");␊ |
| ␉}␊ |
| ␉␊ |
| ␊ |
| ␉// Correct the checksum␊ |
| ␉fadt_mod->Checksum=0;␊ |
| ␉fadt_mod->Checksum=256-checksum8(fadt_mod,fadt_mod->Length);␊ |
| ␉␊ |
| ␊ |
| ␉return fadt_mod;␊ |
| }␊ |
| ␊ |
| /* Setup ACPI without replacing DSDT. */␊ |
| int setupAcpiNoMod()␊ |
| {␊ |
| ␉//␉addConfigurationTable(&gEfiAcpiTableGuid, getAddressOfAcpiTable(), "ACPI");␊ |
| ␉//␉addConfigurationTable(&gEfiAcpi20TableGuid, getAddressOfAcpi20Table(), "ACPI_20");␊ |
| //␉addConfigurationTable(&gEfiAcpiTableGuid, getAddressOfAcpiTable(), "ACPI");␊ |
| //␉addConfigurationTable(&gEfiAcpi20TableGuid, getAddressOfAcpi20Table(), "ACPI_20");␊ |
| ␉/* XXX aserebln why uint32 cast if pointer is uint64 ? */␊ |
| ␉acpi10_p = (uint32_t)getAddressOfAcpiTable();␊ |
| ␉acpi20_p = (uint32_t)getAddressOfAcpi20Table();␊ |
|
| ␉{␊ |
| ␉␉sprintf(dirSpec, "DSDT.aml");␊ |
| ␉}␊ |
| ␉␊ |
| ␊ |
| ␉// Load replacement DSDT␊ |
| ␉new_dsdt = loadACPITable(dirSpec);␊ |
| ␉// Mozodojo: going to patch FACP and load SSDT's even if DSDT.aml is not present␊ |
|
| ␉ {␊ |
| ␉ return setupAcpiNoMod();␊ |
| ␉ }*/␊ |
| ␉␊ |
| ␊ |
| ␉// Mozodojo: Load additional SSDTs␊ |
| ␉struct acpi_2_ssdt *new_ssdt[32]; // 30 + 2 additional tables for pss & cst␊ |
| ␉int ssdt_count=0;␊ |
| ␉␊ |
| ␊ |
| ␉// SSDT Options␊ |
| ␉bool drop_ssdt=false, generate_pstates=false, generate_cstates=false; ␊ |
| ␉␊ |
| ␊ |
| ␉getBoolForKey(kDropSSDT, &drop_ssdt, &bootInfo->chameleonConfig);␊ |
| ␉getBoolForKey(kGeneratePStates, &generate_pstates, &bootInfo->chameleonConfig);␊ |
| ␉getBoolForKey(kGenerateCStates, &generate_cstates, &bootInfo->chameleonConfig);␊ |
|
| ␊ |
| ␉{␊ |
| ␉␉int i;␊ |
| ␉␉␊ |
| ␊ |
| ␉␉for (i=0; i<30; i++)␊ |
| ␉␉{␊ |
| ␉␉␉char filename[512];␊ |
| ␊ |
| ␉␉␉sprintf(filename, i>0?"SSDT-%d.aml":"SSDT.aml", i);␊ |
| ␉␉␉␊ |
| ␊ |
| ␉␉␉if ( (new_ssdt[ssdt_count] = loadACPITable(filename)) )␊ |
| ␉␉␉{␉␉␉␉␊ |
| ␉␉␉{␊ |
| ␉␉␉␉ssdt_count++;␊ |
| ␉␉␉}␊ |
| ␉␉␉else ␊ |
|
| ␉␉␉}␊ |
| ␉␉}␊ |
| ␉}␊ |
| ␉␉␊ |
| ␊ |
| ␉// Do the same procedure for both versions of ACPI␊ |
| ␉for (version=0; version<2; version++) {␊ |
| ␉␉struct acpi_2_rsdp *rsdp, *rsdp_mod;␊ |
| ␉␉struct acpi_2_rsdt *rsdt, *rsdt_mod;␊ |
| ␉␉int rsdplength;␊ |
| ␉␉␊ |
| ␊ |
| ␉␉// Find original rsdp␊ |
| ␉␉rsdp=(struct acpi_2_rsdp *)(version?getAddressOfAcpi20Table():getAddressOfAcpiTable());␊ |
| ␉␉if (!rsdp)␊ |
|
| ␉␉␉continue;␊ |
| ␉␉}␊ |
| ␉␉rsdplength=version?rsdp->Length:20;␊ |
| ␉␉␊ |
| ␊ |
| ␉␉DBG("RSDP version %d found @%x. Length=%d\n",version+1,rsdp,rsdplength);␊ |
| ␉␉␊ |
| ␊ |
| ␉␉/* FIXME: no check that memory allocation succeeded ␊ |
| ␉␉ * Copy and patch RSDP,RSDT, XSDT and FADT␊ |
| ␉␉ * For more info see ACPI Specification pages 110 and following␊ |
| ␉␉ */␊ |
| ␉␉␊ |
| ␊ |
| ␉␉rsdp_mod=(struct acpi_2_rsdp *) AllocateKernelMemory(rsdplength);␊ |
| ␉␉memcpy(rsdp_mod, rsdp, rsdplength); ␊ |
| ␉␉memcpy(rsdp_mod, rsdp, rsdplength);␊ |
| ␊ |
| ␉␉rsdt=(struct acpi_2_rsdt *)(rsdp->RsdtAddress);␊ |
| ␉␉␊ |
| ␊ |
| ␉␉DBG("RSDT @%x, Length %d\n",rsdt, rsdt->Length);␊ |
| ␉␉␊ |
| ␉␉if (rsdt && (uint32_t)rsdt !=0xffffffff && rsdt->Length<0x10000)␊ |
|
| ␉␉␉␉char *table=(char *)(rsdt_entries[i]);␊ |
| ␉␉␉␉if (!table)␊ |
| ␉␉␉␉␉continue;␊ |
| ␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉DBG("TABLE %c%c%c%c,",table[0],table[1],table[2],table[3]);␊ |
| ␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉rsdt_entries[i-dropoffset]=rsdt_entries[i];␊ |
| ␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉if (drop_ssdt && tableSign(table, "SSDT"))␊ |
| ␉␉␉␉{␊ |
| ␉␉␉␉␉dropoffset++;␊ |
|
| ␉␉␉␉if (tableSign(table, "DSDT"))␊ |
| ␉␉␉␉{␊ |
| ␉␉␉␉␉DBG("DSDT found\n");␊ |
| ␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉if(new_dsdt)␊ |
| ␉␉␉␉␉␉rsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;␊ |
| ␉␉␉␉␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉continue;␊ |
| ␉␉␉␉}␊ |
| ␉␉␉␉if (tableSign(table, "FACP"))␊ |
| ␉␉␉␉{␊ |
| ␉␉␉␉␉struct acpi_2_fadt *fadt, *fadt_mod;␊ |
| ␉␉␉␉␉fadt=(struct acpi_2_fadt *)rsdt_entries[i];␊ |
| ␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉DBG("FADT found @%x, Length %d\n",fadt, fadt->Length);␊ |
| ␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉if (!fadt || (uint32_t)fadt == 0xffffffff || fadt->Length>0x10000)␊ |
| ␉␉␉␉␉{␊ |
| ␉␉␉␉␉␉printf("FADT incorrect. Not modified\n");␊ |
|
| ␉␉␉␉␉␉generate_pstates = false; // Generate SSDT only once!␊ |
| ␉␉␉␉␉␉ssdt_count++;␊ |
| ␉␉␉␉␉}␊ |
| ␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉continue;␊ |
| ␉␉␉␉}␊ |
| ␉␉␉}␊ |
| ␉␉␉DBG("\n");␊ |
| ␉␉␉␊ |
| ␊ |
| ␉␉␉// Allocate rsdt in Kernel memory area␊ |
| ␉␉␉rsdt_mod->Length += 4*ssdt_count - 4*dropoffset;␊ |
| ␉␉␉struct acpi_2_rsdt *rsdt_copy = (struct acpi_2_rsdt *)AllocateKernelMemory(rsdt_mod->Length);␊ |
|
| ␉␉␉rsdp_mod->RsdtAddress=(uint32_t)rsdt_mod;␊ |
| ␉␉␉rsdt_entries_num=(rsdt_mod->Length-sizeof(struct acpi_2_rsdt))/4;␊ |
| ␉␉␉rsdt_entries=(uint32_t *)(rsdt_mod+1);␊ |
| ␉␉␉␊ |
| ␊ |
| ␉␉␉// Mozodojo: Insert additional SSDTs into RSDT␊ |
| ␉␉␉if(ssdt_count>0)␊ |
| ␉␉␉{␊ |
| ␉␉␉␉int j;␊ |
| ␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉for (j=0; j<ssdt_count; j++)␊ |
| ␉␉␉␉␉rsdt_entries[i-dropoffset+j]=(uint32_t)new_ssdt[j];␊ |
| ␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉verbose("RSDT: Added %d SSDT table(s)\n", ssdt_count);␊ |
| ␊ |
| ␉␉␉}␊ |
| ␊ |
| ␉␉␉// Correct the checksum of RSDT␊ |
| ␉␉␉DBG("RSDT: Original checksum %d, ", rsdt_mod->Checksum);␊ |
| ␉␉␉␊ |
| ␊ |
| ␉␉␉rsdt_mod->Checksum=0;␊ |
| ␉␉␉rsdt_mod->Checksum=256-checksum8(rsdt_mod,rsdt_mod->Length);␊ |
| ␉␉␉␊ |
| ␊ |
| ␉␉␉DBG("New checksum %d at %x\n", rsdt_mod->Checksum,rsdt_mod);␊ |
| ␉␉}␊ |
| ␉␉else␊ |
|
| ␉␉␉rsdp_mod->RsdtAddress=0;␊ |
| ␉␉␉printf("RSDT not found or RSDT incorrect\n");␊ |
| ␉␉}␊ |
| ␉␉␊ |
| ␊ |
| ␉␉if (version)␊ |
| ␉␉{␊ |
| ␉␉␉struct acpi_2_xsdt *xsdt, *xsdt_mod;␊ |
| ␉␉␉␊ |
| ␊ |
| ␉␉␉// FIXME: handle 64-bit address correctly␊ |
| ␉␉␉␊ |
| ␉␉␉xsdt=(struct acpi_2_xsdt*) ((uint32_t)rsdp->XsdtAddress);␊ |
| ␉␉␉DBG("XSDT @%x;%x, Length=%d\n", (uint32_t)(rsdp->XsdtAddress>>32),(uint32_t)rsdp->XsdtAddress,␊ |
| ␉␉␉␉xsdt->Length);␊ |
| ␉␉␉␉␉xsdt->Length);␊ |
| ␉␉␉if (xsdt && (uint64_t)rsdp->XsdtAddress<0xffffffff && xsdt->Length<0x10000)␊ |
| ␉␉␉{␊ |
| ␉␉␉␉uint64_t *xsdt_entries;␊ |
| ␉␉␉␉int xsdt_entries_num, i;␊ |
| ␉␉␉␉int dropoffset=0;␊ |
| ␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉// mozo: using malloc cos I didn't found how to free already allocated kernel memory␊ |
| ␉␉␉␉xsdt_mod=(struct acpi_2_xsdt*)malloc(xsdt->Length); ␊ |
| ␉␉␉␉memcpy(xsdt_mod, xsdt, xsdt->Length);␊ |
| ␊ |
| ␉␉␉␉rsdp_mod->XsdtAddress=(uint32_t)xsdt_mod;␊ |
| ␉␉␉␉xsdt_entries_num=(xsdt_mod->Length-sizeof(struct acpi_2_xsdt))/8;␊ |
| ␉␉␉␉xsdt_entries=(uint64_t *)(xsdt_mod+1);␊ |
|
| ␉␉␉␉␉char *table=(char *)((uint32_t)(xsdt_entries[i]));␊ |
| ␉␉␉␉␉if (!table)␊ |
| ␉␉␉␉␉␉continue;␊ |
| ␉␉␉␉␉␊ |
| ␉␉␉␉␉xsdt_entries[i-dropoffset]=xsdt_entries[i];␊ |
| ␉␉␉␉␉␊ |
| ␉␉␉␉␉if (drop_ssdt && tableSign(table, "SSDT"))␊ |
| ␉␉␉␉␉{␊ |
| ␉␉␉␉␉␉dropoffset++;␊ |
| ␉␉␉␉␉␉continue;␊ |
| ␉␉␉␉␉}␉␉␉␉␉␊ |
| ␉␉␉␉␉}␊ |
| ␉␉␉␉␉if (tableSign(table, "DSDT"))␊ |
| ␉␉␉␉␉{␊ |
| ␉␉␉␉␉␉DBG("DSDT found\n");␊ |
| ␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉if (new_dsdt) ␊ |
| ␉␉␉␉␉␉␉xsdt_entries[i-dropoffset]=(uint32_t)new_dsdt;␊ |
| ␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);␊ |
| ␉␉␉␉␉␉␊ |
| ␉␉␉␉␉␉continue;␊ |
|
| ␉␉␉␉␉{␊ |
| ␉␉␉␉␉␉struct acpi_2_fadt *fadt, *fadt_mod;␊ |
| ␉␉␉␉␉␉fadt=(struct acpi_2_fadt *)(uint32_t)xsdt_entries[i];␊ |
| ␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉DBG("FADT found @%x,%x, Length %d\n",(uint32_t)(xsdt_entries[i]>>32),fadt, ␊ |
| ␉␉␉␉␉␉␉fadt->Length);␊ |
| ␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉if (!fadt || (uint64_t)xsdt_entries[i] >= 0xffffffff || fadt->Length>0x10000)␊ |
| ␉␉␉␉␉␉{␊ |
| ␉␉␉␉␉␉␉verbose("FADT incorrect or after 4GB. Dropping XSDT\n");␊ |
| ␉␉␉␉␉␉␉goto drop_xsdt;␊ |
| ␉␉␉␉␉␉}␊ |
| ␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉fadt_mod = patch_fadt(fadt, new_dsdt);␊ |
| ␉␉␉␉␉␉xsdt_entries[i-dropoffset]=(uint32_t)fadt_mod;␊ |
| ␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);␊ |
| ␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉// Generate _CST SSDT␊ |
| ␉␉␉␉␉␉if (generate_cstates && (new_ssdt[ssdt_count] = generate_cst_ssdt(fadt_mod))) ␊ |
| ␉␉␉␉␉␉{␊ |
| ␉␉␉␉␉␉␉generate_cstates = false; // Generate SSDT only once!␊ |
| ␉␉␉␉␉␉␉ssdt_count++;␊ |
| ␉␉␉␉␉␉}␊ |
| ␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉// Generating _PSS SSDT␊ |
| ␉␉␉␉␉␉if (generate_pstates && (new_ssdt[ssdt_count] = generate_pss_ssdt((void*)fadt_mod->DSDT)))␊ |
| ␉␉␉␉␉␉{␊ |
| ␉␉␉␉␉␉␉generate_pstates = false; // Generate SSDT only once!␊ |
| ␉␉␉␉␉␉␉ssdt_count++;␊ |
| ␉␉␉␉␉␉}␊ |
| ␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉␉continue;␊ |
| ␉␉␉␉␉}␊ |
| ␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉DBG("TABLE %c%c%c%c@%x,",table[0],table[1],table[2],table[3],xsdt_entries[i]);␊ |
| ␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉}␊ |
| ␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉// Allocate xsdt in Kernel memory area␊ |
| ␉␉␉␉xsdt_mod->Length += 8*ssdt_count - 8*dropoffset;␊ |
| ␉␉␉␉struct acpi_2_xsdt *xsdt_copy = (struct acpi_2_xsdt *)AllocateKernelMemory(xsdt_mod->Length);␊ |
|
| ␉␉␉␉rsdp_mod->XsdtAddress=(uint32_t)xsdt_mod;␊ |
| ␉␉␉␉xsdt_entries_num=(xsdt_mod->Length-sizeof(struct acpi_2_xsdt))/8;␊ |
| ␉␉␉␉xsdt_entries=(uint64_t *)(xsdt_mod+1);␊ |
| ␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉// Mozodojo: Insert additional SSDTs into XSDT␊ |
| ␉␉␉␉if(ssdt_count>0)␊ |
| ␉␉␉␉{␊ |
| ␉␉␉␉␉int j;␊ |
| ␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉for (j=0; j<ssdt_count; j++)␊ |
| ␉␉␉␉␉␉xsdt_entries[i-dropoffset+j]=(uint32_t)new_ssdt[j];␊ |
| ␉␉␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉␉verbose("Added %d SSDT table(s) into XSDT\n", ssdt_count);␊ |
| ␊ |
| ␉␉␉␉}␊ |
| ␊ |
| ␉␉␉␉// Correct the checksum of XSDT␊ |
|
| ␉␉␉else␊ |
| ␉␉␉{␊ |
| ␉␉␉drop_xsdt:␊ |
| ␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉DBG("About to drop XSDT\n");␊ |
| ␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉/*FIXME: Now we just hope that if MacOS doesn't find XSDT it reverts to RSDT. ␊ |
| ␉␉␉␉ * A Better strategy would be to generate␊ |
| ␉␉␉␉ */␊ |
| ␉␉␉␉␊ |
| ␊ |
| ␉␉␉␉rsdp_mod->XsdtAddress=0xffffffffffffffffLL;␊ |
| ␉␉␉␉verbose("XSDT not found or XSDT incorrect\n");␊ |
| ␉␉␉␉verbose("XSDT not found or incorrect\n");␊ |
| ␉␉␉}␊ |
| ␉␉}␊ |
| ␉␉␊ |
| ␊ |
| ␉␉// Correct the checksum of RSDP ␊ |
| ␉␉␊ |
| ␊ |
| ␉␉DBG("RSDP: Original checksum %d, ", rsdp_mod->Checksum);␊ |
| ␉␉␊ |
| ␊ |
| ␉␉rsdp_mod->Checksum=0;␊ |
| ␉␉rsdp_mod->Checksum=256-checksum8(rsdp_mod,20);␊ |
| ␉␉␊ |
| ␊ |
| ␉␉DBG("New checksum %d\n", rsdp_mod->Checksum);␊ |
| ␉␉␊ |
| ␊ |
| ␉␉if (version)␊ |
| ␉␉{␊ |
| ␉␉␉DBG("RSDP: Original extended checksum %d", rsdp_mod->ExtendedChecksum);␊ |
| ␉␉␉␊ |
| ␊ |
| ␉␉␉rsdp_mod->ExtendedChecksum=0;␊ |
| ␉␉␉rsdp_mod->ExtendedChecksum=256-checksum8(rsdp_mod,rsdp_mod->Length);␊ |
| ␉␉␉␊ |
| ␊ |
| ␉␉␉DBG("New extended checksum %d\n", rsdp_mod->ExtendedChecksum);␊ |
| ␉␉␉␊ |
| ␊ |
| ␉␉}␊ |
| ␉␉␊ |
| ␉␉//verbose("Patched ACPI version %d DSDT\n", version+1);␊ |
|
| ␉␉}␊ |
| ␉␉else␊ |
| ␉␉{␊ |
| ␉␉␉/* XXX aserebln why uint32 cast if pointer is uint64 ? */␊ |
| ␉/* XXX aserebln why uint32 cast if pointer is uint64 ? */␊ |
| ␉␉␉acpi10_p = (uint32_t)rsdp_mod;␊ |
| ␉␉␉addConfigurationTable(&gEfiAcpiTableGuid, &acpi10_p, "ACPI");␊ |
| ␉␉}␊ |