Merge back earlier ACPICA material.

This commit is contained in:
Rafael J. Wysocki 2014-05-07 00:45:27 +02:00
commit 23a75c52be
38 changed files with 4824 additions and 1445 deletions

View File

@ -237,7 +237,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
This feature is enabled by default. This feature is enabled by default.
This option allows to turn off the feature. This option allows to turn off the feature.
acpi_no_auto_ssdt [HW,ACPI] Disable automatic loading of SSDT acpi_no_static_ssdt [HW,ACPI]
Disable installation of static SSDTs at early boot time
By default, SSDTs contained in the RSDT/XSDT will be
installed automatically and they will appear under
/sys/firmware/acpi/tables.
This option turns off this feature.
Note that specifying this option does not affect
dynamic table installation which will install SSDT
tables to /sys/firmware/acpi/tables/dynamic.
acpica_no_return_repair [HW, ACPI] acpica_no_return_repair [HW, ACPI]
Disable AML predefined validation mechanism Disable AML predefined validation mechanism

View File

@ -135,6 +135,7 @@ acpi-y += \
rsxface.o rsxface.o
acpi-y += \ acpi-y += \
tbdata.o \
tbfadt.o \ tbfadt.o \
tbfind.o \ tbfind.o \
tbinstal.o \ tbinstal.o \

View File

@ -0,0 +1,170 @@
/******************************************************************************
*
* Module Name: acapps - common include for ACPI applications/tools
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2014, Intel Corp.
* 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.
*/
#ifndef _ACAPPS
#define _ACAPPS
/* Common info for tool signons */
#define ACPICA_NAME "Intel ACPI Component Architecture"
#define ACPICA_COPYRIGHT "Copyright (c) 2000 - 2014 Intel Corporation"
#if ACPI_MACHINE_WIDTH == 64
#define ACPI_WIDTH "-64"
#elif ACPI_MACHINE_WIDTH == 32
#define ACPI_WIDTH "-32"
#else
#error unknown ACPI_MACHINE_WIDTH
#define ACPI_WIDTH "-??"
#endif
/* Macros for signons and file headers */
#define ACPI_COMMON_SIGNON(utility_name) \
"\n%s\n%s version %8.8X%s [%s]\n%s\n\n", \
ACPICA_NAME, \
utility_name, ((u32) ACPI_CA_VERSION), ACPI_WIDTH, __DATE__, \
ACPICA_COPYRIGHT
#define ACPI_COMMON_HEADER(utility_name, prefix) \
"%s%s\n%s%s version %8.8X%s [%s]\n%s%s\n%s\n", \
prefix, ACPICA_NAME, \
prefix, utility_name, ((u32) ACPI_CA_VERSION), ACPI_WIDTH, __DATE__, \
prefix, ACPICA_COPYRIGHT, \
prefix
/* Macros for usage messages */
#define ACPI_USAGE_HEADER(usage) \
printf ("Usage: %s\nOptions:\n", usage);
#define ACPI_OPTION(name, description) \
printf (" %-18s%s\n", name, description);
#define FILE_SUFFIX_DISASSEMBLY "dsl"
#define ACPI_TABLE_FILE_SUFFIX ".dat"
/*
* getopt
*/
int acpi_getopt(int argc, char **argv, char *opts);
int acpi_getopt_argument(int argc, char **argv);
extern int acpi_gbl_optind;
extern int acpi_gbl_opterr;
extern int acpi_gbl_sub_opt_char;
extern char *acpi_gbl_optarg;
/*
* cmfsize - Common get file size function
*/
u32 cm_get_file_size(FILE * file);
#ifndef ACPI_DUMP_APP
/*
* adisasm
*/
acpi_status
ad_aml_disassemble(u8 out_to_file,
char *filename, char *prefix, char **out_filename);
void ad_print_statistics(void);
acpi_status ad_find_dsdt(u8 **dsdt_ptr, u32 *dsdt_length);
void ad_dump_tables(void);
acpi_status ad_get_local_tables(void);
acpi_status
ad_parse_table(struct acpi_table_header *table,
acpi_owner_id * owner_id, u8 load_table, u8 external);
acpi_status ad_display_tables(char *filename, struct acpi_table_header *table);
acpi_status ad_display_statistics(void);
/*
* adwalk
*/
void
acpi_dm_cross_reference_namespace(union acpi_parse_object *parse_tree_root,
struct acpi_namespace_node *namespace_root,
acpi_owner_id owner_id);
void acpi_dm_dump_tree(union acpi_parse_object *origin);
void acpi_dm_find_orphan_methods(union acpi_parse_object *origin);
void
acpi_dm_finish_namespace_load(union acpi_parse_object *parse_tree_root,
struct acpi_namespace_node *namespace_root,
acpi_owner_id owner_id);
void
acpi_dm_convert_resource_indexes(union acpi_parse_object *parse_tree_root,
struct acpi_namespace_node *namespace_root);
/*
* adfile
*/
acpi_status ad_initialize(void);
char *fl_generate_filename(char *input_filename, char *suffix);
acpi_status
fl_split_input_pathname(char *input_path,
char **out_directory_path, char **out_filename);
char *ad_generate_filename(char *prefix, char *table_id);
void
ad_write_table(struct acpi_table_header *table,
u32 length, char *table_name, char *oem_table_id);
#endif
#endif /* _ACAPPS */

View File

@ -103,8 +103,8 @@ ACPI_INIT_GLOBAL(u8, acpi_gbl_auto_serialize_methods, TRUE);
/* /*
* Create the predefined _OSI method in the namespace? Default is TRUE * Create the predefined _OSI method in the namespace? Default is TRUE
* because ACPI CA is fully compatible with other ACPI implementations. * because ACPICA is fully compatible with other ACPI implementations.
* Changing this will revert ACPI CA (and machine ASL) to pre-OSI behavior. * Changing this will revert ACPICA (and machine ASL) to pre-OSI behavior.
*/ */
ACPI_INIT_GLOBAL(u8, acpi_gbl_create_osi_method, TRUE); ACPI_INIT_GLOBAL(u8, acpi_gbl_create_osi_method, TRUE);
@ -160,10 +160,10 @@ ACPI_INIT_GLOBAL(u8, acpi_gbl_truncate_io_addresses, FALSE);
ACPI_INIT_GLOBAL(u8, acpi_gbl_disable_auto_repair, FALSE); ACPI_INIT_GLOBAL(u8, acpi_gbl_disable_auto_repair, FALSE);
/* /*
* Optionally do not load any SSDTs from the RSDT/XSDT during initialization. * Optionally do not install any SSDTs from the RSDT/XSDT during initialization.
* This can be useful for debugging ACPI problems on some machines. * This can be useful for debugging ACPI problems on some machines.
*/ */
ACPI_INIT_GLOBAL(u8, acpi_gbl_disable_ssdt_table_load, FALSE); ACPI_INIT_GLOBAL(u8, acpi_gbl_disable_ssdt_table_install, FALSE);
/* /*
* We keep track of the latest version of Windows that has been requested by * We keep track of the latest version of Windows that has been requested by
@ -509,5 +509,6 @@ ACPI_INIT_GLOBAL(ACPI_FILE, acpi_gbl_debug_file, NULL);
****************************************************************************/ ****************************************************************************/
extern const struct ah_predefined_name asl_predefined_info[]; extern const struct ah_predefined_name asl_predefined_info[];
extern const struct ah_device_id asl_device_ids[];
#endif /* __ACGLOBAL_H__ */ #endif /* __ACGLOBAL_H__ */

View File

@ -733,7 +733,8 @@ union acpi_parse_value {
#define ACPI_DASM_MATCHOP 0x06 /* Parent opcode is a Match() operator */ #define ACPI_DASM_MATCHOP 0x06 /* Parent opcode is a Match() operator */
#define ACPI_DASM_LNOT_PREFIX 0x07 /* Start of a Lnot_equal (etc.) pair of opcodes */ #define ACPI_DASM_LNOT_PREFIX 0x07 /* Start of a Lnot_equal (etc.) pair of opcodes */
#define ACPI_DASM_LNOT_SUFFIX 0x08 /* End of a Lnot_equal (etc.) pair of opcodes */ #define ACPI_DASM_LNOT_SUFFIX 0x08 /* End of a Lnot_equal (etc.) pair of opcodes */
#define ACPI_DASM_IGNORE 0x09 /* Not used at this time */ #define ACPI_DASM_HID_STRING 0x09 /* String is a _HID or _CID */
#define ACPI_DASM_IGNORE 0x0A /* Not used at this time */
/* /*
* Generic operation (for example: If, While, Store) * Generic operation (for example: If, While, Store)
@ -1147,4 +1148,9 @@ struct ah_predefined_name {
#endif #endif
}; };
struct ah_device_id {
char *name;
char *description;
};
#endif /* __ACLOCAL_H__ */ #endif /* __ACLOCAL_H__ */

View File

@ -53,6 +53,26 @@ acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp);
u8 *acpi_tb_scan_memory_for_rsdp(u8 *start_address, u32 length); u8 *acpi_tb_scan_memory_for_rsdp(u8 *start_address, u32 length);
/*
* tbdata - table data structure management
*/
acpi_status acpi_tb_get_next_root_index(u32 *table_index);
void
acpi_tb_init_table_descriptor(struct acpi_table_desc *table_desc,
acpi_physical_address address,
u8 flags, struct acpi_table_header *table);
acpi_status
acpi_tb_acquire_temp_table(struct acpi_table_desc *table_desc,
acpi_physical_address address, u8 flags);
void acpi_tb_release_temp_table(struct acpi_table_desc *table_desc);
u8 acpi_tb_is_table_loaded(u32 table_index);
void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded);
/* /*
* tbfadt - FADT parse/convert/validate * tbfadt - FADT parse/convert/validate
*/ */
@ -72,22 +92,35 @@ acpi_tb_find_table(char *signature,
*/ */
acpi_status acpi_tb_resize_root_table_list(void); acpi_status acpi_tb_resize_root_table_list(void);
acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc); acpi_status acpi_tb_validate_table(struct acpi_table_desc *table_desc);
struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header void acpi_tb_invalidate_table(struct acpi_table_desc *table_desc);
*table_header,
struct acpi_table_desc
*table_desc);
acpi_status acpi_status
acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index); acpi_tb_verify_table(struct acpi_table_desc *table_desc, char *signature);
void acpi_tb_override_table(struct acpi_table_desc *old_table_desc);
acpi_status
acpi_tb_acquire_table(struct acpi_table_desc *table_desc,
struct acpi_table_header **table_ptr,
u32 *table_length, u8 *table_flags);
void
acpi_tb_release_table(struct acpi_table_header *table,
u32 table_length, u8 table_flags);
acpi_status
acpi_tb_install_standard_table(acpi_physical_address address,
u8 flags,
u8 reload, u8 override, u32 *table_index);
acpi_status acpi_status
acpi_tb_store_table(acpi_physical_address address, acpi_tb_store_table(acpi_physical_address address,
struct acpi_table_header *table, struct acpi_table_header *table,
u32 length, u8 flags, u32 *table_index); u32 length, u8 flags, u32 *table_index);
void acpi_tb_delete_table(struct acpi_table_desc *table_desc); void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc);
void acpi_tb_terminate(void); void acpi_tb_terminate(void);
@ -99,10 +132,6 @@ acpi_status acpi_tb_release_owner_id(u32 table_index);
acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id *owner_id); acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id *owner_id);
u8 acpi_tb_is_table_loaded(u32 table_index);
void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded);
/* /*
* tbutils - table manager utilities * tbutils - table manager utilities
*/ */
@ -124,8 +153,13 @@ void acpi_tb_check_dsdt_header(void);
struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index); struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index);
void void
acpi_tb_install_table(acpi_physical_address address, acpi_tb_install_table_with_override(u32 table_index,
char *signature, u32 table_index); struct acpi_table_desc *new_table_desc,
u8 override);
acpi_status
acpi_tb_install_fixed_table(acpi_physical_address address,
char *signature, u32 table_index);
acpi_status acpi_tb_parse_root_table(acpi_physical_address rsdp_address); acpi_status acpi_tb_parse_root_table(acpi_physical_address rsdp_address);

View File

@ -176,8 +176,7 @@ acpi_status acpi_ut_init_globals(void);
char *acpi_ut_get_mutex_name(u32 mutex_id); char *acpi_ut_get_mutex_name(u32 mutex_id);
const char *acpi_ut_get_notify_name(u32 notify_value); const char *acpi_ut_get_notify_name(u32 notify_value, acpi_object_type type);
#endif #endif
char *acpi_ut_get_type_name(acpi_object_type type); char *acpi_ut_get_type_name(acpi_object_type type);
@ -737,4 +736,11 @@ acpi_ut_method_error(const char *module_name,
struct acpi_namespace_node *node, struct acpi_namespace_node *node,
const char *path, acpi_status lookup_status); const char *path, acpi_status lookup_status);
/*
* Utility functions for ACPI names and IDs
*/
const struct ah_predefined_name *acpi_ah_match_predefined_name(char *nameseg);
const struct ah_device_id *acpi_ah_match_hardware_id(char *hid);
#endif /* _ACUTILS_H */ #endif /* _ACUTILS_H */

View File

@ -167,7 +167,8 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
"Dispatching Notify on [%4.4s] (%s) Value 0x%2.2X (%s) Node %p\n", "Dispatching Notify on [%4.4s] (%s) Value 0x%2.2X (%s) Node %p\n",
acpi_ut_get_node_name(node), acpi_ut_get_node_name(node),
acpi_ut_get_type_name(node->type), notify_value, acpi_ut_get_type_name(node->type), notify_value,
acpi_ut_get_notify_name(notify_value), node)); acpi_ut_get_notify_name(notify_value, ACPI_TYPE_ANY),
node));
status = acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch, status = acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch,
info); info);

View File

@ -117,7 +117,7 @@ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context)
ACPI_FUNCTION_TRACE(ev_sci_xrupt_handler); ACPI_FUNCTION_TRACE(ev_sci_xrupt_handler);
/* /*
* We are guaranteed by the ACPI CA initialization/shutdown code that * We are guaranteed by the ACPICA initialization/shutdown code that
* if this interrupt handler is installed, ACPI is enabled. * if this interrupt handler is installed, ACPI is enabled.
*/ */

View File

@ -239,7 +239,7 @@ acpi_remove_notify_handler(acpi_handle device,
union acpi_operand_object *obj_desc; union acpi_operand_object *obj_desc;
union acpi_operand_object *handler_obj; union acpi_operand_object *handler_obj;
union acpi_operand_object *previous_handler_obj; union acpi_operand_object *previous_handler_obj;
acpi_status status; acpi_status status = AE_OK;
u32 i; u32 i;
ACPI_FUNCTION_TRACE(acpi_remove_notify_handler); ACPI_FUNCTION_TRACE(acpi_remove_notify_handler);
@ -251,20 +251,17 @@ acpi_remove_notify_handler(acpi_handle device,
return_ACPI_STATUS(AE_BAD_PARAMETER); return_ACPI_STATUS(AE_BAD_PARAMETER);
} }
/* Make sure all deferred notify tasks are completed */
acpi_os_wait_events_complete();
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Root Object. Global handlers are removed here */ /* Root Object. Global handlers are removed here */
if (device == ACPI_ROOT_OBJECT) { if (device == ACPI_ROOT_OBJECT) {
for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
if (handler_type & (i + 1)) { if (handler_type & (i + 1)) {
status =
acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
if (!acpi_gbl_global_notify[i].handler || if (!acpi_gbl_global_notify[i].handler ||
(acpi_gbl_global_notify[i].handler != (acpi_gbl_global_notify[i].handler !=
handler)) { handler)) {
@ -277,31 +274,40 @@ acpi_remove_notify_handler(acpi_handle device,
acpi_gbl_global_notify[i].handler = NULL; acpi_gbl_global_notify[i].handler = NULL;
acpi_gbl_global_notify[i].context = NULL; acpi_gbl_global_notify[i].context = NULL;
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
/* Make sure all deferred notify tasks are completed */
acpi_os_wait_events_complete();
} }
} }
goto unlock_and_exit; return_ACPI_STATUS(AE_OK);
} }
/* All other objects: Are Notifies allowed on this object? */ /* All other objects: Are Notifies allowed on this object? */
if (!acpi_ev_is_notify_object(node)) { if (!acpi_ev_is_notify_object(node)) {
status = AE_TYPE; return_ACPI_STATUS(AE_TYPE);
goto unlock_and_exit;
} }
/* Must have an existing internal object */ /* Must have an existing internal object */
obj_desc = acpi_ns_get_attached_object(node); obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) { if (!obj_desc) {
status = AE_NOT_EXIST; return_ACPI_STATUS(AE_NOT_EXIST);
goto unlock_and_exit;
} }
/* Internal object exists. Find the handler and remove it */ /* Internal object exists. Find the handler and remove it */
for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
if (handler_type & (i + 1)) { if (handler_type & (i + 1)) {
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
handler_obj = obj_desc->common_notify.notify_list[i]; handler_obj = obj_desc->common_notify.notify_list[i];
previous_handler_obj = NULL; previous_handler_obj = NULL;
@ -329,10 +335,17 @@ acpi_remove_notify_handler(acpi_handle device,
handler_obj->notify.next[i]; handler_obj->notify.next[i];
} }
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
/* Make sure all deferred notify tasks are completed */
acpi_os_wait_events_complete();
acpi_ut_remove_reference(handler_obj); acpi_ut_remove_reference(handler_obj);
} }
} }
return_ACPI_STATUS(status);
unlock_and_exit: unlock_and_exit:
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
@ -457,6 +470,8 @@ exit:
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
ACPI_EXPORT_SYMBOL(acpi_install_sci_handler)
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_remove_sci_handler * FUNCTION: acpi_remove_sci_handler
@ -468,7 +483,6 @@ exit:
* DESCRIPTION: Remove a handler for a System Control Interrupt. * DESCRIPTION: Remove a handler for a System Control Interrupt.
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_remove_sci_handler(acpi_sci_handler address) acpi_status acpi_remove_sci_handler(acpi_sci_handler address)
{ {
struct acpi_sci_handler_info *prev_sci_handler; struct acpi_sci_handler_info *prev_sci_handler;
@ -522,6 +536,8 @@ unlock_and_exit:
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
ACPI_EXPORT_SYMBOL(acpi_remove_sci_handler)
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_install_global_event_handler * FUNCTION: acpi_install_global_event_handler
@ -537,7 +553,6 @@ unlock_and_exit:
* Can be used to update event counters, etc. * Can be used to update event counters, etc.
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_status
acpi_install_global_event_handler(acpi_gbl_event_handler handler, void *context) acpi_install_global_event_handler(acpi_gbl_event_handler handler, void *context)
{ {
@ -840,10 +855,6 @@ acpi_remove_gpe_handler(acpi_handle gpe_device,
return_ACPI_STATUS(AE_BAD_PARAMETER); return_ACPI_STATUS(AE_BAD_PARAMETER);
} }
/* Make sure all deferred GPE tasks are completed */
acpi_os_wait_events_complete();
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
@ -895,9 +906,17 @@ acpi_remove_gpe_handler(acpi_handle gpe_device,
(void)acpi_ev_add_gpe_reference(gpe_event_info); (void)acpi_ev_add_gpe_reference(gpe_event_info);
} }
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
/* Make sure all deferred GPE tasks are completed */
acpi_os_wait_events_complete();
/* Now we can free the handler object */ /* Now we can free the handler object */
ACPI_FREE(handler); ACPI_FREE(handler);
return_ACPI_STATUS(status);
unlock_and_exit: unlock_and_exit:
acpi_os_release_lock(acpi_gbl_gpe_lock, flags); acpi_os_release_lock(acpi_gbl_gpe_lock, flags);

View File

@ -343,16 +343,14 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
struct acpi_walk_state *walk_state) struct acpi_walk_state *walk_state)
{ {
union acpi_operand_object *ddb_handle; union acpi_operand_object *ddb_handle;
struct acpi_table_header *table_header;
struct acpi_table_header *table; struct acpi_table_header *table;
struct acpi_table_desc table_desc;
u32 table_index; u32 table_index;
acpi_status status; acpi_status status;
u32 length; u32 length;
ACPI_FUNCTION_TRACE(ex_load_op); ACPI_FUNCTION_TRACE(ex_load_op);
ACPI_MEMSET(&table_desc, 0, sizeof(struct acpi_table_desc));
/* Source Object can be either an op_region or a Buffer/Field */ /* Source Object can be either an op_region or a Buffer/Field */
switch (obj_desc->common.type) { switch (obj_desc->common.type) {
@ -380,17 +378,17 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
/* Get the table header first so we can get the table length */ /* Get the table header first so we can get the table length */
table = ACPI_ALLOCATE(sizeof(struct acpi_table_header)); table_header = ACPI_ALLOCATE(sizeof(struct acpi_table_header));
if (!table) { if (!table_header) {
return_ACPI_STATUS(AE_NO_MEMORY); return_ACPI_STATUS(AE_NO_MEMORY);
} }
status = status =
acpi_ex_region_read(obj_desc, acpi_ex_region_read(obj_desc,
sizeof(struct acpi_table_header), sizeof(struct acpi_table_header),
ACPI_CAST_PTR(u8, table)); ACPI_CAST_PTR(u8, table_header));
length = table->length; length = table_header->length;
ACPI_FREE(table); ACPI_FREE(table_header);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
@ -420,22 +418,19 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
/* Allocate a buffer for the table */ /* Allocate a buffer for the table */
table_desc.pointer = ACPI_ALLOCATE(length); table = ACPI_ALLOCATE(length);
if (!table_desc.pointer) { if (!table) {
return_ACPI_STATUS(AE_NO_MEMORY); return_ACPI_STATUS(AE_NO_MEMORY);
} }
/* Read the entire table */ /* Read the entire table */
status = acpi_ex_region_read(obj_desc, length, status = acpi_ex_region_read(obj_desc, length,
ACPI_CAST_PTR(u8, ACPI_CAST_PTR(u8, table));
table_desc.pointer));
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
ACPI_FREE(table_desc.pointer); ACPI_FREE(table);
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
table_desc.address = obj_desc->region.address;
break; break;
case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */ case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */
@ -452,10 +447,10 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
/* Get the actual table length from the table header */ /* Get the actual table length from the table header */
table = table_header =
ACPI_CAST_PTR(struct acpi_table_header, ACPI_CAST_PTR(struct acpi_table_header,
obj_desc->buffer.pointer); obj_desc->buffer.pointer);
length = table->length; length = table_header->length;
/* Table cannot extend beyond the buffer */ /* Table cannot extend beyond the buffer */
@ -470,13 +465,12 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
* Copy the table from the buffer because the buffer could be modified * Copy the table from the buffer because the buffer could be modified
* or even deleted in the future * or even deleted in the future
*/ */
table_desc.pointer = ACPI_ALLOCATE(length); table = ACPI_ALLOCATE(length);
if (!table_desc.pointer) { if (!table) {
return_ACPI_STATUS(AE_NO_MEMORY); return_ACPI_STATUS(AE_NO_MEMORY);
} }
ACPI_MEMCPY(table_desc.pointer, table, length); ACPI_MEMCPY(table, table_header, length);
table_desc.address = ACPI_TO_INTEGER(table_desc.pointer);
break; break;
default: default:
@ -484,27 +478,32 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
return_ACPI_STATUS(AE_AML_OPERAND_TYPE); return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
} }
/* Validate table checksum (will not get validated in tb_add_table) */
status = acpi_tb_verify_checksum(table_desc.pointer, length);
if (ACPI_FAILURE(status)) {
ACPI_FREE(table_desc.pointer);
return_ACPI_STATUS(status);
}
/* Complete the table descriptor */
table_desc.length = length;
table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED;
/* Install the new table into the local data structures */ /* Install the new table into the local data structures */
status = acpi_tb_add_table(&table_desc, &table_index); ACPI_INFO((AE_INFO, "Dynamic OEM Table Load:"));
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
status = acpi_tb_install_standard_table(ACPI_PTR_TO_PHYSADDR(table),
ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL,
TRUE, TRUE, &table_index);
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
/* Delete allocated table buffer */ /* Delete allocated table buffer */
acpi_tb_delete_table(&table_desc); ACPI_FREE(table);
return_ACPI_STATUS(status);
}
/*
* Note: Now table is "INSTALLED", it must be validated before
* loading.
*/
status =
acpi_tb_validate_table(&acpi_gbl_root_table_list.
tables[table_index]);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
@ -536,9 +535,6 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
ACPI_INFO((AE_INFO, "Dynamic OEM Table Load:"));
acpi_tb_print_table_header(0, table_desc.pointer);
/* Remove the reference by added by acpi_ex_store above */ /* Remove the reference by added by acpi_ex_store above */
acpi_ut_remove_reference(ddb_handle); acpi_ut_remove_reference(ddb_handle);
@ -546,8 +542,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
/* Invoke table handler if present */ /* Invoke table handler if present */
if (acpi_gbl_table_handler) { if (acpi_gbl_table_handler) {
(void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table,
table_desc.pointer,
acpi_gbl_table_handler_context); acpi_gbl_table_handler_context);
} }
@ -575,6 +570,13 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
ACPI_FUNCTION_TRACE(ex_unload_table); ACPI_FUNCTION_TRACE(ex_unload_table);
/*
* Temporarily emit a warning so that the ASL for the machine can be
* hopefully obtained. This is to say that the Unload() operator is
* extremely rare if not completely unused.
*/
ACPI_WARNING((AE_INFO, "Received request to unload an ACPI table"));
/* /*
* Validate the handle * Validate the handle
* Although the handle is partially validated in acpi_ex_reconfiguration() * Although the handle is partially validated in acpi_ex_reconfiguration()

View File

@ -134,9 +134,11 @@ static struct acpi_exdump_info acpi_ex_dump_method[9] = {
{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(method.aml_start), "Aml Start"} {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(method.aml_start), "Aml Start"}
}; };
static struct acpi_exdump_info acpi_ex_dump_mutex[5] = { static struct acpi_exdump_info acpi_ex_dump_mutex[6] = {
{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_mutex), NULL}, {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_mutex), NULL},
{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(mutex.sync_level), "Sync Level"}, {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(mutex.sync_level), "Sync Level"},
{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(mutex.original_sync_level),
"Original Sync Level"},
{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.owner_thread), "Owner Thread"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.owner_thread), "Owner Thread"},
{ACPI_EXD_UINT16, ACPI_EXD_OFFSET(mutex.acquisition_depth), {ACPI_EXD_UINT16, ACPI_EXD_OFFSET(mutex.acquisition_depth),
"Acquire Depth"}, "Acquire Depth"},

View File

@ -0,0 +1,723 @@
/******************************************************************************
*
* Module Name: tbdata - Table manager data structure functions
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2014, Intel Corp.
* 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 "accommon.h"
#include "acnamesp.h"
#include "actables.h"
#define _COMPONENT ACPI_TABLES
ACPI_MODULE_NAME("tbdata")
/*******************************************************************************
*
* FUNCTION: acpi_tb_init_table_descriptor
*
* PARAMETERS: table_desc - Table descriptor
* address - Physical address of the table
* flags - Allocation flags of the table
* table - Pointer to the table
*
* RETURN: None
*
* DESCRIPTION: Initialize a new table descriptor
*
******************************************************************************/
void
acpi_tb_init_table_descriptor(struct acpi_table_desc *table_desc,
acpi_physical_address address,
u8 flags, struct acpi_table_header *table)
{
/*
* Initialize the table descriptor. Set the pointer to NULL, since the
* table is not fully mapped at this time.
*/
ACPI_MEMSET(table_desc, 0, sizeof(struct acpi_table_desc));
table_desc->address = address;
table_desc->length = table->length;
table_desc->flags = flags;
ACPI_MOVE_32_TO_32(table_desc->signature.ascii, table->signature);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_acquire_table
*
* PARAMETERS: table_desc - Table descriptor
* table_ptr - Where table is returned
* table_length - Where table length is returned
* table_flags - Where table allocation flags are returned
*
* RETURN: Status
*
* DESCRIPTION: Acquire an ACPI table. It can be used for tables not
* maintained in the acpi_gbl_root_table_list.
*
******************************************************************************/
acpi_status
acpi_tb_acquire_table(struct acpi_table_desc *table_desc,
struct acpi_table_header **table_ptr,
u32 *table_length, u8 *table_flags)
{
struct acpi_table_header *table = NULL;
switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) {
case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
table =
acpi_os_map_memory(table_desc->address, table_desc->length);
break;
case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
table =
ACPI_CAST_PTR(struct acpi_table_header,
table_desc->address);
break;
default:
break;
}
/* Table is not valid yet */
if (!table) {
return (AE_NO_MEMORY);
}
/* Fill the return values */
*table_ptr = table;
*table_length = table_desc->length;
*table_flags = table_desc->flags;
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_release_table
*
* PARAMETERS: table - Pointer for the table
* table_length - Length for the table
* table_flags - Allocation flags for the table
*
* RETURN: None
*
* DESCRIPTION: Release a table. The inverse of acpi_tb_acquire_table().
*
******************************************************************************/
void
acpi_tb_release_table(struct acpi_table_header *table,
u32 table_length, u8 table_flags)
{
switch (table_flags & ACPI_TABLE_ORIGIN_MASK) {
case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
acpi_os_unmap_memory(table, table_length);
break;
case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
default:
break;
}
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_acquire_temp_table
*
* PARAMETERS: table_desc - Table descriptor to be acquired
* address - Address of the table
* flags - Allocation flags of the table
*
* RETURN: Status
*
* DESCRIPTION: This function validates the table header to obtain the length
* of a table and fills the table descriptor to make its state as
* "INSTALLED". Such a table descriptor is only used for verified
* installation.
*
******************************************************************************/
acpi_status
acpi_tb_acquire_temp_table(struct acpi_table_desc *table_desc,
acpi_physical_address address, u8 flags)
{
struct acpi_table_header *table_header;
switch (flags & ACPI_TABLE_ORIGIN_MASK) {
case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
/* Get the length of the full table from the header */
table_header =
acpi_os_map_memory(address,
sizeof(struct acpi_table_header));
if (!table_header) {
return (AE_NO_MEMORY);
}
acpi_tb_init_table_descriptor(table_desc, address, flags,
table_header);
acpi_os_unmap_memory(table_header,
sizeof(struct acpi_table_header));
return (AE_OK);
case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
table_header = ACPI_CAST_PTR(struct acpi_table_header, address);
if (!table_header) {
return (AE_NO_MEMORY);
}
acpi_tb_init_table_descriptor(table_desc, address, flags,
table_header);
return (AE_OK);
default:
break;
}
/* Table is not valid yet */
return (AE_NO_MEMORY);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_release_temp_table
*
* PARAMETERS: table_desc - Table descriptor to be released
*
* RETURN: Status
*
* DESCRIPTION: The inverse of acpi_tb_acquire_temp_table().
*
*****************************************************************************/
void acpi_tb_release_temp_table(struct acpi_table_desc *table_desc)
{
/*
* Note that the .Address is maintained by the callers of
* acpi_tb_acquire_temp_table(), thus do not invoke acpi_tb_uninstall_table()
* where .Address will be freed.
*/
acpi_tb_invalidate_table(table_desc);
}
/******************************************************************************
*
* FUNCTION: acpi_tb_validate_table
*
* PARAMETERS: table_desc - Table descriptor
*
* RETURN: Status
*
* DESCRIPTION: This function is called to validate the table, the returned
* table descriptor is in "VALIDATED" state.
*
*****************************************************************************/
acpi_status acpi_tb_validate_table(struct acpi_table_desc *table_desc)
{
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE(tb_validate_table);
/* Validate the table if necessary */
if (!table_desc->pointer) {
status = acpi_tb_acquire_table(table_desc, &table_desc->pointer,
&table_desc->length,
&table_desc->flags);
if (!table_desc->pointer) {
status = AE_NO_MEMORY;
}
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_invalidate_table
*
* PARAMETERS: table_desc - Table descriptor
*
* RETURN: None
*
* DESCRIPTION: Invalidate one internal ACPI table, this is the inverse of
* acpi_tb_validate_table().
*
******************************************************************************/
void acpi_tb_invalidate_table(struct acpi_table_desc *table_desc)
{
ACPI_FUNCTION_TRACE(tb_invalidate_table);
/* Table must be validated */
if (!table_desc->pointer) {
return_VOID;
}
acpi_tb_release_table(table_desc->pointer, table_desc->length,
table_desc->flags);
table_desc->pointer = NULL;
return_VOID;
}
/******************************************************************************
*
* FUNCTION: acpi_tb_verify_table
*
* PARAMETERS: table_desc - Table descriptor
* signature - Table signature to verify
*
* RETURN: Status
*
* DESCRIPTION: This function is called to validate and verify the table, the
* returned table descriptor is in "VALIDATED" state.
*
*****************************************************************************/
acpi_status
acpi_tb_verify_table(struct acpi_table_desc *table_desc, char *signature)
{
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE(tb_verify_table);
/* Validate the table */
status = acpi_tb_validate_table(table_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* If a particular signature is expected (DSDT/FACS), it must match */
if (signature && !ACPI_COMPARE_NAME(&table_desc->signature, signature)) {
ACPI_BIOS_ERROR((AE_INFO,
"Invalid signature 0x%X for ACPI table, expected [%s]",
table_desc->signature.integer, signature));
status = AE_BAD_SIGNATURE;
goto invalidate_and_exit;
}
/* Verify the checksum */
status =
acpi_tb_verify_checksum(table_desc->pointer, table_desc->length);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY,
"%4.4s " ACPI_PRINTF_UINT
" Attempted table install failed",
acpi_ut_valid_acpi_name(table_desc->signature.
ascii) ? table_desc->
signature.ascii : "????",
ACPI_FORMAT_TO_UINT(table_desc->address)));
goto invalidate_and_exit;
}
return_ACPI_STATUS(AE_OK);
invalidate_and_exit:
acpi_tb_invalidate_table(table_desc);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_resize_root_table_list
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Expand the size of global table array
*
******************************************************************************/
acpi_status acpi_tb_resize_root_table_list(void)
{
struct acpi_table_desc *tables;
u32 table_count;
ACPI_FUNCTION_TRACE(tb_resize_root_table_list);
/* allow_resize flag is a parameter to acpi_initialize_tables */
if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) {
ACPI_ERROR((AE_INFO,
"Resize of Root Table Array is not allowed"));
return_ACPI_STATUS(AE_SUPPORT);
}
/* Increase the Table Array size */
if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
table_count = acpi_gbl_root_table_list.max_table_count;
} else {
table_count = acpi_gbl_root_table_list.current_table_count;
}
tables = ACPI_ALLOCATE_ZEROED(((acpi_size) table_count +
ACPI_ROOT_TABLE_SIZE_INCREMENT) *
sizeof(struct acpi_table_desc));
if (!tables) {
ACPI_ERROR((AE_INFO,
"Could not allocate new root table array"));
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Copy and free the previous table array */
if (acpi_gbl_root_table_list.tables) {
ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables,
(acpi_size) table_count *
sizeof(struct acpi_table_desc));
if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
ACPI_FREE(acpi_gbl_root_table_list.tables);
}
}
acpi_gbl_root_table_list.tables = tables;
acpi_gbl_root_table_list.max_table_count =
table_count + ACPI_ROOT_TABLE_SIZE_INCREMENT;
acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED;
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_next_root_index
*
* PARAMETERS: table_index - Where table index is returned
*
* RETURN: Status and table index.
*
* DESCRIPTION: Allocate a new ACPI table entry to the global table list
*
******************************************************************************/
acpi_status acpi_tb_get_next_root_index(u32 *table_index)
{
acpi_status status;
/* Ensure that there is room for the table in the Root Table List */
if (acpi_gbl_root_table_list.current_table_count >=
acpi_gbl_root_table_list.max_table_count) {
status = acpi_tb_resize_root_table_list();
if (ACPI_FAILURE(status)) {
return (status);
}
}
*table_index = acpi_gbl_root_table_list.current_table_count;
acpi_gbl_root_table_list.current_table_count++;
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_terminate
*
* PARAMETERS: None
*
* RETURN: None
*
* DESCRIPTION: Delete all internal ACPI tables
*
******************************************************************************/
void acpi_tb_terminate(void)
{
u32 i;
ACPI_FUNCTION_TRACE(tb_terminate);
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
/* Delete the individual tables */
for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) {
acpi_tb_uninstall_table(&acpi_gbl_root_table_list.tables[i]);
}
/*
* Delete the root table array if allocated locally. Array cannot be
* mapped, so we don't need to check for that flag.
*/
if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
ACPI_FREE(acpi_gbl_root_table_list.tables);
}
acpi_gbl_root_table_list.tables = NULL;
acpi_gbl_root_table_list.flags = 0;
acpi_gbl_root_table_list.current_table_count = 0;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n"));
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
return_VOID;
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_delete_namespace_by_owner
*
* PARAMETERS: table_index - Table index
*
* RETURN: Status
*
* DESCRIPTION: Delete all namespace objects created when this table was loaded.
*
******************************************************************************/
acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index)
{
acpi_owner_id owner_id;
acpi_status status;
ACPI_FUNCTION_TRACE(tb_delete_namespace_by_owner);
status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
if (table_index >= acpi_gbl_root_table_list.current_table_count) {
/* The table index does not exist */
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
return_ACPI_STATUS(AE_NOT_EXIST);
}
/* Get the owner ID for this table, used to delete namespace nodes */
owner_id = acpi_gbl_root_table_list.tables[table_index].owner_id;
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
/*
* Need to acquire the namespace writer lock to prevent interference
* with any concurrent namespace walks. The interpreter must be
* released during the deletion since the acquisition of the deletion
* lock may block, and also since the execution of a namespace walk
* must be allowed to use the interpreter.
*/
(void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
status = acpi_ut_acquire_write_lock(&acpi_gbl_namespace_rw_lock);
acpi_ns_delete_namespace_by_owner(owner_id);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
acpi_ut_release_write_lock(&acpi_gbl_namespace_rw_lock);
status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_allocate_owner_id
*
* PARAMETERS: table_index - Table index
*
* RETURN: Status
*
* DESCRIPTION: Allocates owner_id in table_desc
*
******************************************************************************/
acpi_status acpi_tb_allocate_owner_id(u32 table_index)
{
acpi_status status = AE_BAD_PARAMETER;
ACPI_FUNCTION_TRACE(tb_allocate_owner_id);
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
if (table_index < acpi_gbl_root_table_list.current_table_count) {
status =
acpi_ut_allocate_owner_id(&
(acpi_gbl_root_table_list.
tables[table_index].owner_id));
}
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_release_owner_id
*
* PARAMETERS: table_index - Table index
*
* RETURN: Status
*
* DESCRIPTION: Releases owner_id in table_desc
*
******************************************************************************/
acpi_status acpi_tb_release_owner_id(u32 table_index)
{
acpi_status status = AE_BAD_PARAMETER;
ACPI_FUNCTION_TRACE(tb_release_owner_id);
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
if (table_index < acpi_gbl_root_table_list.current_table_count) {
acpi_ut_release_owner_id(&
(acpi_gbl_root_table_list.
tables[table_index].owner_id));
status = AE_OK;
}
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_owner_id
*
* PARAMETERS: table_index - Table index
* owner_id - Where the table owner_id is returned
*
* RETURN: Status
*
* DESCRIPTION: returns owner_id for the ACPI table
*
******************************************************************************/
acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id * owner_id)
{
acpi_status status = AE_BAD_PARAMETER;
ACPI_FUNCTION_TRACE(tb_get_owner_id);
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
if (table_index < acpi_gbl_root_table_list.current_table_count) {
*owner_id =
acpi_gbl_root_table_list.tables[table_index].owner_id;
status = AE_OK;
}
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_is_table_loaded
*
* PARAMETERS: table_index - Index into the root table
*
* RETURN: Table Loaded Flag
*
******************************************************************************/
u8 acpi_tb_is_table_loaded(u32 table_index)
{
u8 is_loaded = FALSE;
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
if (table_index < acpi_gbl_root_table_list.current_table_count) {
is_loaded = (u8)
(acpi_gbl_root_table_list.tables[table_index].flags &
ACPI_TABLE_IS_LOADED);
}
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
return (is_loaded);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_set_table_loaded_flag
*
* PARAMETERS: table_index - Table index
* is_loaded - TRUE if table is loaded, FALSE otherwise
*
* RETURN: None
*
* DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
*
******************************************************************************/
void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded)
{
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
if (table_index < acpi_gbl_root_table_list.current_table_count) {
if (is_loaded) {
acpi_gbl_root_table_list.tables[table_index].flags |=
ACPI_TABLE_IS_LOADED;
} else {
acpi_gbl_root_table_list.tables[table_index].flags &=
~ACPI_TABLE_IS_LOADED;
}
}
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
}

View File

@ -332,15 +332,15 @@ void acpi_tb_parse_fadt(u32 table_index)
/* Obtain the DSDT and FACS tables via their addresses within the FADT */ /* Obtain the DSDT and FACS tables via their addresses within the FADT */
acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xdsdt, acpi_tb_install_fixed_table((acpi_physical_address) acpi_gbl_FADT.Xdsdt,
ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT); ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT);
/* If Hardware Reduced flag is set, there is no FACS */ /* If Hardware Reduced flag is set, there is no FACS */
if (!acpi_gbl_reduced_hardware) { if (!acpi_gbl_reduced_hardware) {
acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT. acpi_tb_install_fixed_table((acpi_physical_address)
Xfacs, ACPI_SIG_FACS, acpi_gbl_FADT.Xfacs, ACPI_SIG_FACS,
ACPI_TABLE_INDEX_FACS); ACPI_TABLE_INDEX_FACS);
} }
} }

View File

@ -99,8 +99,8 @@ acpi_tb_find_table(char *signature,
/* Table is not currently mapped, map it */ /* Table is not currently mapped, map it */
status = status =
acpi_tb_verify_table(&acpi_gbl_root_table_list. acpi_tb_validate_table(&acpi_gbl_root_table_list.
tables[i]); tables[i]);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }

File diff suppressed because it is too large Load Diff

View File

@ -178,9 +178,13 @@ struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index)
} }
ACPI_MEMCPY(new_table, table_desc->pointer, table_desc->length); ACPI_MEMCPY(new_table, table_desc->pointer, table_desc->length);
acpi_tb_delete_table(table_desc); acpi_tb_uninstall_table(table_desc);
table_desc->pointer = new_table;
table_desc->flags = ACPI_TABLE_ORIGIN_ALLOCATED; acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list.
tables[ACPI_TABLE_INDEX_DSDT],
ACPI_PTR_TO_PHYSADDR(new_table),
ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL,
new_table);
ACPI_INFO((AE_INFO, ACPI_INFO((AE_INFO,
"Forced DSDT copy: length 0x%05X copied locally, original unmapped", "Forced DSDT copy: length 0x%05X copied locally, original unmapped",
@ -189,116 +193,6 @@ struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index)
return (new_table); return (new_table);
} }
/*******************************************************************************
*
* FUNCTION: acpi_tb_install_table
*
* PARAMETERS: address - Physical address of DSDT or FACS
* signature - Table signature, NULL if no need to
* match
* table_index - Index into root table array
*
* RETURN: None
*
* DESCRIPTION: Install an ACPI table into the global data structure. The
* table override mechanism is called to allow the host
* OS to replace any table before it is installed in the root
* table array.
*
******************************************************************************/
void
acpi_tb_install_table(acpi_physical_address address,
char *signature, u32 table_index)
{
struct acpi_table_header *table;
struct acpi_table_header *final_table;
struct acpi_table_desc *table_desc;
if (!address) {
ACPI_ERROR((AE_INFO,
"Null physical address for ACPI table [%s]",
signature));
return;
}
/* Map just the table header */
table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
if (!table) {
ACPI_ERROR((AE_INFO,
"Could not map memory for table [%s] at %p",
signature, ACPI_CAST_PTR(void, address)));
return;
}
/* If a particular signature is expected (DSDT/FACS), it must match */
if (signature && !ACPI_COMPARE_NAME(table->signature, signature)) {
ACPI_BIOS_ERROR((AE_INFO,
"Invalid signature 0x%X for ACPI table, expected [%s]",
*ACPI_CAST_PTR(u32, table->signature),
signature));
goto unmap_and_exit;
}
/*
* Initialize the table entry. Set the pointer to NULL, since the
* table is not fully mapped at this time.
*/
table_desc = &acpi_gbl_root_table_list.tables[table_index];
table_desc->address = address;
table_desc->pointer = NULL;
table_desc->length = table->length;
table_desc->flags = ACPI_TABLE_ORIGIN_MAPPED;
ACPI_MOVE_32_TO_32(table_desc->signature.ascii, table->signature);
/*
* ACPI Table Override:
*
* Before we install the table, let the host OS override it with a new
* one if desired. Any table within the RSDT/XSDT can be replaced,
* including the DSDT which is pointed to by the FADT.
*
* NOTE: If the table is overridden, then final_table will contain a
* mapped pointer to the full new table. If the table is not overridden,
* or if there has been a physical override, then the table will be
* fully mapped later (in verify table). In any case, we must
* unmap the header that was mapped above.
*/
final_table = acpi_tb_table_override(table, table_desc);
if (!final_table) {
final_table = table; /* There was no override */
}
acpi_tb_print_table_header(table_desc->address, final_table);
/* Set the global integer width (based upon revision of the DSDT) */
if (table_index == ACPI_TABLE_INDEX_DSDT) {
acpi_ut_set_integer_width(final_table->revision);
}
/*
* If we have a physical override during this early loading of the ACPI
* tables, unmap the table for now. It will be mapped again later when
* it is actually used. This supports very early loading of ACPI tables,
* before virtual memory is fully initialized and running within the
* host OS. Note: A logical override has the ACPI_TABLE_ORIGIN_OVERRIDE
* flag set and will not be deleted below.
*/
if (final_table != table) {
acpi_tb_delete_table(table_desc);
}
unmap_and_exit:
/* Always unmap the table header that we mapped above */
acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
}
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_tb_get_root_table_entry * FUNCTION: acpi_tb_get_root_table_entry
@ -465,6 +359,7 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
u32 length; u32 length;
u8 *table_entry; u8 *table_entry;
acpi_status status; acpi_status status;
u32 table_index;
ACPI_FUNCTION_TRACE(tb_parse_root_table); ACPI_FUNCTION_TRACE(tb_parse_root_table);
@ -576,31 +471,24 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
/* Initialize the root table array from the RSDT/XSDT */ /* Initialize the root table array from the RSDT/XSDT */
for (i = 0; i < table_count; i++) { for (i = 0; i < table_count; i++) {
if (acpi_gbl_root_table_list.current_table_count >=
acpi_gbl_root_table_list.max_table_count) {
/* There is no more room in the root table array, attempt resize */
status = acpi_tb_resize_root_table_list();
if (ACPI_FAILURE(status)) {
ACPI_WARNING((AE_INFO,
"Truncating %u table entries!",
(unsigned) (table_count -
(acpi_gbl_root_table_list.
current_table_count -
2))));
break;
}
}
/* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */ /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */
acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list. status =
current_table_count].address = acpi_tb_install_standard_table(acpi_tb_get_root_table_entry
acpi_tb_get_root_table_entry(table_entry, table_entry_size); (table_entry,
table_entry_size),
ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL,
FALSE, TRUE, &table_index);
if (ACPI_SUCCESS(status) &&
ACPI_COMPARE_NAME(&acpi_gbl_root_table_list.
tables[table_index].signature,
ACPI_SIG_FADT)) {
acpi_tb_parse_fadt(table_index);
}
table_entry += table_entry_size; table_entry += table_entry_size;
acpi_gbl_root_table_list.current_table_count++;
} }
/* /*
@ -609,22 +497,5 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
*/ */
acpi_os_unmap_memory(table, length); acpi_os_unmap_memory(table, length);
/*
* Complete the initialization of the root table array by examining
* the header of each table
*/
for (i = 2; i < acpi_gbl_root_table_list.current_table_count; i++) {
acpi_tb_install_table(acpi_gbl_root_table_list.tables[i].
address, NULL, i);
/* Special case for FADT - validate it then get the DSDT and FACS */
if (ACPI_COMPARE_NAME
(&acpi_gbl_root_table_list.tables[i].signature,
ACPI_SIG_FADT)) {
acpi_tb_parse_fadt(i);
}
}
return_ACPI_STATUS(AE_OK); return_ACPI_STATUS(AE_OK);
} }

View File

@ -206,8 +206,8 @@ acpi_status
acpi_get_table_header(char *signature, acpi_get_table_header(char *signature,
u32 instance, struct acpi_table_header *out_table_header) u32 instance, struct acpi_table_header *out_table_header)
{ {
u32 i; u32 i;
u32 j; u32 j;
struct acpi_table_header *header; struct acpi_table_header *header;
/* Parameter validation */ /* Parameter validation */
@ -233,7 +233,7 @@ acpi_get_table_header(char *signature,
if (!acpi_gbl_root_table_list.tables[i].pointer) { if (!acpi_gbl_root_table_list.tables[i].pointer) {
if ((acpi_gbl_root_table_list.tables[i].flags & if ((acpi_gbl_root_table_list.tables[i].flags &
ACPI_TABLE_ORIGIN_MASK) == ACPI_TABLE_ORIGIN_MASK) ==
ACPI_TABLE_ORIGIN_MAPPED) { ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL) {
header = header =
acpi_os_map_memory(acpi_gbl_root_table_list. acpi_os_map_memory(acpi_gbl_root_table_list.
tables[i].address, tables[i].address,
@ -321,8 +321,8 @@ acpi_get_table_with_size(char *signature,
u32 instance, struct acpi_table_header **out_table, u32 instance, struct acpi_table_header **out_table,
acpi_size *tbl_size) acpi_size *tbl_size)
{ {
u32 i; u32 i;
u32 j; u32 j;
acpi_status status; acpi_status status;
/* Parameter validation */ /* Parameter validation */
@ -346,7 +346,7 @@ acpi_get_table_with_size(char *signature,
} }
status = status =
acpi_tb_verify_table(&acpi_gbl_root_table_list.tables[i]); acpi_tb_validate_table(&acpi_gbl_root_table_list.tables[i]);
if (ACPI_SUCCESS(status)) { if (ACPI_SUCCESS(status)) {
*out_table = acpi_gbl_root_table_list.tables[i].pointer; *out_table = acpi_gbl_root_table_list.tables[i].pointer;
*tbl_size = acpi_gbl_root_table_list.tables[i].length; *tbl_size = acpi_gbl_root_table_list.tables[i].length;
@ -390,7 +390,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_table)
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_status
acpi_get_table_by_index(u32 table_index, struct acpi_table_header **table) acpi_get_table_by_index(u32 table_index, struct acpi_table_header ** table)
{ {
acpi_status status; acpi_status status;
@ -416,8 +416,8 @@ acpi_get_table_by_index(u32 table_index, struct acpi_table_header **table)
/* Table is not mapped, map it */ /* Table is not mapped, map it */
status = status =
acpi_tb_verify_table(&acpi_gbl_root_table_list. acpi_tb_validate_table(&acpi_gbl_root_table_list.
tables[table_index]); tables[table_index]);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES); (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
return_ACPI_STATUS(status); return_ACPI_STATUS(status);

View File

@ -117,7 +117,7 @@ static acpi_status acpi_tb_load_namespace(void)
tables[ACPI_TABLE_INDEX_DSDT].signature), tables[ACPI_TABLE_INDEX_DSDT].signature),
ACPI_SIG_DSDT) ACPI_SIG_DSDT)
|| ||
ACPI_FAILURE(acpi_tb_verify_table ACPI_FAILURE(acpi_tb_validate_table
(&acpi_gbl_root_table_list. (&acpi_gbl_root_table_list.
tables[ACPI_TABLE_INDEX_DSDT]))) { tables[ACPI_TABLE_INDEX_DSDT]))) {
status = AE_NO_ACPI_TABLES; status = AE_NO_ACPI_TABLES;
@ -128,7 +128,7 @@ static acpi_status acpi_tb_load_namespace(void)
* Save the DSDT pointer for simple access. This is the mapped memory * Save the DSDT pointer for simple access. This is the mapped memory
* address. We must take care here because the address of the .Tables * address. We must take care here because the address of the .Tables
* array can change dynamically as tables are loaded at run-time. Note: * array can change dynamically as tables are loaded at run-time. Note:
* .Pointer field is not validated until after call to acpi_tb_verify_table. * .Pointer field is not validated until after call to acpi_tb_validate_table.
*/ */
acpi_gbl_DSDT = acpi_gbl_DSDT =
acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer; acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer;
@ -174,24 +174,11 @@ static acpi_status acpi_tb_load_namespace(void)
(acpi_gbl_root_table_list.tables[i]. (acpi_gbl_root_table_list.tables[i].
signature), ACPI_SIG_PSDT)) signature), ACPI_SIG_PSDT))
|| ||
ACPI_FAILURE(acpi_tb_verify_table ACPI_FAILURE(acpi_tb_validate_table
(&acpi_gbl_root_table_list.tables[i]))) { (&acpi_gbl_root_table_list.tables[i]))) {
continue; continue;
} }
/*
* Optionally do not load any SSDTs from the RSDT/XSDT. This can
* be useful for debugging ACPI problems on some machines.
*/
if (acpi_gbl_disable_ssdt_table_load) {
ACPI_INFO((AE_INFO, "Ignoring %4.4s at %p",
acpi_gbl_root_table_list.tables[i].signature.
ascii, ACPI_CAST_PTR(void,
acpi_gbl_root_table_list.
tables[i].address)));
continue;
}
/* Ignore errors while loading tables, get as many as possible */ /* Ignore errors while loading tables, get as many as possible */
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES); (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
@ -206,6 +193,45 @@ unlock_and_exit:
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
/*******************************************************************************
*
* FUNCTION: acpi_install_table
*
* PARAMETERS: address - Address of the ACPI table to be installed.
* physical - Whether the address is a physical table
* address or not
*
* RETURN: Status
*
* DESCRIPTION: Dynamically install an ACPI table.
* Note: This function should only be invoked after
* acpi_initialize_tables() and before acpi_load_tables().
*
******************************************************************************/
acpi_status __init
acpi_install_table(acpi_physical_address address, u8 physical)
{
acpi_status status;
u8 flags;
u32 table_index;
ACPI_FUNCTION_TRACE(acpi_install_table);
if (physical) {
flags = ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL;
} else {
flags = ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL;
}
status = acpi_tb_install_standard_table(address, flags,
FALSE, FALSE, &table_index);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL_INIT(acpi_install_table)
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_load_table * FUNCTION: acpi_load_table
@ -222,11 +248,9 @@ unlock_and_exit:
* to ensure that the table is not deleted or unmapped. * to ensure that the table is not deleted or unmapped.
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_load_table(struct acpi_table_header *table) acpi_status acpi_load_table(struct acpi_table_header *table)
{ {
acpi_status status; acpi_status status;
struct acpi_table_desc table_desc;
u32 table_index; u32 table_index;
ACPI_FUNCTION_TRACE(acpi_load_table); ACPI_FUNCTION_TRACE(acpi_load_table);
@ -237,14 +261,6 @@ acpi_status acpi_load_table(struct acpi_table_header *table)
return_ACPI_STATUS(AE_BAD_PARAMETER); return_ACPI_STATUS(AE_BAD_PARAMETER);
} }
/* Init local table descriptor */
ACPI_MEMSET(&table_desc, 0, sizeof(struct acpi_table_desc));
table_desc.address = ACPI_PTR_TO_PHYSADDR(table);
table_desc.pointer = table;
table_desc.length = table->length;
table_desc.flags = ACPI_TABLE_ORIGIN_UNKNOWN;
/* Must acquire the interpreter lock during this operation */ /* Must acquire the interpreter lock during this operation */
status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER);
@ -255,7 +271,24 @@ acpi_status acpi_load_table(struct acpi_table_header *table)
/* Install the table and load it into the namespace */ /* Install the table and load it into the namespace */
ACPI_INFO((AE_INFO, "Host-directed Dynamic ACPI Table Load:")); ACPI_INFO((AE_INFO, "Host-directed Dynamic ACPI Table Load:"));
status = acpi_tb_add_table(&table_desc, &table_index); (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
status = acpi_tb_install_standard_table(ACPI_PTR_TO_PHYSADDR(table),
ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL,
TRUE, FALSE, &table_index);
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
/*
* Note: Now table is "INSTALLED", it must be validated before
* using.
*/
status =
acpi_tb_validate_table(&acpi_gbl_root_table_list.
tables[table_index]);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
goto unlock_and_exit; goto unlock_and_exit;
} }

View File

@ -462,7 +462,7 @@ char *acpi_ut_get_mutex_name(u32 mutex_id)
/* Names for Notify() values, used for debug output */ /* Names for Notify() values, used for debug output */
static const char *acpi_gbl_notify_value_names[ACPI_NOTIFY_MAX + 1] = { static const char *acpi_gbl_generic_notify[ACPI_NOTIFY_MAX + 1] = {
/* 00 */ "Bus Check", /* 00 */ "Bus Check",
/* 01 */ "Device Check", /* 01 */ "Device Check",
/* 02 */ "Device Wake", /* 02 */ "Device Wake",
@ -473,23 +473,75 @@ static const char *acpi_gbl_notify_value_names[ACPI_NOTIFY_MAX + 1] = {
/* 07 */ "Power Fault", /* 07 */ "Power Fault",
/* 08 */ "Capabilities Check", /* 08 */ "Capabilities Check",
/* 09 */ "Device PLD Check", /* 09 */ "Device PLD Check",
/* 10 */ "Reserved", /* 0A */ "Reserved",
/* 11 */ "System Locality Update", /* 0B */ "System Locality Update",
/* 12 */ "Shutdown Request" /* 0C */ "Shutdown Request"
}; };
const char *acpi_ut_get_notify_name(u32 notify_value) static const char *acpi_gbl_device_notify[4] = {
/* 80 */ "Status Change",
/* 81 */ "Information Change",
/* 82 */ "Device-Specific Change",
/* 83 */ "Device-Specific Change"
};
static const char *acpi_gbl_processor_notify[4] = {
/* 80 */ "Performance Capability Change",
/* 81 */ "C-State Change",
/* 82 */ "Throttling Capability Change",
/* 83 */ "Device-Specific Change"
};
static const char *acpi_gbl_thermal_notify[4] = {
/* 80 */ "Thermal Status Change",
/* 81 */ "Thermal Trip Point Change",
/* 82 */ "Thermal Device List Change",
/* 83 */ "Thermal Relationship Change"
};
const char *acpi_ut_get_notify_name(u32 notify_value, acpi_object_type type)
{ {
/* 00 - 0C are common to all object types */
if (notify_value <= ACPI_NOTIFY_MAX) { if (notify_value <= ACPI_NOTIFY_MAX) {
return (acpi_gbl_notify_value_names[notify_value]); return (acpi_gbl_generic_notify[notify_value]);
} else if (notify_value <= ACPI_MAX_SYS_NOTIFY) {
return ("Reserved");
} else if (notify_value <= ACPI_MAX_DEVICE_SPECIFIC_NOTIFY) {
return ("Device Specific");
} else {
return ("Hardware Specific");
} }
/* 0D - 7F are reserved */
if (notify_value <= ACPI_MAX_SYS_NOTIFY) {
return ("Reserved");
}
/* 80 - 83 are per-object-type */
if (notify_value <= 0x83) {
switch (type) {
case ACPI_TYPE_ANY:
case ACPI_TYPE_DEVICE:
return (acpi_gbl_device_notify[notify_value - 0x80]);
case ACPI_TYPE_PROCESSOR:
return (acpi_gbl_processor_notify[notify_value - 0x80]);
case ACPI_TYPE_THERMAL:
return (acpi_gbl_thermal_notify[notify_value - 0x80]);
default:
return ("Target object type does not support notifies");
}
}
/* 84 - BF are device-specific */
if (notify_value <= ACPI_MAX_DEVICE_SPECIFIC_NOTIFY) {
return ("Device-Specific");
}
/* C0 and above are hardware-specific */
return ("Hardware-Specific");
} }
#endif #endif

View File

@ -353,7 +353,7 @@ void acpi_ut_print_string(char *string, u16 max_length)
} }
acpi_os_printf("\""); acpi_os_printf("\"");
for (i = 0; string[i] && (i < max_length); i++) { for (i = 0; (i < max_length) && string[i]; i++) {
/* Escape sequences */ /* Escape sequences */

View File

@ -1770,16 +1770,15 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
} }
#endif #endif
static int __init acpi_no_auto_ssdt_setup(char *s) static int __init acpi_no_static_ssdt_setup(char *s)
{ {
printk(KERN_NOTICE PREFIX "SSDT auto-load disabled\n"); acpi_gbl_disable_ssdt_table_install = TRUE;
pr_info("ACPI: static SSDT installation disabled\n");
acpi_gbl_disable_ssdt_table_load = TRUE; return 0;
return 1;
} }
__setup("acpi_no_auto_ssdt", acpi_no_auto_ssdt_setup); early_param("acpi_no_static_ssdt", acpi_no_static_ssdt_setup);
static int __init acpi_disable_return_repair(char *s) static int __init acpi_disable_return_repair(char *s)
{ {

View File

@ -46,7 +46,7 @@
/* Current ACPICA subsystem version in YYYYMMDD format */ /* Current ACPICA subsystem version in YYYYMMDD format */
#define ACPI_CA_VERSION 0x20140214 #define ACPI_CA_VERSION 0x20140325
#include <acpi/acconfig.h> #include <acpi/acconfig.h>
#include <acpi/actypes.h> #include <acpi/actypes.h>
@ -75,7 +75,7 @@ extern u8 acpi_gbl_auto_serialize_methods;
extern u8 acpi_gbl_copy_dsdt_locally; extern u8 acpi_gbl_copy_dsdt_locally;
extern u8 acpi_gbl_create_osi_method; extern u8 acpi_gbl_create_osi_method;
extern u8 acpi_gbl_disable_auto_repair; extern u8 acpi_gbl_disable_auto_repair;
extern u8 acpi_gbl_disable_ssdt_table_load; extern u8 acpi_gbl_disable_ssdt_table_install;
extern u8 acpi_gbl_do_not_use_xsdt; extern u8 acpi_gbl_do_not_use_xsdt;
extern u8 acpi_gbl_enable_aml_debug_object; extern u8 acpi_gbl_enable_aml_debug_object;
extern u8 acpi_gbl_enable_interpreter_slack; extern u8 acpi_gbl_enable_interpreter_slack;
@ -164,6 +164,9 @@ acpi_decode_pld_buffer(u8 *in_buffer,
/* /*
* ACPI table load/unload interfaces * ACPI table load/unload interfaces
*/ */
acpi_status __init
acpi_install_table(acpi_physical_address address, u8 physical);
acpi_status acpi_load_table(struct acpi_table_header *table); acpi_status acpi_load_table(struct acpi_table_header *table);
acpi_status acpi_unload_parent_table(acpi_handle object); acpi_status acpi_unload_parent_table(acpi_handle object);

View File

@ -367,12 +367,11 @@ struct acpi_table_desc {
/* Masks for Flags field above */ /* Masks for Flags field above */
#define ACPI_TABLE_ORIGIN_UNKNOWN (0) #define ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL (0) /* Virtual address, external maintained */
#define ACPI_TABLE_ORIGIN_MAPPED (1) #define ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL (1) /* Physical address, internally mapped */
#define ACPI_TABLE_ORIGIN_ALLOCATED (2) #define ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL (2) /* Virtual address, internallly allocated */
#define ACPI_TABLE_ORIGIN_OVERRIDE (4) #define ACPI_TABLE_ORIGIN_MASK (3)
#define ACPI_TABLE_ORIGIN_MASK (7) #define ACPI_TABLE_IS_LOADED (8)
#define ACPI_TABLE_IS_LOADED (8)
/* /*
* Get the remaining ACPI tables * Get the remaining ACPI tables

View File

@ -64,4 +64,15 @@
*/ */
#define ACPI_UNUSED_VAR __attribute__ ((unused)) #define ACPI_UNUSED_VAR __attribute__ ((unused))
/*
* Some versions of gcc implement strchr() with a buggy macro. So,
* undef it here. Prevents error messages of this form (usually from the
* file getopt.c):
*
* error: logical '&&' with non-zero constant will always evaluate as true
*/
#ifdef strchr
#undef strchr
#endif
#endif /* __ACGCC_H__ */ #endif /* __ACGCC_H__ */

View File

@ -91,7 +91,7 @@
#include <ctype.h> #include <ctype.h>
#include <unistd.h> #include <unistd.h>
/* Disable kernel specific declarators */ /* Define/disable kernel-specific declarators */
#ifndef __init #ifndef __init
#define __init #define __init
@ -106,7 +106,8 @@
#define ACPI_FLUSH_CPU_CACHE() #define ACPI_FLUSH_CPU_CACHE()
#define ACPI_CAST_PTHREAD_T(pthread) ((acpi_thread_id) (pthread)) #define ACPI_CAST_PTHREAD_T(pthread) ((acpi_thread_id) (pthread))
#if defined(__ia64__) || defined(__x86_64__) || defined(__aarch64__) #if defined(__ia64__) || defined(__x86_64__) ||\
defined(__aarch64__) || defined(__PPC64__)
#define ACPI_MACHINE_WIDTH 64 #define ACPI_MACHINE_WIDTH 64
#define COMPILER_DEPENDENT_INT64 long #define COMPILER_DEPENDENT_INT64 long
#define COMPILER_DEPENDENT_UINT64 unsigned long #define COMPILER_DEPENDENT_UINT64 unsigned long

View File

@ -68,7 +68,8 @@ WARNINGS += $(call cc-supports,-Wstrict-prototypes)
WARNINGS += $(call cc-supports,-Wdeclaration-after-statement) WARNINGS += $(call cc-supports,-Wdeclaration-after-statement)
KERNEL_INCLUDE := ../../../include KERNEL_INCLUDE := ../../../include
CFLAGS += -D_LINUX -DDEFINE_ALTERNATE_TYPES -I$(KERNEL_INCLUDE) ACPICA_INCLUDE := ../../../drivers/acpi/acpica
CFLAGS += -D_LINUX -I$(KERNEL_INCLUDE) -I$(ACPICA_INCLUDE)
CFLAGS += $(WARNINGS) CFLAGS += $(WARNINGS)
ifeq ($(strip $(V)),false) ifeq ($(strip $(V)),false)
@ -92,10 +93,29 @@ endif
# --- ACPIDUMP BEGIN --- # --- ACPIDUMP BEGIN ---
vpath %.c \ vpath %.c \
tools/acpidump ../../../drivers/acpi/acpica\
tools/acpidump\
common\
os_specific/service_layers
CFLAGS += -DACPI_DUMP_APP -Itools/acpidump
DUMP_OBJS = \ DUMP_OBJS = \
acpidump.o apdump.o\
apfiles.o\
apmain.o\
osunixdir.o\
osunixmap.o\
tbprint.o\
tbxfroot.o\
utbuffer.o\
utexcep.o\
utmath.o\
utstring.o\
utxferror.o\
oslinuxtbl.o\
cmfsize.o\
getopt.o
DUMP_OBJS := $(addprefix $(OUTPUT)tools/acpidump/,$(DUMP_OBJS)) DUMP_OBJS := $(addprefix $(OUTPUT)tools/acpidump/,$(DUMP_OBJS))

View File

@ -0,0 +1,101 @@
/******************************************************************************
*
* Module Name: cfsize - Common get file size function
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2014, Intel Corp.
* 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 "accommon.h"
#include "acapps.h"
#include <stdio.h>
#define _COMPONENT ACPI_TOOLS
ACPI_MODULE_NAME("cmfsize")
/*******************************************************************************
*
* FUNCTION: cm_get_file_size
*
* PARAMETERS: file - Open file descriptor
*
* RETURN: File Size. On error, -1 (ACPI_UINT32_MAX)
*
* DESCRIPTION: Get the size of a file. Uses seek-to-EOF. File must be open.
* Does not disturb the current file pointer. Uses perror for
* error messages.
*
******************************************************************************/
u32 cm_get_file_size(FILE * file)
{
long file_size;
long current_offset;
/* Save the current file pointer, seek to EOF to obtain file size */
current_offset = ftell(file);
if (current_offset < 0) {
goto offset_error;
}
if (fseek(file, 0, SEEK_END)) {
goto seek_error;
}
file_size = ftell(file);
if (file_size < 0) {
goto offset_error;
}
/* Restore original file pointer */
if (fseek(file, current_offset, SEEK_SET)) {
goto seek_error;
}
return ((u32)file_size);
offset_error:
perror("Could not get file offset");
return (ACPI_UINT32_MAX);
seek_error:
perror("Could not seek file");
return (ACPI_UINT32_MAX);
}

View File

@ -0,0 +1,239 @@
/******************************************************************************
*
* Module Name: getopt
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2014, Intel Corp.
* 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.
*/
/*
* ACPICA getopt() implementation
*
* Option strings:
* "f" - Option has no arguments
* "f:" - Option requires an argument
* "f^" - Option has optional single-char sub-options
* "f|" - Option has required single-char sub-options
*/
#include <stdio.h>
#include <string.h>
#include <acpi/acpi.h>
#include "accommon.h"
#include "acapps.h"
#define ACPI_OPTION_ERROR(msg, badchar) \
if (acpi_gbl_opterr) {fprintf (stderr, "%s%c\n", msg, badchar);}
int acpi_gbl_opterr = 1;
int acpi_gbl_optind = 1;
int acpi_gbl_sub_opt_char = 0;
char *acpi_gbl_optarg;
static int current_char_ptr = 1;
/*******************************************************************************
*
* FUNCTION: acpi_getopt_argument
*
* PARAMETERS: argc, argv - from main
*
* RETURN: 0 if an argument was found, -1 otherwise. Sets acpi_gbl_Optarg
* to point to the next argument.
*
* DESCRIPTION: Get the next argument. Used to obtain arguments for the
* two-character options after the original call to acpi_getopt.
* Note: Either the argument starts at the next character after
* the option, or it is pointed to by the next argv entry.
* (After call to acpi_getopt, we need to backup to the previous
* argv entry).
*
******************************************************************************/
int acpi_getopt_argument(int argc, char **argv)
{
acpi_gbl_optind--;
current_char_ptr++;
if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') {
acpi_gbl_optarg =
&argv[acpi_gbl_optind++][(int)(current_char_ptr + 1)];
} else if (++acpi_gbl_optind >= argc) {
ACPI_OPTION_ERROR("Option requires an argument: -", 'v');
current_char_ptr = 1;
return (-1);
} else {
acpi_gbl_optarg = argv[acpi_gbl_optind++];
}
current_char_ptr = 1;
return (0);
}
/*******************************************************************************
*
* FUNCTION: acpi_getopt
*
* PARAMETERS: argc, argv - from main
* opts - options info list
*
* RETURN: Option character or EOF
*
* DESCRIPTION: Get the next option
*
******************************************************************************/
int acpi_getopt(int argc, char **argv, char *opts)
{
int current_char;
char *opts_ptr;
if (current_char_ptr == 1) {
if (acpi_gbl_optind >= argc ||
argv[acpi_gbl_optind][0] != '-' ||
argv[acpi_gbl_optind][1] == '\0') {
return (EOF);
} else if (strcmp(argv[acpi_gbl_optind], "--") == 0) {
acpi_gbl_optind++;
return (EOF);
}
}
/* Get the option */
current_char = argv[acpi_gbl_optind][current_char_ptr];
/* Make sure that the option is legal */
if (current_char == ':' ||
(opts_ptr = strchr(opts, current_char)) == NULL) {
ACPI_OPTION_ERROR("Illegal option: -", current_char);
if (argv[acpi_gbl_optind][++current_char_ptr] == '\0') {
acpi_gbl_optind++;
current_char_ptr = 1;
}
return ('?');
}
/* Option requires an argument? */
if (*++opts_ptr == ':') {
if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') {
acpi_gbl_optarg =
&argv[acpi_gbl_optind++][(int)
(current_char_ptr + 1)];
} else if (++acpi_gbl_optind >= argc) {
ACPI_OPTION_ERROR("Option requires an argument: -",
current_char);
current_char_ptr = 1;
return ('?');
} else {
acpi_gbl_optarg = argv[acpi_gbl_optind++];
}
current_char_ptr = 1;
}
/* Option has an optional argument? */
else if (*opts_ptr == '+') {
if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') {
acpi_gbl_optarg =
&argv[acpi_gbl_optind++][(int)
(current_char_ptr + 1)];
} else if (++acpi_gbl_optind >= argc) {
acpi_gbl_optarg = NULL;
} else {
acpi_gbl_optarg = argv[acpi_gbl_optind++];
}
current_char_ptr = 1;
}
/* Option has optional single-char arguments? */
else if (*opts_ptr == '^') {
if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') {
acpi_gbl_optarg =
&argv[acpi_gbl_optind][(int)(current_char_ptr + 1)];
} else {
acpi_gbl_optarg = "^";
}
acpi_gbl_sub_opt_char = acpi_gbl_optarg[0];
acpi_gbl_optind++;
current_char_ptr = 1;
}
/* Option has a required single-char argument? */
else if (*opts_ptr == '|') {
if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') {
acpi_gbl_optarg =
&argv[acpi_gbl_optind][(int)(current_char_ptr + 1)];
} else {
ACPI_OPTION_ERROR
("Option requires a single-character suboption: -",
current_char);
current_char_ptr = 1;
return ('?');
}
acpi_gbl_sub_opt_char = acpi_gbl_optarg[0];
acpi_gbl_optind++;
current_char_ptr = 1;
}
/* Option with no arguments */
else {
if (argv[acpi_gbl_optind][++current_char_ptr] == '\0') {
current_char_ptr = 1;
acpi_gbl_optind++;
}
acpi_gbl_optarg = NULL;
}
return (current_char);
}

View File

@ -1,18 +1,64 @@
.TH ACPIDUMP 8 .TH ACPIDUMP 8
.SH NAME .SH NAME
acpidump \- Dump system's ACPI tables to an ASCII file. acpidump \- dump a system's ACPI tables to an ASCII file
.SH SYNOPSIS .SH SYNOPSIS
.ft B .B acpidump
.B acpidump > acpidump.out .RI [ options ]
.br
.SH DESCRIPTION .SH DESCRIPTION
\fBacpidump \fP dumps the systems ACPI tables to an ASCII file .B acpidump
appropriate for attaching to a bug report. dumps the systems ACPI tables to an ASCII file appropriate for
attaching to a bug report.
Subsequently, they can be processed by utilities in the ACPICA package. Subsequently, they can be processed by utilities in the ACPICA package.
.SS Options
no options worth worrying about. .SH OPTIONS
.PP acpidump options are as follow:
.SH EXAMPLE .TP
.B Options
.TP
.B \-b
Dump tables to binary files
.TP
.B \-c
Dump customized tables
.TP
.B \-h \-?
This help message
.TP
.B \-o <File>
Redirect output to file
.TP
.B \-r <Address>
Dump tables from specified RSDP
.TP
.B \-s
Print table summaries only
.TP
.B \-v
Display version information
.TP
.B \-z
Verbose mode
.TP
.B Table Options
.TP
.B \-a <Address>
Get table via a physical address
.TP
.B \-f <BinaryFile>
Get table via a binary file
.TP
.B \-n <Signature>
Get table via a name/signature
.TP
Invocation without parameters dumps all available tables
.TP
Multiple mixed instances of -a, -f, and -n are supported
.SH EXAMPLES
.nf .nf
# acpidump > acpidump.out # acpidump > acpidump.out
@ -50,10 +96,25 @@ ACPICA: https://acpica.org/
.ta .ta
.nf .nf
/dev/mem /dev/mem
/sys/firmware/acpi/tables/*
/sys/firmware/acpi/tables/dynamic/* /sys/firmware/acpi/tables/dynamic/*
/sys/firmware/efi/systab
.fi .fi
.PP
.SH AUTHOR .SH AUTHOR
.nf .TP
Written by Len Brown <len.brown@intel.com> Original by:
Len Brown <len.brown@intel.com>
.TP
Written by:
Chao Guan <chao.guan@intel.com>
.TP
Updated by:
Bob Moore <robert.moore@intel.com>
Lv Zheng <lv.zheng@intel.com>
.SH SEE ALSO
\&\fIacpixtract\fR\|(8), \fIiasl\fR\|(8).
.SH COPYRIGHT
COPYRIGHT (c) 2013, Intel Corporation.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,204 @@
/******************************************************************************
*
* Module Name: osunixdir - Unix directory access interfaces
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2014, Intel Corp.
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <fnmatch.h>
#include <ctype.h>
#include <sys/stat.h>
/*
* Allocated structure returned from os_open_directory
*/
typedef struct external_find_info {
char *dir_pathname;
DIR *dir_ptr;
char temp_buffer[256];
char *wildcard_spec;
char requested_file_type;
} external_find_info;
/*******************************************************************************
*
* FUNCTION: acpi_os_open_directory
*
* PARAMETERS: dir_pathname - Full pathname to the directory
* wildcard_spec - string of the form "*.c", etc.
*
* RETURN: A directory "handle" to be used in subsequent search operations.
* NULL returned on failure.
*
* DESCRIPTION: Open a directory in preparation for a wildcard search
*
******************************************************************************/
void *acpi_os_open_directory(char *dir_pathname,
char *wildcard_spec, char requested_file_type)
{
struct external_find_info *external_info;
DIR *dir;
/* Allocate the info struct that will be returned to the caller */
external_info = calloc(1, sizeof(struct external_find_info));
if (!external_info) {
return (NULL);
}
/* Get the directory stream */
dir = opendir(dir_pathname);
if (!dir) {
fprintf(stderr, "Cannot open directory - %s\n", dir_pathname);
free(external_info);
return (NULL);
}
/* Save the info in the return structure */
external_info->wildcard_spec = wildcard_spec;
external_info->requested_file_type = requested_file_type;
external_info->dir_pathname = dir_pathname;
external_info->dir_ptr = dir;
return (external_info);
}
/*******************************************************************************
*
* FUNCTION: acpi_os_get_next_filename
*
* PARAMETERS: dir_handle - Created via acpi_os_open_directory
*
* RETURN: Next filename matched. NULL if no more matches.
*
* DESCRIPTION: Get the next file in the directory that matches the wildcard
* specification.
*
******************************************************************************/
char *acpi_os_get_next_filename(void *dir_handle)
{
struct external_find_info *external_info = dir_handle;
struct dirent *dir_entry;
char *temp_str;
int str_len;
struct stat temp_stat;
int err;
while ((dir_entry = readdir(external_info->dir_ptr))) {
if (!fnmatch
(external_info->wildcard_spec, dir_entry->d_name, 0)) {
if (dir_entry->d_name[0] == '.') {
continue;
}
str_len = strlen(dir_entry->d_name) +
strlen(external_info->dir_pathname) + 2;
temp_str = calloc(str_len, 1);
if (!temp_str) {
fprintf(stderr,
"Could not allocate buffer for temporary string\n");
return (NULL);
}
strcpy(temp_str, external_info->dir_pathname);
strcat(temp_str, "/");
strcat(temp_str, dir_entry->d_name);
err = stat(temp_str, &temp_stat);
if (err == -1) {
fprintf(stderr,
"Cannot stat file (should not happen) - %s\n",
temp_str);
free(temp_str);
return (NULL);
}
free(temp_str);
if ((S_ISDIR(temp_stat.st_mode)
&& (external_info->requested_file_type ==
REQUEST_DIR_ONLY))
|| ((!S_ISDIR(temp_stat.st_mode)
&& external_info->requested_file_type ==
REQUEST_FILE_ONLY))) {
/* copy to a temp buffer because dir_entry struct is on the stack */
strcpy(external_info->temp_buffer,
dir_entry->d_name);
return (external_info->temp_buffer);
}
}
}
return (NULL);
}
/*******************************************************************************
*
* FUNCTION: acpi_os_close_directory
*
* PARAMETERS: dir_handle - Created via acpi_os_open_directory
*
* RETURN: None.
*
* DESCRIPTION: Close the open directory and cleanup.
*
******************************************************************************/
void acpi_os_close_directory(void *dir_handle)
{
struct external_find_info *external_info = dir_handle;
/* Close the directory and free allocations */
closedir(external_info->dir_ptr);
free(dir_handle);
}

