ACPI_STATUS AcpiTbVerifyTempTable ( ACPI_TABLE_DESC *TableDesc, char *Signature) { ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_TRACE (TbVerifyTempTable); /* Validate the table */ Status = AcpiTbValidateTempTable (TableDesc); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (AE_NO_MEMORY); } /* If a particular signature is expected (DSDT/FACS), it must match */ if (Signature && !ACPI_COMPARE_NAME (&TableDesc->Signature, Signature)) { ACPI_BIOS_ERROR ((AE_INFO, "Invalid signature 0x%X for ACPI table, expected [%s]", TableDesc->Signature.Integer, Signature)); Status = AE_BAD_SIGNATURE; goto InvalidateAndExit; } /* Verify the checksum */ if (AcpiGbl_VerifyTableChecksum) { Status = AcpiTbVerifyChecksum (TableDesc->Pointer, TableDesc->Length); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY, "%4.4s 0x%8.8X%8.8X" " Attempted table install failed", AcpiUtValidAcpiName (TableDesc->Signature.Ascii) ? TableDesc->Signature.Ascii : "????", ACPI_FORMAT_UINT64 (TableDesc->Address))); goto InvalidateAndExit; } } return_ACPI_STATUS (AE_OK); InvalidateAndExit: AcpiTbInvalidateTable (TableDesc); return_ACPI_STATUS (Status); }
acpi_status acpi_tb_verify_temp_table(struct acpi_table_desc *table_desc, char *signature) { acpi_status status = AE_OK; ACPI_FUNCTION_TRACE(tb_verify_temp_table); /* Validate the table */ status = acpi_tb_validate_temp_table(table_desc); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(AE_NO_MEMORY); } /* If a particular signature is expected (DSDT/FACS), it must match */ if (signature && !ACPI_COMPARE_NAME(&table_desc->signature, signature)) { ACPI_BIOS_ERROR((AE_INFO, "Invalid signature 0x%X for ACPI table, expected [%s]", table_desc->signature.integer, signature)); status = AE_BAD_SIGNATURE; goto invalidate_and_exit; } /* Verify the checksum */ if (acpi_gbl_verify_table_checksum) { status = acpi_tb_verify_checksum(table_desc->pointer, table_desc->length); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, "%4.4s 0x%8.8X%8.8X" " Attempted table install failed", acpi_ut_valid_nameseg(table_desc-> signature. ascii) ? table_desc->signature.ascii : "????", ACPI_FORMAT_UINT64(table_desc-> address))); goto invalidate_and_exit; } } return_ACPI_STATUS(AE_OK); invalidate_and_exit: acpi_tb_invalidate_table(table_desc); return_ACPI_STATUS(status); }
void AcpiTbCheckDsdtHeader ( void) { /* Compare original length and checksum to current values */ if (AcpiGbl_OriginalDsdtHeader.Length != AcpiGbl_DSDT->Length || AcpiGbl_OriginalDsdtHeader.Checksum != AcpiGbl_DSDT->Checksum) { ACPI_BIOS_ERROR ((AE_INFO, "The DSDT has been corrupted or replaced - " "old, new headers below")); AcpiTbPrintTableHeader (0, &AcpiGbl_OriginalDsdtHeader); AcpiTbPrintTableHeader (0, AcpiGbl_DSDT); /* Disable further error messages */ AcpiGbl_OriginalDsdtHeader.Length = AcpiGbl_DSDT->Length; AcpiGbl_OriginalDsdtHeader.Checksum = AcpiGbl_DSDT->Checksum; } }
void acpi_tb_check_dsdt_header(void) { /* Compare original length and checksum to current values */ if (acpi_gbl_original_dsdt_header.length != acpi_gbl_DSDT->length || acpi_gbl_original_dsdt_header.checksum != acpi_gbl_DSDT->checksum) { ACPI_BIOS_ERROR((AE_INFO, "The DSDT has been corrupted or replaced - " "old, new headers below")); acpi_tb_print_table_header(0, &acpi_gbl_original_dsdt_header); acpi_tb_print_table_header(0, acpi_gbl_DSDT); ACPI_ERROR((AE_INFO, "Please send DMI info to [email protected]\n" "If system does not work as expected, please boot with acpi=copy_dsdt")); /* Disable further error messages */ acpi_gbl_original_dsdt_header.length = acpi_gbl_DSDT->length; acpi_gbl_original_dsdt_header.checksum = acpi_gbl_DSDT->checksum; } }
ACPI_STATUS AcpiTbParseRootTable ( ACPI_PHYSICAL_ADDRESS RsdpAddress) { ACPI_TABLE_RSDP *Rsdp; UINT32 TableEntrySize; UINT32 i; UINT32 TableCount; ACPI_TABLE_HEADER *Table; ACPI_PHYSICAL_ADDRESS Address; UINT32 Length; UINT8 *TableEntry; ACPI_STATUS Status; UINT32 TableIndex; ACPI_FUNCTION_TRACE (TbParseRootTable); /* Map the entire RSDP and extract the address of the RSDT or XSDT */ Rsdp = AcpiOsMapMemory (RsdpAddress, sizeof (ACPI_TABLE_RSDP)); if (!Rsdp) { return_ACPI_STATUS (AE_NO_MEMORY); } AcpiTbPrintTableHeader (RsdpAddress, ACPI_CAST_PTR (ACPI_TABLE_HEADER, Rsdp)); /* Use XSDT if present and not overridden. Otherwise, use RSDT */ if ((Rsdp->Revision > 1) && Rsdp->XsdtPhysicalAddress && !AcpiGbl_DoNotUseXsdt) { /* * RSDP contains an XSDT (64-bit physical addresses). We must use * the XSDT if the revision is > 1 and the XSDT pointer is present, * as per the ACPI specification. */ Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->XsdtPhysicalAddress; TableEntrySize = ACPI_XSDT_ENTRY_SIZE; } else { /* Root table is an RSDT (32-bit physical addresses) */ Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->RsdtPhysicalAddress; TableEntrySize = ACPI_RSDT_ENTRY_SIZE; } /* * It is not possible to map more than one entry in some environments, * so unmap the RSDP here before mapping other tables */ AcpiOsUnmapMemory (Rsdp, sizeof (ACPI_TABLE_RSDP)); /* Map the RSDT/XSDT table header to get the full table length */ Table = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER)); if (!Table) { return_ACPI_STATUS (AE_NO_MEMORY); } AcpiTbPrintTableHeader (Address, Table); /* * Validate length of the table, and map entire table. * Minimum length table must contain at least one entry. */ Length = Table->Length; AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER)); if (Length < (sizeof (ACPI_TABLE_HEADER) + TableEntrySize)) { ACPI_BIOS_ERROR ((AE_INFO, "Invalid table length 0x%X in RSDT/XSDT", Length)); return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); } Table = AcpiOsMapMemory (Address, Length); if (!Table) { return_ACPI_STATUS (AE_NO_MEMORY); } /* Validate the root table checksum */ Status = AcpiTbVerifyChecksum (Table, Length); if (ACPI_FAILURE (Status)) { AcpiOsUnmapMemory (Table, Length); return_ACPI_STATUS (Status); } /* Get the number of entries and pointer to first entry */ TableCount = (UINT32) ((Table->Length - sizeof (ACPI_TABLE_HEADER)) / TableEntrySize); TableEntry = ACPI_ADD_PTR (UINT8, Table, sizeof (ACPI_TABLE_HEADER)); /* Initialize the root table array from the RSDT/XSDT */ for (i = 0; i < TableCount; i++) { /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */ Address = AcpiTbGetRootTableEntry (TableEntry, TableEntrySize); /* Skip NULL entries in RSDT/XSDT */ if (!Address) { goto NextTable; } Status = AcpiTbInstallStandardTable (Address, ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, FALSE, TRUE, &TableIndex); if (ACPI_SUCCESS (Status) && ACPI_COMPARE_NAME ( &AcpiGbl_RootTableList.Tables[TableIndex].Signature, ACPI_SIG_FADT)) { AcpiGbl_FadtIndex = TableIndex; AcpiTbParseFadt (); } NextTable: TableEntry += TableEntrySize; } AcpiOsUnmapMemory (Table, Length); return_ACPI_STATUS (AE_OK); }
static void AcpiTbValidateFadt ( void) { char *Name; ACPI_GENERIC_ADDRESS *Address64; UINT8 Length; UINT32 i; /* * Check for FACS and DSDT address mismatches. An address mismatch between * the 32-bit and 64-bit address fields (FIRMWARE_CTRL/X_FIRMWARE_CTRL and * DSDT/X_DSDT) would indicate the presence of two FACS or two DSDT tables. */ if (AcpiGbl_FADT.Facs && (AcpiGbl_FADT.XFacs != (UINT64) AcpiGbl_FADT.Facs)) { ACPI_BIOS_WARNING ((AE_INFO, "32/64X FACS address mismatch in FADT - " "0x%8.8X/0x%8.8X%8.8X, using 32", AcpiGbl_FADT.Facs, ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XFacs))); AcpiGbl_FADT.XFacs = (UINT64) AcpiGbl_FADT.Facs; } if (AcpiGbl_FADT.Dsdt && (AcpiGbl_FADT.XDsdt != (UINT64) AcpiGbl_FADT.Dsdt)) { ACPI_BIOS_WARNING ((AE_INFO, "32/64X DSDT address mismatch in FADT - " "0x%8.8X/0x%8.8X%8.8X, using 32", AcpiGbl_FADT.Dsdt, ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XDsdt))); AcpiGbl_FADT.XDsdt = (UINT64) AcpiGbl_FADT.Dsdt; } /* If Hardware Reduced flag is set, we are all done */ if (AcpiGbl_ReducedHardware) { return; } /* Examine all of the 64-bit extended address fields (X fields) */ for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { /* * Generate pointer to the 64-bit address, get the register * length (width) and the register name */ Address64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS, &AcpiGbl_FADT, FadtInfoTable[i].Address64); Length = *ACPI_ADD_PTR (UINT8, &AcpiGbl_FADT, FadtInfoTable[i].Length); Name = FadtInfoTable[i].Name; /* * For each extended field, check for length mismatch between the * legacy length field and the corresponding 64-bit X length field. */ if (Address64->Address && (Address64->BitWidth != ACPI_MUL_8 (Length))) { ACPI_BIOS_WARNING ((AE_INFO, "32/64X length mismatch in FADT/%s: %u/%u", Name, ACPI_MUL_8 (Length), Address64->BitWidth)); } if (FadtInfoTable[i].Type & ACPI_FADT_REQUIRED) { /* * Field is required (PM1aEvent, PM1aControl, PmTimer). * Both the address and length must be non-zero. */ if (!Address64->Address || !Length) { ACPI_BIOS_ERROR ((AE_INFO, "Required FADT field %s has zero address and/or length: " "0x%8.8X%8.8X/0x%X", Name, ACPI_FORMAT_UINT64 (Address64->Address), Length)); } } else if (FadtInfoTable[i].Type & ACPI_FADT_SEPARATE_LENGTH) { /* * Field is optional (PM2Control, GPE0, GPE1) AND has its own * length field. If present, both the address and length must * be valid. */ if ((Address64->Address && !Length) || (!Address64->Address && Length)) { ACPI_BIOS_WARNING ((AE_INFO, "Optional FADT field %s has zero address or length: " "0x%8.8X%8.8X/0x%X", Name, ACPI_FORMAT_UINT64 (Address64->Address), Length)); } } } }
ACPI_STATUS AcpiTbAddTable ( ACPI_TABLE_DESC *TableDesc, UINT32 *TableIndex) { UINT32 i; ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_TRACE (TbAddTable); if (!TableDesc->Pointer) { Status = AcpiTbVerifyTable (TableDesc); if (ACPI_FAILURE (Status) || !TableDesc->Pointer) { return_ACPI_STATUS (Status); } } /* * Validate the incoming table signature. * * 1) Originally, we checked the table signature for "SSDT" or "PSDT". * 2) We added support for OEMx tables, signature "OEM". * 3) Valid tables were encountered with a null signature, so we just * gave up on validating the signature, (05/2008). * 4) We encountered non-AML tables such as the MADT, which caused * interpreter errors and kernel faults. So now, we once again allow * only "SSDT", "OEMx", and now, also a null signature. (05/2011). */ if ((TableDesc->Pointer->Signature[0] != 0x00) && (!ACPI_COMPARE_NAME (TableDesc->Pointer->Signature, ACPI_SIG_SSDT)) && (ACPI_STRNCMP (TableDesc->Pointer->Signature, "OEM", 3))) { ACPI_BIOS_ERROR ((AE_INFO, "Table has invalid signature [%4.4s] (0x%8.8X), " "must be SSDT or OEMx", AcpiUtValidAcpiName (TableDesc->Pointer->Signature) ? TableDesc->Pointer->Signature : "????", *(UINT32 *) TableDesc->Pointer->Signature)); return_ACPI_STATUS (AE_BAD_SIGNATURE); } (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); /* Check if table is already registered */ for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) { if (!AcpiGbl_RootTableList.Tables[i].Pointer) { Status = AcpiTbVerifyTable (&AcpiGbl_RootTableList.Tables[i]); if (ACPI_FAILURE (Status) || !AcpiGbl_RootTableList.Tables[i].Pointer) { continue; } } /* * Check for a table match on the entire table length, * not just the header. */ if (TableDesc->Length != AcpiGbl_RootTableList.Tables[i].Length) { continue; } if (ACPI_MEMCMP (TableDesc->Pointer, AcpiGbl_RootTableList.Tables[i].Pointer, AcpiGbl_RootTableList.Tables[i].Length)) { continue; } /* * Note: the current mechanism does not unregister a table if it is * dynamically unloaded. The related namespace entries are deleted, * but the table remains in the root table list. * * The assumption here is that the number of different tables that * will be loaded is actually small, and there is minimal overhead * in just keeping the table in case it is needed again. * * If this assumption changes in the future (perhaps on large * machines with many table load/unload operations), tables will * need to be unregistered when they are unloaded, and slots in the * root table list should be reused when empty. */ /* * Table is already registered. * We can delete the table that was passed as a parameter. */ AcpiTbDeleteTable (TableDesc); *TableIndex = i; if (AcpiGbl_RootTableList.Tables[i].Flags & ACPI_TABLE_IS_LOADED) { /* Table is still loaded, this is an error */ Status = AE_ALREADY_EXISTS; goto Release; } else { /* Table was unloaded, allow it to be reloaded */ TableDesc->Pointer = AcpiGbl_RootTableList.Tables[i].Pointer; TableDesc->Address = AcpiGbl_RootTableList.Tables[i].Address; Status = AE_OK; goto PrintHeader; } } /* * ACPI Table Override: * Allow the host to override dynamically loaded tables. * NOTE: the table is fully mapped at this point, and the mapping will * be deleted by TbTableOverride if the table is actually overridden. */ (void) AcpiTbTableOverride (TableDesc->Pointer, TableDesc); /* Add the table to the global root table list */ Status = AcpiTbStoreTable (TableDesc->Address, TableDesc->Pointer, TableDesc->Length, TableDesc->Flags, TableIndex); if (ACPI_FAILURE (Status)) { goto Release; } PrintHeader: AcpiTbPrintTableHeader (TableDesc->Address, TableDesc->Pointer); Release: (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiTbInstallStandardTable ( ACPI_PHYSICAL_ADDRESS Address, UINT8 Flags, BOOLEAN Reload, BOOLEAN Override, UINT32 *TableIndex) { UINT32 i; ACPI_STATUS Status = AE_OK; ACPI_TABLE_DESC NewTableDesc; ACPI_FUNCTION_TRACE (TbInstallStandardTable); /* Acquire a temporary table descriptor for validation */ Status = AcpiTbAcquireTempTable (&NewTableDesc, Address, Flags); if (ACPI_FAILURE (Status)) { ACPI_ERROR ((AE_INFO, "Could not acquire table length at %8.8X%8.8X", ACPI_FORMAT_UINT64 (Address))); return_ACPI_STATUS (Status); } /* * Optionally do not load any SSDTs from the RSDT/XSDT. This can * be useful for debugging ACPI problems on some machines. */ if (!Reload && AcpiGbl_DisableSsdtTableInstall && ACPI_COMPARE_NAME (&NewTableDesc.Signature, ACPI_SIG_SSDT)) { ACPI_INFO ((AE_INFO, "Ignoring installation of %4.4s at %8.8X%8.8X", NewTableDesc.Signature.Ascii, ACPI_FORMAT_UINT64 (Address))); goto ReleaseAndExit; } /* Validate and verify a table before installation */ Status = AcpiTbVerifyTempTable (&NewTableDesc, NULL); if (ACPI_FAILURE (Status)) { goto ReleaseAndExit; } if (Reload) { /* * Validate the incoming table signature. * * 1) Originally, we checked the table signature for "SSDT" or "PSDT". * 2) We added support for OEMx tables, signature "OEM". * 3) Valid tables were encountered with a null signature, so we just * gave up on validating the signature, (05/2008). * 4) We encountered non-AML tables such as the MADT, which caused * interpreter errors and kernel faults. So now, we once again allow * only "SSDT", "OEMx", and now, also a null signature. (05/2011). */ if ((NewTableDesc.Signature.Ascii[0] != 0x00) && (!ACPI_COMPARE_NAME (&NewTableDesc.Signature, ACPI_SIG_SSDT)) && (strncmp (NewTableDesc.Signature.Ascii, "OEM", 3))) { ACPI_BIOS_ERROR ((AE_INFO, "Table has invalid signature [%4.4s] (0x%8.8X), " "must be SSDT or OEMx", AcpiUtValidAcpiName (NewTableDesc.Signature.Ascii) ? NewTableDesc.Signature.Ascii : "????", NewTableDesc.Signature.Integer)); Status = AE_BAD_SIGNATURE; goto ReleaseAndExit; } /* Check if table is already registered */ for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) { /* * Check for a table match on the entire table length, * not just the header. */ if (!AcpiTbCompareTables (&NewTableDesc, i)) { continue; } /* * Note: the current mechanism does not unregister a table if it is * dynamically unloaded. The related namespace entries are deleted, * but the table remains in the root table list. * * The assumption here is that the number of different tables that * will be loaded is actually small, and there is minimal overhead * in just keeping the table in case it is needed again. * * If this assumption changes in the future (perhaps on large * machines with many table load/unload operations), tables will * need to be unregistered when they are unloaded, and slots in the * root table list should be reused when empty. */ if (AcpiGbl_RootTableList.Tables[i].Flags & ACPI_TABLE_IS_LOADED) { /* Table is still loaded, this is an error */ Status = AE_ALREADY_EXISTS; goto ReleaseAndExit; } else { /* * Table was unloaded, allow it to be reloaded. * As we are going to return AE_OK to the caller, we should * take the responsibility of freeing the input descriptor. * Refill the input descriptor to ensure * AcpiTbInstallTableWithOverride() can be called again to * indicate the re-installation. */ AcpiTbUninstallTable (&NewTableDesc); *TableIndex = i; return_ACPI_STATUS (AE_OK); } } } /* Add the table to the global root table list */ AcpiTbInstallTableWithOverride (&NewTableDesc, Override, TableIndex); ReleaseAndExit: /* Release the temporary table descriptor */ AcpiTbReleaseTempTable (&NewTableDesc); return_ACPI_STATUS (Status); }
acpi_status acpi_find_root_pointer(acpi_size *table_address) { u8 *table_ptr; u8 *mem_rover; u32 physical_address; ACPI_FUNCTION_TRACE(acpi_find_root_pointer); /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */ table_ptr = acpi_os_map_memory((acpi_physical_address) ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH); if (!table_ptr) { ACPI_ERROR((AE_INFO, "Could not map memory at 0x%8.8X for length %u", ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH)); return_ACPI_STATUS(AE_NO_MEMORY); } ACPI_MOVE_16_TO_32(&physical_address, table_ptr); /* Convert segment part to physical address */ physical_address <<= 4; acpi_os_unmap_memory(table_ptr, ACPI_EBDA_PTR_LENGTH); /* EBDA present? */ if (physical_address > 0x400) { /* * 1b) Search EBDA paragraphs (EBDA is required to be a * minimum of 1K length) */ table_ptr = acpi_os_map_memory((acpi_physical_address) physical_address, ACPI_EBDA_WINDOW_SIZE); if (!table_ptr) { ACPI_ERROR((AE_INFO, "Could not map memory at 0x%8.8X for length %u", physical_address, ACPI_EBDA_WINDOW_SIZE)); return_ACPI_STATUS(AE_NO_MEMORY); } mem_rover = acpi_tb_scan_memory_for_rsdp(table_ptr, ACPI_EBDA_WINDOW_SIZE); acpi_os_unmap_memory(table_ptr, ACPI_EBDA_WINDOW_SIZE); if (mem_rover) { /* Return the physical address */ physical_address += (u32) ACPI_PTR_DIFF(mem_rover, table_ptr); *table_address = physical_address; return_ACPI_STATUS(AE_OK); } } /* * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh */ table_ptr = acpi_os_map_memory((acpi_physical_address) ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE); if (!table_ptr) { ACPI_ERROR((AE_INFO, "Could not map memory at 0x%8.8X for length %u", ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE)); return_ACPI_STATUS(AE_NO_MEMORY); } mem_rover = acpi_tb_scan_memory_for_rsdp(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE); acpi_os_unmap_memory(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE); if (mem_rover) { /* Return the physical address */ physical_address = (u32) (ACPI_HI_RSDP_WINDOW_BASE + ACPI_PTR_DIFF(mem_rover, table_ptr)); *table_address = physical_address; return_ACPI_STATUS(AE_OK); } /* A valid RSDP was not found */ ACPI_BIOS_ERROR((AE_INFO, "A valid RSDP was not found")); return_ACPI_STATUS(AE_NOT_FOUND); }
static void acpi_tb_convert_fadt(void) { char *name; struct acpi_generic_address *address64; u32 address32; u8 length; u32 i; /* * For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which * should be zero are indeed zero. This will workaround BIOSs that * inadvertently place values in these fields. * * The ACPI 1.0 reserved fields that will be zeroed are the bytes located * at offset 45, 55, 95, and the word located at offset 109, 110. * * Note: The FADT revision value is unreliable. Only the length can be * trusted. */ if (acpi_gbl_FADT.header.length <= ACPI_FADT_V2_SIZE) { acpi_gbl_FADT.preferred_profile = 0; acpi_gbl_FADT.pstate_control = 0; acpi_gbl_FADT.cst_control = 0; acpi_gbl_FADT.boot_flags = 0; } /* * Now we can update the local FADT length to the length of the * current FADT version as defined by the ACPI specification. * Thus, we will have a common FADT internally. */ acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt); /* * Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary. * Later ACPICA code will always use the X 64-bit field. */ acpi_gbl_FADT.Xfacs = acpi_tb_select_address("FACS", acpi_gbl_FADT.facs, acpi_gbl_FADT.Xfacs); acpi_gbl_FADT.Xdsdt = acpi_tb_select_address("DSDT", acpi_gbl_FADT.dsdt, acpi_gbl_FADT.Xdsdt); /* If Hardware Reduced flag is set, we are all done */ if (acpi_gbl_reduced_hardware) { return; } /* Examine all of the 64-bit extended address fields (X fields) */ for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { /* * Get the 32-bit and 64-bit addresses, as well as the register * length and register name. */ address32 = *ACPI_ADD_PTR(u32, &acpi_gbl_FADT, fadt_info_table[i].address32); address64 = ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT, fadt_info_table[i].address64); length = *ACPI_ADD_PTR(u8, &acpi_gbl_FADT, fadt_info_table[i].length); name = fadt_info_table[i].name; /* * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X" * generic address structures as necessary. Later code will always use * the 64-bit address structures. * * November 2013: * Now always use the 64-bit address if it is valid (non-zero), in * accordance with the ACPI specification which states that a 64-bit * address supersedes the 32-bit version. This behavior can be * overridden by the acpi_gbl_use32_bit_fadt_addresses flag. * * During 64-bit address construction and verification, * these cases are handled: * * Address32 zero, Address64 [don't care] - Use Address64 * * Address32 non-zero, Address64 zero - Copy/use Address32 * Address32 non-zero == Address64 non-zero - Use Address64 * Address32 non-zero != Address64 non-zero - Warning, use Address64 * * Override: if acpi_gbl_use32_bit_fadt_addresses is TRUE, and: * Address32 non-zero != Address64 non-zero - Warning, copy/use Address32 * * Note: space_id is always I/O for 32-bit legacy address fields */ if (address32) { if (!address64->address) { /* 64-bit address is zero, use 32-bit address */ acpi_tb_init_generic_address(address64, ACPI_ADR_SPACE_SYSTEM_IO, *ACPI_ADD_PTR(u8, &acpi_gbl_FADT, fadt_info_table [i]. length), (u64)address32, name); } else if (address64->address != (u64)address32) { /* Address mismatch */ ACPI_BIOS_WARNING((AE_INFO, "32/64X address mismatch in FADT/%s: " "0x%8.8X/0x%8.8X%8.8X, using %u-bit address", name, address32, ACPI_FORMAT_UINT64 (address64->address), acpi_gbl_use32_bit_fadt_addresses ? 32 : 64)); if (acpi_gbl_use32_bit_fadt_addresses) { /* 32-bit address override */ acpi_tb_init_generic_address(address64, ACPI_ADR_SPACE_SYSTEM_IO, *ACPI_ADD_PTR (u8, &acpi_gbl_FADT, fadt_info_table [i]. length), (u64) address32, name); } } } /* * For each extended field, check for length mismatch between the * legacy length field and the corresponding 64-bit X length field. * Note: If the legacy length field is > 0xFF bits, ignore this * check. (GPE registers can be larger than the 64-bit GAS structure * can accomodate, 0xFF bits). */ if (address64->address && (ACPI_MUL_8(length) <= ACPI_UINT8_MAX) && (address64->bit_width != ACPI_MUL_8(length))) { ACPI_BIOS_WARNING((AE_INFO, "32/64X length mismatch in FADT/%s: %u/%u", name, ACPI_MUL_8(length), address64->bit_width)); } if (fadt_info_table[i].type & ACPI_FADT_REQUIRED) { /* * Field is required (Pm1a_event, Pm1a_control). * Both the address and length must be non-zero. */ if (!address64->address || !length) { ACPI_BIOS_ERROR((AE_INFO, "Required FADT field %s has zero address and/or length: " "0x%8.8X%8.8X/0x%X", name, ACPI_FORMAT_UINT64(address64-> address), length)); } } else if (fadt_info_table[i].type & ACPI_FADT_SEPARATE_LENGTH) { /* * Field is optional (Pm2_control, GPE0, GPE1) AND has its own * length field. If present, both the address and length must * be valid. */ if ((address64->address && !length) || (!address64->address && length)) { ACPI_BIOS_WARNING((AE_INFO, "Optional FADT field %s has zero address or length: " "0x%8.8X%8.8X/0x%X", name, ACPI_FORMAT_UINT64 (address64->address), length)); } } } }
ACPI_STATUS AcpiTbVerifyTempTable ( ACPI_TABLE_DESC *TableDesc, char *Signature, UINT32 *TableIndex) { ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_TRACE (TbVerifyTempTable); /* Validate the table */ Status = AcpiTbValidateTempTable (TableDesc); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (AE_NO_MEMORY); } /* If a particular signature is expected (DSDT/FACS), it must match */ if (Signature && !ACPI_COMPARE_NAME (&TableDesc->Signature, Signature)) { ACPI_BIOS_ERROR ((AE_INFO, "Invalid signature 0x%X for ACPI table, expected [%s]", TableDesc->Signature.Integer, Signature)); Status = AE_BAD_SIGNATURE; goto InvalidateAndExit; } if (AcpiGbl_EnableTableValidation) { /* Verify the checksum */ Status = AcpiTbVerifyChecksum (TableDesc->Pointer, TableDesc->Length); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY, "%4.4s 0x%8.8X%8.8X" " Attempted table install failed", AcpiUtValidNameseg (TableDesc->Signature.Ascii) ? TableDesc->Signature.Ascii : "????", ACPI_FORMAT_UINT64 (TableDesc->Address))); goto InvalidateAndExit; } /* Avoid duplications */ if (TableIndex) { Status = AcpiTbCheckDuplication (TableDesc, TableIndex); if (ACPI_FAILURE (Status)) { if (Status != AE_CTRL_TERMINATE) { ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY, "%4.4s 0x%8.8X%8.8X" " Table is duplicated", AcpiUtValidNameseg (TableDesc->Signature.Ascii) ? TableDesc->Signature.Ascii : "????", ACPI_FORMAT_UINT64 (TableDesc->Address))); } goto InvalidateAndExit; } } TableDesc->Flags |= ACPI_TABLE_IS_VERIFIED; } return_ACPI_STATUS (Status); InvalidateAndExit: AcpiTbInvalidateTable (TableDesc); return_ACPI_STATUS (Status); }
static void AcpiTbConvertFadt ( void) { ACPI_GENERIC_ADDRESS *Address64; UINT32 Address32; UINT32 i; /* * Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary. * Later code will always use the X 64-bit field. */ if (!AcpiGbl_FADT.XFacs) { AcpiGbl_FADT.XFacs = (UINT64) AcpiGbl_FADT.Facs; } if (!AcpiGbl_FADT.XDsdt) { AcpiGbl_FADT.XDsdt = (UINT64) AcpiGbl_FADT.Dsdt; } /* * For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which * should be zero are indeed zero. This will workaround BIOSs that * inadvertently place values in these fields. * * The ACPI 1.0 reserved fields that will be zeroed are the bytes located * at offset 45, 55, 95, and the word located at offset 109, 110. * * Note: The FADT revision value is unreliable. Only the length can be * trusted. */ if (AcpiGbl_FADT.Header.Length <= ACPI_FADT_V2_SIZE) { AcpiGbl_FADT.PreferredProfile = 0; AcpiGbl_FADT.PstateControl = 0; AcpiGbl_FADT.CstControl = 0; AcpiGbl_FADT.BootFlags = 0; } /* * Now we can update the local FADT length to the length of the * current FADT version as defined by the ACPI specification. * Thus, we will have a common FADT internally. */ AcpiGbl_FADT.Header.Length = sizeof (ACPI_TABLE_FADT); /* * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X" * generic address structures as necessary. Later code will always use * the 64-bit address structures. * * March 2009: * We now always use the 32-bit address if it is valid (non-null). This * is not in accordance with the ACPI specification which states that * the 64-bit address supersedes the 32-bit version, but we do this for * compatibility with other ACPI implementations. Most notably, in the * case where both the 32 and 64 versions are non-null, we use the 32-bit * version. This is the only address that is guaranteed to have been * tested by the BIOS manufacturer. */ for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { Address32 = *ACPI_ADD_PTR (UINT32, &AcpiGbl_FADT, FadtInfoTable[i].Address32); Address64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS, &AcpiGbl_FADT, FadtInfoTable[i].Address64); /* * If both 32- and 64-bit addresses are valid (non-zero), * they must match. */ if (Address64->Address && Address32 && (Address64->Address != (UINT64) Address32)) { ACPI_BIOS_ERROR ((AE_INFO, "32/64X address mismatch in FADT/%s: " "0x%8.8X/0x%8.8X%8.8X, using 32", FadtInfoTable[i].Name, Address32, ACPI_FORMAT_UINT64 (Address64->Address))); } /* Always use 32-bit address if it is valid (non-null) */ if (Address32) { /* * Copy the 32-bit address to the 64-bit GAS structure. The * Space ID is always I/O for 32-bit legacy address fields */ AcpiTbInitGenericAddress (Address64, ACPI_ADR_SPACE_SYSTEM_IO, *ACPI_ADD_PTR (UINT8, &AcpiGbl_FADT, FadtInfoTable[i].Length), (UINT64) Address32, FadtInfoTable[i].Name); } } }
ACPI_STATUS AcpiFindRootPointer ( ACPI_SIZE *TableAddress) { UINT8 *TablePtr; UINT8 *MemRover; UINT32 PhysicalAddress; ACPI_FUNCTION_TRACE (AcpiFindRootPointer); /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */ TablePtr = AcpiOsMapMemory ( (ACPI_PHYSICAL_ADDRESS) ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH); if (!TablePtr) { ACPI_ERROR ((AE_INFO, "Could not map memory at 0x%8.8X for length %u", ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH)); return_ACPI_STATUS (AE_NO_MEMORY); } ACPI_MOVE_16_TO_32 (&PhysicalAddress, TablePtr); /* Convert segment part to physical address */ PhysicalAddress <<= 4; AcpiOsUnmapMemory (TablePtr, ACPI_EBDA_PTR_LENGTH); /* EBDA present? */ if (PhysicalAddress > 0x400) { /* * 1b) Search EBDA paragraphs (EBDA is required to be a * minimum of 1K length) */ TablePtr = AcpiOsMapMemory ( (ACPI_PHYSICAL_ADDRESS) PhysicalAddress, ACPI_EBDA_WINDOW_SIZE); if (!TablePtr) { ACPI_ERROR ((AE_INFO, "Could not map memory at 0x%8.8X for length %u", PhysicalAddress, ACPI_EBDA_WINDOW_SIZE)); return_ACPI_STATUS (AE_NO_MEMORY); } MemRover = AcpiTbScanMemoryForRsdp (TablePtr, ACPI_EBDA_WINDOW_SIZE); AcpiOsUnmapMemory (TablePtr, ACPI_EBDA_WINDOW_SIZE); if (MemRover) { /* Return the physical address */ PhysicalAddress += (UINT32) ACPI_PTR_DIFF (MemRover, TablePtr); *TableAddress = PhysicalAddress; return_ACPI_STATUS (AE_OK); } } /* * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh */ TablePtr = AcpiOsMapMemory ( (ACPI_PHYSICAL_ADDRESS) ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE); if (!TablePtr) { ACPI_ERROR ((AE_INFO, "Could not map memory at 0x%8.8X for length %u", ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE)); return_ACPI_STATUS (AE_NO_MEMORY); } MemRover = AcpiTbScanMemoryForRsdp (TablePtr, ACPI_HI_RSDP_WINDOW_SIZE); AcpiOsUnmapMemory (TablePtr, ACPI_HI_RSDP_WINDOW_SIZE); if (MemRover) { /* Return the physical address */ PhysicalAddress = (UINT32) (ACPI_HI_RSDP_WINDOW_BASE + ACPI_PTR_DIFF (MemRover, TablePtr)); *TableAddress = PhysicalAddress; return_ACPI_STATUS (AE_OK); } /* A valid RSDP was not found */ ACPI_BIOS_ERROR ((AE_INFO, "A valid RSDP was not found")); return_ACPI_STATUS (AE_NOT_FOUND); }
static void acpi_tb_validate_fadt(void) { char *name; struct acpi_generic_address *address64; u8 length; u32 i; /* * Check for FACS and DSDT address mismatches. An address mismatch between * the 32-bit and 64-bit address fields (FIRMWARE_CTRL/X_FIRMWARE_CTRL and * DSDT/X_DSDT) would indicate the presence of two FACS or two DSDT tables. */ if (acpi_gbl_FADT.facs && (acpi_gbl_FADT.Xfacs != (u64)acpi_gbl_FADT.facs)) { ACPI_BIOS_WARNING((AE_INFO, "32/64X FACS address mismatch in FADT - " "0x%8.8X/0x%8.8X%8.8X, using 32", acpi_gbl_FADT.facs, ACPI_FORMAT_UINT64(acpi_gbl_FADT.Xfacs))); acpi_gbl_FADT.Xfacs = (u64)acpi_gbl_FADT.facs; } if (acpi_gbl_FADT.dsdt && (acpi_gbl_FADT.Xdsdt != (u64)acpi_gbl_FADT.dsdt)) { ACPI_BIOS_WARNING((AE_INFO, "32/64X DSDT address mismatch in FADT - " "0x%8.8X/0x%8.8X%8.8X, using 32", acpi_gbl_FADT.dsdt, ACPI_FORMAT_UINT64(acpi_gbl_FADT.Xdsdt))); acpi_gbl_FADT.Xdsdt = (u64)acpi_gbl_FADT.dsdt; } /* If Hardware Reduced flag is set, we are all done */ if (acpi_gbl_reduced_hardware) { return; } /* Examine all of the 64-bit extended address fields (X fields) */ for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { /* * Generate pointer to the 64-bit address, get the register * length (width) and the register name */ address64 = ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT, fadt_info_table[i].address64); length = *ACPI_ADD_PTR(u8, &acpi_gbl_FADT, fadt_info_table[i].length); name = fadt_info_table[i].name; /* * For each extended field, check for length mismatch between the * legacy length field and the corresponding 64-bit X length field. */ if (address64->address && (address64->bit_width != ACPI_MUL_8(length))) { ACPI_BIOS_WARNING((AE_INFO, "32/64X length mismatch in FADT/%s: %u/%u", name, ACPI_MUL_8(length), address64->bit_width)); } if (fadt_info_table[i].type & ACPI_FADT_REQUIRED) { /* * Field is required (Pm1a_event, Pm1a_control, pm_timer). * Both the address and length must be non-zero. */ if (!address64->address || !length) { ACPI_BIOS_ERROR((AE_INFO, "Required FADT field %s has zero address and/or length: " "0x%8.8X%8.8X/0x%X", name, ACPI_FORMAT_UINT64(address64-> address), length)); } } else if (fadt_info_table[i].type & ACPI_FADT_SEPARATE_LENGTH) { /* * Field is optional (Pm2_control, GPE0, GPE1) AND has its own * length field. If present, both the address and length must * be valid. */ if ((address64->address && !length) || (!address64->address && length)) { ACPI_BIOS_WARNING((AE_INFO, "Optional FADT field %s has zero address or length: " "0x%8.8X%8.8X/0x%X", name, ACPI_FORMAT_UINT64 (address64->address), length)); } } } }
static void acpi_tb_convert_fadt(void) { struct acpi_generic_address *address64; u32 address32; u32 i; /* * Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary. * Later code will always use the X 64-bit field. Also, check for an * address mismatch between the 32-bit and 64-bit address fields * (FIRMWARE_CTRL/X_FIRMWARE_CTRL, DSDT/X_DSDT) which would indicate * the presence of two FACS or two DSDT tables. */ if (!acpi_gbl_FADT.Xfacs) { acpi_gbl_FADT.Xfacs = (u64) acpi_gbl_FADT.facs; } else if (acpi_gbl_FADT.facs && (acpi_gbl_FADT.Xfacs != (u64) acpi_gbl_FADT.facs)) { ACPI_WARNING((AE_INFO, "32/64 FACS address mismatch in FADT - two FACS tables!")); } if (!acpi_gbl_FADT.Xdsdt) { acpi_gbl_FADT.Xdsdt = (u64) acpi_gbl_FADT.dsdt; } else if (acpi_gbl_FADT.dsdt && (acpi_gbl_FADT.Xdsdt != (u64) acpi_gbl_FADT.dsdt)) { ACPI_WARNING((AE_INFO, "32/64 DSDT address mismatch in FADT - two DSDT tables!")); } /* * For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which * should be zero are indeed zero. This will workaround BIOSs that * inadvertently place values in these fields. * * The ACPI 1.0 reserved fields that will be zeroed are the bytes located * at offset 45, 55, 95, and the word located at offset 109, 110. * * Note: The FADT revision value is unreliable. Only the length can be * trusted. */ if (acpi_gbl_FADT.header.length <= ACPI_FADT_V2_SIZE) { acpi_gbl_FADT.preferred_profile = 0; acpi_gbl_FADT.pstate_control = 0; acpi_gbl_FADT.cst_control = 0; acpi_gbl_FADT.boot_flags = 0; } /* Update the local FADT table header length */ acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt); /* * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X" * generic address structures as necessary. Later code will always use * the 64-bit address structures. * * March 2009: * We now always use the 32-bit address if it is valid (non-null). This * is not in accordance with the ACPI specification which states that * the 64-bit address supersedes the 32-bit version, but we do this for * compatibility with other ACPI implementations. Most notably, in the * case where both the 32 and 64 versions are non-null, we use the 32-bit * version. This is the only address that is guaranteed to have been * tested by the BIOS manufacturer. */ for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { address32 = *ACPI_ADD_PTR(u32, &acpi_gbl_FADT, fadt_info_table[i].address32); address64 = ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT, fadt_info_table[i].address64); /* * If both 32- and 64-bit addresses are valid (non-zero), * they must match. */ if (address64->address && address32 && (address64->address != (u64)address32)) { ACPI_BIOS_ERROR((AE_INFO, "32/64X address mismatch in FADT/%s: " "0x%8.8X/0x%8.8X%8.8X, using 32", fadt_info_table[i].name, address32, ACPI_FORMAT_UINT64(address64-> address))); } /* Always use 32-bit address if it is valid (non-null) */ if (address32) { /* * Copy the 32-bit address to the 64-bit GAS structure. The * Space ID is always I/O for 32-bit legacy address fields */ acpi_tb_init_generic_address(address64, ACPI_ADR_SPACE_SYSTEM_IO, *ACPI_ADD_PTR(u8, &acpi_gbl_FADT, fadt_info_table [i].length), (u64) address32, fadt_info_table[i].name); } } }
acpi_status acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) { u32 i; acpi_status status = AE_OK; ACPI_FUNCTION_TRACE(tb_add_table); if (!table_desc->pointer) { status = acpi_tb_verify_table(table_desc); if (ACPI_FAILURE(status) || !table_desc->pointer) { return_ACPI_STATUS(status); } } /* * Validate the incoming table signature. * * 1) Originally, we checked the table signature for "SSDT" or "PSDT". * 2) We added support for OEMx tables, signature "OEM". * 3) Valid tables were encountered with a null signature, so we just * gave up on validating the signature, (05/2008). * 4) We encountered non-AML tables such as the MADT, which caused * interpreter errors and kernel faults. So now, we once again allow * only "SSDT", "OEMx", and now, also a null signature. (05/2011). */ if ((table_desc->pointer->signature[0] != 0x00) && (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT)) && (ACPI_STRNCMP(table_desc->pointer->signature, "OEM", 3))) { ACPI_BIOS_ERROR((AE_INFO, "Table has invalid signature [%4.4s] (0x%8.8X), " "must be SSDT or OEMx", acpi_ut_valid_acpi_name(*(u32 *)table_desc-> pointer-> signature) ? table_desc->pointer->signature : "????", *(u32 *)table_desc->pointer->signature)); return_ACPI_STATUS(AE_BAD_SIGNATURE); } (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); /* Check if table is already registered */ for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) { if (!acpi_gbl_root_table_list.tables[i].pointer) { status = acpi_tb_verify_table(&acpi_gbl_root_table_list. tables[i]); if (ACPI_FAILURE(status) || !acpi_gbl_root_table_list.tables[i].pointer) { continue; } } /* * Check for a table match on the entire table length, * not just the header. */ if (table_desc->length != acpi_gbl_root_table_list.tables[i].length) { continue; } if (ACPI_MEMCMP(table_desc->pointer, acpi_gbl_root_table_list.tables[i].pointer, acpi_gbl_root_table_list.tables[i].length)) { continue; } /* * Note: the current mechanism does not unregister a table if it is * dynamically unloaded. The related namespace entries are deleted, * but the table remains in the root table list. * * The assumption here is that the number of different tables that * will be loaded is actually small, and there is minimal overhead * in just keeping the table in case it is needed again. * * If this assumption changes in the future (perhaps on large * machines with many table load/unload operations), tables will * need to be unregistered when they are unloaded, and slots in the * root table list should be reused when empty. */ /* * Table is already registered. * We can delete the table that was passed as a parameter. */ acpi_tb_delete_table(table_desc); *table_index = i; if (acpi_gbl_root_table_list.tables[i]. flags & ACPI_TABLE_IS_LOADED) { /* Table is still loaded, this is an error */ status = AE_ALREADY_EXISTS; goto release; } else { /* Table was unloaded, allow it to be reloaded */ table_desc->pointer = acpi_gbl_root_table_list.tables[i].pointer; table_desc->address = acpi_gbl_root_table_list.tables[i].address; status = AE_OK; goto print_header; } } /* * ACPI Table Override: * Allow the host to override dynamically loaded tables. * NOTE: the table is fully mapped at this point, and the mapping will * be deleted by tb_table_override if the table is actually overridden. */ (void)acpi_tb_table_override(table_desc->pointer, table_desc); /* Add the table to the global root table list */ status = acpi_tb_store_table(table_desc->address, table_desc->pointer, table_desc->length, table_desc->flags, table_index); if (ACPI_FAILURE(status)) { goto release; } print_header: acpi_tb_print_table_header(table_desc->address, table_desc->pointer); release: (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); return_ACPI_STATUS(status); }
static void AcpiTbConvertFadt ( void) { char *Name; ACPI_GENERIC_ADDRESS *Address64; UINT32 Address32; UINT8 Length; UINT8 Flags; UINT32 i; /* * For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which * should be zero are indeed zero. This will workaround BIOSs that * inadvertently place values in these fields. * * The ACPI 1.0 reserved fields that will be zeroed are the bytes located * at offset 45, 55, 95, and the word located at offset 109, 110. * * Note: The FADT revision value is unreliable. Only the length can be * trusted. */ if (AcpiGbl_FADT.Header.Length <= ACPI_FADT_V2_SIZE) { AcpiGbl_FADT.PreferredProfile = 0; AcpiGbl_FADT.PstateControl = 0; AcpiGbl_FADT.CstControl = 0; AcpiGbl_FADT.BootFlags = 0; } /* * Now we can update the local FADT length to the length of the * current FADT version as defined by the ACPI specification. * Thus, we will have a common FADT internally. */ AcpiGbl_FADT.Header.Length = sizeof (ACPI_TABLE_FADT); /* * Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary. * Later ACPICA code will always use the X 64-bit field. */ AcpiGbl_FADT.XFacs = AcpiTbSelectAddress ("FACS", AcpiGbl_FADT.Facs, AcpiGbl_FADT.XFacs); AcpiGbl_FADT.XDsdt = AcpiTbSelectAddress ("DSDT", AcpiGbl_FADT.Dsdt, AcpiGbl_FADT.XDsdt); /* If Hardware Reduced flag is set, we are all done */ if (AcpiGbl_ReducedHardware) { return; } /* Examine all of the 64-bit extended address fields (X fields) */ for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { /* * Get the 32-bit and 64-bit addresses, as well as the register * length and register name. */ Address32 = *ACPI_ADD_PTR (UINT32, &AcpiGbl_FADT, FadtInfoTable[i].Address32); Address64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS, &AcpiGbl_FADT, FadtInfoTable[i].Address64); Length = *ACPI_ADD_PTR (UINT8, &AcpiGbl_FADT, FadtInfoTable[i].Length); Name = FadtInfoTable[i].Name; Flags = FadtInfoTable[i].Flags; /* * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X" * generic address structures as necessary. Later code will always use * the 64-bit address structures. * * November 2013: * Now always use the 64-bit address if it is valid (non-zero), in * accordance with the ACPI specification which states that a 64-bit * address supersedes the 32-bit version. This behavior can be * overridden by the AcpiGbl_Use32BitFadtAddresses flag. * * During 64-bit address construction and verification, * these cases are handled: * * Address32 zero, Address64 [don't care] - Use Address64 * * Address32 non-zero, Address64 zero - Copy/use Address32 * Address32 non-zero == Address64 non-zero - Use Address64 * Address32 non-zero != Address64 non-zero - Warning, use Address64 * * Override: if AcpiGbl_Use32BitFadtAddresses is TRUE, and: * Address32 non-zero != Address64 non-zero - Warning, copy/use Address32 * * Note: SpaceId is always I/O for 32-bit legacy address fields */ if (Address32) { if (!Address64->Address) { /* 64-bit address is zero, use 32-bit address */ AcpiTbInitGenericAddress (Address64, ACPI_ADR_SPACE_SYSTEM_IO, *ACPI_ADD_PTR (UINT8, &AcpiGbl_FADT, FadtInfoTable[i].Length), (UINT64) Address32, Name, Flags); } else if (Address64->Address != (UINT64) Address32) { /* Address mismatch */ ACPI_BIOS_WARNING ((AE_INFO, "32/64X address mismatch in FADT/%s: " "0x%8.8X/0x%8.8X%8.8X, using %u-bit address", Name, Address32, ACPI_FORMAT_UINT64 (Address64->Address), AcpiGbl_Use32BitFadtAddresses ? 32 : 64)); if (AcpiGbl_Use32BitFadtAddresses) { /* 32-bit address override */ AcpiTbInitGenericAddress (Address64, ACPI_ADR_SPACE_SYSTEM_IO, *ACPI_ADD_PTR (UINT8, &AcpiGbl_FADT, FadtInfoTable[i].Length), (UINT64) Address32, Name, Flags); } } } /* * For each extended field, check for length mismatch between the * legacy length field and the corresponding 64-bit X length field. * Note: If the legacy length field is > 0xFF bits, ignore this * check. (GPE registers can be larger than the 64-bit GAS structure * can accomodate, 0xFF bits). */ if (Address64->Address && (ACPI_MUL_8 (Length) <= ACPI_UINT8_MAX) && (Address64->BitWidth != ACPI_MUL_8 (Length))) { ACPI_BIOS_WARNING ((AE_INFO, "32/64X length mismatch in FADT/%s: %u/%u", Name, ACPI_MUL_8 (Length), Address64->BitWidth)); } if (FadtInfoTable[i].Flags & ACPI_FADT_REQUIRED) { /* * Field is required (PM1aEvent, PM1aControl). * Both the address and length must be non-zero. */ if (!Address64->Address || !Length) { ACPI_BIOS_ERROR ((AE_INFO, "Required FADT field %s has zero address and/or length: " "0x%8.8X%8.8X/0x%X", Name, ACPI_FORMAT_UINT64 (Address64->Address), Length)); } } else if (FadtInfoTable[i].Flags & ACPI_FADT_SEPARATE_LENGTH) { /* * Field is optional (PM2Control, GPE0, GPE1) AND has its own * length field. If present, both the address and length must * be valid. */ if ((Address64->Address && !Length) || (!Address64->Address && Length)) { ACPI_BIOS_WARNING ((AE_INFO, "Optional FADT field %s has zero address or length: " "0x%8.8X%8.8X/0x%X", Name, ACPI_FORMAT_UINT64 (Address64->Address), Length)); } } } }
static ACPI_STATUS AcpiDsInitBufferField ( UINT16 AmlOpcode, ACPI_OPERAND_OBJECT *ObjDesc, ACPI_OPERAND_OBJECT *BufferDesc, ACPI_OPERAND_OBJECT *OffsetDesc, ACPI_OPERAND_OBJECT *LengthDesc, ACPI_OPERAND_OBJECT *ResultDesc) { UINT32 Offset; UINT32 BitOffset; UINT32 BitCount; UINT8 FieldFlags; ACPI_STATUS Status; ACPI_FUNCTION_TRACE_PTR (DsInitBufferField, ObjDesc); /* Host object must be a Buffer */ if (BufferDesc->Common.Type != ACPI_TYPE_BUFFER) { ACPI_ERROR ((AE_INFO, "Target of Create Field is not a Buffer object - %s", AcpiUtGetObjectTypeName (BufferDesc))); Status = AE_AML_OPERAND_TYPE; goto Cleanup; } /* * The last parameter to all of these opcodes (ResultDesc) started * out as a NameString, and should therefore now be a NS node * after resolution in AcpiExResolveOperands(). */ if (ACPI_GET_DESCRIPTOR_TYPE (ResultDesc) != ACPI_DESC_TYPE_NAMED) { ACPI_ERROR ((AE_INFO, "(%s) destination not a NS Node [%s]", AcpiPsGetOpcodeName (AmlOpcode), AcpiUtGetDescriptorName (ResultDesc))); Status = AE_AML_OPERAND_TYPE; goto Cleanup; } Offset = (UINT32) OffsetDesc->Integer.Value; /* * Setup the Bit offsets and counts, according to the opcode */ switch (AmlOpcode) { case AML_CREATE_FIELD_OP: /* Offset is in bits, count is in bits */ FieldFlags = AML_FIELD_ACCESS_BYTE; BitOffset = Offset; BitCount = (UINT32) LengthDesc->Integer.Value; /* Must have a valid (>0) bit count */ if (BitCount == 0) { ACPI_BIOS_ERROR ((AE_INFO, "Attempt to CreateField of length zero")); Status = AE_AML_OPERAND_VALUE; goto Cleanup; } break; case AML_CREATE_BIT_FIELD_OP: /* Offset is in bits, Field is one bit */ BitOffset = Offset; BitCount = 1; FieldFlags = AML_FIELD_ACCESS_BYTE; break; case AML_CREATE_BYTE_FIELD_OP: /* Offset is in bytes, field is one byte */ BitOffset = 8 * Offset; BitCount = 8; FieldFlags = AML_FIELD_ACCESS_BYTE; break; case AML_CREATE_WORD_FIELD_OP: /* Offset is in bytes, field is one word */ BitOffset = 8 * Offset; BitCount = 16; FieldFlags = AML_FIELD_ACCESS_WORD; break; case AML_CREATE_DWORD_FIELD_OP: /* Offset is in bytes, field is one dword */ BitOffset = 8 * Offset; BitCount = 32; FieldFlags = AML_FIELD_ACCESS_DWORD; break; case AML_CREATE_QWORD_FIELD_OP: /* Offset is in bytes, field is one qword */ BitOffset = 8 * Offset; BitCount = 64; FieldFlags = AML_FIELD_ACCESS_QWORD; break; default: ACPI_ERROR ((AE_INFO, "Unknown field creation opcode 0x%02X", AmlOpcode)); Status = AE_AML_BAD_OPCODE; goto Cleanup; } /* Entire field must fit within the current length of the buffer */ if ((BitOffset + BitCount) > (8 * (UINT32) BufferDesc->Buffer.Length)) { Status = AE_AML_BUFFER_LIMIT; ACPI_BIOS_EXCEPTION ((AE_INFO, Status, "Field [%4.4s] at bit offset/length %u/%u " "exceeds size of target Buffer (%u bits)", AcpiUtGetNodeName (ResultDesc), BitOffset, BitCount, 8 * (UINT32) BufferDesc->Buffer.Length)); goto Cleanup; } /* * Initialize areas of the field object that are common to all fields * For FieldFlags, use LOCK_RULE = 0 (NO_LOCK), * UPDATE_RULE = 0 (UPDATE_PRESERVE) */ Status = AcpiExPrepCommonFieldObject ( ObjDesc, FieldFlags, 0, BitOffset, BitCount); if (ACPI_FAILURE (Status)) { goto Cleanup; } ObjDesc->BufferField.BufferObj = BufferDesc; /* Reference count for BufferDesc inherits ObjDesc count */ BufferDesc->Common.ReferenceCount = (UINT16) (BufferDesc->Common.ReferenceCount + ObjDesc->Common.ReferenceCount); Cleanup: /* Always delete the operands */ AcpiUtRemoveReference (OffsetDesc); AcpiUtRemoveReference (BufferDesc); if (AmlOpcode == AML_CREATE_FIELD_OP) { AcpiUtRemoveReference (LengthDesc); } /* On failure, delete the result descriptor */ if (ACPI_FAILURE (Status)) { AcpiUtRemoveReference (ResultDesc); /* Result descriptor */ } else { /* Now the address and length are valid for this BufferField */ ObjDesc->BufferField.Flags |= AOPOBJ_DATA_VALID; } return_ACPI_STATUS (Status); }