diff options
Diffstat (limited to 'drivers/acpi/tables/tbxface.c')
-rw-r--r-- | drivers/acpi/tables/tbxface.c | 671 |
1 files changed, 406 insertions, 265 deletions
diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c index 5ba9303293a..807978d5381 100644 --- a/drivers/acpi/tables/tbxface.c +++ b/drivers/acpi/tables/tbxface.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2006, R. Byron Moore + * Copyright (C) 2000 - 2007, R. Byron Moore * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,80 +49,158 @@ #define _COMPONENT ACPI_TABLES ACPI_MODULE_NAME("tbxface") +/* Local prototypes */ +static acpi_status acpi_tb_load_namespace(void); + /******************************************************************************* * - * FUNCTION: acpi_load_tables + * FUNCTION: acpi_allocate_root_table * - * PARAMETERS: None + * PARAMETERS: initial_table_count - Size of initial_table_array, in number of + * struct acpi_table_desc structures * * RETURN: Status * - * DESCRIPTION: This function is called to load the ACPI tables from the - * provided RSDT + * DESCRIPTION: Allocate a root table array. Used by i_aSL compiler and + * acpi_initialize_tables. * ******************************************************************************/ -acpi_status acpi_load_tables(void) + +acpi_status acpi_allocate_root_table(u32 initial_table_count) { - struct acpi_pointer rsdp_address; - acpi_status status; - ACPI_FUNCTION_TRACE(acpi_load_tables); + acpi_gbl_root_table_list.size = initial_table_count; + acpi_gbl_root_table_list.flags = ACPI_ROOT_ALLOW_RESIZE; - /* Get the RSDP */ + return (acpi_tb_resize_root_table_list()); +} - status = acpi_os_get_root_pointer(ACPI_LOGICAL_ADDRESSING, - &rsdp_address); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Could not get the RSDP")); - goto error_exit; - } +/******************************************************************************* + * + * FUNCTION: acpi_initialize_tables + * + * PARAMETERS: initial_table_array - Pointer to an array of pre-allocated + * struct acpi_table_desc structures. If NULL, the + * array is dynamically allocated. + * initial_table_count - Size of initial_table_array, in number of + * struct acpi_table_desc structures + * allow_realloc - Flag to tell Table Manager if resize of + * pre-allocated array is allowed. Ignored + * if initial_table_array is NULL. + * + * RETURN: Status + * + * DESCRIPTION: Initialize the table manager, get the RSDP and RSDT/XSDT. + * + * NOTE: Allows static allocation of the initial table array in order + * to avoid the use of dynamic memory in confined environments + * such as the kernel boot sequence where it may not be available. + * + * If the host OS memory managers are initialized, use NULL for + * initial_table_array, and the table will be dynamically allocated. + * + ******************************************************************************/ - /* Map and validate the RSDP */ +acpi_status __init +acpi_initialize_tables(struct acpi_table_desc * initial_table_array, + u32 initial_table_count, u8 allow_resize) +{ + acpi_physical_address rsdp_address; + acpi_status status; - acpi_gbl_table_flags = rsdp_address.pointer_type; + ACPI_FUNCTION_TRACE(acpi_initialize_tables); - status = acpi_tb_verify_rsdp(&rsdp_address); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "During RSDP validation")); - goto error_exit; + /* + * Set up the Root Table Array + * Allocate the table array if requested + */ + if (!initial_table_array) { + status = acpi_allocate_root_table(initial_table_count); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } else { + /* Root Table Array has been statically allocated by the host */ + + ACPI_MEMSET(initial_table_array, 0, + initial_table_count * + sizeof(struct acpi_table_desc)); + + acpi_gbl_root_table_list.tables = initial_table_array; + acpi_gbl_root_table_list.size = initial_table_count; + acpi_gbl_root_table_list.flags = ACPI_ROOT_ORIGIN_UNKNOWN; + if (allow_resize) { + acpi_gbl_root_table_list.flags |= + ACPI_ROOT_ALLOW_RESIZE; + } } - /* Get the RSDT via the RSDP */ + /* Get the address of the RSDP */ - status = acpi_tb_get_table_rsdt(); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Could not load RSDT")); - goto error_exit; + rsdp_address = acpi_os_get_root_pointer(); + if (!rsdp_address) { + return_ACPI_STATUS(AE_NOT_FOUND); } - /* Now get the tables needed by this subsystem (FADT, DSDT, etc.) */ + /* + * Get the root table (RSDT or XSDT) and extract all entries to the local + * Root Table Array. This array contains the information of the RSDT/XSDT + * in a common, more useable format. + */ + status = + acpi_tb_parse_root_table(rsdp_address, ACPI_TABLE_ORIGIN_MAPPED); + return_ACPI_STATUS(status); +} - status = acpi_tb_get_required_tables(); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Could not get all required tables (DSDT/FADT/FACS)")); - goto error_exit; +/******************************************************************************* + * + * 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_reallocate_root_table(void) +{ + struct acpi_table_desc *tables; + acpi_size new_size; + + 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); } - ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI Tables successfully acquired\n")); + new_size = + (acpi_gbl_root_table_list.count + + ACPI_ROOT_TABLE_SIZE_INCREMENT) * sizeof(struct acpi_table_desc); - /* Load the namespace from the tables */ + /* Create new array and copy the old array */ - status = acpi_ns_load_namespace(); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Could not load namespace")); - goto error_exit; + tables = ACPI_ALLOCATE_ZEROED(new_size); + if (!tables) { + return_ACPI_STATUS(AE_NO_MEMORY); } - return_ACPI_STATUS(AE_OK); + ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, new_size); - error_exit: - ACPI_EXCEPTION((AE_INFO, status, "Could not load tables")); - return_ACPI_STATUS(status); -} - -ACPI_EXPORT_SYMBOL(acpi_load_tables) + acpi_gbl_root_table_list.size = acpi_gbl_root_table_list.count; + acpi_gbl_root_table_list.tables = tables; + acpi_gbl_root_table_list.flags = + ACPI_ROOT_ORIGIN_ALLOCATED | ACPI_ROOT_ALLOW_RESIZE; + return_ACPI_STATUS(AE_OK); +} /******************************************************************************* * * FUNCTION: acpi_load_table @@ -141,342 +219,405 @@ ACPI_EXPORT_SYMBOL(acpi_load_tables) 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 */ + acpi_native_uint table_index; + struct acpi_table_desc table_desc; - 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); - } - - /* Check signature for a valid table type */ - - status = acpi_tb_recognize_table(&table_info, ACPI_TABLE_ALL); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } + if (!table_ptr) + return AE_BAD_PARAMETER; - /* Install the new table into the local data structures */ + ACPI_MEMSET(&table_desc, 0, sizeof(struct acpi_table_desc)); + table_desc.pointer = table_ptr; + table_desc.length = table_ptr->length; + table_desc.flags = ACPI_TABLE_ORIGIN_UNKNOWN; - status = acpi_tb_install_table(&table_info); + /* + * Install the new table into the local data structures + */ + status = acpi_tb_add_table(&table_desc, &table_index); if (ACPI_FAILURE(status)) { - if (status == AE_ALREADY_EXISTS) { - - /* Table already exists, no error */ - - status = AE_OK; - } - - /* Free table allocated by acpi_tb_get_table_body */ - - acpi_tb_delete_single_table(&table_info); - return_ACPI_STATUS(status); + return status; } + status = acpi_ns_load_table(table_index, acpi_gbl_root_node); + return status; +} - /* Convert the table to common format if necessary */ - - switch (table_info.type) { - case ACPI_TABLE_ID_FADT: - - status = acpi_tb_convert_table_fadt(); - break; - - case ACPI_TABLE_ID_FACS: +ACPI_EXPORT_SYMBOL(acpi_load_table) - status = acpi_tb_build_common_facs(&table_info); - break; +/****************************************************************************** + * + * FUNCTION: acpi_get_table_header + * + * PARAMETERS: Signature - ACPI signature of needed table + * Instance - Which instance (for SSDTs) + * out_table_header - The pointer to the table header to fill + * + * RETURN: Status and pointer to mapped table header + * + * DESCRIPTION: Finds an ACPI table header. + * + * NOTE: Caller is responsible in unmapping the header with + * acpi_os_unmap_memory + * + *****************************************************************************/ +acpi_status +acpi_get_table_header(char *signature, + acpi_native_uint instance, + struct acpi_table_header *out_table_header) +{ + acpi_native_uint i; + acpi_native_uint j; + struct acpi_table_header *header; - default: - /* Load table into namespace if it contains executable AML */ + /* Parameter validation */ - status = - acpi_ns_load_table(table_info.installed_desc, - acpi_gbl_root_node); - break; + if (!signature || !out_table_header) { + return (AE_BAD_PARAMETER); } - if (ACPI_FAILURE(status)) { + /* + * Walk the root table list + */ + for (i = 0, j = 0; i < acpi_gbl_root_table_list.count; i++) { + if (!ACPI_COMPARE_NAME + (&(acpi_gbl_root_table_list.tables[i].signature), + signature)) { + continue; + } - /* Uninstall table and free the buffer */ + if (++j < instance) { + continue; + } - (void)acpi_tb_uninstall_table(table_info.installed_desc); + if (!acpi_gbl_root_table_list.tables[i].pointer) { + if ((acpi_gbl_root_table_list.tables[i]. + flags & ACPI_TABLE_ORIGIN_MASK) == + ACPI_TABLE_ORIGIN_MAPPED) { + header = + acpi_os_map_memory(acpi_gbl_root_table_list. + tables[i].address, + sizeof(struct + acpi_table_header)); + if (!header) { + return AE_NO_MEMORY; + } + ACPI_MEMCPY(out_table_header, header, + sizeof(struct acpi_table_header)); + acpi_os_unmap_memory(header, + sizeof(struct + acpi_table_header)); + } else { + return AE_NOT_FOUND; + } + } else { + ACPI_MEMCPY(out_table_header, + acpi_gbl_root_table_list.tables[i].pointer, + sizeof(struct acpi_table_header)); + } + return (AE_OK); } - return_ACPI_STATUS(status); + return (AE_NOT_FOUND); } -ACPI_EXPORT_SYMBOL(acpi_load_table) +ACPI_EXPORT_SYMBOL(acpi_get_table_header) -/******************************************************************************* + +/****************************************************************************** * * FUNCTION: acpi_unload_table_id * - * PARAMETERS: table_type - Type of table to be unloaded - * id - Owner ID of the table to be removed. + * PARAMETERS: id - Owner ID of the table to be removed. * * RETURN: Status * * DESCRIPTION: This routine is used to force the unload of a table (by id) * ******************************************************************************/ -acpi_status acpi_unload_table_id(acpi_table_type table_type, acpi_owner_id id) +acpi_status acpi_unload_table_id(acpi_owner_id id) { - struct acpi_table_desc *table_desc; - acpi_status status; + int i; + acpi_status status = AE_NOT_EXIST; ACPI_FUNCTION_TRACE(acpi_unload_table); - /* Parameter validation */ - if (table_type > ACPI_TABLE_ID_MAX) - return_ACPI_STATUS(AE_BAD_PARAMETER); - /* Find table from the requested type list */ - table_desc = acpi_gbl_table_lists[table_type].next; - while (table_desc && table_desc->owner_id != id) - table_desc = table_desc->next; - - if (!table_desc) - return_ACPI_STATUS(AE_NOT_EXIST); - - /* - * 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 - */ - acpi_ns_delete_namespace_by_owner(table_desc->owner_id); - - status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - if (ACPI_FAILURE(status)) - return_ACPI_STATUS(status); - - (void)acpi_tb_uninstall_table(table_desc); - - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - - return_ACPI_STATUS(AE_OK); + for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { + if (id != acpi_gbl_root_table_list.tables[i].owner_id) { + continue; + } + /* + * 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 + */ + acpi_tb_delete_namespace_by_owner(i); + acpi_tb_release_owner_id(i); + acpi_tb_set_table_loaded_flag(i, FALSE); + } + return_ACPI_STATUS(status); } ACPI_EXPORT_SYMBOL(acpi_unload_table_id) -#ifdef ACPI_FUTURE_USAGE /******************************************************************************* * - * FUNCTION: acpi_unload_table + * FUNCTION: acpi_get_table * - * PARAMETERS: table_type - Type of table to be unloaded + * PARAMETERS: Signature - ACPI signature of needed table + * Instance - Which instance (for SSDTs) + * out_table - Where the pointer to the table is returned * - * RETURN: Status + * RETURN: Status and pointer to table * - * DESCRIPTION: This routine is used to force the unload of a table + * DESCRIPTION: Finds and verifies an ACPI table. * - ******************************************************************************/ -acpi_status acpi_unload_table(acpi_table_type table_type) + *****************************************************************************/ +acpi_status +acpi_get_table(char *signature, + acpi_native_uint instance, struct acpi_table_header ** out_table) { - struct acpi_table_desc *table_desc; - - ACPI_FUNCTION_TRACE(acpi_unload_table); + acpi_native_uint i; + acpi_native_uint j; + acpi_status status; /* Parameter validation */ - if (table_type > ACPI_TABLE_ID_MAX) { - return_ACPI_STATUS(AE_BAD_PARAMETER); + if (!signature || !out_table) { + return (AE_BAD_PARAMETER); } - /* Find all tables of the requested type */ + /* + * Walk the root table list + */ + for (i = 0, j = 0; i < acpi_gbl_root_table_list.count; i++) { + if (!ACPI_COMPARE_NAME + (&(acpi_gbl_root_table_list.tables[i].signature), + signature)) { + continue; + } - table_desc = acpi_gbl_table_lists[table_type].next; - if (!table_desc) { - return_ACPI_STATUS(AE_NOT_EXIST); - } + if (++j < instance) { + continue; + } - while (table_desc) { - /* - * 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 - */ - acpi_ns_delete_namespace_by_owner(table_desc->owner_id); - table_desc = table_desc->next; - } + status = + acpi_tb_verify_table(&acpi_gbl_root_table_list.tables[i]); + if (ACPI_SUCCESS(status)) { + *out_table = acpi_gbl_root_table_list.tables[i].pointer; + } - /* Delete (or unmap) all tables of this type */ + if (!acpi_gbl_permanent_mmap) { + acpi_gbl_root_table_list.tables[i].pointer = 0; + } - acpi_tb_delete_tables_by_type(table_type); - return_ACPI_STATUS(AE_OK); + return (status); + } + + return (AE_NOT_FOUND); } -ACPI_EXPORT_SYMBOL(acpi_unload_table) +ACPI_EXPORT_SYMBOL(acpi_get_table) /******************************************************************************* * - * FUNCTION: acpi_get_table_header + * FUNCTION: acpi_get_table_by_index * - * PARAMETERS: table_type - one of the defined table types - * Instance - the non zero instance of the table, allows - * support for multiple tables of the same type - * see acpi_gbl_acpi_table_flag - * out_table_header - pointer to the struct acpi_table_header if successful + * PARAMETERS: table_index - Table index + * Table - Where the pointer to the table is returned * - * DESCRIPTION: This function is called to get an ACPI table header. The caller - * supplies an pointer to a data area sufficient to contain an ACPI - * struct acpi_table_header structure. + * RETURN: Status and pointer to the table * - * The header contains a length field that can be used to determine - * the size of the buffer needed to contain the entire table. This - * function is not valid for the RSD PTR table since it does not - * have a standard header and is fixed length. + * DESCRIPTION: Obtain a table by an index into the global table list. * ******************************************************************************/ acpi_status -acpi_get_table_header(acpi_table_type table_type, - u32 instance, struct acpi_table_header *out_table_header) +acpi_get_table_by_index(acpi_native_uint table_index, + struct acpi_table_header ** table) { - struct acpi_table_header *tbl_ptr; acpi_status status; - ACPI_FUNCTION_TRACE(acpi_get_table_header); + ACPI_FUNCTION_TRACE(acpi_get_table_by_index); + + /* Parameter validation */ - if ((instance == 0) || - (table_type == ACPI_TABLE_ID_RSDP) || (!out_table_header)) { + if (!table) { return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Check the table type and instance */ + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + + /* Validate index */ - if ((table_type > ACPI_TABLE_ID_MAX) || - (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags) && - instance > 1)) { + if (table_index >= acpi_gbl_root_table_list.count) { + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Get a pointer to the entire table */ + if (!acpi_gbl_root_table_list.tables[table_index].pointer) { - status = acpi_tb_get_table_ptr(table_type, instance, &tbl_ptr); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } + /* Table is not mapped, map it */ - /* The function will return a NULL pointer if the table is not loaded */ - - if (tbl_ptr == NULL) { - return_ACPI_STATUS(AE_NOT_EXIST); + status = + acpi_tb_verify_table(&acpi_gbl_root_table_list. + tables[table_index]); + if (ACPI_FAILURE(status)) { + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return_ACPI_STATUS(status); + } } - /* Copy the header to the caller's buffer */ - - ACPI_MEMCPY(ACPI_CAST_PTR(void, out_table_header), - ACPI_CAST_PTR(void, tbl_ptr), - sizeof(struct acpi_table_header)); - - return_ACPI_STATUS(status); + *table = acpi_gbl_root_table_list.tables[table_index].pointer; + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return_ACPI_STATUS(AE_OK); } -ACPI_EXPORT_SYMBOL(acpi_get_table_header) -#endif /* ACPI_FUTURE_USAGE */ +ACPI_EXPORT_SYMBOL(acpi_get_table_by_index) /******************************************************************************* * - * FUNCTION: acpi_get_table + * FUNCTION: acpi_tb_load_namespace * - * PARAMETERS: table_type - one of the defined table types - * Instance - the non zero instance of the table, allows - * support for multiple tables of the same type - * see acpi_gbl_acpi_table_flag - * ret_buffer - pointer to a structure containing a buffer to - * receive the table + * PARAMETERS: None * * RETURN: Status * - * DESCRIPTION: This function is called to get an ACPI table. The caller - * supplies an out_buffer large enough to contain the entire ACPI - * table. The caller should call the acpi_get_table_header function - * first to determine the buffer size needed. Upon completion - * the out_buffer->Length field will indicate the number of bytes - * copied into the out_buffer->buf_ptr buffer. This table will be - * a complete table including the header. + * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in + * the RSDT/XSDT. * ******************************************************************************/ -acpi_status -acpi_get_table(acpi_table_type table_type, - u32 instance, struct acpi_buffer *ret_buffer) +static acpi_status acpi_tb_load_namespace(void) { - struct acpi_table_header *tbl_ptr; acpi_status status; - acpi_size table_length; + struct acpi_table_header *table; + acpi_native_uint i; - ACPI_FUNCTION_TRACE(acpi_get_table); + ACPI_FUNCTION_TRACE(tb_load_namespace); - /* Parameter validation */ + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - if (instance == 0) { - return_ACPI_STATUS(AE_BAD_PARAMETER); + /* + * Load the namespace. The DSDT is required, but any SSDT and PSDT tables + * are optional. + */ + if (!acpi_gbl_root_table_list.count || + !ACPI_COMPARE_NAME(& + (acpi_gbl_root_table_list. + tables[ACPI_TABLE_INDEX_DSDT].signature), + ACPI_SIG_DSDT) + || + ACPI_FAILURE(acpi_tb_verify_table + (&acpi_gbl_root_table_list. + tables[ACPI_TABLE_INDEX_DSDT]))) { + status = AE_NO_ACPI_TABLES; + goto unlock_and_exit; } - status = acpi_ut_validate_buffer(ret_buffer); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + /* + * Find DSDT table + */ + status = + acpi_os_table_override(acpi_gbl_root_table_list. + tables[ACPI_TABLE_INDEX_DSDT].pointer, + &table); + if (ACPI_SUCCESS(status) && table) { + /* + * DSDT table has been found + */ + acpi_tb_delete_table(&acpi_gbl_root_table_list. + tables[ACPI_TABLE_INDEX_DSDT]); + acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer = + table; + acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].length = + table->length; + acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].flags = + ACPI_TABLE_ORIGIN_UNKNOWN; + + ACPI_INFO((AE_INFO, "Table DSDT replaced by host OS")); + acpi_tb_print_table_header(0, table); } - /* Check the table type and instance */ + status = + acpi_tb_verify_table(&acpi_gbl_root_table_list. + tables[ACPI_TABLE_INDEX_DSDT]); + if (ACPI_FAILURE(status)) { - if ((table_type > ACPI_TABLE_ID_MAX) || - (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags) && - instance > 1)) { - return_ACPI_STATUS(AE_BAD_PARAMETER); + /* A valid DSDT is required */ + + status = AE_NO_ACPI_TABLES; + goto unlock_and_exit; } - /* Get a pointer to the entire table */ + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - status = acpi_tb_get_table_ptr(table_type, instance, &tbl_ptr); + /* + * Load and parse tables. + */ + status = acpi_ns_load_table(ACPI_TABLE_INDEX_DSDT, acpi_gbl_root_node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* - * acpi_tb_get_table_ptr will return a NULL pointer if the - * table is not loaded. + * Load any SSDT or PSDT tables. Note: Loop leaves tables locked */ - if (tbl_ptr == NULL) { - return_ACPI_STATUS(AE_NOT_EXIST); + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { + if ((!ACPI_COMPARE_NAME + (&(acpi_gbl_root_table_list.tables[i].signature), + ACPI_SIG_SSDT) + && + !ACPI_COMPARE_NAME(& + (acpi_gbl_root_table_list.tables[i]. + signature), ACPI_SIG_PSDT)) + || + ACPI_FAILURE(acpi_tb_verify_table + (&acpi_gbl_root_table_list.tables[i]))) { + continue; + } + + /* Ignore errors while loading tables, get as many as possible */ + + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + (void)acpi_ns_load_table(i, acpi_gbl_root_node); + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); } - /* Get the table length */ + ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI Tables successfully acquired\n")); - if (table_type == ACPI_TABLE_ID_RSDP) { + unlock_and_exit: + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return_ACPI_STATUS(status); +} - /* RSD PTR is the only "table" without a header */ +/******************************************************************************* + * + * FUNCTION: acpi_load_tables + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Load the ACPI tables from the RSDT/XSDT + * + ******************************************************************************/ - table_length = sizeof(struct rsdp_descriptor); - } else { - table_length = (acpi_size) tbl_ptr->length; - } +acpi_status acpi_load_tables(void) +{ + acpi_status status; - /* Validate/Allocate/Clear caller buffer */ + ACPI_FUNCTION_TRACE(acpi_load_tables); - status = acpi_ut_initialize_buffer(ret_buffer, table_length); + /* + * Load the namespace from the tables + */ + status = acpi_tb_load_namespace(); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + ACPI_EXCEPTION((AE_INFO, status, + "While loading namespace from ACPI tables")); } - /* Copy the table to the buffer */ - - ACPI_MEMCPY(ACPI_CAST_PTR(void, ret_buffer->pointer), - ACPI_CAST_PTR(void, tbl_ptr), table_length); - - return_ACPI_STATUS(AE_OK); + return_ACPI_STATUS(status); } -ACPI_EXPORT_SYMBOL(acpi_get_table) +ACPI_EXPORT_SYMBOL(acpi_load_tables) |