ACPI_TABLE_HEADER * AcpiTbCopyDsdt ( UINT32 TableIndex) { ACPI_TABLE_HEADER *NewTable; ACPI_TABLE_DESC *TableDesc; TableDesc = &AcpiGbl_RootTableList.Tables[TableIndex]; NewTable = ACPI_ALLOCATE (TableDesc->Length); if (!NewTable) { ACPI_ERROR ((AE_INFO, "Could not copy DSDT of length 0x%X", TableDesc->Length)); return (NULL); } memcpy (NewTable, TableDesc->Pointer, TableDesc->Length); AcpiTbUninstallTable (TableDesc); AcpiTbInitTableDescriptor ( &AcpiGbl_RootTableList.Tables[AcpiGbl_DsdtIndex], ACPI_PTR_TO_PHYSADDR (NewTable), ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL, NewTable); ACPI_INFO (( "Forced DSDT copy: length 0x%05X copied locally, original unmapped", NewTable->Length)); return (NewTable); }
/******************************************************************************* * * FUNCTION: AeLocalLoadTable * * PARAMETERS: TablePtr - pointer to a buffer containing the entire * table to be loaded * * RETURN: Status * * DESCRIPTION: This function is called to load a table from the caller's * buffer. The buffer must contain an entire ACPI Table including * a valid header. The header fields will be verified, and if it * is determined that the table is invalid, the call will fail. * * If the call fails an appropriate status will be returned. * ******************************************************************************/ #if 0 /* XXX unused -- [email protected] */ ACPI_STATUS AeLocalLoadTable ( ACPI_TABLE_HEADER *TablePtr) { ACPI_STATUS Status; ACPI_TABLE_DESC TableInfo; FUNCTION_TRACE ("AeLocalLoadTable"); if (!TablePtr) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Install the new table into the local data structures */ TableInfo.Pointer = TablePtr; Status = AcpiTbInstallTable (NULL, &TableInfo); if (ACPI_FAILURE (Status)) { /* Free table allocated by AcpiTbGetTable */ AcpiTbDeleteSingleTable (&TableInfo); return_ACPI_STATUS (Status); } #ifndef PARSER_ONLY Status = AcpiNsLoadTable (TableInfo.InstalledDesc, AcpiGbl_RootNode); if (ACPI_FAILURE (Status)) { /* Uninstall table and free the buffer */ AcpiTbUninstallTable (TableInfo.InstalledDesc); return_ACPI_STATUS (Status); } #endif return_ACPI_STATUS (Status); }
void AcpiTbTerminate ( void) { UINT32 i; ACPI_FUNCTION_TRACE (TbTerminate); (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); /* Delete the individual tables */ for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) { AcpiTbUninstallTable (&AcpiGbl_RootTableList.Tables[i]); } /* * Delete the root table array if allocated locally. Array cannot be * mapped, so we don't need to check for that flag. */ if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED) { ACPI_FREE (AcpiGbl_RootTableList.Tables); } AcpiGbl_RootTableList.Tables = NULL; AcpiGbl_RootTableList.Flags = 0; AcpiGbl_RootTableList.CurrentTableCount = 0; ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ACPI Tables freed\n")); (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); return_VOID; }
void AcpiTbOverrideTable ( ACPI_TABLE_DESC *OldTableDesc) { ACPI_STATUS Status; char *OverrideType; ACPI_TABLE_DESC NewTableDesc; ACPI_TABLE_HEADER *Table; ACPI_PHYSICAL_ADDRESS Address; UINT32 Length; /* (1) Attempt logical override (returns a logical address) */ Status = AcpiOsTableOverride (OldTableDesc->Pointer, &Table); if (ACPI_SUCCESS (Status) && Table) { AcpiTbAcquireTempTable (&NewTableDesc, ACPI_PTR_TO_PHYSADDR (Table), ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL); OverrideType = "Logical"; goto FinishOverride; } /* (2) Attempt physical override (returns a physical address) */ Status = AcpiOsPhysicalTableOverride (OldTableDesc->Pointer, &Address, &Length); if (ACPI_SUCCESS (Status) && Address && Length) { AcpiTbAcquireTempTable (&NewTableDesc, Address, ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL); OverrideType = "Physical"; goto FinishOverride; } return; /* There was no override */ FinishOverride: /* Validate and verify a table before overriding */ Status = AcpiTbVerifyTempTable (&NewTableDesc, NULL); if (ACPI_FAILURE (Status)) { return; } ACPI_INFO ((AE_INFO, "%4.4s 0x%8.8X%8.8X" " %s table override, new table: 0x%8.8X%8.8X", OldTableDesc->Signature.Ascii, ACPI_FORMAT_UINT64 (OldTableDesc->Address), OverrideType, ACPI_FORMAT_UINT64 (NewTableDesc.Address))); /* We can now uninstall the original table */ AcpiTbUninstallTable (OldTableDesc); /* * Replace the original table descriptor and keep its state as * "VALIDATED". */ AcpiTbInitTableDescriptor (OldTableDesc, NewTableDesc.Address, NewTableDesc.Flags, NewTableDesc.Pointer); AcpiTbValidateTempTable (OldTableDesc); /* Release the temporary table descriptor */ AcpiTbReleaseTempTable (&NewTableDesc); }
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_INIT_FUNCTION AcpiReallocateRootTable ( void) { ACPI_STATUS Status; ACPI_TABLE_DESC *TableDesc; UINT32 i, j; ACPI_FUNCTION_TRACE (AcpiReallocateRootTable); /* * If there are tables unverified, it is required to reallocate the * root table list to clean up invalid table entries. Otherwise only * reallocate the root table list if the host provided a static buffer * for the table array in the call to AcpiInitializeTables(). */ if ((AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED) && AcpiGbl_EnableTableValidation) { return_ACPI_STATUS (AE_SUPPORT); } (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); /* * Ensure OS early boot logic, which is required by some hosts. If the * table state is reported to be wrong, developers should fix the * issue by invoking AcpiPutTable() for the reported table during the * early stage. */ for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) { TableDesc = &AcpiGbl_RootTableList.Tables[i]; if (TableDesc->Pointer) { ACPI_ERROR ((AE_INFO, "Table [%4.4s] is not invalidated during early boot stage", TableDesc->Signature.Ascii)); } } if (!AcpiGbl_EnableTableValidation) { /* * Now it's safe to do full table validation. We can do deferred * table initialization here once the flag is set. */ AcpiGbl_EnableTableValidation = TRUE; for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) { TableDesc = &AcpiGbl_RootTableList.Tables[i]; if (!(TableDesc->Flags & ACPI_TABLE_IS_VERIFIED)) { Status = AcpiTbVerifyTempTable (TableDesc, NULL, &j); if (ACPI_FAILURE (Status)) { AcpiTbUninstallTable (TableDesc); } } } } AcpiGbl_RootTableList.Flags |= ACPI_ROOT_ALLOW_RESIZE; Status = AcpiTbResizeRootTableList (); AcpiGbl_RootTableList.Flags |= ACPI_ROOT_ORIGIN_ALLOCATED; (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiLoadTable ( ACPI_TABLE_HEADER *TablePtr) { ACPI_STATUS Status; ACPI_TABLE_DESC TableInfo; ACPI_POINTER Address; ACPI_FUNCTION_TRACE ("AcpiLoadTable"); if (!TablePtr) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Copy the table to a local buffer */ Address.PointerType = ACPI_LOGICAL_POINTER | ACPI_LOGICAL_ADDRESSING; Address.Pointer.Logical = TablePtr; Status = AcpiTbGetTableBody (&Address, TablePtr, &TableInfo); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Install the new table into the local data structures */ Status = AcpiTbInstallTable (&TableInfo); if (ACPI_FAILURE (Status)) { /* Free table allocated by AcpiTbGetTableBody */ AcpiTbDeleteSingleTable (&TableInfo); return_ACPI_STATUS (Status); } /* Convert the table to common format if necessary */ switch (TableInfo.Type) { case ACPI_TABLE_FADT: Status = AcpiTbConvertTableFadt (); break; case ACPI_TABLE_FACS: Status = AcpiTbBuildCommonFacs (&TableInfo); break; default: /* Load table into namespace if it contains executable AML */ Status = AcpiNsLoadTable (TableInfo.InstalledDesc, AcpiGbl_RootNode); break; } if (ACPI_FAILURE (Status)) { /* Uninstall table and free the buffer */ (void) AcpiTbUninstallTable (TableInfo.InstalledDesc); } 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 (( "Ignoring installation of %4.4s at %8.8X%8.8X", NewTableDesc.Signature.Ascii, ACPI_FORMAT_UINT64 (Address))); goto ReleaseAndExit; } /* Acquire the table lock */ (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); /* Validate and verify a table before installation */ Status = AcpiTbVerifyTempTable (&NewTableDesc, NULL, &i); if (ACPI_FAILURE (Status)) { if (Status == AE_CTRL_TERMINATE) { /* * 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); (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); *TableIndex = i; return_ACPI_STATUS (AE_OK); } goto UnlockAndExit; } /* Add the table to the global root table list */ AcpiTbInstallTableWithOverride (&NewTableDesc, Override, TableIndex); /* Invoke table handler */ (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); AcpiTbNotifyTable (ACPI_TABLE_EVENT_INSTALL, NewTableDesc.Pointer); (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); UnlockAndExit: /* Release the table lock */ (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); ReleaseAndExit: /* Release the temporary table descriptor */ AcpiTbReleaseTempTable (&NewTableDesc); return_ACPI_STATUS (Status); }
void AcpiTbDeleteTablesByType ( ACPI_TABLE_TYPE Type) { ACPI_TABLE_DESC *TableDesc; UINT32 Count; UINT32 i; ACPI_FUNCTION_TRACE_U32 (TbDeleteTablesByType, Type); if (Type > ACPI_TABLE_ID_MAX) { return_VOID; } if (ACPI_FAILURE (AcpiUtAcquireMutex (ACPI_MTX_TABLES))) { return; } /* Clear the appropriate "typed" global table pointer */ switch (Type) { case ACPI_TABLE_ID_RSDP: AcpiGbl_RSDP = NULL; break; case ACPI_TABLE_ID_DSDT: AcpiGbl_DSDT = NULL; break; case ACPI_TABLE_ID_FADT: AcpiGbl_FADT = NULL; break; case ACPI_TABLE_ID_FACS: AcpiGbl_FACS = NULL; break; case ACPI_TABLE_ID_XSDT: AcpiGbl_XSDT = NULL; break; case ACPI_TABLE_ID_SSDT: case ACPI_TABLE_ID_PSDT: default: break; } /* * Free the table * 1) Get the head of the list */ TableDesc = AcpiGbl_TableLists[Type].Next; Count = AcpiGbl_TableLists[Type].Count; /* * 2) Walk the entire list, deleting both the allocated tables * and the table descriptors */ for (i = 0; i < Count; i++) { TableDesc = AcpiTbUninstallTable (TableDesc); } (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); return_VOID; }