View File

@ -0,0 +1,151 @@
/******************************************************************************
*
* Module Name: osunixmap - Unix OSL for file mappings
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2014, Intel Corp.
* 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 "acpidump.h"
#include <unistd.h>
#include <sys/mman.h>
#ifdef _free_BSD
#include <sys/param.h>
#endif
#define _COMPONENT ACPI_OS_SERVICES
ACPI_MODULE_NAME("osunixmap")
#ifndef O_BINARY
#define O_BINARY 0
#endif
#ifdef _free_BSD
#define MMAP_FLAGS MAP_SHARED
#else
#define MMAP_FLAGS MAP_PRIVATE
#endif
#define SYSTEM_MEMORY "/dev/mem"
/*******************************************************************************
*
* FUNCTION: acpi_os_get_page_size
*
* PARAMETERS: None
*
* RETURN: Page size of the platform.
*
* DESCRIPTION: Obtain page size of the platform.
*
******************************************************************************/
static acpi_size acpi_os_get_page_size(void)
{
#ifdef PAGE_SIZE
return PAGE_SIZE;
#else
return sysconf(_SC_PAGESIZE);
#endif
}
/******************************************************************************
*
* FUNCTION: acpi_os_map_memory
*
* PARAMETERS: where - Physical address of memory to be mapped
* length - How much memory to map
*
* RETURN: Pointer to mapped memory. Null on error.
*
* DESCRIPTION: Map physical memory into local address space.
*
*****************************************************************************/
void *acpi_os_map_memory(acpi_physical_address where, acpi_size length)
{
u8 *mapped_memory;
acpi_physical_address offset;
acpi_size page_size;
int fd;
fd = open(SYSTEM_MEMORY, O_RDONLY | O_BINARY);
if (fd < 0) {
fprintf(stderr, "Cannot open %s\n", SYSTEM_MEMORY);
return (NULL);
}
/* Align the offset to use mmap */
page_size = acpi_os_get_page_size();
offset = where % page_size;
/* Map the table header to get the length of the full table */
mapped_memory = mmap(NULL, (length + offset), PROT_READ, MMAP_FLAGS,
fd, (where - offset));
if (mapped_memory == MAP_FAILED) {
fprintf(stderr, "Cannot map %s\n", SYSTEM_MEMORY);
close(fd);
return (NULL);
}
close(fd);
return (ACPI_CAST8(mapped_memory + offset));
}
/******************************************************************************
*
* FUNCTION: acpi_os_unmap_memory
*
* PARAMETERS: where - Logical address of memory to be unmapped
* length - How much memory to unmap
*
* RETURN: None.
*
* DESCRIPTION: Delete a previously created mapping. Where and Length must
* correspond to a previous mapping exactly.
*
*****************************************************************************/
void acpi_os_unmap_memory(void *where, acpi_size length)
{
acpi_physical_address offset;
acpi_size page_size;
page_size = acpi_os_get_page_size();
offset = (acpi_physical_address) where % page_size;
munmap((u8 *)where - offset, (length + offset));
}

View File

@ -1,559 +0,0 @@
/*
* (c) Alexey Starikovskiy, Intel, 2005-2006.
* 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.
*/
#ifdef DEFINE_ALTERNATE_TYPES
/* hack to enable building old application with new headers -lenb */
#define acpi_fadt_descriptor acpi_table_fadt
#define acpi_rsdp_descriptor acpi_table_rsdp
#define DSDT_SIG ACPI_SIG_DSDT
#define FACS_SIG ACPI_SIG_FACS
#define FADT_SIG ACPI_SIG_FADT
#define xfirmware_ctrl Xfacs
#define firmware_ctrl facs
typedef int s32;
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long long s64;
#endif
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <dirent.h>
#include <acpi/acconfig.h>
#include <acpi/platform/acenv.h>
#include <acpi/actypes.h>
#include <acpi/actbl.h>
static inline u8 checksum(u8 * buffer, u32 length)
{
u8 sum = 0, *i = buffer;
buffer += length;
for (; i < buffer; sum += *(i++));
return sum;
}
static unsigned long psz, addr, length;
static int print, connect, skip;
static u8 select_sig[4];
static unsigned long read_efi_systab( void )
{
char buffer[80];
unsigned long addr;
FILE *f = fopen("/sys/firmware/efi/systab", "r");
if (f) {
while (fgets(buffer, 80, f)) {
if (sscanf(buffer, "ACPI20=0x%lx", &addr) == 1)
return addr;
}
fclose(f);
}
return 0;
}
static u8 *acpi_map_memory(unsigned long where, unsigned length)
{
unsigned long offset;
u8 *there;
int fd = open("/dev/mem", O_RDONLY);
if (fd < 0) {
fprintf(stderr, "acpi_os_map_memory: cannot open /dev/mem\n");
exit(1);
}
offset = where % psz;
there = mmap(NULL, length + offset, PROT_READ, MAP_PRIVATE,
fd, where - offset);
close(fd);
if (there == MAP_FAILED) return 0;
return (there + offset);
}
static void acpi_unmap_memory(u8 * there, unsigned length)
{
unsigned long offset = (unsigned long)there % psz;
munmap(there - offset, length + offset);
}
static struct acpi_table_header *acpi_map_table(unsigned long where, char *sig)
{
unsigned size;
struct acpi_table_header *tbl = (struct acpi_table_header *)
acpi_map_memory(where, sizeof(struct acpi_table_header));
if (!tbl || (sig && memcmp(sig, tbl->signature, 4))) return 0;
size = tbl->length;
acpi_unmap_memory((u8 *) tbl, sizeof(struct acpi_table_header));
return (struct acpi_table_header *)acpi_map_memory(where, size);
}
static void acpi_unmap_table(struct acpi_table_header *tbl)
{
acpi_unmap_memory((u8 *)tbl, tbl->length);
}
static struct acpi_rsdp_descriptor *acpi_scan_for_rsdp(u8 *begin, u32 length)
{
struct acpi_rsdp_descriptor *rsdp;
u8 *i, *end = begin + length;
/* Search from given start address for the requested length */
for (i = begin; i < end; i += ACPI_RSDP_SCAN_STEP) {
/* The signature and checksum must both be correct */
if (memcmp((char *)i, "RSD PTR ", 8)) continue;
rsdp = (struct acpi_rsdp_descriptor *)i;
/* Signature matches, check the appropriate checksum */
if (!checksum((u8 *) rsdp, (rsdp->revision < 2) ?
ACPI_RSDP_CHECKSUM_LENGTH :
ACPI_RSDP_XCHECKSUM_LENGTH))
/* Checksum valid, we have found a valid RSDP */
return rsdp;
}
/* Searched entire block, no RSDP was found */
return 0;
}
/*
* Output data
*/
static void acpi_show_data(int fd, u8 * data, int size)
{
char buffer[256];
int len;
int i, remain = size;
while (remain > 0) {
len = snprintf(buffer, 256, " %04x:", size - remain);
for (i = 0; i < 16 && i < remain; i++) {
len +=
snprintf(&buffer[len], 256 - len, " %02x", data[i]);
}
for (; i < 16; i++) {
len += snprintf(&buffer[len], 256 - len, " ");
}
len += snprintf(&buffer[len], 256 - len, " ");
for (i = 0; i < 16 && i < remain; i++) {
buffer[len++] = (isprint(data[i])) ? data[i] : '.';
}
buffer[len++] = '\n';
write(fd, buffer, len);
data += 16;
remain -= 16;
}
}
/*
* Output ACPI table
*/
static void acpi_show_table(int fd, struct acpi_table_header *table, unsigned long addr)
{
char buff[80];
int len = snprintf(buff, 80, "%.4s @ %p\n", table->signature, (void *)addr);
write(fd, buff, len);
acpi_show_data(fd, (u8 *) table, table->length);
buff[0] = '\n';
write(fd, buff, 1);
}
static void write_table(int fd, struct acpi_table_header *tbl, unsigned long addr)
{
static int select_done = 0;
if (!select_sig[0]) {
if (print) {
acpi_show_table(fd, tbl, addr);
} else {
write(fd, tbl, tbl->length);
}
} else if (!select_done && !memcmp(select_sig, tbl->signature, 4)) {
if (skip > 0) {
--skip;
return;
}
if (print) {
acpi_show_table(fd, tbl, addr);
} else {
write(fd, tbl, tbl->length);
}
select_done = 1;
}
}
static void acpi_dump_FADT(int fd, struct acpi_table_header *tbl, unsigned long xaddr) {
struct acpi_fadt_descriptor x;
unsigned long addr;
size_t len = sizeof(struct acpi_fadt_descriptor);
if (len > tbl->length) len = tbl->length;
memcpy(&x, tbl, len);
x.header.length = len;
if (checksum((u8 *)tbl, len)) {
fprintf(stderr, "Wrong checksum for FADT!\n");
}
if (x.header.length >= 148 && x.Xdsdt) {
addr = (unsigned long)x.Xdsdt;
if (connect) {
x.Xdsdt = lseek(fd, 0, SEEK_CUR);
}
} else if (x.header.length >= 44 && x.dsdt) {
addr = (unsigned long)x.dsdt;
if (connect) {
x.dsdt = lseek(fd, 0, SEEK_CUR);
}
} else {
fprintf(stderr, "No DSDT in FADT!\n");
goto no_dsdt;
}
tbl = acpi_map_table(addr, DSDT_SIG);
if (!tbl) goto no_dsdt;
if (checksum((u8 *)tbl, tbl->length))
fprintf(stderr, "Wrong checksum for DSDT!\n");
write_table(fd, tbl, addr);
acpi_unmap_table(tbl);
no_dsdt:
if (x.header.length >= 140 && x.xfirmware_ctrl) {
addr = (unsigned long)x.xfirmware_ctrl;
if (connect) {
x.xfirmware_ctrl = lseek(fd, 0, SEEK_CUR);
}
} else if (x.header.length >= 40 && x.firmware_ctrl) {
addr = (unsigned long)x.firmware_ctrl;
if (connect) {
x.firmware_ctrl = lseek(fd, 0, SEEK_CUR);
}
} else {
fprintf(stderr, "No FACS in FADT!\n");
goto no_facs;
}
tbl = acpi_map_table(addr, FACS_SIG);
if (!tbl) goto no_facs;
/* do not checksum FACS */
write_table(fd, tbl, addr);
acpi_unmap_table(tbl);
no_facs:
write_table(fd, (struct acpi_table_header *)&x, xaddr);
}
static int acpi_dump_SDT(int fd, struct acpi_rsdp_descriptor *rsdp)
{
struct acpi_table_header *sdt, *tbl = 0;
int xsdt = 1, i, num;
char *offset;
unsigned long addr;
if (rsdp->revision > 1 && rsdp->xsdt_physical_address) {
tbl = acpi_map_table(rsdp->xsdt_physical_address, "XSDT");
}
if (!tbl && rsdp->rsdt_physical_address) {
xsdt = 0;
tbl = acpi_map_table(rsdp->rsdt_physical_address, "RSDT");
}
if (!tbl) return 0;
sdt = malloc(tbl->length);
memcpy(sdt, tbl, tbl->length);
acpi_unmap_table(tbl);
if (checksum((u8 *)sdt, sdt->length))
fprintf(stderr, "Wrong checksum for %s!\n", (xsdt)?"XSDT":"RSDT");
num = (sdt->length - sizeof(struct acpi_table_header))/((xsdt)?sizeof(u64):sizeof(u32));
offset = (char *)sdt + sizeof(struct acpi_table_header);
for (i = 0; i < num; ++i, offset += ((xsdt) ? sizeof(u64) : sizeof(u32))) {
addr = (xsdt) ? (unsigned long)(*(u64 *)offset):
(unsigned long)(*(u32 *)offset);
if (!addr) continue;
tbl = acpi_map_table(addr, 0);
if (!tbl) continue;
if (!memcmp(tbl->signature, FADT_SIG, 4)) {
acpi_dump_FADT(fd, tbl, addr);
} else {
if (checksum((u8 *)tbl, tbl->length))
fprintf(stderr, "Wrong checksum for generic table!\n");
write_table(fd, tbl, addr);
}
acpi_unmap_table(tbl);
if (connect) {
if (xsdt)
(*(u64*)offset) = lseek(fd, 0, SEEK_CUR);
else
(*(u32*)offset) = lseek(fd, 0, SEEK_CUR);
}
}
if (xsdt) {
addr = (unsigned long)rsdp->xsdt_physical_address;
if (connect) {
rsdp->xsdt_physical_address = lseek(fd, 0, SEEK_CUR);
}
} else {
addr = (unsigned long)rsdp->rsdt_physical_address;
if (connect) {
rsdp->rsdt_physical_address = lseek(fd, 0, SEEK_CUR);
}
}
write_table(fd, sdt, addr);
free (sdt);
return 1;
}
#define DYNAMIC_SSDT "/sys/firmware/acpi/tables/dynamic"
static void acpi_dump_dynamic_SSDT(int fd)
{
struct stat file_stat;
char filename[256], *ptr;
DIR *tabledir;
struct dirent *entry;
FILE *fp;
int count, readcount, length;
struct acpi_table_header table_header, *ptable;
if (stat(DYNAMIC_SSDT, &file_stat) == -1) {
/* The directory doesn't exist */
return;
}
tabledir = opendir(DYNAMIC_SSDT);
if(!tabledir){
/*can't open the directory */
return;
}
while ((entry = readdir(tabledir)) != 0){
/* skip the file of . /.. */
if (entry->d_name[0] == '.')
continue;
sprintf(filename, "%s/%s", DYNAMIC_SSDT, entry->d_name);
fp = fopen(filename, "r");
if (fp == NULL) {
fprintf(stderr, "Can't open the file of %s\n",
filename);
continue;
}
/* Read the Table header to parse the table length */
count = fread(&table_header, 1, sizeof(struct acpi_table_header), fp);
if (count < sizeof(table_header)) {
/* the length is lessn than ACPI table header. skip it */
fclose(fp);
continue;
}
length = table_header.length;
ptr = malloc(table_header.length);
fseek(fp, 0, SEEK_SET);
readcount = 0;
while(!feof(fp) && readcount < length) {
count = fread(ptr + readcount, 1, 256, fp);
readcount += count;
}
fclose(fp);
ptable = (struct acpi_table_header *) ptr;
if (checksum((u8 *) ptable, ptable->length))
fprintf(stderr, "Wrong checksum "
"for dynamic SSDT table!\n");
write_table(fd, ptable, 0);
free(ptr);
}
closedir(tabledir);
return;
}
static void usage(const char *progname)
{
puts("Usage:");
printf("%s [--addr 0x1234][--table DSDT][--output filename]"
"[--binary][--length 0x456][--help]\n", progname);
puts("\t--addr 0x1234 or -a 0x1234 -- look for tables at this physical address");
puts("\t--table DSDT or -t DSDT -- only dump table with DSDT signature");
puts("\t--output filename or -o filename -- redirect output from stdin to filename");
puts("\t--binary or -b -- dump data in binary form rather than in hex-dump format");
puts("\t--length 0x456 or -l 0x456 -- works only with --addr, dump physical memory"
"\n\t\tregion without trying to understand it's contents");
puts("\t--skip 2 or -s 2 -- skip 2 tables of the given name and output only 3rd one");
puts("\t--help or -h -- this help message");
exit(0);
}
static struct option long_options[] = {
{"addr", 1, 0, 0},
{"table", 1, 0, 0},
{"output", 1, 0, 0},
{"binary", 0, 0, 0},
{"length", 1, 0, 0},
{"skip", 1, 0, 0},
{"help", 0, 0, 0},
{0, 0, 0, 0}
};
int main(int argc, char **argv)
{
int option_index, c, fd;
u8 *raw;
struct acpi_rsdp_descriptor rsdpx, *x = 0;
char *filename = 0;
char buff[80];
memset(select_sig, 0, 4);
print = 1;
connect = 0;
addr = length = 0;
skip = 0;
while (1) {
option_index = 0;
c = getopt_long(argc, argv, "a:t:o:bl:s:h",
long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 0:
switch (option_index) {
case 0:
addr = strtoul(optarg, (char **)NULL, 16);
break;
case 1:
memcpy(select_sig, optarg, 4);
break;
case 2:
filename = optarg;
break;
case 3:
print = 0;
break;
case 4:
length = strtoul(optarg, (char **)NULL, 16);
break;
case 5:
skip = strtoul(optarg, (char **)NULL, 10);
break;
case 6:
usage(argv[0]);
exit(0);
}
break;
case 'a':
addr = strtoul(optarg, (char **)NULL, 16);
break;
case 't':
memcpy(select_sig, optarg, 4);
break;
case 'o':
filename = optarg;
break;
case 'b':
print = 0;
break;
case 'l':
length = strtoul(optarg, (char **)NULL, 16);
break;
case 's':
skip = strtoul(optarg, (char **)NULL, 10);
break;
case 'h':
usage(argv[0]);
exit(0);
default:
printf("Unknown option!\n");
usage(argv[0]);
exit(0);
}
}
fd = STDOUT_FILENO;
if (filename) {
fd = creat(filename, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
if (fd < 0)
return fd;
}
if (!select_sig[0] && !print) {
connect = 1;
}
psz = sysconf(_SC_PAGESIZE);
if (length && addr) {
/* We know length and address, it means we just want a memory dump */
if (!(raw = acpi_map_memory(addr, length)))
goto not_found;
write(fd, raw, length);
acpi_unmap_memory(raw, length);
close(fd);
return 0;
}
length = sizeof(struct acpi_rsdp_descriptor);
if (!addr) {
addr = read_efi_systab();
if (!addr) {
addr = ACPI_HI_RSDP_WINDOW_BASE;
length = ACPI_HI_RSDP_WINDOW_SIZE;
}
}
if (!(raw = acpi_map_memory(addr, length)) ||
!(x = acpi_scan_for_rsdp(raw, length)))
goto not_found;
/* Find RSDP and print all found tables */
memcpy(&rsdpx, x, sizeof(struct acpi_rsdp_descriptor));
acpi_unmap_memory(raw, length);
if (connect) {
lseek(fd, sizeof(struct acpi_rsdp_descriptor), SEEK_SET);
}
if (!acpi_dump_SDT(fd, &rsdpx))
goto not_found;
if (connect) {
lseek(fd, 0, SEEK_SET);
write(fd, x, (rsdpx.revision < 2) ?
ACPI_RSDP_CHECKSUM_LENGTH : ACPI_RSDP_XCHECKSUM_LENGTH);
} else if (!select_sig[0] || !memcmp("RSD PTR ", select_sig, 4)) {
addr += (long)x - (long)raw;
length = snprintf(buff, 80, "RSD PTR @ %p\n", (void *)addr);
write(fd, buff, length);
acpi_show_data(fd, (u8 *) & rsdpx, (rsdpx.revision < 2) ?
ACPI_RSDP_CHECKSUM_LENGTH : ACPI_RSDP_XCHECKSUM_LENGTH);
buff[0] = '\n';
write(fd, buff, 1);
}
acpi_dump_dynamic_SSDT(fd);
close(fd);
return 0;
not_found:
close(fd);
fprintf(stderr, "ACPI tables were not found. If you know location "
"of RSD PTR table (from dmesg, etc), "
"supply it with either --addr or -a option\n");
return 1;
}

View File

@ -0,0 +1,131 @@
/******************************************************************************
*
* Module Name: acpidump.h - Include file for acpi_dump utility
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2014, Intel Corp.
* 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 "accommon.h"
#include "actables.h"
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
/*
* Global variables. Defined in main.c only, externed in all other files
*/
#ifdef _DECLARE_GLOBALS
#define EXTERN
#define INIT_GLOBAL(a,b) a=b
#else
#define EXTERN extern
#define INIT_GLOBAL(a,b) a
#endif
/* Globals */
EXTERN u8 INIT_GLOBAL(gbl_summary_mode, FALSE);
EXTERN u8 INIT_GLOBAL(gbl_verbose_mode, FALSE);
EXTERN u8 INIT_GLOBAL(gbl_binary_mode, FALSE);
EXTERN u8 INIT_GLOBAL(gbl_dump_customized_tables, FALSE);
EXTERN FILE INIT_GLOBAL(*gbl_output_file, NULL);
EXTERN char INIT_GLOBAL(*gbl_output_filename, NULL);
EXTERN u64 INIT_GLOBAL(gbl_rsdp_base, 0);
/* Globals required for use with ACPICA modules */
#ifdef _DECLARE_GLOBALS
u8 acpi_gbl_enable_interpreter_slack = FALSE;
u8 acpi_gbl_integer_byte_width = 8;
u32 acpi_dbg_level = 0;
u32 acpi_dbg_layer = 0;
#endif
/* Action table used to defer requested options */
struct ap_dump_action {
char *argument;
u32 to_be_done;
};
#define AP_MAX_ACTIONS 32
#define AP_DUMP_ALL_TABLES 0
#define AP_DUMP_TABLE_BY_ADDRESS 1
#define AP_DUMP_TABLE_BY_NAME 2
#define AP_DUMP_TABLE_BY_FILE 3
#define AP_MAX_ACPI_FILES 256 /* Prevent infinite loops */
/* Minimum FADT sizes for various table addresses */
#define MIN_FADT_FOR_DSDT (ACPI_FADT_OFFSET (dsdt) + sizeof (u32))
#define MIN_FADT_FOR_FACS (ACPI_FADT_OFFSET (facs) + sizeof (u32))
#define MIN_FADT_FOR_XDSDT (ACPI_FADT_OFFSET (Xdsdt) + sizeof (u64))
#define MIN_FADT_FOR_XFACS (ACPI_FADT_OFFSET (Xfacs) + sizeof (u64))
/*
* apdump - Table get/dump routines
*/
int ap_dump_table_from_file(char *pathname);
int ap_dump_table_by_name(char *signature);
int ap_dump_table_by_address(char *ascii_address);
int ap_dump_all_tables(void);
u8 ap_is_valid_header(struct acpi_table_header *table);
u8 ap_is_valid_checksum(struct acpi_table_header *table);
u32 ap_get_table_length(struct acpi_table_header *table);
/*
* apfiles - File I/O utilities
*/
int ap_open_output_file(char *pathname);
int ap_write_to_binary_file(struct acpi_table_header *table, u32 instance);
struct acpi_table_header *ap_get_table_from_file(char *pathname,
u32 *file_size);

View File

@ -0,0 +1,451 @@
/******************************************************************************
*
* Module Name: apdump - Dump routines for ACPI tables (acpidump)
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2014, Intel Corp.
* 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 "acpidump.h"
/* Local prototypes */
static int
ap_dump_table_buffer(struct acpi_table_header *table,
u32 instance, acpi_physical_address address);
/******************************************************************************
*
* FUNCTION: ap_is_valid_header
*
* PARAMETERS: table - Pointer to table to be validated
*
* RETURN: TRUE if the header appears to be valid. FALSE otherwise
*
* DESCRIPTION: Check for a valid ACPI table header
*
******************************************************************************/
u8 ap_is_valid_header(struct acpi_table_header *table)
{
if (!ACPI_VALIDATE_RSDP_SIG(table->signature)) {
/* Make sure signature is all ASCII and a valid ACPI name */
if (!acpi_ut_valid_acpi_name(table->signature)) {
fprintf(stderr,
"Table signature (0x%8.8X) is invalid\n",
*(u32 *)table->signature);
return (FALSE);
}
/* Check for minimum table length */
if (table->length < sizeof(struct acpi_table_header)) {
fprintf(stderr, "Table length (0x%8.8X) is invalid\n",
table->length);
return (FALSE);
}
}
return (TRUE);
}
/******************************************************************************
*
* FUNCTION: ap_is_valid_checksum
*
* PARAMETERS: table - Pointer to table to be validated
*
* RETURN: TRUE if the checksum appears to be valid. FALSE otherwise.
*
* DESCRIPTION: Check for a valid ACPI table checksum.
*
******************************************************************************/
u8 ap_is_valid_checksum(struct acpi_table_header *table)
{
acpi_status status;
struct acpi_table_rsdp *rsdp;
if (ACPI_VALIDATE_RSDP_SIG(table->signature)) {
/*
* Checksum for RSDP.
* Note: Other checksums are computed during the table dump.
*/
rsdp = ACPI_CAST_PTR(struct acpi_table_rsdp, table);
status = acpi_tb_validate_rsdp(rsdp);
} else {
status = acpi_tb_verify_checksum(table, table->length);
}
if (ACPI_FAILURE(status)) {
fprintf(stderr, "%4.4s: Warning: wrong checksum in table\n",
table->signature);
}
return (AE_OK);
}
/******************************************************************************
*
* FUNCTION: ap_get_table_length
*
* PARAMETERS: table - Pointer to the table
*
* RETURN: Table length
*
* DESCRIPTION: Obtain table length according to table signature.
*
******************************************************************************/
u32 ap_get_table_length(struct acpi_table_header *table)
{
struct acpi_table_rsdp *rsdp;
/* Check if table is valid */
if (!ap_is_valid_header(table)) {
return (0);
}
if (ACPI_VALIDATE_RSDP_SIG(table->signature)) {
rsdp = ACPI_CAST_PTR(struct acpi_table_rsdp, table);
return (rsdp->length);
}
/* Normal ACPI table */
return (table->length);
}
/******************************************************************************
*
* FUNCTION: ap_dump_table_buffer
*
* PARAMETERS: table - ACPI table to be dumped
* instance - ACPI table instance no. to be dumped
* address - Physical address of the table
*
* RETURN: None
*
* DESCRIPTION: Dump an ACPI table in standard ASCII hex format, with a
* header that is compatible with the acpi_xtract utility.
*
******************************************************************************/
static int
ap_dump_table_buffer(struct acpi_table_header *table,
u32 instance, acpi_physical_address address)
{
u32 table_length;
table_length = ap_get_table_length(table);
/* Print only the header if requested */
if (gbl_summary_mode) {
acpi_tb_print_table_header(address, table);
return (0);
}
/* Dump to binary file if requested */
if (gbl_binary_mode) {
return (ap_write_to_binary_file(table, instance));
}
/*
* Dump the table with header for use with acpixtract utility.
* Note: simplest to just always emit a 64-bit address. acpi_xtract
* utility can handle this.
*/
printf("%4.4s @ 0x%8.8X%8.8X\n", table->signature,
ACPI_FORMAT_UINT64(address));
acpi_ut_dump_buffer(ACPI_CAST_PTR(u8, table), table_length,
DB_BYTE_DISPLAY, 0);
printf("\n");
return (0);
}
/******************************************************************************
*
* FUNCTION: ap_dump_all_tables
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Get all tables from the RSDT/XSDT (or at least all of the
* tables that we can possibly get).
*
******************************************************************************/
int ap_dump_all_tables(void)
{
struct acpi_table_header *table;
u32 instance = 0;
acpi_physical_address address;
acpi_status status;
int table_status;
u32 i;
/* Get and dump all available ACPI tables */
for (i = 0; i < AP_MAX_ACPI_FILES; i++) {
status =
acpi_os_get_table_by_index(i, &table, &instance, &address);
if (ACPI_FAILURE(status)) {
/* AE_LIMIT means that no more tables are available */
if (status == AE_LIMIT) {
return (0);
} else if (i == 0) {
fprintf(stderr,
"Could not get ACPI tables, %s\n",
acpi_format_exception(status));
return (-1);
} else {
fprintf(stderr,
"Could not get ACPI table at index %u, %s\n",
i, acpi_format_exception(status));
continue;
}
}
table_status = ap_dump_table_buffer(table, instance, address);
free(table);
if (table_status) {
break;
}
}
/* Something seriously bad happened if the loop terminates here */
return (-1);
}
/******************************************************************************
*
* FUNCTION: ap_dump_table_by_address
*
* PARAMETERS: ascii_address - Address for requested ACPI table
*
* RETURN: Status
*
* DESCRIPTION: Get an ACPI table via a physical address and dump it.
*
******************************************************************************/
int ap_dump_table_by_address(char *ascii_address)
{
acpi_physical_address address;
struct acpi_table_header *table;
acpi_status status;
int table_status;
u64 long_address;
/* Convert argument to an integer physical address */
status = acpi_ut_strtoul64(ascii_address, 0, &long_address);
if (ACPI_FAILURE(status)) {
fprintf(stderr, "%s: Could not convert to a physical address\n",
ascii_address);
return (-1);
}
address = (acpi_physical_address) long_address;
status = acpi_os_get_table_by_address(address, &table);
if (ACPI_FAILURE(status)) {
fprintf(stderr, "Could not get table at 0x%8.8X%8.8X, %s\n",
ACPI_FORMAT_UINT64(address),
acpi_format_exception(status));
return (-1);
}
table_status = ap_dump_table_buffer(table, 0, address);
free(table);
return (table_status);
}
/******************************************************************************
*
* FUNCTION: ap_dump_table_by_name
*
* PARAMETERS: signature - Requested ACPI table signature
*
* RETURN: Status
*
* DESCRIPTION: Get an ACPI table via a signature and dump it. Handles
* multiple tables with the same signature (SSDTs).
*
******************************************************************************/
int ap_dump_table_by_name(char *signature)
{
char local_signature[ACPI_NAME_SIZE + 1];
u32 instance;
struct acpi_table_header *table;
acpi_physical_address address;
acpi_status status;
int table_status;
if (strlen(signature) != ACPI_NAME_SIZE) {
fprintf(stderr,
"Invalid table signature [%s]: must be exactly 4 characters\n",
signature);
return (-1);
}
/* Table signatures are expected to be uppercase */
strcpy(local_signature, signature);
acpi_ut_strupr(local_signature);
/* To be friendly, handle tables whose signatures do not match the name */
if (ACPI_COMPARE_NAME(local_signature, "FADT")) {
strcpy(local_signature, ACPI_SIG_FADT);
} else if (ACPI_COMPARE_NAME(local_signature, "MADT")) {
strcpy(local_signature, ACPI_SIG_MADT);
}
/* Dump all instances of this signature (to handle multiple SSDTs) */
for (instance = 0; instance < AP_MAX_ACPI_FILES; instance++) {
status = acpi_os_get_table_by_name(local_signature, instance,
&table, &address);
if (ACPI_FAILURE(status)) {
/* AE_LIMIT means that no more tables are available */
if (status == AE_LIMIT) {
return (0);
}
fprintf(stderr,
"Could not get ACPI table with signature [%s], %s\n",
local_signature, acpi_format_exception(status));
return (-1);
}
table_status = ap_dump_table_buffer(table, instance, address);
free(table);
if (table_status) {
break;
}
}
/* Something seriously bad happened if the loop terminates here */
return (-1);
}
/******************************************************************************
*
* FUNCTION: ap_dump_table_from_file
*
* PARAMETERS: pathname - File containing the binary ACPI table
*
* RETURN: Status
*
* DESCRIPTION: Dump an ACPI table from a binary file
*
******************************************************************************/
int ap_dump_table_from_file(char *pathname)
{
struct acpi_table_header *table;
u32 file_size = 0;
int table_status = -1;
/* Get the entire ACPI table from the file */
table = ap_get_table_from_file(pathname, &file_size);
if (!table) {
return (-1);
}
/* File must be at least as long as the table length */
if (table->length > file_size) {
fprintf(stderr,
"Table length (0x%X) is too large for input file (0x%X) %s\n",
table->length, file_size, pathname);
goto exit;
}
if (gbl_verbose_mode) {
fprintf(stderr,
"Input file: %s contains table [%4.4s], 0x%X (%u) bytes\n",
pathname, table->signature, file_size, file_size);
}
table_status = ap_dump_table_buffer(table, 0, 0);
exit:
free(table);
return (table_status);
}
/******************************************************************************
*
* FUNCTION: acpi_os* print functions
*
* DESCRIPTION: Used for linkage with ACPICA modules
*
******************************************************************************/
void ACPI_INTERNAL_VAR_XFACE acpi_os_printf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(stdout, fmt, args);
va_end(args);
}
void acpi_os_vprintf(const char *fmt, va_list args)
{
vfprintf(stdout, fmt, args);
}

