ACPI_STATUS AcpiTbUnloadTable ( UINT32 TableIndex) { ACPI_STATUS Status = AE_OK; ACPI_TABLE_HEADER *Table; ACPI_FUNCTION_TRACE (TbUnloadTable); /* Ensure the table is still loaded */ if (!AcpiTbIsTableLoaded (TableIndex)) { return_ACPI_STATUS (AE_NOT_EXIST); } /* Invoke table handler */ Status = AcpiGetTableByIndex (TableIndex, &Table); if (ACPI_SUCCESS (Status)) { AcpiTbNotifyTable (ACPI_TABLE_EVENT_UNLOAD, Table); } /* Delete the portion of the namespace owned by this table */ Status = AcpiTbDeleteNamespaceByOwner (TableIndex); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } (void) AcpiTbReleaseOwnerId (TableIndex); AcpiTbSetTableLoadedFlag (TableIndex, FALSE); return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiUnloadParentTable ( ACPI_HANDLE Object) { ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Object); ACPI_STATUS Status = AE_NOT_EXIST; ACPI_OWNER_ID OwnerId; UINT32 i; ACPI_FUNCTION_TRACE (AcpiUnloadParentTable); /* Parameter validation */ if (!Object) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* * The node OwnerId is currently the same as the parent table ID. * However, this could change in the future. */ OwnerId = Node->OwnerId; if (!OwnerId) { /* OwnerId==0 means DSDT is the owner. DSDT cannot be unloaded */ return_ACPI_STATUS (AE_TYPE); } /* Must acquire the interpreter lock during this operation */ Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Find the table in the global table list */ for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) { if (OwnerId != AcpiGbl_RootTableList.Tables[i].OwnerId) { continue; } /* * Allow unload of SSDT and OEMx tables only. Do not allow unload * of the DSDT. No other types of tables should get here, since * only these types can contain AML and thus are the only types * that can create namespace objects. */ if (ACPI_COMPARE_NAME ( AcpiGbl_RootTableList.Tables[i].Signature.Ascii, ACPI_SIG_DSDT)) { Status = AE_TYPE; break; } /* Ensure the table is actually loaded */ if (!AcpiTbIsTableLoaded (i)) { Status = AE_NOT_EXIST; break; } /* Invoke table handler if present */ if (AcpiGbl_TableHandler) { (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_UNLOAD, AcpiGbl_RootTableList.Tables[i].Pointer, AcpiGbl_TableHandlerContext); } /* * Delete all namespace objects owned by this table. Note that * these objects can appear anywhere in the namespace by virtue * of the AML "Scope" operator. Thus, we need to track ownership * by an ID, not simply a position within the hierarchy. */ Status = AcpiTbDeleteNamespaceByOwner (i); if (ACPI_FAILURE (Status)) { break; } Status = AcpiTbReleaseOwnerId (i); AcpiTbSetTableLoadedFlag (i, FALSE); break; } (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER); return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiExUnloadTable ( ACPI_OPERAND_OBJECT *DdbHandle) { ACPI_STATUS Status = AE_OK; ACPI_OPERAND_OBJECT *TableDesc = DdbHandle; UINT32 TableIndex; ACPI_TABLE_HEADER *Table; ACPI_FUNCTION_TRACE (ExUnloadTable); /* * Validate the handle * Although the handle is partially validated in AcpiExReconfiguration() * when it calls AcpiExResolveOperands(), the handle is more completely * validated here. * * Handle must be a valid operand object of type reference. Also, the * DdbHandle must still be marked valid (table has not been previously * unloaded) */ if ((!DdbHandle) || (ACPI_GET_DESCRIPTOR_TYPE (DdbHandle) != ACPI_DESC_TYPE_OPERAND) || (DdbHandle->Common.Type != ACPI_TYPE_LOCAL_REFERENCE) || (!(DdbHandle->Common.Flags & AOPOBJ_DATA_VALID))) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Get the table index from the DdbHandle */ TableIndex = TableDesc->Reference.Value; /* Ensure the table is still loaded */ if (!AcpiTbIsTableLoaded (TableIndex)) { return_ACPI_STATUS (AE_NOT_EXIST); } /* Invoke table handler if present */ if (AcpiGbl_TableHandler) { Status = AcpiGetTableByIndex (TableIndex, &Table); if (ACPI_SUCCESS (Status)) { (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_UNLOAD, Table, AcpiGbl_TableHandlerContext); } } /* Delete the portion of the namespace owned by this table */ Status = AcpiTbDeleteNamespaceByOwner (TableIndex); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } (void) AcpiTbReleaseOwnerId (TableIndex); AcpiTbSetTableLoadedFlag (TableIndex, FALSE); /* * Invalidate the handle. We do this because the handle may be stored * in a named object and may not be actually deleted until much later. */ DdbHandle->Common.Flags &= ~AOPOBJ_DATA_VALID; return_ACPI_STATUS (AE_OK); }