Commit f3d2e786 authored by Bob Moore's avatar Bob Moore Committed by Len Brown

ACPICA: Implement simplified Table Manager

The Table Manager component has been completely
redesigned and reimplemented. The new design is much
simpler, and reduces the overall code and data size of
the kernel-resident ACPICA by approximately 5%. Also,
it is now possible to obtain the ACPI tables very early
during kernel initialization, even before dynamic memory
management is initialized.
Signed-off-by: default avatarAlexey Starikovskiy <alexey.y.starikovskiy@intel.com>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent 2e42005b
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include <acpi/acpi.h> #include <acpi/acpi.h>
#include <acpi/acdispat.h> #include <acpi/acdispat.h>
#include <acpi/acnamesp.h> #include <acpi/acnamesp.h>
#include <acpi/actables.h>
#define _COMPONENT ACPI_DISPATCHER #define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dsinit") ACPI_MODULE_NAME("dsinit")
...@@ -90,7 +91,7 @@ acpi_ds_init_one_object(acpi_handle obj_handle, ...@@ -90,7 +91,7 @@ acpi_ds_init_one_object(acpi_handle obj_handle,
* We are only interested in NS nodes owned by the table that * We are only interested in NS nodes owned by the table that
* was just loaded * was just loaded
*/ */
if (node->owner_id != info->table_desc->owner_id) { if (node->owner_id != info->owner_id) {
return (AE_OK); return (AE_OK);
} }
...@@ -150,14 +151,21 @@ acpi_ds_init_one_object(acpi_handle obj_handle, ...@@ -150,14 +151,21 @@ acpi_ds_init_one_object(acpi_handle obj_handle,
******************************************************************************/ ******************************************************************************/
acpi_status acpi_status
acpi_ds_initialize_objects(struct acpi_table_desc * table_desc, acpi_ds_initialize_objects(acpi_native_uint table_index,
struct acpi_namespace_node * start_node) struct acpi_namespace_node * start_node)
{ {
acpi_status status; acpi_status status;
struct acpi_init_walk_info info; struct acpi_init_walk_info info;
struct acpi_table_header *table;
acpi_owner_id owner_id;
ACPI_FUNCTION_TRACE(ds_initialize_objects); ACPI_FUNCTION_TRACE(ds_initialize_objects);
status = acpi_tb_get_owner_id(table_index, &owner_id);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"**** Starting initialization of namespace objects ****\n")); "**** Starting initialization of namespace objects ****\n"));
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "Parsing all Control Methods:")); ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "Parsing all Control Methods:"));
...@@ -166,7 +174,8 @@ acpi_ds_initialize_objects(struct acpi_table_desc * table_desc, ...@@ -166,7 +174,8 @@ acpi_ds_initialize_objects(struct acpi_table_desc * table_desc,
info.op_region_count = 0; info.op_region_count = 0;
info.object_count = 0; info.object_count = 0;
info.device_count = 0; info.device_count = 0;
info.table_desc = table_desc; info.table_index = table_index;
info.owner_id = owner_id;
/* Walk entire namespace from the supplied root */ /* Walk entire namespace from the supplied root */
...@@ -176,10 +185,14 @@ acpi_ds_initialize_objects(struct acpi_table_desc * table_desc, ...@@ -176,10 +185,14 @@ acpi_ds_initialize_objects(struct acpi_table_desc * table_desc,
ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace")); ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace"));
} }
status = acpi_get_table_by_index(table_index, &table);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
"\nTable [%4.4s](id %4.4X) - %hd Objects with %hd Devices %hd Methods %hd Regions\n", "\nTable [%4.4s](id %4.4X) - %hd Objects with %hd Devices %hd Methods %hd Regions\n",
table_desc->pointer->signature, table->signature, owner_id, info.object_count,
table_desc->owner_id, info.object_count,
info.device_count, info.method_count, info.device_count, info.method_count,
info.op_region_count)); info.op_region_count));
......
...@@ -70,13 +70,6 @@ acpi_status acpi_ev_initialize_events(void) ...@@ -70,13 +70,6 @@ acpi_status acpi_ev_initialize_events(void)
ACPI_FUNCTION_TRACE(ev_initialize_events); ACPI_FUNCTION_TRACE(ev_initialize_events);
/* Make sure we have ACPI tables */
if (!acpi_gbl_DSDT) {
ACPI_WARNING((AE_INFO, "No ACPI tables present!"));
return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
/* /*
* Initialize the Fixed and General Purpose Events. This is done prior to * Initialize the Fixed and General Purpose Events. This is done prior to
* enabling SCIs to prevent interrupts from occurring before the handlers are * enabling SCIs to prevent interrupts from occurring before the handlers are
......
...@@ -529,7 +529,7 @@ static struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32 ...@@ -529,7 +529,7 @@ static struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32
/* Install new interrupt handler if not SCI_INT */ /* Install new interrupt handler if not SCI_INT */
if (interrupt_number != acpi_gbl_FADT->sci_int) { if (interrupt_number != acpi_gbl_FADT.sci_interrupt) {
status = acpi_os_install_interrupt_handler(interrupt_number, status = acpi_os_install_interrupt_handler(interrupt_number,
acpi_ev_gpe_xrupt_handler, acpi_ev_gpe_xrupt_handler,
gpe_xrupt); gpe_xrupt);
...@@ -567,7 +567,7 @@ acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt) ...@@ -567,7 +567,7 @@ acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt)
/* We never want to remove the SCI interrupt handler */ /* We never want to remove the SCI interrupt handler */
if (gpe_xrupt->interrupt_number == acpi_gbl_FADT->sci_int) { if (gpe_xrupt->interrupt_number == acpi_gbl_FADT.sci_interrupt) {
gpe_xrupt->gpe_block_list_head = NULL; gpe_xrupt->gpe_block_list_head = NULL;
return_ACPI_STATUS(AE_OK); return_ACPI_STATUS(AE_OK);
} }
...@@ -803,17 +803,17 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) ...@@ -803,17 +803,17 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
(gpe_block->block_address.address (gpe_block->block_address.address
+ i + gpe_block->register_count)); + i + gpe_block->register_count));
this_register->status_address.address_space_id = this_register->status_address.space_id =
gpe_block->block_address.address_space_id; gpe_block->block_address.space_id;
this_register->enable_address.address_space_id = this_register->enable_address.space_id =
gpe_block->block_address.address_space_id; gpe_block->block_address.space_id;
this_register->status_address.register_bit_width = this_register->status_address.bit_width =
ACPI_GPE_REGISTER_WIDTH; ACPI_GPE_REGISTER_WIDTH;
this_register->enable_address.register_bit_width = this_register->enable_address.bit_width =
ACPI_GPE_REGISTER_WIDTH; ACPI_GPE_REGISTER_WIDTH;
this_register->status_address.register_bit_offset = this_register->status_address.bit_offset =
ACPI_GPE_REGISTER_WIDTH; ACPI_GPE_REGISTER_WIDTH;
this_register->enable_address.register_bit_offset = this_register->enable_address.bit_offset =
ACPI_GPE_REGISTER_WIDTH; ACPI_GPE_REGISTER_WIDTH;
/* Init the event_info for each GPE within this register */ /* Init the event_info for each GPE within this register */
...@@ -1109,11 +1109,12 @@ acpi_status acpi_ev_gpe_initialize(void) ...@@ -1109,11 +1109,12 @@ acpi_status acpi_ev_gpe_initialize(void)
* If EITHER the register length OR the block address are zero, then that * If EITHER the register length OR the block address are zero, then that
* particular block is not supported. * particular block is not supported.
*/ */
if (acpi_gbl_FADT->gpe0_blk_len && acpi_gbl_FADT->xgpe0_blk.address) { if (acpi_gbl_FADT.gpe0_block_length &&
acpi_gbl_FADT.xgpe0_block.address) {
/* GPE block 0 exists (has both length and address > 0) */ /* GPE block 0 exists (has both length and address > 0) */
register_count0 = (u16) (acpi_gbl_FADT->gpe0_blk_len / 2); register_count0 = (u16) (acpi_gbl_FADT.gpe0_block_length / 2);
gpe_number_max = gpe_number_max =
(register_count0 * ACPI_GPE_REGISTER_WIDTH) - 1; (register_count0 * ACPI_GPE_REGISTER_WIDTH) - 1;
...@@ -1121,9 +1122,9 @@ acpi_status acpi_ev_gpe_initialize(void) ...@@ -1121,9 +1122,9 @@ acpi_status acpi_ev_gpe_initialize(void)
/* Install GPE Block 0 */ /* Install GPE Block 0 */
status = acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device, status = acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device,
&acpi_gbl_FADT->xgpe0_blk, &acpi_gbl_FADT.xgpe0_block,
register_count0, 0, register_count0, 0,
acpi_gbl_FADT->sci_int, acpi_gbl_FADT.sci_interrupt,
&acpi_gbl_gpe_fadt_blocks[0]); &acpi_gbl_gpe_fadt_blocks[0]);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
...@@ -1132,20 +1133,21 @@ acpi_status acpi_ev_gpe_initialize(void) ...@@ -1132,20 +1133,21 @@ acpi_status acpi_ev_gpe_initialize(void)
} }
} }
if (acpi_gbl_FADT->gpe1_blk_len && acpi_gbl_FADT->xgpe1_blk.address) { if (acpi_gbl_FADT.gpe1_block_length &&
acpi_gbl_FADT.xgpe1_block.address) {
/* GPE block 1 exists (has both length and address > 0) */ /* GPE block 1 exists (has both length and address > 0) */
register_count1 = (u16) (acpi_gbl_FADT->gpe1_blk_len / 2); register_count1 = (u16) (acpi_gbl_FADT.gpe1_block_length / 2);
/* Check for GPE0/GPE1 overlap (if both banks exist) */ /* Check for GPE0/GPE1 overlap (if both banks exist) */
if ((register_count0) && if ((register_count0) &&
(gpe_number_max >= acpi_gbl_FADT->gpe1_base)) { (gpe_number_max >= acpi_gbl_FADT.gpe1_base)) {
ACPI_ERROR((AE_INFO, ACPI_ERROR((AE_INFO,
"GPE0 block (GPE 0 to %d) overlaps the GPE1 block (GPE %d to %d) - Ignoring GPE1", "GPE0 block (GPE 0 to %d) overlaps the GPE1 block (GPE %d to %d) - Ignoring GPE1",
gpe_number_max, acpi_gbl_FADT->gpe1_base, gpe_number_max, acpi_gbl_FADT.gpe1_base,
acpi_gbl_FADT->gpe1_base + acpi_gbl_FADT.gpe1_base +
((register_count1 * ((register_count1 *
ACPI_GPE_REGISTER_WIDTH) - 1))); ACPI_GPE_REGISTER_WIDTH) - 1)));
...@@ -1157,10 +1159,11 @@ acpi_status acpi_ev_gpe_initialize(void) ...@@ -1157,10 +1159,11 @@ acpi_status acpi_ev_gpe_initialize(void)
status = status =
acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device, acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device,
&acpi_gbl_FADT->xgpe1_blk, &acpi_gbl_FADT.xgpe1_block,
register_count1, register_count1,
acpi_gbl_FADT->gpe1_base, acpi_gbl_FADT.gpe1_base,
acpi_gbl_FADT->sci_int, acpi_gbl_FADT.
sci_interrupt,
&acpi_gbl_gpe_fadt_blocks &acpi_gbl_gpe_fadt_blocks
[1]); [1]);
...@@ -1173,7 +1176,7 @@ acpi_status acpi_ev_gpe_initialize(void) ...@@ -1173,7 +1176,7 @@ acpi_status acpi_ev_gpe_initialize(void)
* GPE0 and GPE1 do not have to be contiguous in the GPE number * GPE0 and GPE1 do not have to be contiguous in the GPE number
* space. However, GPE0 always starts at GPE number zero. * space. However, GPE0 always starts at GPE number zero.
*/ */
gpe_number_max = acpi_gbl_FADT->gpe1_base + gpe_number_max = acpi_gbl_FADT.gpe1_base +
((register_count1 * ACPI_GPE_REGISTER_WIDTH) - 1); ((register_count1 * ACPI_GPE_REGISTER_WIDTH) - 1);
} }
} }
......
...@@ -63,6 +63,10 @@ static const char *acpi_notify_value_names[] = { ...@@ -63,6 +63,10 @@ static const char *acpi_notify_value_names[] = {
}; };
#endif #endif
/* Pointer to FACS needed for the Global Lock */
static struct acpi_table_facs *facs = NULL;
/* Local prototypes */ /* Local prototypes */
static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context); static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context);
...@@ -306,7 +310,7 @@ static u32 acpi_ev_global_lock_handler(void *context) ...@@ -306,7 +310,7 @@ static u32 acpi_ev_global_lock_handler(void *context)
* If we don't get it now, it will be marked pending and we will * If we don't get it now, it will be marked pending and we will
* take another interrupt when it becomes free. * take another interrupt when it becomes free.
*/ */
ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, acquired); ACPI_ACQUIRE_GLOBAL_LOCK(facs, acquired);
if (acquired) { if (acquired) {
/* Got the lock, now wake all threads waiting for it */ /* Got the lock, now wake all threads waiting for it */
...@@ -342,6 +346,13 @@ acpi_status acpi_ev_init_global_lock_handler(void) ...@@ -342,6 +346,13 @@ acpi_status acpi_ev_init_global_lock_handler(void)
ACPI_FUNCTION_TRACE(ev_init_global_lock_handler); ACPI_FUNCTION_TRACE(ev_init_global_lock_handler);
status =
acpi_get_table(ACPI_SIG_FACS, 0,
(struct acpi_table_header **)&facs);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
acpi_gbl_global_lock_present = TRUE; acpi_gbl_global_lock_present = TRUE;
status = acpi_install_fixed_event_handler(ACPI_EVENT_GLOBAL, status = acpi_install_fixed_event_handler(ACPI_EVENT_GLOBAL,
acpi_ev_global_lock_handler, acpi_ev_global_lock_handler,
...@@ -414,7 +425,7 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout) ...@@ -414,7 +425,7 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout)
/* Attempt to acquire the actual hardware lock */ /* Attempt to acquire the actual hardware lock */
ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, acquired); ACPI_ACQUIRE_GLOBAL_LOCK(facs, acquired);
if (acquired) { if (acquired) {
/* We got the lock */ /* We got the lock */
...@@ -438,6 +449,7 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout) ...@@ -438,6 +449,7 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout)
*/ */
status = acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore, status = acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore,
ACPI_WAIT_FOREVER); ACPI_WAIT_FOREVER);
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
...@@ -472,8 +484,7 @@ acpi_status acpi_ev_release_global_lock(void) ...@@ -472,8 +484,7 @@ acpi_status acpi_ev_release_global_lock(void)
/* Allow any thread to release the lock */ /* Allow any thread to release the lock */
ACPI_RELEASE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, ACPI_RELEASE_GLOBAL_LOCK(facs, pending);
pending);
/* /*
* If the pending bit was set, we must write GBL_RLS to the control * If the pending bit was set, we must write GBL_RLS to the control
......
...@@ -142,7 +142,8 @@ u32 acpi_ev_install_sci_handler(void) ...@@ -142,7 +142,8 @@ u32 acpi_ev_install_sci_handler(void)
ACPI_FUNCTION_TRACE(ev_install_sci_handler); ACPI_FUNCTION_TRACE(ev_install_sci_handler);
status = acpi_os_install_interrupt_handler((u32) acpi_gbl_FADT->sci_int, status =
acpi_os_install_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt,
acpi_ev_sci_xrupt_handler, acpi_ev_sci_xrupt_handler,
acpi_gbl_gpe_xrupt_list_head); acpi_gbl_gpe_xrupt_list_head);
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
...@@ -175,7 +176,8 @@ acpi_status acpi_ev_remove_sci_handler(void) ...@@ -175,7 +176,8 @@ acpi_status acpi_ev_remove_sci_handler(void)
/* Just let the OS remove the handler and disable the level */ /* Just let the OS remove the handler and disable the level */
status = acpi_os_remove_interrupt_handler((u32) acpi_gbl_FADT->sci_int, status =
acpi_os_remove_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt,
acpi_ev_sci_xrupt_handler); acpi_ev_sci_xrupt_handler);
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
......
...@@ -65,13 +65,6 @@ acpi_status acpi_enable(void) ...@@ -65,13 +65,6 @@ acpi_status acpi_enable(void)
ACPI_FUNCTION_TRACE(acpi_enable); ACPI_FUNCTION_TRACE(acpi_enable);
/* Make sure we have the FADT */
if (!acpi_gbl_FADT) {
ACPI_WARNING((AE_INFO, "No FADT information present!"));
return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) { if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
ACPI_DEBUG_PRINT((ACPI_DB_INIT, ACPI_DEBUG_PRINT((ACPI_DB_INIT,
"System is already in ACPI mode\n")); "System is already in ACPI mode\n"));
...@@ -111,11 +104,6 @@ acpi_status acpi_disable(void) ...@@ -111,11 +104,6 @@ acpi_status acpi_disable(void)
ACPI_FUNCTION_TRACE(acpi_disable); ACPI_FUNCTION_TRACE(acpi_disable);
if (!acpi_gbl_FADT) {
ACPI_WARNING((AE_INFO, "No FADT information present!"));
return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
if (acpi_hw_get_mode() == ACPI_SYS_MODE_LEGACY) { if (acpi_hw_get_mode() == ACPI_SYS_MODE_LEGACY) {
ACPI_DEBUG_PRINT((ACPI_DB_INIT, ACPI_DEBUG_PRINT((ACPI_DB_INIT,
"System is already in legacy (non-ACPI) mode\n")); "System is already in legacy (non-ACPI) mode\n"));
......
...@@ -54,7 +54,7 @@ ACPI_MODULE_NAME("exconfig") ...@@ -54,7 +54,7 @@ ACPI_MODULE_NAME("exconfig")
/* Local prototypes */ /* Local prototypes */
static acpi_status static acpi_status
acpi_ex_add_table(struct acpi_table_header *table, acpi_ex_add_table(acpi_native_uint table_index,
struct acpi_namespace_node *parent_node, struct acpi_namespace_node *parent_node,
union acpi_operand_object **ddb_handle); union acpi_operand_object **ddb_handle);
...@@ -74,12 +74,11 @@ acpi_ex_add_table(struct acpi_table_header *table, ...@@ -74,12 +74,11 @@ acpi_ex_add_table(struct acpi_table_header *table,
******************************************************************************/ ******************************************************************************/
static acpi_status static acpi_status
acpi_ex_add_table(struct acpi_table_header *table, acpi_ex_add_table(acpi_native_uint table_index,
struct acpi_namespace_node *parent_node, struct acpi_namespace_node *parent_node,
union acpi_operand_object **ddb_handle) union acpi_operand_object **ddb_handle)
{ {
acpi_status status; acpi_status status;
struct acpi_table_desc table_info;
union acpi_operand_object *obj_desc; union acpi_operand_object *obj_desc;
ACPI_FUNCTION_TRACE(ex_add_table); ACPI_FUNCTION_TRACE(ex_add_table);
...@@ -98,42 +97,16 @@ acpi_ex_add_table(struct acpi_table_header *table, ...@@ -98,42 +97,16 @@ acpi_ex_add_table(struct acpi_table_header *table,
/* Install the new table into the local data structures */ /* Install the new table into the local data structures */
ACPI_MEMSET(&table_info, 0, sizeof(struct acpi_table_desc)); obj_desc->reference.object = ACPI_CAST_PTR(void, table_index);
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 */ /* Add the table to the namespace */
status = acpi_ns_load_table(table_info.installed_desc, parent_node); status = acpi_ns_load_table(table_index, parent_node);
if (ACPI_FAILURE(status)) { 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); acpi_ut_remove_reference(obj_desc);
*ddb_handle = NULL; *ddb_handle = NULL;
}
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
...@@ -156,11 +129,12 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, ...@@ -156,11 +129,12 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
{ {
acpi_status status; acpi_status status;
union acpi_operand_object **operand = &walk_state->operands[0]; union acpi_operand_object **operand = &walk_state->operands[0];
struct acpi_table_header *table; acpi_native_uint table_index;
struct acpi_namespace_node *parent_node; struct acpi_namespace_node *parent_node;
struct acpi_namespace_node *start_node; struct acpi_namespace_node *start_node;
struct acpi_namespace_node *parameter_node = NULL; struct acpi_namespace_node *parameter_node = NULL;
union acpi_operand_object *ddb_handle; union acpi_operand_object *ddb_handle;
struct acpi_table_header *table;
ACPI_FUNCTION_TRACE(ex_load_table_op); ACPI_FUNCTION_TRACE(ex_load_table_op);
...@@ -182,7 +156,7 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, ...@@ -182,7 +156,7 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
status = acpi_tb_find_table(operand[0]->string.pointer, status = acpi_tb_find_table(operand[0]->string.pointer,
operand[1]->string.pointer, operand[1]->string.pointer,
operand[2]->string.pointer, &table); operand[2]->string.pointer, &table_index);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
if (status != AE_NOT_FOUND) { if (status != AE_NOT_FOUND) {
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
...@@ -245,7 +219,7 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, ...@@ -245,7 +219,7 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
/* Load the table into the namespace */ /* Load the table into the namespace */
status = acpi_ex_add_table(table, parent_node, &ddb_handle); status = acpi_ex_add_table(table_index, parent_node, &ddb_handle);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
...@@ -266,9 +240,13 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, ...@@ -266,9 +240,13 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
} }
} }
status = acpi_get_table_by_index(table_index, &table);
if (ACPI_SUCCESS(status)) {
ACPI_INFO((AE_INFO, ACPI_INFO((AE_INFO,
"Dynamic OEM Table Load - [%4.4s] OemId [%6.6s] OemTableId [%8.8s]", "Dynamic OEM Table Load - [%4.4s] OemId [%6.6s] OemTableId [%8.8s]",
table->signature, table->oem_id, table->oem_table_id)); table->signature, table->oem_id,
table->oem_table_id));
}
*return_desc = ddb_handle; *return_desc = ddb_handle;
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
...@@ -298,6 +276,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, ...@@ -298,6 +276,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
union acpi_operand_object *ddb_handle; union acpi_operand_object *ddb_handle;
union acpi_operand_object *buffer_desc = NULL; union acpi_operand_object *buffer_desc = NULL;
struct acpi_table_header *table_ptr = NULL; struct acpi_table_header *table_ptr = NULL;
acpi_native_uint table_index;
acpi_physical_address address; acpi_physical_address address;
struct acpi_table_header table_header; struct acpi_table_header table_header;
acpi_integer temp; acpi_integer temp;
...@@ -420,8 +399,8 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, ...@@ -420,8 +399,8 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
/* The table must be either an SSDT or a PSDT */ /* The table must be either an SSDT or a PSDT */
if ((!ACPI_COMPARE_NAME(table_ptr->signature, PSDT_SIG)) && if ((!ACPI_COMPARE_NAME(table_ptr->signature, ACPI_SIG_PSDT)) &&
(!ACPI_COMPARE_NAME(table_ptr->signature, SSDT_SIG))) { (!ACPI_COMPARE_NAME(table_ptr->signature, ACPI_SIG_SSDT))) {
ACPI_ERROR((AE_INFO, ACPI_ERROR((AE_INFO,
"Table has invalid signature [%4.4s], must be SSDT or PSDT", "Table has invalid signature [%4.4s], must be SSDT or PSDT",
table_ptr->signature)); table_ptr->signature));
...@@ -429,9 +408,16 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, ...@@ -429,9 +408,16 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
goto cleanup; goto cleanup;
} }
/* Install the new table into the local data structures */ /*
* Install the new table into the local data structures
*/
status = acpi_tb_add_table(table_ptr, &table_index);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
status = acpi_ex_add_table(table_ptr, acpi_gbl_root_node, &ddb_handle); status =
acpi_ex_add_table(table_index, acpi_gbl_root_node, &ddb_handle);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
/* On error, table_ptr was deallocated above */ /* On error, table_ptr was deallocated above */
...@@ -477,7 +463,7 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) ...@@ -477,7 +463,7 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
{ {
acpi_status status = AE_OK; acpi_status status = AE_OK;
union acpi_operand_object *table_desc = ddb_handle; union acpi_operand_object *table_desc = ddb_handle;
struct acpi_table_desc *table_info; acpi_native_uint table_index;
ACPI_FUNCTION_TRACE(ex_unload_table); ACPI_FUNCTION_TRACE(ex_unload_table);
...@@ -493,19 +479,18 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) ...@@ -493,19 +479,18 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
return_ACPI_STATUS(AE_BAD_PARAMETER); return_ACPI_STATUS(AE_BAD_PARAMETER);
} }
/* Get the actual table descriptor from the ddb_handle */ /* Get the table index from the ddb_handle */
table_info = (struct acpi_table_desc *)table_desc->reference.object; table_index = (acpi_native_uint) table_desc->reference.object;
/* /*
* Delete the entire namespace under this table Node * Delete the entire namespace under this table Node
* (Offset contains the table_id) * (Offset contains the table_id)
*/ */
acpi_ns_delete_namespace_by_owner(table_info->owner_id); acpi_tb_delete_namespace_by_owner(table_index);
acpi_tb_release_owner_id(table_index);
/* Delete the table itself */
(void)acpi_tb_uninstall_table(table_info->installed_desc); acpi_tb_set_table_loaded_flag(table_index, FALSE);
/* Delete the table descriptor (ddb_handle) */ /* Delete the table descriptor (ddb_handle) */
......
...@@ -359,8 +359,9 @@ acpi_status acpi_ex_create_table_region(struct acpi_walk_state *walk_state) ...@@ -359,8 +359,9 @@ acpi_status acpi_ex_create_table_region(struct acpi_walk_state *walk_state)
union acpi_operand_object **operand = &walk_state->operands[0]; union acpi_operand_object **operand = &walk_state->operands[0];
union acpi_operand_object *obj_desc; union acpi_operand_object *obj_desc;
struct acpi_namespace_node *node; struct acpi_namespace_node *node;
struct acpi_table_header *table;
union acpi_operand_object *region_obj2; union acpi_operand_object *region_obj2;
acpi_native_uint table_index;
struct acpi_table_header *table;
ACPI_FUNCTION_TRACE(ex_create_table_region); ACPI_FUNCTION_TRACE(ex_create_table_region);
...@@ -380,7 +381,7 @@ acpi_status acpi_ex_create_table_region(struct acpi_walk_state *walk_state) ...@@ -380,7 +381,7 @@ acpi_status acpi_ex_create_table_region(struct acpi_walk_state *walk_state)
status = acpi_tb_find_table(operand[1]->string.pointer, status = acpi_tb_find_table(operand[1]->string.pointer,
operand[2]->string.pointer, operand[2]->string.pointer,
operand[3]->string.pointer, &table); operand[3]->string.pointer, &table_index);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
...@@ -395,6 +396,11 @@ acpi_status acpi_ex_create_table_region(struct acpi_walk_state *walk_state) ...@@ -395,6 +396,11 @@ acpi_status acpi_ex_create_table_region(struct acpi_walk_state *walk_state)
region_obj2 = obj_desc->common.next_object; region_obj2 = obj_desc->common.next_object;
region_obj2->extra.region_context = NULL; region_obj2->extra.region_context = NULL;
status = acpi_get_table_by_index(table_index, &table);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Init the region from the operands */ /* Init the region from the operands */
obj_desc->region.space_id = REGION_DATA_TABLE; obj_desc->region.space_id = REGION_DATA_TABLE;
...@@ -553,7 +559,8 @@ acpi_ex_create_method(u8 * aml_start, ...@@ -553,7 +559,8 @@ acpi_ex_create_method(u8 * aml_start,
obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_METHOD); obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
if (!obj_desc) { if (!obj_desc) {
return_ACPI_STATUS(AE_NO_MEMORY); status = AE_NO_MEMORY;
goto exit;
} }
/* Save the method's AML pointer and length */ /* Save the method's AML pointer and length */
...@@ -597,6 +604,7 @@ acpi_ex_create_method(u8 * aml_start, ...@@ -597,6 +604,7 @@ acpi_ex_create_method(u8 * aml_start,
acpi_ut_remove_reference(obj_desc); acpi_ut_remove_reference(obj_desc);
exit:
/* Remove a reference to the operand */ /* Remove a reference to the operand */
acpi_ut_remove_reference(operand[1]); acpi_ut_remove_reference(operand[1]);
......
...@@ -257,14 +257,13 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc, ...@@ -257,14 +257,13 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc,
} }
ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD, ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD,
" Region [%s:%X], Width %X, ByteBase %X, Offset %X at %8.8X%8.8X\n", " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %p\n",
acpi_ut_get_region_name(rgn_desc->region. acpi_ut_get_region_name(rgn_desc->region.
space_id), space_id),
rgn_desc->region.space_id, rgn_desc->region.space_id,
obj_desc->common_field.access_byte_width, obj_desc->common_field.access_byte_width,
obj_desc->common_field.base_byte_offset, obj_desc->common_field.base_byte_offset,
field_datum_byte_offset, field_datum_byte_offset, (void *)address));
ACPI_FORMAT_UINT64(address)));
/* Invoke the appropriate address_space/op_region handler */ /* Invoke the appropriate address_space/op_region handler */
......
...@@ -155,16 +155,15 @@ acpi_ex_system_memory_space_handler(u32 function, ...@@ -155,16 +155,15 @@ acpi_ex_system_memory_space_handler(u32 function,
/* Create a new mapping starting at the address given */ /* Create a new mapping starting at the address given */
status = acpi_os_map_memory(address, window_size, mem_info->mapped_logical_address =
(void **)&mem_info-> acpi_os_map_memory((acpi_native_uint) address, window_size);
mapped_logical_address); if (!mem_info->mapped_logical_address) {
if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO, ACPI_ERROR((AE_INFO,
"Could not map memory at %8.8X%8.8X, size %X", "Could not map memory at %8.8X%8.8X, size %X",
ACPI_FORMAT_UINT64(address), ACPI_FORMAT_UINT64(address),
(u32) window_size)); (u32) window_size));
mem_info->mapped_length = 0; mem_info->mapped_length = 0;
return_ACPI_STATUS(status); return_ACPI_STATUS(AE_NO_MEMORY);
} }
/* Save the physical address and mapping size */ /* Save the physical address and mapping size */
......
...@@ -65,13 +65,6 @@ acpi_status acpi_hw_initialize(void) ...@@ -65,13 +65,6 @@ acpi_status acpi_hw_initialize(void)
ACPI_FUNCTION_TRACE(hw_initialize); ACPI_FUNCTION_TRACE(hw_initialize);
/* We must have the ACPI tables by the time we get here */
if (!acpi_gbl_FADT) {
ACPI_ERROR((AE_INFO, "No FADT is present"));
return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
/* Sanity check the FADT for valid values */ /* Sanity check the FADT for valid values */
status = acpi_ut_validate_fadt(); status = acpi_ut_validate_fadt();
...@@ -106,7 +99,7 @@ acpi_status acpi_hw_set_mode(u32 mode) ...@@ -106,7 +99,7 @@ acpi_status acpi_hw_set_mode(u32 mode)
* ACPI 2.0 clarified that if SMI_CMD in FADT is zero, * ACPI 2.0 clarified that if SMI_CMD in FADT is zero,
* system does not support mode transition. * system does not support mode transition.
*/ */
if (!acpi_gbl_FADT->smi_cmd) { if (!acpi_gbl_FADT.smi_command) {
ACPI_ERROR((AE_INFO, ACPI_ERROR((AE_INFO,
"No SMI_CMD in FADT, mode transition failed")); "No SMI_CMD in FADT, mode transition failed"));
return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE); return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
...@@ -119,7 +112,7 @@ acpi_status acpi_hw_set_mode(u32 mode) ...@@ -119,7 +112,7 @@ acpi_status acpi_hw_set_mode(u32 mode)
* we make sure both the numbers are zero to determine these * we make sure both the numbers are zero to determine these
* transitions are not supported. * transitions are not supported.
*/ */
if (!acpi_gbl_FADT->acpi_enable && !acpi_gbl_FADT->acpi_disable) { if (!acpi_gbl_FADT.acpi_enable && !acpi_gbl_FADT.acpi_disable) {
ACPI_ERROR((AE_INFO, ACPI_ERROR((AE_INFO,
"No ACPI mode transition supported in this system (enable/disable both zero)")); "No ACPI mode transition supported in this system (enable/disable both zero)"));
return_ACPI_STATUS(AE_OK); return_ACPI_STATUS(AE_OK);
...@@ -130,9 +123,8 @@ acpi_status acpi_hw_set_mode(u32 mode) ...@@ -130,9 +123,8 @@ acpi_status acpi_hw_set_mode(u32 mode)
/* BIOS should have disabled ALL fixed and GP events */ /* BIOS should have disabled ALL fixed and GP events */
status = acpi_os_write_port(acpi_gbl_FADT->smi_cmd, status = acpi_os_write_port(acpi_gbl_FADT.smi_command,
(u32) acpi_gbl_FADT->acpi_enable, (u32) acpi_gbl_FADT.acpi_enable, 8);
8);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Attempting to enable ACPI mode\n")); "Attempting to enable ACPI mode\n"));
break; break;
...@@ -143,8 +135,8 @@ acpi_status acpi_hw_set_mode(u32 mode) ...@@ -143,8 +135,8 @@ acpi_status acpi_hw_set_mode(u32 mode)
* BIOS should clear all fixed status bits and restore fixed event * BIOS should clear all fixed status bits and restore fixed event
* enable bits to default * enable bits to default
*/ */
status = acpi_os_write_port(acpi_gbl_FADT->smi_cmd, status = acpi_os_write_port(acpi_gbl_FADT.smi_command,
(u32) acpi_gbl_FADT->acpi_disable, (u32) acpi_gbl_FADT.acpi_disable,
8); 8);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Attempting to enable Legacy (non-ACPI) mode\n")); "Attempting to enable Legacy (non-ACPI) mode\n"));
...@@ -204,7 +196,7 @@ u32 acpi_hw_get_mode(void) ...@@ -204,7 +196,7 @@ u32 acpi_hw_get_mode(void)
* ACPI 2.0 clarified that if SMI_CMD in FADT is zero, * ACPI 2.0 clarified that if SMI_CMD in FADT is zero,
* system does not support mode transition. * system does not support mode transition.
*/ */
if (!acpi_gbl_FADT->smi_cmd) { if (!acpi_gbl_FADT.smi_command) {
return_UINT32(ACPI_SYS_MODE_ACPI); return_UINT32(ACPI_SYS_MODE_ACPI);
} }
......
...@@ -73,7 +73,7 @@ acpi_status acpi_hw_clear_acpi_status(u32 flags) ...@@ -73,7 +73,7 @@ acpi_status acpi_hw_clear_acpi_status(u32 flags)
ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %04X\n", ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %04X\n",
ACPI_BITMASK_ALL_FIXED_STATUS, ACPI_BITMASK_ALL_FIXED_STATUS,
(u16) acpi_gbl_FADT->xpm1a_evt_blk.address)); (u16) acpi_gbl_FADT.xpm1a_event_block.address));
lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
...@@ -86,10 +86,10 @@ acpi_status acpi_hw_clear_acpi_status(u32 flags) ...@@ -86,10 +86,10 @@ acpi_status acpi_hw_clear_acpi_status(u32 flags)
/* Clear the fixed events */ /* Clear the fixed events */
if (acpi_gbl_FADT->xpm1b_evt_blk.address) { if (acpi_gbl_FADT.xpm1b_event_block.address) {
status = status =
acpi_hw_low_level_write(16, ACPI_BITMASK_ALL_FIXED_STATUS, acpi_hw_low_level_write(16, ACPI_BITMASK_ALL_FIXED_STATUS,
&acpi_gbl_FADT->xpm1b_evt_blk); &acpi_gbl_FADT.xpm1b_event_block);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
goto unlock_and_exit; goto unlock_and_exit;
} }
...@@ -422,8 +422,9 @@ acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags) ...@@ -422,8 +422,9 @@ acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags)
ACPI_DEBUG_PRINT((ACPI_DB_IO, ACPI_DEBUG_PRINT((ACPI_DB_IO,
"PM2 control: Read %X from %8.8X%8.8X\n", "PM2 control: Read %X from %8.8X%8.8X\n",
register_value, register_value,
ACPI_FORMAT_UINT64(acpi_gbl_FADT-> ACPI_FORMAT_UINT64(acpi_gbl_FADT.
xpm2_cnt_blk.address))); xpm2_control_block.
address)));
ACPI_REGISTER_INSERT_VALUE(register_value, ACPI_REGISTER_INSERT_VALUE(register_value,
bit_reg_info->bit_position, bit_reg_info->bit_position,
...@@ -433,8 +434,9 @@ acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags) ...@@ -433,8 +434,9 @@ acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags)
ACPI_DEBUG_PRINT((ACPI_DB_IO, ACPI_DEBUG_PRINT((ACPI_DB_IO,
"About to write %4.4X to %8.8X%8.8X\n", "About to write %4.4X to %8.8X%8.8X\n",
register_value, register_value,
ACPI_FORMAT_UINT64(acpi_gbl_FADT-> ACPI_FORMAT_UINT64(acpi_gbl_FADT.
xpm2_cnt_blk.address))); xpm2_control_block.
address)));
status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
ACPI_REGISTER_PM2_CONTROL, ACPI_REGISTER_PM2_CONTROL,
...@@ -495,7 +497,7 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value) ...@@ -495,7 +497,7 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value)
status = status =
acpi_hw_low_level_read(16, &value1, acpi_hw_low_level_read(16, &value1,
&acpi_gbl_FADT->xpm1a_evt_blk); &acpi_gbl_FADT.xpm1a_event_block);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
goto unlock_and_exit; goto unlock_and_exit;
} }
...@@ -504,7 +506,7 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value) ...@@ -504,7 +506,7 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value)
status = status =
acpi_hw_low_level_read(16, &value2, acpi_hw_low_level_read(16, &value2,
&acpi_gbl_FADT->xpm1b_evt_blk); &acpi_gbl_FADT.xpm1b_event_block);
value1 |= value2; value1 |= value2;
break; break;
...@@ -527,14 +529,14 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value) ...@@ -527,14 +529,14 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value)
status = status =
acpi_hw_low_level_read(16, &value1, acpi_hw_low_level_read(16, &value1,
&acpi_gbl_FADT->xpm1a_cnt_blk); &acpi_gbl_FADT.xpm1a_control_block);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
goto unlock_and_exit; goto unlock_and_exit;
} }
status = status =
acpi_hw_low_level_read(16, &value2, acpi_hw_low_level_read(16, &value2,
&acpi_gbl_FADT->xpm1b_cnt_blk); &acpi_gbl_FADT.xpm1b_control_block);
value1 |= value2; value1 |= value2;
break; break;
...@@ -542,19 +544,20 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value) ...@@ -542,19 +544,20 @@ acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value)
status = status =
acpi_hw_low_level_read(8, &value1, acpi_hw_low_level_read(8, &value1,
&acpi_gbl_FADT->xpm2_cnt_blk); &acpi_gbl_FADT.xpm2_control_block);
break; break;
case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
status = status =
acpi_hw_low_level_read(32, &value1, acpi_hw_low_level_read(32, &value1,
&acpi_gbl_FADT->xpm_tmr_blk); &acpi_gbl_FADT.xpm_timer_block);
break; break;
case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
status = acpi_os_read_port(acpi_gbl_FADT->smi_cmd, &value1, 8); status =
acpi_os_read_port(acpi_gbl_FADT.smi_command, &value1, 8);
break; break;
default: default:
...@@ -635,7 +638,7 @@ acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value) ...@@ -635,7 +638,7 @@ acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value)
status = status =
acpi_hw_low_level_write(16, value, acpi_hw_low_level_write(16, value,
&acpi_gbl_FADT->xpm1a_evt_blk); &acpi_gbl_FADT.xpm1a_event_block);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
goto unlock_and_exit; goto unlock_and_exit;
} }
...@@ -644,7 +647,7 @@ acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value) ...@@ -644,7 +647,7 @@ acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value)
status = status =
acpi_hw_low_level_write(16, value, acpi_hw_low_level_write(16, value,
&acpi_gbl_FADT->xpm1b_evt_blk); &acpi_gbl_FADT.xpm1b_event_block);
break; break;
case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */ case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */
...@@ -682,49 +685,50 @@ acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value) ...@@ -682,49 +685,50 @@ acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value)
status = status =
acpi_hw_low_level_write(16, value, acpi_hw_low_level_write(16, value,
&acpi_gbl_FADT->xpm1a_cnt_blk); &acpi_gbl_FADT.xpm1a_control_block);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
goto unlock_and_exit; goto unlock_and_exit;
} }
status = status =
acpi_hw_low_level_write(16, value, acpi_hw_low_level_write(16, value,
&acpi_gbl_FADT->xpm1b_cnt_blk); &acpi_gbl_FADT.xpm1b_control_block);
break; break;
case ACPI_REGISTER_PM1A_CONTROL: /* 16-bit access */ case ACPI_REGISTER_PM1A_CONTROL: /* 16-bit access */
status = status =
acpi_hw_low_level_write(16, value, acpi_hw_low_level_write(16, value,
&acpi_gbl_FADT->xpm1a_cnt_blk); &acpi_gbl_FADT.xpm1a_control_block);
break; break;
case ACPI_REGISTER_PM1B_CONTROL: /* 16-bit access */ case ACPI_REGISTER_PM1B_CONTROL: /* 16-bit access */
status = status =
acpi_hw_low_level_write(16, value, acpi_hw_low_level_write(16, value,
&acpi_gbl_FADT->xpm1b_cnt_blk); &acpi_gbl_FADT.xpm1b_control_block);
break; break;
case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
status = status =
acpi_hw_low_level_write(8, value, acpi_hw_low_level_write(8, value,
&acpi_gbl_FADT->xpm2_cnt_blk); &acpi_gbl_FADT.xpm2_control_block);
break; break;
case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
status = status =
acpi_hw_low_level_write(32, value, acpi_hw_low_level_write(32, value,
&acpi_gbl_FADT->xpm_tmr_blk); &acpi_gbl_FADT.xpm_timer_block);
break; break;
case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
/* SMI_CMD is currently always in IO space */ /* SMI_CMD is currently always in IO space */
status = acpi_os_write_port(acpi_gbl_FADT->smi_cmd, value, 8); status =
acpi_os_write_port(acpi_gbl_FADT.smi_command, value, 8);
break; break;
default: default:
...@@ -783,7 +787,7 @@ acpi_hw_low_level_read(u32 width, u32 * value, struct acpi_generic_address *reg) ...@@ -783,7 +787,7 @@ acpi_hw_low_level_read(u32 width, u32 * value, struct acpi_generic_address *reg)
* Two address spaces supported: Memory or IO. * Two address spaces supported: Memory or IO.
* PCI_Config is not supported here because the GAS struct is insufficient * PCI_Config is not supported here because the GAS struct is insufficient
*/ */
switch (reg->address_space_id) { switch (reg->space_id) {
case ACPI_ADR_SPACE_SYSTEM_MEMORY: case ACPI_ADR_SPACE_SYSTEM_MEMORY:
status = acpi_os_read_memory((acpi_physical_address) address, status = acpi_os_read_memory((acpi_physical_address) address,
...@@ -798,8 +802,7 @@ acpi_hw_low_level_read(u32 width, u32 * value, struct acpi_generic_address *reg) ...@@ -798,8 +802,7 @@ acpi_hw_low_level_read(u32 width, u32 * value, struct acpi_generic_address *reg)
default: default:
ACPI_ERROR((AE_INFO, ACPI_ERROR((AE_INFO,
"Unsupported address space: %X", "Unsupported address space: %X", reg->space_id));
reg->address_space_id));
return (AE_BAD_PARAMETER); return (AE_BAD_PARAMETER);
} }
...@@ -807,7 +810,7 @@ acpi_hw_low_level_read(u32 width, u32 * value, struct acpi_generic_address *reg) ...@@ -807,7 +810,7 @@ acpi_hw_low_level_read(u32 width, u32 * value, struct acpi_generic_address *reg)
"Read: %8.8X width %2d from %8.8X%8.8X (%s)\n", "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n",
*value, width, *value, width,
ACPI_FORMAT_UINT64(address), ACPI_FORMAT_UINT64(address),
acpi_ut_get_region_name(reg->address_space_id))); acpi_ut_get_region_name(reg->space_id)));
return (status); return (status);
} }
...@@ -854,7 +857,7 @@ acpi_hw_low_level_write(u32 width, u32 value, struct acpi_generic_address * reg) ...@@ -854,7 +857,7 @@ acpi_hw_low_level_write(u32 width, u32 value, struct acpi_generic_address * reg)
* Two address spaces supported: Memory or IO. * Two address spaces supported: Memory or IO.
* PCI_Config is not supported here because the GAS struct is insufficient * PCI_Config is not supported here because the GAS struct is insufficient
*/ */
switch (reg->address_space_id) { switch (reg->space_id) {
case ACPI_ADR_SPACE_SYSTEM_MEMORY: case ACPI_ADR_SPACE_SYSTEM_MEMORY:
status = acpi_os_write_memory((acpi_physical_address) address, status = acpi_os_write_memory((acpi_physical_address) address,
...@@ -869,8 +872,7 @@ acpi_hw_low_level_write(u32 width, u32 value, struct acpi_generic_address * reg) ...@@ -869,8 +872,7 @@ acpi_hw_low_level_write(u32 width, u32 value, struct acpi_generic_address * reg)
default: default:
ACPI_ERROR((AE_INFO, ACPI_ERROR((AE_INFO,
"Unsupported address space: %X", "Unsupported address space: %X", reg->space_id));
reg->address_space_id));
return (AE_BAD_PARAMETER); return (AE_BAD_PARAMETER);
} }
...@@ -878,7 +880,7 @@ acpi_hw_low_level_write(u32 width, u32 value, struct acpi_generic_address * reg) ...@@ -878,7 +880,7 @@ acpi_hw_low_level_write(u32 width, u32 value, struct acpi_generic_address * reg)
"Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n", "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n",
value, width, value, width,
ACPI_FORMAT_UINT64(address), ACPI_FORMAT_UINT64(address),
acpi_ut_get_region_name(reg->address_space_id))); acpi_ut_get_region_name(reg->space_id)));
return (status); return (status);
} }
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
*/ */
#include <acpi/acpi.h> #include <acpi/acpi.h>
#include <acpi/actables.h>
#define _COMPONENT ACPI_HARDWARE #define _COMPONENT ACPI_HARDWARE
ACPI_MODULE_NAME("hwsleep") ACPI_MODULE_NAME("hwsleep")
...@@ -62,17 +63,32 @@ ACPI_MODULE_NAME("hwsleep") ...@@ -62,17 +63,32 @@ ACPI_MODULE_NAME("hwsleep")
acpi_status acpi_status
acpi_set_firmware_waking_vector(acpi_physical_address physical_address) acpi_set_firmware_waking_vector(acpi_physical_address physical_address)
{ {
struct acpi_table_facs *facs;
acpi_status status;
ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector); ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector);
/* Get the FACS */
status =
acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,
(struct acpi_table_header **)&facs);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Set the vector */ /* Set the vector */
if (acpi_gbl_common_fACS.vector_width == 32) { if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) {
*(ACPI_CAST_PTR /*
(u32, acpi_gbl_common_fACS.firmware_waking_vector)) * ACPI 1.0 FACS or short table or optional X_ field is zero
= (u32) physical_address; */
facs->firmware_waking_vector = (u32) physical_address;
} else { } else {
*acpi_gbl_common_fACS.firmware_waking_vector = physical_address; /*
* ACPI 2.0 FACS with valid X_ field
*/
facs->xfirmware_waking_vector = physical_address;
} }
return_ACPI_STATUS(AE_OK); return_ACPI_STATUS(AE_OK);
...@@ -97,6 +113,8 @@ ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector) ...@@ -97,6 +113,8 @@ ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector)
acpi_status acpi_status
acpi_get_firmware_waking_vector(acpi_physical_address * physical_address) acpi_get_firmware_waking_vector(acpi_physical_address * physical_address)
{ {
struct acpi_table_facs *facs;
acpi_status status;
ACPI_FUNCTION_TRACE(acpi_get_firmware_waking_vector); ACPI_FUNCTION_TRACE(acpi_get_firmware_waking_vector);
...@@ -104,16 +122,29 @@ acpi_get_firmware_waking_vector(acpi_physical_address * physical_address) ...@@ -104,16 +122,29 @@ acpi_get_firmware_waking_vector(acpi_physical_address * physical_address)
return_ACPI_STATUS(AE_BAD_PARAMETER); return_ACPI_STATUS(AE_BAD_PARAMETER);
} }
/* Get the FACS */
status =
acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,
(struct acpi_table_header **)&facs);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Get the vector */ /* Get the vector */
if (acpi_gbl_common_fACS.vector_width == 32) { if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) {
*physical_address = (acpi_physical_address) /*
* * ACPI 1.0 FACS or short table or optional X_ field is zero
(ACPI_CAST_PTR */
(u32, acpi_gbl_common_fACS.firmware_waking_vector)); *physical_address =
(acpi_physical_address) facs->firmware_waking_vector;
} else { } else {
/*
* ACPI 2.0 FACS with valid X_ field
*/
*physical_address = *physical_address =
*acpi_gbl_common_fACS.firmware_waking_vector; (acpi_physical_address) facs->xfirmware_waking_vector;
} }
return_ACPI_STATUS(AE_OK); return_ACPI_STATUS(AE_OK);
...@@ -429,8 +460,8 @@ acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void) ...@@ -429,8 +460,8 @@ acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void)
ACPI_FLUSH_CPU_CACHE(); ACPI_FLUSH_CPU_CACHE();
status = acpi_os_write_port(acpi_gbl_FADT->smi_cmd, status = acpi_os_write_port(acpi_gbl_FADT.smi_command,
(u32) acpi_gbl_FADT->S4bios_req, 8); (u32) acpi_gbl_FADT.S4bios_request, 8);
do { do {
acpi_os_stall(1000); acpi_os_stall(1000);
......
...@@ -66,7 +66,7 @@ acpi_status acpi_get_timer_resolution(u32 * resolution) ...@@ -66,7 +66,7 @@ acpi_status acpi_get_timer_resolution(u32 * resolution)
return_ACPI_STATUS(AE_BAD_PARAMETER); return_ACPI_STATUS(AE_BAD_PARAMETER);
} }
if (acpi_gbl_FADT->tmr_val_ext == 0) { if ((acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER) == 0) {
*resolution = 24; *resolution = 24;
} else { } else {
*resolution = 32; *resolution = 32;
...@@ -98,7 +98,8 @@ acpi_status acpi_get_timer(u32 * ticks) ...@@ -98,7 +98,8 @@ acpi_status acpi_get_timer(u32 * ticks)
return_ACPI_STATUS(AE_BAD_PARAMETER); return_ACPI_STATUS(AE_BAD_PARAMETER);
} }
status = acpi_hw_low_level_read(32, ticks, &acpi_gbl_FADT->xpm_tmr_blk); status =
acpi_hw_low_level_read(32, ticks, &acpi_gbl_FADT.xpm_timer_block);
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
...@@ -153,7 +154,7 @@ acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed) ...@@ -153,7 +154,7 @@ acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed)
if (start_ticks < end_ticks) { if (start_ticks < end_ticks) {
delta_ticks = end_ticks - start_ticks; delta_ticks = end_ticks - start_ticks;
} else if (start_ticks > end_ticks) { } else if (start_ticks > end_ticks) {
if (acpi_gbl_FADT->tmr_val_ext == 0) { if ((acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER) == 0) {
/* 24-bit Timer */ /* 24-bit Timer */
......
...@@ -44,13 +44,12 @@ ...@@ -44,13 +44,12 @@
#include <acpi/acpi.h> #include <acpi/acpi.h>
#include <acpi/acnamesp.h> #include <acpi/acnamesp.h>
#include <acpi/acdispat.h> #include <acpi/acdispat.h>
#include <acpi/actables.h>
#define _COMPONENT ACPI_NAMESPACE #define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nsload") ACPI_MODULE_NAME("nsload")
/* Local prototypes */ /* Local prototypes */
static acpi_status acpi_ns_load_table_by_type(acpi_table_type table_type);
#ifdef ACPI_FUTURE_IMPLEMENTATION #ifdef ACPI_FUTURE_IMPLEMENTATION
acpi_status acpi_ns_unload_namespace(acpi_handle handle); acpi_status acpi_ns_unload_namespace(acpi_handle handle);
...@@ -62,7 +61,7 @@ static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle); ...@@ -62,7 +61,7 @@ static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle);
* *
* FUNCTION: acpi_ns_load_table * FUNCTION: acpi_ns_load_table
* *
* PARAMETERS: table_desc - Descriptor for table to be loaded * PARAMETERS: table_index - Index for table to be loaded
* Node - Owning NS node * Node - Owning NS node
* *
* RETURN: Status * RETURN: Status
...@@ -72,42 +71,13 @@ static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle); ...@@ -72,42 +71,13 @@ static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle);
******************************************************************************/ ******************************************************************************/
acpi_status acpi_status
acpi_ns_load_table(struct acpi_table_desc *table_desc, acpi_ns_load_table(acpi_native_uint table_index,
struct acpi_namespace_node *node) struct acpi_namespace_node *node)
{ {
acpi_status status; acpi_status status;
ACPI_FUNCTION_TRACE(ns_load_table); ACPI_FUNCTION_TRACE(ns_load_table);
/* Check if table contains valid AML (must be DSDT, PSDT, SSDT, etc.) */
if (!
(acpi_gbl_table_data[table_desc->type].
flags & ACPI_TABLE_EXECUTABLE)) {
/* Just ignore this table */
return_ACPI_STATUS(AE_OK);
}
/* Check validity of the AML start and length */
if (!table_desc->aml_start) {
ACPI_ERROR((AE_INFO, "Null AML pointer"));
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AML block at %p\n",
table_desc->aml_start));
/* Ignore table if there is no AML contained within */
if (!table_desc->aml_length) {
ACPI_WARNING((AE_INFO, "Zero-length AML block in table [%4.4s]",
table_desc->pointer->signature));
return_ACPI_STATUS(AE_OK);
}
/* /*
* Parse the table and load the namespace with all named * Parse the table and load the namespace with all named
* objects found within. Control methods are NOT parsed * objects found within. Control methods are NOT parsed
...@@ -117,15 +87,34 @@ acpi_ns_load_table(struct acpi_table_desc *table_desc, ...@@ -117,15 +87,34 @@ acpi_ns_load_table(struct acpi_table_desc *table_desc,
* to another control method, we can't continue parsing * to another control method, we can't continue parsing
* because we don't know how many arguments to parse next! * because we don't know how many arguments to parse next!
*/ */
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* If table already loaded into namespace, just return */
if (acpi_tb_is_table_loaded(table_index)) {
status = AE_ALREADY_EXISTS;
goto unlock;
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"**** Loading table into namespace ****\n")); "**** Loading table into namespace ****\n"));
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); status = acpi_tb_allocate_owner_id(table_index);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status); goto unlock;
}
status = acpi_ns_parse_table(table_index, node->child);
if (ACPI_SUCCESS(status)) {
acpi_tb_set_table_loaded_flag(table_index, TRUE);
} else {
acpi_tb_release_owner_id(table_index);
} }
status = acpi_ns_parse_table(table_desc, node->child); unlock:
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
...@@ -141,7 +130,7 @@ acpi_ns_load_table(struct acpi_table_desc *table_desc, ...@@ -141,7 +130,7 @@ acpi_ns_load_table(struct acpi_table_desc *table_desc,
ACPI_DEBUG_PRINT((ACPI_DB_INFO, ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"**** Begin Table Method Parsing and Object Initialization ****\n")); "**** Begin Table Method Parsing and Object Initialization ****\n"));
status = acpi_ds_initialize_objects(table_desc, node); status = acpi_ds_initialize_objects(table_index, node);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"**** Completed Table Method Parsing and Object Initialization ****\n")); "**** Completed Table Method Parsing and Object Initialization ****\n"));
...@@ -149,99 +138,7 @@ acpi_ns_load_table(struct acpi_table_desc *table_desc, ...@@ -149,99 +138,7 @@ acpi_ns_load_table(struct acpi_table_desc *table_desc,
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
/******************************************************************************* #ifdef ACPI_OBSOLETE_FUNCTIONS
*
* FUNCTION: acpi_ns_load_table_by_type
*
* PARAMETERS: table_type - Id of the table type to load
*
* RETURN: Status
*
* DESCRIPTION: Load an ACPI table or tables into the namespace. All tables
* of the given type are loaded. The mechanism allows this
* routine to be called repeatedly.
*
******************************************************************************/
static acpi_status acpi_ns_load_table_by_type(acpi_table_type table_type)
{
u32 i;
acpi_status status;
struct acpi_table_desc *table_desc;
ACPI_FUNCTION_TRACE(ns_load_table_by_type);
status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/*
* Table types supported are:
* DSDT (one), SSDT/PSDT (multiple)
*/
switch (table_type) {
case ACPI_TABLE_ID_DSDT:
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace load: DSDT\n"));
table_desc = acpi_gbl_table_lists[ACPI_TABLE_ID_DSDT].next;
/* If table already loaded into namespace, just return */
if (table_desc->loaded_into_namespace) {
goto unlock_and_exit;
}
/* Now load the single DSDT */
status = acpi_ns_load_table(table_desc, acpi_gbl_root_node);
if (ACPI_SUCCESS(status)) {
table_desc->loaded_into_namespace = TRUE;
}
break;
case ACPI_TABLE_ID_SSDT:
case ACPI_TABLE_ID_PSDT:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Namespace load: %d SSDT or PSDTs\n",
acpi_gbl_table_lists[table_type].count));
/*
* Traverse list of SSDT or PSDT tables
*/
table_desc = acpi_gbl_table_lists[table_type].next;
for (i = 0; i < acpi_gbl_table_lists[table_type].count; i++) {
/*
* Only attempt to load table into namespace if it is not
* already loaded!
*/
if (!table_desc->loaded_into_namespace) {
status =
acpi_ns_load_table(table_desc,
acpi_gbl_root_node);
if (ACPI_FAILURE(status)) {
break;
}
table_desc->loaded_into_namespace = TRUE;
}
table_desc = table_desc->next;
}
break;
default:
status = AE_SUPPORT;
break;
}
unlock_and_exit:
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
return_ACPI_STATUS(status);
}
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_load_namespace * FUNCTION: acpi_load_namespace
...@@ -288,6 +185,7 @@ acpi_status acpi_ns_load_namespace(void) ...@@ -288,6 +185,7 @@ acpi_status acpi_ns_load_namespace(void)
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
#endif
#ifdef ACPI_FUTURE_IMPLEMENTATION #ifdef ACPI_FUTURE_IMPLEMENTATION
/******************************************************************************* /*******************************************************************************
......
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
#include <acpi/acnamesp.h> #include <acpi/acnamesp.h>
#include <acpi/acparser.h> #include <acpi/acparser.h>
#include <acpi/acdispat.h> #include <acpi/acdispat.h>
#include <acpi/actables.h>
#define _COMPONENT ACPI_NAMESPACE #define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nsparse") ACPI_MODULE_NAME("nsparse")
...@@ -62,14 +63,24 @@ ACPI_MODULE_NAME("nsparse") ...@@ -62,14 +63,24 @@ ACPI_MODULE_NAME("nsparse")
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_status
acpi_ns_one_complete_parse(u8 pass_number, struct acpi_table_desc *table_desc) acpi_ns_one_complete_parse(acpi_native_uint pass_number,
acpi_native_uint table_index)
{ {
union acpi_parse_object *parse_root; union acpi_parse_object *parse_root;
acpi_status status; acpi_status status;
acpi_native_uint aml_length;
u8 *aml_start;
struct acpi_walk_state *walk_state; struct acpi_walk_state *walk_state;
struct acpi_table_header *table;
acpi_owner_id owner_id;
ACPI_FUNCTION_TRACE(ns_one_complete_parse); ACPI_FUNCTION_TRACE(ns_one_complete_parse);
status = acpi_tb_get_owner_id(table_index, &owner_id);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Create and init a Root Node */ /* Create and init a Root Node */
parse_root = acpi_ps_create_scope_op(); parse_root = acpi_ps_create_scope_op();
...@@ -79,19 +90,34 @@ acpi_ns_one_complete_parse(u8 pass_number, struct acpi_table_desc *table_desc) ...@@ -79,19 +90,34 @@ acpi_ns_one_complete_parse(u8 pass_number, struct acpi_table_desc *table_desc)
/* Create and initialize a new walk state */ /* Create and initialize a new walk state */
walk_state = acpi_ds_create_walk_state(table_desc->owner_id, walk_state = acpi_ds_create_walk_state(owner_id, NULL, NULL, NULL);
NULL, NULL, NULL);
if (!walk_state) { if (!walk_state) {
acpi_ps_free_op(parse_root); acpi_ps_free_op(parse_root);
return_ACPI_STATUS(AE_NO_MEMORY); return_ACPI_STATUS(AE_NO_MEMORY);
} }
status = acpi_get_table_by_index(table_index, &table);
if (ACPI_FAILURE(status)) {
acpi_ds_delete_walk_state(walk_state);
acpi_ps_free_op(parse_root);
return_ACPI_STATUS(status);
}
/* Table must consist of at least a complete header */
if (table->length < sizeof(struct acpi_table_header)) {
status = AE_BAD_HEADER;
} else {
aml_start = (u8 *) table + sizeof(struct acpi_table_header);
aml_length = table->length - sizeof(struct acpi_table_header);
status = acpi_ds_init_aml_walk(walk_state, parse_root, NULL, status = acpi_ds_init_aml_walk(walk_state, parse_root, NULL,
table_desc->aml_start, aml_start, aml_length, NULL,
table_desc->aml_length, NULL, (u8) pass_number);
pass_number); }
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
acpi_ds_delete_walk_state(walk_state); acpi_ds_delete_walk_state(walk_state);
acpi_ps_delete_parse_tree(parse_root);
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
...@@ -119,7 +145,7 @@ acpi_ns_one_complete_parse(u8 pass_number, struct acpi_table_desc *table_desc) ...@@ -119,7 +145,7 @@ acpi_ns_one_complete_parse(u8 pass_number, struct acpi_table_desc *table_desc)
******************************************************************************/ ******************************************************************************/
acpi_status acpi_status
acpi_ns_parse_table(struct acpi_table_desc *table_desc, acpi_ns_parse_table(acpi_native_uint table_index,
struct acpi_namespace_node *start_node) struct acpi_namespace_node *start_node)
{ {
acpi_status status; acpi_status status;
...@@ -137,7 +163,7 @@ acpi_ns_parse_table(struct acpi_table_desc *table_desc, ...@@ -137,7 +163,7 @@ acpi_ns_parse_table(struct acpi_table_desc *table_desc,
* performs another complete parse of the AML.. * performs another complete parse of the AML..
*/ */
ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 1\n")); ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 1\n"));
status = acpi_ns_one_complete_parse(1, table_desc); status = acpi_ns_one_complete_parse(1, table_index);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
...@@ -152,7 +178,7 @@ acpi_ns_parse_table(struct acpi_table_desc *table_desc, ...@@ -152,7 +178,7 @@ acpi_ns_parse_table(struct acpi_table_desc *table_desc,
* parse objects are all cached. * parse objects are all cached.
*/ */
ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 2\n")); ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 2\n"));
status = acpi_ns_one_complete_parse(2, table_desc); status = acpi_ns_one_complete_parse(2, table_index);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
......
...@@ -770,13 +770,6 @@ void acpi_ns_terminate(void) ...@@ -770,13 +770,6 @@ void acpi_ns_terminate(void)
} }
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n")); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n"));
/*
* 2) Now we can delete the ACPI tables
*/
acpi_tb_delete_all_tables();
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n"));
return_VOID; return_VOID;
} }
......
/******************************************************************************
*
* Module Name: tbconvrt - ACPI Table conversion utilities
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include <acpi/actables.h>
#define _COMPONENT ACPI_TABLES
ACPI_MODULE_NAME("tbconvrt")
/* Local prototypes */
static void
acpi_tb_init_generic_address(struct acpi_generic_address *new_gas_struct,
u8 register_bit_width,
acpi_physical_address address);
static void
acpi_tb_convert_fadt1(struct fadt_descriptor *local_fadt,
struct fadt_descriptor_rev1 *original_fadt);
static void
acpi_tb_convert_fadt2(struct fadt_descriptor *local_fadt,
struct fadt_descriptor *original_fadt);
u8 acpi_fadt_is_v1;
ACPI_EXPORT_SYMBOL(acpi_fadt_is_v1)
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_table_count
*
* PARAMETERS: RSDP - Pointer to the RSDP
* RSDT - Pointer to the RSDT/XSDT
*
* RETURN: The number of tables pointed to by the RSDT or XSDT.
*
* DESCRIPTION: Calculate the number of tables. Automatically handles either
* an RSDT or XSDT.
*
******************************************************************************/
u32
acpi_tb_get_table_count(struct rsdp_descriptor *RSDP,
struct acpi_table_header *RSDT)
{
u32 pointer_size;
ACPI_FUNCTION_ENTRY();
/* RSDT pointers are 32 bits, XSDT pointers are 64 bits */
if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
pointer_size = sizeof(u32);
} else {
pointer_size = sizeof(u64);
}
/*
* Determine the number of tables pointed to by the RSDT/XSDT.
* This is defined by the ACPI Specification to be the number of
* pointers contained within the RSDT/XSDT. The size of the pointers
* is architecture-dependent.
*/
return ((RSDT->length -
sizeof(struct acpi_table_header)) / pointer_size);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_convert_to_xsdt
*
* PARAMETERS: table_info - Info about the RSDT
*
* RETURN: Status
*
* DESCRIPTION: Convert an RSDT to an XSDT (internal common format)
*
******************************************************************************/
acpi_status acpi_tb_convert_to_xsdt(struct acpi_table_desc *table_info)
{
acpi_size table_size;
u32 i;
struct xsdt_descriptor *new_table;
ACPI_FUNCTION_ENTRY();
/* Compute size of the converted XSDT */
table_size = ((acpi_size) acpi_gbl_rsdt_table_count * sizeof(u64)) +
sizeof(struct acpi_table_header);
/* Allocate an XSDT */
new_table = ACPI_ALLOCATE_ZEROED(table_size);
if (!new_table) {
return (AE_NO_MEMORY);
}
/* Copy the header and set the length */
ACPI_MEMCPY(new_table, table_info->pointer,
sizeof(struct acpi_table_header));
new_table->length = (u32) table_size;
/* Copy the table pointers */
for (i = 0; i < acpi_gbl_rsdt_table_count; i++) {
/* RSDT pointers are 32 bits, XSDT pointers are 64 bits */
if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
ACPI_STORE_ADDRESS(new_table->table_offset_entry[i],
(ACPI_CAST_PTR
(struct rsdt_descriptor,
table_info->pointer))->
table_offset_entry[i]);
} else {
new_table->table_offset_entry[i] =
(ACPI_CAST_PTR(struct xsdt_descriptor,
table_info->pointer))->
table_offset_entry[i];
}
}
/* Delete the original table (either mapped or in a buffer) */
acpi_tb_delete_single_table(table_info);
/* Point the table descriptor to the new table */
table_info->pointer =
ACPI_CAST_PTR(struct acpi_table_header, new_table);
table_info->length = table_size;
table_info->allocation = ACPI_MEM_ALLOCATED;
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_init_generic_address
*
* PARAMETERS: new_gas_struct - GAS struct to be initialized
* register_bit_width - Width of this register
* Address - Address of the register
*
* RETURN: None
*
* DESCRIPTION: Initialize a GAS structure.
*
******************************************************************************/
static void
acpi_tb_init_generic_address(struct acpi_generic_address *new_gas_struct,
u8 register_bit_width,
acpi_physical_address address)
{
ACPI_STORE_ADDRESS(new_gas_struct->address, address);
new_gas_struct->address_space_id = ACPI_ADR_SPACE_SYSTEM_IO;
new_gas_struct->register_bit_width = register_bit_width;
new_gas_struct->register_bit_offset = 0;
new_gas_struct->access_width = 0;
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_convert_fadt1
*
* PARAMETERS: local_fadt - Pointer to new FADT
* original_fadt - Pointer to old FADT
*
* RETURN: None, populates local_fadt
*
* DESCRIPTION: Convert an ACPI 1.0 FADT to common internal format
*
******************************************************************************/
static void
acpi_tb_convert_fadt1(struct fadt_descriptor *local_fadt,
struct fadt_descriptor_rev1 *original_fadt)
{
/* ACPI 1.0 FACS */
/* The BIOS stored FADT should agree with Revision 1.0 */
acpi_fadt_is_v1 = 1;
/*
* Copy the table header and the common part of the tables.
*
* The 2.0 table is an extension of the 1.0 table, so the entire 1.0
* table can be copied first, then expand some fields to 64 bits.
*/
ACPI_MEMCPY(local_fadt, original_fadt,
sizeof(struct fadt_descriptor_rev1));
/* Convert table pointers to 64-bit fields */
ACPI_STORE_ADDRESS(local_fadt->xfirmware_ctrl,
local_fadt->V1_firmware_ctrl);
ACPI_STORE_ADDRESS(local_fadt->Xdsdt, local_fadt->V1_dsdt);
/*
* System Interrupt Model isn't used in ACPI 2.0
* (local_fadt->Reserved1 = 0;)
*/
/*
* This field is set by the OEM to convey the preferred power management
* profile to OSPM. It doesn't have any 1.0 equivalence. Since we don't
* know what kind of 32-bit system this is, we will use "unspecified".
*/
local_fadt->prefer_PM_profile = PM_UNSPECIFIED;
/*
* Processor Performance State Control. This is the value OSPM writes to
* the SMI_CMD register to assume processor performance state control
* responsibility. There isn't any equivalence in 1.0, but as many 1.x
* ACPI tables contain _PCT and _PSS we also keep this value, unless
* acpi_strict is set.
*/
if (acpi_strict)
local_fadt->pstate_cnt = 0;
/*
* Support for the _CST object and C States change notification.
* This data item hasn't any 1.0 equivalence so leave it zero.
*/
local_fadt->cst_cnt = 0;
/*
* FADT Rev 2 was an interim FADT released between ACPI 1.0 and ACPI 2.0.
* It primarily adds the FADT reset mechanism.
*/
if ((original_fadt->revision == 2) &&
(original_fadt->length ==
sizeof(struct fadt_descriptor_rev2_minus))) {
/*
* Grab the entire generic address struct, plus the 1-byte reset value
* that immediately follows.
*/
ACPI_MEMCPY(&local_fadt->reset_register,
&(ACPI_CAST_PTR(struct fadt_descriptor_rev2_minus,
original_fadt))->reset_register,
sizeof(struct acpi_generic_address) + 1);
} else {
/*
* Since there isn't any equivalence in 1.0 and since it is highly
* likely that a 1.0 system has legacy support.
*/
local_fadt->iapc_boot_arch = BAF_LEGACY_DEVICES;
}
/*
* Convert the V1.0 block addresses to V2.0 GAS structures
*/
acpi_tb_init_generic_address(&local_fadt->xpm1a_evt_blk,
local_fadt->pm1_evt_len,
(acpi_physical_address) local_fadt->
V1_pm1a_evt_blk);
acpi_tb_init_generic_address(&local_fadt->xpm1b_evt_blk,
local_fadt->pm1_evt_len,
(acpi_physical_address) local_fadt->
V1_pm1b_evt_blk);
acpi_tb_init_generic_address(&local_fadt->xpm1a_cnt_blk,
local_fadt->pm1_cnt_len,
(acpi_physical_address) local_fadt->
V1_pm1a_cnt_blk);
acpi_tb_init_generic_address(&local_fadt->xpm1b_cnt_blk,
local_fadt->pm1_cnt_len,
(acpi_physical_address) local_fadt->
V1_pm1b_cnt_blk);
acpi_tb_init_generic_address(&local_fadt->xpm2_cnt_blk,
local_fadt->pm2_cnt_len,
(acpi_physical_address) local_fadt->
V1_pm2_cnt_blk);
acpi_tb_init_generic_address(&local_fadt->xpm_tmr_blk,
local_fadt->pm_tm_len,
(acpi_physical_address) local_fadt->
V1_pm_tmr_blk);
acpi_tb_init_generic_address(&local_fadt->xgpe0_blk, 0,
(acpi_physical_address) local_fadt->
V1_gpe0_blk);
acpi_tb_init_generic_address(&local_fadt->xgpe1_blk, 0,
(acpi_physical_address) local_fadt->
V1_gpe1_blk);
/* Create separate GAS structs for the PM1 Enable registers */
acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable,
(u8) ACPI_DIV_2(acpi_gbl_FADT->
pm1_evt_len),
(acpi_physical_address)
(local_fadt->xpm1a_evt_blk.address +
ACPI_DIV_2(acpi_gbl_FADT->pm1_evt_len)));
/* PM1B is optional; leave null if not present */
if (local_fadt->xpm1b_evt_blk.address) {
acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable,
(u8) ACPI_DIV_2(acpi_gbl_FADT->
pm1_evt_len),
(acpi_physical_address)
(local_fadt->xpm1b_evt_blk.
address +
ACPI_DIV_2(acpi_gbl_FADT->
pm1_evt_len)));
}
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_convert_fadt2
*
* PARAMETERS: local_fadt - Pointer to new FADT
* original_fadt - Pointer to old FADT
*
* RETURN: None, populates local_fadt
*
* DESCRIPTION: Convert an ACPI 2.0 FADT to common internal format.
* Handles optional "X" fields.
*
******************************************************************************/
static void
acpi_tb_convert_fadt2(struct fadt_descriptor *local_fadt,
struct fadt_descriptor *original_fadt)
{
/* We have an ACPI 2.0 FADT but we must copy it to our local buffer */
ACPI_MEMCPY(local_fadt, original_fadt, sizeof(struct fadt_descriptor));
/*
* "X" fields are optional extensions to the original V1.0 fields, so
* we must selectively expand V1.0 fields if the corresponding X field
* is zero.
*/
if (!(local_fadt->xfirmware_ctrl)) {
ACPI_STORE_ADDRESS(local_fadt->xfirmware_ctrl,
local_fadt->V1_firmware_ctrl);
}
if (!(local_fadt->Xdsdt)) {
ACPI_STORE_ADDRESS(local_fadt->Xdsdt, local_fadt->V1_dsdt);
}
if (!(local_fadt->xpm1a_evt_blk.address)) {
acpi_tb_init_generic_address(&local_fadt->xpm1a_evt_blk,
local_fadt->pm1_evt_len,
(acpi_physical_address)
local_fadt->V1_pm1a_evt_blk);
}
if (!(local_fadt->xpm1b_evt_blk.address)) {
acpi_tb_init_generic_address(&local_fadt->xpm1b_evt_blk,
local_fadt->pm1_evt_len,
(acpi_physical_address)
local_fadt->V1_pm1b_evt_blk);
}
if (!(local_fadt->xpm1a_cnt_blk.address)) {
acpi_tb_init_generic_address(&local_fadt->xpm1a_cnt_blk,
local_fadt->pm1_cnt_len,
(acpi_physical_address)
local_fadt->V1_pm1a_cnt_blk);
}
if (!(local_fadt->xpm1b_cnt_blk.address)) {
acpi_tb_init_generic_address(&local_fadt->xpm1b_cnt_blk,
local_fadt->pm1_cnt_len,
(acpi_physical_address)
local_fadt->V1_pm1b_cnt_blk);
}
if (!(local_fadt->xpm2_cnt_blk.address)) {
acpi_tb_init_generic_address(&local_fadt->xpm2_cnt_blk,
local_fadt->pm2_cnt_len,
(acpi_physical_address)
local_fadt->V1_pm2_cnt_blk);
}
if (!(local_fadt->xpm_tmr_blk.address)) {
acpi_tb_init_generic_address(&local_fadt->xpm_tmr_blk,
local_fadt->pm_tm_len,
(acpi_physical_address)
local_fadt->V1_pm_tmr_blk);
}
if (!(local_fadt->xgpe0_blk.address)) {
acpi_tb_init_generic_address(&local_fadt->xgpe0_blk,
0,
(acpi_physical_address)
local_fadt->V1_gpe0_blk);
}
if (!(local_fadt->xgpe1_blk.address)) {
acpi_tb_init_generic_address(&local_fadt->xgpe1_blk,
0,
(acpi_physical_address)
local_fadt->V1_gpe1_blk);
}
/* Create separate GAS structs for the PM1 Enable registers */
acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable,
(u8) ACPI_DIV_2(acpi_gbl_FADT->
pm1_evt_len),
(acpi_physical_address)
(local_fadt->xpm1a_evt_blk.address +
ACPI_DIV_2(acpi_gbl_FADT->pm1_evt_len)));
acpi_gbl_xpm1a_enable.address_space_id =
local_fadt->xpm1a_evt_blk.address_space_id;
/* PM1B is optional; leave null if not present */
if (local_fadt->xpm1b_evt_blk.address) {
acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable,
(u8) ACPI_DIV_2(acpi_gbl_FADT->
pm1_evt_len),
(acpi_physical_address)
(local_fadt->xpm1b_evt_blk.
address +
ACPI_DIV_2(acpi_gbl_FADT->
pm1_evt_len)));
acpi_gbl_xpm1b_enable.address_space_id =
local_fadt->xpm1b_evt_blk.address_space_id;
}
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_convert_table_fadt
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Converts a BIOS supplied ACPI 1.0 FADT to a local
* ACPI 2.0 FADT. If the BIOS supplied a 2.0 FADT then it is simply
* copied to the local FADT. The ACPI CA software uses this
* local FADT. Thus a significant amount of special #ifdef
* type codeing is saved.
*
******************************************************************************/
acpi_status acpi_tb_convert_table_fadt(void)
{
struct fadt_descriptor *local_fadt;
struct acpi_table_desc *table_desc;
ACPI_FUNCTION_TRACE(tb_convert_table_fadt);
/*
* acpi_gbl_FADT is valid. Validate the FADT length. The table must be
* at least as long as the version 1.0 FADT
*/
if (acpi_gbl_FADT->length < sizeof(struct fadt_descriptor_rev1)) {
ACPI_ERROR((AE_INFO, "FADT is invalid, too short: 0x%X",
acpi_gbl_FADT->length));
return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
}
/* Allocate buffer for the ACPI 2.0(+) FADT */
local_fadt = ACPI_ALLOCATE_ZEROED(sizeof(struct fadt_descriptor));
if (!local_fadt) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
if (acpi_gbl_FADT->revision >= FADT2_REVISION_ID) {
if (acpi_gbl_FADT->length < sizeof(struct fadt_descriptor)) {
/* Length is too short to be a V2.0 table */
ACPI_WARNING((AE_INFO,
"Inconsistent FADT length (0x%X) and revision (0x%X), using FADT V1.0 portion of table",
acpi_gbl_FADT->length,
acpi_gbl_FADT->revision));
acpi_tb_convert_fadt1(local_fadt,
(void *)acpi_gbl_FADT);
} else {
/* Valid V2.0 table */
acpi_tb_convert_fadt2(local_fadt, acpi_gbl_FADT);
}
} else {
/* Valid V1.0 table */
acpi_tb_convert_fadt1(local_fadt, (void *)acpi_gbl_FADT);
}
/* Global FADT pointer will point to the new common V2.0 FADT */
acpi_gbl_FADT = local_fadt;
acpi_gbl_FADT->length = sizeof(struct fadt_descriptor);
/* Free the original table */
table_desc = acpi_gbl_table_lists[ACPI_TABLE_ID_FADT].next;
acpi_tb_delete_single_table(table_desc);
/* Install the new table */
table_desc->pointer =
ACPI_CAST_PTR(struct acpi_table_header, acpi_gbl_FADT);
table_desc->allocation = ACPI_MEM_ALLOCATED;
table_desc->length = sizeof(struct fadt_descriptor);
/* Dump the entire FADT */
ACPI_DEBUG_PRINT((ACPI_DB_TABLES,
"Hex dump of common internal FADT, size %d (%X)\n",
acpi_gbl_FADT->length, acpi_gbl_FADT->length));
ACPI_DUMP_BUFFER(ACPI_CAST_PTR(u8, acpi_gbl_FADT),
acpi_gbl_FADT->length);
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_build_common_facs
*
* PARAMETERS: table_info - Info for currently installed FACS
*
* RETURN: Status
*
* DESCRIPTION: Convert ACPI 1.0 and ACPI 2.0 FACS to a common internal
* table format.
*
******************************************************************************/
acpi_status acpi_tb_build_common_facs(struct acpi_table_desc *table_info)
{
ACPI_FUNCTION_TRACE(tb_build_common_facs);
/* Absolute minimum length is 24, but the ACPI spec says 64 */
if (acpi_gbl_FACS->length < 24) {
ACPI_ERROR((AE_INFO, "Invalid FACS table length: 0x%X",
acpi_gbl_FACS->length));
return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
}
if (acpi_gbl_FACS->length < 64) {
ACPI_WARNING((AE_INFO,
"FACS is shorter than the ACPI specification allows: 0x%X, using anyway",
acpi_gbl_FACS->length));
}
/* Copy fields to the new FACS */
acpi_gbl_common_fACS.global_lock = &(acpi_gbl_FACS->global_lock);
if ((acpi_gbl_RSDP->revision < 2) ||
(acpi_gbl_FACS->length < 32) ||
(!(acpi_gbl_FACS->xfirmware_waking_vector))) {
/* ACPI 1.0 FACS or short table or optional X_ field is zero */
acpi_gbl_common_fACS.firmware_waking_vector = ACPI_CAST_PTR(u64,
&
(acpi_gbl_FACS->
firmware_waking_vector));
acpi_gbl_common_fACS.vector_width = 32;
} else {
/* ACPI 2.0 FACS with valid X_ field */
acpi_gbl_common_fACS.firmware_waking_vector =
&acpi_gbl_FACS->xfirmware_waking_vector;
acpi_gbl_common_fACS.vector_width = 64;
}
return_ACPI_STATUS(AE_OK);
}
/******************************************************************************
*
* Module Name: tbfind - find table
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include <acpi/actables.h>
#define _COMPONENT ACPI_TABLES
ACPI_MODULE_NAME("tbfind")
/*******************************************************************************
*
* FUNCTION: acpi_tb_find_table
*
* PARAMETERS: Signature - String with ACPI table signature
* oem_id - String with the table OEM ID
* oem_table_id - String with the OEM Table ID
* table_index - Where the table index is returned
*
* RETURN: Status and table index
*
* DESCRIPTION: Find an ACPI table (in the RSDT/XSDT) that matches the
* Signature, OEM ID and OEM Table ID. Returns an index that can
* be used to get the table header or entire table.
*
******************************************************************************/
acpi_status
acpi_tb_find_table(char *signature,
char *oem_id,
char *oem_table_id, acpi_native_uint * table_index)
{
acpi_native_uint i;
acpi_status status;
ACPI_FUNCTION_TRACE(tb_find_table);
for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
if (ACPI_MEMCMP(&(acpi_gbl_root_table_list.tables[i].signature),
signature, ACPI_NAME_SIZE)) {
/* Not the requested table */
continue;
}
/* Table with matching signature has been found */
if (!acpi_gbl_root_table_list.tables[i].pointer) {
/* Table is not currently mapped, map it */
status =
acpi_tb_verify_table(&acpi_gbl_root_table_list.
tables[i]);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
if (!acpi_gbl_root_table_list.tables[i].pointer) {
continue;
}
}
/* Check for table match on all IDs */
if (!ACPI_MEMCMP
(acpi_gbl_root_table_list.tables[i].pointer->signature,
signature, ACPI_NAME_SIZE) && (!oem_id[0]
||
!ACPI_MEMCMP
(acpi_gbl_root_table_list.
tables[i].pointer->oem_id,
oem_id, ACPI_OEM_ID_SIZE))
&& (!oem_table_id[0]
|| !ACPI_MEMCMP(acpi_gbl_root_table_list.tables[i].
pointer->oem_table_id, oem_table_id,
ACPI_OEM_TABLE_ID_SIZE))) {
*table_index = i;
ACPI_DEBUG_PRINT((ACPI_DB_TABLES,
"Found table [%4.4s]\n", signature));
return_ACPI_STATUS(AE_OK);
}
}
return_ACPI_STATUS(AE_NOT_FOUND);
}
/******************************************************************************
*
* Module Name: tbget - ACPI Table get* routines
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include <acpi/actables.h>
#define _COMPONENT ACPI_TABLES
ACPI_MODULE_NAME("tbget")
/* Local prototypes */
static acpi_status
acpi_tb_get_this_table(struct acpi_pointer *address,
struct acpi_table_header *header,
struct acpi_table_desc *table_info);
static acpi_status
acpi_tb_table_override(struct acpi_table_header *header,
struct acpi_table_desc *table_info);
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_table
*
* PARAMETERS: Address - Address of table to retrieve. Can be
* Logical or Physical
* table_info - Where table info is returned
*
* RETURN: None
*
* DESCRIPTION: Get entire table of unknown size.
*
******************************************************************************/
acpi_status
acpi_tb_get_table(struct acpi_pointer *address,
struct acpi_table_desc *table_info)
{
acpi_status status;
struct acpi_table_header header;
ACPI_FUNCTION_TRACE(tb_get_table);
/* Get the header in order to get signature and table size */
status = acpi_tb_get_table_header(address, &header);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Get the entire table */
status = acpi_tb_get_table_body(address, &header, table_info);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Could not get ACPI table (size %X)",
header.length));
return_ACPI_STATUS(status);
}
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_table_header
*
* PARAMETERS: Address - Address of table to retrieve. Can be
* Logical or Physical
* return_header - Where the table header is returned
*
* RETURN: Status
*
* DESCRIPTION: Get an ACPI table header. Works in both physical or virtual
* addressing mode. Works with both physical or logical pointers.
* Table is either copied or mapped, depending on the pointer
* type and mode of the processor.
*
******************************************************************************/
acpi_status
acpi_tb_get_table_header(struct acpi_pointer *address,
struct acpi_table_header *return_header)
{
acpi_status status = AE_OK;
struct acpi_table_header *header = NULL;
ACPI_FUNCTION_TRACE(tb_get_table_header);
/*
* Flags contains the current processor mode (Virtual or Physical
* addressing) The pointer_type is either Logical or Physical
*/
switch (address->pointer_type) {
case ACPI_PHYSMODE_PHYSPTR:
case ACPI_LOGMODE_LOGPTR:
/* Pointer matches processor mode, copy the header */
ACPI_MEMCPY(return_header, address->pointer.logical,
sizeof(struct acpi_table_header));
break;
case ACPI_LOGMODE_PHYSPTR:
/* Create a logical address for the physical pointer */
status = acpi_os_map_memory(address->pointer.physical,
sizeof(struct acpi_table_header),
(void *)&header);
if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO,
"Could not map memory at %8.8X%8.8X for table header",
ACPI_FORMAT_UINT64(address->pointer.
physical)));
return_ACPI_STATUS(status);
}
/* Copy header and delete mapping */
ACPI_MEMCPY(return_header, header,
sizeof(struct acpi_table_header));
acpi_os_unmap_memory(header, sizeof(struct acpi_table_header));
break;
default:
ACPI_ERROR((AE_INFO, "Invalid address flags %X",
address->pointer_type));
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
ACPI_DEBUG_PRINT((ACPI_DB_TABLES, "Table Signature: [%4.4s]\n",
return_header->signature));
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_table_body
*
* PARAMETERS: Address - Address of table to retrieve. Can be
* Logical or Physical
* Header - Header of the table to retrieve
* table_info - Where the table info is returned
*
* RETURN: Status
*
* DESCRIPTION: Get an entire ACPI table with support to allow the host OS to
* replace the table with a newer version (table override.)
* Works in both physical or virtual
* addressing mode. Works with both physical or logical pointers.
* Table is either copied or mapped, depending on the pointer
* type and mode of the processor.
*
******************************************************************************/
acpi_status
acpi_tb_get_table_body(struct acpi_pointer *address,
struct acpi_table_header *header,
struct acpi_table_desc *table_info)
{
acpi_status status;
ACPI_FUNCTION_TRACE(tb_get_table_body);
if (!table_info || !address) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Attempt table override. */
status = acpi_tb_table_override(header, table_info);
if (ACPI_SUCCESS(status)) {
/* Table was overridden by the host OS */
return_ACPI_STATUS(status);
}
/* No override, get the original table */
status = acpi_tb_get_this_table(address, header, table_info);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_table_override
*
* PARAMETERS: Header - Pointer to table header
* table_info - Return info if table is overridden
*
* RETURN: None
*
* DESCRIPTION: Attempts override of current table with a new one if provided
* by the host OS.
*
******************************************************************************/
static acpi_status
acpi_tb_table_override(struct acpi_table_header *header,
struct acpi_table_desc *table_info)
{
struct acpi_table_header *new_table;
acpi_status status;
struct acpi_pointer address;
ACPI_FUNCTION_TRACE(tb_table_override);
/*
* The OSL will examine the header and decide whether to override this
* table. If it decides to override, a table will be returned in new_table,
* which we will then copy.
*/
status = acpi_os_table_override(header, &new_table);
if (ACPI_FAILURE(status)) {
/* Some severe error from the OSL, but we basically ignore it */
ACPI_EXCEPTION((AE_INFO, status,
"Could not override ACPI table"));
return_ACPI_STATUS(status);
}
if (!new_table) {
/* No table override */
return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
/*
* We have a new table to override the old one. Get a copy of
* the new one. We know that the new table has a logical pointer.
*/
address.pointer_type = ACPI_LOGICAL_POINTER | ACPI_LOGICAL_ADDRESSING;
address.pointer.logical = new_table;
status = acpi_tb_get_this_table(&address, new_table, table_info);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status, "Could not copy ACPI table"));
return_ACPI_STATUS(status);
}
/* Copy the table info */
ACPI_INFO((AE_INFO, "Table [%4.4s] replaced by host OS",
table_info->pointer->signature));
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_this_table
*
* PARAMETERS: Address - Address of table to retrieve. Can be
* Logical or Physical
* Header - Header of the table to retrieve
* table_info - Where the table info is returned
*
* RETURN: Status
*
* DESCRIPTION: Get an entire ACPI table. Works in both physical or virtual
* addressing mode. Works with both physical or logical pointers.
* Table is either copied or mapped, depending on the pointer
* type and mode of the processor.
*
******************************************************************************/
static acpi_status
acpi_tb_get_this_table(struct acpi_pointer *address,
struct acpi_table_header *header,
struct acpi_table_desc *table_info)
{
struct acpi_table_header *full_table = NULL;
u8 allocation;
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE(tb_get_this_table);
/* Validate minimum length */
if (header->length < sizeof(struct acpi_table_header)) {
ACPI_ERROR((AE_INFO,
"Table length (%X) is smaller than minimum (%zX)",
header->length, sizeof(struct acpi_table_header)));
return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
}
/*
* Flags contains the current processor mode (Virtual or Physical
* addressing) The pointer_type is either Logical or Physical
*/
switch (address->pointer_type) {
case ACPI_PHYSMODE_PHYSPTR:
case ACPI_LOGMODE_LOGPTR:
/* Pointer matches processor mode, copy the table to a new buffer */
full_table = ACPI_ALLOCATE(header->length);
if (!full_table) {
ACPI_ERROR((AE_INFO,
"Could not allocate table memory for [%4.4s] length %X",
header->signature, header->length));
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Copy the entire table (including header) to the local buffer */
ACPI_MEMCPY(full_table, address->pointer.logical,
header->length);
/* Save allocation type */
allocation = ACPI_MEM_ALLOCATED;
break;
case ACPI_LOGMODE_PHYSPTR:
/*
* Just map the table's physical memory
* into our address space.
*/
status = acpi_os_map_memory(address->pointer.physical,
(acpi_size) header->length,
ACPI_CAST_PTR(void, &full_table));
if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO,
"Could not map memory for table [%4.4s] at %8.8X%8.8X for length %X",
header->signature,
ACPI_FORMAT_UINT64(address->pointer.
physical),
header->length));
return (status);
}
/* Save allocation type */
allocation = ACPI_MEM_MAPPED;
break;
default:
ACPI_ERROR((AE_INFO, "Invalid address flags %X",
address->pointer_type));
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* Validate checksum for _most_ tables,
* even the ones whose signature we don't recognize
*/
if (table_info->type != ACPI_TABLE_ID_FACS) {
status = acpi_tb_verify_table_checksum(full_table);
#if (!ACPI_CHECKSUM_ABORT)
if (ACPI_FAILURE(status)) {
/* Ignore the error if configuration says so */
status = AE_OK;
}
#endif
}
/* Return values */
table_info->pointer = full_table;
table_info->length = (acpi_size) header->length;
table_info->allocation = allocation;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Found table [%4.4s] at %8.8X%8.8X, mapped/copied to %p\n",
full_table->signature,
ACPI_FORMAT_UINT64(address->pointer.physical),
full_table));
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_table_ptr
*
* PARAMETERS: table_type - one of the defined table types
* Instance - Which table of this type
* return_table - pointer to location to place the pointer for
* return
*
* RETURN: Status
*
* DESCRIPTION: This function is called to get the pointer to an ACPI table.
*
******************************************************************************/
acpi_status
acpi_tb_get_table_ptr(acpi_table_type table_type,
u32 instance, struct acpi_table_header **return_table)
{
struct acpi_table_desc *table_desc;
u32 i;
ACPI_FUNCTION_TRACE(tb_get_table_ptr);
if (table_type > ACPI_TABLE_ID_MAX) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Check for instance out of range of the current table count */
if (instance > acpi_gbl_table_lists[table_type].count) {
return_ACPI_STATUS(AE_NOT_EXIST);
}
/*
* Walk the list to get the desired table
* Note: Instance is one-based
*/
table_desc = acpi_gbl_table_lists[table_type].next;
for (i = 1; i < instance; i++) {
table_desc = table_desc->next;
}
/* We are now pointing to the requested table's descriptor */
*return_table = table_desc->pointer;
return_ACPI_STATUS(AE_OK);
}
/******************************************************************************
*
* Module Name: tbgetall - Get all required ACPI tables
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include <acpi/actables.h>
#define _COMPONENT ACPI_TABLES
ACPI_MODULE_NAME("tbgetall")
/* Local prototypes */
static acpi_status
acpi_tb_get_primary_table(struct acpi_pointer *address,
struct acpi_table_desc *table_info);
static acpi_status
acpi_tb_get_secondary_table(struct acpi_pointer *address,
acpi_string signature,
struct acpi_table_desc *table_info);
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_primary_table
*
* PARAMETERS: Address - Physical address of table to retrieve
* *table_info - Where the table info is returned
*
* RETURN: Status
*
* DESCRIPTION: Maps the physical address of table into a logical address
*
******************************************************************************/
static acpi_status
acpi_tb_get_primary_table(struct acpi_pointer *address,
struct acpi_table_desc *table_info)
{
acpi_status status;
struct acpi_table_header header;
ACPI_FUNCTION_TRACE(tb_get_primary_table);
/* Ignore a NULL address in the RSDT */
if (!address->pointer.value) {
return_ACPI_STATUS(AE_OK);
}
/* Get the header in order to get signature and table size */
status = acpi_tb_get_table_header(address, &header);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Clear the table_info */
ACPI_MEMSET(table_info, 0, sizeof(struct acpi_table_desc));
/*
* Check the table signature and make sure it is recognized.
* Also checks the header checksum
*/
table_info->pointer = &header;
status = acpi_tb_recognize_table(table_info, ACPI_TABLE_PRIMARY);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Get the entire table */
status = acpi_tb_get_table_body(address, &header, table_info);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Install the table */
status = acpi_tb_install_table(table_info);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_secondary_table
*
* PARAMETERS: Address - Physical address of table to retrieve
* *table_info - Where the table info is returned
*
* RETURN: Status
*
* DESCRIPTION: Maps the physical address of table into a logical address
*
******************************************************************************/
static acpi_status
acpi_tb_get_secondary_table(struct acpi_pointer *address,
acpi_string signature,
struct acpi_table_desc *table_info)
{
acpi_status status;
struct acpi_table_header header;
ACPI_FUNCTION_TRACE_STR(tb_get_secondary_table, signature);
/* Get the header in order to match the signature */
status = acpi_tb_get_table_header(address, &header);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Signature must match request */
if (!ACPI_COMPARE_NAME(header.signature, signature)) {
ACPI_ERROR((AE_INFO,
"Incorrect table signature - wanted [%s] found [%4.4s]",
signature, header.signature));
return_ACPI_STATUS(AE_BAD_SIGNATURE);
}
/*
* Check the table signature and make sure it is recognized.
* Also checks the header checksum
*/
table_info->pointer = &header;
status = acpi_tb_recognize_table(table_info, ACPI_TABLE_SECONDARY);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Get the entire table */
status = acpi_tb_get_table_body(address, &header, table_info);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Install the table */
status = acpi_tb_install_table(table_info);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_required_tables
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Load and validate tables other than the RSDT. The RSDT must
* already be loaded and validated.
*
* Get the minimum set of ACPI tables, namely:
*
* 1) FADT (via RSDT in loop below)
* 2) FACS (via FADT)
* 3) DSDT (via FADT)
*
******************************************************************************/
acpi_status acpi_tb_get_required_tables(void)
{
acpi_status status = AE_OK;
u32 i;
struct acpi_table_desc table_info;
struct acpi_pointer address;
ACPI_FUNCTION_TRACE(tb_get_required_tables);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%d ACPI tables in RSDT\n",
acpi_gbl_rsdt_table_count));
address.pointer_type = acpi_gbl_table_flags | ACPI_LOGICAL_ADDRESSING;
/*
* Loop through all table pointers found in RSDT.
* This will NOT include the FACS and DSDT - we must get
* them after the loop.
*
* The only tables we are interested in getting here is the FADT and
* any SSDTs.
*/
for (i = 0; i < acpi_gbl_rsdt_table_count; i++) {
/* Get the table address from the common internal XSDT */
address.pointer.value = acpi_gbl_XSDT->table_offset_entry[i];
/*
* Get the tables needed by this subsystem (FADT and any SSDTs).
* NOTE: All other tables are completely ignored at this time.
*/
status = acpi_tb_get_primary_table(&address, &table_info);
if ((status != AE_OK) && (status != AE_TABLE_NOT_SUPPORTED)) {
ACPI_WARNING((AE_INFO,
"%s, while getting table at %8.8X%8.8X",
acpi_format_exception(status),
ACPI_FORMAT_UINT64(address.pointer.
value)));
}
}
/* We must have a FADT to continue */
if (!acpi_gbl_FADT) {
ACPI_ERROR((AE_INFO, "No FADT present in RSDT/XSDT"));
return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
/*
* Convert the FADT to a common format. This allows earlier revisions of
* the table to coexist with newer versions, using common access code.
*/
status = acpi_tb_convert_table_fadt();
if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO,
"Could not convert FADT to internal common format"));
return_ACPI_STATUS(status);
}
/* Get the FACS (Pointed to by the FADT) */
address.pointer.value = acpi_gbl_FADT->xfirmware_ctrl;
status = acpi_tb_get_secondary_table(&address, FACS_SIG, &table_info);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Could not get/install the FACS"));
return_ACPI_STATUS(status);
}
/*
* Create the common FACS pointer table
* (Contains pointers to the original table)
*/
status = acpi_tb_build_common_facs(&table_info);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Get/install the DSDT (Pointed to by the FADT) */
address.pointer.value = acpi_gbl_FADT->Xdsdt;
status = acpi_tb_get_secondary_table(&address, DSDT_SIG, &table_info);
if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO, "Could not get/install the DSDT"));
return_ACPI_STATUS(status);
}
/* Set Integer Width (32/64) based upon DSDT revision */
acpi_ut_set_integer_width(acpi_gbl_DSDT->revision);
/* Dump the entire DSDT */
ACPI_DEBUG_PRINT((ACPI_DB_TABLES,
"Hex dump of entire DSDT, size %d (0x%X), Integer width = %d\n",
acpi_gbl_DSDT->length, acpi_gbl_DSDT->length,
acpi_gbl_integer_bit_width));
ACPI_DUMP_BUFFER(ACPI_CAST_PTR(u8, acpi_gbl_DSDT),
acpi_gbl_DSDT->length);
/* Always delete the RSDP mapping, we are done with it */
acpi_tb_delete_tables_by_type(ACPI_TABLE_ID_RSDP);
return_ACPI_STATUS(status);
}
...@@ -42,510 +42,494 @@ ...@@ -42,510 +42,494 @@
*/ */
#include <acpi/acpi.h> #include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/actables.h> #include <acpi/actables.h>
#define _COMPONENT ACPI_TABLES #define _COMPONENT ACPI_TABLES
ACPI_MODULE_NAME("tbinstal") ACPI_MODULE_NAME("tbinstal")
/* Local prototypes */ /******************************************************************************
static acpi_status
acpi_tb_match_signature(char *signature,
struct acpi_table_desc *table_info, u8 search_type);
/*******************************************************************************
* *
* FUNCTION: acpi_tb_match_signature * FUNCTION: acpi_tb_verify_table
* *
* PARAMETERS: Signature - Table signature to match * PARAMETERS: table_desc - table
* table_info - Return data
* search_type - Table type to match (primary/secondary)
* *
* RETURN: Status * RETURN: Status
* *
* DESCRIPTION: Compare signature against the list of "ACPI-subsystem-owned" * DESCRIPTION: this function is called to verify and map table
* tables (DSDT/FADT/SSDT, etc.) Returns the table_type_iD on match.
* *
******************************************************************************/ *****************************************************************************/
acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc)
static acpi_status
acpi_tb_match_signature(char *signature,
struct acpi_table_desc *table_info, u8 search_type)
{ {
acpi_native_uint i; u8 checksum;
ACPI_FUNCTION_TRACE(tb_match_signature); ACPI_FUNCTION_TRACE(tb_verify_table);
/* Search for a signature match among the known table types */ /* Map the table if necessary */
for (i = 0; i < (ACPI_TABLE_ID_MAX + 1); i++) { if (!table_desc->pointer) {
if (!(acpi_gbl_table_data[i].flags & search_type)) { table_desc->pointer =
continue; acpi_tb_map(table_desc->address, table_desc->length,
table_desc->flags & ACPI_TABLE_ORIGIN_MASK);
if (!table_desc->pointer) {
return_ACPI_STATUS(AE_NO_MEMORY);
} }
if (!ACPI_STRNCMP(signature, acpi_gbl_table_data[i].signature,
acpi_gbl_table_data[i].sig_length)) {
/* Found a signature match, return index if requested */
if (table_info) {
table_info->type = (u8) i;
} }
ACPI_DEBUG_PRINT((ACPI_DB_INFO, /* FACS is the odd table, has no standard ACPI header and no checksum */
"Table [%4.4s] is an ACPI table consumed by the core subsystem\n",
(char *)acpi_gbl_table_data[i].
signature));
if (ACPI_COMPARE_NAME(&(table_desc->signature), ACPI_SIG_FACS)) {
return_ACPI_STATUS(AE_OK); return_ACPI_STATUS(AE_OK);
} }
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, /* Always calculate checksum, ignore bad checksum if requested */
"Table [%4.4s] is not an ACPI table consumed by the core subsystem - ignored\n",
(char *)signature)); checksum = acpi_tb_checksum(ACPI_CAST_PTR(void, table_desc->pointer),
table_desc->length);
#if (ACPI_CHECKSUM_ABORT)
if (checksum) {
return_ACPI_STATUS(AE_BAD_CHECKSUM);
}
#endif
return_ACPI_STATUS(AE_TABLE_NOT_SUPPORTED); return_ACPI_STATUS(AE_OK);
} }
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_tb_install_table * FUNCTION: acpi_tb_add_table
* *
* PARAMETERS: table_info - Return value from acpi_tb_get_table_body * PARAMETERS: Table - Pointer to the table header
* table_index - Where the table index is returned
* *
* RETURN: Status * RETURN: Status
* *
* DESCRIPTION: Install the table into the global data structures. * DESCRIPTION: This function is called to add the ACPI table
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_tb_install_table(struct acpi_table_desc *table_info) acpi_status
acpi_tb_add_table(struct acpi_table_header *table,
acpi_native_uint * table_index)
{ {
acpi_status status; acpi_native_uint i;
acpi_native_uint length;
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE(tb_install_table); ACPI_FUNCTION_TRACE(tb_add_table);
/* Lock tables while installing */ (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); /* Check if table is already registered */
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status, for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
"Could not acquire table mutex")); if (!acpi_gbl_root_table_list.tables[i].pointer) {
return_ACPI_STATUS(status); 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;
}
} }
/* length = ACPI_MIN(table->length,
* Ignore a table that is already installed. For example, some BIOS acpi_gbl_root_table_list.tables[i].pointer->
* ASL code will repeatedly attempt to load the same SSDT. length);
*/ if (ACPI_MEMCMP
status = acpi_tb_is_table_installed(table_info); (table, acpi_gbl_root_table_list.tables[i].pointer,
if (ACPI_FAILURE(status)) { length)) {
goto unlock_and_exit; continue;
} }
/* Install the table into the global data structure */ /* Table is already registered */
ACPI_FREE(table);
*table_index = i;
goto release;
}
status = acpi_tb_init_table_descriptor(table_info->type, table_info); /*
* Add the table to the global table list
*/
status = acpi_tb_store_table(ACPI_TO_INTEGER(table),
table, table->length,
ACPI_TABLE_ORIGIN_ALLOCATED, table_index);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status, goto release;
"Could not install table [%4.4s]",
table_info->pointer->signature));
} }
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s located at %p\n", acpi_tb_print_table_header(0, table);
acpi_gbl_table_data[table_info->type].name,
table_info->pointer));
unlock_and_exit: release:
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES); (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_tb_recognize_table * FUNCTION: acpi_tb_resize_root_table_list
* *
* PARAMETERS: table_info - Return value from acpi_tb_get_table_body * PARAMETERS: None
* search_type - Table type to match (primary/secondary)
* *
* RETURN: Status * RETURN: Status
* *
* DESCRIPTION: Check a table signature for a match against known table types * DESCRIPTION: Expand the size of global table array
*
* NOTE: All table pointers are validated as follows:
* 1) Table pointer must point to valid physical memory
* 2) Signature must be 4 ASCII chars, even if we don't recognize the
* name
* 3) Table must be readable for length specified in the header
* 4) Table checksum must be valid (with the exception of the FACS
* which has no checksum for some odd reason)
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_status acpi_tb_resize_root_table_list(void)
acpi_tb_recognize_table(struct acpi_table_desc *table_info, u8 search_type)
{ {
struct acpi_table_header *table_header; struct acpi_table_desc *tables;
acpi_status status;
ACPI_FUNCTION_TRACE(tb_recognize_table); ACPI_FUNCTION_TRACE(tb_resize_root_table_list);
/* Ensure that we have a valid table pointer */ /* allow_resize flag is a parameter to acpi_initialize_tables */
table_header = (struct acpi_table_header *)table_info->pointer; if (!(acpi_gbl_root_table_list.flags & ACPI_TABLE_FLAGS_ALLOW_RESIZE)) {
if (!table_header) { ACPI_ERROR((AE_INFO,
return_ACPI_STATUS(AE_BAD_PARAMETER); "Resize of Root Table Array is not allowed"));
return_ACPI_STATUS(AE_SUPPORT);
} }
/* /* Increase the Table Array size */
* We only "recognize" a limited number of ACPI tables -- namely, the
* ones that are used by the subsystem (DSDT, FADT, etc.) tables = ACPI_ALLOCATE_ZEROED((acpi_gbl_root_table_list.size +
* ACPI_ROOT_TABLE_SIZE_INCREMENT)
* An AE_TABLE_NOT_SUPPORTED means that the table was not recognized. * sizeof(struct acpi_table_desc));
* This can be any one of many valid ACPI tables, it just isn't one of if (!tables) {
* the tables that is consumed by the core subsystem ACPI_ERROR((AE_INFO,
*/ "Could not allocate new root table array"));
status = acpi_tb_match_signature(table_header->signature, return_ACPI_STATUS(AE_NO_MEMORY);
table_info, search_type);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
} }
status = acpi_tb_validate_table_header(table_header); /* Copy and free the previous table array */
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status); if (acpi_gbl_root_table_list.tables) {
ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables,
acpi_gbl_root_table_list.size *
sizeof(struct acpi_table_desc));
if (acpi_gbl_root_table_list.flags & ACPI_TABLE_ORIGIN_MASK ==
ACPI_TABLE_ORIGIN_ALLOCATED) {
ACPI_FREE(acpi_gbl_root_table_list.tables);
}
} }
/* Return the table type and length via the info struct */ acpi_gbl_root_table_list.tables = tables;
acpi_gbl_root_table_list.size += ACPI_ROOT_TABLE_SIZE_INCREMENT;
acpi_gbl_root_table_list.flags = (u8) (ACPI_TABLE_ORIGIN_ALLOCATED |
(acpi_gbl_root_table_list.
flags &
~ACPI_TABLE_ORIGIN_MASK));
table_info->length = (acpi_size) table_header->length; return_ACPI_STATUS(AE_OK);
return_ACPI_STATUS(status);
} }
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_tb_init_table_descriptor * FUNCTION: acpi_tb_store_table
* *
* PARAMETERS: table_type - The type of the table * PARAMETERS: Address - Table address
* table_info - A table info struct * Table - Table header
* Length - Table length
* Flags - flags
* *
* RETURN: None. * RETURN: Status and table index.
* *
* DESCRIPTION: Install a table into the global data structs. * DESCRIPTION: Add an ACPI table to the global table list
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_status
acpi_tb_init_table_descriptor(acpi_table_type table_type, acpi_tb_store_table(acpi_physical_address address,
struct acpi_table_desc *table_info) struct acpi_table_header *table,
u32 length, u8 flags, acpi_native_uint * table_index)
{ {
struct acpi_table_list *list_head; acpi_status status = AE_OK;
struct acpi_table_desc *table_desc;
acpi_status status;
ACPI_FUNCTION_TRACE_U32(tb_init_table_descriptor, table_type);
/* Allocate a descriptor for this table */
table_desc = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_table_desc)); /* Ensure that there is room for the table in the Root Table List */
if (!table_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Get a new owner ID for the table */ if (acpi_gbl_root_table_list.count >= acpi_gbl_root_table_list.size) {
status = acpi_tb_resize_root_table_list();
status = acpi_ut_allocate_owner_id(&table_desc->owner_id);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
goto error_exit1; return (status);
}
} }
/* Install the table into the global data structure */ /* Initialize added table */
list_head = &acpi_gbl_table_lists[table_type]; acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].
address = address;
acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].
pointer = table;
acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].length =
length;
acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].
owner_id = 0;
acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].flags =
flags;
ACPI_MOVE_32_TO_32(&
(acpi_gbl_root_table_list.
tables[acpi_gbl_root_table_list.count].signature),
table->signature);
*table_index = acpi_gbl_root_table_list.count;
acpi_gbl_root_table_list.count++;
return (status);
}
/* /*******************************************************************************
* Two major types of tables: 1) Only one instance is allowed. This *
* includes most ACPI tables such as the DSDT. 2) Multiple instances of * FUNCTION: acpi_tb_delete_table
* the table are allowed. This includes SSDT and PSDTs. *
*/ * PARAMETERS: table_index - Table index
if (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags)) { *
/* * RETURN: None
* Only one table allowed, and a table has alread been installed *
* at this location, so return an error. * DESCRIPTION: Delete one internal ACPI table
*/ *
if (list_head->next) { ******************************************************************************/
status = AE_ALREADY_EXISTS;
goto error_exit2;
}
table_desc->next = list_head->next; void acpi_tb_delete_table(acpi_native_uint table_index)
list_head->next = table_desc; {
struct acpi_table_desc *table_desc;
if (table_desc->next) { /* table_index assumed valid */
table_desc->next->prev = table_desc;
}
list_head->count++; table_desc = &acpi_gbl_root_table_list.tables[table_index];
} else {
/*
* Link the new table in to the list of tables of this type.
* Insert at the end of the list, order IS IMPORTANT.
*
* table_desc->Prev & Next are already NULL from calloc()
*/
list_head->count++;
if (!list_head->next) { /* Table must be mapped or allocated */
list_head->next = table_desc;
} else {
table_desc->next = list_head->next;
while (table_desc->next->next) { if (!table_desc->pointer) {
table_desc->next = table_desc->next->next; return;
} }
table_desc->next->next = table_desc; if (table_desc->flags & ACPI_TABLE_ORIGIN_MAPPED) {
table_desc->prev = table_desc->next; acpi_tb_unmap(table_desc->pointer, table_desc->length,
table_desc->next = NULL; table_desc->flags & ACPI_TABLE_ORIGIN_MASK);
} } else if (table_desc->flags & ACPI_TABLE_ORIGIN_ALLOCATED) {
ACPI_FREE(table_desc->pointer);
} }
/* Finish initialization of the table descriptor */ table_desc->pointer = NULL;
}
table_desc->loaded_into_namespace = FALSE; /*******************************************************************************
table_desc->type = (u8) table_type; *
table_desc->pointer = table_info->pointer; * FUNCTION: acpi_tb_terminate
table_desc->length = table_info->length; *
table_desc->allocation = table_info->allocation; * PARAMETERS: None
table_desc->aml_start = (u8 *) (table_desc->pointer + 1), *
table_desc->aml_length = (u32) * RETURN: None
(table_desc->length - (u32) sizeof(struct acpi_table_header)); *
* DESCRIPTION: Delete all internal ACPI tables
*
******************************************************************************/
/* void acpi_tb_terminate(void)
* Set the appropriate global pointer (if there is one) to point to the {
* newly installed table acpi_native_uint i;
*/
if (acpi_gbl_table_data[table_type].global_ptr) {
*(acpi_gbl_table_data[table_type].global_ptr) =
table_info->pointer;
}
/* Return Data */ ACPI_FUNCTION_TRACE(tb_terminate);
table_info->owner_id = table_desc->owner_id; (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
table_info->installed_desc = table_desc;
return_ACPI_STATUS(AE_OK);
/* Error exit with cleanup */ /* Delete the individual tables */
error_exit2: for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
acpi_tb_delete_table(i);
}
acpi_ut_release_owner_id(&table_desc->owner_id); /*
* 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_TABLE_ORIGIN_MASK) ==
ACPI_TABLE_ORIGIN_ALLOCATED) {
ACPI_FREE(acpi_gbl_root_table_list.tables);
}
error_exit1: acpi_gbl_root_table_list.tables = NULL;
acpi_gbl_root_table_list.flags = 0;
acpi_gbl_root_table_list.count = 0;
ACPI_FREE(table_desc); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n"));
return_ACPI_STATUS(status); (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
} }
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_tb_delete_all_tables * FUNCTION: acpi_tb_delete_namespace_by_owner
* *
* PARAMETERS: None. * PARAMETERS: table_index - Table index
* *
* RETURN: None. * RETURN: None
* *
* DESCRIPTION: Delete all internal ACPI tables * DESCRIPTION: Delete all namespace objects created when this table was loaded.
* *
******************************************************************************/ ******************************************************************************/
void acpi_tb_delete_all_tables(void) void acpi_tb_delete_namespace_by_owner(acpi_native_uint table_index)
{ {
acpi_table_type type; acpi_owner_id owner_id;
/* (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
* Free memory allocated for ACPI tables if (table_index < acpi_gbl_root_table_list.count) {
* Memory can either be mapped or allocated owner_id =
*/ acpi_gbl_root_table_list.tables[table_index].owner_id;
for (type = 0; type < (ACPI_TABLE_ID_MAX + 1); type++) { } else {
acpi_tb_delete_tables_by_type(type); (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
return;
} }
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
acpi_ns_delete_namespace_by_owner(owner_id);
} }
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_tb_delete_tables_by_type * FUNCTION: acpi_tb_allocate_owner_id
* *
* PARAMETERS: Type - The table type to be deleted * PARAMETERS: table_index - Table index
* *
* RETURN: None. * RETURN: Status
* *
* DESCRIPTION: Delete an internal ACPI table * DESCRIPTION: Allocates owner_id in table_desc
* Locks the ACPI table mutex
* *
******************************************************************************/ ******************************************************************************/
void acpi_tb_delete_tables_by_type(acpi_table_type type) acpi_status acpi_tb_allocate_owner_id(acpi_native_uint table_index)
{ {
struct acpi_table_desc *table_desc; acpi_status status = AE_BAD_PARAMETER;
u32 count;
u32 i;
ACPI_FUNCTION_TRACE_U32(tb_delete_tables_by_type, type); ACPI_FUNCTION_TRACE(tb_allocate_owner_id);
if (type > ACPI_TABLE_ID_MAX) { (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
return_VOID; if (table_index < acpi_gbl_root_table_list.count) {
status = acpi_ut_allocate_owner_id
(&(acpi_gbl_root_table_list.tables[table_index].owner_id));
} }
if (ACPI_FAILURE(acpi_ut_acquire_mutex(ACPI_MTX_TABLES))) { (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
return; return_ACPI_STATUS(status);
} }
/* 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; * FUNCTION: acpi_tb_release_owner_id
*
* PARAMETERS: table_index - Table index
*
* RETURN: Status
*
* DESCRIPTION: Releases owner_id in table_desc
*
******************************************************************************/
case ACPI_TABLE_ID_SSDT: acpi_status acpi_tb_release_owner_id(acpi_native_uint table_index)
case ACPI_TABLE_ID_PSDT: {
default: acpi_status status = AE_BAD_PARAMETER;
break;
}
/* ACPI_FUNCTION_TRACE(tb_release_owner_id);
* 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;
/* (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
* 2) Walk the entire list, deleting both the allocated tables if (table_index < acpi_gbl_root_table_list.count) {
* and the table descriptors acpi_ut_release_owner_id(&
*/ (acpi_gbl_root_table_list.
for (i = 0; i < count; i++) { tables[table_index].owner_id));
table_desc = acpi_tb_uninstall_table(table_desc); status = AE_OK;
} }
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES); (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
return_VOID; return_ACPI_STATUS(status);
} }
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_tb_delete_single_table * FUNCTION: acpi_tb_get_owner_id
* *
* PARAMETERS: table_info - A table info struct * PARAMETERS: table_index - Table index
* owner_id - Where the table owner_id is returned
* *
* RETURN: None. * RETURN: Status
* *
* DESCRIPTION: Low-level free for a single ACPI table. Handles cases where * DESCRIPTION: returns owner_id for the ACPI table
* the table was allocated a buffer or was mapped.
* *
******************************************************************************/ ******************************************************************************/
void acpi_tb_delete_single_table(struct acpi_table_desc *table_desc) acpi_status
acpi_tb_get_owner_id(acpi_native_uint table_index, acpi_owner_id * owner_id)
{ {
acpi_status status = AE_BAD_PARAMETER;
/* Must have a valid table descriptor and pointer */ ACPI_FUNCTION_TRACE(tb_get_owner_id);
if ((!table_desc) || (!table_desc->pointer)) { (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
return; if (table_index < acpi_gbl_root_table_list.count) {
*owner_id =
acpi_gbl_root_table_list.tables[table_index].owner_id;
status = AE_OK;
} }
/* Valid table, determine type of memory allocation */ (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
return_ACPI_STATUS(status);
switch (table_desc->allocation) { }
case ACPI_MEM_NOT_ALLOCATED:
break;
case ACPI_MEM_ALLOCATED:
ACPI_FREE(table_desc->pointer);
break;
case ACPI_MEM_MAPPED: /*******************************************************************************
*
* FUNCTION: acpi_tb_is_table_loaded
*
* PARAMETERS: table_index - Table index
*
* RETURN: Table Loaded Flag
*
******************************************************************************/
acpi_os_unmap_memory(table_desc->pointer, table_desc->length); u8 acpi_tb_is_table_loaded(acpi_native_uint table_index)
break; {
u8 is_loaded = FALSE;
default: (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
break; if (table_index < acpi_gbl_root_table_list.count) {
is_loaded = (u8)
(acpi_gbl_root_table_list.tables[table_index].
flags & ACPI_TABLE_FLAGS_LOADED);
} }
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
return (is_loaded);
} }
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_tb_uninstall_table * FUNCTION: acpi_tb_set_table_loaded_flag
* *
* PARAMETERS: table_info - A table info struct * PARAMETERS: table_index - Table index
* is_loaded - TRUE if table is loaded, FALSE otherwise
* *
* RETURN: Pointer to the next table in the list (of same type) * RETURN: None
* *
* DESCRIPTION: Free the memory associated with an internal ACPI table that * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
* is either installed or has never been installed.
* Table mutex should be locked.
* *
******************************************************************************/ ******************************************************************************/
struct acpi_table_desc *acpi_tb_uninstall_table(struct acpi_table_desc void acpi_tb_set_table_loaded_flag(acpi_native_uint table_index, u8 is_loaded)
*table_desc)
{ {
struct acpi_table_desc *next_desc;
ACPI_FUNCTION_TRACE_PTR(tb_uninstall_table, table_desc);
if (!table_desc) {
return_PTR(NULL);
}
/* Unlink the descriptor from the doubly linked list */
if (table_desc->prev) { (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
table_desc->prev->next = table_desc->next; if (table_index < acpi_gbl_root_table_list.count) {
if (is_loaded) {
acpi_gbl_root_table_list.tables[table_index].flags |=
ACPI_TABLE_FLAGS_LOADED;
} else { } else {
/* Is first on list, update list head */ acpi_gbl_root_table_list.tables[table_index].flags &=
~ACPI_TABLE_FLAGS_LOADED;
acpi_gbl_table_lists[table_desc->type].next = table_desc->next;
} }
if (table_desc->next) {
table_desc->next->prev = table_desc->prev;
} }
/* Free the memory allocated for the table itself */ (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
acpi_tb_delete_single_table(table_desc);
/* Free the owner ID associated with this table */
acpi_ut_release_owner_id(&table_desc->owner_id);
/* Free the table descriptor */
next_desc = table_desc->next;
ACPI_FREE(table_desc);
/* Return pointer to the next descriptor */
return_PTR(next_desc);
} }
/******************************************************************************
*
* Module Name: tbrsdt - ACPI RSDT table utilities
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include <acpi/actables.h>
#define _COMPONENT ACPI_TABLES
ACPI_MODULE_NAME("tbrsdt")
/*******************************************************************************
*
* FUNCTION: acpi_tb_verify_rsdp
*
* PARAMETERS: Address - RSDP (Pointer to RSDT)
*
* RETURN: Status
*
* DESCRIPTION: Load and validate the RSDP (ptr) and RSDT (table)
*
******************************************************************************/
acpi_status acpi_tb_verify_rsdp(struct acpi_pointer *address)
{
struct acpi_table_desc table_info;
acpi_status status;
struct rsdp_descriptor *rsdp;
ACPI_FUNCTION_TRACE(tb_verify_rsdp);
switch (address->pointer_type) {
case ACPI_LOGICAL_POINTER:
rsdp = address->pointer.logical;
break;
case ACPI_PHYSICAL_POINTER:
/*
* Obtain access to the RSDP structure
*/
status = acpi_os_map_memory(address->pointer.physical,
sizeof(struct rsdp_descriptor),
ACPI_CAST_PTR(void, &rsdp));
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
break;
default:
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Verify RSDP signature and checksum */
status = acpi_tb_validate_rsdp(rsdp);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
/* RSDP is ok. Init the table info */
table_info.pointer = ACPI_CAST_PTR(struct acpi_table_header, rsdp);
table_info.length = sizeof(struct rsdp_descriptor);
if (address->pointer_type == ACPI_PHYSICAL_POINTER) {
table_info.allocation = ACPI_MEM_MAPPED;
} else {
table_info.allocation = ACPI_MEM_NOT_ALLOCATED;
}
/* Save the table pointers and allocation info */
status = acpi_tb_init_table_descriptor(ACPI_TABLE_ID_RSDP, &table_info);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
/* Save the RSDP in a global for easy access */
acpi_gbl_RSDP =
ACPI_CAST_PTR(struct rsdp_descriptor, table_info.pointer);
return_ACPI_STATUS(status);
/* Error exit */
cleanup:
if (acpi_gbl_table_flags & ACPI_PHYSICAL_POINTER) {
acpi_os_unmap_memory(rsdp, sizeof(struct rsdp_descriptor));
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_rsdt_address
*
* PARAMETERS: out_address - Where the address is returned
*
* RETURN: None, Address
*
* DESCRIPTION: Extract the address of either the RSDT or XSDT, depending on the
* version of the RSDP and whether the XSDT pointer is valid
*
******************************************************************************/
void acpi_tb_get_rsdt_address(struct acpi_pointer *out_address)
{
ACPI_FUNCTION_ENTRY();
out_address->pointer_type =
acpi_gbl_table_flags | ACPI_LOGICAL_ADDRESSING;
/* Use XSDT if it is present */
if ((acpi_gbl_RSDP->revision >= 2) &&
acpi_gbl_RSDP->xsdt_physical_address) {
out_address->pointer.value =
acpi_gbl_RSDP->xsdt_physical_address;
acpi_gbl_root_table_type = ACPI_TABLE_TYPE_XSDT;
} else {
/* No XSDT, use the RSDT */
out_address->pointer.value =
acpi_gbl_RSDP->rsdt_physical_address;
acpi_gbl_root_table_type = ACPI_TABLE_TYPE_RSDT;
}
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_validate_rsdt
*
* PARAMETERS: table_ptr - Addressable pointer to the RSDT.
*
* RETURN: Status
*
* DESCRIPTION: Validate signature for the RSDT or XSDT
*
******************************************************************************/
acpi_status acpi_tb_validate_rsdt(struct acpi_table_header *table_ptr)
{
char *signature;
ACPI_FUNCTION_ENTRY();
/* Validate minimum length */
if (table_ptr->length < sizeof(struct acpi_table_header)) {
ACPI_ERROR((AE_INFO,
"RSDT/XSDT length (%X) is smaller than minimum (%zX)",
table_ptr->length,
sizeof(struct acpi_table_header)));
return (AE_INVALID_TABLE_LENGTH);
}
/* Search for appropriate signature, RSDT or XSDT */
if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
signature = RSDT_SIG;
} else {
signature = XSDT_SIG;
}
if (!ACPI_COMPARE_NAME(table_ptr->signature, signature)) {
/* Invalid RSDT or XSDT signature */
ACPI_ERROR((AE_INFO,
"Invalid signature where RSDP indicates RSDT/XSDT should be located. RSDP:"));
ACPI_DUMP_BUFFER(acpi_gbl_RSDP, 20);
ACPI_ERROR((AE_INFO,
"RSDT/XSDT signature at %X is invalid",
acpi_gbl_RSDP->rsdt_physical_address));
if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
ACPI_ERROR((AE_INFO, "Looking for RSDT"));
} else {
ACPI_ERROR((AE_INFO, "Looking for XSDT"));
}
ACPI_DUMP_BUFFER(ACPI_CAST_PTR(char, table_ptr), 48);
return (AE_BAD_SIGNATURE);
}
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_table_rsdt
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Load and validate the RSDP (ptr) and RSDT (table)
*
******************************************************************************/
acpi_status acpi_tb_get_table_rsdt(void)
{
struct acpi_table_desc table_info;
acpi_status status;
struct acpi_pointer address;
ACPI_FUNCTION_TRACE(tb_get_table_rsdt);
/* Get the RSDT/XSDT via the RSDP */
acpi_tb_get_rsdt_address(&address);
table_info.type = ACPI_TABLE_ID_XSDT;
status = acpi_tb_get_table(&address, &table_info);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Could not get the RSDT/XSDT"));
return_ACPI_STATUS(status);
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"RSDP located at %p, points to RSDT physical=%8.8X%8.8X\n",
acpi_gbl_RSDP,
ACPI_FORMAT_UINT64(address.pointer.value)));
/* Check the RSDT or XSDT signature */
status = acpi_tb_validate_rsdt(table_info.pointer);
if (ACPI_FAILURE(status)) {
goto error_cleanup;
}
/* Get the number of tables defined in the RSDT or XSDT */
acpi_gbl_rsdt_table_count = acpi_tb_get_table_count(acpi_gbl_RSDP,
table_info.pointer);
/* Convert and/or copy to an XSDT structure */
status = acpi_tb_convert_to_xsdt(&table_info);
if (ACPI_FAILURE(status)) {
goto error_cleanup;
}
/* Save the table pointers and allocation info */
status = acpi_tb_init_table_descriptor(ACPI_TABLE_ID_XSDT, &table_info);
if (ACPI_FAILURE(status)) {
goto error_cleanup;
}
acpi_gbl_XSDT =
ACPI_CAST_PTR(struct xsdt_descriptor, table_info.pointer);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "XSDT located at %p\n", acpi_gbl_XSDT));
return_ACPI_STATUS(status);
error_cleanup:
/* Free table allocated by acpi_tb_get_table */
acpi_tb_delete_single_table(&table_info);
return_ACPI_STATUS(status);
}
/****************************************************************************** /******************************************************************************
* *
* Module Name: tbutils - Table manipulation utilities * Module Name: tbutils - table utilities
* *
*****************************************************************************/ *****************************************************************************/
...@@ -48,295 +48,507 @@ ...@@ -48,295 +48,507 @@
ACPI_MODULE_NAME("tbutils") ACPI_MODULE_NAME("tbutils")
/* Local prototypes */ /* Local prototypes */
#ifdef ACPI_OBSOLETE_FUNCTIONS static void acpi_tb_parse_fadt(struct acpi_table_fadt *fadt, u8 flags);
acpi_status
acpi_tb_handle_to_object(u16 table_id, struct acpi_table_desc **table_desc); static void inline
#endif acpi_tb_init_generic_address(struct acpi_generic_address *new_gas_struct,
u8 bit_width, acpi_physical_address address);
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_tb_is_table_installed * FUNCTION: acpi_tb_print_table_header
*
* PARAMETERS: new_table_desc - Descriptor for new table being installed
* *
* RETURN: Status - AE_ALREADY_EXISTS if the table is already installed * PARAMETERS: Address - Table physical address
* Header - Table header
* *
* DESCRIPTION: Determine if an ACPI table is already installed * RETURN: None
* *
* MUTEX: Table data structures should be locked * DESCRIPTION: Print an ACPI table header
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_tb_is_table_installed(struct acpi_table_desc *new_table_desc) void
acpi_tb_print_table_header(acpi_physical_address address,
struct acpi_table_header *header)
{ {
struct acpi_table_desc *table_desc;
ACPI_FUNCTION_TRACE(tb_is_table_installed);
/* Get the list descriptor and first table descriptor */
table_desc = acpi_gbl_table_lists[new_table_desc->type].next;
/* Examine all installed tables of this type */
while (table_desc) {
/*
* If the table lengths match, perform a full bytewise compare. This
* means that we will allow tables with duplicate oem_table_id(s), as
* long as the tables are different in some way.
*
* Checking if the table has been loaded into the namespace means that
* we don't check for duplicate tables during the initial installation
* of tables within the RSDT/XSDT.
*/
if ((table_desc->loaded_into_namespace) &&
(table_desc->pointer->length ==
new_table_desc->pointer->length)
&&
(!ACPI_MEMCMP
(table_desc->pointer, new_table_desc->pointer,
new_table_desc->pointer->length))) {
/* Match: this table is already installed */
ACPI_DEBUG_PRINT((ACPI_DB_TABLES,
"Table [%4.4s] already installed: Rev %X OemTableId [%8.8s]\n",
new_table_desc->pointer->signature,
new_table_desc->pointer->revision,
new_table_desc->pointer->
oem_table_id));
new_table_desc->owner_id = table_desc->owner_id;
new_table_desc->installed_desc = table_desc;
return_ACPI_STATUS(AE_ALREADY_EXISTS);
}
/* Get next table on the list */ ACPI_INFO((AE_INFO,
"%4.4s @ 0x%p Length 0x%04X (v%3.3d %6.6s %8.8s 0x%08X %4.4s 0x%08X)",
table_desc = table_desc->next; header->signature, ACPI_CAST_PTR(void, address),
} header->length, header->revision, header->oem_id,
header->oem_table_id, header->oem_revision,
return_ACPI_STATUS(AE_OK); header->asl_compiler_id, header->asl_compiler_revision));
} }
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_tb_validate_table_header * FUNCTION: acpi_tb_init_generic_address
* *
* PARAMETERS: table_header - Logical pointer to the table * PARAMETERS: new_gas_struct - GAS struct to be initialized
* * bit_width - Width of this register
* RETURN: Status * Address - Address of the register
* *
* DESCRIPTION: Check an ACPI table header for validity * RETURN: None
* *
* NOTE: Table pointers are validated as follows: * DESCRIPTION: Initialize a GAS structure.
* 1) Table pointer must point to valid physical memory
* 2) Signature must be 4 ASCII chars, even if we don't recognize the
* name
* 3) Table must be readable for length specified in the header
* 4) Table checksum must be valid (with the exception of the FACS
* which has no checksum because it contains variable fields)
* *
******************************************************************************/ ******************************************************************************/
acpi_status static void inline
acpi_tb_validate_table_header(struct acpi_table_header *table_header) acpi_tb_init_generic_address(struct acpi_generic_address *new_gas_struct,
u8 bit_width, acpi_physical_address address)
{ {
acpi_name signature;
ACPI_FUNCTION_ENTRY(); ACPI_STORE_ADDRESS(new_gas_struct->address, address);
new_gas_struct->space_id = ACPI_ADR_SPACE_SYSTEM_IO;
/* Verify that this is a valid address */ new_gas_struct->bit_width = bit_width;
new_gas_struct->bit_offset = 0;
if (!acpi_os_readable(table_header, sizeof(struct acpi_table_header))) { new_gas_struct->access_width = 0;
ACPI_ERROR((AE_INFO,
"Cannot read table header at %p", table_header));
return (AE_BAD_ADDRESS);
}
/* Ensure that the signature is 4 ASCII characters */
ACPI_MOVE_32_TO_32(&signature, table_header->signature);
if (!acpi_ut_valid_acpi_name(signature)) {
ACPI_ERROR((AE_INFO, "Invalid table signature 0x%8.8X",
signature));
ACPI_DUMP_BUFFER(table_header,
sizeof(struct acpi_table_header));
return (AE_BAD_SIGNATURE);
}
/* Validate the table length */
if (table_header->length < sizeof(struct acpi_table_header)) {
ACPI_ERROR((AE_INFO,
"Invalid length 0x%X in table with signature %4.4s",
(u32) table_header->length,
ACPI_CAST_PTR(char, &signature)));
ACPI_DUMP_BUFFER(table_header,
sizeof(struct acpi_table_header));
return (AE_BAD_HEADER);
}
return (AE_OK);
} }
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_tb_sum_table * FUNCTION: acpi_tb_checksum
* *
* PARAMETERS: Buffer - Buffer to sum * PARAMETERS: Buffer - Pointer to memory region to be checked
* Length - Size of the buffer * Length - Length of this memory region
* *
* RETURN: 8 bit sum of buffer * RETURN: Checksum (u8)
* *
* DESCRIPTION: Computes an 8 bit sum of the buffer(length) and returns it. * DESCRIPTION: Calculates circular checksum of memory region.
* *
******************************************************************************/ ******************************************************************************/
u8 acpi_tb_sum_table(void *buffer, u32 length) u8 acpi_tb_checksum(u8 * buffer, acpi_native_uint length)
{ {
acpi_native_uint i;
u8 sum = 0; u8 sum = 0;
u8 *end = buffer + length;
if (!buffer || !length) { while (buffer < end) {
return (0); sum = (u8) (sum + *(buffer++));
} }
for (i = 0; i < length; i++) { return sum;
sum = (u8) (sum + ((u8 *) buffer)[i]);
}
return (sum);
} }
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_tb_generate_checksum * FUNCTION: acpi_tb_convert_fadt
* *
* PARAMETERS: Table - Pointer to a valid ACPI table (with a * PARAMETERS: Fadt - FADT table to be converted
* standard ACPI header)
* *
* RETURN: 8 bit checksum of buffer * RETURN: None
* *
* DESCRIPTION: Computes an 8 bit checksum of the table. * DESCRIPTION: Converts a BIOS supplied ACPI 1.0 FADT to a local
* ACPI 2.0 FADT. If the BIOS supplied a 2.0 FADT then it is simply
* copied to the local FADT. The ACPI CA software uses this
* local FADT. Thus a significant amount of special #ifdef
* type codeing is saved.
* *
******************************************************************************/ ******************************************************************************/
u8 acpi_tb_generate_checksum(struct acpi_table_header * table) void acpi_tb_convert_fadt(struct acpi_table_fadt *fadt)
{ {
u8 checksum;
/* Sum the entire table as-is */ /*
* Convert table pointers to 64-bit fields
*/
if (!acpi_gbl_FADT.Xfacs) {
acpi_gbl_FADT.Xfacs = (u64) acpi_gbl_FADT.facs;
}
checksum = acpi_tb_sum_table(table, table->length); if (!acpi_gbl_FADT.Xdsdt) {
acpi_gbl_FADT.Xdsdt = (u64) acpi_gbl_FADT.dsdt;
}
/* Subtract off the existing checksum value in the table */ /*
* Convert the V1.0 block addresses to V2.0 GAS structures
*/
acpi_tb_init_generic_address(&acpi_gbl_FADT.xpm1a_event_block,
acpi_gbl_FADT.pm1_event_length,
(acpi_physical_address) acpi_gbl_FADT.
pm1a_event_block);
acpi_tb_init_generic_address(&acpi_gbl_FADT.xpm1b_event_block,
acpi_gbl_FADT.pm1_event_length,
(acpi_physical_address) acpi_gbl_FADT.
pm1b_event_block);
acpi_tb_init_generic_address(&acpi_gbl_FADT.xpm1a_control_block,
acpi_gbl_FADT.pm1_control_length,
(acpi_physical_address) acpi_gbl_FADT.
pm1a_control_block);
acpi_tb_init_generic_address(&acpi_gbl_FADT.xpm1b_control_block,
acpi_gbl_FADT.pm1_control_length,
(acpi_physical_address) acpi_gbl_FADT.
pm1b_control_block);
acpi_tb_init_generic_address(&acpi_gbl_FADT.xpm2_control_block,
acpi_gbl_FADT.pm2_control_length,
(acpi_physical_address) acpi_gbl_FADT.
pm2_control_block);
acpi_tb_init_generic_address(&acpi_gbl_FADT.xpm_timer_block,
acpi_gbl_FADT.pm_timer_length,
(acpi_physical_address) acpi_gbl_FADT.
pm_timer_block);
acpi_tb_init_generic_address(&acpi_gbl_FADT.xgpe0_block, 0,
(acpi_physical_address) acpi_gbl_FADT.
gpe0_block);
acpi_tb_init_generic_address(&acpi_gbl_FADT.xgpe1_block, 0,
(acpi_physical_address) acpi_gbl_FADT.
gpe1_block);
checksum = (u8) (checksum - table->checksum); /*
* Create separate GAS structs for the PM1 Enable registers
*/
acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable,
(u8) ACPI_DIV_2(acpi_gbl_FADT.
pm1_event_length),
(acpi_physical_address)
(acpi_gbl_FADT.xpm1a_event_block.address +
ACPI_DIV_2(acpi_gbl_FADT.
pm1_event_length)));
/*
* PM1B is optional; leave null if not present
*/
if (acpi_gbl_FADT.xpm1b_event_block.address) {
acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable,
(u8) ACPI_DIV_2(acpi_gbl_FADT.
pm1_event_length),
(acpi_physical_address)
(acpi_gbl_FADT.xpm1b_event_block.
address +
ACPI_DIV_2(acpi_gbl_FADT.
pm1_event_length)));
}
/* Compute the final checksum */ /* Global FADT is the new common V2.0 FADT */
checksum = (u8) (0 - checksum); acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt);
return (checksum);
} }
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_tb_set_checksum * FUNCTION: acpi_tb_parse_fadt
* *
* PARAMETERS: Table - Pointer to a valid ACPI table (with a * PARAMETERS: Fadt - Pointer to FADT table
* standard ACPI header) * Flags - Flags
* *
* RETURN: None. Sets the table checksum field * RETURN: none
* *
* DESCRIPTION: Computes an 8 bit checksum of the table and inserts the * DESCRIPTION: This function is called to initialise the FADT, DSDT and FACS
* checksum into the table header. * tables (FADT contains the addresses of the DSDT and FACS)
* *
******************************************************************************/ ******************************************************************************/
void acpi_tb_set_checksum(struct acpi_table_header *table) static void acpi_tb_parse_fadt(struct acpi_table_fadt *fadt, u8 flags)
{ {
acpi_physical_address dsdt_address =
(acpi_physical_address) fadt->Xdsdt;
acpi_physical_address facs_address =
(acpi_physical_address) fadt->Xfacs;
struct acpi_table_header *table;
if (!dsdt_address) {
goto no_dsdt;
}
table =
acpi_os_map_memory(dsdt_address, sizeof(struct acpi_table_header));
if (!table) {
goto no_dsdt;
}
/* Initialize the DSDT table */
ACPI_MOVE_32_TO_32(&
(acpi_gbl_root_table_list.
tables[ACPI_TABLE_INDEX_DSDT].signature),
ACPI_SIG_DSDT);
acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].address =
dsdt_address;
acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].length =
table->length;
acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].flags = flags;
acpi_tb_print_table_header(dsdt_address, table);
/* Global integer width is based upon revision of the DSDT */
table->checksum = acpi_tb_generate_checksum(table); acpi_ut_set_integer_width(table->revision);
acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
no_dsdt:
if (!facs_address) {
return;
}
table =
acpi_os_map_memory(facs_address, sizeof(struct acpi_table_header));
if (!table) {
return;
}
/* Initialize the FACS table */
ACPI_MOVE_32_TO_32(&
(acpi_gbl_root_table_list.
tables[ACPI_TABLE_INDEX_FACS].signature),
ACPI_SIG_FACS);
acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_FACS].address =
facs_address;
acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_FACS].length =
table->length;
acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_FACS].flags = flags;
ACPI_INFO((AE_INFO, "%4.4s @ 0x%p",
table->signature, ACPI_CAST_PTR(void, facs_address)));
acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
} }
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_tb_verify_table_checksum * FUNCTION: acpi_tb_parse_root_table
* *
* PARAMETERS: *table_header - ACPI table to verify * PARAMETERS: Rsdp - Pointer to the RSDP
* Flags - Flags
* *
* RETURN: 8 bit checksum of table * RETURN: Status
*
* DESCRIPTION: This function is called to parse the Root System Description
* Table (RSDT or XSDT)
* *
* DESCRIPTION: Generates an 8 bit checksum of table and returns and compares * NOTE: Tables are mapped (not copied) for efficiency. The FACS must
* it to the existing checksum value. * be mapped and cannot be copied because it contains the actual
* memory location of the ACPI Global Lock.
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_status acpi_tb_parse_root_table(struct acpi_table_rsdp *rsdp, u8 flags)
acpi_tb_verify_table_checksum(struct acpi_table_header *table_header)
{ {
struct acpi_table_header *table;
acpi_physical_address address;
u32 length;
u8 *table_entry;
acpi_native_uint i;
acpi_native_uint pointer_size;
u32 table_count;
u8 checksum; u8 checksum;
acpi_status status;
ACPI_FUNCTION_TRACE(tb_parse_root_table);
ACPI_FUNCTION_TRACE(tb_verify_table_checksum); /* Differentiate between RSDT and XSDT root tables */
/* Compute the checksum on the table */ if (rsdp->revision > 1 && rsdp->xsdt_physical_address) {
/*
* Root table is 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_native_uint) rsdp->xsdt_physical_address;
pointer_size = sizeof(u64);
} else {
/* Root table is an RSDT (32-bit physical addresses) */
checksum = acpi_tb_generate_checksum(table_header); address = (acpi_native_uint) rsdp->rsdt_physical_address;
pointer_size = sizeof(u32);
}
/* Checksum ok? */ /* Map the table header to get the full table length */
if (checksum == table_header->checksum) { table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
return_ACPI_STATUS(AE_OK); if (!table) {
return (AE_NO_MEMORY);
} }
/* Get the length of the full table, verify length and map entire table */
length = table->length;
acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
if (length < sizeof(struct acpi_table_header)) {
ACPI_ERROR((AE_INFO, "Invalid length 0x%X in RSDT/XSDT",
length));
return (AE_INVALID_TABLE_LENGTH);
}
table = acpi_os_map_memory(address, length);
if (!table) {
return (AE_NO_MEMORY);
}
/* Validate the root table checksum */
checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length);
#if (ACPI_CHECKSUM_ABORT)
if (checksum) {
acpi_os_unmap_memory(table, length);
return (AE_BAD_CHECKSUM);
}
#endif
acpi_tb_print_table_header(address, table);
/* Calculate the number of tables described in the root table */
table_count =
(table->length - sizeof(struct acpi_table_header)) / pointer_size;
/* Setup loop */
table_entry =
ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header);
acpi_gbl_root_table_list.count = 2;
/*
* Initialize the ACPI table entries
* First two entries in the table array are reserved for the DSDT and FACS
*/
for (i = 0; i < table_count; ++i, table_entry += pointer_size) {
/* Ensure there is room for another table entry */
if (acpi_gbl_root_table_list.count >=
acpi_gbl_root_table_list.size) {
status = acpi_tb_resize_root_table_list();
if (ACPI_FAILURE(status)) {
ACPI_WARNING((AE_INFO, ACPI_WARNING((AE_INFO,
"Incorrect checksum in table [%4.4s] - is %2.2X, should be %2.2X", "Truncating %u table entries!",
table_header->signature, table_header->checksum, (unsigned)
checksum)); (acpi_gbl_root_table_list.size -
acpi_gbl_root_table_list.
count)));
break;
}
}
/* Get the physical address (32-bit for RSDT, 64-bit for XSDT) */
if (pointer_size == sizeof(u32)) {
acpi_gbl_root_table_list.
tables[acpi_gbl_root_table_list.count].address =
(acpi_physical_address) (*ACPI_CAST_PTR
(u32, table_entry));
} else {
acpi_gbl_root_table_list.
tables[acpi_gbl_root_table_list.count].address =
(acpi_physical_address) (*ACPI_CAST_PTR
(u64, table_entry));
}
acpi_gbl_root_table_list.count++;
}
/*
* It is not possible to map more than one entry in some environments,
* so unmap the root table here before mapping other tables
*/
acpi_os_unmap_memory(table, length);
/* Initialize all tables other than the DSDT and FACS */
for (i = 2; i < acpi_gbl_root_table_list.count; i++) {
address = acpi_gbl_root_table_list.tables[i].address;
length = sizeof(struct acpi_table_header);
table = acpi_os_map_memory(address, length);
if (!table) {
continue;
}
acpi_gbl_root_table_list.tables[i].length = table->length;
acpi_gbl_root_table_list.tables[i].flags = flags;
ACPI_MOVE_32_TO_32(&
(acpi_gbl_root_table_list.tables[i].
signature), table->signature);
acpi_tb_print_table_header(address, table);
return_ACPI_STATUS(AE_BAD_CHECKSUM); /*
* Special case for the FADT because of multiple versions -
* get a local copy and convert to common format
*/
if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_FADT)) {
acpi_os_unmap_memory(table, length);
length = table->length;
table = acpi_os_map_memory(address, length);
if (!table) {
continue;
}
/* Copy the entire FADT locally */
ACPI_MEMCPY(&acpi_gbl_FADT, table,
ACPI_MIN(table->length,
sizeof(struct acpi_table_fadt)));
/* Small table means old revision, convert to new */
if (table->length < sizeof(struct acpi_table_fadt)) {
acpi_tb_convert_fadt(ACPI_CAST_PTR
(struct acpi_table_fadt,
table));
}
/* Unmap original FADT */
acpi_os_unmap_memory(table, length);
acpi_tb_parse_fadt(&acpi_gbl_FADT, flags);
} else {
acpi_os_unmap_memory(table, length);
}
}
return_ACPI_STATUS(AE_OK);
} }
#ifdef ACPI_OBSOLETE_FUNCTIONS /******************************************************************************
/*******************************************************************************
* *
* FUNCTION: acpi_tb_handle_to_object * FUNCTION: acpi_tb_map
* *
* PARAMETERS: table_id - Id for which the function is searching * PARAMETERS: Address - Address to be mapped
* table_desc - Pointer to return the matching table * Length - Length to be mapped
* descriptor. * Flags - Logical or physical addressing mode
* *
* RETURN: Search the tables to find one with a matching table_id and * RETURN: Pointer to mapped region
* return a pointer to that table descriptor.
* *
******************************************************************************/ * DESCRIPTION: Maps memory according to flag
*
*****************************************************************************/
acpi_status void *acpi_tb_map(acpi_physical_address address, u32 length, u32 flags)
acpi_tb_handle_to_object(u16 table_id,
struct acpi_table_desc **return_table_desc)
{ {
u32 i;
struct acpi_table_desc *table_desc;
ACPI_FUNCTION_NAME(tb_handle_to_object);
for (i = 0; i < ACPI_TABLE_MAX; i++) { if (flags == ACPI_TABLE_ORIGIN_MAPPED) {
table_desc = acpi_gbl_table_lists[i].next; return (acpi_os_map_memory(address, length));
while (table_desc) { } else {
if (table_desc->table_id == table_id) { return (ACPI_CAST_PTR(void, address));
*return_table_desc = table_desc;
return (AE_OK);
} }
}
table_desc = table_desc->next; /******************************************************************************
} *
} * FUNCTION: acpi_tb_unmap
*
* PARAMETERS: Pointer - To mapped region
* Length - Length to be unmapped
* Flags - Logical or physical addressing mode
*
* RETURN: None
*
* DESCRIPTION: Unmaps memory according to flag
*
*****************************************************************************/
ACPI_ERROR((AE_INFO, "TableId=%X does not exist", table_id)); void acpi_tb_unmap(void *pointer, u32 length, u32 flags)
return (AE_BAD_PARAMETER); {
if (flags == ACPI_TABLE_ORIGIN_MAPPED) {
acpi_os_unmap_memory(pointer, length);
}
} }
#endif
...@@ -49,80 +49,146 @@ ...@@ -49,80 +49,146 @@
#define _COMPONENT ACPI_TABLES #define _COMPONENT ACPI_TABLES
ACPI_MODULE_NAME("tbxface") ACPI_MODULE_NAME("tbxface")
/* Local prototypes */
static acpi_status acpi_tb_load_namespace(void);
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_load_tables * FUNCTION: acpi_initialize_tables
* *
* PARAMETERS: None * 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 * RETURN: Status
* *
* DESCRIPTION: This function is called to load the ACPI tables from the * DESCRIPTION: Initialize the table manager, get the RSDP and RSDT/XSDT.
* provided RSDT *
* 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.
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_load_tables(void)
acpi_status
acpi_initialize_tables(struct acpi_table_desc *initial_table_array,
u32 initial_table_count, u8 allow_resize)
{ {
struct acpi_pointer rsdp_address; acpi_physical_address address;
acpi_status status; acpi_status status;
struct acpi_table_rsdp *rsdp;
ACPI_FUNCTION_TRACE(acpi_load_tables); ACPI_FUNCTION_TRACE(acpi_initialize_tables);
/* Get the RSDP */ /*
* Set up the Root Table Array
* Allocate the table array if requested
*/
if (!initial_table_array) {
acpi_gbl_root_table_list.size = initial_table_count;
acpi_gbl_root_table_list.flags = ACPI_TABLE_FLAGS_ALLOW_RESIZE;
status = acpi_os_get_root_pointer(ACPI_LOGICAL_ADDRESSING, status = acpi_tb_resize_root_table_list();
&rsdp_address);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status, "Could not get the RSDP")); return_ACPI_STATUS(status);
goto error_exit; }
} else {
/* Root Table Array has been statically allocated by the host */
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_TABLE_ORIGIN_UNKNOWN;
if (allow_resize) {
acpi_gbl_root_table_list.flags =
ACPI_TABLE_FLAGS_ALLOW_RESIZE;
}
} }
/* Map and validate the RSDP */ /* Get the RSDP and map it */
acpi_gbl_table_flags = rsdp_address.pointer_type; address = acpi_os_get_root_pointer();
if (!address) {
return_ACPI_STATUS(AE_NOT_FOUND);
}
status = acpi_tb_verify_rsdp(&rsdp_address); rsdp = acpi_os_map_memory(address, sizeof(struct acpi_table_rsdp));
if (ACPI_FAILURE(status)) { if (!rsdp) {
ACPI_EXCEPTION((AE_INFO, status, "During RSDP validation")); return_ACPI_STATUS(AE_NO_MEMORY);
goto error_exit;
} }
/* Get the RSDT via the RSDP */ ACPI_INFO((AE_INFO, "%.8s @ 0x%p",
rsdp->signature, ACPI_CAST_PTR(void, address)));
status = acpi_tb_get_table_rsdt(); /*
if (ACPI_FAILURE(status)) { * Get the root table (RSDT or XSDT) and extract all entries to the local
ACPI_EXCEPTION((AE_INFO, status, "Could not load RSDT")); * Root Table Array. This array contains the information of the RSDT/XSDT
goto error_exit; * in a common, more useable format.
} */
status = acpi_tb_parse_root_table(rsdp, ACPI_TABLE_ORIGIN_MAPPED);
acpi_os_unmap_memory(rsdp, sizeof(struct acpi_table_rsdp));
return_ACPI_STATUS(status);
}
/* Now get the tables needed by this subsystem (FADT, DSDT, etc.) */ ACPI_EXPORT_SYMBOL(acpi_initialize_tables)
status = acpi_tb_get_required_tables(); /*******************************************************************************
if (ACPI_FAILURE(status)) { *
ACPI_EXCEPTION((AE_INFO, status, * FUNCTION: acpi_reallocate_root_table
"Could not get all required tables (DSDT/FADT/FACS)")); *
goto error_exit; * 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_TABLE_ORIGIN_MASK) !=
ACPI_TABLE_ORIGIN_UNKNOWN) {
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(); tables = ACPI_ALLOCATE_ZEROED(new_size);
if (ACPI_FAILURE(status)) { if (!tables) {
ACPI_EXCEPTION((AE_INFO, status, "Could not load namespace")); return_ACPI_STATUS(AE_NO_MEMORY);
goto error_exit;
} }
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_TABLE_ORIGIN_ALLOCATED | ACPI_TABLE_FLAGS_ALLOW_RESIZE;
return_ACPI_STATUS(AE_OK);
}
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_load_table * FUNCTION: acpi_load_table
...@@ -141,342 +207,358 @@ ACPI_EXPORT_SYMBOL(acpi_load_tables) ...@@ -141,342 +207,358 @@ ACPI_EXPORT_SYMBOL(acpi_load_tables)
acpi_status acpi_load_table(struct acpi_table_header *table_ptr) acpi_status acpi_load_table(struct acpi_table_header *table_ptr)
{ {
acpi_status status; acpi_status status;
struct acpi_table_desc table_info; acpi_native_uint table_index;
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); /*
* Install the new table into the local data structures
*/
status = acpi_tb_add_table(table_ptr, &table_index);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
status = acpi_ns_load_table(table_index, acpi_gbl_root_node);
/* 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); return_ACPI_STATUS(status);
} }
/* Install the new table into the local data structures */
status = acpi_tb_install_table(&table_info); ACPI_EXPORT_SYMBOL(acpi_load_table)
if (ACPI_FAILURE(status)) {
if (status == AE_ALREADY_EXISTS) {
/* Table already exists, no error */ /******************************************************************************
*
* FUNCTION: acpi_get_table_header
*
* PARAMETERS: Signature - ACPI signature of needed table
* Instance - Which instance (for SSDTs)
* out_table_header - Where the pointer to the table header
* is returned
*
* 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;
status = AE_OK; /*
* 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;
} }
/* Free table allocated by acpi_tb_get_table_body */ if (++j < instance) {
continue;
acpi_tb_delete_single_table(&table_info);
return_ACPI_STATUS(status);
} }
/* Convert the table to common format if necessary */ *out_table_header =
acpi_tb_map(acpi_gbl_root_table_list.tables[i].address,
switch (table_info.type) { (u32) sizeof(struct acpi_table_header),
case ACPI_TABLE_ID_FADT: acpi_gbl_root_table_list.tables[i].
flags & ACPI_TABLE_ORIGIN_MASK);
status = acpi_tb_convert_table_fadt();
break;
case ACPI_TABLE_ID_FACS:
status = acpi_tb_build_common_facs(&table_info); if (!out_table_header) {
break; return (AE_NO_MEMORY);
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)) { return (AE_OK);
/* Uninstall table and free the buffer */
(void)acpi_tb_uninstall_table(table_info.installed_desc);
} }
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 * FUNCTION: acpi_unload_table_id
* *
* PARAMETERS: table_type - Type of table to be unloaded * PARAMETERS: id - Owner ID of the table to be removed.
* id - Owner ID of the table to be removed.
* *
* RETURN: Status * RETURN: Status
* *
* DESCRIPTION: This routine is used to force the unload of a table (by id) * 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; int i;
acpi_status status; acpi_status status = AE_NOT_EXIST;
ACPI_FUNCTION_TRACE(acpi_unload_table); 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 */ /* Find table from the requested type list */
table_desc = acpi_gbl_table_lists[table_type].next; for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
while (table_desc && table_desc->owner_id != id) if (id != acpi_gbl_root_table_list.tables[i].owner_id) {
table_desc = table_desc->next; continue;
}
if (!table_desc)
return_ACPI_STATUS(AE_NOT_EXIST);
/* /*
* Delete all namespace objects owned by this table. Note that these * Delete all namespace objects owned by this table. Note that these
* objects can appear anywhere in the namespace by virtue of the AML * objects can appear anywhere in the namespace by virtue of the AML
* "Scope" operator. Thus, we need to track ownership by an ID, not * "Scope" operator. Thus, we need to track ownership by an ID, not
* simply a position within the hierarchy * simply a position within the hierarchy
*/ */
acpi_ns_delete_namespace_by_owner(table_desc->owner_id); acpi_tb_delete_namespace_by_owner(i);
acpi_tb_release_owner_id(i);
status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); acpi_tb_set_table_loaded_flag(i, FALSE);
if (ACPI_FAILURE(status)) }
return_ACPI_STATUS(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);
} }
ACPI_EXPORT_SYMBOL(acpi_unload_table_id) 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_native_uint i;
acpi_native_uint j;
ACPI_FUNCTION_TRACE(acpi_unload_table); acpi_status status;
/* Parameter validation */
if (table_type > ACPI_TABLE_ID_MAX) { /*
return_ACPI_STATUS(AE_BAD_PARAMETER); * 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;
} }
/* Find all tables of the requested type */ if (++j < instance) {
continue;
table_desc = acpi_gbl_table_lists[table_type].next;
if (!table_desc) {
return_ACPI_STATUS(AE_NOT_EXIST);
} }
while (table_desc) { status =
/* acpi_tb_verify_table(&acpi_gbl_root_table_list.tables[i]);
* Delete all namespace objects owned by this table. Note that these if (ACPI_SUCCESS(status)) {
* objects can appear anywhere in the namespace by virtue of the AML *out_table = acpi_gbl_root_table_list.tables[i].pointer;
* "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;
} }
/* Delete (or unmap) all tables of this type */ return (status);
}
acpi_tb_delete_tables_by_type(table_type); return (AE_NOT_FOUND);
return_ACPI_STATUS(AE_OK);
} }
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 * PARAMETERS: table_index - Table index
* Instance - the non zero instance of the table, allows * Table - Where the pointer to the table is returned
* 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
* *
* DESCRIPTION: This function is called to get an ACPI table header. The caller * RETURN: Status and pointer to the table
* supplies an pointer to a data area sufficient to contain an ACPI
* struct acpi_table_header structure.
* *
* The header contains a length field that can be used to determine * DESCRIPTION: Obtain a table by an index into the global table list.
* 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.
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_status
acpi_get_table_header(acpi_table_type table_type, acpi_get_table_by_index(acpi_native_uint table_index,
u32 instance, struct acpi_table_header *out_table_header) struct acpi_table_header ** table)
{ {
struct acpi_table_header *tbl_ptr;
acpi_status status; acpi_status status;
ACPI_FUNCTION_TRACE(acpi_get_table_header); ACPI_FUNCTION_TRACE(acpi_get_table_by_index);
if ((instance == 0) || (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
(table_type == ACPI_TABLE_ID_RSDP) || (!out_table_header)) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Check the table type and instance */ /* Validate index */
if ((table_type > ACPI_TABLE_ID_MAX) || if (table_index >= acpi_gbl_root_table_list.count) {
(ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags) && (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
instance > 1)) {
return_ACPI_STATUS(AE_BAD_PARAMETER); return_ACPI_STATUS(AE_BAD_PARAMETER);
} }
/* Get a pointer to the entire table */ if (!acpi_gbl_root_table_list.tables[table_index].pointer) {
/* Table is not mapped, map it */
status = acpi_tb_get_table_ptr(table_type, instance, &tbl_ptr); status =
acpi_tb_verify_table(&acpi_gbl_root_table_list.
tables[table_index]);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
/* The function will return a NULL pointer if the table is not loaded */
if (tbl_ptr == NULL) {
return_ACPI_STATUS(AE_NOT_EXIST);
} }
/* Copy the header to the caller's buffer */ *table = acpi_gbl_root_table_list.tables[table_index].pointer;
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
ACPI_MEMCPY(ACPI_CAST_PTR(void, out_table_header), return_ACPI_STATUS(AE_OK);
ACPI_CAST_PTR(void, tbl_ptr),
sizeof(struct acpi_table_header));
return_ACPI_STATUS(status);
} }
ACPI_EXPORT_SYMBOL(acpi_get_table_header) ACPI_EXPORT_SYMBOL(acpi_get_table_by_index)
#endif /* ACPI_FUTURE_USAGE */
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_get_table * FUNCTION: acpi_tb_load_namespace
* *
* PARAMETERS: table_type - one of the defined table types * PARAMETERS: None
* 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
* *
* RETURN: Status * RETURN: Status
* *
* DESCRIPTION: This function is called to get an ACPI table. The caller * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in
* supplies an out_buffer large enough to contain the entire ACPI * the RSDT/XSDT.
* 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.
* *
******************************************************************************/ ******************************************************************************/
acpi_status static acpi_status acpi_tb_load_namespace(void)
acpi_get_table(acpi_table_type table_type,
u32 instance, struct acpi_buffer *ret_buffer)
{ {
struct acpi_table_header *tbl_ptr;
acpi_status status; 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)) { * Find DSDT table
return_ACPI_STATUS(status); */
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_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)) {
/* A valid DSDT is required */
if ((table_type > ACPI_TABLE_ID_MAX) || status = AE_NO_ACPI_TABLES;
(ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags) && goto unlock_and_exit;
instance > 1)) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
} }
/* 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)) { if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
/* /*
* acpi_tb_get_table_ptr will return a NULL pointer if the * Load any SSDT or PSDT tables. Note: Loop leaves tables locked
* table is not loaded.
*/ */
if (tbl_ptr == NULL) { (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
return_ACPI_STATUS(AE_NOT_EXIST); 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;
} }
/* Get the table length */ /* Ignore errors while loading tables, get as many as possible */
if (table_type == ACPI_TABLE_ID_RSDP) {
/* RSD PTR is the only "table" without a header */ (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
(void)acpi_ns_load_table(i, acpi_gbl_root_node);
table_length = sizeof(struct rsdp_descriptor); (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
} else {
table_length = (acpi_size) tbl_ptr->length;
} }
/* Validate/Allocate/Clear caller buffer */ ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI Tables successfully acquired\n"));
status = acpi_ut_initialize_buffer(ret_buffer, table_length); unlock_and_exit:
if (ACPI_FAILURE(status)) { (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
/* Copy the table to the buffer */ /*******************************************************************************
*
* FUNCTION: acpi_load_tables
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Load the ACPI tables from the RSDT/XSDT
*
******************************************************************************/
acpi_status acpi_load_tables(void)
{
acpi_status status;
ACPI_MEMCPY(ACPI_CAST_PTR(void, ret_buffer->pointer), ACPI_FUNCTION_TRACE(acpi_load_tables);
ACPI_CAST_PTR(void, tbl_ptr), table_length);
return_ACPI_STATUS(AE_OK); /*
* Load the namespace from the tables
*/
status = acpi_tb_load_namespace();
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"While loading namespace from ACPI tables"));
}
return_ACPI_STATUS(status);
} }
ACPI_EXPORT_SYMBOL(acpi_get_table) ACPI_EXPORT_SYMBOL(acpi_load_tables)
...@@ -48,11 +48,10 @@ ...@@ -48,11 +48,10 @@
ACPI_MODULE_NAME("tbxfroot") ACPI_MODULE_NAME("tbxfroot")
/* Local prototypes */ /* Local prototypes */
static acpi_status
acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags);
static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length); static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length);
static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp);
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_tb_validate_rsdp * FUNCTION: acpi_tb_validate_rsdp
...@@ -65,14 +64,18 @@ static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length); ...@@ -65,14 +64,18 @@ static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length);
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_tb_validate_rsdp(struct rsdp_descriptor *rsdp) static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
{ {
ACPI_FUNCTION_ENTRY(); ACPI_FUNCTION_ENTRY();
/* /*
* The signature and checksum must both be correct * The signature and checksum must both be correct
*
* Note: Sometimes there exists more than one RSDP in memory; the valid
* RSDP has a valid checksum, all others have an invalid checksum.
*/ */
if (ACPI_STRNCMP((char *)rsdp, RSDP_SIG, sizeof(RSDP_SIG) - 1) != 0) { if (ACPI_STRNCMP((char *)rsdp, ACPI_SIG_RSDP, sizeof(ACPI_SIG_RSDP) - 1)
!= 0) {
/* Nope, BAD Signature */ /* Nope, BAD Signature */
...@@ -81,394 +84,27 @@ acpi_status acpi_tb_validate_rsdp(struct rsdp_descriptor *rsdp) ...@@ -81,394 +84,27 @@ acpi_status acpi_tb_validate_rsdp(struct rsdp_descriptor *rsdp)
/* Check the standard checksum */ /* Check the standard checksum */
if (acpi_tb_sum_table(rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) { if (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) {
return (AE_BAD_CHECKSUM); return (AE_BAD_CHECKSUM);
} }
/* Check extended checksum if table version >= 2 */ /* Check extended checksum if table version >= 2 */
if ((rsdp->revision >= 2) && if ((rsdp->revision >= 2) &&
(acpi_tb_sum_table(rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) { (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) {
return (AE_BAD_CHECKSUM); return (AE_BAD_CHECKSUM);
} }
return (AE_OK); return (AE_OK);
} }
/*******************************************************************************
*
* FUNCTION: acpi_tb_find_table
*
* PARAMETERS: Signature - String with ACPI table signature
* oem_id - String with the table OEM ID
* oem_table_id - String with the OEM Table ID
* table_ptr - Where the table pointer is returned
*
* RETURN: Status
*
* DESCRIPTION: Find an ACPI table (in the RSDT/XSDT) that matches the
* Signature, OEM ID and OEM Table ID.
*
******************************************************************************/
acpi_status
acpi_tb_find_table(char *signature,
char *oem_id,
char *oem_table_id, struct acpi_table_header ** table_ptr)
{
acpi_status status;
struct acpi_table_header *table;
ACPI_FUNCTION_TRACE(tb_find_table);
/* Validate string lengths */
if ((ACPI_STRLEN(signature) > ACPI_NAME_SIZE) ||
(ACPI_STRLEN(oem_id) > sizeof(table->oem_id)) ||
(ACPI_STRLEN(oem_table_id) > sizeof(table->oem_table_id))) {
return_ACPI_STATUS(AE_AML_STRING_LIMIT);
}
if (ACPI_COMPARE_NAME(signature, DSDT_SIG)) {
/*
* The DSDT pointer is contained in the FADT, not the RSDT.
* This code should suffice, because the only code that would perform
* a "find" on the DSDT is the data_table_region() AML opcode -- in
* which case, the DSDT is guaranteed to be already loaded.
* If this becomes insufficient, the FADT will have to be found first.
*/
if (!acpi_gbl_DSDT) {
return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
table = acpi_gbl_DSDT;
} else {
/* Find the table */
status = acpi_get_firmware_table(signature, 1,
ACPI_LOGICAL_ADDRESSING,
&table);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
/* Check oem_id and oem_table_id */
if ((oem_id[0] &&
ACPI_STRNCMP(oem_id, table->oem_id,
sizeof(table->oem_id))) ||
(oem_table_id[0] &&
ACPI_STRNCMP(oem_table_id, table->oem_table_id,
sizeof(table->oem_table_id)))) {
return_ACPI_STATUS(AE_AML_NAME_NOT_FOUND);
}
ACPI_DEBUG_PRINT((ACPI_DB_TABLES, "Found table [%4.4s]\n",
table->signature));
*table_ptr = table;
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_get_firmware_table
*
* PARAMETERS: Signature - Any ACPI table signature
* Instance - the non zero instance of the table, allows
* support for multiple tables of the same type
* Flags - Physical/Virtual support
* table_pointer - Where a buffer containing the table is
* returned
*
* RETURN: Status
*
* DESCRIPTION: This function is called to get an ACPI table. A buffer is
* allocated for the table and returned in table_pointer.
* This table will be a complete table including the header.
*
******************************************************************************/
acpi_status
acpi_get_firmware_table(acpi_string signature,
u32 instance,
u32 flags, struct acpi_table_header **table_pointer)
{
acpi_status status;
struct acpi_pointer address;
struct acpi_table_header *header = NULL;
struct acpi_table_desc *table_info = NULL;
struct acpi_table_desc *rsdt_info;
u32 table_count;
u32 i;
u32 j;
ACPI_FUNCTION_TRACE(acpi_get_firmware_table);
/*
* Ensure that at least the table manager is initialized. We don't
* require that the entire ACPI subsystem is up for this interface.
* If we have a buffer, we must have a length too
*/
if ((instance == 0) || (!signature) || (!table_pointer)) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Ensure that we have a RSDP */
if (!acpi_gbl_RSDP) {
/* Get the RSDP */
status = acpi_os_get_root_pointer(flags, &address);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "RSDP not found\n"));
return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
/* Map and validate the RSDP */
if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) {
status = acpi_os_map_memory(address.pointer.physical,
sizeof(struct
rsdp_descriptor),
(void *)&acpi_gbl_RSDP);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
} else {
acpi_gbl_RSDP = address.pointer.logical;
}
/* The RDSP signature and checksum must both be correct */
status = acpi_tb_validate_rsdp(acpi_gbl_RSDP);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
/* Get the RSDT address via the RSDP */
acpi_tb_get_rsdt_address(&address);
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"RSDP located at %p, RSDT physical=%8.8X%8.8X\n",
acpi_gbl_RSDP,
ACPI_FORMAT_UINT64(address.pointer.value)));
/* Insert processor_mode flags */
address.pointer_type |= flags;
/* Get and validate the RSDT */
rsdt_info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_table_desc));
if (!rsdt_info) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
status = acpi_tb_get_table(&address, rsdt_info);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
status = acpi_tb_validate_rsdt(rsdt_info->pointer);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
/* Allocate a scratch table header and table descriptor */
header = ACPI_ALLOCATE(sizeof(struct acpi_table_header));
if (!header) {
status = AE_NO_MEMORY;
goto cleanup;
}
table_info = ACPI_ALLOCATE(sizeof(struct acpi_table_desc));
if (!table_info) {
status = AE_NO_MEMORY;
goto cleanup;
}
/* Get the number of table pointers within the RSDT */
table_count =
acpi_tb_get_table_count(acpi_gbl_RSDP, rsdt_info->pointer);
address.pointer_type = acpi_gbl_table_flags | flags;
/*
* Search the RSDT/XSDT for the correct instance of the
* requested table
*/
for (i = 0, j = 0; i < table_count; i++) {
/*
* Get the next table pointer, handle RSDT vs. XSDT
* RSDT pointers are 32 bits, XSDT pointers are 64 bits
*/
if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
address.pointer.value =
(ACPI_CAST_PTR
(struct rsdt_descriptor,
rsdt_info->pointer))->table_offset_entry[i];
} else {
address.pointer.value =
(ACPI_CAST_PTR
(struct xsdt_descriptor,
rsdt_info->pointer))->table_offset_entry[i];
}
/* Get the table header */
status = acpi_tb_get_table_header(&address, header);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
/* Compare table signatures and table instance */
if (ACPI_COMPARE_NAME(header->signature, signature)) {
/* An instance of the table was found */
j++;
if (j >= instance) {
/* Found the correct instance, get the entire table */
status =
acpi_tb_get_table_body(&address, header,
table_info);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
*table_pointer = table_info->pointer;
goto cleanup;
}
}
}
/* Did not find the table */
status = AE_NOT_EXIST;
cleanup:
if (rsdt_info->pointer) {
acpi_os_unmap_memory(rsdt_info->pointer,
(acpi_size) rsdt_info->pointer->length);
}
ACPI_FREE(rsdt_info);
if (header) {
ACPI_FREE(header);
}
if (table_info) {
ACPI_FREE(table_info);
}
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_get_firmware_table)
/* TBD: Move to a new file */
#if ACPI_MACHINE_WIDTH != 16 #if ACPI_MACHINE_WIDTH != 16
/*******************************************************************************
*
* FUNCTION: acpi_find_root_pointer
*
* PARAMETERS: Flags - Logical/Physical addressing
* rsdp_address - Where to place the RSDP address
*
* RETURN: Status, Physical address of the RSDP
*
* DESCRIPTION: Find the RSDP
*
******************************************************************************/
acpi_status acpi_find_root_pointer(u32 flags, struct acpi_pointer *rsdp_address)
{
struct acpi_table_desc table_info;
acpi_status status;
ACPI_FUNCTION_TRACE(acpi_find_root_pointer);
/* Get the RSDP */
status = acpi_tb_find_rsdp(&table_info, flags);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"RSDP structure not found - Flags=%X", flags));
return_ACPI_STATUS(AE_NO_ACPI_TABLES);
}
rsdp_address->pointer_type = ACPI_PHYSICAL_POINTER;
rsdp_address->pointer.physical = table_info.physical_address;
return_ACPI_STATUS(AE_OK);
}
ACPI_EXPORT_SYMBOL(acpi_find_root_pointer)
/*******************************************************************************
*
* FUNCTION: acpi_tb_scan_memory_for_rsdp
*
* PARAMETERS: start_address - Starting pointer for search
* Length - Maximum length to search
*
* RETURN: Pointer to the RSDP if found, otherwise NULL.
*
* DESCRIPTION: Search a block of memory for the RSDP signature
*
******************************************************************************/
static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length)
{
acpi_status status;
u8 *mem_rover;
u8 *end_address;
ACPI_FUNCTION_TRACE(tb_scan_memory_for_rsdp);
end_address = start_address + length;
/* Search from given start address for the requested length */
for (mem_rover = start_address; mem_rover < end_address;
mem_rover += ACPI_RSDP_SCAN_STEP) {
/* The RSDP signature and checksum must both be correct */
status =
acpi_tb_validate_rsdp(ACPI_CAST_PTR
(struct rsdp_descriptor, mem_rover));
if (ACPI_SUCCESS(status)) {
/* Sig and checksum valid, we have found a real RSDP */
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"RSDP located at physical address %p\n",
mem_rover));
return_PTR(mem_rover);
}
/* No sig match or bad checksum, keep searching */
}
/* Searched entire block, no RSDP was found */
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Searched entire block from %p, valid RSDP was not found\n",
start_address));
return_PTR(NULL);
}
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_tb_find_rsdp * FUNCTION: acpi_tb_find_rsdp
* *
* PARAMETERS: table_info - Where the table info is returned * PARAMETERS: table_address - Where the table pointer is returned
* Flags - Current memory mode (logical vs.
* physical addressing)
* *
* RETURN: Status, RSDP physical address * RETURN: Status, RSDP physical address
* *
...@@ -484,34 +120,25 @@ static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length) ...@@ -484,34 +120,25 @@ static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length)
* *
******************************************************************************/ ******************************************************************************/
static acpi_status acpi_status acpi_find_root_pointer(acpi_native_uint * table_address)
acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags)
{ {
u8 *table_ptr; u8 *table_ptr;
u8 *mem_rover; u8 *mem_rover;
u32 physical_address; u32 physical_address;
acpi_status status;
ACPI_FUNCTION_TRACE(tb_find_rsdp);
/* ACPI_FUNCTION_TRACE(acpi_find_root_pointer);
* Scan supports either logical addressing or physical addressing
*/
if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) {
/* 1a) Get the location of the Extended BIOS Data Area (EBDA) */ /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */
status = acpi_os_map_memory((acpi_physical_address) table_ptr = acpi_os_map_memory((acpi_physical_address)
ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LOCATION,
ACPI_EBDA_PTR_LENGTH, ACPI_EBDA_PTR_LENGTH);
(void *)&table_ptr); if (!table_ptr) {
if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO, ACPI_ERROR((AE_INFO,
"Could not map memory at %8.8X for length %X", "Could not map memory at %8.8X for length %X",
ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH));
ACPI_EBDA_PTR_LENGTH));
return_ACPI_STATUS(status); return_ACPI_STATUS(AE_NO_MEMORY);
} }
ACPI_MOVE_16_TO_32(&physical_address, table_ptr); ACPI_MOVE_16_TO_32(&physical_address, table_ptr);
...@@ -528,20 +155,19 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags) ...@@ -528,20 +155,19 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags)
* 1b) Search EBDA paragraphs (EBDA is required to be a * 1b) Search EBDA paragraphs (EBDA is required to be a
* minimum of 1_k length) * minimum of 1_k length)
*/ */
status = acpi_os_map_memory((acpi_physical_address) table_ptr = acpi_os_map_memory((acpi_native_uint)
physical_address, physical_address,
ACPI_EBDA_WINDOW_SIZE, ACPI_EBDA_WINDOW_SIZE);
(void *)&table_ptr); if (!table_ptr) {
if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO, ACPI_ERROR((AE_INFO,
"Could not map memory at %8.8X for length %X", "Could not map memory at %8.8X for length %X",
physical_address, physical_address, ACPI_EBDA_WINDOW_SIZE));
ACPI_EBDA_WINDOW_SIZE));
return_ACPI_STATUS(status); return_ACPI_STATUS(AE_NO_MEMORY);
} }
mem_rover = acpi_tb_scan_memory_for_rsdp(table_ptr, mem_rover =
acpi_tb_scan_memory_for_rsdp(table_ptr,
ACPI_EBDA_WINDOW_SIZE); ACPI_EBDA_WINDOW_SIZE);
acpi_os_unmap_memory(table_ptr, ACPI_EBDA_WINDOW_SIZE); acpi_os_unmap_memory(table_ptr, ACPI_EBDA_WINDOW_SIZE);
...@@ -552,8 +178,7 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags) ...@@ -552,8 +178,7 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags)
physical_address += physical_address +=
(u32) ACPI_PTR_DIFF(mem_rover, table_ptr); (u32) ACPI_PTR_DIFF(mem_rover, table_ptr);
table_info->physical_address = *table_address = physical_address;
(acpi_physical_address) physical_address;
return_ACPI_STATUS(AE_OK); return_ACPI_STATUS(AE_OK);
} }
} }
...@@ -561,23 +186,21 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags) ...@@ -561,23 +186,21 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags)
/* /*
* 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh
*/ */
status = acpi_os_map_memory((acpi_physical_address) table_ptr = acpi_os_map_memory((acpi_physical_address)
ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_BASE,
ACPI_HI_RSDP_WINDOW_SIZE, ACPI_HI_RSDP_WINDOW_SIZE);
(void *)&table_ptr);
if (ACPI_FAILURE(status)) { if (!table_ptr) {
ACPI_ERROR((AE_INFO, ACPI_ERROR((AE_INFO,
"Could not map memory at %8.8X for length %X", "Could not map memory at %8.8X for length %X",
ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_BASE,
ACPI_HI_RSDP_WINDOW_SIZE)); ACPI_HI_RSDP_WINDOW_SIZE));
return_ACPI_STATUS(status); return_ACPI_STATUS(AE_NO_MEMORY);
} }
mem_rover = mem_rover =
acpi_tb_scan_memory_for_rsdp(table_ptr, acpi_tb_scan_memory_for_rsdp(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
ACPI_HI_RSDP_WINDOW_SIZE);
acpi_os_unmap_memory(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE); acpi_os_unmap_memory(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
if (mem_rover) { if (mem_rover) {
...@@ -588,62 +211,69 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags) ...@@ -588,62 +211,69 @@ acpi_tb_find_rsdp(struct acpi_table_desc *table_info, u32 flags)
(ACPI_HI_RSDP_WINDOW_BASE + (ACPI_HI_RSDP_WINDOW_BASE +
ACPI_PTR_DIFF(mem_rover, table_ptr)); ACPI_PTR_DIFF(mem_rover, table_ptr));
table_info->physical_address = *table_address = physical_address;
(acpi_physical_address) physical_address;
return_ACPI_STATUS(AE_OK); return_ACPI_STATUS(AE_OK);
} }
}
/* /* A valid RSDP was not found */
* Physical addressing
*/
else {
/* 1a) Get the location of the EBDA */
ACPI_MOVE_16_TO_32(&physical_address, ACPI_EBDA_PTR_LOCATION); ACPI_ERROR((AE_INFO, "A valid RSDP was not found"));
physical_address <<= 4; /* Convert segment to physical address */ return_ACPI_STATUS(AE_NOT_FOUND);
}
/* EBDA present? */ ACPI_EXPORT_SYMBOL(acpi_find_root_pointer)
if (physical_address > 0x400) { /*******************************************************************************
/* *
* 1b) Search EBDA paragraphs (EBDA is required to be a minimum of * FUNCTION: acpi_tb_scan_memory_for_rsdp
* 1_k length) *
*/ * PARAMETERS: start_address - Starting pointer for search
mem_rover = * Length - Maximum length to search
acpi_tb_scan_memory_for_rsdp(ACPI_PHYSADDR_TO_PTR *
(physical_address), * RETURN: Pointer to the RSDP if found, otherwise NULL.
ACPI_EBDA_WINDOW_SIZE); *
if (mem_rover) { * DESCRIPTION: Search a block of memory for the RSDP signature
*
******************************************************************************/
static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length)
{
acpi_status status;
u8 *mem_rover;
u8 *end_address;
/* Return the physical address */ ACPI_FUNCTION_TRACE(tb_scan_memory_for_rsdp);
table_info->physical_address = end_address = start_address + length;
ACPI_TO_INTEGER(mem_rover);
return_ACPI_STATUS(AE_OK);
}
}
/* 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh */ /* Search from given start address for the requested length */
mem_rover = for (mem_rover = start_address; mem_rover < end_address;
acpi_tb_scan_memory_for_rsdp(ACPI_PHYSADDR_TO_PTR mem_rover += ACPI_RSDP_SCAN_STEP) {
(ACPI_HI_RSDP_WINDOW_BASE),
ACPI_HI_RSDP_WINDOW_SIZE);
if (mem_rover) {
/* Found it, return the physical address */ /* The RSDP signature and checksum must both be correct */
table_info->physical_address = status =
ACPI_TO_INTEGER(mem_rover); acpi_tb_validate_rsdp(ACPI_CAST_PTR
return_ACPI_STATUS(AE_OK); (struct acpi_table_rsdp, mem_rover));
if (ACPI_SUCCESS(status)) {
/* Sig and checksum valid, we have found a real RSDP */
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"RSDP located at physical address %p\n",
mem_rover));
return_PTR(mem_rover);
} }
/* No sig match or bad checksum, keep searching */
} }
/* A valid RSDP was not found */ /* Searched entire block, no RSDP was found */
ACPI_ERROR((AE_INFO, "No valid RSDP was found")); ACPI_DEBUG_PRINT((ACPI_DB_INFO,
return_ACPI_STATUS(AE_NOT_FOUND); "Searched entire block from %p, valid RSDP was not found\n",
start_address));
return_PTR(NULL);
} }
#endif #endif
...@@ -46,8 +46,9 @@ ...@@ -46,8 +46,9 @@
#include <acpi/acpi.h> #include <acpi/acpi.h>
#include <acpi/acnamesp.h> #include <acpi/acnamesp.h>
ACPI_EXPORT_SYMBOL(acpi_gbl_FADT)
#define _COMPONENT ACPI_UTILITIES #define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("utglobal") ACPI_MODULE_NAME("utglobal")
/******************************************************************************* /*******************************************************************************
* *
...@@ -280,53 +281,6 @@ char acpi_ut_hex_to_ascii_char(acpi_integer integer, u32 position) ...@@ -280,53 +281,6 @@ char acpi_ut_hex_to_ascii_char(acpi_integer integer, u32 position)
return (acpi_gbl_hex_to_ascii[(integer >> position) & 0xF]); return (acpi_gbl_hex_to_ascii[(integer >> position) & 0xF]);
} }
/*******************************************************************************
*
* Table name globals
*
* NOTE: This table includes ONLY the ACPI tables that the subsystem consumes.
* it is NOT an exhaustive list of all possible ACPI tables. All ACPI tables
* that are not used by the subsystem are simply ignored.
*
* Do NOT add any table to this list that is not consumed directly by this
* subsystem (No MADT, ECDT, SBST, etc.)
*
******************************************************************************/
struct acpi_table_list acpi_gbl_table_lists[ACPI_TABLE_ID_MAX + 1];
struct acpi_table_support acpi_gbl_table_data[ACPI_TABLE_ID_MAX + 1] = {
/*********** Name, Signature, Global typed pointer Signature size, Type How many allowed?, Contains valid AML? */
/* RSDP 0 */ {RSDP_NAME, RSDP_SIG, NULL, sizeof(RSDP_SIG) - 1,
ACPI_TABLE_ROOT | ACPI_TABLE_SINGLE}
,
/* DSDT 1 */ {DSDT_SIG, DSDT_SIG, (void *)&acpi_gbl_DSDT,
sizeof(DSDT_SIG) - 1,
ACPI_TABLE_SECONDARY | ACPI_TABLE_SINGLE |
ACPI_TABLE_EXECUTABLE}
,
/* FADT 2 */ {FADT_SIG, FADT_SIG, (void *)&acpi_gbl_FADT,
sizeof(FADT_SIG) - 1,
ACPI_TABLE_PRIMARY | ACPI_TABLE_SINGLE}
,
/* FACS 3 */ {FACS_SIG, FACS_SIG, (void *)&acpi_gbl_FACS,
sizeof(FACS_SIG) - 1,
ACPI_TABLE_SECONDARY | ACPI_TABLE_SINGLE}
,
/* PSDT 4 */ {PSDT_SIG, PSDT_SIG, NULL, sizeof(PSDT_SIG) - 1,
ACPI_TABLE_PRIMARY | ACPI_TABLE_MULTIPLE |
ACPI_TABLE_EXECUTABLE}
,
/* SSDT 5 */ {SSDT_SIG, SSDT_SIG, NULL, sizeof(SSDT_SIG) - 1,
ACPI_TABLE_PRIMARY | ACPI_TABLE_MULTIPLE |
ACPI_TABLE_EXECUTABLE}
,
/* XSDT 6 */ {XSDT_SIG, XSDT_SIG, NULL, sizeof(RSDT_SIG) - 1,
ACPI_TABLE_ROOT | ACPI_TABLE_SINGLE}
,
};
/****************************************************************************** /******************************************************************************
* *
* Event and Hardware globals * Event and Hardware globals
...@@ -751,13 +705,6 @@ void acpi_ut_init_globals(void) ...@@ -751,13 +705,6 @@ void acpi_ut_init_globals(void)
return; return;
} }
/* ACPI table structure */
for (i = 0; i < (ACPI_TABLE_ID_MAX + 1); i++) {
acpi_gbl_table_lists[i].next = NULL;
acpi_gbl_table_lists[i].count = 0;
}
/* Mutex locked flags */ /* Mutex locked flags */
for (i = 0; i < ACPI_NUM_MUTEX; i++) { for (i = 0; i < ACPI_NUM_MUTEX; i++) {
...@@ -784,14 +731,6 @@ void acpi_ut_init_globals(void) ...@@ -784,14 +731,6 @@ void acpi_ut_init_globals(void)
acpi_gbl_exception_handler = NULL; acpi_gbl_exception_handler = NULL;
acpi_gbl_init_handler = NULL; acpi_gbl_init_handler = NULL;
/* Global "typed" ACPI table pointers */
acpi_gbl_RSDP = NULL;
acpi_gbl_XSDT = NULL;
acpi_gbl_FACS = NULL;
acpi_gbl_FADT = NULL;
acpi_gbl_DSDT = NULL;
/* Global Lock support */ /* Global Lock support */
acpi_gbl_global_lock_semaphore = NULL; acpi_gbl_global_lock_semaphore = NULL;
...@@ -801,8 +740,6 @@ void acpi_ut_init_globals(void) ...@@ -801,8 +740,6 @@ void acpi_ut_init_globals(void)
/* Miscellaneous variables */ /* Miscellaneous variables */
acpi_gbl_table_flags = ACPI_PHYSICAL_POINTER;
acpi_gbl_rsdp_original_location = 0;
acpi_gbl_cm_single_step = FALSE; acpi_gbl_cm_single_step = FALSE;
acpi_gbl_db_terminate_threads = FALSE; acpi_gbl_db_terminate_threads = FALSE;
acpi_gbl_shutdown = FALSE; acpi_gbl_shutdown = FALSE;
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include <acpi/acpi.h> #include <acpi/acpi.h>
#include <acpi/acnamesp.h> #include <acpi/acnamesp.h>
#include <acpi/acevents.h> #include <acpi/acevents.h>
#include <acpi/actables.h>
#define _COMPONENT ACPI_UTILITIES #define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("utinit") ACPI_MODULE_NAME("utinit")
...@@ -73,8 +74,8 @@ acpi_ut_fadt_register_error(char *register_name, u32 value, u8 offset) ...@@ -73,8 +74,8 @@ acpi_ut_fadt_register_error(char *register_name, u32 value, u8 offset)
{ {
ACPI_WARNING((AE_INFO, ACPI_WARNING((AE_INFO,
"Invalid FADT value %s=%X at offset %X FADT=%p", "Invalid FADT value %s=%X at offset %X in FADT=%p",
register_name, value, offset, acpi_gbl_FADT)); register_name, value, offset, &acpi_gbl_FADT));
} }
/****************************************************************************** /******************************************************************************
...@@ -96,62 +97,70 @@ acpi_status acpi_ut_validate_fadt(void) ...@@ -96,62 +97,70 @@ acpi_status acpi_ut_validate_fadt(void)
* Verify Fixed ACPI Description Table fields, * Verify Fixed ACPI Description Table fields,
* but don't abort on any problems, just display error * but don't abort on any problems, just display error
*/ */
if (acpi_gbl_FADT->pm1_evt_len < 4) { if (acpi_gbl_FADT.pm1_event_length < 4) {
acpi_ut_fadt_register_error("PM1_EVT_LEN", acpi_ut_fadt_register_error("PM1_EVT_LEN",
(u32) acpi_gbl_FADT->pm1_evt_len, (u32) acpi_gbl_FADT.
ACPI_FADT_OFFSET(pm1_evt_len)); pm1_event_length,
ACPI_FADT_OFFSET(pm1_event_length));
} }
if (!acpi_gbl_FADT->pm1_cnt_len) { if (!acpi_gbl_FADT.pm1_control_length) {
acpi_ut_fadt_register_error("PM1_CNT_LEN", 0, acpi_ut_fadt_register_error("PM1_CNT_LEN", 0,
ACPI_FADT_OFFSET(pm1_cnt_len)); ACPI_FADT_OFFSET
(pm1_control_length));
} }
if (!acpi_gbl_FADT->xpm1a_evt_blk.address) { if (!acpi_gbl_FADT.xpm1a_event_block.address) {
acpi_ut_fadt_register_error("X_PM1a_EVT_BLK", 0, acpi_ut_fadt_register_error("X_PM1a_EVT_BLK", 0,
ACPI_FADT_OFFSET(xpm1a_evt_blk. ACPI_FADT_OFFSET(xpm1a_event_block.
address)); address));
} }
if (!acpi_gbl_FADT->xpm1a_cnt_blk.address) { if (!acpi_gbl_FADT.xpm1a_control_block.address) {
acpi_ut_fadt_register_error("X_PM1a_CNT_BLK", 0, acpi_ut_fadt_register_error("X_PM1a_CNT_BLK", 0,
ACPI_FADT_OFFSET(xpm1a_cnt_blk. ACPI_FADT_OFFSET
address)); (xpm1a_control_block.address));
} }
if (!acpi_gbl_FADT->xpm_tmr_blk.address) { if (!acpi_gbl_FADT.xpm_timer_block.address) {
acpi_ut_fadt_register_error("X_PM_TMR_BLK", 0, acpi_ut_fadt_register_error("X_PM_TMR_BLK", 0,
ACPI_FADT_OFFSET(xpm_tmr_blk. ACPI_FADT_OFFSET(xpm_timer_block.
address)); address));
} }
if ((acpi_gbl_FADT->xpm2_cnt_blk.address && if ((acpi_gbl_FADT.xpm2_control_block.address &&
!acpi_gbl_FADT->pm2_cnt_len)) { !acpi_gbl_FADT.pm2_control_length)) {
acpi_ut_fadt_register_error("PM2_CNT_LEN", acpi_ut_fadt_register_error("PM2_CNT_LEN",
(u32) acpi_gbl_FADT->pm2_cnt_len, (u32) acpi_gbl_FADT.
ACPI_FADT_OFFSET(pm2_cnt_len)); pm2_control_length,
ACPI_FADT_OFFSET
(pm2_control_length));
} }
if (acpi_gbl_FADT->pm_tm_len < 4) { if (acpi_gbl_FADT.pm_timer_length < 4) {
acpi_ut_fadt_register_error("PM_TM_LEN", acpi_ut_fadt_register_error("PM_TM_LEN",
(u32) acpi_gbl_FADT->pm_tm_len, (u32) acpi_gbl_FADT.pm_timer_length,
ACPI_FADT_OFFSET(pm_tm_len)); ACPI_FADT_OFFSET(pm_timer_length));
} }
/* Length of GPE blocks must be a multiple of 2 */ /* Length of GPE blocks must be a multiple of 2 */
if (acpi_gbl_FADT->xgpe0_blk.address && if (acpi_gbl_FADT.xgpe0_block.address &&
(acpi_gbl_FADT->gpe0_blk_len & 1)) { (acpi_gbl_FADT.gpe0_block_length & 1)) {
acpi_ut_fadt_register_error("(x)GPE0_BLK_LEN", acpi_ut_fadt_register_error("(x)GPE0_BLK_LEN",
(u32) acpi_gbl_FADT->gpe0_blk_len, (u32) acpi_gbl_FADT.
ACPI_FADT_OFFSET(gpe0_blk_len)); gpe0_block_length,
ACPI_FADT_OFFSET
(gpe0_block_length));
} }
if (acpi_gbl_FADT->xgpe1_blk.address && if (acpi_gbl_FADT.xgpe1_block.address &&
(acpi_gbl_FADT->gpe1_blk_len & 1)) { (acpi_gbl_FADT.gpe1_block_length & 1)) {
acpi_ut_fadt_register_error("(x)GPE1_BLK_LEN", acpi_ut_fadt_register_error("(x)GPE1_BLK_LEN",
(u32) acpi_gbl_FADT->gpe1_blk_len, (u32) acpi_gbl_FADT.
ACPI_FADT_OFFSET(gpe1_blk_len)); gpe1_block_length,
ACPI_FADT_OFFSET
(gpe1_block_length));
} }
return (AE_OK); return (AE_OK);
...@@ -178,7 +187,6 @@ static void acpi_ut_terminate(void) ...@@ -178,7 +187,6 @@ static void acpi_ut_terminate(void)
ACPI_FUNCTION_TRACE(ut_terminate); ACPI_FUNCTION_TRACE(ut_terminate);
/* Free global tables, etc. */
/* Free global GPE blocks and related info structures */ /* Free global GPE blocks and related info structures */
gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head; gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head;
...@@ -239,6 +247,10 @@ void acpi_ut_subsystem_shutdown(void) ...@@ -239,6 +247,10 @@ void acpi_ut_subsystem_shutdown(void)
acpi_ns_terminate(); acpi_ns_terminate();
/* Delete the ACPI tables */
acpi_tb_terminate();
/* Close the globals */ /* Close the globals */
acpi_ut_terminate(); acpi_ut_terminate();
......
...@@ -67,9 +67,9 @@ u8 acpi_ut_is_aml_table(struct acpi_table_header *table) ...@@ -67,9 +67,9 @@ u8 acpi_ut_is_aml_table(struct acpi_table_header *table)
/* These are the only tables that contain executable AML */ /* These are the only tables that contain executable AML */
if (ACPI_COMPARE_NAME(table->signature, DSDT_SIG) || if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_DSDT) ||
ACPI_COMPARE_NAME(table->signature, PSDT_SIG) || ACPI_COMPARE_NAME(table->signature, ACPI_SIG_PSDT) ||
ACPI_COMPARE_NAME(table->signature, SSDT_SIG)) { ACPI_COMPARE_NAME(table->signature, ACPI_SIG_SSDT)) {
return (TRUE); return (TRUE);
} }
...@@ -418,7 +418,7 @@ u32 acpi_ut_dword_byte_swap(u32 value) ...@@ -418,7 +418,7 @@ u32 acpi_ut_dword_byte_swap(u32 value)
void acpi_ut_set_integer_width(u8 revision) void acpi_ut_set_integer_width(u8 revision)
{ {
if (revision <= 1) { if (revision < 2) {
/* 32-bit case */ /* 32-bit case */
......
...@@ -398,7 +398,6 @@ acpi_status acpi_get_system_info(struct acpi_buffer * out_buffer) ...@@ -398,7 +398,6 @@ acpi_status acpi_get_system_info(struct acpi_buffer * out_buffer)
{ {
struct acpi_system_info *info_ptr; struct acpi_system_info *info_ptr;
acpi_status status; acpi_status status;
u32 i;
ACPI_FUNCTION_TRACE(acpi_get_system_info); ACPI_FUNCTION_TRACE(acpi_get_system_info);
...@@ -431,9 +430,7 @@ acpi_status acpi_get_system_info(struct acpi_buffer * out_buffer) ...@@ -431,9 +430,7 @@ acpi_status acpi_get_system_info(struct acpi_buffer * out_buffer)
/* Timer resolution - 24 or 32 bits */ /* Timer resolution - 24 or 32 bits */
if (!acpi_gbl_FADT) { if (acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER) {
info_ptr->timer_resolution = 0;
} else if (acpi_gbl_FADT->tmr_val_ext == 0) {
info_ptr->timer_resolution = 24; info_ptr->timer_resolution = 24;
} else { } else {
info_ptr->timer_resolution = 32; info_ptr->timer_resolution = 32;
...@@ -449,13 +446,6 @@ acpi_status acpi_get_system_info(struct acpi_buffer * out_buffer) ...@@ -449,13 +446,6 @@ acpi_status acpi_get_system_info(struct acpi_buffer * out_buffer)
info_ptr->debug_layer = acpi_dbg_layer; info_ptr->debug_layer = acpi_dbg_layer;
info_ptr->debug_level = acpi_dbg_level; info_ptr->debug_level = acpi_dbg_level;
/* Current status of the ACPI tables, per table type */
info_ptr->num_table_types = ACPI_TABLE_ID_MAX + 1;
for (i = 0; i < (ACPI_TABLE_ID_MAX + 1); i++) {
info_ptr->table_info[i].count = acpi_gbl_table_lists[i].count;
}
return_ACPI_STATUS(AE_OK); return_ACPI_STATUS(AE_OK);
} }
......
...@@ -63,7 +63,7 @@ ...@@ -63,7 +63,7 @@
/* Current ACPICA subsystem version in YYYYMMDD format */ /* Current ACPICA subsystem version in YYYYMMDD format */
#define ACPI_CA_VERSION 0x20060721 #define ACPI_CA_VERSION 0x20060823
/* /*
* OS name, used for the _OS object. The _OS object is essentially obsolete, * OS name, used for the _OS object. The _OS object is essentially obsolete,
...@@ -115,6 +115,10 @@ ...@@ -115,6 +115,10 @@
#define ACPI_NUM_OWNERID_MASKS 8 #define ACPI_NUM_OWNERID_MASKS 8
/* Size of the root table array is increased by this increment */
#define ACPI_ROOT_TABLE_SIZE_INCREMENT 4
/****************************************************************************** /******************************************************************************
* *
* ACPI Specification constants (Do not change unless the specification changes) * ACPI Specification constants (Do not change unless the specification changes)
...@@ -152,6 +156,11 @@ ...@@ -152,6 +156,11 @@
#define ACPI_PATH_SEGMENT_LENGTH 5 /* 4 chars for name + 1 char for separator */ #define ACPI_PATH_SEGMENT_LENGTH 5 /* 4 chars for name + 1 char for separator */
#define ACPI_PATH_SEPARATOR '.' #define ACPI_PATH_SEPARATOR '.'
/* Sizes for ACPI table headers */
#define ACPI_OEM_ID_SIZE 6
#define ACPI_OEM_TABLE_ID_SIZE 8
/* Constants used in searching for the RSDP in low memory */ /* Constants used in searching for the RSDP in low memory */
#define ACPI_EBDA_PTR_LOCATION 0x0000040E /* Physical Address */ #define ACPI_EBDA_PTR_LOCATION 0x0000040E /* Physical Address */
......
...@@ -210,7 +210,7 @@ acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state); ...@@ -210,7 +210,7 @@ acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state);
* dsinit * dsinit
*/ */
acpi_status acpi_status
acpi_ds_initialize_objects(struct acpi_table_desc *table_desc, acpi_ds_initialize_objects(acpi_native_uint table_index,
struct acpi_namespace_node *start_node); struct acpi_namespace_node *start_node);
/* /*
......
...@@ -140,47 +140,23 @@ ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_leave_wake_gpes_disabled, TRUE); ...@@ -140,47 +140,23 @@ ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_leave_wake_gpes_disabled, TRUE);
****************************************************************************/ ****************************************************************************/
/* /*
* Table pointers. * acpi_gbl_root_table_list is the master list of ACPI tables found in the
* Although these pointers are somewhat redundant with the global acpi_table, * RSDT/XSDT.
* they are convenient because they are typed pointers.
* *
* These tables are single-table only; meaning that there can be at most one * acpi_gbl_FADT is a local copy of the FADT, converted to a common format.
* of each in the system. Each global points to the actual table.
*/ */
ACPI_EXTERN u32 acpi_gbl_table_flags; ACPI_EXTERN struct acpi_internal_rsdt acpi_gbl_root_table_list;
ACPI_EXTERN u32 acpi_gbl_rsdt_table_count; ACPI_EXTERN struct acpi_table_fadt acpi_gbl_FADT;
ACPI_EXTERN struct rsdp_descriptor *acpi_gbl_RSDP;
ACPI_EXTERN struct xsdt_descriptor *acpi_gbl_XSDT;
ACPI_EXTERN struct fadt_descriptor *acpi_gbl_FADT;
ACPI_EXTERN struct acpi_table_header *acpi_gbl_DSDT;
ACPI_EXTERN struct facs_descriptor *acpi_gbl_FACS;
ACPI_EXTERN struct acpi_common_facs acpi_gbl_common_fACS;
/*
* Since there may be multiple SSDTs and PSDTs, a single pointer is not
* sufficient; Therefore, there isn't one!
*/
/* The root table can be either an RSDT or an XSDT */
ACPI_EXTERN u8 acpi_gbl_root_table_type;
#define ACPI_TABLE_TYPE_RSDT 'R'
#define ACPI_TABLE_TYPE_XSDT 'X'
/* /*
* Handle both ACPI 1.0 and ACPI 2.0 Integer widths: * Handle both ACPI 1.0 and ACPI 2.0 Integer widths. The integer width is
* If we are executing a method that exists in a 32-bit ACPI table, * determined by the revision of the DSDT: If the DSDT revision is less than
* use only the lower 32 bits of the (internal) 64-bit Integer. * 2, use only the lower 32 bits of the internal 64-bit Integer.
*/ */
ACPI_EXTERN u8 acpi_gbl_integer_bit_width; ACPI_EXTERN u8 acpi_gbl_integer_bit_width;
ACPI_EXTERN u8 acpi_gbl_integer_byte_width; ACPI_EXTERN u8 acpi_gbl_integer_byte_width;
ACPI_EXTERN u8 acpi_gbl_integer_nybble_width; ACPI_EXTERN u8 acpi_gbl_integer_nybble_width;
/*
* ACPI Table info arrays
*/
extern struct acpi_table_list acpi_gbl_table_lists[ACPI_TABLE_ID_MAX + 1];
extern struct acpi_table_support acpi_gbl_table_data[ACPI_TABLE_ID_MAX + 1];
/***************************************************************************** /*****************************************************************************
* *
* Mutual exlusion within ACPICA subsystem * Mutual exlusion within ACPICA subsystem
......
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
#define ACPI_SERIALIZED 0xFF #define ACPI_SERIALIZED 0xFF
typedef u32 acpi_mutex_handle; typedef u32 acpi_mutex_handle;
#define ACPI_GLOBAL_LOCK (acpi_semaphore) (-1)
/* Total number of aml opcodes defined */ /* Total number of aml opcodes defined */
...@@ -79,8 +80,8 @@ union acpi_parse_object; ...@@ -79,8 +80,8 @@ union acpi_parse_object;
* table below also! * table below also!
*/ */
#define ACPI_MTX_INTERPRETER 0 /* AML Interpreter, main lock */ #define ACPI_MTX_INTERPRETER 0 /* AML Interpreter, main lock */
#define ACPI_MTX_TABLES 1 /* Data for ACPI tables */ #define ACPI_MTX_NAMESPACE 1 /* ACPI Namespace */
#define ACPI_MTX_NAMESPACE 2 /* ACPI Namespace */ #define ACPI_MTX_TABLES 2 /* Data for ACPI tables */
#define ACPI_MTX_EVENTS 3 /* Data for ACPI events */ #define ACPI_MTX_EVENTS 3 /* Data for ACPI events */
#define ACPI_MTX_CACHES 4 /* Internal caches, general purposes */ #define ACPI_MTX_CACHES 4 /* Internal caches, general purposes */
#define ACPI_MTX_MEMORY 5 /* Debug memory tracking lists */ #define ACPI_MTX_MEMORY 5 /* Debug memory tracking lists */
...@@ -218,25 +219,35 @@ struct acpi_namespace_node { ...@@ -218,25 +219,35 @@ struct acpi_namespace_node {
* ACPI Table Descriptor. One per ACPI table * ACPI Table Descriptor. One per ACPI table
*/ */
struct acpi_table_desc { struct acpi_table_desc {
struct acpi_table_desc *prev; acpi_physical_address address;
struct acpi_table_desc *next;
struct acpi_table_desc *installed_desc;
struct acpi_table_header *pointer; struct acpi_table_header *pointer;
u8 *aml_start; u32 length; /* Length fixed at 32 bits */
u64 physical_address; union acpi_name_union signature;
acpi_size length;
u32 aml_length;
acpi_owner_id owner_id; acpi_owner_id owner_id;
u8 type; u8 flags;
u8 allocation;
u8 loaded_into_namespace;
}; };
struct acpi_table_list { struct acpi_internal_rsdt {
struct acpi_table_desc *next; struct acpi_table_desc *tables;
u32 count; u32 count;
u32 size;
u8 flags;
}; };
/* Flags for both structs above */
#define ACPI_TABLE_ORIGIN_UNKNOWN (0)
#define ACPI_TABLE_ORIGIN_MAPPED (1)
#define ACPI_TABLE_ORIGIN_ALLOCATED (2)
#define ACPI_TABLE_ORIGIN_MASK (3)
#define ACPI_TABLE_FLAGS_LOADED (4)
#define ACPI_TABLE_FLAGS_ALLOW_RESIZE (8)
/* Predefined (fixed) table indexes */
#define ACPI_TABLE_INDEX_DSDT (0)
#define ACPI_TABLE_INDEX_FACS (1)
struct acpi_find_context { struct acpi_find_context {
char *search_for; char *search_for;
acpi_handle *list; acpi_handle *list;
......
...@@ -82,7 +82,7 @@ acpi_status acpi_ns_initialize_devices(void); ...@@ -82,7 +82,7 @@ acpi_status acpi_ns_initialize_devices(void);
acpi_status acpi_ns_load_namespace(void); acpi_status acpi_ns_load_namespace(void);
acpi_status acpi_status
acpi_ns_load_table(struct acpi_table_desc *table_desc, acpi_ns_load_table(acpi_native_uint table_index,
struct acpi_namespace_node *node); struct acpi_namespace_node *node);
/* /*
...@@ -106,11 +106,12 @@ struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type, ...@@ -106,11 +106,12 @@ struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type,
* nsparse - table parsing * nsparse - table parsing
*/ */
acpi_status acpi_status
acpi_ns_parse_table(struct acpi_table_desc *table_desc, acpi_ns_parse_table(acpi_native_uint table_index,
struct acpi_namespace_node *scope); struct acpi_namespace_node *start_node);
acpi_status acpi_status
acpi_ns_one_complete_parse(u8 pass_number, struct acpi_table_desc *table_desc); acpi_ns_one_complete_parse(acpi_native_uint pass_number,
acpi_native_uint table_index);
/* /*
* nsaccess - Top-level namespace access * nsaccess - Top-level namespace access
......
...@@ -85,7 +85,7 @@ acpi_status acpi_os_terminate(void); ...@@ -85,7 +85,7 @@ acpi_status acpi_os_terminate(void);
/* /*
* ACPI Table interfaces * ACPI Table interfaces
*/ */
acpi_status acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *address); acpi_physical_address acpi_os_get_root_pointer(void);
acpi_status acpi_status
acpi_os_predefined_override(const struct acpi_predefined_names *init_val, acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
...@@ -143,9 +143,7 @@ void acpi_os_release_mutex(acpi_mutex handle); ...@@ -143,9 +143,7 @@ void acpi_os_release_mutex(acpi_mutex handle);
*/ */
void *acpi_os_allocate(acpi_size size); void *acpi_os_allocate(acpi_size size);
acpi_status void __iomem *acpi_os_map_memory(acpi_physical_address where, acpi_native_uint length);
acpi_os_map_memory(acpi_physical_address physical_address,
acpi_size size, void __iomem ** logical_address);
void acpi_os_unmap_memory(void __iomem * logical_address, acpi_size size); void acpi_os_unmap_memory(void __iomem * logical_address, acpi_size size);
......
...@@ -51,6 +51,10 @@ ...@@ -51,6 +51,10 @@
/* /*
* Global interfaces * Global interfaces
*/ */
acpi_status
acpi_initialize_tables(struct acpi_table_desc *initial_storage,
u32 initial_table_count, u8 allow_resize);
acpi_status acpi_initialize_subsystem(void); acpi_status acpi_initialize_subsystem(void);
acpi_status acpi_enable_subsystem(u32 flags); acpi_status acpi_enable_subsystem(u32 flags);
...@@ -92,30 +96,28 @@ void acpi_free(void *address); ...@@ -92,30 +96,28 @@ void acpi_free(void *address);
/* /*
* ACPI table manipulation interfaces * ACPI table manipulation interfaces
*/ */
acpi_status acpi_status acpi_reallocate_root_table(void);
acpi_find_root_pointer(u32 flags, struct acpi_pointer *rsdp_address);
acpi_status acpi_find_root_pointer(acpi_native_uint * rsdp_address);
acpi_status acpi_load_tables(void); acpi_status acpi_load_tables(void);
acpi_status acpi_load_table(struct acpi_table_header *table_ptr); acpi_status acpi_load_table(struct acpi_table_header *table_ptr);
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);
#ifdef ACPI_FUTURE_USAGE
acpi_status acpi_unload_table(acpi_table_type table_type);
acpi_status acpi_status
acpi_get_table_header(acpi_table_type table_type, acpi_get_table_header(acpi_string signature,
u32 instance, struct acpi_table_header *out_table_header); acpi_native_uint instance,
#endif /* ACPI_FUTURE_USAGE */ struct acpi_table_header **out_table_header);
acpi_status acpi_status
acpi_get_table(acpi_table_type table_type, acpi_get_table(acpi_string signature,
u32 instance, struct acpi_buffer *ret_buffer); acpi_native_uint instance, struct acpi_table_header **out_table);
acpi_status acpi_status
acpi_get_firmware_table(acpi_string signature, acpi_get_table_by_index(acpi_native_uint table_index,
u32 instance, struct acpi_table_header **out_table);
u32 flags, struct acpi_table_header **table_pointer);
/* /*
* Namespace and name interfaces * Namespace and name interfaces
......
...@@ -139,7 +139,8 @@ struct acpi_init_walk_info { ...@@ -139,7 +139,8 @@ struct acpi_init_walk_info {
u16 buffer_init; u16 buffer_init;
u16 package_init; u16 package_init;
u16 object_count; u16 object_count;
struct acpi_table_desc *table_desc; acpi_owner_id owner_id;
acpi_native_uint table_index;
}; };
struct acpi_get_devices_info { struct acpi_get_devices_info {
......
...@@ -44,105 +44,62 @@ ...@@ -44,105 +44,62 @@
#ifndef __ACTABLES_H__ #ifndef __ACTABLES_H__
#define __ACTABLES_H__ #define __ACTABLES_H__
/* Used in acpi_tb_map_acpi_table for size parameter if table header is to be used */
#define SIZE_IN_HEADER 0
/*
* tbconvrt - Table conversion routines
*/
acpi_status acpi_tb_convert_to_xsdt(struct acpi_table_desc *table_info);
acpi_status acpi_tb_convert_table_fadt(void);
acpi_status acpi_tb_build_common_facs(struct acpi_table_desc *table_info);
u32
acpi_tb_get_table_count(struct rsdp_descriptor *RSDP,
struct acpi_table_header *RSDT);
/* /*
* tbget - Table "get" routines * tbfind - find ACPI table
*/ */
acpi_status acpi_status
acpi_tb_get_table(struct acpi_pointer *address, acpi_tb_find_table(char *signature,
struct acpi_table_desc *table_info); char *oem_id,
char *oem_table_id, acpi_native_uint * table_index);
acpi_status
acpi_tb_get_table_header(struct acpi_pointer *address,
struct acpi_table_header *return_header);
acpi_status
acpi_tb_get_table_body(struct acpi_pointer *address,
struct acpi_table_header *header,
struct acpi_table_desc *table_info);
acpi_status
acpi_tb_get_table_ptr(acpi_table_type table_type,
u32 instance, struct acpi_table_header **table_ptr_loc);
acpi_status acpi_tb_verify_rsdp(struct acpi_pointer *address);
void acpi_tb_get_rsdt_address(struct acpi_pointer *out_address);
acpi_status acpi_tb_validate_rsdt(struct acpi_table_header *table_ptr);
/* /*
* tbgetall - get multiple required tables * tbinstal - Table removal and deletion
*/ */
acpi_status acpi_tb_get_required_tables(void); acpi_status acpi_tb_resize_root_table_list(void);
/* acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc);
* tbinstall - Table installation
*/
acpi_status acpi_tb_install_table(struct acpi_table_desc *table_info);
acpi_status acpi_status
acpi_tb_recognize_table(struct acpi_table_desc *table_info, u8 search_type); acpi_tb_add_table(struct acpi_table_header *table,
acpi_native_uint * table_index);
acpi_status acpi_status
acpi_tb_init_table_descriptor(acpi_table_type table_type, acpi_tb_store_table(acpi_physical_address address,
struct acpi_table_desc *table_info); struct acpi_table_header *table,
u32 length, u8 flags, acpi_native_uint * table_index);
/* void acpi_tb_delete_table(acpi_native_uint table_index);
* tbremove - Table removal and deletion
*/
void acpi_tb_delete_all_tables(void);
void acpi_tb_delete_tables_by_type(acpi_table_type type); void acpi_tb_terminate(void);
void acpi_tb_delete_single_table(struct acpi_table_desc *table_desc); void acpi_tb_delete_namespace_by_owner(acpi_native_uint table_index);
struct acpi_table_desc *acpi_tb_uninstall_table(struct acpi_table_desc acpi_status acpi_tb_allocate_owner_id(acpi_native_uint table_index);
*table_desc);
acpi_status acpi_tb_release_owner_id(acpi_native_uint table_index);
/*
* tbxfroot - RSDP, RSDT utilities
*/
acpi_status acpi_status
acpi_tb_find_table(char *signature, acpi_tb_get_owner_id(acpi_native_uint table_index, acpi_owner_id * owner_id);
char *oem_id,
char *oem_table_id, struct acpi_table_header **table_ptr);
acpi_status acpi_tb_get_table_rsdt(void); u8 acpi_tb_is_table_loaded(acpi_native_uint table_index);
acpi_status acpi_tb_validate_rsdp(struct rsdp_descriptor *rsdp); void acpi_tb_set_table_loaded_flag(acpi_native_uint table_index, u8 is_loaded);
/* /*
* tbutils - common table utilities * tbutils - table manager utilities
*/ */
acpi_status acpi_tb_is_table_installed(struct acpi_table_desc *new_table_desc); void
acpi_tb_print_table_header(acpi_physical_address address,
struct acpi_table_header *header);
acpi_status u8 acpi_tb_checksum(u8 * buffer, acpi_native_uint length);
acpi_tb_verify_table_checksum(struct acpi_table_header *table_header);
u8 acpi_tb_sum_table(void *buffer, u32 length); void acpi_tb_convert_fadt(struct acpi_table_fadt *fadt);
u8 acpi_tb_generate_checksum(struct acpi_table_header *table); acpi_status acpi_tb_parse_root_table(struct acpi_table_rsdp *rsdp, u8 flags);
void acpi_tb_set_checksum(struct acpi_table_header *table); void *acpi_tb_map(acpi_physical_address address, u32 length, u32 flags);
acpi_status void acpi_tb_unmap(void *pointer, u32 length, u32 flags);
acpi_tb_validate_table_header(struct acpi_table_header *table_header);
#endif /* __ACTABLES_H__ */ #endif /* __ACTABLES_H__ */
...@@ -48,15 +48,15 @@ ...@@ -48,15 +48,15 @@
* Values for description table header signatures. Useful because they make * Values for description table header signatures. Useful because they make
* it more difficult to inadvertently type in the wrong signature. * it more difficult to inadvertently type in the wrong signature.
*/ */
#define DSDT_SIG "DSDT" /* Differentiated System Description Table */ #define ACPI_SIG_DSDT "DSDT" /* Differentiated System Description Table */
#define FADT_SIG "FACP" /* Fixed ACPI Description Table */ #define ACPI_SIG_FADT "FACP" /* Fixed ACPI Description Table */
#define FACS_SIG "FACS" /* Firmware ACPI Control Structure */ #define ACPI_SIG_FACS "FACS" /* Firmware ACPI Control Structure */
#define PSDT_SIG "PSDT" /* Persistent System Description Table */ #define ACPI_SIG_PSDT "PSDT" /* Persistent System Description Table */
#define RSDP_SIG "RSD PTR " /* Root System Description Pointer */ #define ACPI_SIG_RSDP "RSD PTR " /* Root System Description Pointer */
#define RSDT_SIG "RSDT" /* Root System Description Table */ #define ACPI_SIG_RSDT "RSDT" /* Root System Description Table */
#define XSDT_SIG "XSDT" /* Extended System Description Table */ #define ACPI_SIG_XSDT "XSDT" /* Extended System Description Table */
#define SSDT_SIG "SSDT" /* Secondary System Description Table */ #define ACPI_SIG_SSDT "SSDT" /* Secondary System Description Table */
#define RSDP_NAME "RSDP" #define ACPI_RSDP_NAME "RSDP"
/* /*
* All tables and structures must be byte-packed to match the ACPI * All tables and structures must be byte-packed to match the ACPI
...@@ -83,27 +83,29 @@ ...@@ -83,27 +83,29 @@
* *
******************************************************************************/ ******************************************************************************/
#define ACPI_TABLE_HEADER_DEF \
char signature[4]; /* ASCII table signature */\
u32 length; /* Length of table in bytes, including this header */\
u8 revision; /* ACPI Specification minor version # */\
u8 checksum; /* To make sum of entire table == 0 */\
char oem_id[6]; /* ASCII OEM identification */\
char oem_table_id[8]; /* ASCII OEM table identification */\
u32 oem_revision; /* OEM revision number */\
char asl_compiler_id[4]; /* ASCII ASL compiler vendor ID */\
u32 asl_compiler_revision; /* ASL compiler version */
struct acpi_table_header { struct acpi_table_header {
ACPI_TABLE_HEADER_DEF}; char signature[ACPI_NAME_SIZE]; /* ASCII table signature */
u32 length; /* Length of table in bytes, including this header */
u8 revision; /* ACPI Specification minor version # */
u8 checksum; /* To make sum of entire table == 0 */
char oem_id[ACPI_OEM_ID_SIZE]; /* ASCII OEM identification */
char oem_table_id[ACPI_OEM_TABLE_ID_SIZE]; /* ASCII OEM table identification */
u32 oem_revision; /* OEM revision number */
char asl_compiler_id[ACPI_NAME_SIZE]; /* ASCII ASL compiler vendor ID */
u32 asl_compiler_revision; /* ASL compiler version */
};
/* /*
* GAS - Generic Address Structure (ACPI 2.0+) * GAS - Generic Address Structure (ACPI 2.0+)
*
* Note: Since this structure is used in the ACPI tables, it is byte aligned.
* If misalignment is not supported, access to the Address field must be
* performed with care.
*/ */
struct acpi_generic_address { struct acpi_generic_address {
u8 address_space_id; /* Address space where struct or register exists */ u8 space_id; /* Address space where struct or register exists */
u8 register_bit_width; /* Size in bits of given register */ u8 bit_width; /* Size in bits of given register */
u8 register_bit_offset; /* Bit offset within the register */ u8 bit_offset; /* Bit offset within the register */
u8 access_width; /* Minimum Access size (ACPI 3.0) */ u8 access_width; /* Minimum Access size (ACPI 3.0) */
u64 address; /* 64-bit address of struct or register */ u64 address; /* 64-bit address of struct or register */
}; };
...@@ -114,10 +116,10 @@ struct acpi_generic_address { ...@@ -114,10 +116,10 @@ struct acpi_generic_address {
* *
******************************************************************************/ ******************************************************************************/
struct rsdp_descriptor { struct acpi_table_rsdp {
char signature[8]; /* ACPI signature, contains "RSD PTR " */ char signature[8]; /* ACPI signature, contains "RSD PTR " */
u8 checksum; /* ACPI 1.0 checksum */ u8 checksum; /* ACPI 1.0 checksum */
char oem_id[6]; /* OEM identification */ char oem_id[ACPI_OEM_ID_SIZE]; /* OEM identification */
u8 revision; /* Must be (0) for ACPI 1.0 or (2) for ACPI 2.0+ */ u8 revision; /* Must be (0) for ACPI 1.0 or (2) for ACPI 2.0+ */
u32 rsdt_physical_address; /* 32-bit physical address of the RSDT */ u32 rsdt_physical_address; /* 32-bit physical address of the RSDT */
u32 length; /* Table length in bytes, including header (ACPI 2.0+) */ u32 length; /* Table length in bytes, including header (ACPI 2.0+) */
...@@ -134,12 +136,14 @@ struct rsdp_descriptor { ...@@ -134,12 +136,14 @@ struct rsdp_descriptor {
* *
******************************************************************************/ ******************************************************************************/
struct rsdt_descriptor { struct acpi_table_rsdt {
ACPI_TABLE_HEADER_DEF u32 table_offset_entry[1]; /* Array of pointers to ACPI tables */ struct acpi_table_header header; /* Common ACPI table header */
u32 table_offset_entry[1]; /* Array of pointers to ACPI tables */
}; };
struct xsdt_descriptor { struct acpi_table_xsdt {
ACPI_TABLE_HEADER_DEF u64 table_offset_entry[1]; /* Array of pointers to ACPI tables */ struct acpi_table_header header; /* Common ACPI table header */
u64 table_offset_entry[1]; /* Array of pointers to ACPI tables */
}; };
/******************************************************************************* /*******************************************************************************
...@@ -148,36 +152,27 @@ struct xsdt_descriptor { ...@@ -148,36 +152,27 @@ struct xsdt_descriptor {
* *
******************************************************************************/ ******************************************************************************/
struct facs_descriptor { struct acpi_table_facs {
char signature[4]; /* ASCII table signature */ char signature[4]; /* ASCII table signature */
u32 length; /* Length of structure, in bytes */ u32 length; /* Length of structure, in bytes */
u32 hardware_signature; /* Hardware configuration signature */ u32 hardware_signature; /* Hardware configuration signature */
u32 firmware_waking_vector; /* 32-bit physical address of the Firmware Waking Vector */ u32 firmware_waking_vector; /* 32-bit physical address of the Firmware Waking Vector */
u32 global_lock; /* Global Lock for shared hardware resources */ u32 global_lock; /* Global Lock for shared hardware resources */
u32 flags;
/* Flags (32 bits) */
u8 S4bios_f:1; /* 00: S4BIOS support is present */
u8:7; /* 01-07: Reserved, must be zero */
u8 reserved1[3]; /* 08-31: Reserved, must be zero */
u64 xfirmware_waking_vector; /* 64-bit version of the Firmware Waking Vector (ACPI 2.0+) */ u64 xfirmware_waking_vector; /* 64-bit version of the Firmware Waking Vector (ACPI 2.0+) */
u8 version; /* Version of this table (ACPI 2.0+) */ u8 version; /* Version of this table (ACPI 2.0+) */
u8 reserved[31]; /* Reserved, must be zero */ u8 reserved[31]; /* Reserved, must be zero */
}; };
/* Flag macros */
#define ACPI_FACS_S4_BIOS_PRESENT (1) /* 00: S4BIOS support is present */
/* Global lock flags */
#define ACPI_GLOCK_PENDING 0x01 /* 00: Pending global lock ownership */ #define ACPI_GLOCK_PENDING 0x01 /* 00: Pending global lock ownership */
#define ACPI_GLOCK_OWNED 0x02 /* 01: Global lock is owned */ #define ACPI_GLOCK_OWNED 0x02 /* 01: Global lock is owned */
/*
* Common FACS - This is a version-independent FACS structure used for internal use only
*/
struct acpi_common_facs {
u32 *global_lock;
u64 *firmware_waking_vector;
u8 vector_width;
};
/******************************************************************************* /*******************************************************************************
* *
* FADT - Fixed ACPI Description Table (Signature "FACP") * FADT - Fixed ACPI Description Table (Signature "FACP")
...@@ -186,121 +181,98 @@ struct acpi_common_facs { ...@@ -186,121 +181,98 @@ struct acpi_common_facs {
/* Fields common to all versions of the FADT */ /* Fields common to all versions of the FADT */
#define ACPI_FADT_COMMON \ struct acpi_table_fadt {
ACPI_TABLE_HEADER_DEF \ struct acpi_table_header header; /* Common ACPI table header */
u32 V1_firmware_ctrl; /* 32-bit physical address of FACS */ \ u32 facs; /* 32-bit physical address of FACS */
u32 V1_dsdt; /* 32-bit physical address of DSDT */ \ u32 dsdt; /* 32-bit physical address of DSDT */
u8 reserved1; /* System Interrupt Model isn't used in ACPI 2.0*/ \ u8 model; /* System Interrupt Model (ACPI 1.0) not used in ACPI 2.0+ */
u8 prefer_PM_profile; /* Conveys preferred power management profile to OSPM. */ \ u8 preferred_profile; /* Conveys preferred power management profile to OSPM. */
u16 sci_int; /* System vector of SCI interrupt */ \ u16 sci_interrupt; /* System vector of SCI interrupt */
u32 smi_cmd; /* Port address of SMI command port */ \ u32 smi_command; /* Port address of SMI command port */
u8 acpi_enable; /* Value to write to smi_cmd to enable ACPI */ \ u8 acpi_enable; /* Value to write to smi_cmd to enable ACPI */
u8 acpi_disable; /* Value to write to smi_cmd to disable ACPI */ \ u8 acpi_disable; /* Value to write to smi_cmd to disable ACPI */
u8 S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */ \ u8 S4bios_request; /* Value to write to SMI CMD to enter S4BIOS state */
u8 pstate_cnt; /* Processor performance state control*/ \ u8 pstate_control; /* Processor performance state control */
u32 V1_pm1a_evt_blk; /* Port address of Power Mgt 1a Event Reg Blk */ \ u32 pm1a_event_block; /* Port address of Power Mgt 1a Event Reg Blk */
u32 V1_pm1b_evt_blk; /* Port address of Power Mgt 1b Event Reg Blk */ \ u32 pm1b_event_block; /* Port address of Power Mgt 1b Event Reg Blk */
u32 V1_pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ \ u32 pm1a_control_block; /* Port address of Power Mgt 1a Control Reg Blk */
u32 V1_pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ \ u32 pm1b_control_block; /* Port address of Power Mgt 1b Control Reg Blk */
u32 V1_pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */ \ u32 pm2_control_block; /* Port address of Power Mgt 2 Control Reg Blk */
u32 V1_pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ \ u32 pm_timer_block; /* Port address of Power Mgt Timer Ctrl Reg Blk */
u32 V1_gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */ \ u32 gpe0_block; /* Port addr of General Purpose acpi_event 0 Reg Blk */
u32 V1_gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */ \ u32 gpe1_block; /* Port addr of General Purpose acpi_event 1 Reg Blk */
u8 pm1_evt_len; /* Byte Length of ports at pm1_x_evt_blk */ \ u8 pm1_event_length; /* Byte Length of ports at pm1_x_evt_blk */
u8 pm1_cnt_len; /* Byte Length of ports at pm1_x_cnt_blk */ \ u8 pm1_control_length; /* Byte Length of ports at pm1_x_cnt_blk */
u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ \ u8 pm2_control_length; /* Byte Length of ports at pm2_cnt_blk */
u8 pm_tm_len; /* Byte Length of ports at pm_tm_blk */ \ u8 pm_timer_length; /* Byte Length of ports at pm_tmr_blk */
u8 gpe0_blk_len; /* Byte Length of ports at gpe0_blk */ \ u8 gpe0_block_length; /* Byte Length of ports at gpe0_blk */
u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ \ u8 gpe1_block_length; /* Byte Length of ports at gpe1_blk */
u8 gpe1_base; /* Offset in gpe model where gpe1 events start */ \ u8 gpe1_base; /* Offset in gpe model where gpe1 events start */
u8 cst_cnt; /* Support for the _CST object and C States change notification.*/ \ u8 cst_control; /* Support for the _CST object and C States change notification. */
u16 plvl2_lat; /* Worst case HW latency to enter/exit C2 state */ \ u16 C2latency; /* Worst case HW latency to enter/exit C2 state */
u16 plvl3_lat; /* Worst case HW latency to enter/exit C3 state */ \ u16 C3latency; /* Worst case HW latency to enter/exit C3 state */
u16 flush_size; /* Processor's memory cache line width, in bytes */ \ u16 flush_size; /* Processor's memory cache line width, in bytes */
u16 flush_stride; /* Number of flush strides that need to be read */ \ u16 flush_stride; /* Number of flush strides that need to be read */
u8 duty_offset; /* Processor's duty cycle index in processor's P_CNT reg*/ \ u8 duty_offset; /* Processor's duty cycle index in processor's P_CNT reg */
u8 duty_width; /* Processor's duty cycle value bit width in P_CNT register.*/ \ u8 duty_width; /* Processor's duty cycle value bit width in P_CNT register. */
u8 day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */ \ u8 day_alarm; /* Index to day-of-month alarm in RTC CMOS RAM */
u8 mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */ \ u8 month_alarm; /* Index to month-of-year alarm in RTC CMOS RAM */
u8 century; /* Index to century in RTC CMOS RAM */ \ u8 century; /* Index to century in RTC CMOS RAM */
u16 iapc_boot_arch; /* IA-PC Boot Architecture Flags. See Table 5-10 for description*/ \ u16 boot_flags; /* IA-PC Boot Architecture Flags. See Table 5-10 for description */
u8 reserved2; /* Reserved, must be zero */ u8 reserved; /* Reserved, must be zero */
u32 flags; /* Miscellaneous flag bits */
/*
* ACPI 2.0+ FADT
*/
struct fadt_descriptor {
ACPI_FADT_COMMON
/* Flags (32 bits) */
u8 wb_invd:1; /* 00: The wbinvd instruction works properly */
u8 wb_invd_flush:1; /* 01: The wbinvd flushes but does not invalidate */
u8 proc_c1:1; /* 02: All processors support C1 state */
u8 plvl2_up:1; /* 03: C2 state works on MP system */
u8 pwr_button:1; /* 04: Power button is handled as a generic feature */
u8 sleep_button:1; /* 05: Sleep button is handled as a generic feature, or not present */
u8 fixed_rTC:1; /* 06: RTC wakeup stat not in fixed register space */
u8 rtcs4:1; /* 07: RTC wakeup stat not possible from S4 */
u8 tmr_val_ext:1; /* 08: tmr_val is 32 bits 0=24-bits */
u8 dock_cap:1; /* 09: Docking supported */
u8 reset_reg_sup:1; /* 10: System reset via the FADT RESET_REG supported */
u8 sealed_case:1; /* 11: No internal expansion capabilities and case is sealed */
u8 headless:1; /* 12: No local video capabilities or local input devices */
u8 cpu_sw_sleep:1; /* 13: Must execute native instruction after writing SLP_TYPx register */
u8 pci_exp_wak:1; /* 14: System supports PCIEXP_WAKE (STS/EN) bits (ACPI 3.0) */
u8 use_platform_clock:1; /* 15: OSPM should use platform-provided timer (ACPI 3.0) */
u8 S4rtc_sts_valid:1; /* 16: Contents of RTC_STS valid after S4 wake (ACPI 3.0) */
u8 remote_power_on_capable:1; /* 17: System is compatible with remote power on (ACPI 3.0) */
u8 force_apic_cluster_model:1; /* 18: All local APICs must use cluster model (ACPI 3.0) */
u8 force_apic_physical_destination_mode:1; /* 19: All local x_aPICs must use physical dest mode (ACPI 3.0) */
u8:4; /* 20-23: Reserved, must be zero */
u8 reserved3; /* 24-31: Reserved, must be zero */
struct acpi_generic_address reset_register; /* Reset register address in GAS format */ struct acpi_generic_address reset_register; /* Reset register address in GAS format */
u8 reset_value; /* Value to write to the reset_register port to reset the system */ u8 reset_value; /* Value to write to the reset_register port to reset the system */
u8 reserved4[3]; /* These three bytes must be zero */ u8 reserved4[3]; /* These three bytes must be zero */
u64 xfirmware_ctrl; /* 64-bit physical address of FACS */ u64 Xfacs; /* 64-bit physical address of FACS */
u64 Xdsdt; /* 64-bit physical address of DSDT */ u64 Xdsdt; /* 64-bit physical address of DSDT */
struct acpi_generic_address xpm1a_evt_blk; /* Extended Power Mgt 1a acpi_event Reg Blk address */ struct acpi_generic_address xpm1a_event_block; /* Extended Power Mgt 1a acpi_event Reg Blk address */
struct acpi_generic_address xpm1b_evt_blk; /* Extended Power Mgt 1b acpi_event Reg Blk address */ struct acpi_generic_address xpm1b_event_block; /* Extended Power Mgt 1b acpi_event Reg Blk address */
struct acpi_generic_address xpm1a_cnt_blk; /* Extended Power Mgt 1a Control Reg Blk address */ struct acpi_generic_address xpm1a_control_block; /* Extended Power Mgt 1a Control Reg Blk address */
struct acpi_generic_address xpm1b_cnt_blk; /* Extended Power Mgt 1b Control Reg Blk address */ struct acpi_generic_address xpm1b_control_block; /* Extended Power Mgt 1b Control Reg Blk address */
struct acpi_generic_address xpm2_cnt_blk; /* Extended Power Mgt 2 Control Reg Blk address */ struct acpi_generic_address xpm2_control_block; /* Extended Power Mgt 2 Control Reg Blk address */
struct acpi_generic_address xpm_tmr_blk; /* Extended Power Mgt Timer Ctrl Reg Blk address */ struct acpi_generic_address xpm_timer_block; /* Extended Power Mgt Timer Ctrl Reg Blk address */
struct acpi_generic_address xgpe0_blk; /* Extended General Purpose acpi_event 0 Reg Blk address */ struct acpi_generic_address xgpe0_block; /* Extended General Purpose acpi_event 0 Reg Blk address */
struct acpi_generic_address xgpe1_blk; /* Extended General Purpose acpi_event 1 Reg Blk address */ struct acpi_generic_address xgpe1_block; /* Extended General Purpose acpi_event 1 Reg Blk address */
}; };
/* /* FADT flags */
* "Down-revved" ACPI 2.0 FADT descriptor
* Defined here to allow compiler to generate the length of the struct #define ACPI_FADT_WBINVD (1) /* 00: The wbinvd instruction works properly */
*/ #define ACPI_FADT_WBINVD_FLUSH (1<<1) /* 01: The wbinvd flushes but does not invalidate */
struct fadt_descriptor_rev2_minus { #define ACPI_FADT_C1_SUPPORTED (1<<2) /* 02: All processors support C1 state */
ACPI_FADT_COMMON u32 flags; #define ACPI_FADT_C2_MP_SUPPORTED (1<<3) /* 03: C2 state works on MP system */
struct acpi_generic_address reset_register; /* Reset register address in GAS format */ #define ACPI_FADT_POWER_BUTTON (1<<4) /* 04: Power button is handled as a generic feature */
u8 reset_value; /* Value to write to the reset_register port to reset the system. */ #define ACPI_FADT_SLEEP_BUTTON (1<<5) /* 05: Sleep button is handled as a generic feature, or not present */
u8 reserved7[3]; /* Reserved, must be zero */ #define ACPI_FADT_FIXED_RTC (1<<6) /* 06: RTC wakeup stat not in fixed register space */
}; #define ACPI_FADT_S4_RTC_WAKE (1<<7) /* 07: RTC wakeup stat not possible from S4 */
#define ACPI_FADT_32BIT_TIMER (1<<8) /* 08: tmr_val is 32 bits 0=24-bits */
#define ACPI_FADT_DOCKING_SUPPORTED (1<<9) /* 09: Docking supported */
#define ACPI_FADT_RESET_REGISTER (1<<10) /* 10: System reset via the FADT RESET_REG supported */
#define ACPI_FADT_SEALED_CASE (1<<11) /* 11: No internal expansion capabilities and case is sealed */
#define ACPI_FADT_HEADLESS (1<<12) /* 12: No local video capabilities or local input devices */
#define ACPI_FADT_SLEEP_TYPE (1<<13) /* 13: Must execute native instruction after writing SLP_TYPx register */
#define ACPI_FADT_PCI_EXPRESS_WAKE (1<<14) /* 14: System supports PCIEXP_WAKE (STS/EN) bits (ACPI 3.0) */
#define ACPI_FADT_PLATFORM_CLOCK (1<<15) /* 15: OSPM should use platform-provided timer (ACPI 3.0) */
#define ACPI_FADT_S4_RTC_VALID (1<<16) /* 16: Contents of RTC_STS valid after S4 wake (ACPI 3.0) */
#define ACPI_FADT_REMOTE_POWER_ON (1<<17) /* 17: System is compatible with remote power on (ACPI 3.0) */
#define ACPI_FADT_APIC_CLUSTER (1<<18) /* 18: All local APICs must use cluster model (ACPI 3.0) */
#define ACPI_FADT_APIC_PHYSICAL (1<<19) /* 19: All local x_aPICs must use physical dest mode (ACPI 3.0) */
/* /*
* ACPI 1.0 FADT * FADT Prefered Power Management Profiles
* Defined here to allow compiler to generate the length of the struct
*/ */
struct fadt_descriptor_rev1 { enum acpi_prefered_pm_profiles {
ACPI_FADT_COMMON u32 flags; PM_UNSPECIFIED = 0,
PM_DESKTOP = 1,
PM_MOBILE = 2,
PM_WORKSTATION = 3,
PM_ENTERPRISE_SERVER = 4,
PM_SOHO_SERVER = 5,
PM_APPLIANCE_PC = 6
}; };
/* FADT: Prefered Power Management Profiles */ /* FADT Boot Arch Flags */
#define PM_UNSPECIFIED 0
#define PM_DESKTOP 1
#define PM_MOBILE 2
#define PM_WORKSTATION 3
#define PM_ENTERPRISE_SERVER 4
#define PM_SOHO_SERVER 5
#define PM_APPLIANCE_PC 6
/* FADT: Boot Arch Flags */
#define BAF_LEGACY_DEVICES 0x0001 #define BAF_LEGACY_DEVICES 0x0001
#define BAF_8042_KEYBOARD_CONTROLLER 0x0002 #define BAF_8042_KEYBOARD_CONTROLLER 0x0002
...@@ -312,59 +284,11 @@ struct fadt_descriptor_rev1 { ...@@ -312,59 +284,11 @@ struct fadt_descriptor_rev1 {
#pragma pack() #pragma pack()
/* #define ACPI_FADT_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_fadt, f)
* This macro is temporary until the table bitfield flag definitions
* are removed and replaced by a Flags field.
*/
#define ACPI_FLAG_OFFSET(d,f,o) (u8) (ACPI_OFFSET (d,f) + \
sizeof(((d *)0)->f) + o)
/*
* Get the remaining ACPI tables
*/
#include "actbl1.h"
/* /*
* ACPI Table information. We save the table address, length, * Get the remaining ACPI tables
* and type of memory allocation (mapped or allocated) for each
* table for 1) when we exit, and 2) if a new table is installed
*/ */
#define ACPI_MEM_NOT_ALLOCATED 0 #include <acpi/actbl1.h>
#define ACPI_MEM_ALLOCATED 1
#define ACPI_MEM_MAPPED 2
/* Definitions for the Flags bitfield member of struct acpi_table_support */
#define ACPI_TABLE_SINGLE 0x00
#define ACPI_TABLE_MULTIPLE 0x01
#define ACPI_TABLE_EXECUTABLE 0x02
#define ACPI_TABLE_ROOT 0x00
#define ACPI_TABLE_PRIMARY 0x10
#define ACPI_TABLE_SECONDARY 0x20
#define ACPI_TABLE_ALL 0x30
#define ACPI_TABLE_TYPE_MASK 0x30
/* Data about each known table type */
struct acpi_table_support {
char *name;
char *signature;
void **global_ptr;
u8 sig_length;
u8 flags;
};
extern u8 acpi_fadt_is_v1; /* is set to 1 if FADT is revision 1,
* needed for certain workarounds */
/* Macros used to generate offsets to specific table fields */
#define ACPI_FACS_OFFSET(f) (u8) ACPI_OFFSET (struct facs_descriptor,f)
#define ACPI_FADT_OFFSET(f) (u8) ACPI_OFFSET (struct fadt_descriptor, f)
#define ACPI_GAS_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_generic_address,f)
#define ACPI_HDR_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_header,f)
#define ACPI_RSDP_OFFSET(f) (u8) ACPI_OFFSET (struct rsdp_descriptor,f)
#define ACPI_FADT_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct fadt_descriptor,f,o)
#define ACPI_FACS_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct facs_descriptor,f,o)
#endif /* __ACTBL_H__ */ #endif /* __ACTBL_H__ */
...@@ -73,12 +73,6 @@ ...@@ -73,12 +73,6 @@
#define ACPI_SIG_TCPA "TCPA" /* Trusted Computing Platform Alliance table */ #define ACPI_SIG_TCPA "TCPA" /* Trusted Computing Platform Alliance table */
#define ACPI_SIG_WDRT "WDRT" /* Watchdog Resource Table */ #define ACPI_SIG_WDRT "WDRT" /* Watchdog Resource Table */
/* Legacy names */
#define APIC_SIG "APIC" /* Multiple APIC Description Table */
#define BOOT_SIG "BOOT" /* Simple Boot Flag Table */
#define SBST_SIG "SBST" /* Smart Battery Specification Table */
/* /*
* All tables must be byte-packed to match the ACPI specification, since * All tables must be byte-packed to match the ACPI specification, since
* the tables are provided by the system BIOS. * the tables are provided by the system BIOS.
...@@ -91,6 +85,13 @@ ...@@ -91,6 +85,13 @@
* portable, so do not use any other bitfield types. * portable, so do not use any other bitfield types.
*/ */
/* Common Sub-table header (used in MADT, SRAT, etc.) */
struct acpi_subtable_header {
u8 type;
u8 length;
};
/******************************************************************************* /*******************************************************************************
* *
* ASF - Alert Standard Format table (Signature "ASF!") * ASF - Alert Standard Format table (Signature "ASF!")
...@@ -98,24 +99,27 @@ ...@@ -98,24 +99,27 @@
******************************************************************************/ ******************************************************************************/
struct acpi_table_asf { struct acpi_table_asf {
ACPI_TABLE_HEADER_DEF}; struct acpi_table_header header; /* Common ACPI table header */
};
#define ACPI_ASF_HEADER_DEF \ /* ASF subtable header */
u8 type; \
u8 reserved; \
u16 length;
struct acpi_asf_header { struct acpi_asf_header {
ACPI_ASF_HEADER_DEF}; u8 type;
u8 reserved;
u16 length;
};
/* Values for Type field */ /* Values for Type field above */
#define ASF_INFO 0 enum acpi_asf_type {
#define ASF_ALERT 1 ACPI_ASF_TYPE_INFO = 0,
#define ASF_CONTROL 2 ACPI_ASF_TYPE_ALERT = 1,
#define ASF_BOOT 3 ACPI_ASF_TYPE_CONTROL = 2,
#define ASF_ADDRESS 4 ACPI_ASF_TYPE_BOOT = 3,
#define ASF_RESERVED 5 ACPI_ASF_TYPE_ADDRESS = 4,
ACPI_ASF_TYPE_RESERVED = 5
};
/* /*
* ASF subtables * ASF subtables
...@@ -124,7 +128,8 @@ ACPI_ASF_HEADER_DEF}; ...@@ -124,7 +128,8 @@ ACPI_ASF_HEADER_DEF};
/* 0: ASF Information */ /* 0: ASF Information */
struct acpi_asf_info { struct acpi_asf_info {
ACPI_ASF_HEADER_DEF u8 min_reset_value; struct acpi_asf_header header;
u8 min_reset_value;
u8 min_poll_interval; u8 min_poll_interval;
u16 system_id; u16 system_id;
u32 mfg_id; u32 mfg_id;
...@@ -135,7 +140,8 @@ struct acpi_asf_info { ...@@ -135,7 +140,8 @@ struct acpi_asf_info {
/* 1: ASF Alerts */ /* 1: ASF Alerts */
struct acpi_asf_alert { struct acpi_asf_alert {
ACPI_ASF_HEADER_DEF u8 assert_mask; struct acpi_asf_header header;
u8 assert_mask;
u8 deassert_mask; u8 deassert_mask;
u8 alerts; u8 alerts;
u8 data_length; u8 data_length;
...@@ -145,7 +151,8 @@ struct acpi_asf_alert { ...@@ -145,7 +151,8 @@ struct acpi_asf_alert {
/* 2: ASF Remote Control */ /* 2: ASF Remote Control */
struct acpi_asf_remote { struct acpi_asf_remote {
ACPI_ASF_HEADER_DEF u8 controls; struct acpi_asf_header header;
u8 controls;
u8 data_length; u8 data_length;
u16 reserved2; u16 reserved2;
u8 array[1]; u8 array[1];
...@@ -154,7 +161,8 @@ struct acpi_asf_remote { ...@@ -154,7 +161,8 @@ struct acpi_asf_remote {
/* 3: ASF RMCP Boot Options */ /* 3: ASF RMCP Boot Options */
struct acpi_asf_rmcp { struct acpi_asf_rmcp {
ACPI_ASF_HEADER_DEF u8 capabilities[7]; struct acpi_asf_header header;
u8 capabilities[7];
u8 completion_code; u8 completion_code;
u32 enterprise_id; u32 enterprise_id;
u8 command; u8 command;
...@@ -166,7 +174,8 @@ struct acpi_asf_rmcp { ...@@ -166,7 +174,8 @@ struct acpi_asf_rmcp {
/* 4: ASF Address */ /* 4: ASF Address */
struct acpi_asf_address { struct acpi_asf_address {
ACPI_ASF_HEADER_DEF u8 eprom_address; struct acpi_asf_header header;
u8 eprom_address;
u8 devices; u8 devices;
u8 smbus_addresses[1]; u8 smbus_addresses[1];
}; };
...@@ -178,7 +187,8 @@ struct acpi_asf_address { ...@@ -178,7 +187,8 @@ struct acpi_asf_address {
******************************************************************************/ ******************************************************************************/
struct acpi_table_boot { struct acpi_table_boot {
ACPI_TABLE_HEADER_DEF u8 cmos_index; /* Index in CMOS RAM for the boot register */ struct acpi_table_header header; /* Common ACPI table header */
u8 cmos_index; /* Index in CMOS RAM for the boot register */
u8 reserved[3]; u8 reserved[3];
}; };
...@@ -189,7 +199,8 @@ struct acpi_table_boot { ...@@ -189,7 +199,8 @@ struct acpi_table_boot {
******************************************************************************/ ******************************************************************************/
struct acpi_table_cpep { struct acpi_table_cpep {
ACPI_TABLE_HEADER_DEF u64 reserved; struct acpi_table_header header; /* Common ACPI table header */
u64 reserved;
}; };
/* Subtable */ /* Subtable */
...@@ -197,9 +208,9 @@ struct acpi_table_cpep { ...@@ -197,9 +208,9 @@ struct acpi_table_cpep {
struct acpi_cpep_polling { struct acpi_cpep_polling {
u8 type; u8 type;
u8 length; u8 length;
u8 processor_id; /* Processor ID */ u8 id; /* Processor ID */
u8 processor_eid; /* Processor EID */ u8 eid; /* Processor EID */
u32 polling_interval; /* Polling interval (msec) */ u32 interval; /* Polling interval (msec) */
}; };
/******************************************************************************* /*******************************************************************************
...@@ -209,7 +220,8 @@ struct acpi_cpep_polling { ...@@ -209,7 +220,8 @@ struct acpi_cpep_polling {
******************************************************************************/ ******************************************************************************/
struct acpi_table_dbgp { struct acpi_table_dbgp {
ACPI_TABLE_HEADER_DEF u8 interface_type; /* 0=full 16550, 1=subset of 16550 */ struct acpi_table_header header; /* Common ACPI table header */
u8 type; /* 0=full 16550, 1=subset of 16550 */
u8 reserved[3]; u8 reserved[3];
struct acpi_generic_address debug_port; struct acpi_generic_address debug_port;
}; };
...@@ -220,12 +232,13 @@ struct acpi_table_dbgp { ...@@ -220,12 +232,13 @@ struct acpi_table_dbgp {
* *
******************************************************************************/ ******************************************************************************/
struct ec_boot_resources { struct acpi_table_ecdt {
ACPI_TABLE_HEADER_DEF struct acpi_generic_address ec_control; /* Address of EC command/status register */ struct acpi_table_header header; /* Common ACPI table header */
struct acpi_generic_address ec_data; /* Address of EC data register */ struct acpi_generic_address control; /* Address of EC command/status register */
struct acpi_generic_address data; /* Address of EC data register */
u32 uid; /* Unique ID - must be same as the EC _UID method */ u32 uid; /* Unique ID - must be same as the EC _UID method */
u8 gpe_bit; /* The GPE for the EC */ u8 gpe; /* The GPE for the EC */
u8 ec_id[1]; /* Full namepath of the EC in the ACPI namespace */ u8 id[1]; /* Full namepath of the EC in the ACPI namespace */
}; };
/******************************************************************************* /*******************************************************************************
...@@ -234,22 +247,22 @@ struct ec_boot_resources { ...@@ -234,22 +247,22 @@ struct ec_boot_resources {
* *
******************************************************************************/ ******************************************************************************/
struct acpi_hpet_table { struct acpi_table_hpet {
ACPI_TABLE_HEADER_DEF u32 hardware_id; /* Hardware ID of event timer block */ struct acpi_table_header header; /* Common ACPI table header */
struct acpi_generic_address base_address; /* Address of event timer block */ u32 id; /* Hardware ID of event timer block */
u8 hpet_number; /* HPET sequence number */ struct acpi_generic_address address; /* Address of event timer block */
u16 clock_tick; /* Main counter min tick, periodic mode */ u8 sequence; /* HPET sequence number */
u8 attributes; u16 minimum_tick; /* Main counter min tick, periodic mode */
u8 flags;
}; };
#if 0 /* HPET flags to be converted to macros */ /*! Flags */
struct { /* Flags (8 bits) */
u8 page_protect:1; /* 00: No page protection */ #define ACPI_HPET_PAGE_PROTECT (1) /* 00: No page protection */
u8 page_protect4:1; /* 01: 4_kB page protected */ #define ACPI_HPET_PAGE_PROTECT_4 (1<<1) /* 01: 4KB page protected */
u8 page_protect64:1; /* 02: 64_kB page protected */ #define ACPI_HPET_PAGE_PROTECT_64 (1<<2) /* 02: 64KB page protected */
u8:5; /* 03-07: Reserved, must be zero */
} flags; /*! [End] no source code translation !*/
#endif
/******************************************************************************* /*******************************************************************************
* *
...@@ -257,148 +270,159 @@ struct { /* Flags (8 bits) */ ...@@ -257,148 +270,159 @@ struct { /* Flags (8 bits) */
* *
******************************************************************************/ ******************************************************************************/
struct multiple_apic_table { struct acpi_table_madt {
ACPI_TABLE_HEADER_DEF u32 local_apic_address; /* Physical address of local APIC */ struct acpi_table_header header; /* Common ACPI table header */
u32 address; /* Physical address of local APIC */
/* Flags (32 bits) */ u32 flags;
u8 PCATcompat:1; /* 00: System also has dual 8259s */
u8:7; /* 01-07: Reserved, must be zero */
u8 reserved1[3]; /* 08-31: Reserved, must be zero */
}; };
/* Values for MADT PCATCompat */ /* Flags */
#define DUAL_PIC 0
#define MULTIPLE_APIC 1
/* Common MADT Sub-table header */
#define APIC_HEADER_DEF \
u8 type; \
u8 length;
struct apic_header {
APIC_HEADER_DEF};
/* Values for Type in struct apic_header */
#define APIC_PROCESSOR 0 #define ACPI_MADT_PCAT_COMPAT (1) /* 00: System also has dual 8259s */
#define APIC_IO 1
#define APIC_XRUPT_OVERRIDE 2
#define APIC_NMI 3
#define APIC_LOCAL_NMI 4
#define APIC_ADDRESS_OVERRIDE 5
#define APIC_IO_SAPIC 6
#define APIC_LOCAL_SAPIC 7
#define APIC_XRUPT_SOURCE 8
#define APIC_RESERVED 9 /* 9 and greater are reserved */
/* Flag definitions for MADT sub-tables */ /* Values for PCATCompat flag */
#define ACPI_MADT_IFLAGS /* INTI flags (16 bits) */ \ #define ACPI_MADT_DUAL_PIC 0
u8 polarity : 2; /* 00-01: Polarity of APIC I/O input signals */\ #define ACPI_MADT_MULTIPLE_APIC 1
u8 trigger_mode : 2; /* 02-03: Trigger mode of APIC input signals */\
u8 : 4; /* 04-07: Reserved, must be zero */\
u8 reserved1; /* 08-15: Reserved, must be zero */
#define ACPI_MADT_LFLAGS /* Local Sapic flags (32 bits) */ \ /* Values for subtable type in struct acpi_subtable_header */
u8 processor_enabled: 1; /* 00: Processor is usable if set */\
u8 : 7; /* 01-07: Reserved, must be zero */\
u8 reserved2[3]; /* 08-31: Reserved, must be zero */
/* Values for MPS INTI flags */
#define POLARITY_CONFORMS 0 enum acpi_madt_type {
#define POLARITY_ACTIVE_HIGH 1 ACPI_MADT_TYPE_LOCAL_APIC = 0,
#define POLARITY_RESERVED 2 ACPI_MADT_TYPE_IO_APIC = 1,
#define POLARITY_ACTIVE_LOW 3 ACPI_MADT_TYPE_INTERRUPT_OVERRIDE = 2,
ACPI_MADT_TYPE_NMI_SOURCE = 3,
#define TRIGGER_CONFORMS 0 ACPI_MADT_TYPE_LOCAL_APIC_NMI = 4,
#define TRIGGER_EDGE 1 ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE = 5,
#define TRIGGER_RESERVED 2 ACPI_MADT_TYPE_IO_SAPIC = 6,
#define TRIGGER_LEVEL 3 ACPI_MADT_TYPE_LOCAL_SAPIC = 7,
ACPI_MADT_TYPE_INTERRUPT_SOURCE = 8,
ACPI_MADT_TYPE_RESERVED = 9 /* 9 and greater are reserved */
};
/* /*
* MADT Sub-tables, correspond to Type in struct apic_header * MADT Sub-tables, correspond to Type in struct acpi_subtable_header
*/ */
/* 0: processor APIC */ /* 0: Processor Local APIC */
struct madt_processor_apic { struct acpi_madt_local_apic {
APIC_HEADER_DEF u8 processor_id; /* ACPI processor id */ struct acpi_subtable_header header;
u8 local_apic_id; /* Processor's local APIC id */ u8 processor_id; /* ACPI processor id */
ACPI_MADT_LFLAGS}; u8 id; /* Processor's local APIC id */
u32 lapic_flags;
};
/* 1: IO APIC */ /* 1: IO APIC */
struct madt_io_apic { struct acpi_madt_io_apic {
APIC_HEADER_DEF u8 io_apic_id; /* I/O APIC ID */ struct acpi_subtable_header header;
u8 id; /* I/O APIC ID */
u8 reserved; /* Reserved - must be zero */ u8 reserved; /* Reserved - must be zero */
u32 address; /* APIC physical address */ u32 address; /* APIC physical address */
u32 interrupt; /* Global system interrupt where INTI lines start */ u32 global_irq_base; /* Global system interrupt where INTI lines start */
}; };
/* 2: Interrupt Override */ /* 2: Interrupt Override */
struct madt_interrupt_override { struct acpi_madt_interrupt_override {
APIC_HEADER_DEF u8 bus; /* 0 - ISA */ struct acpi_subtable_header header;
u8 source; /* Interrupt source (IRQ) */ u8 bus; /* 0 - ISA */
u32 interrupt; /* Global system interrupt */ u8 source_irq; /* Interrupt source (IRQ) */
ACPI_MADT_IFLAGS}; u32 global_irq; /* Global system interrupt */
u16 inti_flags;
};
/* 3: NMI Sources */ /* 3: NMI Source */
struct madt_nmi_source { struct acpi_madt_nmi_source {
APIC_HEADER_DEF ACPI_MADT_IFLAGS u32 interrupt; /* Global system interrupt */ struct acpi_subtable_header header;
u16 inti_flags;
u32 global_irq; /* Global system interrupt */
}; };
/* 4: Local APIC NMI */ /* 4: Local APIC NMI */
struct madt_local_apic_nmi { struct acpi_madt_local_apic_nmi {
APIC_HEADER_DEF u8 processor_id; /* ACPI processor id */ struct acpi_subtable_header header;
ACPI_MADT_IFLAGS u8 lint; /* LINTn to which NMI is connected */ u8 processor_id; /* ACPI processor id */
u16 inti_flags;
u8 lint; /* LINTn to which NMI is connected */
}; };
/* 5: Address Override */ /* 5: Address Override */
struct madt_address_override { struct acpi_madt_local_apic_override {
APIC_HEADER_DEF u16 reserved; /* Reserved, must be zero */ struct acpi_subtable_header header;
u16 reserved; /* Reserved, must be zero */
u64 address; /* APIC physical address */ u64 address; /* APIC physical address */
}; };
/* 6: I/O Sapic */ /* 6: I/O Sapic */
struct madt_io_sapic { struct acpi_madt_io_sapic {
APIC_HEADER_DEF u8 io_sapic_id; /* I/O SAPIC ID */ struct acpi_subtable_header header;
u8 id; /* I/O SAPIC ID */
u8 reserved; /* Reserved, must be zero */ u8 reserved; /* Reserved, must be zero */
u32 interrupt_base; /* Glocal interrupt for SAPIC start */ u32 global_irq_base; /* Global interrupt for SAPIC start */
u64 address; /* SAPIC physical address */ u64 address; /* SAPIC physical address */
}; };
/* 7: Local Sapic */ /* 7: Local Sapic */
struct madt_local_sapic { struct acpi_madt_local_sapic {
APIC_HEADER_DEF u8 processor_id; /* ACPI processor id */ struct acpi_subtable_header header;
u8 local_sapic_id; /* SAPIC ID */ u8 processor_id; /* ACPI processor id */
u8 local_sapic_eid; /* SAPIC EID */ u8 id; /* SAPIC ID */
u8 eid; /* SAPIC EID */
u8 reserved[3]; /* Reserved, must be zero */ u8 reserved[3]; /* Reserved, must be zero */
ACPI_MADT_LFLAGS u32 processor_uID; /* Numeric UID - ACPI 3.0 */ u32 lapic_flags;
char processor_uIDstring[1]; /* String UID - ACPI 3.0 */ u32 uid; /* Numeric UID - ACPI 3.0 */
char uid_string[1]; /* String UID - ACPI 3.0 */
}; };
/* 8: Platform Interrupt Source */ /* 8: Platform Interrupt Source */
struct madt_interrupt_source { struct acpi_madt_interrupt_source {
APIC_HEADER_DEF ACPI_MADT_IFLAGS u8 interrupt_type; /* 1=PMI, 2=INIT, 3=corrected */ struct acpi_subtable_header header;
u8 processor_id; /* Processor ID */ u16 inti_flags;
u8 processor_eid; /* Processor EID */ u8 type; /* 1=PMI, 2=INIT, 3=corrected */
u8 id; /* Processor ID */
u8 eid; /* Processor EID */
u8 io_sapic_vector; /* Vector value for PMI interrupts */ u8 io_sapic_vector; /* Vector value for PMI interrupts */
u32 interrupt; /* Global system interrupt */ u32 global_irq; /* Global system interrupt */
u32 flags; /* Interrupt Source Flags */ u32 flags; /* Interrupt Source Flags */
}; };
#ifdef DUPLICATE_DEFINITION_WITH_LINUX_ACPI_H /* Flags field above */
#define ACPI_MADT_CPEI_OVERRIDE (1)
/*
* Common flags fields for MADT subtables
*/
/* MADT Local APIC flags (lapic_flags) */
#define ACPI_MADT_ENABLED (1) /* 00: Processor is usable if set */
/* MADT MPS INTI flags (inti_flags) */
#define ACPI_MADT_POLARITY_MASK (3) /* 00-01: Polarity of APIC I/O input signals */
#define ACPI_MADT_TRIGGER_MASK (3<<2) /* 02-03: Trigger mode of APIC input signals */
/* Values for MPS INTI flags */
#define ACPI_MADT_POLARITY_CONFORMS 0
#define ACPI_MADT_POLARITY_ACTIVE_HIGH 1
#define ACPI_MADT_POLARITY_RESERVED 2
#define ACPI_MADT_POLARITY_ACTIVE_LOW 3
#define ACPI_MADT_TRIGGER_CONFORMS (0)
#define ACPI_MADT_TRIGGER_EDGE (1<<2)
#define ACPI_MADT_TRIGGER_RESERVED (2<<2)
#define ACPI_MADT_TRIGGER_LEVEL (3<<2)
/******************************************************************************* /*******************************************************************************
* *
* MCFG - PCI Memory Mapped Configuration table and sub-table * MCFG - PCI Memory Mapped Configuration table and sub-table
...@@ -406,17 +430,19 @@ struct madt_interrupt_source { ...@@ -406,17 +430,19 @@ struct madt_interrupt_source {
******************************************************************************/ ******************************************************************************/
struct acpi_table_mcfg { struct acpi_table_mcfg {
ACPI_TABLE_HEADER_DEF u8 reserved[8]; struct acpi_table_header header; /* Common ACPI table header */
u8 reserved[8];
}; };
/* Subtable */
struct acpi_mcfg_allocation { struct acpi_mcfg_allocation {
u64 base_address; /* Base address, processor-relative */ u64 address; /* Base address, processor-relative */
u16 pci_segment; /* PCI segment group number */ u16 pci_segment; /* PCI segment group number */
u8 start_bus_number; /* Starting PCI Bus number */ u8 start_bus_number; /* Starting PCI Bus number */
u8 end_bus_number; /* Final PCI Bus number */ u8 end_bus_number; /* Final PCI Bus number */
u32 reserved; u32 reserved;
}; };
#endif
/******************************************************************************* /*******************************************************************************
* *
...@@ -424,8 +450,9 @@ struct acpi_mcfg_allocation { ...@@ -424,8 +450,9 @@ struct acpi_mcfg_allocation {
* *
******************************************************************************/ ******************************************************************************/
struct smart_battery_table { struct acpi_table_sbst {
ACPI_TABLE_HEADER_DEF u32 warning_level; struct acpi_table_header header; /* Common ACPI table header */
u32 warning_level;
u32 low_level; u32 low_level;
u32 critical_level; u32 critical_level;
}; };
...@@ -436,9 +463,10 @@ struct smart_battery_table { ...@@ -436,9 +463,10 @@ struct smart_battery_table {
* *
******************************************************************************/ ******************************************************************************/
struct system_locality_info { struct acpi_table_slit {
ACPI_TABLE_HEADER_DEF u64 locality_count; struct acpi_table_header header; /* Common ACPI table header */
u8 entry[1][1]; u64 locality_count;
u8 entry[1]; /* Real size = localities^2 */
}; };
/******************************************************************************* /*******************************************************************************
...@@ -448,7 +476,8 @@ struct system_locality_info { ...@@ -448,7 +476,8 @@ struct system_locality_info {
******************************************************************************/ ******************************************************************************/
struct acpi_table_spcr { struct acpi_table_spcr {
ACPI_TABLE_HEADER_DEF u8 interface_type; /* 0=full 16550, 1=subset of 16550 */ struct acpi_table_header header; /* Common ACPI table header */
u8 interface_type; /* 0=full 16550, 1=subset of 16550 */
u8 reserved[3]; u8 reserved[3];
struct acpi_generic_address serial_port; struct acpi_generic_address serial_port;
u8 interrupt_type; u8 interrupt_type;
...@@ -459,7 +488,7 @@ struct acpi_table_spcr { ...@@ -459,7 +488,7 @@ struct acpi_table_spcr {
u8 stop_bits; u8 stop_bits;
u8 flow_control; u8 flow_control;
u8 terminal_type; u8 terminal_type;
u8 reserved2; u8 reserved1;
u16 pci_device_id; u16 pci_device_id;
u16 pci_vendor_id; u16 pci_vendor_id;
u8 pci_bus; u8 pci_bus;
...@@ -467,7 +496,7 @@ struct acpi_table_spcr { ...@@ -467,7 +496,7 @@ struct acpi_table_spcr {
u8 pci_function; u8 pci_function;
u32 pci_flags; u32 pci_flags;
u8 pci_segment; u8 pci_segment;
u32 reserved3; u32 reserved2;
}; };
/******************************************************************************* /*******************************************************************************
...@@ -477,12 +506,13 @@ struct acpi_table_spcr { ...@@ -477,12 +506,13 @@ struct acpi_table_spcr {
******************************************************************************/ ******************************************************************************/
struct acpi_table_spmi { struct acpi_table_spmi {
ACPI_TABLE_HEADER_DEF u8 reserved; struct acpi_table_header header; /* Common ACPI table header */
u8 reserved;
u8 interface_type; u8 interface_type;
u16 spec_revision; /* Version of IPMI */ u16 spec_revision; /* Version of IPMI */
u8 interrupt_type; u8 interrupt_type;
u8 gpe_number; /* GPE assigned */ u8 gpe_number; /* GPE assigned */
u8 reserved2; u8 reserved1;
u8 pci_device_flag; u8 pci_device_flag;
u32 interrupt; u32 interrupt;
struct acpi_generic_address ipmi_register; struct acpi_generic_address ipmi_register;
...@@ -498,56 +528,61 @@ struct acpi_table_spmi { ...@@ -498,56 +528,61 @@ struct acpi_table_spmi {
* *
******************************************************************************/ ******************************************************************************/
struct system_resource_affinity { struct acpi_table_srat {
ACPI_TABLE_HEADER_DEF u32 reserved1; /* Must be value '1' */ struct acpi_table_header header; /* Common ACPI table header */
u64 reserved2; /* Reserved, must be zero */ u32 table_revision; /* Must be value '1' */
u64 reserved; /* Reserved, must be zero */
}; };
/* SRAT common sub-table header */ /* Values for subtable type in struct acpi_subtable_header */
#define SRAT_SUBTABLE_HEADER \
u8 type; \
u8 length;
/* Values for Type above */ enum acpi_srat_type {
ACPI_SRAT_TYPE_CPU_AFFINITY = 0,
#define SRAT_CPU_AFFINITY 0 ACPI_SRAT_TYPE_MEMORY_AFFINITY = 1,
#define SRAT_MEMORY_AFFINITY 1 ACPI_SRAT_TYPE_RESERVED = 2
#define SRAT_RESERVED 2 };
/* SRAT sub-tables */ /* SRAT sub-tables */
struct static_resource_alloc { struct acpi_srat_cpu_affinity {
SRAT_SUBTABLE_HEADER u8 proximity_domain_lo; struct acpi_subtable_header header;
u8 proximity_domain_lo;
u8 apic_id; u8 apic_id;
u32 flags;
/* Flags (32 bits) */
u8 enabled:1; /* 00: Use affinity structure */
u8:7; /* 01-07: Reserved, must be zero */
u8 reserved3[3]; /* 08-31: Reserved, must be zero */
u8 local_sapic_eid; u8 local_sapic_eid;
u8 proximity_domain_hi[3]; u8 proximity_domain_hi[3];
u32 reserved4; /* Reserved, must be zero */ u32 reserved; /* Reserved, must be zero */
}; };
struct memory_affinity { /* Flags */
SRAT_SUBTABLE_HEADER u32 proximity_domain;
u16 reserved3; #define ACPI_SRAT_CPU_ENABLED (1) /* 00: Use affinity structure */
struct acpi_srat_mem_affinity {
struct acpi_subtable_header header;
u32 proximity_domain;
u16 reserved; /* Reserved, must be zero */
u64 base_address; u64 base_address;
u64 address_length; u64 length;
u32 reserved4; u32 memory_type; /* See acpi_address_range_id */
u32 flags;
u64 reserved1; /* Reserved, must be zero */
};
/* Flags */
/* Flags (32 bits) */ #define ACPI_SRAT_MEM_ENABLED (1) /* 00: Use affinity structure */
#define ACPI_SRAT_MEM_HOT_PLUGGABLE (1<<1) /* 01: Memory region is hot pluggable */
#define ACPI_SRAT_MEM_NON_VOLATILE (1<<2) /* 02: Memory region is non-volatile */
u8 enabled:1; /* 00: Use affinity structure */ /* Memory types */
u8 hot_pluggable:1; /* 01: Memory region is hot pluggable */
u8 non_volatile:1; /* 02: Memory is non-volatile */
u8:5; /* 03-07: Reserved, must be zero */
u8 reserved5[3]; /* 08-31: Reserved, must be zero */
u64 reserved6; /* Reserved, must be zero */ enum acpi_address_range_id {
ACPI_ADDRESS_RANGE_MEMORY = 1,
ACPI_ADDRESS_RANGE_RESERVED = 2,
ACPI_ADDRESS_RANGE_ACPI = 3,
ACPI_ADDRESS_RANGE_NVS = 4,
ACPI_ADDRESS_RANGE_COUNT = 5
}; };
/******************************************************************************* /*******************************************************************************
...@@ -557,7 +592,8 @@ struct memory_affinity { ...@@ -557,7 +592,8 @@ struct memory_affinity {
******************************************************************************/ ******************************************************************************/
struct acpi_table_tcpa { struct acpi_table_tcpa {
ACPI_TABLE_HEADER_DEF u16 reserved; struct acpi_table_header header; /* Common ACPI table header */
u16 reserved;
u32 max_log_length; /* Maximum length for the event log area */ u32 max_log_length; /* Maximum length for the event log area */
u64 log_address; /* Address of the event log area */ u64 log_address; /* Address of the event log area */
}; };
...@@ -569,7 +605,8 @@ struct acpi_table_tcpa { ...@@ -569,7 +605,8 @@ struct acpi_table_tcpa {
******************************************************************************/ ******************************************************************************/
struct acpi_table_wdrt { struct acpi_table_wdrt {
ACPI_TABLE_HEADER_DEF u32 header_length; /* Watchdog Header Length */ struct acpi_table_header header; /* Common ACPI table header */
u32 header_length; /* Watchdog Header Length */
u8 pci_segment; /* PCI Segment number */ u8 pci_segment; /* PCI Segment number */
u8 pci_bus; /* PCI Bus number */ u8 pci_bus; /* PCI Bus number */
u8 pci_device; /* PCI Device number */ u8 pci_device; /* PCI Device number */
...@@ -582,58 +619,9 @@ struct acpi_table_wdrt { ...@@ -582,58 +619,9 @@ struct acpi_table_wdrt {
u32 entries; /* Number of watchdog entries that follow */ u32 entries; /* Number of watchdog entries that follow */
}; };
#if 0 /* Flags, will be converted to macros */ /* Flags */
u8 enabled:1; /* 00: Timer enabled */
u8:6; /* 01-06: Reserved */ #define ACPI_WDRT_TIMER_ENABLED (1) /* 00: Timer enabled */
u8 sleep_stop:1; /* 07: Timer stopped in sleep state */
#endif
/* Macros used to generate offsets to specific table fields */
#define ACPI_ASF0_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_asf_info,f)
#define ACPI_ASF1_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_asf_alert,f)
#define ACPI_ASF2_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_asf_remote,f)
#define ACPI_ASF3_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_asf_rmcp,f)
#define ACPI_ASF4_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_asf_address,f)
#define ACPI_BOOT_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_boot,f)
#define ACPI_CPEP_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_cpep,f)
#define ACPI_CPEP0_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_cpep_polling,f)
#define ACPI_DBGP_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_dbgp,f)
#define ACPI_ECDT_OFFSET(f) (u8) ACPI_OFFSET (struct ec_boot_resources,f)
#define ACPI_HPET_OFFSET(f) (u8) ACPI_OFFSET (struct hpet_table,f)
#define ACPI_MADT_OFFSET(f) (u8) ACPI_OFFSET (struct multiple_apic_table,f)
#define ACPI_MADT0_OFFSET(f) (u8) ACPI_OFFSET (struct madt_processor_apic,f)
#define ACPI_MADT1_OFFSET(f) (u8) ACPI_OFFSET (struct madt_io_apic,f)
#define ACPI_MADT2_OFFSET(f) (u8) ACPI_OFFSET (struct madt_interrupt_override,f)
#define ACPI_MADT3_OFFSET(f) (u8) ACPI_OFFSET (struct madt_nmi_source,f)
#define ACPI_MADT4_OFFSET(f) (u8) ACPI_OFFSET (struct madt_local_apic_nmi,f)
#define ACPI_MADT5_OFFSET(f) (u8) ACPI_OFFSET (struct madt_address_override,f)
#define ACPI_MADT6_OFFSET(f) (u8) ACPI_OFFSET (struct madt_io_sapic,f)
#define ACPI_MADT7_OFFSET(f) (u8) ACPI_OFFSET (struct madt_local_sapic,f)
#define ACPI_MADT8_OFFSET(f) (u8) ACPI_OFFSET (struct madt_interrupt_source,f)
#define ACPI_MADTH_OFFSET(f) (u8) ACPI_OFFSET (struct apic_header,f)
#define ACPI_MCFG_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_mcfg,f)
#define ACPI_MCFG0_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_mcfg_allocation,f)
#define ACPI_SBST_OFFSET(f) (u8) ACPI_OFFSET (struct smart_battery_table,f)
#define ACPI_SLIT_OFFSET(f) (u8) ACPI_OFFSET (struct system_locality_info,f)
#define ACPI_SPCR_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_spcr,f)
#define ACPI_SPMI_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_spmi,f)
#define ACPI_SRAT_OFFSET(f) (u8) ACPI_OFFSET (struct system_resource_affinity,f)
#define ACPI_SRAT0_OFFSET(f) (u8) ACPI_OFFSET (struct static_resource_alloc,f)
#define ACPI_SRAT1_OFFSET(f) (u8) ACPI_OFFSET (struct memory_affinity,f)
#define ACPI_TCPA_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_tcpa,f)
#define ACPI_WDRT_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_table_wdrt,f)
#define ACPI_HPET_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct hpet_table,f,o)
#define ACPI_SRAT0_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct static_resource_alloc,f,o)
#define ACPI_SRAT1_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct memory_affinity,f,o)
#define ACPI_MADT_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct multiple_apic_table,f,o)
#define ACPI_MADT0_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct madt_processor_apic,f,o)
#define ACPI_MADT2_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct madt_interrupt_override,f,o)
#define ACPI_MADT3_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct madt_nmi_source,f,o)
#define ACPI_MADT4_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct madt_local_apic_nmi,f,o)
#define ACPI_MADT7_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct madt_local_sapic,f,o)
#define ACPI_MADT8_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (struct madt_interrupt_source,f,o)
/* Reset to default packing */ /* Reset to default packing */
......
...@@ -191,7 +191,7 @@ typedef s32 acpi_native_int; ...@@ -191,7 +191,7 @@ typedef s32 acpi_native_int;
typedef u64 acpi_table_ptr; typedef u64 acpi_table_ptr;
typedef u32 acpi_io_address; typedef u32 acpi_io_address;
typedef u64 acpi_physical_address; typedef u32 acpi_physical_address;
#define ACPI_MAX_PTR ACPI_UINT32_MAX #define ACPI_MAX_PTR ACPI_UINT32_MAX
#define ACPI_SIZE_MAX ACPI_UINT32_MAX #define ACPI_SIZE_MAX ACPI_UINT32_MAX
...@@ -311,36 +311,6 @@ typedef acpi_native_uint acpi_size; ...@@ -311,36 +311,6 @@ typedef acpi_native_uint acpi_size;
* *
******************************************************************************/ ******************************************************************************/
/*
* Pointer overlays to avoid lots of typecasting for
* code that accepts both physical and logical pointers.
*/
union acpi_pointers {
acpi_physical_address physical;
void *logical;
acpi_table_ptr value;
};
struct acpi_pointer {
u32 pointer_type;
union acpi_pointers pointer;
};
/* pointer_types for above */
#define ACPI_PHYSICAL_POINTER 0x01
#define ACPI_LOGICAL_POINTER 0x02
/* Processor mode */
#define ACPI_PHYSICAL_ADDRESSING 0x04
#define ACPI_LOGICAL_ADDRESSING 0x08
#define ACPI_MEMORY_MODE 0x0C
#define ACPI_PHYSMODE_PHYSPTR ACPI_PHYSICAL_ADDRESSING | ACPI_PHYSICAL_POINTER
#define ACPI_LOGMODE_PHYSPTR ACPI_LOGICAL_ADDRESSING | ACPI_PHYSICAL_POINTER
#define ACPI_LOGMODE_LOGPTR ACPI_LOGICAL_ADDRESSING | ACPI_LOGICAL_POINTER
/* Logical defines and NULL */ /* Logical defines and NULL */
#ifdef FALSE #ifdef FALSE
...@@ -490,21 +460,6 @@ typedef u64 acpi_integer; ...@@ -490,21 +460,6 @@ typedef u64 acpi_integer;
#define ACPI_NOTIFY_BUS_MODE_MISMATCH (u8) 6 #define ACPI_NOTIFY_BUS_MODE_MISMATCH (u8) 6
#define ACPI_NOTIFY_POWER_FAULT (u8) 7 #define ACPI_NOTIFY_POWER_FAULT (u8) 7
/*
* Table types. These values are passed to the table related APIs
*/
typedef u32 acpi_table_type;
#define ACPI_TABLE_ID_RSDP (acpi_table_type) 0
#define ACPI_TABLE_ID_DSDT (acpi_table_type) 1
#define ACPI_TABLE_ID_FADT (acpi_table_type) 2
#define ACPI_TABLE_ID_FACS (acpi_table_type) 3
#define ACPI_TABLE_ID_PSDT (acpi_table_type) 4
#define ACPI_TABLE_ID_SSDT (acpi_table_type) 5
#define ACPI_TABLE_ID_XSDT (acpi_table_type) 6
#define ACPI_TABLE_ID_MAX 6
#define ACPI_NUM_TABLE_TYPES (ACPI_TABLE_ID_MAX+1)
/* /*
* Types associated with ACPI names and objects. The first group of * Types associated with ACPI names and objects. The first group of
* values (up to ACPI_TYPE_EXTERNAL_MAX) correspond to the definition * values (up to ACPI_TYPE_EXTERNAL_MAX) correspond to the definition
...@@ -815,13 +770,6 @@ struct acpi_buffer { ...@@ -815,13 +770,6 @@ struct acpi_buffer {
#define ACPI_SYS_MODE_LEGACY 0x0002 #define ACPI_SYS_MODE_LEGACY 0x0002
#define ACPI_SYS_MODES_MASK 0x0003 #define ACPI_SYS_MODES_MASK 0x0003
/*
* ACPI Table Info. One per ACPI table _type_
*/
struct acpi_table_info {
u32 count;
};
/* /*
* System info returned by acpi_get_system_info() * System info returned by acpi_get_system_info()
*/ */
...@@ -833,8 +781,6 @@ struct acpi_system_info { ...@@ -833,8 +781,6 @@ struct acpi_system_info {
u32 reserved2; u32 reserved2;
u32 debug_level; u32 debug_level;
u32 debug_layer; u32 debug_layer;
u32 num_table_types;
struct acpi_table_info table_info[ACPI_TABLE_ID_MAX + 1];
}; };
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment