diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-05-27 18:11:38 +0200 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-05-27 18:11:38 +0200 |
commit | c9b77a4070a60762aee048e3c353d72fb990f940 (patch) | |
tree | 7820cae684404d2bd26814a327f0e2809724dd33 | |
parent | 85dbd5801f62b66e2aa7826aaefcaebead44c8a6 (diff) | |
parent | bc381eebd4b246d6cc29d97ab34d2c54ecc40a87 (diff) |
Merge back earlier ACPICA material.
Conflicts:
drivers/acpi/acpica/acglobal.h
52 files changed, 5625 insertions, 2004 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 43842177b771..60a278948652 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -237,7 +237,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted. This feature is enabled by default. 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] Disable AML predefined validation mechanism diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index b7ed86a20427..8bb43f06e11f 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile @@ -135,6 +135,7 @@ acpi-y += \ rsxface.o acpi-y += \ + tbdata.o \ tbfadt.o \ tbfind.o \ tbinstal.o \ diff --git a/drivers/acpi/acpica/acapps.h b/drivers/acpi/acpica/acapps.h new file mode 100644 index 000000000000..8698ffba6f39 --- /dev/null +++ b/drivers/acpi/acpica/acapps.h @@ -0,0 +1,170 @@ +/****************************************************************************** + * + * Module Name: acapps - common include for ACPI applications/tools + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#ifndef _ACAPPS +#define _ACAPPS + +/* Common info for tool signons */ + +#define ACPICA_NAME "Intel ACPI Component Architecture" +#define ACPICA_COPYRIGHT "Copyright (c) 2000 - 2014 Intel Corporation" + +#if ACPI_MACHINE_WIDTH == 64 +#define ACPI_WIDTH "-64" + +#elif ACPI_MACHINE_WIDTH == 32 +#define ACPI_WIDTH "-32" + +#else +#error unknown ACPI_MACHINE_WIDTH +#define ACPI_WIDTH "-??" + +#endif + +/* Macros for signons and file headers */ + +#define ACPI_COMMON_SIGNON(utility_name) \ + "\n%s\n%s version %8.8X%s [%s]\n%s\n\n", \ + ACPICA_NAME, \ + utility_name, ((u32) ACPI_CA_VERSION), ACPI_WIDTH, __DATE__, \ + ACPICA_COPYRIGHT + +#define ACPI_COMMON_HEADER(utility_name, prefix) \ + "%s%s\n%s%s version %8.8X%s [%s]\n%s%s\n%s\n", \ + prefix, ACPICA_NAME, \ + prefix, utility_name, ((u32) ACPI_CA_VERSION), ACPI_WIDTH, __DATE__, \ + prefix, ACPICA_COPYRIGHT, \ + prefix + +/* Macros for usage messages */ + +#define ACPI_USAGE_HEADER(usage) \ + printf ("Usage: %s\nOptions:\n", usage); + +#define ACPI_OPTION(name, description) \ + printf (" %-18s%s\n", name, description); + +#define FILE_SUFFIX_DISASSEMBLY "dsl" +#define ACPI_TABLE_FILE_SUFFIX ".dat" + +/* + * getopt + */ +int acpi_getopt(int argc, char **argv, char *opts); + +int acpi_getopt_argument(int argc, char **argv); + +extern int acpi_gbl_optind; +extern int acpi_gbl_opterr; +extern int acpi_gbl_sub_opt_char; +extern char *acpi_gbl_optarg; + +/* + * cmfsize - Common get file size function + */ +u32 cm_get_file_size(FILE * file); + +#ifndef ACPI_DUMP_APP +/* + * adisasm + */ +acpi_status +ad_aml_disassemble(u8 out_to_file, + char *filename, char *prefix, char **out_filename); + +void ad_print_statistics(void); + +acpi_status ad_find_dsdt(u8 **dsdt_ptr, u32 *dsdt_length); + +void ad_dump_tables(void); + +acpi_status ad_get_local_tables(void); + +acpi_status +ad_parse_table(struct acpi_table_header *table, + acpi_owner_id * owner_id, u8 load_table, u8 external); + +acpi_status ad_display_tables(char *filename, struct acpi_table_header *table); + +acpi_status ad_display_statistics(void); + +/* + * adwalk + */ +void +acpi_dm_cross_reference_namespace(union acpi_parse_object *parse_tree_root, + struct acpi_namespace_node *namespace_root, + acpi_owner_id owner_id); + +void acpi_dm_dump_tree(union acpi_parse_object *origin); + +void acpi_dm_find_orphan_methods(union acpi_parse_object *origin); + +void +acpi_dm_finish_namespace_load(union acpi_parse_object *parse_tree_root, + struct acpi_namespace_node *namespace_root, + acpi_owner_id owner_id); + +void +acpi_dm_convert_resource_indexes(union acpi_parse_object *parse_tree_root, + struct acpi_namespace_node *namespace_root); + +/* + * adfile + */ +acpi_status ad_initialize(void); + +char *fl_generate_filename(char *input_filename, char *suffix); + +acpi_status +fl_split_input_pathname(char *input_path, + char **out_directory_path, char **out_filename); + +char *ad_generate_filename(char *prefix, char *table_id); + +void +ad_write_table(struct acpi_table_header *table, + u32 length, char *table_name, char *oem_table_id); +#endif + +#endif /* _ACAPPS */ diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h index 68ec61fff188..7a7811a9fc26 100644 --- a/drivers/acpi/acpica/acevents.h +++ b/drivers/acpi/acpica/acevents.h @@ -104,9 +104,10 @@ acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info); */ acpi_status 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, - u8 gpe_block_base_number, + u16 gpe_block_base_number, u32 interrupt_number, struct acpi_gpe_block_info **return_gpe_block); diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index a08a448068dd..115eedcade1e 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -44,144 +44,14 @@ #ifndef __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 * ****************************************************************************/ -/* - * 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); +/* Master list of all ACPI tables that were found in the RSDT/XSDT */ -/* - * 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); /* DSDT information. Used to check for DSDT corruption */ @@ -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_table_handler, acpi_gbl_table_handler); 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(struct acpi_sci_handler_info *, acpi_gbl_sci_handler_list); @@ -296,7 +165,6 @@ ACPI_GLOBAL(u8, acpi_gbl_reg_methods_executed); /* Misc */ 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_ps_find_count); ACPI_GLOBAL(u16, acpi_gbl_pm1_enable_register_save); @@ -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_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 */ /***************************************************************************** @@ -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_device_id asl_device_ids[]; #endif /* __ACGLOBAL_H__ */ diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 52a21dafb540..91f801a2e689 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -450,9 +450,9 @@ struct acpi_gpe_event_info { struct acpi_gpe_register_info { struct acpi_generic_address status_address; /* Address of status 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_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 { 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_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 */ u16 gpe_count; /* Number of individual GPEs in block */ - u8 block_base_number; /* Base GPE number for this block */ - u8 initialized; /* TRUE if this block is initialized */ + u16 block_base_number; /* Base GPE number for this block */ + u8 space_id; + u8 initialized; /* TRUE if this block is initialized */ }; /* Information about GPE interrupt handlers, one per each interrupt level used for GPEs */ @@ -733,7 +734,8 @@ union acpi_parse_value { #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_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) @@ -1147,4 +1149,9 @@ struct ah_predefined_name { #endif }; +struct ah_device_id { + char *name; + char *description; +}; + #endif /* __ACLOCAL_H__ */ diff --git a/drivers/acpi/acpica/acpredef.h b/drivers/acpi/acpica/acpredef.h index a48d713e9599..34001a9fd098 100644 --- a/drivers/acpi/acpica/acpredef.h +++ b/drivers/acpi/acpica/acpredef.h @@ -586,6 +586,10 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { {{"_LID", METHOD_0ARGS, 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, METHOD_RETURNS(ACPI_RTYPE_BUFFER)}}, diff --git a/drivers/acpi/acpica/actables.h b/drivers/acpi/acpica/actables.h index 5fa4b2027697..bda9a7eb50c1 100644 --- a/drivers/acpi/acpica/actables.h +++ b/drivers/acpi/acpica/actables.h @@ -54,6 +54,26 @@ acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp); 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 */ void acpi_tb_parse_fadt(u32 table_index); @@ -72,22 +92,35 @@ acpi_tb_find_table(char *signature, */ 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 - *table_header, - struct acpi_table_desc - *table_desc); +void acpi_tb_invalidate_table(struct acpi_table_desc *table_desc); 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_tb_store_table(acpi_physical_address address, struct acpi_table_header *table, 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); @@ -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); -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 */ @@ -124,8 +153,13 @@ void acpi_tb_check_dsdt_header(void); struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index); void -acpi_tb_install_table(acpi_physical_address address, - char *signature, u32 table_index); +acpi_tb_install_table_with_override(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); diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index ceeec0b7ccb1..1e256c5bda20 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -176,8 +176,7 @@ acpi_status acpi_ut_init_globals(void); 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 char *acpi_ut_get_type_name(acpi_object_type type); @@ -737,4 +736,11 @@ acpi_ut_method_error(const char *module_name, struct acpi_namespace_node *node, 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 */ diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index 955f83da68a5..48f70013b488 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -383,7 +383,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) if (!(gpe_register_info->enable_for_run | gpe_register_info->enable_for_wake)) { 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", gpe_register_info-> base_gpe_number, @@ -416,7 +416,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) } 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", 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, status = acpi_hw_clear_gpe(gpe_event_info); if (ACPI_FAILURE(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); } } @@ -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); if (ACPI_FAILURE(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); } @@ -764,7 +765,7 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, gpe_event_info); if (ACPI_FAILURE(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)); } break; @@ -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. */ ACPI_ERROR((AE_INFO, - "No handler or method for GPE%02X, disabling event", + "No handler or method for GPE %02X, disabling event", gpe_number)); break; diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c index caaed3c673fd..d86699eea33c 100644 --- a/drivers/acpi/acpica/evgpeblk.c +++ b/drivers/acpi/acpica/evgpeblk.c @@ -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) */ - this_register->base_gpe_number = - (u8) (gpe_block->block_base_number + - (i * ACPI_GPE_REGISTER_WIDTH)); + this_register->base_gpe_number = (u16) + (gpe_block->block_base_number + + (i * ACPI_GPE_REGISTER_WIDTH)); - this_register->status_address.address = - gpe_block->block_address.address + i; + this_register->status_address.address = gpe_block->address + i; this_register->enable_address.address = - gpe_block->block_address.address + i + - gpe_block->register_count; + gpe_block->address + i + gpe_block->register_count; - this_register->status_address.space_id = - gpe_block->block_address.space_id; - this_register->enable_address.space_id = - gpe_block->block_address.space_id; + this_register->status_address.space_id = gpe_block->space_id; + this_register->enable_address.space_id = gpe_block->space_id; this_register->status_address.bit_width = ACPI_GPE_REGISTER_WIDTH; this_register->enable_address.bit_width = @@ -334,9 +330,10 @@ error_exit: acpi_status 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, - u8 gpe_block_base_number, + u16 gpe_block_base_number, u32 interrupt_number, struct acpi_gpe_block_info **return_gpe_block) { @@ -359,15 +356,14 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, /* Initialize the new GPE block */ + gpe_block->address = address; + gpe_block->space_id = space_id; gpe_block->node = gpe_device; gpe_block->gpe_count = (u16)(register_count * ACPI_GPE_REGISTER_WIDTH); gpe_block->initialized = FALSE; gpe_block->register_count = register_count; 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 * Note: disables and clears all GPEs in the block @@ -408,12 +404,14 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, } 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 + (gpe_block->gpe_count - 1)), 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 */ diff --git a/drivers/acpi/acpica/evgpeinit.c b/drivers/acpi/acpica/evgpeinit.c index ae779c1e871d..49fc7effd961 100644 --- a/drivers/acpi/acpica/evgpeinit.c +++ b/drivers/acpi/acpica/evgpeinit.c @@ -131,8 +131,10 @@ acpi_status acpi_ev_gpe_initialize(void) /* Install GPE Block 0 */ status = acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device, - &acpi_gbl_FADT.xgpe0_block, - register_count0, 0, + acpi_gbl_FADT.xgpe0_block. + address, + acpi_gbl_FADT.xgpe0_block. + space_id, register_count0, 0, acpi_gbl_FADT.sci_interrupt, &acpi_gbl_gpe_fadt_blocks[0]); @@ -169,8 +171,10 @@ acpi_status acpi_ev_gpe_initialize(void) status = acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device, - &acpi_gbl_FADT.xgpe1_block, - register_count1, + acpi_gbl_FADT.xgpe1_block. + address, + acpi_gbl_FADT.xgpe1_block. + space_id, register_count1, acpi_gbl_FADT.gpe1_base, acpi_gbl_FADT. sci_interrupt, diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c index 5d594eb2e5ec..24ea3424981b 100644 --- a/drivers/acpi/acpica/evmisc.c +++ b/drivers/acpi/acpica/evmisc.c @@ -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", acpi_ut_get_node_name(node), 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, info); diff --git a/drivers/acpi/acpica/evsci.c b/drivers/acpi/acpica/evsci.c index 4d8a709c1fc4..29630e303829 100644 --- a/drivers/acpi/acpica/evsci.c +++ b/drivers/acpi/acpica/evsci.c @@ -117,7 +117,7 @@ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context) 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. */ diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index a734b27da061..11e5803b8b41 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c @@ -239,7 +239,7 @@ acpi_remove_notify_handler(acpi_handle device, union acpi_operand_object *obj_desc; union acpi_operand_object *handler_obj; union acpi_operand_object *previous_handler_obj; - acpi_status status; + acpi_status status = AE_OK; u32 i; ACPI_FUNCTION_TRACE(acpi_remove_notify_handler); @@ -251,20 +251,17 @@ acpi_remove_notify_handler(acpi_handle device, 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 */ if (device == ACPI_ROOT_OBJECT) { for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { 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 || (acpi_gbl_global_notify[i].handler != handler)) { @@ -277,31 +274,40 @@ acpi_remove_notify_handler(acpi_handle device, acpi_gbl_global_notify[i].handler = NULL; acpi_gbl_global_notify[i].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? */ if (!acpi_ev_is_notify_object(node)) { - status = AE_TYPE; - goto unlock_and_exit; + return_ACPI_STATUS(AE_TYPE); } /* Must have an existing internal object */ obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { - status = AE_NOT_EXIST; - goto unlock_and_exit; + return_ACPI_STATUS(AE_NOT_EXIST); } /* Internal object exists. Find the handler and remove it */ for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { 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]; previous_handler_obj = NULL; @@ -329,10 +335,17 @@ acpi_remove_notify_handler(acpi_handle device, 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); } } + return_ACPI_STATUS(status); + unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); @@ -457,6 +470,8 @@ exit: return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_install_sci_handler) + /******************************************************************************* * * FUNCTION: acpi_remove_sci_handler @@ -468,7 +483,6 @@ exit: * DESCRIPTION: Remove a handler for a System Control Interrupt. * ******************************************************************************/ - acpi_status acpi_remove_sci_handler(acpi_sci_handler address) { struct acpi_sci_handler_info *prev_sci_handler; @@ -522,6 +536,8 @@ unlock_and_exit: return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_remove_sci_handler) + /******************************************************************************* * * FUNCTION: acpi_install_global_event_handler @@ -537,7 +553,6 @@ unlock_and_exit: * Can be used to update event counters, etc. * ******************************************************************************/ - acpi_status acpi_install_global_event_handler(acpi_gbl_event_handler handler, void *context) { @@ -840,10 +855,6 @@ acpi_remove_gpe_handler(acpi_handle gpe_device, return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Make sure all deferred GPE tasks are completed */ - - acpi_os_wait_events_complete(); - status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); @@ -895,9 +906,17 @@ acpi_remove_gpe_handler(acpi_handle gpe_device, (void)acpi_ev_add_gpe_reference(gpe_event_info); } + 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 */ ACPI_FREE(handler); + return_ACPI_STATUS(status); unlock_and_exit: acpi_os_release_lock(acpi_gbl_gpe_lock, flags); diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c index 20a1392ffe06..cb534faf5369 100644 --- a/drivers/acpi/acpica/evxfgpe.c +++ b/drivers/acpi/acpica/evxfgpe.c @@ -599,9 +599,10 @@ acpi_install_gpe_block(acpi_handle gpe_device, * For user-installed GPE Block Devices, the gpe_block_base_number * is always zero */ - status = - acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0, - interrupt_number, &gpe_block); + status = acpi_ev_create_gpe_block(node, gpe_block_address->address, + gpe_block_address->space_id, + register_count, 0, interrupt_number, + &gpe_block); if (ACPI_FAILURE(status)) { goto unlock_and_exit; } diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c index 8ba1464efd11..7d2949420db7 100644 --- a/drivers/acpi/acpica/exconfig.c +++ b/drivers/acpi/acpica/exconfig.c @@ -343,16 +343,14 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, struct acpi_walk_state *walk_state) { union acpi_operand_object *ddb_handle; + struct acpi_table_header *table_header; struct acpi_table_header *table; - struct acpi_table_desc table_desc; u32 table_index; acpi_status status; u32 length; 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 */ switch (obj_desc->common.type) { @@ -380,17 +378,17 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, /* Get the table header first so we can get the table length */ - table = ACPI_ALLOCATE(sizeof(struct acpi_table_header)); - if (!table) { + table_header = ACPI_ALLOCATE(sizeof(struct acpi_table_header)); + if (!table_header) { return_ACPI_STATUS(AE_NO_MEMORY); } status = acpi_ex_region_read(obj_desc, sizeof(struct acpi_table_header), - ACPI_CAST_PTR(u8, table)); - length = table->length; - ACPI_FREE(table); + ACPI_CAST_PTR(u8, table_header)); + length = table_header->length; + ACPI_FREE(table_header); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); @@ -420,22 +418,19 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, /* Allocate a buffer for the table */ - table_desc.pointer = ACPI_ALLOCATE(length); - if (!table_desc.pointer) { + table = ACPI_ALLOCATE(length); + if (!table) { return_ACPI_STATUS(AE_NO_MEMORY); } /* Read the entire table */ status = acpi_ex_region_read(obj_desc, length, - ACPI_CAST_PTR(u8, - table_desc.pointer)); + ACPI_CAST_PTR(u8, table)); if (ACPI_FAILURE(status)) { - ACPI_FREE(table_desc.pointer); + ACPI_FREE(table); return_ACPI_STATUS(status); } - - table_desc.address = obj_desc->region.address; break; case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */ @@ -452,10 +447,10 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, /* Get the actual table length from the table header */ - table = + table_header = ACPI_CAST_PTR(struct acpi_table_header, obj_desc->buffer.pointer); - length = table->length; + length = table_header->length; /* Table cannot extend beyond the buffer */ @@ -470,13 +465,12 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, * Copy the table from the buffer because the buffer could be modified * or even deleted in the future */ - table_desc.pointer = ACPI_ALLOCATE(length); - if (!table_desc.pointer) { + table = ACPI_ALLOCATE(length); + if (!table) { return_ACPI_STATUS(AE_NO_MEMORY); } - ACPI_MEMCPY(table_desc.pointer, table, length); - table_desc.address = ACPI_TO_INTEGER(table_desc.pointer); + ACPI_MEMCPY(table, table_header, length); break; default: @@ -484,27 +478,32 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } - /* Validate table checksum (will not get validated in tb_add_table) */ - - status = acpi_tb_verify_checksum(table_desc.pointer, length); - if (ACPI_FAILURE(status)) { - ACPI_FREE(table_desc.pointer); - return_ACPI_STATUS(status); - } - - /* Complete the table descriptor */ + /* Install the new table into the local data structures */ - table_desc.length = length; - table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; + ACPI_INFO((AE_INFO, "Dynamic OEM Table Load:")); + (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)) { /* 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); } @@ -536,9 +535,6 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, 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 */ acpi_ut_remove_reference(ddb_handle); @@ -546,8 +542,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, /* Invoke table handler if present */ if (acpi_gbl_table_handler) { - (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, - table_desc.pointer, + (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table, acpi_gbl_table_handler_context); } @@ -576,6 +571,13 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) 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 * Although the handle is partially validated in acpi_ex_reconfiguration() * when it calls acpi_ex_resolve_operands(), the handle is more completely diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c index 973fdae00f94..925202acc3e4 100644 --- a/drivers/acpi/acpica/exdump.c +++ b/drivers/acpi/acpica/exdump.c @@ -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"} }; -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_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_UINT16, ACPI_EXD_OFFSET(mutex.acquisition_depth), "Acquire Depth"}, diff --git a/drivers/acpi/acpica/hwpci.c b/drivers/acpi/acpica/hwpci.c index e701d8c33dbf..6aade8e1d2a1 100644 --- a/drivers/acpi/acpica/hwpci.c +++ b/drivers/acpi/acpica/hwpci.c @@ -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 */ 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); } @@ -187,6 +188,10 @@ acpi_hw_build_pci_list(acpi_handle root_pci_device, while (1) { status = acpi_get_parent(current_device, &parent_device); if (ACPI_FAILURE(status)) { + + /* Must delete the list before exit */ + + acpi_hw_delete_pci_list(*return_list_head); return (status); } @@ -199,6 +204,10 @@ acpi_hw_build_pci_list(acpi_handle root_pci_device, list_element = ACPI_ALLOCATE(sizeof(struct acpi_pci_device)); if (!list_element) { + + /* Must delete the list before exit */ + + acpi_hw_delete_pci_list(*return_list_head); return (AE_NO_MEMORY); } diff --git a/drivers/acpi/acpica/rscreate.c b/drivers/acpi/acpica/rscreate.c index 75d369050657..049d9c22a0f9 100644 --- a/drivers/acpi/acpica/rscreate.c +++ b/drivers/acpi/acpica/rscreate.c @@ -72,6 +72,8 @@ acpi_buffer_to_resource(u8 *aml_buffer, void *resource; void *current_resource_ptr; + ACPI_FUNCTION_TRACE(acpi_buffer_to_resource); + /* * Note: we allow AE_AML_NO_RESOURCE_END_TAG, since an end tag * is not required here. @@ -85,7 +87,7 @@ acpi_buffer_to_resource(u8 *aml_buffer, status = AE_OK; } if (ACPI_FAILURE(status)) { - return (status); + return_ACPI_STATUS(status); } /* Allocate a buffer for the converted resource */ @@ -93,7 +95,7 @@ acpi_buffer_to_resource(u8 *aml_buffer, resource = ACPI_ALLOCATE_ZEROED(list_size_needed); current_resource_ptr = resource; if (!resource) { - return (AE_NO_MEMORY); + return_ACPI_STATUS(AE_NO_MEMORY); } /* Perform the AML-to-Resource conversion */ @@ -110,9 +112,11 @@ acpi_buffer_to_resource(u8 *aml_buffer, *resource_ptr = resource; } - return (status); + return_ACPI_STATUS(status); } +ACPI_EXPORT_SYMBOL(acpi_buffer_to_resource) + /******************************************************************************* * * FUNCTION: acpi_rs_create_resource_list @@ -130,10 +134,9 @@ acpi_buffer_to_resource(u8 *aml_buffer, * of device resources. * ******************************************************************************/ - acpi_status acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer, - struct acpi_buffer * output_buffer) + struct acpi_buffer *output_buffer) { acpi_status status; diff --git a/drivers/acpi/acpica/tbdata.c b/drivers/acpi/acpica/tbdata.c new file mode 100644 index 000000000000..cbe29944dc97 --- /dev/null +++ b/drivers/acpi/acpica/tbdata.c @@ -0,0 +1,723 @@ +/****************************************************************************** + * + * Module Name: tbdata - Table manager data structure functions + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" +#include "acnamesp.h" +#include "actables.h" + +#define _COMPONENT ACPI_TABLES +ACPI_MODULE_NAME("tbdata") + +/******************************************************************************* + * + * FUNCTION: acpi_tb_init_table_descriptor + * + * PARAMETERS: table_desc - Table descriptor + * address - Physical address of the table + * flags - Allocation flags of the table + * table - Pointer to the table + * + * RETURN: None + * + * DESCRIPTION: Initialize a new table descriptor + * + ******************************************************************************/ +void +acpi_tb_init_table_descriptor(struct acpi_table_desc *table_desc, + acpi_physical_address address, + u8 flags, struct acpi_table_header *table) +{ + + /* + * Initialize the table descriptor. Set the pointer to NULL, since the + * table is not fully mapped at this time. + */ + ACPI_MEMSET(table_desc, 0, sizeof(struct acpi_table_desc)); + table_desc->address = address; + table_desc->length = table->length; + table_desc->flags = flags; + ACPI_MOVE_32_TO_32(table_desc->signature.ascii, table->signature); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_acquire_table + * + * PARAMETERS: table_desc - Table descriptor + * table_ptr - Where table is returned + * table_length - Where table length is returned + * table_flags - Where table allocation flags are returned + * + * RETURN: Status + * + * DESCRIPTION: Acquire an ACPI table. It can be used for tables not + * maintained in the acpi_gbl_root_table_list. + * + ******************************************************************************/ + +acpi_status +acpi_tb_acquire_table(struct acpi_table_desc *table_desc, + struct acpi_table_header **table_ptr, + u32 *table_length, u8 *table_flags) +{ + struct acpi_table_header *table = NULL; + + switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) { + case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL: + + table = + acpi_os_map_memory(table_desc->address, table_desc->length); + break; + + case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: + case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: + + table = + ACPI_CAST_PTR(struct acpi_table_header, + table_desc->address); + break; + + default: + + break; + } + + /* Table is not valid yet */ + + if (!table) { + return (AE_NO_MEMORY); + } + + /* Fill the return values */ + + *table_ptr = table; + *table_length = table_desc->length; + *table_flags = table_desc->flags; + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_release_table + * + * PARAMETERS: table - Pointer for the table + * table_length - Length for the table + * table_flags - Allocation flags for the table + * + * RETURN: None + * + * DESCRIPTION: Release a table. The inverse of acpi_tb_acquire_table(). + * + ******************************************************************************/ + +void +acpi_tb_release_table(struct acpi_table_header *table, + u32 table_length, u8 table_flags) +{ + + switch (table_flags & ACPI_TABLE_ORIGIN_MASK) { + case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL: + + acpi_os_unmap_memory(table, table_length); + break; + + case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: + case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: + default: + + break; + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_acquire_temp_table + * + * PARAMETERS: table_desc - Table descriptor to be acquired + * address - Address of the table + * flags - Allocation flags of the table + * + * RETURN: Status + * + * DESCRIPTION: This function validates the table header to obtain the length + * of a table and fills the table descriptor to make its state as + * "INSTALLED". Such a table descriptor is only used for verified + * installation. + * + ******************************************************************************/ + +acpi_status +acpi_tb_acquire_temp_table(struct acpi_table_desc *table_desc, + acpi_physical_address address, u8 flags) +{ + struct acpi_table_header *table_header; + + switch (flags & ACPI_TABLE_ORIGIN_MASK) { + case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL: + + /* Get the length of the full table from the header */ + + table_header = + acpi_os_map_memory(address, + sizeof(struct acpi_table_header)); + if (!table_header) { + return (AE_NO_MEMORY); + } + + acpi_tb_init_table_descriptor(table_desc, address, flags, + table_header); + acpi_os_unmap_memory(table_header, + sizeof(struct acpi_table_header)); + return (AE_OK); + + case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: + case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: + + table_header = ACPI_CAST_PTR(struct acpi_table_header, address); + if (!table_header) { + return (AE_NO_MEMORY); + } + + acpi_tb_init_table_descriptor(table_desc, address, flags, + table_header); + return (AE_OK); + + default: + + break; + } + + /* Table is not valid yet */ + + return (AE_NO_MEMORY); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_release_temp_table + * + * PARAMETERS: table_desc - Table descriptor to be released + * + * RETURN: Status + * + * DESCRIPTION: The inverse of acpi_tb_acquire_temp_table(). + * + *****************************************************************************/ + +void acpi_tb_release_temp_table(struct acpi_table_desc *table_desc) +{ + + /* + * Note that the .Address is maintained by the callers of + * acpi_tb_acquire_temp_table(), thus do not invoke acpi_tb_uninstall_table() + * where .Address will be freed. + */ + acpi_tb_invalidate_table(table_desc); +} + +/****************************************************************************** + * + * FUNCTION: acpi_tb_validate_table + * + * PARAMETERS: table_desc - Table descriptor + * + * RETURN: Status + * + * DESCRIPTION: This function is called to validate the table, the returned + * table descriptor is in "VALIDATED" state. + * + *****************************************************************************/ + +acpi_status acpi_tb_validate_table(struct acpi_table_desc *table_desc) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(tb_validate_table); + + /* Validate the table if necessary */ + + if (!table_desc->pointer) { + status = acpi_tb_acquire_table(table_desc, &table_desc->pointer, + &table_desc->length, + &table_desc->flags); + if (!table_desc->pointer) { + status = AE_NO_MEMORY; + } + } + + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_invalidate_table + * + * PARAMETERS: table_desc - Table descriptor + * + * RETURN: None + * + * DESCRIPTION: Invalidate one internal ACPI table, this is the inverse of + * acpi_tb_validate_table(). + * + ******************************************************************************/ + +void acpi_tb_invalidate_table(struct acpi_table_desc *table_desc) +{ + + ACPI_FUNCTION_TRACE(tb_invalidate_table); + + /* Table must be validated */ + + if (!table_desc->pointer) { + return_VOID; + } + + acpi_tb_release_table(table_desc->pointer, table_desc->length, + table_desc->flags); + table_desc->pointer = NULL; + + return_VOID; +} + +/****************************************************************************** + * + * FUNCTION: acpi_tb_verify_table + * + * PARAMETERS: table_desc - Table descriptor + * signature - Table signature to verify + * + * RETURN: Status + * + * DESCRIPTION: This function is called to validate and verify the table, the + * returned table descriptor is in "VALIDATED" state. + * + *****************************************************************************/ + +acpi_status +acpi_tb_verify_table(struct acpi_table_desc *table_desc, char *signature) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(tb_verify_table); + + /* Validate the table */ + + status = acpi_tb_validate_table(table_desc); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* If a particular signature is expected (DSDT/FACS), it must match */ + + if (signature && !ACPI_COMPARE_NAME(&table_desc->signature, signature)) { + ACPI_BIOS_ERROR((AE_INFO, + "Invalid signature 0x%X for ACPI table, expected [%s]", + table_desc->signature.integer, signature)); + status = AE_BAD_SIGNATURE; + goto invalidate_and_exit; + } + + /* Verify the checksum */ + + status = + acpi_tb_verify_checksum(table_desc->pointer, table_desc->length); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, + "%4.4s " ACPI_PRINTF_UINT + " Attempted table install failed", + acpi_ut_valid_acpi_name(table_desc->signature. + ascii) ? table_desc-> + signature.ascii : "????", + ACPI_FORMAT_TO_UINT(table_desc->address))); + goto invalidate_and_exit; + } + + return_ACPI_STATUS(AE_OK); + +invalidate_and_exit: + acpi_tb_invalidate_table(table_desc); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_resize_root_table_list + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Expand the size of global table array + * + ******************************************************************************/ + +acpi_status acpi_tb_resize_root_table_list(void) +{ + struct acpi_table_desc *tables; + u32 table_count; + + ACPI_FUNCTION_TRACE(tb_resize_root_table_list); + + /* allow_resize flag is a parameter to acpi_initialize_tables */ + + if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) { + ACPI_ERROR((AE_INFO, + "Resize of Root Table Array is not allowed")); + return_ACPI_STATUS(AE_SUPPORT); + } + + /* Increase the Table Array size */ + + if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { + table_count = acpi_gbl_root_table_list.max_table_count; + } else { + table_count = acpi_gbl_root_table_list.current_table_count; + } + + tables = ACPI_ALLOCATE_ZEROED(((acpi_size) table_count + + ACPI_ROOT_TABLE_SIZE_INCREMENT) * + sizeof(struct acpi_table_desc)); + if (!tables) { + ACPI_ERROR((AE_INFO, + "Could not allocate new root table array")); + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Copy and free the previous table array */ + + if (acpi_gbl_root_table_list.tables) { + ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, + (acpi_size) table_count * + sizeof(struct acpi_table_desc)); + + if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { + ACPI_FREE(acpi_gbl_root_table_list.tables); + } + } + + acpi_gbl_root_table_list.tables = tables; + acpi_gbl_root_table_list.max_table_count = + table_count + ACPI_ROOT_TABLE_SIZE_INCREMENT; + acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED; + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_get_next_root_index + * + * PARAMETERS: table_index - Where table index is returned + * + * RETURN: Status and table index. + * + * DESCRIPTION: Allocate a new ACPI table entry to the global table list + * + ******************************************************************************/ + +acpi_status acpi_tb_get_next_root_index(u32 *table_index) +{ + acpi_status status; + + /* Ensure that there is room for the table in the Root Table List */ + + if (acpi_gbl_root_table_list.current_table_count >= + acpi_gbl_root_table_list.max_table_count) { + status = acpi_tb_resize_root_table_list(); + if (ACPI_FAILURE(status)) { + return (status); + } + } + + *table_index = acpi_gbl_root_table_list.current_table_count; + acpi_gbl_root_table_list.current_table_count++; + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_terminate + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Delete all internal ACPI tables + * + ******************************************************************************/ + +void acpi_tb_terminate(void) +{ + u32 i; + + ACPI_FUNCTION_TRACE(tb_terminate); + + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + + /* Delete the individual tables */ + + for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) { + acpi_tb_uninstall_table(&acpi_gbl_root_table_list.tables[i]); + } + + /* + * Delete the root table array if allocated locally. Array cannot be + * mapped, so we don't need to check for that flag. + */ + if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { + ACPI_FREE(acpi_gbl_root_table_list.tables); + } + + acpi_gbl_root_table_list.tables = NULL; + acpi_gbl_root_table_list.flags = 0; + acpi_gbl_root_table_list.current_table_count = 0; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n")); + + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_delete_namespace_by_owner + * + * PARAMETERS: table_index - Table index + * + * RETURN: Status + * + * DESCRIPTION: Delete all namespace objects created when this table was loaded. + * + ******************************************************************************/ + +acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index) +{ + acpi_owner_id owner_id; + acpi_status status; + + ACPI_FUNCTION_TRACE(tb_delete_namespace_by_owner); + + status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + if (table_index >= acpi_gbl_root_table_list.current_table_count) { + + /* The table index does not exist */ + + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return_ACPI_STATUS(AE_NOT_EXIST); + } + + /* Get the owner ID for this table, used to delete namespace nodes */ + + owner_id = acpi_gbl_root_table_list.tables[table_index].owner_id; + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + + /* + * Need to acquire the namespace writer lock to prevent interference + * with any concurrent namespace walks. The interpreter must be + * released during the deletion since the acquisition of the deletion + * lock may block, and also since the execution of a namespace walk + * must be allowed to use the interpreter. + */ + (void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); + status = acpi_ut_acquire_write_lock(&acpi_gbl_namespace_rw_lock); + + acpi_ns_delete_namespace_by_owner(owner_id); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + acpi_ut_release_write_lock(&acpi_gbl_namespace_rw_lock); + + status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_allocate_owner_id + * + * PARAMETERS: table_index - Table index + * + * RETURN: Status + * + * DESCRIPTION: Allocates owner_id in table_desc + * + ******************************************************************************/ + +acpi_status acpi_tb_allocate_owner_id(u32 table_index) +{ + acpi_status status = AE_BAD_PARAMETER; + + ACPI_FUNCTION_TRACE(tb_allocate_owner_id); + + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + if (table_index < acpi_gbl_root_table_list.current_table_count) { + status = + acpi_ut_allocate_owner_id(& + (acpi_gbl_root_table_list. + tables[table_index].owner_id)); + } + + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_release_owner_id + * + * PARAMETERS: table_index - Table index + * + * RETURN: Status + * + * DESCRIPTION: Releases owner_id in table_desc + * + ******************************************************************************/ + +acpi_status acpi_tb_release_owner_id(u32 table_index) +{ + acpi_status status = AE_BAD_PARAMETER; + + ACPI_FUNCTION_TRACE(tb_release_owner_id); + + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + if (table_index < acpi_gbl_root_table_list.current_table_count) { + acpi_ut_release_owner_id(& + (acpi_gbl_root_table_list. + tables[table_index].owner_id)); + status = AE_OK; + } + + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_get_owner_id + * + * PARAMETERS: table_index - Table index + * owner_id - Where the table owner_id is returned + * + * RETURN: Status + * + * DESCRIPTION: returns owner_id for the ACPI table + * + ******************************************************************************/ + +acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id * owner_id) +{ + acpi_status status = AE_BAD_PARAMETER; + + ACPI_FUNCTION_TRACE(tb_get_owner_id); + + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + if (table_index < acpi_gbl_root_table_list.current_table_count) { + *owner_id = + acpi_gbl_root_table_list.tables[table_index].owner_id; + status = AE_OK; + } + + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_is_table_loaded + * + * PARAMETERS: table_index - Index into the root table + * + * RETURN: Table Loaded Flag + * + ******************************************************************************/ + +u8 acpi_tb_is_table_loaded(u32 table_index) +{ + u8 is_loaded = FALSE; + + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + if (table_index < acpi_gbl_root_table_list.current_table_count) { + is_loaded = (u8) + (acpi_gbl_root_table_list.tables[table_index].flags & + ACPI_TABLE_IS_LOADED); + } + + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return (is_loaded); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_set_table_loaded_flag + * + * PARAMETERS: table_index - Table index + * is_loaded - TRUE if table is loaded, FALSE otherwise + * + * RETURN: None + * + * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE. + * + ******************************************************************************/ + +void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded) +{ + + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + if (table_index < acpi_gbl_root_table_list.current_table_count) { + if (is_loaded) { + acpi_gbl_root_table_list.tables[table_index].flags |= + ACPI_TABLE_IS_LOADED; + } else { + acpi_gbl_root_table_list.tables[table_index].flags &= + ~ACPI_TABLE_IS_LOADED; + } + } + + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); +} diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c index ec14588254d4..41519a958083 100644 --- a/drivers/acpi/acpica/tbfadt.c +++ b/drivers/acpi/acpica/tbfadt.c @@ -52,7 +52,8 @@ ACPI_MODULE_NAME("tbfadt") static void acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, 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); @@ -69,13 +70,14 @@ typedef struct acpi_fadt_info { u16 address32; u16 length; u8 default_length; - u8 type; + u8 flags; } acpi_fadt_info; #define ACPI_FADT_OPTIONAL 0 #define ACPI_FADT_REQUIRED 1 #define ACPI_FADT_SEPARATE_LENGTH 2 +#define ACPI_FADT_GPE_REGISTER 4 static struct acpi_fadt_info fadt_info_table[] = { {"Pm1aEventBlock", @@ -125,14 +127,14 @@ static struct acpi_fadt_info fadt_info_table[] = { ACPI_FADT_OFFSET(gpe0_block), ACPI_FADT_OFFSET(gpe0_block_length), 0, - ACPI_FADT_SEPARATE_LENGTH}, + ACPI_FADT_SEPARATE_LENGTH | ACPI_FADT_GPE_REGISTER}, {"Gpe1Block", ACPI_FADT_OFFSET(xgpe1_block), ACPI_FADT_OFFSET(gpe1_block), ACPI_FADT_OFFSET(gpe1_block_length), 0, - ACPI_FADT_SEPARATE_LENGTH} + ACPI_FADT_SEPARATE_LENGTH | ACPI_FADT_GPE_REGISTER} }; #define ACPI_FADT_INFO_ENTRIES \ @@ -189,19 +191,29 @@ static struct acpi_fadt_pm_info fadt_pm_info_table[] = { static void acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, u8 space_id, - u8 byte_width, u64 address, char *register_name) + u8 byte_width, + u64 address, char *register_name, u8 flags) { 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); - - if (byte_width > 31) { /* (31*8)=248 */ - 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))); + if (byte_width > 31) { /* (31*8)=248, (32*8)=256 */ + /* + * No error for GPE blocks, because we do not use the bit_width + * for GPEs, the legacy length (byte_width) is used instead to + * allow for a large number of GPEs. + */ + 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; } @@ -332,15 +344,15 @@ void acpi_tb_parse_fadt(u32 table_index) /* Obtain the DSDT and FACS tables via their addresses within the FADT */ - acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xdsdt, - ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT); + acpi_tb_install_fixed_table((acpi_physical_address) acpi_gbl_FADT.Xdsdt, + ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT); /* If Hardware Reduced flag is set, there is no FACS */ if (!acpi_gbl_reduced_hardware) { - acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT. - Xfacs, ACPI_SIG_FACS, - ACPI_TABLE_INDEX_FACS); + acpi_tb_install_fixed_table((acpi_physical_address) + acpi_gbl_FADT.Xfacs, ACPI_SIG_FACS, + ACPI_TABLE_INDEX_FACS); } } @@ -450,6 +462,7 @@ static void acpi_tb_convert_fadt(void) struct acpi_generic_address *address64; u32 address32; u8 length; + u8 flags; u32 i; /* @@ -515,6 +528,7 @@ static void acpi_tb_convert_fadt(void) fadt_info_table[i].length); 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" @@ -554,7 +568,7 @@ static void acpi_tb_convert_fadt(void) [i]. length), (u64)address32, - name); + name, flags); } else if (address64->address != (u64)address32) { /* Address mismatch */ @@ -582,7 +596,8 @@ static void acpi_tb_convert_fadt(void) length), (u64) address32, - name); + name, + flags); } } } @@ -603,7 +618,7 @@ static void acpi_tb_convert_fadt(void) 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). * Both the address and length must be non-zero. @@ -617,7 +632,7 @@ static void acpi_tb_convert_fadt(void) address), 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 * length field. If present, both the address and length must @@ -726,7 +741,7 @@ static void acpi_tb_setup_fadt_registers(void) (fadt_pm_info_table[i]. register_num * pm1_register_byte_width), - "PmRegisters"); + "PmRegisters", 0); } } } diff --git a/drivers/acpi/acpica/tbfind.c b/drivers/acpi/acpica/tbfind.c index c12003947bd5..cb947700206c 100644 --- a/drivers/acpi/acpica/tbfind.c +++ b/drivers/acpi/acpica/tbfind.c @@ -99,8 +99,8 @@ acpi_tb_find_table(char *signature, /* Table is not currently mapped, map it */ 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_FAILURE(status)) { return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c index e3040947e9a0..d4d6029fef44 100644 --- a/drivers/acpi/acpica/tbinstal.c +++ b/drivers/acpi/acpica/tbinstal.c @@ -43,688 +43,483 @@ #include <acpi/acpi.h> #include "accommon.h" -#include "acnamesp.h" #include "actables.h" #define _COMPONENT ACPI_TABLES 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; + u8 is_identical; + struct acpi_table_header *table; + u32 table_length; + u8 table_flags; - ACPI_FUNCTION_TRACE(tb_verify_table); - - /* Map the table if necessary */ - - if (!table_desc->pointer) { - 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); - } + status = + acpi_tb_acquire_table(&acpi_gbl_root_table_list.tables[table_index], + &table, &table_length, &table_flags); + if (ACPI_FAILURE(status)) { + return (FALSE); } - /* 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 = - acpi_tb_verify_checksum(table_desc->pointer, table_desc->length); + /* Release the acquired table */ - 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 - * table_index - Where the table index is returned + * PARAMETERS: table_index - Index into root table array + * 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 - * dynamically load tables via the Load and load_table AML - * operators. + * 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. * ******************************************************************************/ -acpi_status -acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) +void +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_desc->pointer) { - status = acpi_tb_verify_table(table_desc); - if (ACPI_FAILURE(status) || !table_desc->pointer) { - return_ACPI_STATUS(status); - } + if (table_index >= acpi_gbl_root_table_list.current_table_count) { + return; } /* - * Validate the incoming table signature. + * ACPI Table Override: * - * 1) Originally, we checked the table signature for "SSDT" or "PSDT". - * 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 - * only "SSDT", "OEMx", and now, also a null signature. (05/2011). + * 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. */ - if ((table_desc->pointer->signature[0] != 0x00) && - (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT)) - && (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); + if (override) { + acpi_tb_override_table(new_table_desc); } - (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) { - 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; - } - } + /* Set the global integer width (based upon revision of the DSDT) */ - /* - * Check for a table match on the entire table length, - * 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; - } + if (table_index == ACPI_TABLE_INDEX_DSDT) { + acpi_ut_set_integer_width(new_table_desc->pointer->revision); } - - /* - * 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 - * table_desc - Table descriptor initialized for the - * original table. May or may not be mapped. + * 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: Pointer to the entire new table. NULL if table not overridden. - * If overridden, installs the new table within the input table - * descriptor. + * RETURN: Status * - * DESCRIPTION: Attempt table override by calling the OSL override functions. - * Note: If the table is overridden, then the entire new table - * is mapped and returned by this function. + * DESCRIPTION: Install a fixed ACPI table (DSDT/FACS) into the global data + * structure. * ******************************************************************************/ -struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header - *table_header, - struct acpi_table_desc - *table_desc) +acpi_status +acpi_tb_install_fixed_table(acpi_physical_address address, + char *signature, u32 table_index) { + struct acpi_table_desc new_table_desc; 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 (ACPI_SUCCESS(status) && new_table) { - new_address = ACPI_PTR_TO_PHYSADDR(new_table); - new_table_length = new_table->length; - new_flags = ACPI_TABLE_ORIGIN_OVERRIDE; - override_type = "Logical"; - goto finish_override; + if (!address) { + ACPI_ERROR((AE_INFO, + "Null physical address for ACPI table [%s]", + signature)); + return (AE_NO_MEMORY); } - /* (2) Attempt physical override (returns a physical address) */ + /* Fill a table descriptor for validation */ - status = acpi_os_physical_table_override(table_header, - &new_address, - &new_table_length); - if (ACPI_SUCCESS(status) && new_address && new_table_length) { - - /* Map the entire new table */ - - 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; + status = acpi_tb_acquire_temp_table(&new_table_desc, address, + ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, "Could not acquire table length at %p", + ACPI_CAST_PTR(void, address))); + return_ACPI_STATUS(status); } - return (NULL); /* There was no override */ - -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))); + /* Validate and verify a table before installation */ - /* 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; - table_desc->pointer = new_table; - table_desc->length = new_table_length; - table_desc->flags = new_flags; + /* Release the temporary table descriptor */ - 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 * - * 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 table_count; - - ACPI_FUNCTION_TRACE(tb_resize_root_table_list); - - /* allow_resize flag is a parameter to acpi_initialize_tables */ + u32 i; + acpi_status status = AE_OK; + struct acpi_table_desc new_table_desc; - 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); - } + ACPI_FUNCTION_TRACE(tb_install_standard_table); - /* Increase the Table Array size */ + /* Acquire a temporary table descriptor for validation */ - 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; + status = acpi_tb_acquire_temp_table(&new_table_desc, address, flags); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, "Could not acquire table length at %p", + ACPI_CAST_PTR(void, address))); + return_ACPI_STATUS(status); } - 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); + /* + * Optionally do not load any SSDTs from the RSDT/XSDT. This can + * be useful for debugging ACPI problems on some machines. + */ + if (!reload && + acpi_gbl_disable_ssdt_table_install && + 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 */ - - 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)); + /* Validate and verify a table before installation */ - if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { - ACPI_FREE(acpi_gbl_root_table_list.tables); - } + status = acpi_tb_verify_table(&new_table_desc, NULL); + if (ACPI_FAILURE(status)) { + goto release_and_exit; } - 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_store_table - * - * PARAMETERS: address - Table address - * table - Table header - * length - Table length - * flags - flags - * - * RETURN: Status and table index. - * - * DESCRIPTION: Add an ACPI table to the global table list - * - ******************************************************************************/ + if (reload) { + /* + * Validate the incoming table signature. + * + * 1) Originally, we checked the table signature for "SSDT" or "PSDT". + * 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 + * only "SSDT", "OEMx", and now, also a null signature. (05/2011). + */ + if ((new_table_desc.signature.ascii[0] != 0x00) && + (!ACPI_COMPARE_NAME + (&new_table_desc.signature, ACPI_SIG_SSDT)) + && (ACPI_STRNCMP(new_table_desc.signature.ascii, "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(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 -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; + /* Check if table is already registered */ - /* 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) { - status = acpi_tb_resize_root_table_list(); - if (ACPI_FAILURE(status)) { - return (status); + /* + * 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. + */ + 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 = - &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 - * - ******************************************************************************/ + /* Add the table to the global root table list */ -void acpi_tb_delete_table(struct acpi_table_desc *table_desc) -{ - /* Table must be mapped or allocated */ - if (!table_desc->pointer) { - return; + status = acpi_tb_get_next_root_index(&i); + if (ACPI_FAILURE(status)) { + goto release_and_exit; } - 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); - break; + *table_index = i; + 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; - } - - table_desc->pointer = NULL; + acpi_tb_release_temp_table(&new_table_desc); + return_ACPI_STATUS(status); } /******************************************************************************* * - * FUNCTION: acpi_tb_terminate + * FUNCTION: acpi_tb_override_table * - * PARAMETERS: None + * PARAMETERS: old_table_desc - Validated table descriptor to be + * overridden * * 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_FUNCTION_TRACE(tb_terminate); - - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - - /* Delete the individual tables */ + acpi_status status; + char *override_type; + struct acpi_table_desc new_table_desc; + struct acpi_table_header *table; + acpi_physical_address address; + u32 length; - for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) { - acpi_tb_delete_table(&acpi_gbl_root_table_list.tables[i]); - } + /* (1) Attempt logical override (returns a logical address) */ - /* - * 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); + status = acpi_os_table_override(old_table_desc->pointer, &table); + if (ACPI_SUCCESS(status) && table) { + acpi_tb_acquire_temp_table(&new_table_desc, + ACPI_PTR_TO_PHYSADDR(table), + ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL); + override_type = "Logical"; + goto finish_override; } - acpi_gbl_root_table_list.tables = NULL; - acpi_gbl_root_table_list.flags = 0; - acpi_gbl_root_table_list.current_table_count = 0; + /* (2) Attempt physical override (returns a physical address) */ - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n")); - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + status = acpi_os_physical_table_override(old_table_desc->pointer, + &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 */ -/******************************************************************************* - * - * 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; +finish_override: - 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)) { - return_ACPI_STATUS(status); + return; } - 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); - } + ACPI_INFO((AE_INFO, "%4.4s " ACPI_PRINTF_UINT + " %s table override, new table: " ACPI_PRINTF_UINT, + old_table_desc->signature.ascii, + ACPI_FORMAT_TO_UINT(old_table_desc->address), + override_type, ACPI_FORMAT_TO_UINT(new_table_desc.address))); - /* 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; - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + acpi_tb_uninstall_table(old_table_desc); /* - * 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. + * Replace the original table descriptor and keep its state as + * "VALIDATED". */ - (void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); - status = acpi_ut_acquire_write_lock(&acpi_gbl_namespace_rw_lock); + acpi_tb_init_table_descriptor(old_table_desc, new_table_desc.address, + new_table_desc.flags, + new_table_desc.pointer); + acpi_tb_validate_table(old_table_desc); - acpi_ns_delete_namespace_by_owner(owner_id); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } + /* Release the temporary table descriptor */ - acpi_ut_release_write_lock(&acpi_gbl_namespace_rw_lock); - - status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); - return_ACPI_STATUS(status); + acpi_tb_release_temp_table(&new_table_desc); } /******************************************************************************* * - * 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_FUNCTION_TRACE(tb_allocate_owner_id); + acpi_status status; + struct acpi_table_desc *table_desc; - (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)); + status = acpi_tb_get_next_root_index(table_index); + if (ACPI_FAILURE(status)) { + return (status); } - (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; - } + /* Initialize added table */ - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return_ACPI_STATUS(status); + table_desc = &acpi_gbl_root_table_list.tables[*table_index]; + 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 - * owner_id - Where the table owner_id is returned + * PARAMETERS: table_desc - Table descriptor * - * 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); - 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; - } + ACPI_FUNCTION_TRACE(tb_uninstall_table); - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_is_table_loaded - * - * PARAMETERS: table_index - Table index - * - * RETURN: Table Loaded Flag - * - ******************************************************************************/ + /* Table must be installed */ -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); + if (!table_desc->address) { + return_VOID; } - (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) -{ + acpi_tb_invalidate_table(table_desc); - (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; - } + if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) == + ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL) { + ACPI_FREE(ACPI_CAST_PTR(void, table_desc->address)); } - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + table_desc->address = ACPI_PTR_TO_PHYSADDR(NULL); + return_VOID; } diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index 9fb85f38de90..e37a103013a4 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c @@ -49,8 +49,6 @@ ACPI_MODULE_NAME("tbutils") /* Local prototypes */ -static acpi_status acpi_tb_validate_xsdt(acpi_physical_address address); - static acpi_physical_address 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) } ACPI_MEMCPY(new_table, table_desc->pointer, table_desc->length); - acpi_tb_delete_table(table_desc); - table_desc->pointer = new_table; - table_desc->flags = ACPI_TABLE_ORIGIN_ALLOCATED; + acpi_tb_uninstall_table(table_desc); + + 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, "Forced DSDT copy: length 0x%05X copied locally, original unmapped", @@ -191,116 +193,6 @@ struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index) /******************************************************************************* * - * 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 * * PARAMETERS: table_entry - Pointer to the RSDT/XSDT table entry @@ -357,87 +249,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 * * PARAMETERS: rsdp - Pointer to the RSDP @@ -461,10 +272,10 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address) u32 table_count; struct acpi_table_header *table; acpi_physical_address address; - acpi_physical_address rsdt_address; u32 length; u8 *table_entry; acpi_status status; + u32 table_index; ACPI_FUNCTION_TRACE(tb_parse_root_table); @@ -489,14 +300,11 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address) * as per the ACPI specification. */ address = (acpi_physical_address) rsdp->xsdt_physical_address; - rsdt_address = - (acpi_physical_address) rsdp->rsdt_physical_address; table_entry_size = ACPI_XSDT_ENTRY_SIZE; } else { /* Root table is an RSDT (32-bit physical addresses) */ address = (acpi_physical_address) rsdp->rsdt_physical_address; - rsdt_address = address; table_entry_size = ACPI_RSDT_ENTRY_SIZE; } @@ -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)); - /* - * 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 */ 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) /* Initialize the root table array from the RSDT/XSDT */ 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) */ - acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list. - current_table_count].address = + address = 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; - 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) */ 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); } diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index a1593159d9ea..6482b0ded652 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -206,8 +206,8 @@ acpi_status acpi_get_table_header(char *signature, u32 instance, struct acpi_table_header *out_table_header) { - u32 i; - u32 j; + u32 i; + u32 j; struct acpi_table_header *header; /* Parameter validation */ @@ -233,7 +233,7 @@ acpi_get_table_header(char *signature, if (!acpi_gbl_root_table_list.tables[i].pointer) { if ((acpi_gbl_root_table_list.tables[i].flags & ACPI_TABLE_ORIGIN_MASK) == - ACPI_TABLE_ORIGIN_MAPPED) { + ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL) { header = acpi_os_map_memory(acpi_gbl_root_table_list. tables[i].address, @@ -321,8 +321,8 @@ acpi_get_table_with_size(char *signature, u32 instance, struct acpi_table_header **out_table, acpi_size *tbl_size) { - u32 i; - u32 j; + u32 i; + u32 j; acpi_status status; /* Parameter validation */ @@ -346,7 +346,7 @@ acpi_get_table_with_size(char *signature, } 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)) { *out_table = acpi_gbl_root_table_list.tables[i].pointer; *tbl_size = acpi_gbl_root_table_list.tables[i].length; @@ -390,7 +390,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_table) * ******************************************************************************/ 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; @@ -416,8 +416,8 @@ acpi_get_table_by_index(u32 table_index, struct acpi_table_header **table) /* Table is not mapped, map it */ status = - acpi_tb_verify_table(&acpi_gbl_root_table_list. - tables[table_index]); + acpi_tb_validate_table(&acpi_gbl_root_table_list. + tables[table_index]); if (ACPI_FAILURE(status)) { (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); return_ACPI_STATUS(status); diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c index 0909420fc776..ab5308b81aa8 100644 --- a/drivers/acpi/acpica/tbxfload.c +++ b/drivers/acpi/acpica/tbxfload.c @@ -117,7 +117,7 @@ static acpi_status acpi_tb_load_namespace(void) tables[ACPI_TABLE_INDEX_DSDT].signature), ACPI_SIG_DSDT) || - ACPI_FAILURE(acpi_tb_verify_table + ACPI_FAILURE(acpi_tb_validate_table (&acpi_gbl_root_table_list. tables[ACPI_TABLE_INDEX_DSDT]))) { status = AE_NO_ACPI_TABLES; @@ -128,7 +128,7 @@ static acpi_status acpi_tb_load_namespace(void) * Save the DSDT pointer for simple access. This is the mapped memory * address. We must take care here because the address of the .Tables * 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_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer; @@ -174,24 +174,11 @@ static acpi_status acpi_tb_load_namespace(void) (acpi_gbl_root_table_list.tables[i]. signature), ACPI_SIG_PSDT)) || - ACPI_FAILURE(acpi_tb_verify_table + ACPI_FAILURE(acpi_tb_validate_table (&acpi_gbl_root_table_list.tables[i]))) { 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 */ (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); @@ -208,6 +195,45 @@ unlock_and_exit: /******************************************************************************* * + * 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 * * PARAMETERS: table - Pointer to a buffer containing the ACPI @@ -222,11 +248,9 @@ unlock_and_exit: * to ensure that the table is not deleted or unmapped. * ******************************************************************************/ - acpi_status acpi_load_table(struct acpi_table_header *table) { acpi_status status; - struct acpi_table_desc table_desc; u32 table_index; ACPI_FUNCTION_TRACE(acpi_load_table); @@ -237,14 +261,6 @@ acpi_status acpi_load_table(struct acpi_table_header *table) return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* 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 */ status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); @@ -255,7 +271,24 @@ acpi_status acpi_load_table(struct acpi_table_header *table) /* Install the table and load it into the namespace */ 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)) { goto unlock_and_exit; } diff --git a/drivers/acpi/acpica/utdecode.c b/drivers/acpi/acpica/utdecode.c index fbfa9eca011f..90ec37c473c6 100644 --- a/drivers/acpi/acpica/utdecode.c +++ b/drivers/acpi/acpica/utdecode.c @@ -462,7 +462,7 @@ char *acpi_ut_get_mutex_name(u32 mutex_id) /* 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", /* 01 */ "Device Check", /* 02 */ "Device Wake", @@ -473,23 +473,75 @@ static const char *acpi_gbl_notify_value_names[ACPI_NOTIFY_MAX + 1] = { /* 07 */ "Power Fault", /* 08 */ "Capabilities Check", /* 09 */ "Device PLD Check", - /* 10 */ "Reserved", - /* 11 */ "System Locality Update", - /* 12 */ "Shutdown Request" + /* 0A */ "Reserved", + /* 0B */ "System Locality Update", + /* 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) { - return (acpi_gbl_notify_value_names[notify_value]); - } else if (notify_value <= ACPI_MAX_SYS_NOTIFY) { + return (acpi_gbl_generic_notify[notify_value]); + } + + /* 0D - 7F are reserved */ + + if (notify_value <= ACPI_MAX_SYS_NOTIFY) { return ("Reserved"); - } else if (notify_value <= ACPI_MAX_DEVICE_SPECIFIC_NOTIFY) { - return ("Device Specific"); - } else { - return ("Hardware Specific"); } + + /* 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 diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index f3abeae9d2f8..d69be3cb3fae 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -55,28 +55,7 @@ ACPI_MODULE_NAME("utglobal") * 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 */ - const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] = { "\\_S0_", "\\_S1_", @@ -337,7 +316,6 @@ acpi_status acpi_ut_init_globals(void) acpi_gbl_acpi_hardware_present = TRUE; acpi_gbl_last_owner_id_index = 0; acpi_gbl_next_owner_id_offset = 0; - acpi_gbl_trace_method_name = 0; acpi_gbl_trace_dbg_level = 0; acpi_gbl_trace_dbg_layer = 0; acpi_gbl_debugger_configuration = DEBUGGER_THREADING; @@ -377,9 +355,7 @@ acpi_status acpi_ut_init_globals(void) acpi_gbl_disable_mem_tracking = FALSE; #endif -#ifdef ACPI_DEBUGGER - acpi_gbl_db_terminate_threads = FALSE; -#endif + ACPI_DEBUGGER_EXEC(acpi_gbl_db_terminate_threads = FALSE); return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/acpica/utstring.c b/drivers/acpi/acpica/utstring.c index 77219336c7e0..6dc54b3c28b0 100644 --- a/drivers/acpi/acpica/utstring.c +++ b/drivers/acpi/acpica/utstring.c @@ -353,7 +353,7 @@ void acpi_ut_print_string(char *string, u16 max_length) } acpi_os_printf("\""); - for (i = 0; string[i] && (i < max_length); i++) { + for (i = 0; (i < max_length) && string[i]; i++) { /* Escape sequences */ diff --git a/drivers/acpi/acpica/utxferror.c b/drivers/acpi/acpica/utxferror.c index edd861102f1b..88ef77f3cf88 100644 --- a/drivers/acpi/acpica/utxferror.c +++ b/drivers/acpi/acpica/utxferror.c @@ -53,6 +53,7 @@ ACPI_MODULE_NAME("utxferror") * This module is used for the in-kernel ACPICA as well as the ACPICA * tools/applications. */ +#ifndef ACPI_NO_ERROR_MESSAGES /* Entire module */ /******************************************************************************* * * FUNCTION: acpi_error @@ -249,3 +250,4 @@ acpi_bios_warning(const char *module_name, } ACPI_EXPORT_SYMBOL(acpi_bios_warning) +#endif /* ACPI_NO_ERROR_MESSAGES */ diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 6776c599816f..9aeae41e22fb 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -1770,16 +1770,15 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object) } #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 1; + return 0; } -__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) { diff --git a/include/acpi/acnames.h b/include/acpi/acnames.h index 3dd6e838dc30..f0e713fadb1f 100644 --- a/include/acpi/acnames.h +++ b/include/acpi/acnames.h @@ -55,6 +55,7 @@ #define METHOD_NAME__HID "_HID" #define METHOD_NAME__INI "_INI" #define METHOD_NAME__PLD "_PLD" +#define METHOD_NAME__PRP "_PRP" #define METHOD_NAME__PRS "_PRS" #define METHOD_NAME__PRT "_PRT" #define METHOD_NAME__PRW "_PRW" diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 44f5e9749601..b5f7132f431f 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -46,7 +46,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20140214 +#define ACPI_CA_VERSION 0x20140424 #include <acpi/acconfig.h> #include <acpi/actypes.h> @@ -55,233 +55,469 @@ 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; -extern struct acpi_table_fadt acpi_gbl_FADT; -extern u8 acpi_gbl_system_awake_and_running; -extern u8 acpi_gbl_reduced_hardware; /* ACPI 5.0 */ -extern u8 acpi_gbl_osi_data; +#ifdef DEFINE_ACPI_GLOBALS +#define ACPI_GLOBAL(type,name) \ + extern type name; \ + type name -/* Runtime configuration of debug print levels */ +#define ACPI_INIT_GLOBAL(type,name,value) \ + type name=value -extern u32 acpi_dbg_level; -extern u32 acpi_dbg_layer; - -/* ACPICA runtime options */ +#else +#ifndef ACPI_GLOBAL +#define ACPI_GLOBAL(type,name) \ + extern type name +#endif -extern u8 acpi_gbl_auto_serialize_methods; -extern u8 acpi_gbl_copy_dsdt_locally; -extern u8 acpi_gbl_create_osi_method; -extern u8 acpi_gbl_disable_auto_repair; -extern u8 acpi_gbl_disable_ssdt_table_load; -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; +#ifndef ACPI_INIT_GLOBAL +#define ACPI_INIT_GLOBAL(type,name,value) \ + extern type name +#endif +#endif /* - * Hardware-reduced prototypes. All interfaces that use these macros will - * be configured out of the ACPICA build if the ACPI_REDUCED_HARDWARE flag - * is set to TRUE. + * These macros configure the various ACPICA interfaces. They are + * useful for generating stub inline functions for features that are + * configured out of the current kernel or ACPICA application. */ -#if (!ACPI_REDUCED_HARDWARE) -#define ACPI_HW_DEPENDENT_RETURN_STATUS(prototype) \ +#ifndef ACPI_EXTERNAL_RETURN_STATUS +#define ACPI_EXTERNAL_RETURN_STATUS(prototype) \ prototype; +#endif -#define ACPI_HW_DEPENDENT_RETURN_OK(prototype) \ +#ifndef ACPI_EXTERNAL_RETURN_OK +#define ACPI_EXTERNAL_RETURN_OK(prototype) \ prototype; +#endif -#define ACPI_HW_DEPENDENT_RETURN_VOID(prototype) \ +#ifndef ACPI_EXTERNAL_RETURN_VOID +#define ACPI_EXTERNAL_RETURN_VOID(prototype) \ prototype; +#endif -#else -#define ACPI_HW_DEPENDENT_RETURN_STATUS(prototype) \ - static ACPI_INLINE prototype {return(AE_NOT_CONFIGURED);} - -#define ACPI_HW_DEPENDENT_RETURN_OK(prototype) \ - static ACPI_INLINE prototype {return(AE_OK);} +#ifndef ACPI_EXTERNAL_RETURN_UINT32 +#define ACPI_EXTERNAL_RETURN_UINT32(prototype) \ + prototype; +#endif -#define ACPI_HW_DEPENDENT_RETURN_VOID(prototype) \ - static ACPI_INLINE prototype {return;} +#ifndef ACPI_EXTERNAL_RETURN_PTR +#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_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_INIT_GLOBAL(u8, acpi_gbl_enable_interpreter_slack, FALSE); -acpi_status __init acpi_initialize_objects(u32 flags); - -acpi_status __init acpi_terminate(void); +/* + * 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); /* - * 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_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable(void)) -#ifdef ACPI_FUTURE_USAGE -acpi_status acpi_subsystem_status(void); -#endif +ACPI_INIT_GLOBAL(u8, acpi_gbl_create_osi_method, TRUE); -#ifdef ACPI_FUTURE_USAGE -acpi_status acpi_get_system_info(struct acpi_buffer *ret_buffer); -#endif +/* + * 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); -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, - acpi_physical_address address, - acpi_size length, u8 warn); +/* + * Optionally do not install 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_install, FALSE); -acpi_status -acpi_decode_pld_buffer(u8 *in_buffer, - acpi_size length, struct acpi_pld_info **return_buffer); +/* + * We keep track of the latest version of Windows that has been requested by + * 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 -acpi_get_table_header(acpi_string signature, - u32 instance, struct acpi_table_header *out_table_header); +#define ACPI_HW_DEPENDENT_RETURN_OK(prototype) \ + ACPI_EXTERNAL_RETURN_OK(prototype) -acpi_status -acpi_get_table_with_size(acpi_string signature, - u32 instance, struct acpi_table_header **out_table, - acpi_size *tbl_size); +#define ACPI_HW_DEPENDENT_RETURN_VOID(prototype) \ + ACPI_EXTERNAL_RETURN_VOID(prototype) -acpi_status -acpi_get_table(acpi_string signature, - u32 instance, struct acpi_table_header **out_table); +#else +#define ACPI_HW_DEPENDENT_RETURN_STATUS(prototype) \ + static ACPI_INLINE prototype {return(AE_NOT_CONFIGURED);} -acpi_status -acpi_get_table_by_index(u32 table_index, struct acpi_table_header **out_table); +#define ACPI_HW_DEPENDENT_RETURN_OK(prototype) \ + static ACPI_INLINE prototype {return(AE_OK);} -acpi_status -acpi_install_table_handler(acpi_table_handler handler, void *context); +#define ACPI_HW_DEPENDENT_RETURN_VOID(prototype) \ + 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 -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); +#ifndef ACPI_NO_ERROR_MESSAGES +#define ACPI_MSG_DEPENDENT_RETURN_VOID(prototype) \ + prototype; -acpi_status -acpi_get_devices(const char *HID, - acpi_walk_callback user_function, - void *context, void **return_value); +#else +#define ACPI_MSG_DEPENDENT_RETURN_VOID(prototype) \ + static ACPI_INLINE prototype {return;} -acpi_status -acpi_get_name(acpi_handle object, - u32 name_type, struct acpi_buffer *ret_path_ptr); +#endif /* ACPI_NO_ERROR_MESSAGES */ -acpi_status -acpi_get_handle(acpi_handle parent, - acpi_string pathname, acpi_handle * ret_handle); +/* + * Debugging output prototypes (default: no debug output). + * + * 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 -acpi_attach_data(acpi_handle object, acpi_object_handler handler, void *data); +#else +#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_debug_trace(char *name, u32 debug_level, u32 debug_layer, u32 flags); +ACPI_EXTERNAL_RETURN_STATUS(acpi_status __init acpi_enable_subsystem(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_evaluate_object(acpi_handle object, - acpi_string pathname, - struct acpi_object_list *parameter_objects, - struct acpi_buffer *return_object_buffer); +ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable(void)) +ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable(void)) +#ifdef ACPI_FUTURE_USAGE +ACPI_EXTERNAL_RETURN_STATUS(acpi_status acpi_subsystem_status(void)) +#endif -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); +#ifdef ACPI_FUTURE_USAGE +ACPI_EXTERNAL_RETURN_STATUS(acpi_status + acpi_get_system_info(struct acpi_buffer + *ret_buffer)) +#endif +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, - struct acpi_device_info **return_buffer); +/* + * ACPI table load/unload interfaces + */ +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_get_next_object(acpi_object_type type, - acpi_handle parent, - acpi_handle child, acpi_handle * out_handle); +ACPI_EXTERNAL_RETURN_STATUS(acpi_status + acpi_unload_parent_table(acpi_handle object)) +ACPI_EXTERNAL_RETURN_STATUS(acpi_status __init acpi_load_tables(void)) -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 */ -acpi_status -acpi_install_initialization_handler(acpi_init_handler handler, u32 function); - +ACPI_EXTERNAL_RETURN_STATUS(acpi_status + acpi_install_initialization_handler + (acpi_init_handler handler, u32 function)) ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status - acpi_install_sci_handler(acpi_sci_handler - address, - void *context)) + acpi_install_sci_handler(acpi_sci_handler + address, + void *context)) ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_remove_sci_handler(acpi_sci_handler address)) @@ -313,30 +549,42 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status u32 gpe_number, acpi_gpe_handler address)) -acpi_status acpi_install_notify_handler(acpi_handle device, u32 handler_type, - acpi_notify_handler handler, - void *context); - -acpi_status -acpi_remove_notify_handler(acpi_handle device, - u32 handler_type, acpi_notify_handler handler); - -acpi_status -acpi_install_address_space_handler(acpi_handle device, - acpi_adr_space_type space_id, - acpi_adr_space_handler handler, - acpi_adr_space_setup setup, void *context); - -acpi_status -acpi_remove_address_space_handler(acpi_handle device, - acpi_adr_space_type space_id, - acpi_adr_space_handler handler); - +ACPI_EXTERNAL_RETURN_STATUS(acpi_status + acpi_install_notify_handler(acpi_handle device, + u32 handler_type, + acpi_notify_handler + handler, + void *context)) +ACPI_EXTERNAL_RETURN_STATUS(acpi_status + acpi_remove_notify_handler(acpi_handle device, + u32 handler_type, + acpi_notify_handler + handler)) +ACPI_EXTERNAL_RETURN_STATUS(acpi_status + acpi_install_address_space_handler(acpi_handle + device, + acpi_adr_space_type + space_id, + acpi_adr_space_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 -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 - -acpi_status acpi_install_interface_handler(acpi_interface_handler handler); +ACPI_EXTERNAL_RETURN_STATUS(acpi_status + acpi_install_interface_handler + (acpi_interface_handler handler)) /* * Global Lock interfaces @@ -351,10 +599,14 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status /* * Interfaces to AML mutex objects */ -acpi_status -acpi_acquire_mutex(acpi_handle handle, acpi_string pathname, u16 timeout); +ACPI_EXTERNAL_RETURN_STATUS(acpi_status + 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 @@ -434,57 +686,69 @@ typedef acpi_status(*acpi_walk_resource_callback) (struct acpi_resource * resource, void *context); -acpi_status -acpi_get_vendor_resource(acpi_handle device, - char *name, - struct acpi_vendor_uuid *uuid, - struct acpi_buffer *ret_buffer); - -acpi_status -acpi_get_current_resources(acpi_handle device, struct acpi_buffer *ret_buffer); - +ACPI_EXTERNAL_RETURN_STATUS(acpi_status + acpi_get_vendor_resource(acpi_handle device, + char *name, + struct acpi_vendor_uuid + *uuid, + 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 -acpi_status -acpi_get_possible_resources(acpi_handle device, struct acpi_buffer *ret_buffer); +ACPI_EXTERNAL_RETURN_STATUS(acpi_status + acpi_get_possible_resources(acpi_handle device, + struct acpi_buffer + *ret_buffer)) #endif - -acpi_status -acpi_get_event_resources(acpi_handle device_handle, - struct acpi_buffer *ret_buffer); - -acpi_status -acpi_walk_resource_buffer(struct acpi_buffer *buffer, - acpi_walk_resource_callback user_function, - void *context); - -acpi_status -acpi_walk_resources(acpi_handle device, - char *name, - acpi_walk_resource_callback user_function, void *context); - -acpi_status -acpi_set_current_resources(acpi_handle device, struct acpi_buffer *in_buffer); - -acpi_status -acpi_get_irq_routing_table(acpi_handle device, struct acpi_buffer *ret_buffer); - -acpi_status -acpi_resource_to_address64(struct acpi_resource *resource, - struct acpi_resource_address64 *out); - -acpi_status -acpi_buffer_to_resource(u8 *aml_buffer, - u16 aml_buffer_length, - struct acpi_resource **resource_ptr); +ACPI_EXTERNAL_RETURN_STATUS(acpi_status + acpi_get_event_resources(acpi_handle device_handle, + struct acpi_buffer + *ret_buffer)) +ACPI_EXTERNAL_RETURN_STATUS(acpi_status + acpi_walk_resource_buffer(struct acpi_buffer + *buffer, + acpi_walk_resource_callback + user_function, + void *context)) +ACPI_EXTERNAL_RETURN_STATUS(acpi_status + acpi_walk_resources(acpi_handle device, char *name, + acpi_walk_resource_callback + user_function, void *context)) +ACPI_EXTERNAL_RETURN_STATUS(acpi_status + acpi_set_current_resources(acpi_handle device, + struct acpi_buffer + *in_buffer)) +ACPI_EXTERNAL_RETURN_STATUS(acpi_status + acpi_get_irq_routing_table(acpi_handle device, + struct acpi_buffer + *ret_buffer)) +ACPI_EXTERNAL_RETURN_STATUS(acpi_status + acpi_resource_to_address64(struct acpi_resource + *resource, + struct + acpi_resource_address64 + *out)) +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 */ -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_read_bit_register(u32 register_id, @@ -497,18 +761,20 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status /* * Sleep/Wake interfaces */ -acpi_status -acpi_get_sleep_type_data(u8 sleep_state, u8 *slp_typ_a, u8 *slp_typ_b); - -acpi_status acpi_enter_sleep_state_prep(u8 sleep_state); +ACPI_EXTERNAL_RETURN_STATUS(acpi_status + acpi_get_sleep_type_data(u8 sleep_state, + u8 *slp_typ_a, + 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_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_prep(u8 sleep_state)) +ACPI_EXTERNAL_RETURN_STATUS(acpi_status acpi_leave_sleep_state(u8 sleep_state)) ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_set_firmware_waking_vector(u32 @@ -535,53 +801,72 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status /* * Error/Warning output */ -ACPI_PRINTF_LIKE(3) -void ACPI_INTERNAL_VAR_XFACE -acpi_error(const char *module_name, u32 line_number, const char *format, ...); - -ACPI_PRINTF_LIKE(4) -void ACPI_INTERNAL_VAR_XFACE -acpi_exception(const char *module_name, - u32 line_number, acpi_status status, const char *format, ...); - -ACPI_PRINTF_LIKE(3) -void ACPI_INTERNAL_VAR_XFACE -acpi_warning(const char *module_name, u32 line_number, const char *format, ...); - -ACPI_PRINTF_LIKE(3) -void ACPI_INTERNAL_VAR_XFACE -acpi_info(const char *module_name, u32 line_number, const char *format, ...); - -ACPI_PRINTF_LIKE(3) -void ACPI_INTERNAL_VAR_XFACE -acpi_bios_error(const char *module_name, - u32 line_number, const char *format, ...); - -ACPI_PRINTF_LIKE(3) -void ACPI_INTERNAL_VAR_XFACE -acpi_bios_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_error(const char *module_name, + u32 line_number, + const char *format, ...)) +ACPI_MSG_DEPENDENT_RETURN_VOID(ACPI_PRINTF_LIKE(4) + void ACPI_INTERNAL_VAR_XFACE + acpi_exception(const char *module_name, + u32 line_number, + acpi_status status, + const char *format, ...)) +ACPI_MSG_DEPENDENT_RETURN_VOID(ACPI_PRINTF_LIKE(3) + void ACPI_INTERNAL_VAR_XFACE + 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_info(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_bios_error(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_bios_warning(const char *module_name, + u32 line_number, + const char *format, ...)) /* * 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 -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_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, ...); -#endif +/* + * Divergences + */ +acpi_status acpi_get_id(acpi_handle object, acpi_owner_id * out_type); + +acpi_status acpi_unload_table_id(acpi_owner_id id); + +acpi_status +acpi_get_table_with_size(acpi_string signature, + u32 instance, struct acpi_table_header **out_table, + acpi_size *tbl_size); + +acpi_status +acpi_get_data_full(acpi_handle object, acpi_object_handler handler, void **data, + void (*callback)(void *)); #endif /* __ACXFACE_H__ */ diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h index 3b30e36b53b5..1cc7ef13c01a 100644 --- a/include/acpi/actbl.h +++ b/include/acpi/actbl.h @@ -367,12 +367,11 @@ struct acpi_table_desc { /* Masks for Flags field above */ -#define ACPI_TABLE_ORIGIN_UNKNOWN (0) -#define ACPI_TABLE_ORIGIN_MAPPED (1) -#define ACPI_TABLE_ORIGIN_ALLOCATED (2) -#define ACPI_TABLE_ORIGIN_OVERRIDE (4) -#define ACPI_TABLE_ORIGIN_MASK (7) -#define ACPI_TABLE_IS_LOADED (8) +#define ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL (0) /* Virtual address, external maintained */ +#define ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL (1) /* Physical address, internally mapped */ +#define ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL (2) /* Virtual address, internallly allocated */ +#define ACPI_TABLE_ORIGIN_MASK (3) +#define ACPI_TABLE_IS_LOADED (8) /* * Get the remaining ACPI tables diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h index 212c65de75df..4ad7da805180 100644 --- a/include/acpi/actbl1.h +++ b/include/acpi/actbl1.h @@ -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 */ @@ -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 */ diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index c8adad9c6b6a..860e5c883eb3 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -70,6 +70,7 @@ #define ACPI_SIG_HPET "HPET" /* High Precision Event Timer table */ #define ACPI_SIG_IBFT "IBFT" /* iSCSI Boot Firmware Table */ #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_MCHI "MCHI" /* Management Controller Host Interface table */ #define ACPI_SIG_MTMR "MTMR" /* MID Timer table */ @@ -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 */ @@ -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 * * Conforms to "PCI Firmware Specification", Revision 3.0, June 20, 2005 @@ -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 */ diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index e76356574374..19b26bb69a70 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -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 /* * Memory allocation tracking (used by acpi_exec to detect memory leaks) @@ -350,6 +359,8 @@ typedef u32 acpi_physical_address; #endif /* ACPI_DBG_TRACK_ALLOCATIONS */ +#endif /* ACPI_NO_MEM_ALLOCATIONS */ + /****************************************************************************** * * ACPI Specification constants (Do not change unless the specification changes) @@ -928,9 +939,19 @@ struct acpi_object_list { * Miscellaneous common Data Structures used by the interfaces */ #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_LOCAL_BUFFER (acpi_size) (-2) /* For internal use only (enables tracking) */ +#endif /* ACPI_NO_MEM_ALLOCATIONS */ + struct acpi_buffer { acpi_size length; /* Length in bytes of the buffer */ void *pointer; /* pointer to buffer */ diff --git a/include/acpi/platform/acgcc.h b/include/acpi/platform/acgcc.h index a476b9118b49..384875da3713 100644 --- a/include/acpi/platform/acgcc.h +++ b/include/acpi/platform/acgcc.h @@ -64,4 +64,15 @@ */ #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__ */ diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h index 93c55ed7c53d..4c2f9e78001c 100644 --- a/include/acpi/platform/aclinux.h +++ b/include/acpi/platform/aclinux.h @@ -73,6 +73,37 @@ #endif #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 */ #define ACPI_MACHINE_WIDTH BITS_PER_LONG @@ -91,7 +122,7 @@ #include <ctype.h> #include <unistd.h> -/* Disable kernel specific declarators */ +/* Define/disable kernel-specific declarators */ #ifndef __init #define __init @@ -106,7 +137,8 @@ #define ACPI_FLUSH_CPU_CACHE() #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 COMPILER_DEPENDENT_INT64 long #define COMPILER_DEPENDENT_UINT64 unsigned long diff --git a/tools/power/acpi/Makefile b/tools/power/acpi/Makefile index c2c0f20067a5..7ac578019ea9 100644 --- a/tools/power/acpi/Makefile +++ b/tools/power/acpi/Makefile @@ -68,7 +68,8 @@ WARNINGS += $(call cc-supports,-Wstrict-prototypes) WARNINGS += $(call cc-supports,-Wdeclaration-after-statement) 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) ifeq ($(strip $(V)),false) @@ -92,10 +93,29 @@ endif # --- ACPIDUMP BEGIN --- vpath %.c \ - tools/acpidump + ../../../drivers/acpi/acpica\ + tools/acpidump\ + common\ + os_specific/service_layers + +CFLAGS += -DACPI_DUMP_APP -Itools/acpidump 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)) diff --git a/tools/power/acpi/common/cmfsize.c b/tools/power/acpi/common/cmfsize.c new file mode 100644 index 000000000000..5140e5edae1f --- /dev/null +++ b/tools/power/acpi/common/cmfsize.c @@ -0,0 +1,101 @@ +/****************************************************************************** + * + * Module Name: cfsize - Common get file size function + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" +#include "acapps.h" +#include <stdio.h> + +#define _COMPONENT ACPI_TOOLS +ACPI_MODULE_NAME("cmfsize") + +/******************************************************************************* + * + * FUNCTION: cm_get_file_size + * + * PARAMETERS: file - Open file descriptor + * + * RETURN: File Size. On error, -1 (ACPI_UINT32_MAX) + * + * DESCRIPTION: Get the size of a file. Uses seek-to-EOF. File must be open. + * Does not disturb the current file pointer. Uses perror for + * error messages. + * + ******************************************************************************/ +u32 cm_get_file_size(FILE * file) +{ + long file_size; + long current_offset; + + /* Save the current file pointer, seek to EOF to obtain file size */ + + current_offset = ftell(file); + if (current_offset < 0) { + goto offset_error; + } + + if (fseek(file, 0, SEEK_END)) { + goto seek_error; + } + + file_size = ftell(file); + if (file_size < 0) { + goto offset_error; + } + + /* Restore original file pointer */ + + if (fseek(file, current_offset, SEEK_SET)) { + goto seek_error; + } + + return ((u32)file_size); + +offset_error: + perror("Could not get file offset"); + return (ACPI_UINT32_MAX); + +seek_error: + perror("Could not seek file"); + return (ACPI_UINT32_MAX); +} diff --git a/tools/power/acpi/common/getopt.c b/tools/power/acpi/common/getopt.c new file mode 100644 index 000000000000..a302f52e4fd3 --- /dev/null +++ b/tools/power/acpi/common/getopt.c @@ -0,0 +1,239 @@ +/****************************************************************************** + * + * Module Name: getopt + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +/* + * ACPICA getopt() implementation + * + * Option strings: + * "f" - Option has no arguments + * "f:" - Option requires an argument + * "f^" - Option has optional single-char sub-options + * "f|" - Option has required single-char sub-options + */ + +#include <stdio.h> +#include <string.h> +#include <acpi/acpi.h> +#include "accommon.h" +#include "acapps.h" + +#define ACPI_OPTION_ERROR(msg, badchar) \ + if (acpi_gbl_opterr) {fprintf (stderr, "%s%c\n", msg, badchar);} + +int acpi_gbl_opterr = 1; +int acpi_gbl_optind = 1; +int acpi_gbl_sub_opt_char = 0; +char *acpi_gbl_optarg; + +static int current_char_ptr = 1; + +/******************************************************************************* + * + * FUNCTION: acpi_getopt_argument + * + * PARAMETERS: argc, argv - from main + * + * RETURN: 0 if an argument was found, -1 otherwise. Sets acpi_gbl_Optarg + * to point to the next argument. + * + * DESCRIPTION: Get the next argument. Used to obtain arguments for the + * two-character options after the original call to acpi_getopt. + * Note: Either the argument starts at the next character after + * the option, or it is pointed to by the next argv entry. + * (After call to acpi_getopt, we need to backup to the previous + * argv entry). + * + ******************************************************************************/ + +int acpi_getopt_argument(int argc, char **argv) +{ + acpi_gbl_optind--; + current_char_ptr++; + + if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') { + acpi_gbl_optarg = + &argv[acpi_gbl_optind++][(int)(current_char_ptr + 1)]; + } else if (++acpi_gbl_optind >= argc) { + ACPI_OPTION_ERROR("Option requires an argument: -", 'v'); + + current_char_ptr = 1; + return (-1); + } else { + acpi_gbl_optarg = argv[acpi_gbl_optind++]; + } + + current_char_ptr = 1; + return (0); +} + +/******************************************************************************* + * + * FUNCTION: acpi_getopt + * + * PARAMETERS: argc, argv - from main + * opts - options info list + * + * RETURN: Option character or EOF + * + * DESCRIPTION: Get the next option + * + ******************************************************************************/ + +int acpi_getopt(int argc, char **argv, char *opts) +{ + int current_char; + char *opts_ptr; + + if (current_char_ptr == 1) { + if (acpi_gbl_optind >= argc || + argv[acpi_gbl_optind][0] != '-' || + argv[acpi_gbl_optind][1] == '\0') { + return (EOF); + } else if (strcmp(argv[acpi_gbl_optind], "--") == 0) { + acpi_gbl_optind++; + return (EOF); + } + } + + /* Get the option */ + + current_char = argv[acpi_gbl_optind][current_char_ptr]; + + /* Make sure that the option is legal */ + + if (current_char == ':' || + (opts_ptr = strchr(opts, current_char)) == NULL) { + ACPI_OPTION_ERROR("Illegal option: -", current_char); + + if (argv[acpi_gbl_optind][++current_char_ptr] == '\0') { + acpi_gbl_optind++; + current_char_ptr = 1; + } + + return ('?'); + } + + /* Option requires an argument? */ + + if (*++opts_ptr == ':') { + if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') { + acpi_gbl_optarg = + &argv[acpi_gbl_optind++][(int) + (current_char_ptr + 1)]; + } else if (++acpi_gbl_optind >= argc) { + ACPI_OPTION_ERROR("Option requires an argument: -", + current_char); + + current_char_ptr = 1; + return ('?'); + } else { + acpi_gbl_optarg = argv[acpi_gbl_optind++]; + } + + current_char_ptr = 1; + } + + /* Option has an optional argument? */ + + else if (*opts_ptr == '+') { + if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') { + acpi_gbl_optarg = + &argv[acpi_gbl_optind++][(int) + (current_char_ptr + 1)]; + } else if (++acpi_gbl_optind >= argc) { + acpi_gbl_optarg = NULL; + } else { + acpi_gbl_optarg = argv[acpi_gbl_optind++]; + } + + current_char_ptr = 1; + } + + /* Option has optional single-char arguments? */ + + else if (*opts_ptr == '^') { + if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') { + acpi_gbl_optarg = + &argv[acpi_gbl_optind][(int)(current_char_ptr + 1)]; + } else { + acpi_gbl_optarg = "^"; + } + + acpi_gbl_sub_opt_char = acpi_gbl_optarg[0]; + acpi_gbl_optind++; + current_char_ptr = 1; + } + + /* Option has a required single-char argument? */ + + else if (*opts_ptr == '|') { + if (argv[acpi_gbl_optind][(int)(current_char_ptr + 1)] != '\0') { + acpi_gbl_optarg = + &argv[acpi_gbl_optind][(int)(current_char_ptr + 1)]; + } else { + ACPI_OPTION_ERROR + ("Option requires a single-character suboption: -", + current_char); + + current_char_ptr = 1; + return ('?'); + } + + acpi_gbl_sub_opt_char = acpi_gbl_optarg[0]; + acpi_gbl_optind++; + current_char_ptr = 1; + } + + /* Option with no arguments */ + + else { + if (argv[acpi_gbl_optind][++current_char_ptr] == '\0') { + current_char_ptr = 1; + acpi_gbl_optind++; + } + + acpi_gbl_optarg = NULL; + } + + return (current_char); +} diff --git a/tools/power/acpi/man/acpidump.8 b/tools/power/acpi/man/acpidump.8 index adfa99166e5e..38f095d86b52 100644 --- a/tools/power/acpi/man/acpidump.8 +++ b/tools/power/acpi/man/acpidump.8 @@ -1,18 +1,64 @@ .TH ACPIDUMP 8 .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 -.ft B -.B acpidump > acpidump.out +.B acpidump +.RI [ options ] +.br + .SH DESCRIPTION -\fBacpidump \fP dumps the systems ACPI tables to an ASCII file -appropriate for attaching to a bug report. +.B acpidump +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. -.SS Options -no options worth worrying about. -.PP -.SH EXAMPLE + +.SH OPTIONS +acpidump options are as follow: +.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 # acpidump > acpidump.out @@ -50,10 +96,25 @@ ACPICA: https://acpica.org/ .ta .nf /dev/mem +/sys/firmware/acpi/tables/* /sys/firmware/acpi/tables/dynamic/* +/sys/firmware/efi/systab .fi -.PP .SH AUTHOR -.nf -Written by Len Brown <len.brown@intel.com> +.TP +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. diff --git a/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c b/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c new file mode 100644 index 000000000000..ba7bad04dff1 --- /dev/null +++ b/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c @@ -0,0 +1,1325 @@ +/****************************************************************************** + * + * 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, + ¤t_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); +} diff --git a/tools/power/acpi/os_specific/service_layers/osunixdir.c b/tools/power/acpi/os_specific/service_layers/osunixdir.c new file mode 100644 index 000000000000..733f9e490fc4 --- /dev/null +++ b/tools/power/acpi/os_specific/service_layers/osunixdir.c @@ -0,0 +1,204 @@ +/****************************************************************************** + * + * Module Name: osunixdir - Unix directory access interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <dirent.h> +#include <fnmatch.h> +#include <ctype.h> +#include <sys/stat.h> + +/* + * Allocated structure returned from os_open_directory + */ +typedef struct external_find_info { + char *dir_pathname; + DIR *dir_ptr; + char temp_buffer[256]; + char *wildcard_spec; + char requested_file_type; + +} external_find_info; + +/******************************************************************************* + * + * FUNCTION: acpi_os_open_directory + * + * PARAMETERS: dir_pathname - Full pathname to the directory + * wildcard_spec - string of the form "*.c", etc. + * + * RETURN: A directory "handle" to be used in subsequent search operations. + * NULL returned on failure. + * + * DESCRIPTION: Open a directory in preparation for a wildcard search + * + ******************************************************************************/ + +void *acpi_os_open_directory(char *dir_pathname, + char *wildcard_spec, char requested_file_type) +{ + struct external_find_info *external_info; + DIR *dir; + + /* Allocate the info struct that will be returned to the caller */ + + external_info = calloc(1, sizeof(struct external_find_info)); + if (!external_info) { + return (NULL); + } + + /* Get the directory stream */ + + dir = opendir(dir_pathname); + if (!dir) { + fprintf(stderr, "Cannot open directory - %s\n", dir_pathname); + free(external_info); + return (NULL); + } + + /* Save the info in the return structure */ + + external_info->wildcard_spec = wildcard_spec; + external_info->requested_file_type = requested_file_type; + external_info->dir_pathname = dir_pathname; + external_info->dir_ptr = dir; + return (external_info); +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_get_next_filename + * + * PARAMETERS: dir_handle - Created via acpi_os_open_directory + * + * RETURN: Next filename matched. NULL if no more matches. + * + * DESCRIPTION: Get the next file in the directory that matches the wildcard + * specification. + * + ******************************************************************************/ + +char *acpi_os_get_next_filename(void *dir_handle) +{ + struct external_find_info *external_info = dir_handle; + struct dirent *dir_entry; + char *temp_str; + int str_len; + struct stat temp_stat; + int err; + + while ((dir_entry = readdir(external_info->dir_ptr))) { + if (!fnmatch + (external_info->wildcard_spec, dir_entry->d_name, 0)) { + if (dir_entry->d_name[0] == '.') { + continue; + } + + str_len = strlen(dir_entry->d_name) + + strlen(external_info->dir_pathname) + 2; + + temp_str = calloc(str_len, 1); + if (!temp_str) { + fprintf(stderr, + "Could not allocate buffer for temporary string\n"); + return (NULL); + } + + strcpy(temp_str, external_info->dir_pathname); + strcat(temp_str, "/"); + strcat(temp_str, dir_entry->d_name); + + err = stat(temp_str, &temp_stat); + if (err == -1) { + fprintf(stderr, + "Cannot stat file (should not happen) - %s\n", + temp_str); + free(temp_str); + return (NULL); + } + + free(temp_str); + + if ((S_ISDIR(temp_stat.st_mode) + && (external_info->requested_file_type == + REQUEST_DIR_ONLY)) + || ((!S_ISDIR(temp_stat.st_mode) + && external_info->requested_file_type == + REQUEST_FILE_ONLY))) { + + /* copy to a temp buffer because dir_entry struct is on the stack */ + + strcpy(external_info->temp_buffer, + dir_entry->d_name); + return (external_info->temp_buffer); + } + } + } + + return (NULL); +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_close_directory + * + * PARAMETERS: dir_handle - Created via acpi_os_open_directory + * + * RETURN: None. + * + * DESCRIPTION: Close the open directory and cleanup. + * + ******************************************************************************/ + +void acpi_os_close_directory(void *dir_handle) +{ + struct external_find_info *external_info = dir_handle; + + /* Close the directory and free allocations */ + + closedir(external_info->dir_ptr); + free(dir_handle); +} diff --git a/tools/power/acpi/os_specific/service_layers/osunixmap.c b/tools/power/acpi/os_specific/service_layers/osunixmap.c new file mode 100644 index 000000000000..99b47b6194a3 --- /dev/null +++ b/tools/power/acpi/os_specific/service_layers/osunixmap.c @@ -0,0 +1,151 @@ +/****************************************************************************** + * + * Module Name: osunixmap - Unix OSL for file mappings + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpidump.h" +#include <unistd.h> +#include <sys/mman.h> +#ifdef _free_BSD +#include <sys/param.h> +#endif + +#define _COMPONENT ACPI_OS_SERVICES +ACPI_MODULE_NAME("osunixmap") + +#ifndef O_BINARY +#define O_BINARY 0 +#endif +#ifdef _free_BSD +#define MMAP_FLAGS MAP_SHARED +#else +#define MMAP_FLAGS MAP_PRIVATE +#endif +#define SYSTEM_MEMORY "/dev/mem" +/******************************************************************************* + * + * FUNCTION: acpi_os_get_page_size + * + * PARAMETERS: None + * + * RETURN: Page size of the platform. + * + * DESCRIPTION: Obtain page size of the platform. + * + ******************************************************************************/ +static acpi_size acpi_os_get_page_size(void) +{ + +#ifdef PAGE_SIZE + return PAGE_SIZE; +#else + return sysconf(_SC_PAGESIZE); +#endif +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_map_memory + * + * PARAMETERS: where - Physical address of memory to be mapped + * length - How much memory to map + * + * RETURN: Pointer to mapped memory. Null on error. + * + * DESCRIPTION: Map physical memory into local address space. + * + *****************************************************************************/ + +void *acpi_os_map_memory(acpi_physical_address where, acpi_size length) +{ + u8 *mapped_memory; + acpi_physical_address offset; + acpi_size page_size; + int fd; + + fd = open(SYSTEM_MEMORY, O_RDONLY | O_BINARY); + if (fd < 0) { + fprintf(stderr, "Cannot open %s\n", SYSTEM_MEMORY); + return (NULL); + } + + /* Align the offset to use mmap */ + + page_size = acpi_os_get_page_size(); + offset = where % page_size; + + /* Map the table header to get the length of the full table */ + + mapped_memory = mmap(NULL, (length + offset), PROT_READ, MMAP_FLAGS, + fd, (where - offset)); + if (mapped_memory == MAP_FAILED) { + fprintf(stderr, "Cannot map %s\n", SYSTEM_MEMORY); + close(fd); + return (NULL); + } + + close(fd); + return (ACPI_CAST8(mapped_memory + offset)); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_unmap_memory + * + * PARAMETERS: where - Logical address of memory to be unmapped + * length - How much memory to unmap + * + * RETURN: None. + * + * DESCRIPTION: Delete a previously created mapping. Where and Length must + * correspond to a previous mapping exactly. + * + *****************************************************************************/ + +void acpi_os_unmap_memory(void *where, acpi_size length) +{ + acpi_physical_address offset; + acpi_size page_size; + + page_size = acpi_os_get_page_size(); + offset = (acpi_physical_address) where % page_size; + munmap((u8 *)where - offset, (length + offset)); +} diff --git a/tools/power/acpi/tools/acpidump/acpidump.c b/tools/power/acpi/tools/acpidump/acpidump.c deleted file mode 100644 index a84553a0e0df..000000000000 --- a/tools/power/acpi/tools/acpidump/acpidump.c +++ /dev/null @@ -1,559 +0,0 @@ -/* - * (c) Alexey Starikovskiy, Intel, 2005-2006. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#ifdef DEFINE_ALTERNATE_TYPES -/* hack to enable building old application with new headers -lenb */ -#define acpi_fadt_descriptor acpi_table_fadt -#define acpi_rsdp_descriptor acpi_table_rsdp -#define DSDT_SIG ACPI_SIG_DSDT -#define FACS_SIG ACPI_SIG_FACS -#define FADT_SIG ACPI_SIG_FADT -#define xfirmware_ctrl Xfacs -#define firmware_ctrl facs - -typedef int s32; -typedef unsigned char u8; -typedef unsigned short u16; -typedef unsigned int u32; -typedef unsigned long long u64; -typedef long long s64; -#endif - -#include <sys/mman.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <getopt.h> - -#include <dirent.h> - -#include <acpi/acconfig.h> -#include <acpi/platform/acenv.h> -#include <acpi/actypes.h> -#include <acpi/actbl.h> - -static inline u8 checksum(u8 * buffer, u32 length) -{ - u8 sum = 0, *i = buffer; - buffer += length; - for (; i < buffer; sum += *(i++)); - return sum; -} - -static unsigned long psz, addr, length; -static int print, connect, skip; -static u8 select_sig[4]; - -static unsigned long read_efi_systab( void ) -{ - char buffer[80]; - unsigned long addr; - FILE *f = fopen("/sys/firmware/efi/systab", "r"); - if (f) { - while (fgets(buffer, 80, f)) { - if (sscanf(buffer, "ACPI20=0x%lx", &addr) == 1) - return addr; - } - fclose(f); - } - return 0; -} - -static u8 *acpi_map_memory(unsigned long where, unsigned length) -{ - unsigned long offset; - u8 *there; - int fd = open("/dev/mem", O_RDONLY); - if (fd < 0) { - fprintf(stderr, "acpi_os_map_memory: cannot open /dev/mem\n"); - exit(1); - } - offset = where % psz; - there = mmap(NULL, length + offset, PROT_READ, MAP_PRIVATE, - fd, where - offset); - close(fd); - if (there == MAP_FAILED) return 0; - return (there + offset); -} - -static void acpi_unmap_memory(u8 * there, unsigned length) -{ - unsigned long offset = (unsigned long)there % psz; - munmap(there - offset, length + offset); -} - -static struct acpi_table_header *acpi_map_table(unsigned long where, char *sig) -{ - unsigned size; - struct acpi_table_header *tbl = (struct acpi_table_header *) - acpi_map_memory(where, sizeof(struct acpi_table_header)); - if (!tbl || (sig && memcmp(sig, tbl->signature, 4))) return 0; - size = tbl->length; - acpi_unmap_memory((u8 *) tbl, sizeof(struct acpi_table_header)); - return (struct acpi_table_header *)acpi_map_memory(where, size); -} - -static void acpi_unmap_table(struct acpi_table_header *tbl) -{ - acpi_unmap_memory((u8 *)tbl, tbl->length); -} - -static struct acpi_rsdp_descriptor *acpi_scan_for_rsdp(u8 *begin, u32 length) -{ - struct acpi_rsdp_descriptor *rsdp; - u8 *i, *end = begin + length; - /* Search from given start address for the requested length */ - for (i = begin; i < end; i += ACPI_RSDP_SCAN_STEP) { - /* The signature and checksum must both be correct */ - if (memcmp((char *)i, "RSD PTR ", 8)) continue; - rsdp = (struct acpi_rsdp_descriptor *)i; - /* Signature matches, check the appropriate checksum */ - if (!checksum((u8 *) rsdp, (rsdp->revision < 2) ? - ACPI_RSDP_CHECKSUM_LENGTH : - ACPI_RSDP_XCHECKSUM_LENGTH)) - /* Checksum valid, we have found a valid RSDP */ - return rsdp; - } - /* Searched entire block, no RSDP was found */ - return 0; -} - -/* - * Output data - */ -static void acpi_show_data(int fd, u8 * data, int size) -{ - char buffer[256]; - int len; - int i, remain = size; - while (remain > 0) { - len = snprintf(buffer, 256, " %04x:", size - remain); - for (i = 0; i < 16 && i < remain; i++) { - len += - snprintf(&buffer[len], 256 - len, " %02x", data[i]); - } - for (; i < 16; i++) { - len += snprintf(&buffer[len], 256 - len, " "); - } - len += snprintf(&buffer[len], 256 - len, " "); - for (i = 0; i < 16 && i < remain; i++) { - buffer[len++] = (isprint(data[i])) ? data[i] : '.'; - } - buffer[len++] = '\n'; - write(fd, buffer, len); - data += 16; - remain -= 16; - } -} - -/* - * Output ACPI table - */ -static void acpi_show_table(int fd, struct acpi_table_header *table, unsigned long addr) -{ - char buff[80]; - int len = snprintf(buff, 80, "%.4s @ %p\n", table->signature, (void *)addr); - write(fd, buff, len); - acpi_show_data(fd, (u8 *) table, table->length); - buff[0] = '\n'; - write(fd, buff, 1); -} - -static void write_table(int fd, struct acpi_table_header *tbl, unsigned long addr) -{ - static int select_done = 0; - if (!select_sig[0]) { - if (print) { - acpi_show_table(fd, tbl, addr); - } else { - write(fd, tbl, tbl->length); - } - } else if (!select_done && !memcmp(select_sig, tbl->signature, 4)) { - if (skip > 0) { - --skip; - return; - } - if (print) { - acpi_show_table(fd, tbl, addr); - } else { - write(fd, tbl, tbl->length); - } - select_done = 1; - } -} - -static void acpi_dump_FADT(int fd, struct acpi_table_header *tbl, unsigned long xaddr) { - struct acpi_fadt_descriptor x; - unsigned long addr; - size_t len = sizeof(struct acpi_fadt_descriptor); - if (len > tbl->length) len = tbl->length; - memcpy(&x, tbl, len); - x.header.length = len; - if (checksum((u8 *)tbl, len)) { - fprintf(stderr, "Wrong checksum for FADT!\n"); - } - if (x.header.length >= 148 && x.Xdsdt) { - addr = (unsigned long)x.Xdsdt; - if (connect) { - x.Xdsdt = lseek(fd, 0, SEEK_CUR); - } - } else if (x.header.length >= 44 && x.dsdt) { - addr = (unsigned long)x.dsdt; - if (connect) { - x.dsdt = lseek(fd, 0, SEEK_CUR); - } - } else { - fprintf(stderr, "No DSDT in FADT!\n"); - goto no_dsdt; - } - tbl = acpi_map_table(addr, DSDT_SIG); - if (!tbl) goto no_dsdt; - if (checksum((u8 *)tbl, tbl->length)) - fprintf(stderr, "Wrong checksum for DSDT!\n"); - write_table(fd, tbl, addr); - acpi_unmap_table(tbl); -no_dsdt: - if (x.header.length >= 140 && x.xfirmware_ctrl) { - addr = (unsigned long)x.xfirmware_ctrl; - if (connect) { - x.xfirmware_ctrl = lseek(fd, 0, SEEK_CUR); - } - } else if (x.header.length >= 40 && x.firmware_ctrl) { - addr = (unsigned long)x.firmware_ctrl; - if (connect) { - x.firmware_ctrl = lseek(fd, 0, SEEK_CUR); - } - } else { - fprintf(stderr, "No FACS in FADT!\n"); - goto no_facs; - } - tbl = acpi_map_table(addr, FACS_SIG); - if (!tbl) goto no_facs; - /* do not checksum FACS */ - write_table(fd, tbl, addr); - acpi_unmap_table(tbl); -no_facs: - write_table(fd, (struct acpi_table_header *)&x, xaddr); -} - -static int acpi_dump_SDT(int fd, struct acpi_rsdp_descriptor *rsdp) -{ - struct acpi_table_header *sdt, *tbl = 0; - int xsdt = 1, i, num; - char *offset; - unsigned long addr; - if (rsdp->revision > 1 && rsdp->xsdt_physical_address) { - tbl = acpi_map_table(rsdp->xsdt_physical_address, "XSDT"); - } - if (!tbl && rsdp->rsdt_physical_address) { - xsdt = 0; - tbl = acpi_map_table(rsdp->rsdt_physical_address, "RSDT"); - } - if (!tbl) return 0; - sdt = malloc(tbl->length); - memcpy(sdt, tbl, tbl->length); - acpi_unmap_table(tbl); - if (checksum((u8 *)sdt, sdt->length)) - fprintf(stderr, "Wrong checksum for %s!\n", (xsdt)?"XSDT":"RSDT"); - num = (sdt->length - sizeof(struct acpi_table_header))/((xsdt)?sizeof(u64):sizeof(u32)); - offset = (char *)sdt + sizeof(struct acpi_table_header); - for (i = 0; i < num; ++i, offset += ((xsdt) ? sizeof(u64) : sizeof(u32))) { - addr = (xsdt) ? (unsigned long)(*(u64 *)offset): - (unsigned long)(*(u32 *)offset); - if (!addr) continue; - tbl = acpi_map_table(addr, 0); - if (!tbl) continue; - if (!memcmp(tbl->signature, FADT_SIG, 4)) { - acpi_dump_FADT(fd, tbl, addr); - } else { - if (checksum((u8 *)tbl, tbl->length)) - fprintf(stderr, "Wrong checksum for generic table!\n"); - write_table(fd, tbl, addr); - } - acpi_unmap_table(tbl); - if (connect) { - if (xsdt) - (*(u64*)offset) = lseek(fd, 0, SEEK_CUR); - else - (*(u32*)offset) = lseek(fd, 0, SEEK_CUR); - } - } - if (xsdt) { - addr = (unsigned long)rsdp->xsdt_physical_address; - if (connect) { - rsdp->xsdt_physical_address = lseek(fd, 0, SEEK_CUR); - } - } else { - addr = (unsigned long)rsdp->rsdt_physical_address; - if (connect) { - rsdp->rsdt_physical_address = lseek(fd, 0, SEEK_CUR); - } - } - write_table(fd, sdt, addr); - free (sdt); - return 1; -} - -#define DYNAMIC_SSDT "/sys/firmware/acpi/tables/dynamic" - -static void acpi_dump_dynamic_SSDT(int fd) -{ - struct stat file_stat; - char filename[256], *ptr; - DIR *tabledir; - struct dirent *entry; - FILE *fp; - int count, readcount, length; - struct acpi_table_header table_header, *ptable; - - if (stat(DYNAMIC_SSDT, &file_stat) == -1) { - /* The directory doesn't exist */ - return; - } - tabledir = opendir(DYNAMIC_SSDT); - if(!tabledir){ - /*can't open the directory */ - return; - } - - while ((entry = readdir(tabledir)) != 0){ - /* skip the file of . /.. */ - if (entry->d_name[0] == '.') - continue; - - sprintf(filename, "%s/%s", DYNAMIC_SSDT, entry->d_name); - fp = fopen(filename, "r"); - if (fp == NULL) { - fprintf(stderr, "Can't open the file of %s\n", - filename); - continue; - } - /* Read the Table header to parse the table length */ - count = fread(&table_header, 1, sizeof(struct acpi_table_header), fp); - if (count < sizeof(table_header)) { - /* the length is lessn than ACPI table header. skip it */ - fclose(fp); - continue; - } - length = table_header.length; - ptr = malloc(table_header.length); - fseek(fp, 0, SEEK_SET); - readcount = 0; - while(!feof(fp) && readcount < length) { - count = fread(ptr + readcount, 1, 256, fp); - readcount += count; - } - fclose(fp); - ptable = (struct acpi_table_header *) ptr; - if (checksum((u8 *) ptable, ptable->length)) - fprintf(stderr, "Wrong checksum " - "for dynamic SSDT table!\n"); - write_table(fd, ptable, 0); - free(ptr); - } - closedir(tabledir); - return; -} - -static void usage(const char *progname) -{ - puts("Usage:"); - printf("%s [--addr 0x1234][--table DSDT][--output filename]" - "[--binary][--length 0x456][--help]\n", progname); - puts("\t--addr 0x1234 or -a 0x1234 -- look for tables at this physical address"); - puts("\t--table DSDT or -t DSDT -- only dump table with DSDT signature"); - puts("\t--output filename or -o filename -- redirect output from stdin to filename"); - puts("\t--binary or -b -- dump data in binary form rather than in hex-dump format"); - puts("\t--length 0x456 or -l 0x456 -- works only with --addr, dump physical memory" - "\n\t\tregion without trying to understand it's contents"); - puts("\t--skip 2 or -s 2 -- skip 2 tables of the given name and output only 3rd one"); - puts("\t--help or -h -- this help message"); - exit(0); -} - -static struct option long_options[] = { - {"addr", 1, 0, 0}, - {"table", 1, 0, 0}, - {"output", 1, 0, 0}, - {"binary", 0, 0, 0}, - {"length", 1, 0, 0}, - {"skip", 1, 0, 0}, - {"help", 0, 0, 0}, - {0, 0, 0, 0} -}; -int main(int argc, char **argv) -{ - int option_index, c, fd; - u8 *raw; - struct acpi_rsdp_descriptor rsdpx, *x = 0; - char *filename = 0; - char buff[80]; - memset(select_sig, 0, 4); - print = 1; - connect = 0; - addr = length = 0; - skip = 0; - while (1) { - option_index = 0; - c = getopt_long(argc, argv, "a:t:o:bl:s:h", - long_options, &option_index); - if (c == -1) - break; - - switch (c) { - case 0: - switch (option_index) { - case 0: - addr = strtoul(optarg, (char **)NULL, 16); - break; - case 1: - memcpy(select_sig, optarg, 4); - break; - case 2: - filename = optarg; - break; - case 3: - print = 0; - break; - case 4: - length = strtoul(optarg, (char **)NULL, 16); - break; - case 5: - skip = strtoul(optarg, (char **)NULL, 10); - break; - case 6: - usage(argv[0]); - exit(0); - } - break; - case 'a': - addr = strtoul(optarg, (char **)NULL, 16); - break; - case 't': - memcpy(select_sig, optarg, 4); - break; - case 'o': - filename = optarg; - break; - case 'b': - print = 0; - break; - case 'l': - length = strtoul(optarg, (char **)NULL, 16); - break; - case 's': - skip = strtoul(optarg, (char **)NULL, 10); - break; - case 'h': - usage(argv[0]); - exit(0); - default: - printf("Unknown option!\n"); - usage(argv[0]); - exit(0); - } - } - - fd = STDOUT_FILENO; - if (filename) { - fd = creat(filename, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); - if (fd < 0) - return fd; - } - - if (!select_sig[0] && !print) { - connect = 1; - } - - psz = sysconf(_SC_PAGESIZE); - if (length && addr) { - /* We know length and address, it means we just want a memory dump */ - if (!(raw = acpi_map_memory(addr, length))) - goto not_found; - write(fd, raw, length); - acpi_unmap_memory(raw, length); - close(fd); - return 0; - } - - length = sizeof(struct acpi_rsdp_descriptor); - if (!addr) { - addr = read_efi_systab(); - if (!addr) { - addr = ACPI_HI_RSDP_WINDOW_BASE; - length = ACPI_HI_RSDP_WINDOW_SIZE; - } - } - - if (!(raw = acpi_map_memory(addr, length)) || - !(x = acpi_scan_for_rsdp(raw, length))) - goto not_found; - - /* Find RSDP and print all found tables */ - memcpy(&rsdpx, x, sizeof(struct acpi_rsdp_descriptor)); - acpi_unmap_memory(raw, length); - if (connect) { - lseek(fd, sizeof(struct acpi_rsdp_descriptor), SEEK_SET); - } - if (!acpi_dump_SDT(fd, &rsdpx)) - goto not_found; - if (connect) { - lseek(fd, 0, SEEK_SET); - write(fd, x, (rsdpx.revision < 2) ? - ACPI_RSDP_CHECKSUM_LENGTH : ACPI_RSDP_XCHECKSUM_LENGTH); - } else if (!select_sig[0] || !memcmp("RSD PTR ", select_sig, 4)) { - addr += (long)x - (long)raw; - length = snprintf(buff, 80, "RSD PTR @ %p\n", (void *)addr); - write(fd, buff, length); - acpi_show_data(fd, (u8 *) & rsdpx, (rsdpx.revision < 2) ? - ACPI_RSDP_CHECKSUM_LENGTH : ACPI_RSDP_XCHECKSUM_LENGTH); - buff[0] = '\n'; - write(fd, buff, 1); - } - acpi_dump_dynamic_SSDT(fd); - close(fd); - return 0; -not_found: - close(fd); - fprintf(stderr, "ACPI tables were not found. If you know location " - "of RSD PTR table (from dmesg, etc), " - "supply it with either --addr or -a option\n"); - return 1; -} diff --git a/tools/power/acpi/tools/acpidump/acpidump.h b/tools/power/acpi/tools/acpidump/acpidump.h new file mode 100644 index 000000000000..46f519597fe5 --- /dev/null +++ b/tools/power/acpi/tools/acpidump/acpidump.h @@ -0,0 +1,130 @@ +/****************************************************************************** + * + * 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); diff --git a/tools/power/acpi/tools/acpidump/apdump.c b/tools/power/acpi/tools/acpidump/apdump.c new file mode 100644 index 000000000000..3cac12378366 --- /dev/null +++ b/tools/power/acpi/tools/acpidump/apdump.c @@ -0,0 +1,451 @@ +/****************************************************************************** + * + * Module Name: apdump - Dump routines for ACPI tables (acpidump) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpidump.h" + +/* Local prototypes */ + +static int +ap_dump_table_buffer(struct acpi_table_header *table, + u32 instance, acpi_physical_address address); + +/****************************************************************************** + * + * FUNCTION: ap_is_valid_header + * + * PARAMETERS: table - Pointer to table to be validated + * + * RETURN: TRUE if the header appears to be valid. FALSE otherwise + * + * DESCRIPTION: Check for a valid ACPI table header + * + ******************************************************************************/ + +u8 ap_is_valid_header(struct acpi_table_header *table) +{ + + if (!ACPI_VALIDATE_RSDP_SIG(table->signature)) { + + /* Make sure signature is all ASCII and a valid ACPI name */ + + if (!acpi_ut_valid_acpi_name(table->signature)) { + fprintf(stderr, + "Table signature (0x%8.8X) is invalid\n", + *(u32 *)table->signature); + return (FALSE); + } + + /* Check for minimum table length */ + + if (table->length < sizeof(struct acpi_table_header)) { + fprintf(stderr, "Table length (0x%8.8X) is invalid\n", + table->length); + return (FALSE); + } + } + + return (TRUE); +} + +/****************************************************************************** + * + * FUNCTION: ap_is_valid_checksum + * + * PARAMETERS: table - Pointer to table to be validated + * + * RETURN: TRUE if the checksum appears to be valid. FALSE otherwise. + * + * DESCRIPTION: Check for a valid ACPI table checksum. + * + ******************************************************************************/ + +u8 ap_is_valid_checksum(struct acpi_table_header *table) +{ + acpi_status status; + struct acpi_table_rsdp *rsdp; + + if (ACPI_VALIDATE_RSDP_SIG(table->signature)) { + /* + * Checksum for RSDP. + * Note: Other checksums are computed during the table dump. + */ + rsdp = ACPI_CAST_PTR(struct acpi_table_rsdp, table); + status = acpi_tb_validate_rsdp(rsdp); + } else { + status = acpi_tb_verify_checksum(table, table->length); + } + + if (ACPI_FAILURE(status)) { + fprintf(stderr, "%4.4s: Warning: wrong checksum in table\n", + table->signature); + } + + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: ap_get_table_length + * + * PARAMETERS: table - Pointer to the table + * + * RETURN: Table length + * + * DESCRIPTION: Obtain table length according to table signature. + * + ******************************************************************************/ + +u32 ap_get_table_length(struct acpi_table_header *table) +{ + struct acpi_table_rsdp *rsdp; + + /* Check if table is valid */ + + if (!ap_is_valid_header(table)) { + return (0); + } + + if (ACPI_VALIDATE_RSDP_SIG(table->signature)) { + rsdp = ACPI_CAST_PTR(struct acpi_table_rsdp, table); + return (rsdp->length); + } + + /* Normal ACPI table */ + + return (table->length); +} + +/****************************************************************************** + * + * FUNCTION: ap_dump_table_buffer + * + * PARAMETERS: table - ACPI table to be dumped + * instance - ACPI table instance no. to be dumped + * address - Physical address of the table + * + * RETURN: None + * + * DESCRIPTION: Dump an ACPI table in standard ASCII hex format, with a + * header that is compatible with the acpi_xtract utility. + * + ******************************************************************************/ + +static int +ap_dump_table_buffer(struct acpi_table_header *table, + u32 instance, acpi_physical_address address) +{ + u32 table_length; + + table_length = ap_get_table_length(table); + + /* Print only the header if requested */ + + if (gbl_summary_mode) { + acpi_tb_print_table_header(address, table); + return (0); + } + + /* Dump to binary file if requested */ + + if (gbl_binary_mode) { + return (ap_write_to_binary_file(table, instance)); + } + + /* + * Dump the table with header for use with acpixtract utility. + * Note: simplest to just always emit a 64-bit address. acpi_xtract + * utility can handle this. + */ + printf("%4.4s @ 0x%8.8X%8.8X\n", table->signature, + ACPI_FORMAT_UINT64(address)); + + acpi_ut_dump_buffer(ACPI_CAST_PTR(u8, table), table_length, + DB_BYTE_DISPLAY, 0); + printf("\n"); + return (0); +} + +/****************************************************************************** + * + * FUNCTION: ap_dump_all_tables + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Get all tables from the RSDT/XSDT (or at least all of the + * tables that we can possibly get). + * + ******************************************************************************/ + +int ap_dump_all_tables(void) +{ + struct acpi_table_header *table; + u32 instance = 0; + acpi_physical_address address; + acpi_status status; + int table_status; + u32 i; + + /* Get and dump all available ACPI tables */ + + for (i = 0; i < AP_MAX_ACPI_FILES; i++) { + status = + acpi_os_get_table_by_index(i, &table, &instance, &address); + if (ACPI_FAILURE(status)) { + + /* AE_LIMIT means that no more tables are available */ + + if (status == AE_LIMIT) { + return (0); + } else if (i == 0) { + fprintf(stderr, + "Could not get ACPI tables, %s\n", + acpi_format_exception(status)); + return (-1); + } else { + fprintf(stderr, + "Could not get ACPI table at index %u, %s\n", + i, acpi_format_exception(status)); + continue; + } + } + + table_status = ap_dump_table_buffer(table, instance, address); + free(table); + + if (table_status) { + break; + } + } + + /* Something seriously bad happened if the loop terminates here */ + + return (-1); +} + +/****************************************************************************** + * + * FUNCTION: ap_dump_table_by_address + * + * PARAMETERS: ascii_address - Address for requested ACPI table + * + * RETURN: Status + * + * DESCRIPTION: Get an ACPI table via a physical address and dump it. + * + ******************************************************************************/ + +int ap_dump_table_by_address(char *ascii_address) +{ + acpi_physical_address address; + struct acpi_table_header *table; + acpi_status status; + int table_status; + u64 long_address; + + /* Convert argument to an integer physical address */ + + status = acpi_ut_strtoul64(ascii_address, 0, &long_address); + if (ACPI_FAILURE(status)) { + fprintf(stderr, "%s: Could not convert to a physical address\n", + ascii_address); + return (-1); + } + + address = (acpi_physical_address) long_address; + status = acpi_os_get_table_by_address(address, &table); + if (ACPI_FAILURE(status)) { + fprintf(stderr, "Could not get table at 0x%8.8X%8.8X, %s\n", + ACPI_FORMAT_UINT64(address), + acpi_format_exception(status)); + return (-1); + } + + table_status = ap_dump_table_buffer(table, 0, address); + free(table); + return (table_status); +} + +/****************************************************************************** + * + * FUNCTION: ap_dump_table_by_name + * + * PARAMETERS: signature - Requested ACPI table signature + * + * RETURN: Status + * + * DESCRIPTION: Get an ACPI table via a signature and dump it. Handles + * multiple tables with the same signature (SSDTs). + * + ******************************************************************************/ + +int ap_dump_table_by_name(char *signature) +{ + char local_signature[ACPI_NAME_SIZE + 1]; + u32 instance; + struct acpi_table_header *table; + acpi_physical_address address; + acpi_status status; + int table_status; + + if (strlen(signature) != ACPI_NAME_SIZE) { + fprintf(stderr, + "Invalid table signature [%s]: must be exactly 4 characters\n", + signature); + return (-1); + } + + /* Table signatures are expected to be uppercase */ + + strcpy(local_signature, signature); + acpi_ut_strupr(local_signature); + + /* To be friendly, handle tables whose signatures do not match the name */ + + if (ACPI_COMPARE_NAME(local_signature, "FADT")) { + strcpy(local_signature, ACPI_SIG_FADT); + } else if (ACPI_COMPARE_NAME(local_signature, "MADT")) { + strcpy(local_signature, ACPI_SIG_MADT); + } + + /* Dump all instances of this signature (to handle multiple SSDTs) */ + + for (instance = 0; instance < AP_MAX_ACPI_FILES; instance++) { + status = acpi_os_get_table_by_name(local_signature, instance, + &table, &address); + if (ACPI_FAILURE(status)) { + + /* AE_LIMIT means that no more tables are available */ + + if (status == AE_LIMIT) { + return (0); + } + + fprintf(stderr, + "Could not get ACPI table with signature [%s], %s\n", + local_signature, acpi_format_exception(status)); + return (-1); + } + + table_status = ap_dump_table_buffer(table, instance, address); + free(table); + + if (table_status) { + break; + } + } + + /* Something seriously bad happened if the loop terminates here */ + + return (-1); +} + +/****************************************************************************** + * + * FUNCTION: ap_dump_table_from_file + * + * PARAMETERS: pathname - File containing the binary ACPI table + * + * RETURN: Status + * + * DESCRIPTION: Dump an ACPI table from a binary file + * + ******************************************************************************/ + +int ap_dump_table_from_file(char *pathname) +{ + struct acpi_table_header *table; + u32 file_size = 0; + int table_status = -1; + + /* Get the entire ACPI table from the file */ + + table = ap_get_table_from_file(pathname, &file_size); + if (!table) { + return (-1); + } + + /* File must be at least as long as the table length */ + + if (table->length > file_size) { + fprintf(stderr, + "Table length (0x%X) is too large for input file (0x%X) %s\n", + table->length, file_size, pathname); + goto exit; + } + + if (gbl_verbose_mode) { + fprintf(stderr, + "Input file: %s contains table [%4.4s], 0x%X (%u) bytes\n", + pathname, table->signature, file_size, file_size); + } + + table_status = ap_dump_table_buffer(table, 0, 0); + +exit: + free(table); + return (table_status); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os* print functions + * + * DESCRIPTION: Used for linkage with ACPICA modules + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE acpi_os_printf(const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + vfprintf(stdout, fmt, args); + va_end(args); +} + +void acpi_os_vprintf(const char *fmt, va_list args) +{ + vfprintf(stdout, fmt, args); +} diff --git a/tools/power/acpi/tools/acpidump/apfiles.c b/tools/power/acpi/tools/acpidump/apfiles.c new file mode 100644 index 000000000000..4488accc010b --- /dev/null +++ b/tools/power/acpi/tools/acpidump/apfiles.c @@ -0,0 +1,228 @@ +/****************************************************************************** + * + * Module Name: apfiles - File-related functions for acpidump utility + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "acpidump.h" +#include "acapps.h" + +/****************************************************************************** + * + * FUNCTION: ap_open_output_file + * + * PARAMETERS: pathname - Output filename + * + * RETURN: Open file handle + * + * DESCRIPTION: Open a text output file for acpidump. Checks if file already + * exists. + * + ******************************************************************************/ + +int ap_open_output_file(char *pathname) +{ + struct stat stat_info; + FILE *file; + + /* If file exists, prompt for overwrite */ + + if (!stat(pathname, &stat_info)) { + fprintf(stderr, + "Target path already exists, overwrite? [y|n] "); + + if (getchar() != 'y') { + return (-1); + } + } + + /* Point stdout to the file */ + + file = freopen(pathname, "w", stdout); + if (!file) { + perror("Could not open output file"); + return (-1); + } + + /* Save the file and path */ + + gbl_output_file = file; + gbl_output_filename = pathname; + return (0); +} + +/****************************************************************************** + * + * FUNCTION: ap_write_to_binary_file + * + * PARAMETERS: table - ACPI table to be written + * instance - ACPI table instance no. to be written + * + * RETURN: Status + * + * DESCRIPTION: Write an ACPI table to a binary file. Builds the output + * filename from the table signature. + * + ******************************************************************************/ + +int ap_write_to_binary_file(struct acpi_table_header *table, u32 instance) +{ + char filename[ACPI_NAME_SIZE + 16]; + char instance_str[16]; + FILE *file; + size_t actual; + u32 table_length; + + /* Obtain table length */ + + table_length = ap_get_table_length(table); + + /* Construct lower-case filename from the table local signature */ + + if (ACPI_VALIDATE_RSDP_SIG(table->signature)) { + ACPI_MOVE_NAME(filename, ACPI_RSDP_NAME); + } else { + ACPI_MOVE_NAME(filename, table->signature); + } + filename[0] = (char)ACPI_TOLOWER(filename[0]); + filename[1] = (char)ACPI_TOLOWER(filename[1]); + filename[2] = (char)ACPI_TOLOWER(filename[2]); + filename[3] = (char)ACPI_TOLOWER(filename[3]); + filename[ACPI_NAME_SIZE] = 0; + + /* Handle multiple SSDts - create different filenames for each */ + + if (instance > 0) { + sprintf(instance_str, "%u", instance); + strcat(filename, instance_str); + } + + strcat(filename, ACPI_TABLE_FILE_SUFFIX); + + if (gbl_verbose_mode) { + fprintf(stderr, + "Writing [%4.4s] to binary file: %s 0x%X (%u) bytes\n", + table->signature, filename, table->length, + table->length); + } + + /* Open the file and dump the entire table in binary mode */ + + file = fopen(filename, "wb"); + if (!file) { + perror("Could not open output file"); + return (-1); + } + + actual = fwrite(table, 1, table_length, file); + if (actual != table_length) { + perror("Error writing binary output file"); + fclose(file); + return (-1); + } + + fclose(file); + return (0); +} + +/****************************************************************************** + * + * FUNCTION: ap_get_table_from_file + * + * PARAMETERS: pathname - File containing the binary ACPI table + * out_file_size - Where the file size is returned + * + * RETURN: Buffer containing the ACPI table. NULL on error. + * + * DESCRIPTION: Open a file and read it entirely into a new buffer + * + ******************************************************************************/ + +struct acpi_table_header *ap_get_table_from_file(char *pathname, + u32 *out_file_size) +{ + struct acpi_table_header *buffer = NULL; + FILE *file; + u32 file_size; + size_t actual; + + /* Must use binary mode */ + + file = fopen(pathname, "rb"); + if (!file) { + perror("Could not open input file"); + return (NULL); + } + + /* Need file size to allocate a buffer */ + + file_size = cm_get_file_size(file); + if (file_size == ACPI_UINT32_MAX) { + fprintf(stderr, + "Could not get input file size: %s\n", pathname); + goto cleanup; + } + + /* Allocate a buffer for the entire file */ + + buffer = calloc(1, file_size); + if (!buffer) { + fprintf(stderr, + "Could not allocate file buffer of size: %u\n", + file_size); + goto cleanup; + } + + /* Read the entire file */ + + actual = fread(buffer, 1, file_size, file); + if (actual != file_size) { + fprintf(stderr, "Could not read input file: %s\n", pathname); + free(buffer); + buffer = NULL; + goto cleanup; + } + + *out_file_size = file_size; + +cleanup: + fclose(file); + return (buffer); +} diff --git a/tools/power/acpi/tools/acpidump/apmain.c b/tools/power/acpi/tools/acpidump/apmain.c new file mode 100644 index 000000000000..51e8d638db18 --- /dev/null +++ b/tools/power/acpi/tools/acpidump/apmain.c @@ -0,0 +1,351 @@ +/****************************************************************************** + * + * 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); +} |