View File

@ -0,0 +1,228 @@
/******************************************************************************
*
* Module Name: apfiles - File-related functions for acpidump utility
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2014, Intel Corp.
* 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 "acpidump.h"
#include "acapps.h"
/******************************************************************************
*
* FUNCTION: ap_open_output_file
*
* PARAMETERS: pathname - Output filename
*
* RETURN: Open file handle
*
* DESCRIPTION: Open a text output file for acpidump. Checks if file already
* exists.
*
******************************************************************************/
int ap_open_output_file(char *pathname)
{
struct stat stat_info;
FILE *file;
/* If file exists, prompt for overwrite */
if (!stat(pathname, &stat_info)) {
fprintf(stderr,
"Target path already exists, overwrite? [y|n] ");
if (getchar() != 'y') {
return (-1);
}
}
/* Point stdout to the file */
file = freopen(pathname, "w", stdout);
if (!file) {
perror("Could not open output file");
return (-1);
}
/* Save the file and path */
gbl_output_file = file;
gbl_output_filename = pathname;
return (0);
}
/******************************************************************************
*
* FUNCTION: ap_write_to_binary_file
*
* PARAMETERS: table - ACPI table to be written
* instance - ACPI table instance no. to be written
*
* RETURN: Status
*
* DESCRIPTION: Write an ACPI table to a binary file. Builds the output
* filename from the table signature.
*
******************************************************************************/
int ap_write_to_binary_file(struct acpi_table_header *table, u32 instance)
{
char filename[ACPI_NAME_SIZE + 16];
char instance_str[16];
FILE *file;
size_t actual;
u32 table_length;
/* Obtain table length */
table_length = ap_get_table_length(table);
/* Construct lower-case filename from the table local signature */
if (ACPI_VALIDATE_RSDP_SIG(table->signature)) {
ACPI_MOVE_NAME(filename, ACPI_RSDP_NAME);
} else {
ACPI_MOVE_NAME(filename, table->signature);
}
filename[0] = (char)ACPI_TOLOWER(filename[0]);
filename[1] = (char)ACPI_TOLOWER(filename[1]);
filename[2] = (char)ACPI_TOLOWER(filename[2]);
filename[3] = (char)ACPI_TOLOWER(filename[3]);
filename[ACPI_NAME_SIZE] = 0;
/* Handle multiple SSDts - create different filenames for each */
if (instance > 0) {
sprintf(instance_str, "%u", instance);
strcat(filename, instance_str);
}
strcat(filename, ACPI_TABLE_FILE_SUFFIX);
if (gbl_verbose_mode) {
fprintf(stderr,
"Writing [%4.4s] to binary file: %s 0x%X (%u) bytes\n",
table->signature, filename, table->length,
table->length);
}
/* Open the file and dump the entire table in binary mode */
file = fopen(filename, "wb");
if (!file) {
perror("Could not open output file");
return (-1);
}
actual = fwrite(table, 1, table_length, file);
if (actual != table_length) {
perror("Error writing binary output file");
fclose(file);
return (-1);
}
fclose(file);
return (0);
}
/******************************************************************************
*
* FUNCTION: ap_get_table_from_file
*
* PARAMETERS: pathname - File containing the binary ACPI table
* out_file_size - Where the file size is returned
*
* RETURN: Buffer containing the ACPI table. NULL on error.
*
* DESCRIPTION: Open a file and read it entirely into a new buffer
*
******************************************************************************/
struct acpi_table_header *ap_get_table_from_file(char *pathname,
u32 *out_file_size)
{
struct acpi_table_header *buffer = NULL;
FILE *file;
u32 file_size;
size_t actual;
/* Must use binary mode */
file = fopen(pathname, "rb");
if (!file) {
perror("Could not open input file");
return (NULL);
}
/* Need file size to allocate a buffer */
file_size = cm_get_file_size(file);
if (file_size == ACPI_UINT32_MAX) {
fprintf(stderr,
"Could not get input file size: %s\n", pathname);
goto cleanup;
}
/* Allocate a buffer for the entire file */
buffer = calloc(1, file_size);
if (!buffer) {
fprintf(stderr,
"Could not allocate file buffer of size: %u\n",
file_size);
goto cleanup;
}
/* Read the entire file */
actual = fread(buffer, 1, file_size, file);
if (actual != file_size) {
fprintf(stderr, "Could not read input file: %s\n", pathname);
free(buffer);
buffer = NULL;
goto cleanup;
}
*out_file_size = file_size;
cleanup:
fclose(file);
return (buffer);
}

View File

@ -0,0 +1,340 @@
/******************************************************************************
*
* Module Name: apmain - Main module for the acpidump utility
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2014, Intel Corp.
* 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.
*/
#define _DECLARE_GLOBALS
#include "acpidump.h"
#include "acapps.h"
/*
* acpidump - A portable utility for obtaining system ACPI tables and dumping
* them in an ASCII hex format suitable for binary extraction via acpixtract.
*
* Obtaining the system ACPI tables is an OS-specific operation.
*
* This utility can be ported to any host operating system by providing a
* module containing system-specific versions of these interfaces:
*
* acpi_os_get_table_by_address
* acpi_os_get_table_by_index
* acpi_os_get_table_by_name
*
* See the ACPICA Reference Guide for the exact definitions of these
* interfaces. Also, see these ACPICA source code modules for example
* implementations:
*
* source/os_specific/service_layers/oswintbl.c
* source/os_specific/service_layers/oslinuxtbl.c
*/
/* Local prototypes */
static void ap_display_usage(void);
static int ap_do_options(int argc, char **argv);
static void ap_insert_action(char *argument, u32 to_be_done);
/* Table for deferred actions from command line options */
struct ap_dump_action action_table[AP_MAX_ACTIONS];
u32 current_action = 0;
#define AP_UTILITY_NAME "ACPI Binary Table Dump Utility"
#define AP_SUPPORTED_OPTIONS "?a:bcf:hn:o:r:svz"
/******************************************************************************
*
* FUNCTION: ap_display_usage
*
* DESCRIPTION: Usage message for the acpi_dump utility
*
******************************************************************************/
static void ap_display_usage(void)
{
ACPI_USAGE_HEADER("acpidump [options]");
ACPI_OPTION("-b", "Dump tables to binary files");
ACPI_OPTION("-c", "Dump customized tables");
ACPI_OPTION("-h -?", "This help message");
ACPI_OPTION("-o <File>", "Redirect output to file");
ACPI_OPTION("-r <Address>", "Dump tables from specified RSDP");
ACPI_OPTION("-s", "Print table summaries only");
ACPI_OPTION("-v", "Display version information");
ACPI_OPTION("-z", "Verbose mode");
printf("\nTable Options:\n");
ACPI_OPTION("-a <Address>", "Get table via a physical address");
ACPI_OPTION("-f <BinaryFile>", "Get table via a binary file");
ACPI_OPTION("-n <Signature>", "Get table via a name/signature");
printf("\n"
"Invocation without parameters dumps all available tables\n"
"Multiple mixed instances of -a, -f, and -n are supported\n\n");
}
/******************************************************************************
*
* FUNCTION: ap_insert_action
*
* PARAMETERS: argument - Pointer to the argument for this action
* to_be_done - What to do to process this action
*
* RETURN: None. Exits program if action table becomes full.
*
* DESCRIPTION: Add an action item to the action table
*
******************************************************************************/
static void ap_insert_action(char *argument, u32 to_be_done)
{
/* Insert action and check for table overflow */
action_table[current_action].argument = argument;
action_table[current_action].to_be_done = to_be_done;
current_action++;
if (current_action > AP_MAX_ACTIONS) {
fprintf(stderr, "Too many table options (max %u)\n",
AP_MAX_ACTIONS);
exit(-1);
}
}
/******************************************************************************
*
* FUNCTION: ap_do_options
*
* PARAMETERS: argc/argv - Standard argc/argv
*
* RETURN: Status
*
* DESCRIPTION: Command line option processing. The main actions for getting
* and dumping tables are deferred via the action table.
*
*****************************************************************************/
static int ap_do_options(int argc, char **argv)
{
int j;
acpi_status status;
/* Command line options */
while ((j = acpi_getopt(argc, argv, AP_SUPPORTED_OPTIONS)) != EOF)
switch (j) {
/*
* Global options
*/
case 'b': /* Dump all input tables to binary files */
gbl_binary_mode = TRUE;
continue;
case 'c': /* Dump customized tables */
gbl_dump_customized_tables = TRUE;
continue;
case 'h':
case '?':
ap_display_usage();
exit(0);
case 'o': /* Redirect output to a single file */
if (ap_open_output_file(acpi_gbl_optarg)) {
exit(-1);
}
continue;
case 'r': /* Dump tables from specified RSDP */
status =
acpi_ut_strtoul64(acpi_gbl_optarg, 0,
&gbl_rsdp_base);
if (ACPI_FAILURE(status)) {
fprintf(stderr,
"%s: Could not convert to a physical address\n",
acpi_gbl_optarg);
exit(-1);
}
continue;
case 's': /* Print table summaries only */
gbl_summary_mode = TRUE;
continue;
case 'v': /* Revision/version */
printf(ACPI_COMMON_SIGNON(AP_UTILITY_NAME));
exit(0);
case 'z': /* Verbose mode */
gbl_verbose_mode = TRUE;
fprintf(stderr, ACPI_COMMON_SIGNON(AP_UTILITY_NAME));
continue;
/*
* Table options
*/
case 'a': /* Get table by physical address */
ap_insert_action(acpi_gbl_optarg,
AP_DUMP_TABLE_BY_ADDRESS);
break;
case 'f': /* Get table from a file */
ap_insert_action(acpi_gbl_optarg,
AP_DUMP_TABLE_BY_FILE);
break;
case 'n': /* Get table by input name (signature) */
ap_insert_action(acpi_gbl_optarg,
AP_DUMP_TABLE_BY_NAME);
break;
default:
ap_display_usage();
exit(-1);
}
/* If there are no actions, this means "get/dump all tables" */
if (current_action == 0) {
ap_insert_action(NULL, AP_DUMP_ALL_TABLES);
}
return (0);
}
/******************************************************************************
*
* FUNCTION: main
*
* PARAMETERS: argc/argv - Standard argc/argv
*
* RETURN: Status
*
* DESCRIPTION: C main function for acpidump utility
*
******************************************************************************/
int ACPI_SYSTEM_XFACE main(int argc, char *argv[])
{
int status = 0;
struct ap_dump_action *action;
u32 file_size;
u32 i;
ACPI_DEBUG_INITIALIZE(); /* For debug version only */
/* Process command line options */
if (ap_do_options(argc, argv)) {
return (-1);
}
/* Get/dump ACPI table(s) as requested */
for (i = 0; i < current_action; i++) {
action = &action_table[i];
switch (action->to_be_done) {
case AP_DUMP_ALL_TABLES:
status = ap_dump_all_tables();
break;
case AP_DUMP_TABLE_BY_ADDRESS:
status = ap_dump_table_by_address(action->argument);
break;
case AP_DUMP_TABLE_BY_NAME:
status = ap_dump_table_by_name(action->argument);
break;
case AP_DUMP_TABLE_BY_FILE:
status = ap_dump_table_from_file(action->argument);
break;
default:
fprintf(stderr,
"Internal error, invalid action: 0x%X\n",
action->to_be_done);
return (-1);
}
if (status) {
return (status);
}
}
if (gbl_output_file) {
if (gbl_verbose_mode) {
/* Summary for the output file */
file_size = cm_get_file_size(gbl_output_file);
fprintf(stderr,
"Output file %s contains 0x%X (%u) bytes\n\n",
gbl_output_filename, file_size, file_size);
}
fclose(gbl_output_file);
}
return (status);
}