void acpi_tb_free_acpi_tables_of_type ( acpi_table_desc *list_head) { acpi_table_desc *table_desc; u32 count; u32 i; FUNCTION_TRACE_PTR ("Tb_free_acpi_tables_of_type", list_head); /* Get the head of the list */ table_desc = list_head; count = list_head->count; /* * Walk the entire list, deleting both the allocated tables * and the table descriptors */ for (i = 0; i < count; i++) { table_desc = acpi_tb_uninstall_table (table_desc); } return_VOID; }
/******************************************************************************* * * FUNCTION: acpi_reallocate_root_table * * PARAMETERS: None * * RETURN: Status * * DESCRIPTION: Reallocate Root Table List into dynamic memory. Copies the * root list from the previously provided scratch area. Should * be called once dynamic memory allocation is available in the * kernel. * ******************************************************************************/ acpi_status ACPI_INIT_FUNCTION acpi_reallocate_root_table(void) { acpi_status status; struct acpi_table_desc *table_desc; u32 i, j; ACPI_FUNCTION_TRACE(acpi_reallocate_root_table); /* * Only reallocate the root table if the host provided a static buffer * for the table array in the call to acpi_initialize_tables. */ if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { return_ACPI_STATUS(AE_SUPPORT); } (void)acpi_ut_acquire_mutex(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 acpi_put_table() for the reported table during the * early stage. */ for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) { table_desc = &acpi_gbl_root_table_list.tables[i]; if (table_desc->pointer) { ACPI_ERROR((AE_INFO, "Table [%4.4s] is not invalidated during early boot stage", table_desc->signature.ascii)); } } if (!acpi_gbl_enable_table_validation) { /* * Now it's safe to do full table validation. We can do deferred * table initilization here once the flag is set. */ acpi_gbl_enable_table_validation = TRUE; for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) { table_desc = &acpi_gbl_root_table_list.tables[i]; if (!(table_desc->flags & ACPI_TABLE_IS_VERIFIED)) { status = acpi_tb_verify_temp_table(table_desc, NULL, &j); if (ACPI_FAILURE(status)) { acpi_tb_uninstall_table(table_desc); } } } } acpi_gbl_root_table_list.flags |= ACPI_ROOT_ALLOW_RESIZE; status = acpi_tb_resize_root_table_list(); acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED; (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); return_ACPI_STATUS(status); }
void acpi_tb_terminate(void) { u32 i; ACPI_FUNCTION_TRACE(tb_terminate); (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); /* Delete the individual tables */ for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) { acpi_tb_uninstall_table(&acpi_gbl_root_table_list.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 (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { ACPI_FREE(acpi_gbl_root_table_list.tables); } acpi_gbl_root_table_list.tables = NULL; acpi_gbl_root_table_list.flags = 0; acpi_gbl_root_table_list.current_table_count = 0; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n")); (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); return_VOID; }
acpi_status acpi_load_table ( acpi_table_header *table_ptr) { acpi_status status; acpi_table_desc table_info; FUNCTION_TRACE ("Acpi_load_table"); if (!table_ptr) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Copy the table to a local buffer */ status = acpi_tb_get_table (0, table_ptr, &table_info); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* Install the new table into the local data structures */ status = acpi_tb_install_table (NULL, &table_info); if (ACPI_FAILURE (status)) { /* Free table allocated by Acpi_tb_get_table */ acpi_tb_delete_single_table (&table_info); return_ACPI_STATUS (status); } status = acpi_ns_load_table (table_info.installed_desc, acpi_gbl_root_node); if (ACPI_FAILURE (status)) { /* Uninstall table and free the buffer */ acpi_tb_uninstall_table (table_info.installed_desc); return_ACPI_STATUS (status); } return_ACPI_STATUS (status); }
acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) { acpi_status status = AE_OK; union acpi_operand_object *table_desc = ddb_handle; struct acpi_table_desc *table_info; ACPI_FUNCTION_TRACE("ex_unload_table"); /* * Validate the handle * Although the handle is partially validated in acpi_ex_reconfiguration(), * when it calls acpi_ex_resolve_operands(), the handle is more completely * validated here. */ if ((!ddb_handle) || (ACPI_GET_DESCRIPTOR_TYPE(ddb_handle) != ACPI_DESC_TYPE_OPERAND) || (ACPI_GET_OBJECT_TYPE(ddb_handle) != ACPI_TYPE_LOCAL_REFERENCE)) { return_ACPI_STATUS(AE_BAD_PARAMETER); } /* Get the actual table descriptor from the ddb_handle */ table_info = (struct acpi_table_desc *)table_desc->reference.object; /* * Delete the entire namespace under this table Node * (Offset contains the table_id) */ acpi_ns_delete_namespace_by_owner(table_info->owner_id); acpi_ut_release_owner_id(&table_info->owner_id); /* Delete the table itself */ (void)acpi_tb_uninstall_table(table_info->installed_desc); /* Delete the table descriptor (ddb_handle) */ acpi_ut_remove_reference(table_desc); return_ACPI_STATUS(status); }
acpi_status acpi_load_table ( struct acpi_table_header *table_ptr) { acpi_status status; struct acpi_table_desc table_info; struct acpi_pointer address; ACPI_FUNCTION_TRACE ("acpi_load_table"); if (!table_ptr) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Copy the table to a local buffer */ address.pointer_type = ACPI_LOGICAL_POINTER | ACPI_LOGICAL_ADDRESSING; address.pointer.logical = table_ptr; status = acpi_tb_get_table_body (&address, table_ptr, &table_info); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* Install the new table into the local data structures */ status = acpi_tb_install_table (&table_info); if (ACPI_FAILURE (status)) { /* Free table allocated by acpi_tb_get_table_body */ acpi_tb_delete_single_table (&table_info); return_ACPI_STATUS (status); } /* Convert the table to common format if necessary */ switch (table_info.type) { case ACPI_TABLE_FADT: status = acpi_tb_convert_table_fadt (); break; case ACPI_TABLE_FACS: status = acpi_tb_build_common_facs (&table_info); break; default: /* Load table into namespace if it contains executable AML */ status = acpi_ns_load_table (table_info.installed_desc, acpi_gbl_root_node); break; } if (ACPI_FAILURE (status)) { /* Uninstall table and free the buffer */ (void) acpi_tb_uninstall_table (table_info.installed_desc); } return_ACPI_STATUS (status); }
static acpi_status acpi_ex_add_table(struct acpi_table_header *table, struct acpi_namespace_node *parent_node, union acpi_operand_object **ddb_handle) { acpi_status status; struct acpi_table_desc table_info; union acpi_operand_object *obj_desc; ACPI_FUNCTION_TRACE(ex_add_table); /* Create an object to be the table handle */ obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE); if (!obj_desc) { return_ACPI_STATUS(AE_NO_MEMORY); } /* Init the table handle */ obj_desc->reference.opcode = AML_LOAD_OP; *ddb_handle = obj_desc; /* Install the new table into the local data structures */ ACPI_MEMSET(&table_info, 0, sizeof(struct acpi_table_desc)); table_info.type = ACPI_TABLE_ID_SSDT; table_info.pointer = table; table_info.length = (acpi_size) table->length; table_info.allocation = ACPI_MEM_ALLOCATED; status = acpi_tb_install_table(&table_info); obj_desc->reference.object = table_info.installed_desc; if (ACPI_FAILURE(status)) { if (status == AE_ALREADY_EXISTS) { /* Table already exists, just return the handle */ return_ACPI_STATUS(AE_OK); } goto cleanup; } /* Add the table to the namespace */ status = acpi_ns_load_table(table_info.installed_desc, parent_node); if (ACPI_FAILURE(status)) { /* Uninstall table on error */ (void)acpi_tb_uninstall_table(table_info.installed_desc); goto cleanup; } return_ACPI_STATUS(AE_OK); cleanup: acpi_ut_remove_reference(obj_desc); *ddb_handle = NULL; return_ACPI_STATUS(status); }
void acpi_tb_delete_tables_by_type(acpi_table_type type) { struct acpi_table_desc *table_desc; u32 count; u32 i; ACPI_FUNCTION_TRACE_U32(tb_delete_tables_by_type, type); if (type > ACPI_TABLE_ID_MAX) { return_VOID; } if (ACPI_FAILURE(acpi_ut_acquire_mutex(ACPI_MTX_TABLES))) { return; } /* Clear the appropriate "typed" global table pointer */ switch (type) { case ACPI_TABLE_ID_RSDP: acpi_gbl_RSDP = NULL; break; case ACPI_TABLE_ID_DSDT: acpi_gbl_DSDT = NULL; break; case ACPI_TABLE_ID_FADT: acpi_gbl_FADT = NULL; break; case ACPI_TABLE_ID_FACS: acpi_gbl_FACS = NULL; break; case ACPI_TABLE_ID_XSDT: acpi_gbl_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 */ table_desc = acpi_gbl_table_lists[type].next; count = acpi_gbl_table_lists[type].count; /* * 2) Walk the entire list, deleting both the allocated tables * and the table descriptors */ for (i = 0; i < count; i++) { table_desc = acpi_tb_uninstall_table(table_desc); } (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); return_VOID; }