Commit c9b77a40 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge back earlier ACPICA material.

Conflicts:
	drivers/acpi/acpica/acglobal.h
parents 85dbd580 bc381eeb
...@@ -237,7 +237,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted. ...@@ -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
......
...@@ -135,6 +135,7 @@ acpi-y += \ ...@@ -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 \
......
/******************************************************************************
*
* 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 */
...@@ -104,9 +104,10 @@ acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info); ...@@ -104,9 +104,10 @@ acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info);
*/ */
acpi_status acpi_status
acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
struct acpi_generic_address *gpe_block_address, u64 address,
u8 space_id,
u32 register_count, u32 register_count,
u8 gpe_block_base_number, u16 gpe_block_base_number,
u32 interrupt_number, u32 interrupt_number,
struct acpi_gpe_block_info **return_gpe_block); struct acpi_gpe_block_info **return_gpe_block);
......
...@@ -44,144 +44,14 @@ ...@@ -44,144 +44,14 @@
#ifndef __ACGLOBAL_H__ #ifndef __ACGLOBAL_H__
#define __ACGLOBAL_H__ #define __ACGLOBAL_H__
/*
* Ensure that the globals are actually defined and initialized only once.
*
* The use of these macros allows a single list of globals (here) in order
* to simplify maintenance of the code.
*/
#ifdef DEFINE_ACPI_GLOBALS
#define ACPI_GLOBAL(type,name) \
extern type name; \
type name
#define ACPI_INIT_GLOBAL(type,name,value) \
type name=value
#else
#define ACPI_GLOBAL(type,name) \
extern type name
#define ACPI_INIT_GLOBAL(type,name,value) \
extern type name
#endif
#ifdef DEFINE_ACPI_GLOBALS
/* Public globals, available from outside ACPICA subsystem */
/***************************************************************************** /*****************************************************************************
* *
* Runtime configuration (static defaults that can be overriden at runtime) * Globals related to the ACPI tables
* *
****************************************************************************/ ****************************************************************************/
/* /* Master list of all ACPI tables that were found in the RSDT/XSDT */
* Enable "slack" in the AML interpreter? Default is FALSE, and the
* interpreter strictly follows the ACPI specification. Setting to TRUE
* allows the interpreter to ignore certain errors and/or bad AML constructs.
*
* Currently, these features are enabled by this flag:
*
* 1) Allow "implicit return" of last value in a control method
* 2) Allow access beyond the end of an operation region
* 3) Allow access to uninitialized locals/args (auto-init to integer 0)
* 4) Allow ANY object type to be a source operand for the Store() operator
* 5) Allow unresolved references (invalid target name) in package objects
* 6) Enable warning messages for behavior that is not ACPI spec compliant
*/
ACPI_INIT_GLOBAL(u8, acpi_gbl_enable_interpreter_slack, FALSE);
/*
* Automatically serialize all methods that create named objects? Default
* is TRUE, meaning that all non_serialized methods are scanned once at
* table load time to determine those that create named objects. Methods
* that create named objects are marked Serialized in order to prevent
* possible run-time problems if they are entered by more than one thread.
*/
ACPI_INIT_GLOBAL(u8, acpi_gbl_auto_serialize_methods, TRUE);
/*
* Create the predefined _OSI method in the namespace? Default is TRUE
* because ACPI CA is fully compatible with other ACPI implementations.
* Changing this will revert ACPI CA (and machine ASL) to pre-OSI behavior.
*/
ACPI_INIT_GLOBAL(u8, acpi_gbl_create_osi_method, TRUE);
/*
* Optionally use default values for the ACPI register widths. Set this to
* TRUE to use the defaults, if an FADT contains incorrect widths/lengths.
*/
ACPI_INIT_GLOBAL(u8, acpi_gbl_use_default_register_widths, TRUE);
/*
* Optionally enable output from the AML Debug Object.
*/
ACPI_INIT_GLOBAL(u8, acpi_gbl_enable_aml_debug_object, FALSE);
/*
* Optionally copy the entire DSDT to local memory (instead of simply
* mapping it.) There are some BIOSs that corrupt or replace the original
* DSDT, creating the need for this option. Default is FALSE, do not copy
* the DSDT.
*/
ACPI_INIT_GLOBAL(u8, acpi_gbl_copy_dsdt_locally, FALSE);
/*
* Optionally ignore an XSDT if present and use the RSDT instead.
* Although the ACPI specification requires that an XSDT be used instead
* of the RSDT, the XSDT has been found to be corrupt or ill-formed on
* some machines. Default behavior is to use the XSDT if present.
*/
ACPI_INIT_GLOBAL(u8, acpi_gbl_do_not_use_xsdt, FALSE);
/*
* Optionally use 32-bit FADT addresses if and when there is a conflict
* (address mismatch) between the 32-bit and 64-bit versions of the
* address. Although ACPICA adheres to the ACPI specification which
* requires the use of the corresponding 64-bit address if it is non-zero,
* some machines have been found to have a corrupted non-zero 64-bit
* address. Default is TRUE, favor the 32-bit addresses.
*/
ACPI_INIT_GLOBAL(u8, acpi_gbl_use32_bit_fadt_addresses, TRUE);
/*
* Optionally truncate I/O addresses to 16 bits. Provides compatibility
* with other ACPI implementations. NOTE: During ACPICA initialization,
* this value is set to TRUE if any Windows OSI strings have been
* requested by the BIOS.
*/
ACPI_INIT_GLOBAL(u8, acpi_gbl_truncate_io_addresses, FALSE);
/*
* Disable runtime checking and repair of values returned by control methods.
* Use only if the repair is causing a problem on a particular machine.
*/
ACPI_INIT_GLOBAL(u8, acpi_gbl_disable_auto_repair, FALSE);
/*
* Optionally do not load any SSDTs from the RSDT/XSDT during initialization.
* This can be useful for debugging ACPI problems on some machines.
*/
ACPI_INIT_GLOBAL(u8, acpi_gbl_disable_ssdt_table_load, FALSE);
/*
* We keep track of the latest version of Windows that has been requested by
* the BIOS.
*/
ACPI_INIT_GLOBAL(u8, acpi_gbl_osi_data, 0);
#endif /* DEFINE_ACPI_GLOBALS */
/*****************************************************************************
*
* ACPI Table globals
*
****************************************************************************/
/*
* Master list of all ACPI tables that were found in the RSDT/XSDT.
*/
ACPI_GLOBAL(struct acpi_table_list, acpi_gbl_root_table_list); ACPI_GLOBAL(struct acpi_table_list, acpi_gbl_root_table_list);
/* DSDT information. Used to check for DSDT corruption */ /* DSDT information. Used to check for DSDT corruption */
...@@ -279,7 +149,6 @@ ACPI_GLOBAL(acpi_exception_handler, acpi_gbl_exception_handler); ...@@ -279,7 +149,6 @@ ACPI_GLOBAL(acpi_exception_handler, acpi_gbl_exception_handler);
ACPI_GLOBAL(acpi_init_handler, acpi_gbl_init_handler); ACPI_GLOBAL(acpi_init_handler, acpi_gbl_init_handler);
ACPI_GLOBAL(acpi_table_handler, acpi_gbl_table_handler); ACPI_GLOBAL(acpi_table_handler, acpi_gbl_table_handler);
ACPI_GLOBAL(void *, acpi_gbl_table_handler_context); ACPI_GLOBAL(void *, acpi_gbl_table_handler_context);
ACPI_GLOBAL(struct acpi_walk_state *, acpi_gbl_breakpoint_walk);
ACPI_GLOBAL(acpi_interface_handler, acpi_gbl_interface_handler); ACPI_GLOBAL(acpi_interface_handler, acpi_gbl_interface_handler);
ACPI_GLOBAL(struct acpi_sci_handler_info *, acpi_gbl_sci_handler_list); ACPI_GLOBAL(struct acpi_sci_handler_info *, acpi_gbl_sci_handler_list);
...@@ -296,7 +165,6 @@ ACPI_GLOBAL(u8, acpi_gbl_reg_methods_executed); ...@@ -296,7 +165,6 @@ ACPI_GLOBAL(u8, acpi_gbl_reg_methods_executed);
/* Misc */ /* Misc */
ACPI_GLOBAL(u32, acpi_gbl_original_mode); ACPI_GLOBAL(u32, acpi_gbl_original_mode);
ACPI_GLOBAL(u32, acpi_gbl_rsdp_original_location);
ACPI_GLOBAL(u32, acpi_gbl_ns_lookup_count); ACPI_GLOBAL(u32, acpi_gbl_ns_lookup_count);
ACPI_GLOBAL(u32, acpi_gbl_ps_find_count); ACPI_GLOBAL(u32, acpi_gbl_ps_find_count);
ACPI_GLOBAL(u16, acpi_gbl_pm1_enable_register_save); ACPI_GLOBAL(u16, acpi_gbl_pm1_enable_register_save);
...@@ -483,11 +351,6 @@ ACPI_GLOBAL(u16, acpi_gbl_node_type_count_misc); ...@@ -483,11 +351,6 @@ ACPI_GLOBAL(u16, acpi_gbl_node_type_count_misc);
ACPI_GLOBAL(u32, acpi_gbl_num_nodes); ACPI_GLOBAL(u32, acpi_gbl_num_nodes);
ACPI_GLOBAL(u32, acpi_gbl_num_objects); ACPI_GLOBAL(u32, acpi_gbl_num_objects);
ACPI_GLOBAL(u32, acpi_gbl_size_of_parse_tree);
ACPI_GLOBAL(u32, acpi_gbl_size_of_method_trees);
ACPI_GLOBAL(u32, acpi_gbl_size_of_node_entries);
ACPI_GLOBAL(u32, acpi_gbl_size_of_acpi_objects);
#endif /* ACPI_DEBUGGER */ #endif /* ACPI_DEBUGGER */
/***************************************************************************** /*****************************************************************************
...@@ -509,5 +372,6 @@ ACPI_INIT_GLOBAL(ACPI_FILE, acpi_gbl_debug_file, NULL); ...@@ -509,5 +372,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__ */
...@@ -450,9 +450,9 @@ struct acpi_gpe_event_info { ...@@ -450,9 +450,9 @@ struct acpi_gpe_event_info {
struct acpi_gpe_register_info { struct acpi_gpe_register_info {
struct acpi_generic_address status_address; /* Address of status reg */ struct acpi_generic_address status_address; /* Address of status reg */
struct acpi_generic_address enable_address; /* Address of enable reg */ struct acpi_generic_address enable_address; /* Address of enable reg */
u16 base_gpe_number; /* Base GPE number for this register */
u8 enable_for_wake; /* GPEs to keep enabled when sleeping */ u8 enable_for_wake; /* GPEs to keep enabled when sleeping */
u8 enable_for_run; /* GPEs to keep enabled when running */ u8 enable_for_run; /* GPEs to keep enabled when running */
u8 base_gpe_number; /* Base GPE number for this register */
}; };
/* /*
...@@ -466,11 +466,12 @@ struct acpi_gpe_block_info { ...@@ -466,11 +466,12 @@ struct acpi_gpe_block_info {
struct acpi_gpe_xrupt_info *xrupt_block; /* Backpointer to interrupt block */ struct acpi_gpe_xrupt_info *xrupt_block; /* Backpointer to interrupt block */
struct acpi_gpe_register_info *register_info; /* One per GPE register pair */ struct acpi_gpe_register_info *register_info; /* One per GPE register pair */
struct acpi_gpe_event_info *event_info; /* One for each GPE */ struct acpi_gpe_event_info *event_info; /* One for each GPE */
struct acpi_generic_address block_address; /* Base address of the block */ u64 address; /* Base address of the block */
u32 register_count; /* Number of register pairs in block */ u32 register_count; /* Number of register pairs in block */
u16 gpe_count; /* Number of individual GPEs in block */ u16 gpe_count; /* Number of individual GPEs in block */
u8 block_base_number; /* Base GPE number for this block */ u16 block_base_number; /* Base GPE number for this block */
u8 initialized; /* TRUE if this block is initialized */ u8 space_id;
u8 initialized; /* TRUE if this block is initialized */
}; };
/* Information about GPE interrupt handlers, one per each interrupt level used for GPEs */ /* Information about GPE interrupt handlers, one per each interrupt level used for GPEs */
...@@ -733,7 +734,8 @@ union acpi_parse_value { ...@@ -733,7 +734,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 +1149,9 @@ struct ah_predefined_name { ...@@ -1147,4 +1149,9 @@ struct ah_predefined_name {
#endif #endif
}; };
struct ah_device_id {
char *name;
char *description;
};
#endif /* __ACLOCAL_H__ */ #endif /* __ACLOCAL_H__ */
...@@ -586,6 +586,10 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { ...@@ -586,6 +586,10 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = {
{{"_LID", METHOD_0ARGS, {{"_LID", METHOD_0ARGS,
METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, METHOD_RETURNS(ACPI_RTYPE_INTEGER)}},
{{"_LPD", METHOD_0ARGS,
METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (1 Int(rev), n Pkg (2 Int) */
PACKAGE_INFO(ACPI_PTYPE2_REV_FIXED, ACPI_RTYPE_INTEGER, 2, 0, 0, 0),
{{"_MAT", METHOD_0ARGS, {{"_MAT", METHOD_0ARGS,
METHOD_RETURNS(ACPI_RTYPE_BUFFER)}}, METHOD_RETURNS(ACPI_RTYPE_BUFFER)}},
......
...@@ -53,6 +53,26 @@ acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp); ...@@ -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, ...@@ -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); ...@@ -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); ...@@ -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);
......
...@@ -176,8 +176,7 @@ acpi_status acpi_ut_init_globals(void); ...@@ -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, ...@@ -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 */
...@@ -383,7 +383,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) ...@@ -383,7 +383,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
if (!(gpe_register_info->enable_for_run | if (!(gpe_register_info->enable_for_run |
gpe_register_info->enable_for_wake)) { gpe_register_info->enable_for_wake)) {
ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS, ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,
"Ignore disabled registers for GPE%02X-GPE%02X: " "Ignore disabled registers for GPE %02X-%02X: "
"RunEnable=%02X, WakeEnable=%02X\n", "RunEnable=%02X, WakeEnable=%02X\n",
gpe_register_info-> gpe_register_info->
base_gpe_number, base_gpe_number,
...@@ -416,7 +416,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) ...@@ -416,7 +416,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
} }
ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS, ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,
"Read registers for GPE%02X-GPE%02X: Status=%02X, Enable=%02X, " "Read registers for GPE %02X-%02X: Status=%02X, Enable=%02X, "
"RunEnable=%02X, WakeEnable=%02X\n", "RunEnable=%02X, WakeEnable=%02X\n",
gpe_register_info->base_gpe_number, gpe_register_info->base_gpe_number,
gpe_register_info->base_gpe_number + gpe_register_info->base_gpe_number +
...@@ -706,7 +706,8 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, ...@@ -706,7 +706,8 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,
status = acpi_hw_clear_gpe(gpe_event_info); status = acpi_hw_clear_gpe(gpe_event_info);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status, ACPI_EXCEPTION((AE_INFO, status,
"Unable to clear GPE%02X", gpe_number)); "Unable to clear GPE %02X",
gpe_number));
return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
} }
} }
...@@ -723,7 +724,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, ...@@ -723,7 +724,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,
status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE); status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status, ACPI_EXCEPTION((AE_INFO, status,
"Unable to disable GPE%02X", gpe_number)); "Unable to disable GPE %02X", gpe_number));
return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); return_UINT32(ACPI_INTERRUPT_NOT_HANDLED);
} }
...@@ -764,7 +765,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, ...@@ -764,7 +765,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,
gpe_event_info); gpe_event_info);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status, ACPI_EXCEPTION((AE_INFO, status,
"Unable to queue handler for GPE%02X - event disabled", "Unable to queue handler for GPE %02X - event disabled",
gpe_number)); gpe_number));
} }
break; break;
...@@ -776,7 +777,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, ...@@ -776,7 +777,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,
* a GPE to be enabled if it has no handler or method. * a GPE to be enabled if it has no handler or method.
*/ */
ACPI_ERROR((AE_INFO, ACPI_ERROR((AE_INFO,
"No handler or method for GPE%02X, disabling event", "No handler or method for GPE %02X, disabling event",
gpe_number)); gpe_number));
break; break;
......
...@@ -252,21 +252,17 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) ...@@ -252,21 +252,17 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
/* Init the register_info for this GPE register (8 GPEs) */ /* Init the register_info for this GPE register (8 GPEs) */
this_register->base_gpe_number = this_register->base_gpe_number = (u16)
(u8) (gpe_block->block_base_number + (gpe_block->block_base_number +
(i * ACPI_GPE_REGISTER_WIDTH)); (i * ACPI_GPE_REGISTER_WIDTH));
this_register->status_address.address = this_register->status_address.address = gpe_block->address + i;
gpe_block->block_address.address + i;
this_register->enable_address.address = this_register->enable_address.address =
gpe_block->block_address.address + i + gpe_block->address + i + gpe_block->register_count;
gpe_block->register_count;
this_register->status_address.space_id = this_register->status_address.space_id = gpe_block->space_id;
gpe_block->block_address.space_id; this_register->enable_address.space_id = gpe_block->space_id;
this_register->enable_address.space_id =
gpe_block->block_address.space_id;
this_register->status_address.bit_width = this_register->status_address.bit_width =
ACPI_GPE_REGISTER_WIDTH; ACPI_GPE_REGISTER_WIDTH;
this_register->enable_address.bit_width = this_register->enable_address.bit_width =
...@@ -334,9 +330,10 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) ...@@ -334,9 +330,10 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
acpi_status acpi_status
acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
struct acpi_generic_address *gpe_block_address, u64 address,
u8 space_id,
u32 register_count, u32 register_count,
u8 gpe_block_base_number, u16 gpe_block_base_number,
u32 interrupt_number, u32 interrupt_number,
struct acpi_gpe_block_info **return_gpe_block) struct acpi_gpe_block_info **return_gpe_block)
{ {
...@@ -359,15 +356,14 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, ...@@ -359,15 +356,14 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
/* Initialize the new GPE block */ /* Initialize the new GPE block */
gpe_block->address = address;
gpe_block->space_id = space_id;
gpe_block->node = gpe_device; gpe_block->node = gpe_device;
gpe_block->gpe_count = (u16)(register_count * ACPI_GPE_REGISTER_WIDTH); gpe_block->gpe_count = (u16)(register_count * ACPI_GPE_REGISTER_WIDTH);
gpe_block->initialized = FALSE; gpe_block->initialized = FALSE;
gpe_block->register_count = register_count; gpe_block->register_count = register_count;
gpe_block->block_base_number = gpe_block_base_number; gpe_block->block_base_number = gpe_block_base_number;
ACPI_MEMCPY(&gpe_block->block_address, gpe_block_address,
sizeof(struct acpi_generic_address));
/* /*
* Create the register_info and event_info sub-structures * Create the register_info and event_info sub-structures
* Note: disables and clears all GPEs in the block * Note: disables and clears all GPEs in the block
...@@ -408,12 +404,14 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, ...@@ -408,12 +404,14 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
} }
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
" Initialized GPE %02X to %02X [%4.4s] %u regs on interrupt 0x%X\n", " Initialized GPE %02X to %02X [%4.4s] %u regs on interrupt 0x%X%s\n",
(u32)gpe_block->block_base_number, (u32)gpe_block->block_base_number,
(u32)(gpe_block->block_base_number + (u32)(gpe_block->block_base_number +
(gpe_block->gpe_count - 1)), (gpe_block->gpe_count - 1)),
gpe_device->name.ascii, gpe_block->register_count, gpe_device->name.ascii, gpe_block->register_count,
interrupt_number)); interrupt_number,
interrupt_number ==
acpi_gbl_FADT.sci_interrupt ? " (SCI)" : ""));
/* Update global count of currently available GPEs */ /* Update global count of currently available GPEs */
......
...@@ -131,8 +131,10 @@ acpi_status acpi_ev_gpe_initialize(void) ...@@ -131,8 +131,10 @@ acpi_status acpi_ev_gpe_initialize(void)
/* Install GPE Block 0 */ /* Install GPE Block 0 */
status = acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device, status = acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device,
&acpi_gbl_FADT.xgpe0_block, acpi_gbl_FADT.xgpe0_block.
register_count0, 0, address,
acpi_gbl_FADT.xgpe0_block.
space_id, register_count0, 0,
acpi_gbl_FADT.sci_interrupt, acpi_gbl_FADT.sci_interrupt,
&acpi_gbl_gpe_fadt_blocks[0]); &acpi_gbl_gpe_fadt_blocks[0]);
...@@ -169,8 +171,10 @@ acpi_status acpi_ev_gpe_initialize(void) ...@@ -169,8 +171,10 @@ acpi_status acpi_ev_gpe_initialize(void)
status = status =
acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device, acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device,
&acpi_gbl_FADT.xgpe1_block, acpi_gbl_FADT.xgpe1_block.
register_count1, address,
acpi_gbl_FADT.xgpe1_block.
space_id, register_count1,
acpi_gbl_FADT.gpe1_base, acpi_gbl_FADT.gpe1_base,
acpi_gbl_FADT. acpi_gbl_FADT.
sci_interrupt, sci_interrupt,
......
...@@ -167,7 +167,8 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, ...@@ -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);
......
...@@ -117,7 +117,7 @@ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context) ...@@ -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.
*/ */
......
...@@ -239,7 +239,7 @@ acpi_remove_notify_handler(acpi_handle device, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 @@ acpi_status acpi_install_sci_handler(acpi_sci_handler address, void *context) ...@@ -457,6 +470,8 @@ acpi_status acpi_install_sci_handler(acpi_sci_handler address, void *context)
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 @@ acpi_status acpi_install_sci_handler(acpi_sci_handler address, void *context) ...@@ -468,7 +483,6 @@ acpi_status acpi_install_sci_handler(acpi_sci_handler address, void *context)
* 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 @@ acpi_status acpi_remove_sci_handler(acpi_sci_handler address) ...@@ -522,6 +536,8 @@ acpi_status acpi_remove_sci_handler(acpi_sci_handler address)
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 @@ acpi_status acpi_remove_sci_handler(acpi_sci_handler address) ...@@ -537,7 +553,6 @@ acpi_status acpi_remove_sci_handler(acpi_sci_handler address)
* 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, ...@@ -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, ...@@ -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);
......
...@@ -599,9 +599,10 @@ acpi_install_gpe_block(acpi_handle gpe_device, ...@@ -599,9 +599,10 @@ acpi_install_gpe_block(acpi_handle gpe_device,
* For user-installed GPE Block Devices, the gpe_block_base_number * For user-installed GPE Block Devices, the gpe_block_base_number
* is always zero * is always zero
*/ */
status = status = acpi_ev_create_gpe_block(node, gpe_block_address->address,
acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0, gpe_block_address->space_id,
interrupt_number, &gpe_block); register_count, 0, interrupt_number,
&gpe_block);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
goto unlock_and_exit; goto unlock_and_exit;
} }
......
...@@ -343,16 +343,14 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) */ /* Install the new table into the local data structures */
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; ACPI_INFO((AE_INFO, "Dynamic OEM Table Load:"));
table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
/* Install the new table into the local data structures */ status = acpi_tb_install_standard_table(ACPI_PTR_TO_PHYSADDR(table),
ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL,
TRUE, TRUE, &table_index);
status = acpi_tb_add_table(&table_desc, &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, ...@@ -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, ...@@ -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) ...@@ -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()
......
...@@ -134,9 +134,11 @@ static struct acpi_exdump_info acpi_ex_dump_method[9] = { ...@@ -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"},
......
...@@ -140,11 +140,12 @@ acpi_hw_derive_pci_id(struct acpi_pci_id *pci_id, ...@@ -140,11 +140,12 @@ acpi_hw_derive_pci_id(struct acpi_pci_id *pci_id,
/* Walk the list, updating the PCI device/function/bus numbers */ /* Walk the list, updating the PCI device/function/bus numbers */
status = acpi_hw_process_pci_list(pci_id, list_head); status = acpi_hw_process_pci_list(pci_id, list_head);
}
/* Always delete the list */ /* Delete the list */
acpi_hw_delete_pci_list(list_head);
}
acpi_hw_delete_pci_list(list_head);
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
...@@ -187,6 +188,10 @@ acpi_hw_build_pci_list(acpi_handle root_pci_device, ...@@ -187,6 +188,10 @@ acpi_hw_build_pci_list(acpi_handle root_pci_device,
while (1) { while (1) {
status = acpi_get_parent(current_device, &parent_device); status = acpi_get_parent(current_device, &parent_device);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
/* Must delete the list before exit */
acpi_hw_delete_pci_list(*return_list_head);
return (status); return (status);
} }
...@@ -199,6 +204,10 @@ acpi_hw_build_pci_list(acpi_handle root_pci_device, ...@@ -199,6 +204,10 @@ acpi_hw_build_pci_list(acpi_handle root_pci_device,
list_element = ACPI_ALLOCATE(sizeof(struct acpi_pci_device)); list_element = ACPI_ALLOCATE(sizeof(struct acpi_pci_device));
if (!list_element) { if (!list_element) {
/* Must delete the list before exit */
acpi_hw_delete_pci_list(*return_list_head);
return (AE_NO_MEMORY); return (AE_NO_MEMORY);
} }
......
...@@ -72,6 +72,8 @@ acpi_buffer_to_resource(u8 *aml_buffer, ...@@ -72,6 +72,8 @@ acpi_buffer_to_resource(u8 *aml_buffer,
void *resource; void *resource;
void *current_resource_ptr; void *current_resource_ptr;
ACPI_FUNCTION_TRACE(acpi_buffer_to_resource);
/* /*
* Note: we allow AE_AML_NO_RESOURCE_END_TAG, since an end tag * Note: we allow AE_AML_NO_RESOURCE_END_TAG, since an end tag
* is not required here. * is not required here.
...@@ -85,7 +87,7 @@ acpi_buffer_to_resource(u8 *aml_buffer, ...@@ -85,7 +87,7 @@ acpi_buffer_to_resource(u8 *aml_buffer,
status = AE_OK; status = AE_OK;
} }
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
return (status); return_ACPI_STATUS(status);
} }
/* Allocate a buffer for the converted resource */ /* Allocate a buffer for the converted resource */
...@@ -93,7 +95,7 @@ acpi_buffer_to_resource(u8 *aml_buffer, ...@@ -93,7 +95,7 @@ acpi_buffer_to_resource(u8 *aml_buffer,
resource = ACPI_ALLOCATE_ZEROED(list_size_needed); resource = ACPI_ALLOCATE_ZEROED(list_size_needed);
current_resource_ptr = resource; current_resource_ptr = resource;
if (!resource) { if (!resource) {
return (AE_NO_MEMORY); return_ACPI_STATUS(AE_NO_MEMORY);
} }
/* Perform the AML-to-Resource conversion */ /* Perform the AML-to-Resource conversion */
...@@ -110,9 +112,11 @@ acpi_buffer_to_resource(u8 *aml_buffer, ...@@ -110,9 +112,11 @@ acpi_buffer_to_resource(u8 *aml_buffer,
*resource_ptr = resource; *resource_ptr = resource;
} }
return (status); return_ACPI_STATUS(status);
} }
ACPI_EXPORT_SYMBOL(acpi_buffer_to_resource)
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_rs_create_resource_list * FUNCTION: acpi_rs_create_resource_list
...@@ -130,10 +134,9 @@ acpi_buffer_to_resource(u8 *aml_buffer, ...@@ -130,10 +134,9 @@ acpi_buffer_to_resource(u8 *aml_buffer,
* of device resources. * of device resources.
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_status
acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer, acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer,
struct acpi_buffer * output_buffer) struct acpi_buffer *output_buffer)
{ {
acpi_status status; acpi_status status;
......
/******************************************************************************
*
* 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);
}
...@@ -52,7 +52,8 @@ ACPI_MODULE_NAME("tbfadt") ...@@ -52,7 +52,8 @@ ACPI_MODULE_NAME("tbfadt")
static void static void
acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
u8 space_id, u8 space_id,
u8 byte_width, u64 address, char *register_name); u8 byte_width,
u64 address, char *register_name, u8 flags);
static void acpi_tb_convert_fadt(void); static void acpi_tb_convert_fadt(void);
...@@ -69,13 +70,14 @@ typedef struct acpi_fadt_info { ...@@ -69,13 +70,14 @@ typedef struct acpi_fadt_info {
u16 address32; u16 address32;
u16 length; u16 length;
u8 default_length; u8 default_length;
u8 type; u8 flags;
} acpi_fadt_info; } acpi_fadt_info;
#define ACPI_FADT_OPTIONAL 0 #define ACPI_FADT_OPTIONAL 0
#define ACPI_FADT_REQUIRED 1 #define ACPI_FADT_REQUIRED 1
#define ACPI_FADT_SEPARATE_LENGTH 2 #define ACPI_FADT_SEPARATE_LENGTH 2
#define ACPI_FADT_GPE_REGISTER 4
static struct acpi_fadt_info fadt_info_table[] = { static struct acpi_fadt_info fadt_info_table[] = {
{"Pm1aEventBlock", {"Pm1aEventBlock",
...@@ -125,14 +127,14 @@ static struct acpi_fadt_info fadt_info_table[] = { ...@@ -125,14 +127,14 @@ static struct acpi_fadt_info fadt_info_table[] = {
ACPI_FADT_OFFSET(gpe0_block), ACPI_FADT_OFFSET(gpe0_block),
ACPI_FADT_OFFSET(gpe0_block_length), ACPI_FADT_OFFSET(gpe0_block_length),
0, 0,
ACPI_FADT_SEPARATE_LENGTH}, ACPI_FADT_SEPARATE_LENGTH | ACPI_FADT_GPE_REGISTER},
{"Gpe1Block", {"Gpe1Block",
ACPI_FADT_OFFSET(xgpe1_block), ACPI_FADT_OFFSET(xgpe1_block),
ACPI_FADT_OFFSET(gpe1_block), ACPI_FADT_OFFSET(gpe1_block),
ACPI_FADT_OFFSET(gpe1_block_length), ACPI_FADT_OFFSET(gpe1_block_length),
0, 0,
ACPI_FADT_SEPARATE_LENGTH} ACPI_FADT_SEPARATE_LENGTH | ACPI_FADT_GPE_REGISTER}
}; };
#define ACPI_FADT_INFO_ENTRIES \ #define ACPI_FADT_INFO_ENTRIES \
...@@ -189,19 +191,29 @@ static struct acpi_fadt_pm_info fadt_pm_info_table[] = { ...@@ -189,19 +191,29 @@ static struct acpi_fadt_pm_info fadt_pm_info_table[] = {
static void static void
acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
u8 space_id, u8 space_id,
u8 byte_width, u64 address, char *register_name) u8 byte_width,
u64 address, char *register_name, u8 flags)
{ {
u8 bit_width; u8 bit_width;
/* Bit width field in the GAS is only one byte long, 255 max */ /*
* Bit width field in the GAS is only one byte long, 255 max.
* Check for bit_width overflow in GAS.
*/
bit_width = (u8)(byte_width * 8); bit_width = (u8)(byte_width * 8);
if (byte_width > 31) { /* (31*8)=248, (32*8)=256 */
if (byte_width > 31) { /* (31*8)=248 */ /*
ACPI_ERROR((AE_INFO, * No error for GPE blocks, because we do not use the bit_width
"%s - 32-bit FADT register is too long (%u bytes, %u bits) " * for GPEs, the legacy length (byte_width) is used instead to
"to convert to GAS struct - 255 bits max, truncating", * allow for a large number of GPEs.
register_name, byte_width, (byte_width * 8))); */
if (!(flags & ACPI_FADT_GPE_REGISTER)) {
ACPI_ERROR((AE_INFO,
"%s - 32-bit FADT register is too long (%u bytes, %u bits) "
"to convert to GAS struct - 255 bits max, truncating",
register_name, byte_width,
(byte_width * 8)));
}
bit_width = 255; bit_width = 255;
} }
...@@ -332,15 +344,15 @@ void acpi_tb_parse_fadt(u32 table_index) ...@@ -332,15 +344,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);
} }
} }
...@@ -450,6 +462,7 @@ static void acpi_tb_convert_fadt(void) ...@@ -450,6 +462,7 @@ static void acpi_tb_convert_fadt(void)
struct acpi_generic_address *address64; struct acpi_generic_address *address64;
u32 address32; u32 address32;
u8 length; u8 length;
u8 flags;
u32 i; u32 i;
/* /*
...@@ -515,6 +528,7 @@ static void acpi_tb_convert_fadt(void) ...@@ -515,6 +528,7 @@ static void acpi_tb_convert_fadt(void)
fadt_info_table[i].length); fadt_info_table[i].length);
name = fadt_info_table[i].name; name = fadt_info_table[i].name;
flags = fadt_info_table[i].flags;
/* /*
* Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X" * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X"
...@@ -554,7 +568,7 @@ static void acpi_tb_convert_fadt(void) ...@@ -554,7 +568,7 @@ static void acpi_tb_convert_fadt(void)
[i]. [i].
length), length),
(u64)address32, (u64)address32,
name); name, flags);
} else if (address64->address != (u64)address32) { } else if (address64->address != (u64)address32) {
/* Address mismatch */ /* Address mismatch */
...@@ -582,7 +596,8 @@ static void acpi_tb_convert_fadt(void) ...@@ -582,7 +596,8 @@ static void acpi_tb_convert_fadt(void)
length), length),
(u64) (u64)
address32, address32,
name); name,
flags);
} }
} }
} }
...@@ -603,7 +618,7 @@ static void acpi_tb_convert_fadt(void) ...@@ -603,7 +618,7 @@ static void acpi_tb_convert_fadt(void)
address64->bit_width)); address64->bit_width));
} }
if (fadt_info_table[i].type & ACPI_FADT_REQUIRED) { if (fadt_info_table[i].flags & ACPI_FADT_REQUIRED) {
/* /*
* Field is required (Pm1a_event, Pm1a_control). * Field is required (Pm1a_event, Pm1a_control).
* Both the address and length must be non-zero. * Both the address and length must be non-zero.
...@@ -617,7 +632,7 @@ static void acpi_tb_convert_fadt(void) ...@@ -617,7 +632,7 @@ static void acpi_tb_convert_fadt(void)
address), address),
length)); length));
} }
} else if (fadt_info_table[i].type & ACPI_FADT_SEPARATE_LENGTH) { } else if (fadt_info_table[i].flags & ACPI_FADT_SEPARATE_LENGTH) {
/* /*
* Field is optional (Pm2_control, GPE0, GPE1) AND has its own * Field is optional (Pm2_control, GPE0, GPE1) AND has its own
* length field. If present, both the address and length must * length field. If present, both the address and length must
...@@ -726,7 +741,7 @@ static void acpi_tb_setup_fadt_registers(void) ...@@ -726,7 +741,7 @@ static void acpi_tb_setup_fadt_registers(void)
(fadt_pm_info_table[i]. (fadt_pm_info_table[i].
register_num * register_num *
pm1_register_byte_width), pm1_register_byte_width),
"PmRegisters"); "PmRegisters", 0);
} }
} }
} }
...@@ -99,8 +99,8 @@ acpi_tb_find_table(char *signature, ...@@ -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);
} }
......
...@@ -43,688 +43,483 @@ ...@@ -43,688 +43,483 @@
#include <acpi/acpi.h> #include <acpi/acpi.h>
#include "accommon.h" #include "accommon.h"
#include "acnamesp.h"
#include "actables.h" #include "actables.h"
#define _COMPONENT ACPI_TABLES #define _COMPONENT ACPI_TABLES
ACPI_MODULE_NAME("tbinstal") ACPI_MODULE_NAME("tbinstal")
/****************************************************************************** /* Local prototypes */
static u8
acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index);
/*******************************************************************************
* *
* FUNCTION: acpi_tb_verify_table * FUNCTION: acpi_tb_compare_tables
* *
* PARAMETERS: table_desc - table * PARAMETERS: table_desc - Table 1 descriptor to be compared
* table_index - Index of table 2 to be compared
* *
* RETURN: Status * RETURN: TRUE if both tables are identical.
* *
* DESCRIPTION: this function is called to verify and map table * DESCRIPTION: This function compares a table with another table that has
* already been installed in the root table list.
* *
*****************************************************************************/ ******************************************************************************/
acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc)
static u8
acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index)
{ {
acpi_status status = AE_OK; acpi_status status = AE_OK;
u8 is_identical;
struct acpi_table_header *table;
u32 table_length;
u8 table_flags;
ACPI_FUNCTION_TRACE(tb_verify_table); status =
acpi_tb_acquire_table(&acpi_gbl_root_table_list.tables[table_index],
/* Map the table if necessary */ &table, &table_length, &table_flags);
if (ACPI_FAILURE(status)) {
if (!table_desc->pointer) { return (FALSE);
if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) ==
ACPI_TABLE_ORIGIN_MAPPED) {
table_desc->pointer =
acpi_os_map_memory(table_desc->address,
table_desc->length);
}
if (!table_desc->pointer) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
} }
/* Always calculate checksum, ignore bad checksum if requested */ /*
* Check for a table match on the entire table length,
* not just the header.
*/
is_identical = (u8)((table_desc->length != table_length ||
ACPI_MEMCMP(table_desc->pointer, table,
table_length)) ? FALSE : TRUE);
status = /* Release the acquired table */
acpi_tb_verify_checksum(table_desc->pointer, table_desc->length);
return_ACPI_STATUS(status); acpi_tb_release_table(table, table_length, table_flags);
return (is_identical);
} }
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_tb_add_table * FUNCTION: acpi_tb_install_table_with_override
* *
* PARAMETERS: table_desc - Table descriptor * PARAMETERS: table_index - Index into root table array
* table_index - Where the table index is returned * new_table_desc - New table descriptor to install
* override - Whether override should be performed
* *
* RETURN: Status * RETURN: None
* *
* DESCRIPTION: This function is called to add an ACPI table. It is used to * DESCRIPTION: Install an ACPI table into the global data structure. The
* dynamically load tables via the Load and load_table AML * table override mechanism is called to allow the host
* operators. * OS to replace any table before it is installed in the root
* table array.
* *
******************************************************************************/ ******************************************************************************/
acpi_status void
acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) acpi_tb_install_table_with_override(u32 table_index,
struct acpi_table_desc *new_table_desc,
u8 override)
{ {
u32 i;
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE(tb_add_table); if (table_index >= acpi_gbl_root_table_list.current_table_count) {
return;
if (!table_desc->pointer) {
status = acpi_tb_verify_table(table_desc);
if (ACPI_FAILURE(status) || !table_desc->pointer) {
return_ACPI_STATUS(status);
}
} }
/* /*
* Validate the incoming table signature. * ACPI Table Override:
* *
* 1) Originally, we checked the table signature for "SSDT" or "PSDT". * Before we install the table, let the host OS override it with a new
* 2) We added support for OEMx tables, signature "OEM". * one if desired. Any table within the RSDT/XSDT can be replaced,
* 3) Valid tables were encountered with a null signature, so we just * including the DSDT which is pointed to by the FADT.
* gave up on validating the signature, (05/2008).
* 4) We encountered non-AML tables such as the MADT, which caused
* interpreter errors and kernel faults. So now, we once again allow
* only "SSDT", "OEMx", and now, also a null signature. (05/2011).
*/ */
if ((table_desc->pointer->signature[0] != 0x00) && if (override) {
(!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT)) acpi_tb_override_table(new_table_desc);
&& (ACPI_STRNCMP(table_desc->pointer->signature, "OEM", 3))) {
ACPI_BIOS_ERROR((AE_INFO,
"Table has invalid signature [%4.4s] (0x%8.8X), "
"must be SSDT or OEMx",
acpi_ut_valid_acpi_name(table_desc->pointer->
signature) ?
table_desc->pointer->signature : "????",
*(u32 *)table_desc->pointer->signature));
return_ACPI_STATUS(AE_BAD_SIGNATURE);
} }
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list.
tables[table_index],
new_table_desc->address,
new_table_desc->flags,
new_table_desc->pointer);
/* Check if table is already registered */ acpi_tb_print_table_header(new_table_desc->address,
new_table_desc->pointer);
for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) { /* Set the global integer width (based upon revision of the DSDT) */
if (!acpi_gbl_root_table_list.tables[i].pointer) {
status =
acpi_tb_verify_table(&acpi_gbl_root_table_list.
tables[i]);
if (ACPI_FAILURE(status)
|| !acpi_gbl_root_table_list.tables[i].pointer) {
continue;
}
}
/* if (table_index == ACPI_TABLE_INDEX_DSDT) {
* Check for a table match on the entire table length, acpi_ut_set_integer_width(new_table_desc->pointer->revision);
* not just the header.
*/
if (table_desc->length !=
acpi_gbl_root_table_list.tables[i].length) {
continue;
}
if (ACPI_MEMCMP(table_desc->pointer,
acpi_gbl_root_table_list.tables[i].pointer,
acpi_gbl_root_table_list.tables[i].length)) {
continue;
}
/*
* Note: the current mechanism does not unregister a table if it is
* dynamically unloaded. The related namespace entries are deleted,
* but the table remains in the root table list.
*
* The assumption here is that the number of different tables that
* will be loaded is actually small, and there is minimal overhead
* in just keeping the table in case it is needed again.
*
* If this assumption changes in the future (perhaps on large
* machines with many table load/unload operations), tables will
* need to be unregistered when they are unloaded, and slots in the
* root table list should be reused when empty.
*/
/*
* Table is already registered.
* We can delete the table that was passed as a parameter.
*/
acpi_tb_delete_table(table_desc);
*table_index = i;
if (acpi_gbl_root_table_list.tables[i].
flags & ACPI_TABLE_IS_LOADED) {
/* Table is still loaded, this is an error */
status = AE_ALREADY_EXISTS;
goto release;
} else {
/* Table was unloaded, allow it to be reloaded */
table_desc->pointer =
acpi_gbl_root_table_list.tables[i].pointer;
table_desc->address =
acpi_gbl_root_table_list.tables[i].address;
status = AE_OK;
goto print_header;
}
} }
/*
* ACPI Table Override:
* Allow the host to override dynamically loaded tables.
* NOTE: the table is fully mapped at this point, and the mapping will
* be deleted by tb_table_override if the table is actually overridden.
*/
(void)acpi_tb_table_override(table_desc->pointer, table_desc);
/* Add the table to the global root table list */
status = acpi_tb_store_table(table_desc->address, table_desc->pointer,
table_desc->length, table_desc->flags,
table_index);
if (ACPI_FAILURE(status)) {
goto release;
}
print_header:
acpi_tb_print_table_header(table_desc->address, table_desc->pointer);
release:
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
return_ACPI_STATUS(status);
} }
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_tb_table_override * FUNCTION: acpi_tb_install_fixed_table
* *
* PARAMETERS: table_header - Header for the original table * PARAMETERS: address - Physical address of DSDT or FACS
* table_desc - Table descriptor initialized for the * signature - Table signature, NULL if no need to
* original table. May or may not be mapped. * match
* table_index - Index into root table array
* *
* RETURN: Pointer to the entire new table. NULL if table not overridden. * RETURN: Status
* If overridden, installs the new table within the input table
* descriptor.
* *
* DESCRIPTION: Attempt table override by calling the OSL override functions. * DESCRIPTION: Install a fixed ACPI table (DSDT/FACS) into the global data
* Note: If the table is overridden, then the entire new table * structure.
* is mapped and returned by this function.
* *
******************************************************************************/ ******************************************************************************/
struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header acpi_status
*table_header, acpi_tb_install_fixed_table(acpi_physical_address address,
struct acpi_table_desc char *signature, u32 table_index)
*table_desc)
{ {
struct acpi_table_desc new_table_desc;
acpi_status status; acpi_status status;
struct acpi_table_header *new_table = NULL;
acpi_physical_address new_address = 0;
u32 new_table_length = 0;
u8 new_flags;
char *override_type;
/* (1) Attempt logical override (returns a logical address) */ ACPI_FUNCTION_TRACE(tb_install_fixed_table);
status = acpi_os_table_override(table_header, &new_table); if (!address) {
if (ACPI_SUCCESS(status) && new_table) { ACPI_ERROR((AE_INFO,
new_address = ACPI_PTR_TO_PHYSADDR(new_table); "Null physical address for ACPI table [%s]",
new_table_length = new_table->length; signature));
new_flags = ACPI_TABLE_ORIGIN_OVERRIDE; return (AE_NO_MEMORY);
override_type = "Logical";
goto finish_override;
} }
/* (2) Attempt physical override (returns a physical address) */ /* Fill a table descriptor for validation */
status = acpi_os_physical_table_override(table_header, status = acpi_tb_acquire_temp_table(&new_table_desc, address,
&new_address, ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL);
&new_table_length); if (ACPI_FAILURE(status)) {
if (ACPI_SUCCESS(status) && new_address && new_table_length) { ACPI_ERROR((AE_INFO, "Could not acquire table length at %p",
ACPI_CAST_PTR(void, address)));
/* Map the entire new table */ return_ACPI_STATUS(status);
new_table = acpi_os_map_memory(new_address, new_table_length);
if (!new_table) {
ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY,
"%4.4s " ACPI_PRINTF_UINT
" Attempted physical table override failed",
table_header->signature,
ACPI_FORMAT_TO_UINT(table_desc->
address)));
return (NULL);
}
override_type = "Physical";
new_flags = ACPI_TABLE_ORIGIN_MAPPED;
goto finish_override;
} }
return (NULL); /* There was no override */ /* Validate and verify a table before installation */
finish_override:
ACPI_INFO((AE_INFO, "%4.4s " ACPI_PRINTF_UINT
" %s table override, new table: " ACPI_PRINTF_UINT,
table_header->signature,
ACPI_FORMAT_TO_UINT(table_desc->address),
override_type, ACPI_FORMAT_TO_UINT(new_table)));
/* We can now unmap/delete the original table (if fully mapped) */ status = acpi_tb_verify_table(&new_table_desc, signature);
if (ACPI_FAILURE(status)) {
goto release_and_exit;
}
acpi_tb_delete_table(table_desc); acpi_tb_install_table_with_override(table_index, &new_table_desc, TRUE);
/* Setup descriptor for the new table */ release_and_exit:
table_desc->address = new_address; /* Release the temporary table descriptor */
table_desc->pointer = new_table;
table_desc->length = new_table_length;
table_desc->flags = new_flags;
return (new_table); acpi_tb_release_temp_table(&new_table_desc);
return_ACPI_STATUS(status);
} }
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_tb_resize_root_table_list * FUNCTION: acpi_tb_install_standard_table
* *
* PARAMETERS: None * PARAMETERS: address - Address of the table (might be a virtual
* address depending on the table_flags)
* flags - Flags for the table
* reload - Whether reload should be performed
* override - Whether override should be performed
* table_index - Where the table index is returned
* *
* RETURN: Status * RETURN: Status
* *
* DESCRIPTION: Expand the size of global table array * DESCRIPTION: This function is called to install an ACPI table that is
* neither DSDT nor FACS (a "standard" table.)
* When this function is called by "Load" or "LoadTable" opcodes,
* or by acpi_load_table() API, the "Reload" parameter is set.
* After sucessfully returning from this function, table is
* "INSTALLED" but not "VALIDATED".
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_tb_resize_root_table_list(void) acpi_status
acpi_tb_install_standard_table(acpi_physical_address address,
u8 flags,
u8 reload, u8 override, u32 *table_index)
{ {
struct acpi_table_desc *tables; u32 i;
u32 table_count; acpi_status status = AE_OK;
struct acpi_table_desc new_table_desc;
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_FUNCTION_TRACE(tb_install_standard_table);
ACPI_ERROR((AE_INFO,
"Resize of Root Table Array is not allowed"));
return_ACPI_STATUS(AE_SUPPORT);
}
/* Increase the Table Array size */ /* Acquire a temporary table descriptor for validation */
if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { status = acpi_tb_acquire_temp_table(&new_table_desc, address, flags);
table_count = acpi_gbl_root_table_list.max_table_count; if (ACPI_FAILURE(status)) {
} else { ACPI_ERROR((AE_INFO, "Could not acquire table length at %p",
table_count = acpi_gbl_root_table_list.current_table_count; ACPI_CAST_PTR(void, address)));
return_ACPI_STATUS(status);
} }
tables = ACPI_ALLOCATE_ZEROED(((acpi_size) table_count + /*
ACPI_ROOT_TABLE_SIZE_INCREMENT) * * Optionally do not load any SSDTs from the RSDT/XSDT. This can
sizeof(struct acpi_table_desc)); * be useful for debugging ACPI problems on some machines.
if (!tables) { */
ACPI_ERROR((AE_INFO, if (!reload &&
"Could not allocate new root table array")); acpi_gbl_disable_ssdt_table_install &&
return_ACPI_STATUS(AE_NO_MEMORY); ACPI_COMPARE_NAME(&new_table_desc.signature, ACPI_SIG_SSDT)) {
ACPI_INFO((AE_INFO, "Ignoring installation of %4.4s at %p",
new_table_desc.signature.ascii, ACPI_CAST_PTR(void,
address)));
goto release_and_exit;
} }
/* Copy and free the previous table array */ /* Validate and verify a table before installation */
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) { status = acpi_tb_verify_table(&new_table_desc, NULL);
ACPI_FREE(acpi_gbl_root_table_list.tables); if (ACPI_FAILURE(status)) {
} goto release_and_exit;
} }
acpi_gbl_root_table_list.tables = tables; if (reload) {
acpi_gbl_root_table_list.max_table_count = /*
table_count + ACPI_ROOT_TABLE_SIZE_INCREMENT; * Validate the incoming table signature.
acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED; *
* 1) Originally, we checked the table signature for "SSDT" or "PSDT".
return_ACPI_STATUS(AE_OK); * 2) We added support for OEMx tables, signature "OEM".
} * 3) Valid tables were encountered with a null signature, so we just
* gave up on validating the signature, (05/2008).
/******************************************************************************* * 4) We encountered non-AML tables such as the MADT, which caused
* * interpreter errors and kernel faults. So now, we once again allow
* FUNCTION: acpi_tb_store_table * only "SSDT", "OEMx", and now, also a null signature. (05/2011).
* */
* PARAMETERS: address - Table address if ((new_table_desc.signature.ascii[0] != 0x00) &&
* table - Table header (!ACPI_COMPARE_NAME
* length - Table length (&new_table_desc.signature, ACPI_SIG_SSDT))
* flags - flags && (ACPI_STRNCMP(new_table_desc.signature.ascii, "OEM", 3)))
* {
* RETURN: Status and table index. ACPI_BIOS_ERROR((AE_INFO,
* "Table has invalid signature [%4.4s] (0x%8.8X), "
* DESCRIPTION: Add an ACPI table to the global table list "must be SSDT or OEMx",
* acpi_ut_valid_acpi_name(new_table_desc.
******************************************************************************/ signature.
ascii) ?
new_table_desc.signature.
ascii : "????",
new_table_desc.signature.integer));
status = AE_BAD_SIGNATURE;
goto release_and_exit;
}
acpi_status /* Check if table is already registered */
acpi_tb_store_table(acpi_physical_address address,
struct acpi_table_header *table,
u32 length, u8 flags, u32 *table_index)
{
acpi_status status;
struct acpi_table_desc *new_table;
/* Ensure that there is room for the table in the Root Table List */ for (i = 0; i < acpi_gbl_root_table_list.current_table_count;
++i) {
/*
* Check for a table match on the entire table length,
* not just the header.
*/
if (!acpi_tb_compare_tables(&new_table_desc, i)) {
continue;
}
if (acpi_gbl_root_table_list.current_table_count >= /*
acpi_gbl_root_table_list.max_table_count) { * Note: the current mechanism does not unregister a table if it is
status = acpi_tb_resize_root_table_list(); * dynamically unloaded. The related namespace entries are deleted,
if (ACPI_FAILURE(status)) { * but the table remains in the root table list.
return (status); *
* The assumption here is that the number of different tables that
* will be loaded is actually small, and there is minimal overhead
* in just keeping the table in case it is needed again.
*
* If this assumption changes in the future (perhaps on large
* machines with many table load/unload operations), tables will
* need to be unregistered when they are unloaded, and slots in the
* root table list should be reused when empty.
*/
if (acpi_gbl_root_table_list.tables[i].
flags & ACPI_TABLE_IS_LOADED) {
/* Table is still loaded, this is an error */
status = AE_ALREADY_EXISTS;
goto release_and_exit;
} else {
/*
* Table was unloaded, allow it to be reloaded.
* As we are going to return AE_OK to the caller, we should
* take the responsibility of freeing the input descriptor.
* Refill the input descriptor to ensure
* acpi_tb_install_table_with_override() can be called again to
* indicate the re-installation.
*/
acpi_tb_uninstall_table(&new_table_desc);
*table_index = i;
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
return_ACPI_STATUS(AE_OK);
}
} }
} }
new_table = /* Add the table to the global root table list */
&acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.
current_table_count];
/* Initialize added table */
new_table->address = address;
new_table->pointer = table;
new_table->length = length;
new_table->owner_id = 0;
new_table->flags = flags;
ACPI_MOVE_32_TO_32(&new_table->signature, table->signature);
*table_index = acpi_gbl_root_table_list.current_table_count;
acpi_gbl_root_table_list.current_table_count++;
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_delete_table
*
* PARAMETERS: table_index - Table index
*
* RETURN: None
*
* DESCRIPTION: Delete one internal ACPI table
*
******************************************************************************/
void acpi_tb_delete_table(struct acpi_table_desc *table_desc) status = acpi_tb_get_next_root_index(&i);
{ if (ACPI_FAILURE(status)) {
/* Table must be mapped or allocated */ goto release_and_exit;
if (!table_desc->pointer) {
return;
} }
switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) {
case ACPI_TABLE_ORIGIN_MAPPED:
acpi_os_unmap_memory(table_desc->pointer, table_desc->length);
break;
case ACPI_TABLE_ORIGIN_ALLOCATED:
ACPI_FREE(table_desc->pointer); *table_index = i;
break; acpi_tb_install_table_with_override(i, &new_table_desc, override);
/* Not mapped or allocated, there is nothing we can do */ release_and_exit:
default: /* Release the temporary table descriptor */
return; acpi_tb_release_temp_table(&new_table_desc);
} return_ACPI_STATUS(status);
table_desc->pointer = NULL;
} }
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_tb_terminate * FUNCTION: acpi_tb_override_table
* *
* PARAMETERS: None * PARAMETERS: old_table_desc - Validated table descriptor to be
* overridden
* *
* RETURN: None * RETURN: None
* *
* DESCRIPTION: Delete all internal ACPI tables * DESCRIPTION: Attempt table override by calling the OSL override functions.
* Note: If the table is overridden, then the entire new table
* is acquired and returned by this function.
* Before/after invocation, the table descriptor is in a state
* that is "VALIDATED".
* *
******************************************************************************/ ******************************************************************************/
void acpi_tb_terminate(void) void acpi_tb_override_table(struct acpi_table_desc *old_table_desc)
{ {
u32 i; acpi_status status;
char *override_type;
ACPI_FUNCTION_TRACE(tb_terminate); struct acpi_table_desc new_table_desc;
struct acpi_table_header *table;
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); acpi_physical_address address;
u32 length;
/* Delete the individual tables */
for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) { /* (1) Attempt logical override (returns a logical address) */
acpi_tb_delete_table(&acpi_gbl_root_table_list.tables[i]);
}
/* status = acpi_os_table_override(old_table_desc->pointer, &table);
* Delete the root table array if allocated locally. Array cannot be if (ACPI_SUCCESS(status) && table) {
* mapped, so we don't need to check for that flag. acpi_tb_acquire_temp_table(&new_table_desc,
*/ ACPI_PTR_TO_PHYSADDR(table),
if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL);
ACPI_FREE(acpi_gbl_root_table_list.tables); override_type = "Logical";
goto finish_override;
} }
acpi_gbl_root_table_list.tables = NULL; /* (2) Attempt physical override (returns a physical address) */
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")); status = acpi_os_physical_table_override(old_table_desc->pointer,
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES); &address, &length);
if (ACPI_SUCCESS(status) && address && length) {
acpi_tb_acquire_temp_table(&new_table_desc, address,
ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL);
override_type = "Physical";
goto finish_override;
}
return_VOID; return; /* There was no override */
}
/******************************************************************************* finish_override:
*
* 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); /* Validate and verify a table before overriding */
status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); status = acpi_tb_verify_table(&new_table_desc, NULL);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status); return;
} }
if (table_index >= acpi_gbl_root_table_list.current_table_count) { ACPI_INFO((AE_INFO, "%4.4s " ACPI_PRINTF_UINT
" %s table override, new table: " ACPI_PRINTF_UINT,
/* The table index does not exist */ old_table_desc->signature.ascii,
ACPI_FORMAT_TO_UINT(old_table_desc->address),
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES); override_type, ACPI_FORMAT_TO_UINT(new_table_desc.address)));
return_ACPI_STATUS(AE_NOT_EXIST);
}
/* Get the owner ID for this table, used to delete namespace nodes */ /* We can now uninstall the original table */
owner_id = acpi_gbl_root_table_list.tables[table_index].owner_id; acpi_tb_uninstall_table(old_table_desc);
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
/* /*
* Need to acquire the namespace writer lock to prevent interference * Replace the original table descriptor and keep its state as
* with any concurrent namespace walks. The interpreter must be * "VALIDATED".
* 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); acpi_tb_init_table_descriptor(old_table_desc, new_table_desc.address,
status = acpi_ut_acquire_write_lock(&acpi_gbl_namespace_rw_lock); new_table_desc.flags,
new_table_desc.pointer);
acpi_tb_validate_table(old_table_desc);
acpi_ns_delete_namespace_by_owner(owner_id); /* Release the temporary table descriptor */
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
acpi_ut_release_write_lock(&acpi_gbl_namespace_rw_lock); acpi_tb_release_temp_table(&new_table_desc);
status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER);
return_ACPI_STATUS(status);
} }
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_tb_allocate_owner_id * FUNCTION: acpi_tb_store_table
* *
* PARAMETERS: table_index - Table index * PARAMETERS: address - Table address
* table - Table header
* length - Table length
* flags - Install flags
* table_index - Where the table index is returned
* *
* RETURN: Status * RETURN: Status and table index.
* *
* DESCRIPTION: Allocates owner_id in table_desc * DESCRIPTION: Add an ACPI table to the global table list
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_tb_allocate_owner_id(u32 table_index) acpi_status
acpi_tb_store_table(acpi_physical_address address,
struct acpi_table_header * table,
u32 length, u8 flags, u32 *table_index)
{ {
acpi_status status = AE_BAD_PARAMETER; acpi_status status;
struct acpi_table_desc *table_desc;
ACPI_FUNCTION_TRACE(tb_allocate_owner_id);
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); status = acpi_tb_get_next_root_index(table_index);
if (table_index < acpi_gbl_root_table_list.current_table_count) { if (ACPI_FAILURE(status)) {
status = acpi_ut_allocate_owner_id return (status);
(&(acpi_gbl_root_table_list.tables[table_index].owner_id));
} }
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES); /* Initialize added table */
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); table_desc = &acpi_gbl_root_table_list.tables[*table_index];
return_ACPI_STATUS(status); acpi_tb_init_table_descriptor(table_desc, address, flags, table);
table_desc->pointer = table;
return (AE_OK);
} }
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_tb_get_owner_id * FUNCTION: acpi_tb_uninstall_table
* *
* PARAMETERS: table_index - Table index * PARAMETERS: table_desc - Table descriptor
* owner_id - Where the table owner_id is returned
* *
* RETURN: Status * RETURN: None
* *
* DESCRIPTION: returns owner_id for the ACPI table * DESCRIPTION: Delete one internal ACPI table
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id *owner_id) void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc)
{ {
acpi_status status = AE_BAD_PARAMETER;
ACPI_FUNCTION_TRACE(tb_get_owner_id);
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); ACPI_FUNCTION_TRACE(tb_uninstall_table);
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); /* Table must be installed */
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_is_table_loaded
*
* PARAMETERS: table_index - Table index
*
* RETURN: Table Loaded Flag
*
******************************************************************************/
u8 acpi_tb_is_table_loaded(u32 table_index) if (!table_desc->address) {
{ return_VOID;
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); acpi_tb_invalidate_table(table_desc);
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_desc->flags & ACPI_TABLE_ORIGIN_MASK) ==
if (table_index < acpi_gbl_root_table_list.current_table_count) { ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL) {
if (is_loaded) { ACPI_FREE(ACPI_CAST_PTR(void, table_desc->address));
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); table_desc->address = ACPI_PTR_TO_PHYSADDR(NULL);
return_VOID;
} }
...@@ -49,8 +49,6 @@ ...@@ -49,8 +49,6 @@
ACPI_MODULE_NAME("tbutils") ACPI_MODULE_NAME("tbutils")
/* Local prototypes */ /* Local prototypes */
static acpi_status acpi_tb_validate_xsdt(acpi_physical_address address);
static acpi_physical_address static acpi_physical_address
acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size); acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size);
...@@ -178,9 +176,13 @@ struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index) ...@@ -178,9 +176,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 +191,6 @@ struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index) ...@@ -189,116 +191,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
...@@ -355,87 +247,6 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size) ...@@ -355,87 +247,6 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size)
} }
} }
/*******************************************************************************
*
* FUNCTION: acpi_tb_validate_xsdt
*
* PARAMETERS: address - Physical address of the XSDT (from RSDP)
*
* RETURN: Status. AE_OK if the table appears to be valid.
*
* DESCRIPTION: Validate an XSDT to ensure that it is of minimum size and does
* not contain any NULL entries. A problem that is seen in the
* field is that the XSDT exists, but is actually useless because
* of one or more (or all) NULL entries.
*
******************************************************************************/
static acpi_status acpi_tb_validate_xsdt(acpi_physical_address xsdt_address)
{
struct acpi_table_header *table;
u8 *next_entry;
acpi_physical_address address;
u32 length;
u32 entry_count;
acpi_status status;
u32 i;
/* Get the XSDT length */
table =
acpi_os_map_memory(xsdt_address, sizeof(struct acpi_table_header));
if (!table) {
return (AE_NO_MEMORY);
}
length = table->length;
acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
/*
* Minimum XSDT length is the size of the standard ACPI header
* plus one physical address entry
*/
if (length < (sizeof(struct acpi_table_header) + ACPI_XSDT_ENTRY_SIZE)) {
return (AE_INVALID_TABLE_LENGTH);
}
/* Map the entire XSDT */
table = acpi_os_map_memory(xsdt_address, length);
if (!table) {
return (AE_NO_MEMORY);
}
/* Get the number of entries and pointer to first entry */
status = AE_OK;
next_entry = ACPI_ADD_PTR(u8, table, sizeof(struct acpi_table_header));
entry_count = (u32)((table->length - sizeof(struct acpi_table_header)) /
ACPI_XSDT_ENTRY_SIZE);
/* Validate each entry (physical address) within the XSDT */
for (i = 0; i < entry_count; i++) {
address =
acpi_tb_get_root_table_entry(next_entry,
ACPI_XSDT_ENTRY_SIZE);
if (!address) {
/* Detected a NULL entry, XSDT is invalid */
status = AE_NULL_ENTRY;
break;
}
next_entry += ACPI_XSDT_ENTRY_SIZE;
}
/* Unmap table */
acpi_os_unmap_memory(table, length);
return (status);
}
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_tb_parse_root_table * FUNCTION: acpi_tb_parse_root_table
...@@ -461,10 +272,10 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address) ...@@ -461,10 +272,10 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
u32 table_count; u32 table_count;
struct acpi_table_header *table; struct acpi_table_header *table;
acpi_physical_address address; acpi_physical_address address;
acpi_physical_address rsdt_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);
...@@ -489,14 +300,11 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address) ...@@ -489,14 +300,11 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
* as per the ACPI specification. * as per the ACPI specification.
*/ */
address = (acpi_physical_address) rsdp->xsdt_physical_address; address = (acpi_physical_address) rsdp->xsdt_physical_address;
rsdt_address =
(acpi_physical_address) rsdp->rsdt_physical_address;
table_entry_size = ACPI_XSDT_ENTRY_SIZE; table_entry_size = ACPI_XSDT_ENTRY_SIZE;
} else { } else {
/* Root table is an RSDT (32-bit physical addresses) */ /* Root table is an RSDT (32-bit physical addresses) */
address = (acpi_physical_address) rsdp->rsdt_physical_address; address = (acpi_physical_address) rsdp->rsdt_physical_address;
rsdt_address = address;
table_entry_size = ACPI_RSDT_ENTRY_SIZE; table_entry_size = ACPI_RSDT_ENTRY_SIZE;
} }
...@@ -506,24 +314,6 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address) ...@@ -506,24 +314,6 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
*/ */
acpi_os_unmap_memory(rsdp, sizeof(struct acpi_table_rsdp)); acpi_os_unmap_memory(rsdp, sizeof(struct acpi_table_rsdp));
/*
* If it is present and used, validate the XSDT for access/size
* and ensure that all table entries are at least non-NULL
*/
if (table_entry_size == ACPI_XSDT_ENTRY_SIZE) {
status = acpi_tb_validate_xsdt(address);
if (ACPI_FAILURE(status)) {
ACPI_BIOS_WARNING((AE_INFO,
"XSDT is invalid (%s), using RSDT",
acpi_format_exception(status)));
/* Fall back to the RSDT */
address = rsdt_address;
table_entry_size = ACPI_RSDT_ENTRY_SIZE;
}
}
/* Map the RSDT/XSDT table header to get the full table length */ /* Map the RSDT/XSDT table header to get the full table length */
table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
...@@ -576,31 +366,33 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address) ...@@ -576,31 +366,33 @@ 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. address =
current_table_count].address =
acpi_tb_get_root_table_entry(table_entry, table_entry_size); acpi_tb_get_root_table_entry(table_entry, table_entry_size);
/* Skip NULL entries in RSDT/XSDT */
if (!address) {
goto next_table;
}
status = acpi_tb_install_standard_table(address,
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);
}
next_table:
table_entry += table_entry_size; table_entry += table_entry_size;
acpi_gbl_root_table_list.current_table_count++;
} }
/* /*
...@@ -609,22 +401,5 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address) ...@@ -609,22 +401,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);
} }
...@@ -206,8 +206,8 @@ acpi_status ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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);
......
...@@ -117,7 +117,7 @@ static acpi_status acpi_tb_load_namespace(void) ...@@ -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) ...@@ -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) ...@@ -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 @@ static acpi_status acpi_tb_load_namespace(void) ...@@ -206,6 +193,45 @@ static acpi_status acpi_tb_load_namespace(void)
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 @@ static acpi_status acpi_tb_load_namespace(void) ...@@ -222,11 +248,9 @@ static acpi_status acpi_tb_load_namespace(void)
* 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) ...@@ -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) ...@@ -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;
} }
......
...@@ -462,7 +462,7 @@ char *acpi_ut_get_mutex_name(u32 mutex_id) ...@@ -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] = { ...@@ -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) { }
/* 0D - 7F are reserved */
if (notify_value <= ACPI_MAX_SYS_NOTIFY) {
return ("Reserved"); return ("Reserved");
} else if (notify_value <= ACPI_MAX_DEVICE_SPECIFIC_NOTIFY) {
return ("Device Specific");
} else {
return ("Hardware Specific");
} }
/* 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
......
...@@ -55,28 +55,7 @@ ACPI_MODULE_NAME("utglobal") ...@@ -55,28 +55,7 @@ ACPI_MODULE_NAME("utglobal")
* Static global variable initialization. * Static global variable initialization.
* *
******************************************************************************/ ******************************************************************************/
/* Debug output control masks */
u32 acpi_dbg_level = ACPI_DEBUG_DEFAULT;
u32 acpi_dbg_layer = 0;
/* acpi_gbl_FADT is a local copy of the FADT, converted to a common format. */
struct acpi_table_fadt acpi_gbl_FADT;
u32 acpi_gbl_trace_flags;
acpi_name acpi_gbl_trace_method_name;
u8 acpi_gbl_system_awake_and_running;
u32 acpi_current_gpe_count;
/*
* ACPI 5.0 introduces the concept of a "reduced hardware platform", meaning
* that the ACPI hardware is no longer required. A flag in the FADT indicates
* a reduced HW machine, and that flag is duplicated here for convenience.
*/
u8 acpi_gbl_reduced_hardware;
/* Various state name strings */ /* Various state name strings */
const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] = { const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] = {
"\\_S0_", "\\_S0_",
"\\_S1_", "\\_S1_",
...@@ -337,7 +316,6 @@ acpi_status acpi_ut_init_globals(void) ...@@ -337,7 +316,6 @@ acpi_status acpi_ut_init_globals(void)
acpi_gbl_acpi_hardware_present = TRUE; acpi_gbl_acpi_hardware_present = TRUE;
acpi_gbl_last_owner_id_index = 0; acpi_gbl_last_owner_id_index = 0;
acpi_gbl_next_owner_id_offset = 0; acpi_gbl_next_owner_id_offset = 0;
acpi_gbl_trace_method_name = 0;
acpi_gbl_trace_dbg_level = 0; acpi_gbl_trace_dbg_level = 0;
acpi_gbl_trace_dbg_layer = 0; acpi_gbl_trace_dbg_layer = 0;
acpi_gbl_debugger_configuration = DEBUGGER_THREADING; acpi_gbl_debugger_configuration = DEBUGGER_THREADING;
...@@ -377,9 +355,7 @@ acpi_status acpi_ut_init_globals(void) ...@@ -377,9 +355,7 @@ acpi_status acpi_ut_init_globals(void)
acpi_gbl_disable_mem_tracking = FALSE; acpi_gbl_disable_mem_tracking = FALSE;
#endif #endif
#ifdef ACPI_DEBUGGER ACPI_DEBUGGER_EXEC(acpi_gbl_db_terminate_threads = FALSE);
acpi_gbl_db_terminate_threads = FALSE;
#endif
return_ACPI_STATUS(AE_OK); return_ACPI_STATUS(AE_OK);
} }
......
...@@ -353,7 +353,7 @@ void acpi_ut_print_string(char *string, u16 max_length) ...@@ -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 */
......
...@@ -53,6 +53,7 @@ ACPI_MODULE_NAME("utxferror") ...@@ -53,6 +53,7 @@ ACPI_MODULE_NAME("utxferror")
* This module is used for the in-kernel ACPICA as well as the ACPICA * This module is used for the in-kernel ACPICA as well as the ACPICA
* tools/applications. * tools/applications.
*/ */
#ifndef ACPI_NO_ERROR_MESSAGES /* Entire module */
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_error * FUNCTION: acpi_error
...@@ -249,3 +250,4 @@ acpi_bios_warning(const char *module_name, ...@@ -249,3 +250,4 @@ acpi_bios_warning(const char *module_name,
} }
ACPI_EXPORT_SYMBOL(acpi_bios_warning) ACPI_EXPORT_SYMBOL(acpi_bios_warning)
#endif /* ACPI_NO_ERROR_MESSAGES */
...@@ -1770,16 +1770,15 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object) ...@@ -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)
{ {
......
...@@ -55,6 +55,7 @@ ...@@ -55,6 +55,7 @@
#define METHOD_NAME__HID "_HID" #define METHOD_NAME__HID "_HID"
#define METHOD_NAME__INI "_INI" #define METHOD_NAME__INI "_INI"
#define METHOD_NAME__PLD "_PLD" #define METHOD_NAME__PLD "_PLD"
#define METHOD_NAME__PRP "_PRP"
#define METHOD_NAME__PRS "_PRS" #define METHOD_NAME__PRS "_PRS"
#define METHOD_NAME__PRT "_PRT" #define METHOD_NAME__PRT "_PRT"
#define METHOD_NAME__PRW "_PRW" #define METHOD_NAME__PRW "_PRW"
......
...@@ -46,7 +46,7 @@ ...@@ -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 0x20140424
#include <acpi/acconfig.h> #include <acpi/acconfig.h>
#include <acpi/actypes.h> #include <acpi/actypes.h>
...@@ -55,233 +55,469 @@ ...@@ -55,233 +55,469 @@
extern u8 acpi_gbl_permanent_mmap; extern u8 acpi_gbl_permanent_mmap;
/*****************************************************************************
*
* Macros used for ACPICA globals and configuration
*
****************************************************************************/
/* /*
* Globals that are publically available * Ensure that global variables are defined and initialized only once.
*
* The use of these macros allows for a single list of globals (here)
* in order to simplify maintenance of the code.
*/ */
extern u32 acpi_current_gpe_count; #ifdef DEFINE_ACPI_GLOBALS
extern struct acpi_table_fadt acpi_gbl_FADT; #define ACPI_GLOBAL(type,name) \
extern u8 acpi_gbl_system_awake_and_running; extern type name; \
extern u8 acpi_gbl_reduced_hardware; /* ACPI 5.0 */ type name
extern u8 acpi_gbl_osi_data;
/* Runtime configuration of debug print levels */ #define ACPI_INIT_GLOBAL(type,name,value) \
type name=value
extern u32 acpi_dbg_level; #else
extern u32 acpi_dbg_layer; #ifndef ACPI_GLOBAL
#define ACPI_GLOBAL(type,name) \
/* ACPICA runtime options */ extern type name
#endif
extern u8 acpi_gbl_auto_serialize_methods; #ifndef ACPI_INIT_GLOBAL
extern u8 acpi_gbl_copy_dsdt_locally; #define ACPI_INIT_GLOBAL(type,name,value) \
extern u8 acpi_gbl_create_osi_method; extern type name
extern u8 acpi_gbl_disable_auto_repair; #endif
extern u8 acpi_gbl_disable_ssdt_table_load; #endif
extern u8 acpi_gbl_do_not_use_xsdt;
extern u8 acpi_gbl_enable_aml_debug_object;
extern u8 acpi_gbl_enable_interpreter_slack;
extern u32 acpi_gbl_trace_flags;
extern acpi_name acpi_gbl_trace_method_name;
extern u8 acpi_gbl_truncate_io_addresses;
extern u8 acpi_gbl_use32_bit_fadt_addresses;
extern u8 acpi_gbl_use_default_register_widths;
/* /*
* Hardware-reduced prototypes. All interfaces that use these macros will * These macros configure the various ACPICA interfaces. They are
* be configured out of the ACPICA build if the ACPI_REDUCED_HARDWARE flag * useful for generating stub inline functions for features that are
* is set to TRUE. * configured out of the current kernel or ACPICA application.
*/ */
#if (!ACPI_REDUCED_HARDWARE) #ifndef ACPI_EXTERNAL_RETURN_STATUS
#define ACPI_HW_DEPENDENT_RETURN_STATUS(prototype) \ #define ACPI_EXTERNAL_RETURN_STATUS(prototype) \
prototype; prototype;
#endif
#define ACPI_HW_DEPENDENT_RETURN_OK(prototype) \ #ifndef ACPI_EXTERNAL_RETURN_OK
#define ACPI_EXTERNAL_RETURN_OK(prototype) \
prototype; prototype;
#endif
#define ACPI_HW_DEPENDENT_RETURN_VOID(prototype) \ #ifndef ACPI_EXTERNAL_RETURN_VOID
#define ACPI_EXTERNAL_RETURN_VOID(prototype) \
prototype; prototype;
#endif
#else #ifndef ACPI_EXTERNAL_RETURN_UINT32
#define ACPI_HW_DEPENDENT_RETURN_STATUS(prototype) \ #define ACPI_EXTERNAL_RETURN_UINT32(prototype) \
static ACPI_INLINE prototype {return(AE_NOT_CONFIGURED);} prototype;
#endif
#define ACPI_HW_DEPENDENT_RETURN_OK(prototype) \
static ACPI_INLINE prototype {return(AE_OK);}
#define ACPI_HW_DEPENDENT_RETURN_VOID(prototype) \ #ifndef ACPI_EXTERNAL_RETURN_PTR
static ACPI_INLINE prototype {return;} #define ACPI_EXTERNAL_RETURN_PTR(prototype) \
prototype;
#endif
#endif /* !ACPI_REDUCED_HARDWARE */ /*****************************************************************************
*
* Public globals and runtime configuration options
*
****************************************************************************/
/* /*
* Initialization * Enable "slack mode" of the AML interpreter? Default is FALSE, and the
* interpreter strictly follows the ACPI specification. Setting to TRUE
* allows the interpreter to ignore certain errors and/or bad AML constructs.
*
* Currently, these features are enabled by this flag:
*
* 1) Allow "implicit return" of last value in a control method
* 2) Allow access beyond the end of an operation region
* 3) Allow access to uninitialized locals/args (auto-init to integer 0)
* 4) Allow ANY object type to be a source operand for the Store() operator
* 5) Allow unresolved references (invalid target name) in package objects
* 6) Enable warning messages for behavior that is not ACPI spec compliant
*/ */
acpi_status __init ACPI_INIT_GLOBAL(u8, acpi_gbl_enable_interpreter_slack, FALSE);
acpi_initialize_tables(struct acpi_table_desc *initial_storage,
u32 initial_table_count, u8 allow_resize);
acpi_status __init acpi_initialize_subsystem(void);
acpi_status __init acpi_enable_subsystem(u32 flags);
acpi_status __init acpi_initialize_objects(u32 flags); /*
* Automatically serialize all methods that create named objects? Default
acpi_status __init acpi_terminate(void); * is TRUE, meaning that all non_serialized methods are scanned once at
* table load time to determine those that create named objects. Methods
* that create named objects are marked Serialized in order to prevent
* possible run-time problems if they are entered by more than one thread.
*/
ACPI_INIT_GLOBAL(u8, acpi_gbl_auto_serialize_methods, TRUE);
/* /*
* Miscellaneous global interfaces * Create the predefined _OSI method in the namespace? Default is TRUE
* because ACPICA is fully compatible with other ACPI implementations.
* Changing this will revert ACPICA (and machine ASL) to pre-OSI behavior.
*/ */
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable(void)) ACPI_INIT_GLOBAL(u8, acpi_gbl_create_osi_method, TRUE);
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable(void))
#ifdef ACPI_FUTURE_USAGE
acpi_status acpi_subsystem_status(void);
#endif
#ifdef ACPI_FUTURE_USAGE /*
acpi_status acpi_get_system_info(struct acpi_buffer *ret_buffer); * Optionally use default values for the ACPI register widths. Set this to
#endif * TRUE to use the defaults, if an FADT contains incorrect widths/lengths.
*/
ACPI_INIT_GLOBAL(u8, acpi_gbl_use_default_register_widths, TRUE);
acpi_status acpi_get_statistics(struct acpi_statistics *stats); /*
* Optionally enable output from the AML Debug Object.
*/
ACPI_INIT_GLOBAL(u8, acpi_gbl_enable_aml_debug_object, FALSE);
const char *acpi_format_exception(acpi_status exception); /*
* Optionally copy the entire DSDT to local memory (instead of simply
* mapping it.) There are some BIOSs that corrupt or replace the original
* DSDT, creating the need for this option. Default is FALSE, do not copy
* the DSDT.
*/
ACPI_INIT_GLOBAL(u8, acpi_gbl_copy_dsdt_locally, FALSE);
acpi_status acpi_purge_cached_objects(void); /*
* Optionally ignore an XSDT if present and use the RSDT instead.
* Although the ACPI specification requires that an XSDT be used instead
* of the RSDT, the XSDT has been found to be corrupt or ill-formed on
* some machines. Default behavior is to use the XSDT if present.
*/
ACPI_INIT_GLOBAL(u8, acpi_gbl_do_not_use_xsdt, FALSE);
acpi_status acpi_install_interface(acpi_string interface_name); /*
* Optionally use 32-bit FADT addresses if and when there is a conflict
* (address mismatch) between the 32-bit and 64-bit versions of the
* address. Although ACPICA adheres to the ACPI specification which
* requires the use of the corresponding 64-bit address if it is non-zero,
* some machines have been found to have a corrupted non-zero 64-bit
* address. Default is TRUE, favor the 32-bit addresses.
*/
ACPI_INIT_GLOBAL(u8, acpi_gbl_use32_bit_fadt_addresses, TRUE);
acpi_status acpi_remove_interface(acpi_string interface_name); /*
* Optionally truncate I/O addresses to 16 bits. Provides compatibility
* with other ACPI implementations. NOTE: During ACPICA initialization,
* this value is set to TRUE if any Windows OSI strings have been
* requested by the BIOS.
*/
ACPI_INIT_GLOBAL(u8, acpi_gbl_truncate_io_addresses, FALSE);
acpi_status acpi_update_interfaces(u8 action); /*
* Disable runtime checking and repair of values returned by control methods.
* Use only if the repair is causing a problem on a particular machine.
*/
ACPI_INIT_GLOBAL(u8, acpi_gbl_disable_auto_repair, FALSE);
u32 /*
acpi_check_address_range(acpi_adr_space_type space_id, * Optionally do not install any SSDTs from the RSDT/XSDT during initialization.
acpi_physical_address address, * This can be useful for debugging ACPI problems on some machines.
acpi_size length, u8 warn); */
ACPI_INIT_GLOBAL(u8, acpi_gbl_disable_ssdt_table_install, FALSE);
acpi_status /*
acpi_decode_pld_buffer(u8 *in_buffer, * We keep track of the latest version of Windows that has been requested by
acpi_size length, struct acpi_pld_info **return_buffer); * the BIOS. ACPI 5.0.
*/
ACPI_INIT_GLOBAL(u8, acpi_gbl_osi_data, 0);
/* /*
* ACPI table load/unload interfaces * ACPI 5.0 introduces the concept of a "reduced hardware platform", meaning
* that the ACPI hardware is no longer required. A flag in the FADT indicates
* a reduced HW machine, and that flag is duplicated here for convenience.
*/ */
acpi_status acpi_load_table(struct acpi_table_header *table); ACPI_INIT_GLOBAL(u8, acpi_gbl_reduced_hardware, FALSE);
acpi_status acpi_unload_parent_table(acpi_handle object); /*
* This mechanism is used to trace a specified AML method. The method is
* traced each time it is executed.
*/
ACPI_INIT_GLOBAL(u32, acpi_gbl_trace_flags, 0);
ACPI_INIT_GLOBAL(acpi_name, acpi_gbl_trace_method_name, 0);
acpi_status __init acpi_load_tables(void); /*
* Runtime configuration of debug output control masks. We want the debug
* switches statically initialized so they are already set when the debugger
* is entered.
*/
ACPI_INIT_GLOBAL(u32, acpi_dbg_level, ACPI_DEBUG_DEFAULT);
ACPI_INIT_GLOBAL(u32, acpi_dbg_layer, 0);
/* /*
* ACPI table manipulation interfaces * Other miscellaneous globals
*/ */
acpi_status __init acpi_reallocate_root_table(void); ACPI_GLOBAL(struct acpi_table_fadt, acpi_gbl_FADT);
ACPI_GLOBAL(u32, acpi_current_gpe_count);
ACPI_GLOBAL(u8, acpi_gbl_system_awake_and_running);
acpi_status __init acpi_find_root_pointer(acpi_size *rsdp_address); /*****************************************************************************
*
* ACPICA public interface configuration.
*
* Interfaces that are configured out of the ACPICA build are replaced
* by inlined stubs by default.
*
****************************************************************************/
acpi_status acpi_unload_table_id(acpi_owner_id id); /*
* Hardware-reduced prototypes (default: Not hardware reduced).
*
* All ACPICA hardware-related interfaces that use these macros will be
* configured out of the ACPICA build if the ACPI_REDUCED_HARDWARE flag
* is set to TRUE.
*
* Note: This static build option for reduced hardware is intended to
* reduce ACPICA code size if desired or necessary. However, even if this
* option is not specified, the runtime behavior of ACPICA is dependent
* on the actual FADT reduced hardware flag (HW_REDUCED_ACPI). If set,
* the flag will enable similar behavior -- ACPICA will not attempt
* to access any ACPI-relate hardware (SCI, GPEs, Fixed Events, etc.)
*/
#if (!ACPI_REDUCED_HARDWARE)
#define ACPI_HW_DEPENDENT_RETURN_STATUS(prototype) \
ACPI_EXTERNAL_RETURN_STATUS(prototype)
acpi_status #define ACPI_HW_DEPENDENT_RETURN_OK(prototype) \
acpi_get_table_header(acpi_string signature, ACPI_EXTERNAL_RETURN_OK(prototype)
u32 instance, struct acpi_table_header *out_table_header);
acpi_status #define ACPI_HW_DEPENDENT_RETURN_VOID(prototype) \
acpi_get_table_with_size(acpi_string signature, ACPI_EXTERNAL_RETURN_VOID(prototype)
u32 instance, struct acpi_table_header **out_table,
acpi_size *tbl_size);
acpi_status #else
acpi_get_table(acpi_string signature, #define ACPI_HW_DEPENDENT_RETURN_STATUS(prototype) \
u32 instance, struct acpi_table_header **out_table); static ACPI_INLINE prototype {return(AE_NOT_CONFIGURED);}
acpi_status #define ACPI_HW_DEPENDENT_RETURN_OK(prototype) \
acpi_get_table_by_index(u32 table_index, struct acpi_table_header **out_table); static ACPI_INLINE prototype {return(AE_OK);}
acpi_status #define ACPI_HW_DEPENDENT_RETURN_VOID(prototype) \
acpi_install_table_handler(acpi_table_handler handler, void *context); static ACPI_INLINE prototype {return;}
acpi_status acpi_remove_table_handler(acpi_table_handler handler); #endif /* !ACPI_REDUCED_HARDWARE */
/* /*
* Namespace and name interfaces * Error message prototypes (default: error messages enabled).
*
* All interfaces related to error and warning messages
* will be configured out of the ACPICA build if the
* ACPI_NO_ERROR_MESSAGE flag is defined.
*/ */
acpi_status #ifndef ACPI_NO_ERROR_MESSAGES
acpi_walk_namespace(acpi_object_type type, #define ACPI_MSG_DEPENDENT_RETURN_VOID(prototype) \
acpi_handle start_object, prototype;
u32 max_depth,
acpi_walk_callback descending_callback,
acpi_walk_callback ascending_callback,
void *context, void **return_value);
acpi_status #else
acpi_get_devices(const char *HID, #define ACPI_MSG_DEPENDENT_RETURN_VOID(prototype) \
acpi_walk_callback user_function, static ACPI_INLINE prototype {return;}
void *context, void **return_value);
acpi_status #endif /* ACPI_NO_ERROR_MESSAGES */
acpi_get_name(acpi_handle object,
u32 name_type, struct acpi_buffer *ret_path_ptr);
acpi_status /*
acpi_get_handle(acpi_handle parent, * Debugging output prototypes (default: no debug output).
acpi_string pathname, acpi_handle * ret_handle); *
* All interfaces related to debug output messages
* will be configured out of the ACPICA build unless the
* ACPI_DEBUG_OUTPUT flag is defined.
*/
#ifdef ACPI_DEBUG_OUTPUT
#define ACPI_DBG_DEPENDENT_RETURN_VOID(prototype) \
prototype;
acpi_status #else
acpi_attach_data(acpi_handle object, acpi_object_handler handler, void *data); #define ACPI_DBG_DEPENDENT_RETURN_VOID(prototype) \
static ACPI_INLINE prototype {return;}
acpi_status acpi_detach_data(acpi_handle object, acpi_object_handler handler); #endif /* ACPI_DEBUG_OUTPUT */
acpi_status /*****************************************************************************
acpi_get_data_full(acpi_handle object, acpi_object_handler handler, void **data, *
void (*callback)(void *)); * ACPICA public interface prototypes
*
****************************************************************************/
acpi_status /*
acpi_get_data(acpi_handle object, acpi_object_handler handler, void **data); * Initialization
*/
ACPI_EXTERNAL_RETURN_STATUS(acpi_status __init
acpi_initialize_tables(struct acpi_table_desc
*initial_storage,
u32 initial_table_count,
u8 allow_resize))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status __init acpi_initialize_subsystem(void))
acpi_status ACPI_EXTERNAL_RETURN_STATUS(acpi_status __init acpi_enable_subsystem(u32 flags))
acpi_debug_trace(char *name, u32 debug_level, u32 debug_layer, u32 flags);
ACPI_EXTERNAL_RETURN_STATUS(acpi_status __init
acpi_initialize_objects(u32 flags))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status __init acpi_terminate(void))
/* /*
* Object manipulation and enumeration * Miscellaneous global interfaces
*/ */
acpi_status ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable(void))
acpi_evaluate_object(acpi_handle object, ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable(void))
acpi_string pathname, #ifdef ACPI_FUTURE_USAGE
struct acpi_object_list *parameter_objects, ACPI_EXTERNAL_RETURN_STATUS(acpi_status acpi_subsystem_status(void))
struct acpi_buffer *return_object_buffer); #endif
acpi_status #ifdef ACPI_FUTURE_USAGE
acpi_evaluate_object_typed(acpi_handle object, ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_string pathname, acpi_get_system_info(struct acpi_buffer
struct acpi_object_list *external_params, *ret_buffer))
struct acpi_buffer *return_buffer, #endif
acpi_object_type return_type); ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_get_statistics(struct acpi_statistics *stats))
ACPI_EXTERNAL_RETURN_PTR(const char
*acpi_format_exception(acpi_status exception))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status acpi_purge_cached_objects(void))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_install_interface(acpi_string interface_name))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_remove_interface(acpi_string interface_name))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status acpi_update_interfaces(u8 action))
ACPI_EXTERNAL_RETURN_UINT32(u32
acpi_check_address_range(acpi_adr_space_type
space_id,
acpi_physical_address
address, acpi_size length,
u8 warn))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_decode_pld_buffer(u8 *in_buffer,
acpi_size length,
struct acpi_pld_info
**return_buffer))
acpi_status /*
acpi_get_object_info(acpi_handle object, * ACPI table load/unload interfaces
struct acpi_device_info **return_buffer); */
ACPI_EXTERNAL_RETURN_STATUS(acpi_status __init
acpi_install_table(acpi_physical_address address,
u8 physical))
acpi_status acpi_install_method(u8 *buffer); ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_load_table(struct acpi_table_header *table))
acpi_status ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_get_next_object(acpi_object_type type, acpi_unload_parent_table(acpi_handle object))
acpi_handle parent, ACPI_EXTERNAL_RETURN_STATUS(acpi_status __init acpi_load_tables(void))
acpi_handle child, acpi_handle * out_handle);
acpi_status acpi_get_type(acpi_handle object, acpi_object_type * out_type); /*
* ACPI table manipulation interfaces
*/
ACPI_EXTERNAL_RETURN_STATUS(acpi_status __init acpi_reallocate_root_table(void))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status __init
acpi_find_root_pointer(acpi_size * rsdp_address))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_get_table_header(acpi_string signature,
u32 instance,
struct acpi_table_header
*out_table_header))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_get_table(acpi_string signature, u32 instance,
struct acpi_table_header
**out_table))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_get_table_by_index(u32 table_index,
struct acpi_table_header
**out_table))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_install_table_handler(acpi_table_handler
handler, void *context))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_remove_table_handler(acpi_table_handler
handler))
acpi_status acpi_get_id(acpi_handle object, acpi_owner_id * out_type); /*
* Namespace and name interfaces
*/
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_walk_namespace(acpi_object_type type,
acpi_handle start_object,
u32 max_depth,
acpi_walk_callback
descending_callback,
acpi_walk_callback
ascending_callback,
void *context,
void **return_value))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_get_devices(const char *HID,
acpi_walk_callback user_function,
void *context,
void **return_value))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_get_name(acpi_handle object, u32 name_type,
struct acpi_buffer *ret_path_ptr))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_get_handle(acpi_handle parent,
acpi_string pathname,
acpi_handle * ret_handle))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_attach_data(acpi_handle object,
acpi_object_handler handler,
void *data))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_detach_data(acpi_handle object,
acpi_object_handler handler))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_get_data(acpi_handle object,
acpi_object_handler handler,
void **data))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_debug_trace(char *name, u32 debug_level,
u32 debug_layer, u32 flags))
acpi_status acpi_get_parent(acpi_handle object, acpi_handle * out_handle); /*
* Object manipulation and enumeration
*/
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_evaluate_object(acpi_handle object,
acpi_string pathname,
struct acpi_object_list
*parameter_objects,
struct acpi_buffer
*return_object_buffer))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_evaluate_object_typed(acpi_handle object,
acpi_string pathname,
struct acpi_object_list
*external_params,
struct acpi_buffer
*return_buffer,
acpi_object_type
return_type))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_get_object_info(acpi_handle object,
struct acpi_device_info
**return_buffer))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status acpi_install_method(u8 *buffer))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_get_next_object(acpi_object_type type,
acpi_handle parent,
acpi_handle child,
acpi_handle * out_handle))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_get_type(acpi_handle object,
acpi_object_type * out_type))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_get_parent(acpi_handle object,
acpi_handle * out_handle))
/* /*
* Handler interfaces * Handler interfaces
*/ */
acpi_status ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_install_initialization_handler(acpi_init_handler handler, u32 function); acpi_install_initialization_handler
(acpi_init_handler handler, u32 function))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
acpi_install_sci_handler(acpi_sci_handler acpi_install_sci_handler(acpi_sci_handler
address, address,
void *context)) void *context))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
acpi_remove_sci_handler(acpi_sci_handler acpi_remove_sci_handler(acpi_sci_handler
address)) address))
...@@ -313,30 +549,42 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status ...@@ -313,30 +549,42 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
u32 gpe_number, u32 gpe_number,
acpi_gpe_handler acpi_gpe_handler
address)) address))
acpi_status acpi_install_notify_handler(acpi_handle device, u32 handler_type, ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_notify_handler handler, acpi_install_notify_handler(acpi_handle device,
void *context); u32 handler_type,
acpi_notify_handler
acpi_status handler,
acpi_remove_notify_handler(acpi_handle device, void *context))
u32 handler_type, acpi_notify_handler handler); ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_remove_notify_handler(acpi_handle device,
acpi_status u32 handler_type,
acpi_install_address_space_handler(acpi_handle device, acpi_notify_handler
acpi_adr_space_type space_id, handler))
acpi_adr_space_handler handler, ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_adr_space_setup setup, void *context); acpi_install_address_space_handler(acpi_handle
device,
acpi_status acpi_adr_space_type
acpi_remove_address_space_handler(acpi_handle device, space_id,
acpi_adr_space_type space_id, acpi_adr_space_handler
acpi_adr_space_handler handler); handler,
acpi_adr_space_setup
setup,
void *context))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_remove_address_space_handler(acpi_handle
device,
acpi_adr_space_type
space_id,
acpi_adr_space_handler
handler))
#ifdef ACPI_FUTURE_USAGE #ifdef ACPI_FUTURE_USAGE
acpi_status acpi_install_exception_handler(acpi_exception_handler handler); ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_install_exception_handler
(acpi_exception_handler handler))
#endif #endif
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_status acpi_install_interface_handler(acpi_interface_handler handler); acpi_install_interface_handler
(acpi_interface_handler handler))
/* /*
* Global Lock interfaces * Global Lock interfaces
...@@ -351,10 +599,14 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status ...@@ -351,10 +599,14 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
/* /*
* Interfaces to AML mutex objects * Interfaces to AML mutex objects
*/ */
acpi_status ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_acquire_mutex(acpi_handle handle, acpi_string pathname, u16 timeout); acpi_acquire_mutex(acpi_handle handle,
acpi_string pathname,
u16 timeout))
acpi_status acpi_release_mutex(acpi_handle handle, acpi_string pathname); ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_release_mutex(acpi_handle handle,
acpi_string pathname))
/* /*
* Fixed Event interfaces * Fixed Event interfaces
...@@ -434,57 +686,69 @@ typedef ...@@ -434,57 +686,69 @@ typedef
acpi_status(*acpi_walk_resource_callback) (struct acpi_resource * resource, acpi_status(*acpi_walk_resource_callback) (struct acpi_resource * resource,
void *context); void *context);
acpi_status ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_get_vendor_resource(acpi_handle device, acpi_get_vendor_resource(acpi_handle device,
char *name, char *name,
struct acpi_vendor_uuid *uuid, struct acpi_vendor_uuid
struct acpi_buffer *ret_buffer); *uuid,
struct acpi_buffer
acpi_status *ret_buffer))
acpi_get_current_resources(acpi_handle device, struct acpi_buffer *ret_buffer); ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_get_current_resources(acpi_handle device,
struct acpi_buffer
*ret_buffer))
#ifdef ACPI_FUTURE_USAGE #ifdef ACPI_FUTURE_USAGE
acpi_status ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_get_possible_resources(acpi_handle device, struct acpi_buffer *ret_buffer); acpi_get_possible_resources(acpi_handle device,
struct acpi_buffer
*ret_buffer))
#endif #endif
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_status acpi_get_event_resources(acpi_handle device_handle,
acpi_get_event_resources(acpi_handle device_handle, struct acpi_buffer
struct acpi_buffer *ret_buffer); *ret_buffer))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_status acpi_walk_resource_buffer(struct acpi_buffer
acpi_walk_resource_buffer(struct acpi_buffer *buffer, *buffer,
acpi_walk_resource_callback user_function, acpi_walk_resource_callback
void *context); user_function,
void *context))
acpi_status ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_walk_resources(acpi_handle device, acpi_walk_resources(acpi_handle device, char *name,
char *name, acpi_walk_resource_callback
acpi_walk_resource_callback user_function, void *context); user_function, void *context))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_status acpi_set_current_resources(acpi_handle device,
acpi_set_current_resources(acpi_handle device, struct acpi_buffer *in_buffer); struct acpi_buffer
*in_buffer))
acpi_status ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_get_irq_routing_table(acpi_handle device, struct acpi_buffer *ret_buffer); acpi_get_irq_routing_table(acpi_handle device,
struct acpi_buffer
acpi_status *ret_buffer))
acpi_resource_to_address64(struct acpi_resource *resource, ACPI_EXTERNAL_RETURN_STATUS(acpi_status
struct acpi_resource_address64 *out); acpi_resource_to_address64(struct acpi_resource
*resource,
acpi_status struct
acpi_buffer_to_resource(u8 *aml_buffer, acpi_resource_address64
u16 aml_buffer_length, *out))
struct acpi_resource **resource_ptr); ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_buffer_to_resource(u8 *aml_buffer,
u16 aml_buffer_length,
struct acpi_resource
**resource_ptr))
/* /*
* Hardware (ACPI device) interfaces * Hardware (ACPI device) interfaces
*/ */
acpi_status acpi_reset(void); ACPI_EXTERNAL_RETURN_STATUS(acpi_status acpi_reset(void))
acpi_status acpi_read(u64 *value, struct acpi_generic_address *reg); ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_read(u64 *value,
struct acpi_generic_address *reg))
acpi_status acpi_write(u64 value, struct acpi_generic_address *reg); ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_write(u64 value,
struct acpi_generic_address *reg))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
acpi_read_bit_register(u32 register_id, acpi_read_bit_register(u32 register_id,
...@@ -497,18 +761,20 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status ...@@ -497,18 +761,20 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
/* /*
* Sleep/Wake interfaces * Sleep/Wake interfaces
*/ */
acpi_status ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_get_sleep_type_data(u8 sleep_state, u8 *slp_typ_a, u8 *slp_typ_b); acpi_get_sleep_type_data(u8 sleep_state,
u8 *slp_typ_a,
acpi_status acpi_enter_sleep_state_prep(u8 sleep_state); u8 *slp_typ_b))
acpi_status acpi_enter_sleep_state(u8 sleep_state); ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_enter_sleep_state_prep(u8 sleep_state))
ACPI_EXTERNAL_RETURN_STATUS(acpi_status acpi_enter_sleep_state(u8 sleep_state))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enter_sleep_state_s4bios(void)) ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enter_sleep_state_s4bios(void))
acpi_status acpi_leave_sleep_state_prep(u8 sleep_state); ACPI_EXTERNAL_RETURN_STATUS(acpi_status
acpi_leave_sleep_state_prep(u8 sleep_state))
acpi_status acpi_leave_sleep_state(u8 sleep_state); ACPI_EXTERNAL_RETURN_STATUS(acpi_status acpi_leave_sleep_state(u8 sleep_state))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
acpi_set_firmware_waking_vector(u32 acpi_set_firmware_waking_vector(u32
...@@ -535,53 +801,72 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status ...@@ -535,53 +801,72 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
/* /*
* Error/Warning output * Error/Warning output
*/ */
ACPI_PRINTF_LIKE(3) ACPI_MSG_DEPENDENT_RETURN_VOID(ACPI_PRINTF_LIKE(3)
void ACPI_INTERNAL_VAR_XFACE void ACPI_INTERNAL_VAR_XFACE
acpi_error(const char *module_name, u32 line_number, const char *format, ...); acpi_error(const char *module_name,
u32 line_number,
ACPI_PRINTF_LIKE(4) const char *format, ...))
void ACPI_INTERNAL_VAR_XFACE ACPI_MSG_DEPENDENT_RETURN_VOID(ACPI_PRINTF_LIKE(4)
acpi_exception(const char *module_name, void ACPI_INTERNAL_VAR_XFACE
u32 line_number, acpi_status status, const char *format, ...); acpi_exception(const char *module_name,
u32 line_number,
ACPI_PRINTF_LIKE(3) acpi_status status,
void ACPI_INTERNAL_VAR_XFACE const char *format, ...))
acpi_warning(const char *module_name, u32 line_number, const char *format, ...); ACPI_MSG_DEPENDENT_RETURN_VOID(ACPI_PRINTF_LIKE(3)
void ACPI_INTERNAL_VAR_XFACE
ACPI_PRINTF_LIKE(3) acpi_warning(const char *module_name,
void ACPI_INTERNAL_VAR_XFACE u32 line_number,
acpi_info(const char *module_name, u32 line_number, const char *format, ...); const char *format, ...))
ACPI_MSG_DEPENDENT_RETURN_VOID(ACPI_PRINTF_LIKE(3)
ACPI_PRINTF_LIKE(3) void ACPI_INTERNAL_VAR_XFACE
void ACPI_INTERNAL_VAR_XFACE acpi_info(const char *module_name,
acpi_bios_error(const char *module_name, u32 line_number,
u32 line_number, const char *format, ...); const char *format, ...))
ACPI_MSG_DEPENDENT_RETURN_VOID(ACPI_PRINTF_LIKE(3)
ACPI_PRINTF_LIKE(3) void ACPI_INTERNAL_VAR_XFACE
void ACPI_INTERNAL_VAR_XFACE acpi_bios_error(const char *module_name,
acpi_bios_warning(const char *module_name, u32 line_number,
u32 line_number, const char *format, ...); const char *format, ...))
ACPI_MSG_DEPENDENT_RETURN_VOID(ACPI_PRINTF_LIKE(3)
void ACPI_INTERNAL_VAR_XFACE
acpi_bios_warning(const char *module_name,
u32 line_number,
const char *format, ...))
/* /*
* Debug output * Debug output
*/ */
#ifdef ACPI_DEBUG_OUTPUT ACPI_DBG_DEPENDENT_RETURN_VOID(ACPI_PRINTF_LIKE(6)
void ACPI_INTERNAL_VAR_XFACE
acpi_debug_print(u32 requested_debug_level,
u32 line_number,
const char *function_name,
const char *module_name,
u32 component_id,
const char *format, ...))
ACPI_DBG_DEPENDENT_RETURN_VOID(ACPI_PRINTF_LIKE(6)
void ACPI_INTERNAL_VAR_XFACE
acpi_debug_print_raw(u32 requested_debug_level,
u32 line_number,
const char *function_name,
const char *module_name,
u32 component_id,
const char *format, ...))
ACPI_PRINTF_LIKE(6) /*
void ACPI_INTERNAL_VAR_XFACE * Divergences
acpi_debug_print(u32 requested_debug_level, */
u32 line_number, acpi_status acpi_get_id(acpi_handle object, acpi_owner_id * out_type);
const char *function_name,
const char *module_name, acpi_status acpi_unload_table_id(acpi_owner_id id);
u32 component_id, const char *format, ...);
acpi_status
ACPI_PRINTF_LIKE(6) acpi_get_table_with_size(acpi_string signature,
void ACPI_INTERNAL_VAR_XFACE u32 instance, struct acpi_table_header **out_table,
acpi_debug_print_raw(u32 requested_debug_level, acpi_size *tbl_size);
u32 line_number,
const char *function_name, acpi_status
const char *module_name, acpi_get_data_full(acpi_handle object, acpi_object_handler handler, void **data,
u32 component_id, const char *format, ...); void (*callback)(void *));
#endif
#endif /* __ACXFACE_H__ */ #endif /* __ACXFACE_H__ */
...@@ -367,12 +367,11 @@ struct acpi_table_desc { ...@@ -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
......
...@@ -675,7 +675,7 @@ enum acpi_madt_type { ...@@ -675,7 +675,7 @@ enum acpi_madt_type {
}; };
/* /*
* MADT Sub-tables, correspond to Type in struct acpi_subtable_header * MADT Subtables, correspond to Type in struct acpi_subtable_header
*/ */
/* 0: Processor Local APIC */ /* 0: Processor Local APIC */
...@@ -918,7 +918,7 @@ enum acpi_srat_type { ...@@ -918,7 +918,7 @@ enum acpi_srat_type {
}; };
/* /*
* SRAT Sub-tables, correspond to Type in struct acpi_subtable_header * SRAT Subtables, correspond to Type in struct acpi_subtable_header
*/ */
/* 0: Processor Local APIC/SAPIC Affinity */ /* 0: Processor Local APIC/SAPIC Affinity */
......
...@@ -70,6 +70,7 @@ ...@@ -70,6 +70,7 @@
#define ACPI_SIG_HPET "HPET" /* High Precision Event Timer table */ #define ACPI_SIG_HPET "HPET" /* High Precision Event Timer table */
#define ACPI_SIG_IBFT "IBFT" /* iSCSI Boot Firmware Table */ #define ACPI_SIG_IBFT "IBFT" /* iSCSI Boot Firmware Table */
#define ACPI_SIG_IVRS "IVRS" /* I/O Virtualization Reporting Structure */ #define ACPI_SIG_IVRS "IVRS" /* I/O Virtualization Reporting Structure */
#define ACPI_SIG_LPIT "LPIT" /* Low Power Idle Table */
#define ACPI_SIG_MCFG "MCFG" /* PCI Memory Mapped Configuration table */ #define ACPI_SIG_MCFG "MCFG" /* PCI Memory Mapped Configuration table */
#define ACPI_SIG_MCHI "MCHI" /* Management Controller Host Interface table */ #define ACPI_SIG_MCHI "MCHI" /* Management Controller Host Interface table */
#define ACPI_SIG_MTMR "MTMR" /* MID Timer table */ #define ACPI_SIG_MTMR "MTMR" /* MID Timer table */
...@@ -456,7 +457,7 @@ struct acpi_dmar_pci_path { ...@@ -456,7 +457,7 @@ struct acpi_dmar_pci_path {
}; };
/* /*
* DMAR Sub-tables, correspond to Type in struct acpi_dmar_header * DMAR Subtables, correspond to Type in struct acpi_dmar_header
*/ */
/* 0: Hardware Unit Definition */ /* 0: Hardware Unit Definition */
...@@ -820,7 +821,71 @@ struct acpi_ivrs_memory { ...@@ -820,7 +821,71 @@ struct acpi_ivrs_memory {
/******************************************************************************* /*******************************************************************************
* *
* MCFG - PCI Memory Mapped Configuration table and sub-table * LPIT - Low Power Idle Table
*
* Conforms to "ACPI Low Power Idle Table (LPIT) and _LPD Proposal (DRAFT)"
*
******************************************************************************/
struct acpi_table_lpit {
struct acpi_table_header header; /* Common ACPI table header */
};
/* LPIT subtable header */
struct acpi_lpit_header {
u32 type; /* Subtable type */
u32 length; /* Subtable length */
u16 unique_id;
u16 reserved;
u32 flags;
};
/* Values for subtable Type above */
enum acpi_lpit_type {
ACPI_LPIT_TYPE_NATIVE_CSTATE = 0x00,
ACPI_LPIT_TYPE_SIMPLE_IO = 0x01
};
/* Masks for Flags field above */
#define ACPI_LPIT_STATE_DISABLED (1)
#define ACPI_LPIT_NO_COUNTER (1<<1)
/*
* LPIT subtables, correspond to Type in struct acpi_lpit_header
*/
/* 0x00: Native C-state instruction based LPI structure */
struct acpi_lpit_native {
struct acpi_lpit_header header;
struct acpi_generic_address entry_trigger;
u32 residency;
u32 latency;
struct acpi_generic_address residency_counter;
u64 counter_frequency;
};
/* 0x01: Simple I/O based LPI structure */
struct acpi_lpit_io {
struct acpi_lpit_header header;
struct acpi_generic_address entry_trigger;
u32 trigger_action;
u64 trigger_value;
u64 trigger_mask;
struct acpi_generic_address minimum_idle_state;
u32 residency;
u32 latency;
struct acpi_generic_address residency_counter;
u64 counter_frequency;
};
/*******************************************************************************
*
* MCFG - PCI Memory Mapped Configuration table and subtable
* Version 1 * Version 1
* *
* Conforms to "PCI Firmware Specification", Revision 3.0, June 20, 2005 * Conforms to "PCI Firmware Specification", Revision 3.0, June 20, 2005
...@@ -923,7 +988,7 @@ enum acpi_slic_type { ...@@ -923,7 +988,7 @@ enum acpi_slic_type {
}; };
/* /*
* SLIC Sub-tables, correspond to Type in struct acpi_slic_header * SLIC Subtables, correspond to Type in struct acpi_slic_header
*/ */
/* 0: Public Key Structure */ /* 0: Public Key Structure */
......
...@@ -329,6 +329,15 @@ typedef u32 acpi_physical_address; ...@@ -329,6 +329,15 @@ typedef u32 acpi_physical_address;
* *
******************************************************************************/ ******************************************************************************/
#ifdef ACPI_NO_MEM_ALLOCATIONS
#define ACPI_ALLOCATE(a) NULL
#define ACPI_ALLOCATE_ZEROED(a) NULL
#define ACPI_FREE(a)
#define ACPI_MEM_TRACKING(a)
#else /* ACPI_NO_MEM_ALLOCATIONS */
#ifdef ACPI_DBG_TRACK_ALLOCATIONS #ifdef ACPI_DBG_TRACK_ALLOCATIONS
/* /*
* Memory allocation tracking (used by acpi_exec to detect memory leaks) * Memory allocation tracking (used by acpi_exec to detect memory leaks)
...@@ -350,6 +359,8 @@ typedef u32 acpi_physical_address; ...@@ -350,6 +359,8 @@ typedef u32 acpi_physical_address;
#endif /* ACPI_DBG_TRACK_ALLOCATIONS */ #endif /* ACPI_DBG_TRACK_ALLOCATIONS */
#endif /* ACPI_NO_MEM_ALLOCATIONS */
/****************************************************************************** /******************************************************************************
* *
* ACPI Specification constants (Do not change unless the specification changes) * ACPI Specification constants (Do not change unless the specification changes)
...@@ -928,9 +939,19 @@ struct acpi_object_list { ...@@ -928,9 +939,19 @@ struct acpi_object_list {
* Miscellaneous common Data Structures used by the interfaces * Miscellaneous common Data Structures used by the interfaces
*/ */
#define ACPI_NO_BUFFER 0 #define ACPI_NO_BUFFER 0
#ifdef ACPI_NO_MEM_ALLOCATIONS
#define ACPI_ALLOCATE_BUFFER (acpi_size) (0)
#define ACPI_ALLOCATE_LOCAL_BUFFER (acpi_size) (0)
#else /* ACPI_NO_MEM_ALLOCATIONS */
#define ACPI_ALLOCATE_BUFFER (acpi_size) (-1) /* Let ACPICA allocate buffer */ #define ACPI_ALLOCATE_BUFFER (acpi_size) (-1) /* Let ACPICA allocate buffer */
#define ACPI_ALLOCATE_LOCAL_BUFFER (acpi_size) (-2) /* For internal use only (enables tracking) */ #define ACPI_ALLOCATE_LOCAL_BUFFER (acpi_size) (-2) /* For internal use only (enables tracking) */
#endif /* ACPI_NO_MEM_ALLOCATIONS */
struct acpi_buffer { struct acpi_buffer {
acpi_size length; /* Length in bytes of the buffer */ acpi_size length; /* Length in bytes of the buffer */
void *pointer; /* pointer to buffer */ void *pointer; /* pointer to buffer */
......
...@@ -64,4 +64,15 @@ ...@@ -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__ */
...@@ -73,6 +73,37 @@ ...@@ -73,6 +73,37 @@
#endif #endif
#include <asm/acpi.h> #include <asm/acpi.h>
#ifndef CONFIG_ACPI
/* External globals for __KERNEL__, stubs is needed */
#define ACPI_GLOBAL(t,a)
#define ACPI_INIT_GLOBAL(t,a,b)
/* Generating stubs for configurable ACPICA macros */
#define ACPI_NO_MEM_ALLOCATIONS
/* Generating stubs for configurable ACPICA functions */
#define ACPI_NO_ERROR_MESSAGES
#undef ACPI_DEBUG_OUTPUT
/* External interface for __KERNEL__, stub is needed */
#define ACPI_EXTERNAL_RETURN_STATUS(prototype) \
static ACPI_INLINE prototype {return(AE_NOT_CONFIGURED);}
#define ACPI_EXTERNAL_RETURN_OK(prototype) \
static ACPI_INLINE prototype {return(AE_OK);}
#define ACPI_EXTERNAL_RETURN_VOID(prototype) \
static ACPI_INLINE prototype {return;}
#define ACPI_EXTERNAL_RETURN_UINT32(prototype) \
static ACPI_INLINE prototype {return(0);}
#define ACPI_EXTERNAL_RETURN_PTR(prototype) \
static ACPI_INLINE prototype {return(NULL);}
#endif /* CONFIG_ACPI */
/* Host-dependent types and defines for in-kernel ACPICA */ /* Host-dependent types and defines for in-kernel ACPICA */
#define ACPI_MACHINE_WIDTH BITS_PER_LONG #define ACPI_MACHINE_WIDTH BITS_PER_LONG
...@@ -91,7 +122,7 @@ ...@@ -91,7 +122,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 +137,8 @@ ...@@ -106,7 +137,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
......
...@@ -68,7 +68,8 @@ WARNINGS += $(call cc-supports,-Wstrict-prototypes) ...@@ -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 ...@@ -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))
......
/******************************************************************************
*
* 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);
}
/******************************************************************************
*
* 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);
}
.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/ ...@@ -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.
/******************************************************************************
*
* Module Name: oslinuxtbl - Linux OSL for obtaining ACPI tables
*
*****************************************************************************/
/*
* 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"
#define _COMPONENT ACPI_OS_SERVICES
ACPI_MODULE_NAME("oslinuxtbl")
#ifndef PATH_MAX
#define PATH_MAX 256
#endif
/* List of information about obtained ACPI tables */
typedef struct osl_table_info {
struct osl_table_info *next;
u32 instance;
char signature[ACPI_NAME_SIZE];
} osl_table_info;
/* Local prototypes */
static acpi_status osl_table_initialize(void);
static acpi_status
osl_table_name_from_file(char *filename, char *signature, u32 *instance);
static acpi_status osl_add_table_to_list(char *signature, u32 instance);
static acpi_status
osl_read_table_from_file(char *filename,
acpi_size file_offset,
char *signature, struct acpi_table_header **table);
static acpi_status
osl_map_table(acpi_size address,
char *signature, struct acpi_table_header **table);
static void osl_unmap_table(struct acpi_table_header *table);
static acpi_physical_address osl_find_rsdp_via_efi(void);
static acpi_status osl_load_rsdp(void);
static acpi_status osl_list_customized_tables(char *directory);
static acpi_status
osl_get_customized_table(char *pathname,
char *signature,
u32 instance,
struct acpi_table_header **table,
acpi_physical_address * address);
static acpi_status osl_list_bios_tables(void);
static acpi_status
osl_get_bios_table(char *signature,
u32 instance,
struct acpi_table_header **table,
acpi_physical_address * address);
static acpi_status osl_get_last_status(acpi_status default_status);
/* File locations */
#define DYNAMIC_TABLE_DIR "/sys/firmware/acpi/tables/dynamic"
#define STATIC_TABLE_DIR "/sys/firmware/acpi/tables"
#define EFI_SYSTAB "/sys/firmware/efi/systab"
/* Should we get dynamically loaded SSDTs from DYNAMIC_TABLE_DIR? */
u8 gbl_dump_dynamic_tables = TRUE;
/* Initialization flags */
u8 gbl_table_list_initialized = FALSE;
/* Local copies of main ACPI tables */
struct acpi_table_rsdp gbl_rsdp;
struct acpi_table_fadt *gbl_fadt = NULL;
struct acpi_table_rsdt *gbl_rsdt = NULL;
struct acpi_table_xsdt *gbl_xsdt = NULL;
/* Table addresses */
acpi_physical_address gbl_fadt_address = 0;
acpi_physical_address gbl_rsdp_address = 0;
/* Revision of RSD PTR */
u8 gbl_revision = 0;
struct osl_table_info *gbl_table_list_head = NULL;
u32 gbl_table_count = 0;
/******************************************************************************
*
* FUNCTION: osl_get_last_status
*
* PARAMETERS: default_status - Default error status to return
*
* RETURN: Status; Converted from errno.
*
* DESCRIPTION: Get last errno and conver it to acpi_status.
*
*****************************************************************************/
static acpi_status osl_get_last_status(acpi_status default_status)
{
switch (errno) {
case EACCES:
case EPERM:
return (AE_ACCESS);
case ENOENT:
return (AE_NOT_FOUND);
case ENOMEM:
return (AE_NO_MEMORY);
default:
return (default_status);
}
}
/******************************************************************************
*
* FUNCTION: acpi_os_get_table_by_address
*
* PARAMETERS: address - Physical address of the ACPI table
* table - Where a pointer to the table is returned
*
* RETURN: Status; Table buffer is returned if AE_OK.
* AE_NOT_FOUND: A valid table was not found at the address
*
* DESCRIPTION: Get an ACPI table via a physical memory address.
*
*****************************************************************************/
acpi_status
acpi_os_get_table_by_address(acpi_physical_address address,
struct acpi_table_header ** table)
{
u32 table_length;
struct acpi_table_header *mapped_table;
struct acpi_table_header *local_table = NULL;
acpi_status status = AE_OK;
/* Get main ACPI tables from memory on first invocation of this function */
status = osl_table_initialize();
if (ACPI_FAILURE(status)) {
return (status);
}
/* Map the table and validate it */
status = osl_map_table(address, NULL, &mapped_table);
if (ACPI_FAILURE(status)) {
return (status);
}
/* Copy table to local buffer and return it */
table_length = ap_get_table_length(mapped_table);
if (table_length == 0) {
status = AE_BAD_HEADER;
goto exit;
}
local_table = calloc(1, table_length);
if (!local_table) {
status = AE_NO_MEMORY;
goto exit;
}
ACPI_MEMCPY(local_table, mapped_table, table_length);
exit:
osl_unmap_table(mapped_table);
*table = local_table;
return (status);
}
/******************************************************************************
*
* FUNCTION: acpi_os_get_table_by_name
*
* PARAMETERS: signature - ACPI Signature for desired table. Must be
* a null terminated 4-character string.
* instance - Multiple table support for SSDT/UEFI (0...n)
* Must be 0 for other tables.
* table - Where a pointer to the table is returned
* address - Where the table physical address is returned
*
* RETURN: Status; Table buffer and physical address returned if AE_OK.
* AE_LIMIT: Instance is beyond valid limit
* AE_NOT_FOUND: A table with the signature was not found
*
* NOTE: Assumes the input signature is uppercase.
*
*****************************************************************************/
acpi_status
acpi_os_get_table_by_name(char *signature,
u32 instance,
struct acpi_table_header ** table,
acpi_physical_address * address)
{
acpi_status status;
/* Get main ACPI tables from memory on first invocation of this function */
status = osl_table_initialize();
if (ACPI_FAILURE(status)) {
return (status);
}
/* Not a main ACPI table, attempt to extract it from the RSDT/XSDT */
if (!gbl_dump_customized_tables) {
/* Attempt to get the table from the memory */
status =
osl_get_bios_table(signature, instance, table, address);
} else {
/* Attempt to get the table from the static directory */
status = osl_get_customized_table(STATIC_TABLE_DIR, signature,
instance, table, address);
}
if (ACPI_FAILURE(status) && status == AE_LIMIT) {
if (gbl_dump_dynamic_tables) {
/* Attempt to get a dynamic table */
status =
osl_get_customized_table(DYNAMIC_TABLE_DIR,
signature, instance, table,
address);
}
}
return (status);
}
/******************************************************************************
*
* FUNCTION: osl_add_table_to_list
*
* PARAMETERS: signature - Table signature
* instance - Table instance
*
* RETURN: Status; Successfully added if AE_OK.
* AE_NO_MEMORY: Memory allocation error
*
* DESCRIPTION: Insert a table structure into OSL table list.
*
*****************************************************************************/
static acpi_status osl_add_table_to_list(char *signature, u32 instance)
{
struct osl_table_info *new_info;
struct osl_table_info *next;
u32 next_instance = 0;
u8 found = FALSE;
new_info = calloc(1, sizeof(struct osl_table_info));
if (!new_info) {
return (AE_NO_MEMORY);
}
ACPI_MOVE_NAME(new_info->signature, signature);
if (!gbl_table_list_head) {
gbl_table_list_head = new_info;
} else {
next = gbl_table_list_head;
while (1) {
if (ACPI_COMPARE_NAME(next->signature, signature)) {
if (next->instance == instance) {
found = TRUE;
}
if (next->instance >= next_instance) {
next_instance = next->instance + 1;
}
}
if (!next->next) {
break;
}
next = next->next;
}
next->next = new_info;
}
if (found) {
if (instance) {
fprintf(stderr,
"%4.4s: Warning unmatched table instance %d, expected %d\n",
signature, instance, next_instance);
}
instance = next_instance;
}
new_info->instance = instance;
gbl_table_count++;
return (AE_OK);
}
/******************************************************************************
*
* FUNCTION: acpi_os_get_table_by_index
*
* PARAMETERS: index - Which table to get
* table - Where a pointer to the table is returned
* instance - Where a pointer to the table instance no. is
* returned
* address - Where the table physical address is returned
*
* RETURN: Status; Table buffer and physical address returned if AE_OK.
* AE_LIMIT: Index is beyond valid limit
*
* DESCRIPTION: Get an ACPI table via an index value (0 through n). Returns
* AE_LIMIT when an invalid index is reached. Index is not
* necessarily an index into the RSDT/XSDT.
*
*****************************************************************************/
acpi_status
acpi_os_get_table_by_index(u32 index,
struct acpi_table_header ** table,
u32 *instance, acpi_physical_address * address)
{
struct osl_table_info *info;
acpi_status status;
u32 i;
/* Get main ACPI tables from memory on first invocation of this function */
status = osl_table_initialize();
if (ACPI_FAILURE(status)) {
return (status);
}
/* Validate Index */
if (index >= gbl_table_count) {
return (AE_LIMIT);
}
/* Point to the table list entry specified by the Index argument */
info = gbl_table_list_head;
for (i = 0; i < index; i++) {
info = info->next;
}
/* Now we can just get the table via the signature */
status = acpi_os_get_table_by_name(info->signature, info->instance,
table, address);
if (ACPI_SUCCESS(status)) {
*instance = info->instance;
}
return (status);
}
/******************************************************************************
*
* FUNCTION: osl_find_rsdp_via_efi
*
* PARAMETERS: None
*
* RETURN: RSDP address if found
*
* DESCRIPTION: Find RSDP address via EFI.
*
*****************************************************************************/
static acpi_physical_address osl_find_rsdp_via_efi(void)
{
FILE *file;
char buffer[80];
unsigned long address = 0;
file = fopen(EFI_SYSTAB, "r");
if (file) {
while (fgets(buffer, 80, file)) {
if (sscanf(buffer, "ACPI20=0x%lx", &address) == 1) {
break;
}
}
fclose(file);
}
return ((acpi_physical_address) (address));
}
/******************************************************************************
*
* FUNCTION: osl_load_rsdp
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Scan and load RSDP.
*
*****************************************************************************/
static acpi_status osl_load_rsdp(void)
{
struct acpi_table_header *mapped_table;
u8 *rsdp_address;
acpi_physical_address rsdp_base;
acpi_size rsdp_size;
/* Get RSDP from memory */
rsdp_size = sizeof(struct acpi_table_rsdp);
if (gbl_rsdp_base) {
rsdp_base = gbl_rsdp_base;
} else {
rsdp_base = osl_find_rsdp_via_efi();
}
if (!rsdp_base) {
rsdp_base = ACPI_HI_RSDP_WINDOW_BASE;
rsdp_size = ACPI_HI_RSDP_WINDOW_SIZE;
}
rsdp_address = acpi_os_map_memory(rsdp_base, rsdp_size);
if (!rsdp_address) {
return (osl_get_last_status(AE_BAD_ADDRESS));
}
/* Search low memory for the RSDP */
mapped_table = ACPI_CAST_PTR(struct acpi_table_header,
acpi_tb_scan_memory_for_rsdp(rsdp_address,
rsdp_size));
if (!mapped_table) {
acpi_os_unmap_memory(rsdp_address, rsdp_size);
return (AE_NOT_FOUND);
}
gbl_rsdp_address =
rsdp_base + (ACPI_CAST8(mapped_table) - rsdp_address);
ACPI_MEMCPY(&gbl_rsdp, mapped_table, sizeof(struct acpi_table_rsdp));
acpi_os_unmap_memory(rsdp_address, rsdp_size);
return (AE_OK);
}
/******************************************************************************
*
* FUNCTION: osl_can_use_xsdt
*
* PARAMETERS: None
*
* RETURN: TRUE if XSDT is allowed to be used.
*
* DESCRIPTION: This function collects logic that can be used to determine if
* XSDT should be used instead of RSDT.
*
*****************************************************************************/
static u8 osl_can_use_xsdt(void)
{
if (gbl_revision && !acpi_gbl_do_not_use_xsdt) {
return (TRUE);
} else {
return (FALSE);
}
}
/******************************************************************************
*
* FUNCTION: osl_table_initialize
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Initialize ACPI table data. Get and store main ACPI tables to
* local variables. Main ACPI tables include RSDT, FADT, RSDT,
* and/or XSDT.
*
*****************************************************************************/
static acpi_status osl_table_initialize(void)
{
acpi_status status;
acpi_physical_address address;
if (gbl_table_list_initialized) {
return (AE_OK);
}
/* Get RSDP from memory */
status = osl_load_rsdp();
if (ACPI_FAILURE(status)) {
return (status);
}
/* Get XSDT from memory */
if (gbl_rsdp.revision && !gbl_do_not_dump_xsdt) {
if (gbl_xsdt) {
free(gbl_xsdt);
gbl_xsdt = NULL;
}
gbl_revision = 2;
status = osl_get_bios_table(ACPI_SIG_XSDT, 0,
ACPI_CAST_PTR(struct
acpi_table_header *,
&gbl_xsdt), &address);
if (ACPI_FAILURE(status)) {
return (status);
}
}
/* Get RSDT from memory */
if (gbl_rsdp.rsdt_physical_address) {
if (gbl_rsdt) {
free(gbl_rsdt);
gbl_rsdt = NULL;
}
status = osl_get_bios_table(ACPI_SIG_RSDT, 0,
ACPI_CAST_PTR(struct
acpi_table_header *,
&gbl_rsdt), &address);
if (ACPI_FAILURE(status)) {
return (status);
}
}
/* Get FADT from memory */
if (gbl_fadt) {
free(gbl_fadt);
gbl_fadt = NULL;
}
status = osl_get_bios_table(ACPI_SIG_FADT, 0,
ACPI_CAST_PTR(struct acpi_table_header *,
&gbl_fadt),
&gbl_fadt_address);
if (ACPI_FAILURE(status)) {
return (status);
}
if (!gbl_dump_customized_tables) {
/* Add mandatory tables to global table list first */
status = osl_add_table_to_list(ACPI_RSDP_NAME, 0);
if (ACPI_FAILURE(status)) {
return (status);
}
status = osl_add_table_to_list(ACPI_SIG_RSDT, 0);
if (ACPI_FAILURE(status)) {
return (status);
}
if (gbl_revision == 2) {
status = osl_add_table_to_list(ACPI_SIG_XSDT, 0);
if (ACPI_FAILURE(status)) {
return (status);
}
}
status = osl_add_table_to_list(ACPI_SIG_DSDT, 0);
if (ACPI_FAILURE(status)) {
return (status);
}
status = osl_add_table_to_list(ACPI_SIG_FACS, 0);
if (ACPI_FAILURE(status)) {
return (status);
}
/* Add all tables found in the memory */
status = osl_list_bios_tables();
if (ACPI_FAILURE(status)) {
return (status);
}
} else {
/* Add all tables found in the static directory */
status = osl_list_customized_tables(STATIC_TABLE_DIR);
if (ACPI_FAILURE(status)) {
return (status);
}
}
if (gbl_dump_dynamic_tables) {
/* Add all dynamically loaded tables in the dynamic directory */
status = osl_list_customized_tables(DYNAMIC_TABLE_DIR);
if (ACPI_FAILURE(status)) {
return (status);
}
}
gbl_table_list_initialized = TRUE;
return (AE_OK);
}
/******************************************************************************
*
* FUNCTION: osl_list_bios_tables
*
* PARAMETERS: None
*
* RETURN: Status; Table list is initialized if AE_OK.
*
* DESCRIPTION: Add ACPI tables to the table list from memory.
*
* NOTE: This works on Linux as table customization does not modify the
* addresses stored in RSDP/RSDT/XSDT/FADT.
*
*****************************************************************************/
static acpi_status osl_list_bios_tables(void)
{
struct acpi_table_header *mapped_table = NULL;
u8 *table_data;
u8 number_of_tables;
u8 item_size;
acpi_physical_address table_address = 0;
acpi_status status = AE_OK;
u32 i;
if (osl_can_use_xsdt()) {
item_size = sizeof(u64);
table_data =
ACPI_CAST8(gbl_xsdt) + sizeof(struct acpi_table_header);
number_of_tables =
(u8)((gbl_xsdt->header.length -
sizeof(struct acpi_table_header))
/ item_size);
} else { /* Use RSDT if XSDT is not available */
item_size = sizeof(u32);
table_data =
ACPI_CAST8(gbl_rsdt) + sizeof(struct acpi_table_header);
number_of_tables =
(u8)((gbl_rsdt->header.length -
sizeof(struct acpi_table_header))
/ item_size);
}
/* Search RSDT/XSDT for the requested table */
for (i = 0; i < number_of_tables; ++i, table_data += item_size) {
if (osl_can_use_xsdt()) {
table_address =
(acpi_physical_address) (*ACPI_CAST64(table_data));
} else {
table_address =
(acpi_physical_address) (*ACPI_CAST32(table_data));
}
/* Skip NULL entries in RSDT/XSDT */
if (!table_address) {
continue;
}
status = osl_map_table(table_address, NULL, &mapped_table);
if (ACPI_FAILURE(status)) {
return (status);
}
osl_add_table_to_list(mapped_table->signature, 0);
osl_unmap_table(mapped_table);
}
return (AE_OK);
}
/******************************************************************************
*
* FUNCTION: osl_get_bios_table
*
* PARAMETERS: signature - ACPI Signature for common table. Must be
* a null terminated 4-character string.
* instance - Multiple table support for SSDT/UEFI (0...n)
* Must be 0 for other tables.
* table - Where a pointer to the table is returned
* address - Where the table physical address is returned
*
* RETURN: Status; Table buffer and physical address returned if AE_OK.
* AE_LIMIT: Instance is beyond valid limit
* AE_NOT_FOUND: A table with the signature was not found
*
* DESCRIPTION: Get a BIOS provided ACPI table
*
* NOTE: Assumes the input signature is uppercase.
*
*****************************************************************************/
static acpi_status
osl_get_bios_table(char *signature,
u32 instance,
struct acpi_table_header **table,
acpi_physical_address * address)
{
struct acpi_table_header *local_table = NULL;
struct acpi_table_header *mapped_table = NULL;
u8 *table_data;
u8 number_of_tables;
u8 item_size;
u32 current_instance = 0;
acpi_physical_address table_address = 0;
u32 table_length = 0;
acpi_status status = AE_OK;
u32 i;
/* Handle special tables whose addresses are not in RSDT/XSDT */
if (ACPI_COMPARE_NAME(signature, ACPI_RSDP_NAME) ||
ACPI_COMPARE_NAME(signature, ACPI_SIG_RSDT) ||
ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT) ||
ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT) ||
ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) {
/*
* Get the appropriate address, either 32-bit or 64-bit. Be very
* careful about the FADT length and validate table addresses.
* Note: The 64-bit addresses have priority.
*/
if (ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT)) {
if ((gbl_fadt->header.length >= MIN_FADT_FOR_XDSDT) &&
gbl_fadt->Xdsdt) {
table_address =
(acpi_physical_address) gbl_fadt->Xdsdt;
} else
if ((gbl_fadt->header.length >= MIN_FADT_FOR_DSDT)
&& gbl_fadt->dsdt) {
table_address =
(acpi_physical_address) gbl_fadt->dsdt;
}
} else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) {
if ((gbl_fadt->header.length >= MIN_FADT_FOR_XFACS) &&
gbl_fadt->Xfacs) {
table_address =
(acpi_physical_address) gbl_fadt->Xfacs;
} else
if ((gbl_fadt->header.length >= MIN_FADT_FOR_FACS)
&& gbl_fadt->facs) {
table_address =
(acpi_physical_address) gbl_fadt->facs;
}
} else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT)) {
if (!gbl_revision) {
return (AE_BAD_SIGNATURE);
}
table_address =
(acpi_physical_address) gbl_rsdp.
xsdt_physical_address;
} else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_RSDT)) {
table_address =
(acpi_physical_address) gbl_rsdp.
rsdt_physical_address;
} else {
table_address =
(acpi_physical_address) gbl_rsdp_address;
signature = ACPI_SIG_RSDP;
}
/* Now we can get the requested special table */
status = osl_map_table(table_address, signature, &mapped_table);
if (ACPI_FAILURE(status)) {
return (status);
}
table_length = ap_get_table_length(mapped_table);
} else { /* Case for a normal ACPI table */
if (osl_can_use_xsdt()) {
item_size = sizeof(u64);
table_data =
ACPI_CAST8(gbl_xsdt) +
sizeof(struct acpi_table_header);
number_of_tables =
(u8)((gbl_xsdt->header.length -
sizeof(struct acpi_table_header))
/ item_size);
} else { /* Use RSDT if XSDT is not available */
item_size = sizeof(u32);
table_data =
ACPI_CAST8(gbl_rsdt) +
sizeof(struct acpi_table_header);
number_of_tables =
(u8)((gbl_rsdt->header.length -
sizeof(struct acpi_table_header))
/ item_size);
}
/* Search RSDT/XSDT for the requested table */
for (i = 0; i < number_of_tables; ++i, table_data += item_size) {
if (osl_can_use_xsdt()) {
table_address =
(acpi_physical_address) (*ACPI_CAST64
(table_data));
} else {
table_address =
(acpi_physical_address) (*ACPI_CAST32
(table_data));
}
/* Skip NULL entries in RSDT/XSDT */
if (!table_address) {
continue;
}
status =
osl_map_table(table_address, NULL, &mapped_table);
if (ACPI_FAILURE(status)) {
return (status);
}
table_length = mapped_table->length;
/* Does this table match the requested signature? */
if (!ACPI_COMPARE_NAME
(mapped_table->signature, signature)) {
osl_unmap_table(mapped_table);
mapped_table = NULL;
continue;
}
/* Match table instance (for SSDT/UEFI tables) */
if (current_instance != instance) {
osl_unmap_table(mapped_table);
mapped_table = NULL;
current_instance++;
continue;
}
break;
}
}
if (!mapped_table) {
return (AE_LIMIT);
}
if (table_length == 0) {
status = AE_BAD_HEADER;
goto exit;
}
/* Copy table to local buffer and return it */
local_table = calloc(1, table_length);
if (!local_table) {
status = AE_NO_MEMORY;
goto exit;
}
ACPI_MEMCPY(local_table, mapped_table, table_length);
*address = table_address;
*table = local_table;
exit:
osl_unmap_table(mapped_table);
return (status);
}
/******************************************************************************
*
* FUNCTION: osl_list_customized_tables
*
* PARAMETERS: directory - Directory that contains the tables
*
* RETURN: Status; Table list is initialized if AE_OK.
*
* DESCRIPTION: Add ACPI tables to the table list from a directory.
*
*****************************************************************************/
static acpi_status osl_list_customized_tables(char *directory)
{
void *table_dir;
u32 instance;
char temp_name[ACPI_NAME_SIZE];
char *filename;
acpi_status status = AE_OK;
/* Open the requested directory */
table_dir = acpi_os_open_directory(directory, "*", REQUEST_FILE_ONLY);
if (!table_dir) {
return (osl_get_last_status(AE_NOT_FOUND));
}
/* Examine all entries in this directory */
while ((filename = acpi_os_get_next_filename(table_dir))) {
/* Extract table name and instance number */
status =
osl_table_name_from_file(filename, temp_name, &instance);
/* Ignore meaningless files */
if (ACPI_FAILURE(status)) {
continue;
}
/* Add new info node to global table list */
status = osl_add_table_to_list(temp_name, instance);
if (ACPI_FAILURE(status)) {
break;
}
}
acpi_os_close_directory(table_dir);
return (status);
}
/******************************************************************************
*
* FUNCTION: osl_map_table
*
* PARAMETERS: address - Address of the table in memory
* signature - Optional ACPI Signature for desired table.
* Null terminated 4-character string.
* table - Where a pointer to the mapped table is
* returned
*
* RETURN: Status; Mapped table is returned if AE_OK.
* AE_NOT_FOUND: A valid table was not found at the address
*
* DESCRIPTION: Map entire ACPI table into caller's address space.
*
*****************************************************************************/
static acpi_status
osl_map_table(acpi_size address,
char *signature, struct acpi_table_header **table)
{
struct acpi_table_header *mapped_table;
u32 length;
if (!address) {
return (AE_BAD_ADDRESS);
}
/*
* Map the header so we can get the table length.
* Use sizeof (struct acpi_table_header) as:
* 1. it is bigger than 24 to include RSDP->Length
* 2. it is smaller than sizeof (struct acpi_table_rsdp)
*/
mapped_table =
acpi_os_map_memory(address, sizeof(struct acpi_table_header));
if (!mapped_table) {
fprintf(stderr, "Could not map table header at 0x%8.8X%8.8X\n",
ACPI_FORMAT_UINT64(address));
return (osl_get_last_status(AE_BAD_ADDRESS));
}
/* If specified, signature must match */
if (signature) {
if (ACPI_VALIDATE_RSDP_SIG(signature)) {
if (!ACPI_VALIDATE_RSDP_SIG(mapped_table->signature)) {
acpi_os_unmap_memory(mapped_table,
sizeof(struct
acpi_table_header));
return (AE_BAD_SIGNATURE);
}
} else
if (!ACPI_COMPARE_NAME(signature, mapped_table->signature))
{
acpi_os_unmap_memory(mapped_table,
sizeof(struct acpi_table_header));
return (AE_BAD_SIGNATURE);
}
}
/* Map the entire table */
length = ap_get_table_length(mapped_table);
acpi_os_unmap_memory(mapped_table, sizeof(struct acpi_table_header));
if (length == 0) {
return (AE_BAD_HEADER);
}
mapped_table = acpi_os_map_memory(address, length);
if (!mapped_table) {
fprintf(stderr,
"Could not map table at 0x%8.8X%8.8X length %8.8X\n",
ACPI_FORMAT_UINT64(address), length);
return (osl_get_last_status(AE_INVALID_TABLE_LENGTH));
}
(void)ap_is_valid_checksum(mapped_table);
*table = mapped_table;
return (AE_OK);
}
/******************************************************************************
*
* FUNCTION: osl_unmap_table
*
* PARAMETERS: table - A pointer to the mapped table
*
* RETURN: None
*
* DESCRIPTION: Unmap entire ACPI table.
*
*****************************************************************************/
static void osl_unmap_table(struct acpi_table_header *table)
{
if (table) {
acpi_os_unmap_memory(table, ap_get_table_length(table));
}
}
/******************************************************************************
*
* FUNCTION: osl_table_name_from_file
*
* PARAMETERS: filename - File that contains the desired table
* signature - Pointer to 4-character buffer to store
* extracted table signature.
* instance - Pointer to integer to store extracted
* table instance number.
*
* RETURN: Status; Table name is extracted if AE_OK.
*
* DESCRIPTION: Extract table signature and instance number from a table file
* name.
*
*****************************************************************************/
static acpi_status
osl_table_name_from_file(char *filename, char *signature, u32 *instance)
{
/* Ignore meaningless files */
if (strlen(filename) < ACPI_NAME_SIZE) {
return (AE_BAD_SIGNATURE);
}
/* Extract instance number */
if (isdigit((int)filename[ACPI_NAME_SIZE])) {
sscanf(&filename[ACPI_NAME_SIZE], "%d", instance);
} else if (strlen(filename) != ACPI_NAME_SIZE) {
return (AE_BAD_SIGNATURE);
} else {
*instance = 0;
}
/* Extract signature */
ACPI_MOVE_NAME(signature, filename);
return (AE_OK);
}
/******************************************************************************
*
* FUNCTION: osl_read_table_from_file
*
* PARAMETERS: filename - File that contains the desired table
* file_offset - Offset of the table in file
* signature - Optional ACPI Signature for desired table.
* A null terminated 4-character string.
* table - Where a pointer to the table is returned
*
* RETURN: Status; Table buffer is returned if AE_OK.
*
* DESCRIPTION: Read a ACPI table from a file.
*
*****************************************************************************/
static acpi_status
osl_read_table_from_file(char *filename,
acpi_size file_offset,
char *signature, struct acpi_table_header **table)
{
FILE *table_file;
struct acpi_table_header header;
struct acpi_table_header *local_table = NULL;
u32 table_length;
s32 count;
acpi_status status = AE_OK;
/* Open the file */
table_file = fopen(filename, "rb");
if (table_file == NULL) {
fprintf(stderr, "Could not open table file: %s\n", filename);
return (osl_get_last_status(AE_NOT_FOUND));
}
fseek(table_file, file_offset, SEEK_SET);
/* Read the Table header to get the table length */
count = fread(&header, 1, sizeof(struct acpi_table_header), table_file);
if (count != sizeof(struct acpi_table_header)) {
fprintf(stderr, "Could not read table header: %s\n", filename);
status = AE_BAD_HEADER;
goto exit;
}
/* If signature is specified, it must match the table */
if (signature) {
if (ACPI_VALIDATE_RSDP_SIG(signature)) {
if (!ACPI_VALIDATE_RSDP_SIG(header.signature)) {
fprintf(stderr,
"Incorrect RSDP signature: found %8.8s\n",
header.signature);
status = AE_BAD_SIGNATURE;
goto exit;
}
} else if (!ACPI_COMPARE_NAME(signature, header.signature)) {
fprintf(stderr,
"Incorrect signature: Expecting %4.4s, found %4.4s\n",
signature, header.signature);
status = AE_BAD_SIGNATURE;
goto exit;
}
}
table_length = ap_get_table_length(&header);
if (table_length == 0) {
status = AE_BAD_HEADER;
goto exit;
}
/* Read the entire table into a local buffer */
local_table = calloc(1, table_length);
if (!local_table) {
fprintf(stderr,
"%4.4s: Could not allocate buffer for table of length %X\n",
header.signature, table_length);
status = AE_NO_MEMORY;
goto exit;
}
fseek(table_file, file_offset, SEEK_SET);
count = fread(local_table, 1, table_length, table_file);
if (count != table_length) {
fprintf(stderr, "%4.4s: Could not read table content\n",
header.signature);
status = AE_INVALID_TABLE_LENGTH;
goto exit;
}
/* Validate checksum */
(void)ap_is_valid_checksum(local_table);
exit:
fclose(table_file);
*table = local_table;
return (status);
}
/******************************************************************************
*
* FUNCTION: osl_get_customized_table
*
* PARAMETERS: pathname - Directory to find Linux customized table
* signature - ACPI Signature for desired table. Must be
* a null terminated 4-character string.
* instance - Multiple table support for SSDT/UEFI (0...n)
* Must be 0 for other tables.
* table - Where a pointer to the table is returned
* address - Where the table physical address is returned
*
* RETURN: Status; Table buffer is returned if AE_OK.
* AE_LIMIT: Instance is beyond valid limit
* AE_NOT_FOUND: A table with the signature was not found
*
* DESCRIPTION: Get an OS customized table.
*
*****************************************************************************/
static acpi_status
osl_get_customized_table(char *pathname,
char *signature,
u32 instance,
struct acpi_table_header **table,
acpi_physical_address * address)
{
void *table_dir;
u32 current_instance = 0;
char temp_name[ACPI_NAME_SIZE];
char table_filename[PATH_MAX];
char *filename;
acpi_status status;
/* Open the directory for customized tables */
table_dir = acpi_os_open_directory(pathname, "*", REQUEST_FILE_ONLY);
if (!table_dir) {
return (osl_get_last_status(AE_NOT_FOUND));
}
/* Attempt to find the table in the directory */
while ((filename = acpi_os_get_next_filename(table_dir))) {
/* Ignore meaningless files */
if (!ACPI_COMPARE_NAME(filename, signature)) {
continue;
}
/* Extract table name and instance number */
status =
osl_table_name_from_file(filename, temp_name,
&current_instance);
/* Ignore meaningless files */
if (ACPI_FAILURE(status) || current_instance != instance) {
continue;
}
/* Create the table pathname */
if (instance != 0) {
sprintf(table_filename, "%s/%4.4s%d", pathname,
temp_name, instance);
} else {
sprintf(table_filename, "%s/%4.4s", pathname,
temp_name);
}
break;
}
acpi_os_close_directory(table_dir);
if (!filename) {
return (AE_LIMIT);
}
/* There is no physical address saved for customized tables, use zero */
*address = 0;
status = osl_read_table_from_file(table_filename, 0, NULL, table);
return (status);
}
/******************************************************************************
*
* 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);
}
/******************************************************************************
*
* 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));
}
/*
* (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;
}
/******************************************************************************
*
* 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.
*/
/*
* Global variables. Defined in main.c only, externed in all other files
*/
#ifdef _DECLARE_GLOBALS
#define EXTERN
#define INIT_GLOBAL(a,b) a=b
#define DEFINE_ACPI_GLOBALS 1
#else
#define EXTERN extern
#define INIT_GLOBAL(a,b) a
#endif
#include <acpi/acpi.h>
#include "accommon.h"
#include "actables.h"
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
/* 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 u8 INIT_GLOBAL(gbl_do_not_dump_xsdt, 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_integer_byte_width = 8;
#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);
/******************************************************************************
*
* 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);
}
/******************************************************************************
*
* 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);
}
/******************************************************************************
*
* 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:svxz"
/******************************************************************************
*
* 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");
ACPI_OPTION("-x", "Do not use but dump XSDT");
ACPI_OPTION("-x -x", "Do not use or dump XSDT");
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 'x': /* Do not use XSDT */
if (!acpi_gbl_do_not_use_xsdt) {
acpi_gbl_do_not_use_xsdt = TRUE;
} else {
gbl_do_not_dump_xsdt = 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);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment