From e09b41010ba33a20a87472ee821fa407a5b8da36 Mon Sep 17 00:00:00 2001 From: José Pekkarinen Date: Mon, 11 Apr 2016 10:41:07 +0300 Subject: These changes are the raw update to linux-4.4.6-rt14. Kernel sources are taken from kernel.org, and rt patch from the rt wiki download page. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During the rebasing, the following patch collided: Force tick interrupt and get rid of softirq magic(I70131fb85). Collisions have been removed because its logic was found on the source already. Change-Id: I7f57a4081d9deaa0d9ccfc41a6c8daccdee3b769 Signed-off-by: José Pekkarinen --- kernel/drivers/acpi/acpica/Makefile | 20 +- kernel/drivers/acpi/acpica/acapps.h | 2 +- kernel/drivers/acpi/acpica/accommon.h | 3 + kernel/drivers/acpi/acpica/acdebug.h | 36 +- kernel/drivers/acpi/acpica/acdispat.h | 8 + kernel/drivers/acpi/acpica/acglobal.h | 26 +- kernel/drivers/acpi/acpica/acinterp.h | 26 +- kernel/drivers/acpi/acpica/aclocal.h | 65 +- kernel/drivers/acpi/acpica/acmacros.h | 9 + kernel/drivers/acpi/acpica/acnamesp.h | 18 +- kernel/drivers/acpi/acpica/acobject.h | 2 + kernel/drivers/acpi/acpica/acopcode.h | 4 +- kernel/drivers/acpi/acpica/acparser.h | 11 +- kernel/drivers/acpi/acpica/acpredef.h | 45 +- kernel/drivers/acpi/acpica/acstruct.h | 3 +- kernel/drivers/acpi/acpica/actables.h | 18 +- kernel/drivers/acpi/acpica/acutils.h | 91 +-- kernel/drivers/acpi/acpica/amlcode.h | 11 +- kernel/drivers/acpi/acpica/dbcmds.c | 1187 ++++++++++++++++++++++++++++++ kernel/drivers/acpi/acpica/dbconvert.c | 484 ++++++++++++ kernel/drivers/acpi/acpica/dbdisply.c | 1108 ++++++++++++++++++++++++++++ kernel/drivers/acpi/acpica/dbexec.c | 764 +++++++++++++++++++ kernel/drivers/acpi/acpica/dbfileio.c | 256 +++++++ kernel/drivers/acpi/acpica/dbhistry.c | 239 ++++++ kernel/drivers/acpi/acpica/dbinput.c | 1267 ++++++++++++++++++++++++++++++++ kernel/drivers/acpi/acpica/dbmethod.c | 369 ++++++++++ kernel/drivers/acpi/acpica/dbnames.c | 947 ++++++++++++++++++++++++ kernel/drivers/acpi/acpica/dbobject.c | 533 ++++++++++++++ kernel/drivers/acpi/acpica/dbstats.c | 546 ++++++++++++++ kernel/drivers/acpi/acpica/dbtest.c | 1057 ++++++++++++++++++++++++++ kernel/drivers/acpi/acpica/dbutils.c | 457 ++++++++++++ kernel/drivers/acpi/acpica/dbxface.c | 513 +++++++++++++ kernel/drivers/acpi/acpica/dsargs.c | 4 +- kernel/drivers/acpi/acpica/dscontrol.c | 2 +- kernel/drivers/acpi/acpica/dsdebug.c | 231 ++++++ kernel/drivers/acpi/acpica/dsfield.c | 2 +- kernel/drivers/acpi/acpica/dsinit.c | 22 +- kernel/drivers/acpi/acpica/dsmethod.c | 40 +- kernel/drivers/acpi/acpica/dsobject.c | 7 +- kernel/drivers/acpi/acpica/dsopcode.c | 31 +- kernel/drivers/acpi/acpica/dsutils.c | 4 +- kernel/drivers/acpi/acpica/dswload.c | 19 +- kernel/drivers/acpi/acpica/dswload2.c | 2 +- kernel/drivers/acpi/acpica/evgpeinit.c | 2 +- kernel/drivers/acpi/acpica/evregion.c | 22 +- kernel/drivers/acpi/acpica/evxface.c | 2 +- kernel/drivers/acpi/acpica/evxfevnt.c | 2 +- kernel/drivers/acpi/acpica/exconfig.c | 10 +- kernel/drivers/acpi/acpica/exconvrt.c | 10 +- kernel/drivers/acpi/acpica/excreate.c | 1 + kernel/drivers/acpi/acpica/exdebug.c | 366 ++++++++- kernel/drivers/acpi/acpica/exdump.c | 14 +- kernel/drivers/acpi/acpica/exfield.c | 2 +- kernel/drivers/acpi/acpica/exfldio.c | 52 +- kernel/drivers/acpi/acpica/exmisc.c | 36 +- kernel/drivers/acpi/acpica/exnames.c | 2 +- kernel/drivers/acpi/acpica/exoparg2.c | 8 +- kernel/drivers/acpi/acpica/exoparg3.c | 4 +- kernel/drivers/acpi/acpica/exregion.c | 9 +- kernel/drivers/acpi/acpica/exresnte.c | 2 +- kernel/drivers/acpi/acpica/exresolv.c | 17 +- kernel/drivers/acpi/acpica/exresop.c | 2 + kernel/drivers/acpi/acpica/exstore.c | 120 ++- kernel/drivers/acpi/acpica/exstoren.c | 5 +- kernel/drivers/acpi/acpica/exstorob.c | 18 +- kernel/drivers/acpi/acpica/exutils.c | 32 + kernel/drivers/acpi/acpica/hwpci.c | 9 +- kernel/drivers/acpi/acpica/hwxfsleep.c | 114 ++- kernel/drivers/acpi/acpica/nsaccess.c | 16 +- kernel/drivers/acpi/acpica/nsconvert.c | 10 +- kernel/drivers/acpi/acpica/nsdump.c | 8 +- kernel/drivers/acpi/acpica/nseval.c | 11 +- kernel/drivers/acpi/acpica/nsinit.c | 4 +- kernel/drivers/acpi/acpica/nsload.c | 16 +- kernel/drivers/acpi/acpica/nsnames.c | 275 ++++--- kernel/drivers/acpi/acpica/nsparse.c | 43 +- kernel/drivers/acpi/acpica/nspredef.c | 2 +- kernel/drivers/acpi/acpica/nsprepkg.c | 13 + kernel/drivers/acpi/acpica/nsrepair.c | 2 +- kernel/drivers/acpi/acpica/nsrepair2.c | 2 +- kernel/drivers/acpi/acpica/nssearch.c | 37 +- kernel/drivers/acpi/acpica/nsutils.c | 22 +- kernel/drivers/acpi/acpica/nsxfeval.c | 5 +- kernel/drivers/acpi/acpica/nsxfname.c | 37 +- kernel/drivers/acpi/acpica/psargs.c | 26 +- kernel/drivers/acpi/acpica/psloop.c | 32 +- kernel/drivers/acpi/acpica/psobject.c | 17 +- kernel/drivers/acpi/acpica/psopinfo.c | 3 - kernel/drivers/acpi/acpica/psparse.c | 14 +- kernel/drivers/acpi/acpica/pstree.c | 2 - kernel/drivers/acpi/acpica/psutils.c | 17 +- kernel/drivers/acpi/acpica/psxface.c | 123 +--- kernel/drivers/acpi/acpica/rscreate.c | 9 +- kernel/drivers/acpi/acpica/rsdump.c | 3 - kernel/drivers/acpi/acpica/rsmisc.c | 8 +- kernel/drivers/acpi/acpica/rsutils.c | 15 +- kernel/drivers/acpi/acpica/rsxface.c | 12 +- kernel/drivers/acpi/acpica/tbdata.c | 8 +- kernel/drivers/acpi/acpica/tbfadt.c | 22 +- kernel/drivers/acpi/acpica/tbfind.c | 36 +- kernel/drivers/acpi/acpica/tbinstal.c | 47 +- kernel/drivers/acpi/acpica/tbprint.c | 10 +- kernel/drivers/acpi/acpica/tbutils.c | 102 +-- kernel/drivers/acpi/acpica/tbxface.c | 17 +- kernel/drivers/acpi/acpica/tbxfload.c | 97 ++- kernel/drivers/acpi/acpica/utalloc.c | 6 +- kernel/drivers/acpi/acpica/utbuffer.c | 4 +- kernel/drivers/acpi/acpica/utcache.c | 6 +- kernel/drivers/acpi/acpica/utcopy.c | 42 +- kernel/drivers/acpi/acpica/utdebug.c | 35 +- kernel/drivers/acpi/acpica/utdecode.c | 21 +- kernel/drivers/acpi/acpica/utdelete.c | 3 + kernel/drivers/acpi/acpica/utfileio.c | 15 +- kernel/drivers/acpi/acpica/utglobal.c | 13 +- kernel/drivers/acpi/acpica/uthex.c | 4 +- kernel/drivers/acpi/acpica/utids.c | 100 ++- kernel/drivers/acpi/acpica/utinit.c | 18 +- kernel/drivers/acpi/acpica/utmisc.c | 13 +- kernel/drivers/acpi/acpica/utmutex.c | 21 + kernel/drivers/acpi/acpica/utnonansi.c | 380 ++++++++++ kernel/drivers/acpi/acpica/utosi.c | 9 +- kernel/drivers/acpi/acpica/utpredef.c | 4 +- kernel/drivers/acpi/acpica/utprint.c | 6 +- kernel/drivers/acpi/acpica/utstring.c | 345 +-------- kernel/drivers/acpi/acpica/uttrack.c | 8 +- kernel/drivers/acpi/acpica/utxface.c | 39 +- kernel/drivers/acpi/acpica/utxferror.c | 11 +- kernel/drivers/acpi/acpica/utxfinit.c | 11 - 128 files changed, 12255 insertions(+), 1332 deletions(-) create mode 100644 kernel/drivers/acpi/acpica/dbcmds.c create mode 100644 kernel/drivers/acpi/acpica/dbconvert.c create mode 100644 kernel/drivers/acpi/acpica/dbdisply.c create mode 100644 kernel/drivers/acpi/acpica/dbexec.c create mode 100644 kernel/drivers/acpi/acpica/dbfileio.c create mode 100644 kernel/drivers/acpi/acpica/dbhistry.c create mode 100644 kernel/drivers/acpi/acpica/dbinput.c create mode 100644 kernel/drivers/acpi/acpica/dbmethod.c create mode 100644 kernel/drivers/acpi/acpica/dbnames.c create mode 100644 kernel/drivers/acpi/acpica/dbobject.c create mode 100644 kernel/drivers/acpi/acpica/dbstats.c create mode 100644 kernel/drivers/acpi/acpica/dbtest.c create mode 100644 kernel/drivers/acpi/acpica/dbutils.c create mode 100644 kernel/drivers/acpi/acpica/dbxface.c create mode 100644 kernel/drivers/acpi/acpica/dsdebug.c create mode 100644 kernel/drivers/acpi/acpica/utnonansi.c (limited to 'kernel/drivers/acpi/acpica') diff --git a/kernel/drivers/acpi/acpica/Makefile b/kernel/drivers/acpi/acpica/Makefile index c1a963581..885936f79 100644 --- a/kernel/drivers/acpi/acpica/Makefile +++ b/kernel/drivers/acpi/acpica/Makefile @@ -11,6 +11,7 @@ obj-y += acpi.o acpi-y := \ dsargs.o \ dscontrol.o \ + dsdebug.o \ dsfield.o \ dsinit.o \ dsmethod.o \ @@ -122,7 +123,6 @@ acpi-y += \ rsaddr.o \ rscalc.o \ rscreate.o \ - rsdump.o \ rsdumpinfo.o \ rsinfo.o \ rsio.o \ @@ -164,6 +164,7 @@ acpi-y += \ utmath.o \ utmisc.o \ utmutex.o \ + utnonansi.o \ utobject.o \ utosi.o \ utownerid.o \ @@ -176,7 +177,24 @@ acpi-y += \ utxferror.o \ utxfmutex.o +acpi-$(CONFIG_ACPI_DEBUGGER) += \ + dbcmds.o \ + dbconvert.o \ + dbdisply.o \ + dbexec.o \ + dbhistry.o \ + dbinput.o \ + dbmethod.o \ + dbnames.o \ + dbobject.o \ + dbstats.o \ + dbutils.o \ + dbxface.o \ + rsdump.o \ + acpi-$(ACPI_FUTURE_USAGE) += \ + dbfileio.o \ + dbtest.o \ utcache.o \ utfileio.o \ utprint.o \ diff --git a/kernel/drivers/acpi/acpica/acapps.h b/kernel/drivers/acpi/acpica/acapps.h index e9f0833e8..e4cc48fbf 100644 --- a/kernel/drivers/acpi/acpica/acapps.h +++ b/kernel/drivers/acpi/acpica/acapps.h @@ -88,7 +88,7 @@ acpi_os_printf (" %-18s%s\n", name, description); #define FILE_SUFFIX_DISASSEMBLY "dsl" -#define ACPI_TABLE_FILE_SUFFIX ".dat" +#define FILE_SUFFIX_BINARY_TABLE ".dat" /* Needs the dot */ /* * getopt diff --git a/kernel/drivers/acpi/acpica/accommon.h b/kernel/drivers/acpi/acpica/accommon.h index 853aa2dbd..a8d8092ee 100644 --- a/kernel/drivers/acpi/acpica/accommon.h +++ b/kernel/drivers/acpi/acpica/accommon.h @@ -59,5 +59,8 @@ #include "acglobal.h" /* All global variables */ #include "achware.h" /* Hardware defines and interfaces */ #include "acutils.h" /* Utility interfaces */ +#ifndef ACPI_USE_SYSTEM_CLIBRARY +#include "acclib.h" /* C library interfaces */ +#endif /* !ACPI_USE_SYSTEM_CLIBRARY */ #endif /* __ACCOMMON_H__ */ diff --git a/kernel/drivers/acpi/acpica/acdebug.h b/kernel/drivers/acpi/acpica/acdebug.h index 4169bb87a..c928ba494 100644 --- a/kernel/drivers/acpi/acpica/acdebug.h +++ b/kernel/drivers/acpi/acpica/acdebug.h @@ -44,6 +44,12 @@ #ifndef __ACDEBUG_H__ #define __ACDEBUG_H__ +/* The debugger is used in conjunction with the disassembler most of time */ + +#ifdef ACPI_DISASSEMBLER +#include "acdisasm.h" +#endif + #define ACPI_DEBUG_BUFFER_SIZE 0x4000 /* 16K buffer for return objects */ struct acpi_db_command_info { @@ -67,9 +73,6 @@ struct acpi_db_execute_walk { }; #define PARAM_LIST(pl) pl -#define DBTEST_OUTPUT_LEVEL(lvl) if (acpi_gbl_db_opt_verbose) -#define VERBOSE_PRINT(fp) DBTEST_OUTPUT_LEVEL(lvl) {\ - acpi_os_printf PARAM_LIST(fp);} #define EX_NO_SINGLE_STEP 1 #define EX_SINGLE_STEP 2 @@ -77,10 +80,6 @@ struct acpi_db_execute_walk { /* * dbxface - external debugger interfaces */ -acpi_status acpi_db_initialize(void); - -void acpi_db_terminate(void); - acpi_status acpi_db_single_step(struct acpi_walk_state *walk_state, union acpi_parse_object *op, u32 op_type); @@ -102,6 +101,8 @@ void acpi_db_display_interfaces(char *action_arg, char *interface_name_arg); acpi_status acpi_db_sleep(char *object_arg); +void acpi_db_trace(char *enable_arg, char *method_arg, char *once_arg); + void acpi_db_display_locks(void); void acpi_db_display_resources(char *object_arg); @@ -231,7 +232,9 @@ void acpi_db_open_debug_file(char *name); acpi_status acpi_db_load_acpi_table(char *filename); acpi_status -acpi_db_get_table_from_file(char *filename, struct acpi_table_header **table); +acpi_db_get_table_from_file(char *filename, + struct acpi_table_header **table, + u8 must_be_aml_table); /* * dbhistry - debugger HISTORY command @@ -259,6 +262,23 @@ acpi_status acpi_db_user_commands(char prompt, union acpi_parse_object *op); char *acpi_db_get_next_token(char *string, char **next, acpi_object_type * return_type); +/* + * dbobject + */ +void acpi_db_decode_internal_object(union acpi_operand_object *obj_desc); + +void +acpi_db_display_internal_object(union acpi_operand_object *obj_desc, + struct acpi_walk_state *walk_state); + +void acpi_db_decode_arguments(struct acpi_walk_state *walk_state); + +void acpi_db_decode_locals(struct acpi_walk_state *walk_state); + +void +acpi_db_dump_method_info(acpi_status status, + struct acpi_walk_state *walk_state); + /* * dbstats - Generation and display of ACPI table statistics */ diff --git a/kernel/drivers/acpi/acpica/acdispat.h b/kernel/drivers/acpi/acpica/acdispat.h index 408f04bca..7094dc89e 100644 --- a/kernel/drivers/acpi/acpica/acdispat.h +++ b/kernel/drivers/acpi/acpica/acdispat.h @@ -354,4 +354,12 @@ acpi_status acpi_ds_result_push(union acpi_operand_object *object, struct acpi_walk_state *walk_state); +/* + * dsdebug - parser debugging routines + */ +void +acpi_ds_dump_method_stack(acpi_status status, + struct acpi_walk_state *walk_state, + union acpi_parse_object *op); + #endif /* _ACDISPAT_H_ */ diff --git a/kernel/drivers/acpi/acpica/acglobal.h b/kernel/drivers/acpi/acpica/acglobal.h index 166ee9554..941497f31 100644 --- a/kernel/drivers/acpi/acpica/acglobal.h +++ b/kernel/drivers/acpi/acpica/acglobal.h @@ -58,6 +58,10 @@ ACPI_GLOBAL(struct acpi_table_list, acpi_gbl_root_table_list); ACPI_GLOBAL(struct acpi_table_header *, acpi_gbl_DSDT); ACPI_GLOBAL(struct acpi_table_header, acpi_gbl_original_dsdt_header); +ACPI_INIT_GLOBAL(u32, acpi_gbl_dsdt_index, ACPI_INVALID_TABLE_INDEX); +ACPI_INIT_GLOBAL(u32, acpi_gbl_facs_index, ACPI_INVALID_TABLE_INDEX); +ACPI_INIT_GLOBAL(u32, acpi_gbl_xfacs_index, ACPI_INVALID_TABLE_INDEX); +ACPI_INIT_GLOBAL(u32, acpi_gbl_fadt_index, ACPI_INVALID_TABLE_INDEX); #if (!ACPI_REDUCED_HARDWARE) ACPI_GLOBAL(struct acpi_table_facs *, acpi_gbl_FACS); @@ -233,6 +237,10 @@ ACPI_INIT_GLOBAL(u32, acpi_gbl_nesting_level, 0); ACPI_GLOBAL(struct acpi_thread_state *, acpi_gbl_current_walk_list); +/* Maximum number of While() loop iterations before forced abort */ + +ACPI_GLOBAL(u16, acpi_gbl_max_loop_iterations); + /* Control method single step flag */ ACPI_GLOBAL(u8, acpi_gbl_cm_single_step); @@ -288,8 +296,6 @@ ACPI_GLOBAL(u32, acpi_fixed_event_count[ACPI_NUM_FIXED_EVENTS]); ACPI_GLOBAL(u32, acpi_gbl_original_dbg_level); ACPI_GLOBAL(u32, acpi_gbl_original_dbg_layer); -ACPI_GLOBAL(u32, acpi_gbl_trace_dbg_level); -ACPI_GLOBAL(u32, acpi_gbl_trace_dbg_layer); /***************************************************************************** * @@ -307,9 +313,10 @@ ACPI_INIT_GLOBAL(u8, acpi_gbl_no_resource_disassembly, FALSE); ACPI_INIT_GLOBAL(u8, acpi_gbl_ignore_noop_operator, FALSE); ACPI_INIT_GLOBAL(u8, acpi_gbl_cstyle_disassembly, TRUE); ACPI_INIT_GLOBAL(u8, acpi_gbl_force_aml_disassembly, FALSE); +ACPI_INIT_GLOBAL(u8, acpi_gbl_dm_opt_verbose, TRUE); -ACPI_GLOBAL(u8, acpi_gbl_db_opt_disasm); -ACPI_GLOBAL(u8, acpi_gbl_db_opt_verbose); +ACPI_GLOBAL(u8, acpi_gbl_dm_opt_disasm); +ACPI_GLOBAL(u8, acpi_gbl_dm_opt_listing); ACPI_GLOBAL(u8, acpi_gbl_num_external_methods); ACPI_GLOBAL(u32, acpi_gbl_resolved_external_methods); ACPI_GLOBAL(struct acpi_external_list *, acpi_gbl_external_list); @@ -318,9 +325,9 @@ ACPI_GLOBAL(struct acpi_external_file *, acpi_gbl_external_file_list); #ifdef ACPI_DEBUGGER -ACPI_INIT_GLOBAL(u8, acpi_gbl_db_terminate_threads, FALSE); ACPI_INIT_GLOBAL(u8, acpi_gbl_abort_method, FALSE); ACPI_INIT_GLOBAL(u8, acpi_gbl_method_executing, FALSE); +ACPI_INIT_GLOBAL(acpi_thread_id, acpi_gbl_db_thread_id, ACPI_INVALID_THREAD_ID); ACPI_GLOBAL(u8, acpi_gbl_db_opt_no_ini_methods); ACPI_GLOBAL(u8, acpi_gbl_db_opt_no_region_support); @@ -330,6 +337,8 @@ ACPI_GLOBAL(char *, acpi_gbl_db_filename); ACPI_GLOBAL(u32, acpi_gbl_db_debug_level); ACPI_GLOBAL(u32, acpi_gbl_db_console_debug_level); ACPI_GLOBAL(struct acpi_namespace_node *, acpi_gbl_db_scope_node); +ACPI_GLOBAL(u8, acpi_gbl_db_terminate_loop); +ACPI_GLOBAL(u8, acpi_gbl_db_threads_terminated); ACPI_GLOBAL(char *, acpi_gbl_db_args[ACPI_DEBUGGER_MAX_ARGS]); ACPI_GLOBAL(acpi_object_type, acpi_gbl_db_arg_types[ACPI_DEBUGGER_MAX_ARGS]); @@ -344,13 +353,16 @@ ACPI_GLOBAL(char, acpi_gbl_db_debug_filename[ACPI_DB_LINE_BUFFER_SIZE]); /* * Statistic globals */ -ACPI_GLOBAL(u16, acpi_gbl_obj_type_count[ACPI_TYPE_NS_NODE_MAX + 1]); -ACPI_GLOBAL(u16, acpi_gbl_node_type_count[ACPI_TYPE_NS_NODE_MAX + 1]); +ACPI_GLOBAL(u16, acpi_gbl_obj_type_count[ACPI_TOTAL_TYPES]); +ACPI_GLOBAL(u16, acpi_gbl_node_type_count[ACPI_TOTAL_TYPES]); ACPI_GLOBAL(u16, acpi_gbl_obj_type_count_misc); 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(acpi_mutex, acpi_gbl_db_command_ready); +ACPI_GLOBAL(acpi_mutex, acpi_gbl_db_command_complete); + #endif /* ACPI_DEBUGGER */ /***************************************************************************** diff --git a/kernel/drivers/acpi/acpica/acinterp.h b/kernel/drivers/acpi/acpica/acinterp.h index 1886bde54..e9e936e78 100644 --- a/kernel/drivers/acpi/acpica/acinterp.h +++ b/kernel/drivers/acpi/acpica/acinterp.h @@ -131,6 +131,28 @@ void acpi_ex_do_debug_object(union acpi_operand_object *source_desc, u32 level, u32 index); +void +acpi_ex_start_trace_method(struct acpi_namespace_node *method_node, + union acpi_operand_object *obj_desc, + struct acpi_walk_state *walk_state); + +void +acpi_ex_stop_trace_method(struct acpi_namespace_node *method_node, + union acpi_operand_object *obj_desc, + struct acpi_walk_state *walk_state); + +void +acpi_ex_start_trace_opcode(union acpi_parse_object *op, + struct acpi_walk_state *walk_state); + +void +acpi_ex_stop_trace_opcode(union acpi_parse_object *op, + struct acpi_walk_state *walk_state); + +void +acpi_ex_trace_point(acpi_trace_event_type type, + u8 begin, u8 *aml, char *pathname); + /* * exfield - ACPI AML (p-code) execution - field manipulation */ @@ -375,12 +397,10 @@ void acpi_ex_dump_operands(union acpi_operand_object **operands, const char *opcode_name, u32 num_opcodes); -#ifdef ACPI_FUTURE_USAGE void acpi_ex_dump_object_descriptor(union acpi_operand_object *object, u32 flags); void acpi_ex_dump_namespace_node(struct acpi_namespace_node *node, u32 flags); -#endif /* ACPI_FUTURE_USAGE */ /* * exnames - AML namestring support @@ -468,6 +488,8 @@ void acpi_ex_eisa_id_to_string(char *dest, u64 compressed_id); void acpi_ex_integer_to_string(char *dest, u64 value); +void acpi_ex_pci_cls_to_string(char *dest, u8 class_code[3]); + u8 acpi_is_valid_space_id(u8 space_id); /* diff --git a/kernel/drivers/acpi/acpica/aclocal.h b/kernel/drivers/acpi/acpica/aclocal.h index 7f50dd9eb..e1dd784d8 100644 --- a/kernel/drivers/acpi/acpica/aclocal.h +++ b/kernel/drivers/acpi/acpica/aclocal.h @@ -83,10 +83,8 @@ union acpi_parse_object; #define ACPI_MTX_EVENTS 3 /* Data for ACPI events */ #define ACPI_MTX_CACHES 4 /* Internal caches, general purposes */ #define ACPI_MTX_MEMORY 5 /* Debug memory tracking lists */ -#define ACPI_MTX_DEBUG_CMD_COMPLETE 6 /* AML debugger */ -#define ACPI_MTX_DEBUG_CMD_READY 7 /* AML debugger */ -#define ACPI_MAX_MUTEX 7 +#define ACPI_MAX_MUTEX 5 #define ACPI_NUM_MUTEX ACPI_MAX_MUTEX+1 /* Lock structure for reader/writer interfaces */ @@ -111,6 +109,14 @@ struct acpi_rw_lock { #define ACPI_MUTEX_NOT_ACQUIRED (acpi_thread_id) 0 +/* This Thread ID means an invalid thread ID */ + +#ifdef ACPI_OS_INVALID_THREAD_ID +#define ACPI_INVALID_THREAD_ID ACPI_OS_INVALID_THREAD_ID +#else +#define ACPI_INVALID_THREAD_ID ((acpi_thread_id) 0xFFFFFFFF) +#endif + /* Table for the global mutexes */ struct acpi_mutex_info { @@ -174,8 +180,12 @@ struct acpi_namespace_node { */ #ifdef ACPI_LARGE_NAMESPACE_NODE union acpi_parse_object *op; + void *method_locals; + void *method_args; u32 value; u32 length; + u8 arg_count; + #endif }; @@ -209,11 +219,9 @@ struct acpi_table_list { #define ACPI_ROOT_ORIGIN_ALLOCATED (1) #define ACPI_ROOT_ALLOW_RESIZE (2) -/* Predefined (fixed) table indexes */ +/* Predefined table indexes */ -#define ACPI_TABLE_INDEX_DSDT (0) -#define ACPI_TABLE_INDEX_FACS (1) -#define ACPI_TABLE_INDEX_X_FACS (2) +#define ACPI_INVALID_TABLE_INDEX (0xFFFFFFFF) struct acpi_find_context { char *search_for; @@ -285,13 +293,17 @@ acpi_status(*acpi_internal_method) (struct acpi_walk_state * walk_state); #define ACPI_BTYPE_BUFFER_FIELD 0x00002000 #define ACPI_BTYPE_DDB_HANDLE 0x00004000 #define ACPI_BTYPE_DEBUG_OBJECT 0x00008000 -#define ACPI_BTYPE_REFERENCE 0x00010000 +#define ACPI_BTYPE_REFERENCE_OBJECT 0x00010000 /* From Index(), ref_of(), etc (type6_opcodes) */ #define ACPI_BTYPE_RESOURCE 0x00020000 +#define ACPI_BTYPE_NAMED_REFERENCE 0x00040000 /* Generic unresolved Name or Namepath */ #define ACPI_BTYPE_COMPUTE_DATA (ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_BUFFER) #define ACPI_BTYPE_DATA (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_PACKAGE) -#define ACPI_BTYPE_DATA_REFERENCE (ACPI_BTYPE_DATA | ACPI_BTYPE_REFERENCE | ACPI_BTYPE_DDB_HANDLE) + + /* Used by Copy, de_ref_of, Store, Printf, Fprintf */ + +#define ACPI_BTYPE_DATA_REFERENCE (ACPI_BTYPE_DATA | ACPI_BTYPE_REFERENCE_OBJECT | ACPI_BTYPE_DDB_HANDLE) #define ACPI_BTYPE_DEVICE_OBJECTS (ACPI_BTYPE_DEVICE | ACPI_BTYPE_THERMAL | ACPI_BTYPE_PROCESSOR) #define ACPI_BTYPE_OBJECTS_AND_REFS 0x0001FFFF /* ARG or LOCAL */ #define ACPI_BTYPE_ALL_OBJECTS 0x0000FFFF @@ -353,11 +365,21 @@ struct acpi_package_info3 { u16 reserved; }; +struct acpi_package_info4 { + u8 type; + u8 object_type1; + u8 count1; + u8 sub_object_types; + u8 pkg_count; + u16 reserved; +}; + union acpi_predefined_info { struct acpi_name_info info; struct acpi_package_info ret_info; struct acpi_package_info2 ret_info2; struct acpi_package_info3 ret_info3; + struct acpi_package_info4 ret_info4; }; /* Reset to default packing */ @@ -394,6 +416,13 @@ struct acpi_simple_repair_info { #define ACPI_NUM_RTYPES 5 /* Number of actual object types */ +/* Info for running the _REG methods */ + +struct acpi_reg_walk_info { + acpi_adr_space_type space_id; + u32 reg_run_count; +}; + /***************************************************************************** * * Event typedefs and structs @@ -705,7 +734,7 @@ union acpi_parse_value { union acpi_parse_object *arg; /* arguments and contained ops */ }; -#ifdef ACPI_DISASSEMBLER +#if defined(ACPI_DISASSEMBLER) || defined(ACPI_DEBUG_OUTPUT) #define ACPI_DISASM_ONLY_MEMBERS(a) a; #else #define ACPI_DISASM_ONLY_MEMBERS(a) @@ -716,7 +745,7 @@ union acpi_parse_value { u8 descriptor_type; /* To differentiate various internal objs */\ u8 flags; /* Type of Op */\ u16 aml_opcode; /* AML opcode */\ - u32 aml_offset; /* Offset of declaration in AML */\ + u8 *aml; /* Address of declaration in AML */\ union acpi_parse_object *next; /* Next op */\ struct acpi_namespace_node *node; /* For use by interpreter */\ union acpi_parse_value value; /* Value or args associated with the opcode */\ @@ -829,7 +858,7 @@ struct acpi_parse_state { #define ACPI_PARSEOP_PARAMLIST 0x02 #define ACPI_PARSEOP_EMPTY_TERMLIST 0x04 #define ACPI_PARSEOP_PREDEF_CHECKED 0x08 -#define ACPI_PARSEOP_SPECIAL 0x10 +#define ACPI_PARSEOP_CLOSING_PAREN 0x10 #define ACPI_PARSEOP_COMPOUND 0x20 #define ACPI_PARSEOP_ASSIGNMENT 0x40 @@ -1093,6 +1122,9 @@ struct acpi_db_method_info { * Index of current thread inside all them created. */ char init_args; +#ifdef ACPI_DEBUGGER + acpi_object_type arg_types[4]; +#endif char *arguments[4]; char num_threads_str[11]; char id_of_thread_str[11]; @@ -1109,6 +1141,10 @@ struct acpi_integrity_info { #define ACPI_DB_CONSOLE_OUTPUT 0x02 #define ACPI_DB_DUPLICATE_OUTPUT 0x03 +struct acpi_object_info { + u32 types[ACPI_TOTAL_TYPES]; +}; + /***************************************************************************** * * Debug @@ -1166,4 +1202,9 @@ struct ah_uuid { char *string; }; +struct ah_table { + char *signature; + char *description; +}; + #endif /* __ACLOCAL_H__ */ diff --git a/kernel/drivers/acpi/acpica/acmacros.h b/kernel/drivers/acpi/acpica/acmacros.h index c240bdf82..e85366ceb 100644 --- a/kernel/drivers/acpi/acpica/acmacros.h +++ b/kernel/drivers/acpi/acpica/acmacros.h @@ -220,6 +220,15 @@ #define ACPI_MUL_32(a) _ACPI_MUL(a, 5) #define ACPI_MOD_32(a) _ACPI_MOD(a, 32) +/* Test for ASCII character */ + +#define ACPI_IS_ASCII(c) ((c) < 0x80) + +/* Signed integers */ + +#define ACPI_SIGN_POSITIVE 0 +#define ACPI_SIGN_NEGATIVE 1 + /* * Rounding macros (Power of two boundaries only) */ diff --git a/kernel/drivers/acpi/acpica/acnamesp.h b/kernel/drivers/acpi/acpica/acnamesp.h index 952fbe0b7..5d261c942 100644 --- a/kernel/drivers/acpi/acpica/acnamesp.h +++ b/kernel/drivers/acpi/acpica/acnamesp.h @@ -66,6 +66,7 @@ #define ACPI_NS_PREFIX_IS_SCOPE 0x10 #define ACPI_NS_EXTERNAL 0x20 #define ACPI_NS_TEMPORARY 0x40 +#define ACPI_NS_OVERRIDE_IF_FOUND 0x80 /* Flags for acpi_ns_walk_namespace */ @@ -192,9 +193,7 @@ acpi_ns_convert_to_resource(union acpi_operand_object *original_object, /* * nsdump - Namespace dump/print utilities */ -#ifdef ACPI_FUTURE_USAGE void acpi_ns_dump_tables(acpi_handle search_base, u32 max_depth); -#endif /* ACPI_FUTURE_USAGE */ void acpi_ns_dump_entry(acpi_handle handle, u32 debug_level); @@ -207,7 +206,6 @@ acpi_status acpi_ns_dump_one_object(acpi_handle obj_handle, u32 level, void *context, void **return_value); -#ifdef ACPI_FUTURE_USAGE void acpi_ns_dump_objects(acpi_object_type type, u8 display_type, @@ -219,7 +217,6 @@ acpi_ns_dump_object_paths(acpi_object_type type, u8 display_type, u32 max_depth, acpi_owner_id owner_id, acpi_handle start_handle); -#endif /* ACPI_FUTURE_USAGE */ /* * nseval - Namespace evaluation functions @@ -271,17 +268,20 @@ acpi_ns_check_package(struct acpi_evaluate_info *info, */ u32 acpi_ns_opens_scope(acpi_object_type type); -acpi_status -acpi_ns_build_external_path(struct acpi_namespace_node *node, - acpi_size size, char *name_buffer); - char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node); +u32 +acpi_ns_build_normalized_path(struct acpi_namespace_node *node, + char *full_path, u32 path_size, u8 no_trailing); + +char *acpi_ns_get_normalized_pathname(struct acpi_namespace_node *node, + u8 no_trailing); + char *acpi_ns_name_of_current_scope(struct acpi_walk_state *walk_state); acpi_status acpi_ns_handle_to_pathname(acpi_handle target_handle, - struct acpi_buffer *buffer); + struct acpi_buffer *buffer, u8 no_trailing); u8 acpi_ns_pattern_match(struct acpi_namespace_node *obj_node, char *search_for); diff --git a/kernel/drivers/acpi/acpica/acobject.h b/kernel/drivers/acpi/acpica/acobject.h index 3e9720e1f..0bd02c4a5 100644 --- a/kernel/drivers/acpi/acpica/acobject.h +++ b/kernel/drivers/acpi/acpica/acobject.h @@ -176,6 +176,7 @@ struct acpi_object_method { u8 param_count; u8 sync_level; union acpi_operand_object *mutex; + union acpi_operand_object *node; u8 *aml_start; union { acpi_internal_method implementation; @@ -335,6 +336,7 @@ struct acpi_object_reference { void *object; /* name_op=>HANDLE to obj, index_op=>union acpi_operand_object */ struct acpi_namespace_node *node; /* ref_of or Namepath */ union acpi_operand_object **where; /* Target of Index */ + u8 *index_pointer; /* Used for Buffers and Strings */ u32 value; /* Used for Local/Arg/Index/ddb_handle */ }; diff --git a/kernel/drivers/acpi/acpica/acopcode.h b/kernel/drivers/acpi/acpica/acopcode.h index fd85ad05a..f9acf92fa 100644 --- a/kernel/drivers/acpi/acpica/acopcode.h +++ b/kernel/drivers/acpi/acpica/acopcode.h @@ -211,7 +211,7 @@ #define ARGI_ARG4 ARG_NONE #define ARGI_ARG5 ARG_NONE #define ARGI_ARG6 ARG_NONE -#define ARGI_BANK_FIELD_OP ARGI_INVALID_OPCODE +#define ARGI_BANK_FIELD_OP ARGI_LIST1 (ARGI_INTEGER) #define ARGI_BIT_AND_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) #define ARGI_BIT_NAND_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) #define ARGI_BIT_NOR_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) @@ -307,7 +307,7 @@ #define ARGI_SLEEP_OP ARGI_LIST1 (ARGI_INTEGER) #define ARGI_STALL_OP ARGI_LIST1 (ARGI_INTEGER) #define ARGI_STATICSTRING_OP ARGI_INVALID_OPCODE -#define ARGI_STORE_OP ARGI_LIST2 (ARGI_DATAREFOBJ, ARGI_TARGETREF) +#define ARGI_STORE_OP ARGI_LIST2 (ARGI_DATAREFOBJ, ARGI_STORE_TARGET) #define ARGI_STRING_OP ARGI_INVALID_OPCODE #define ARGI_SUBTRACT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) #define ARGI_THERMAL_ZONE_OP ARGI_INVALID_OPCODE diff --git a/kernel/drivers/acpi/acpica/acparser.h b/kernel/drivers/acpi/acpica/acparser.h index 74a390c6d..8fc8c7cea 100644 --- a/kernel/drivers/acpi/acpica/acparser.h +++ b/kernel/drivers/acpi/acpica/acparser.h @@ -70,6 +70,9 @@ * *****************************************************************************/ +extern const u8 acpi_gbl_short_op_index[]; +extern const u8 acpi_gbl_long_op_index[]; + /* * psxface - Parser external interfaces */ @@ -191,10 +194,8 @@ union acpi_parse_object *acpi_ps_find(union acpi_parse_object *scope, union acpi_parse_object *acpi_ps_get_arg(union acpi_parse_object *op, u32 argn); -#ifdef ACPI_FUTURE_USAGE union acpi_parse_object *acpi_ps_get_depth_next(union acpi_parse_object *origin, union acpi_parse_object *op); -#endif /* ACPI_FUTURE_USAGE */ /* * pswalk - parse tree walk routines @@ -222,19 +223,17 @@ void acpi_ps_delete_parse_tree(union acpi_parse_object *root); /* * psutils - parser utilities */ -union acpi_parse_object *acpi_ps_create_scope_op(void); +union acpi_parse_object *acpi_ps_create_scope_op(u8 *aml); void acpi_ps_init_op(union acpi_parse_object *op, u16 opcode); -union acpi_parse_object *acpi_ps_alloc_op(u16 opcode); +union acpi_parse_object *acpi_ps_alloc_op(u16 opcode, u8 *aml); void acpi_ps_free_op(union acpi_parse_object *op); u8 acpi_ps_is_leading_char(u32 c); -#ifdef ACPI_FUTURE_USAGE u32 acpi_ps_get_name(union acpi_parse_object *op); -#endif /* ACPI_FUTURE_USAGE */ void acpi_ps_set_name(union acpi_parse_object *op, u32 name); diff --git a/kernel/drivers/acpi/acpica/acpredef.h b/kernel/drivers/acpi/acpica/acpredef.h index a972d11c9..b9474b529 100644 --- a/kernel/drivers/acpi/acpica/acpredef.h +++ b/kernel/drivers/acpi/acpica/acpredef.h @@ -105,6 +105,11 @@ * count = 0 (optional) * (Used for _DLM) * + * ACPI_PTYPE2_VAR_VAR: Variable number of subpackages, each of either a + * constant or variable length. The subpackages are preceded by a + * constant number of objects. + * (Used for _LPI, _RDI) + * * ACPI_PTYPE2_UUID_PAIR: Each subpackage is preceded by a UUID Buffer. The UUID * defines the format of the package. Zero-length parent package is * allowed. @@ -123,7 +128,8 @@ enum acpi_return_package_types { ACPI_PTYPE2_MIN = 8, ACPI_PTYPE2_REV_FIXED = 9, ACPI_PTYPE2_FIX_VAR = 10, - ACPI_PTYPE2_UUID_PAIR = 11 + ACPI_PTYPE2_VAR_VAR = 11, + ACPI_PTYPE2_UUID_PAIR = 12 }; /* Support macros for users of the predefined info table */ @@ -172,7 +178,7 @@ enum acpi_return_package_types { * These are the names that can actually be evaluated via acpi_evaluate_object. * Not present in this table are the following: * - * 1) Predefined/Reserved names that are never evaluated via + * 1) Predefined/Reserved names that are not usually evaluated via * acpi_evaluate_object: * _Lxx and _Exx GPE methods * _Qxx EC methods @@ -361,6 +367,9 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (4 Int) */ PACKAGE_INFO(ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4, 0, 0, 0), + {{"_BTH", METHOD_1ARGS(ACPI_TYPE_INTEGER), /* ACPI 6.0 */ + METHOD_NO_RETURN_VALUE}}, + {{"_BTM", METHOD_1ARGS(ACPI_TYPE_INTEGER), METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, @@ -390,6 +399,9 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER, 0, 0, 0, 0), + {{"_CR3", METHOD_0ARGS, /* ACPI 6.0 */ + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + {{"_CRS", METHOD_0ARGS, METHOD_RETURNS(ACPI_RTYPE_BUFFER)}}, @@ -445,7 +457,7 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { {{"_DOS", METHOD_1ARGS(ACPI_TYPE_INTEGER), METHOD_NO_RETURN_VALUE}}, - {{"_DSD", METHOD_0ARGS, + {{"_DSD", METHOD_0ARGS, /* ACPI 6.0 */ METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each: 1 Buf, 1 Pkg */ PACKAGE_INFO(ACPI_PTYPE2_UUID_PAIR, ACPI_RTYPE_BUFFER, 1, ACPI_RTYPE_PACKAGE, 1, 0), @@ -604,6 +616,12 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { 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), + {{"_LPI", METHOD_0ARGS, /* ACPI 6.0 */ + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (3 Int, n Pkg (10 Int/Buf) */ + PACKAGE_INFO(ACPI_PTYPE2_VAR_VAR, ACPI_RTYPE_INTEGER, 3, + ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER | ACPI_RTYPE_STRING, + 10, 0), + {{"_MAT", METHOD_0ARGS, METHOD_RETURNS(ACPI_RTYPE_BUFFER)}}, @@ -624,6 +642,9 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { ACPI_TYPE_INTEGER), METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + {{"_MTL", METHOD_0ARGS, /* ACPI 6.0 */ + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + {{"_NTT", METHOD_0ARGS, METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, @@ -716,6 +737,10 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0), + {{"_PRR", METHOD_0ARGS, /* ACPI 6.0 */ + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (1 Ref) */ + PACKAGE_INFO(ACPI_PTYPE1_FIXED, ACPI_RTYPE_REFERENCE, 1, 0, 0, 0), + {{"_PRS", METHOD_0ARGS, METHOD_RETURNS(ACPI_RTYPE_BUFFER)}}, @@ -796,6 +821,11 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { {{"_PXM", METHOD_0ARGS, METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + {{"_RDI", METHOD_0ARGS, /* ACPI 6.0 */ + METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (1 Int, n Pkg (m Ref)) */ + PACKAGE_INFO(ACPI_PTYPE2_VAR_VAR, ACPI_RTYPE_INTEGER, 1, + ACPI_RTYPE_REFERENCE, 0, 0), + {{"_REG", METHOD_2ARGS(ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER), METHOD_NO_RETURN_VALUE}}, @@ -808,6 +838,9 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { {{"_ROM", METHOD_2ARGS(ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER), METHOD_RETURNS(ACPI_RTYPE_BUFFER)}}, + {{"_RST", METHOD_0ARGS, /* ACPI 6.0 */ + METHOD_NO_RETURN_VALUE}}, + {{"_RTV", METHOD_0ARGS, METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, @@ -935,6 +968,9 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { {{"_TDL", METHOD_0ARGS, METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + {{"_TFP", METHOD_0ARGS, /* ACPI 6.0 */ + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + {{"_TIP", METHOD_1ARGS(ACPI_TYPE_INTEGER), METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, @@ -959,6 +995,9 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each 5 Int with count */ PACKAGE_INFO(ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER, 5, 0, 0, 0), + {{"_TSN", METHOD_0ARGS, /* ACPI 6.0 */ + METHOD_RETURNS(ACPI_RTYPE_REFERENCE)}}, + {{"_TSP", METHOD_0ARGS, METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, diff --git a/kernel/drivers/acpi/acpica/acstruct.h b/kernel/drivers/acpi/acpica/acstruct.h index 87c7860b3..f9992dced 100644 --- a/kernel/drivers/acpi/acpica/acstruct.h +++ b/kernel/drivers/acpi/acpica/acstruct.h @@ -82,9 +82,10 @@ struct acpi_walk_state { u8 return_used; u8 scope_depth; u8 pass_number; /* Parse pass during table load */ + u8 namespace_override; /* Override existing objects */ u8 result_size; /* Total elements for the result stack */ u8 result_count; /* Current number of occupied elements of result stack */ - u32 aml_offset; + u8 *aml; u32 arg_types; u32 method_breakpoint; /* For single stepping */ u32 user_breakpoint; /* User AML breakpoint */ diff --git a/kernel/drivers/acpi/acpica/actables.h b/kernel/drivers/acpi/acpica/actables.h index 7e0b6f1be..591ea9531 100644 --- a/kernel/drivers/acpi/acpica/actables.h +++ b/kernel/drivers/acpi/acpica/actables.h @@ -85,7 +85,7 @@ 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); +void acpi_tb_parse_fadt(void); void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length); @@ -138,8 +138,6 @@ acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id *owner_id); */ acpi_status acpi_tb_initialize_facs(void); -u8 acpi_tb_tables_loaded(void); - void acpi_tb_print_table_header(acpi_physical_address address, struct acpi_table_header *header); @@ -154,14 +152,20 @@ void acpi_tb_check_dsdt_header(void); struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index); void -acpi_tb_install_table_with_override(u32 table_index, - struct acpi_table_desc *new_table_desc, - u8 override); +acpi_tb_install_table_with_override(struct acpi_table_desc *new_table_desc, + u8 override, u32 *table_index); acpi_status acpi_tb_install_fixed_table(acpi_physical_address address, - char *signature, u32 table_index); + char *signature, u32 *table_index); acpi_status acpi_tb_parse_root_table(acpi_physical_address rsdp_address); +u8 acpi_is_valid_signature(char *signature); + +/* + * tbxfload + */ +acpi_status acpi_tb_load_namespace(void); + #endif /* __ACTABLES_H__ */ diff --git a/kernel/drivers/acpi/acpica/acutils.h b/kernel/drivers/acpi/acpica/acutils.h index 2b3c5bd22..8b8fef6cc 100644 --- a/kernel/drivers/acpi/acpica/acutils.h +++ b/kernel/drivers/acpi/acpica/acutils.h @@ -166,6 +166,17 @@ struct acpi_pkg_info { #define DB_DWORD_DISPLAY 4 #define DB_QWORD_DISPLAY 8 +/* + * utnonansi - Non-ANSI C library functions + */ +void acpi_ut_strupr(char *src_string); + +void acpi_ut_strlwr(char *src_string); + +int acpi_ut_stricmp(char *string1, char *string2); + +acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer); + /* * utglobal - Global data structures and procedures */ @@ -205,68 +216,6 @@ acpi_status acpi_ut_hardware_initialize(void); void acpi_ut_subsystem_shutdown(void); -/* - * utclib - Local implementations of C library functions - */ -#ifndef ACPI_USE_SYSTEM_CLIBRARY - -acpi_size acpi_ut_strlen(const char *string); - -char *acpi_ut_strchr(const char *string, int ch); - -char *acpi_ut_strcpy(char *dst_string, const char *src_string); - -char *acpi_ut_strncpy(char *dst_string, - const char *src_string, acpi_size count); - -int acpi_ut_memcmp(const char *buffer1, const char *buffer2, acpi_size count); - -int acpi_ut_strncmp(const char *string1, const char *string2, acpi_size count); - -int acpi_ut_strcmp(const char *string1, const char *string2); - -char *acpi_ut_strcat(char *dst_string, const char *src_string); - -char *acpi_ut_strncat(char *dst_string, - const char *src_string, acpi_size count); - -u32 acpi_ut_strtoul(const char *string, char **terminator, u32 base); - -char *acpi_ut_strstr(char *string1, char *string2); - -void *acpi_ut_memcpy(void *dest, const void *src, acpi_size count); - -void *acpi_ut_memset(void *dest, u8 value, acpi_size count); - -int acpi_ut_to_upper(int c); - -int acpi_ut_to_lower(int c); - -extern const u8 _acpi_ctype[]; - -#define _ACPI_XA 0x00 /* extra alphabetic - not supported */ -#define _ACPI_XS 0x40 /* extra space */ -#define _ACPI_BB 0x00 /* BEL, BS, etc. - not supported */ -#define _ACPI_CN 0x20 /* CR, FF, HT, NL, VT */ -#define _ACPI_DI 0x04 /* '0'-'9' */ -#define _ACPI_LO 0x02 /* 'a'-'z' */ -#define _ACPI_PU 0x10 /* punctuation */ -#define _ACPI_SP 0x08 /* space */ -#define _ACPI_UP 0x01 /* 'A'-'Z' */ -#define _ACPI_XD 0x80 /* '0'-'9', 'A'-'F', 'a'-'f' */ - -#define ACPI_IS_DIGIT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_DI)) -#define ACPI_IS_SPACE(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_SP)) -#define ACPI_IS_XDIGIT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_XD)) -#define ACPI_IS_UPPER(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_UP)) -#define ACPI_IS_LOWER(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO)) -#define ACPI_IS_PRINT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP | _ACPI_DI | _ACPI_XS | _ACPI_PU)) -#define ACPI_IS_ALPHA(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP)) - -#endif /* !ACPI_USE_SYSTEM_CLIBRARY */ - -#define ACPI_IS_ASCII(c) ((c) < 0x80) - /* * utcopy - Object construction and conversion interfaces */ @@ -430,6 +379,10 @@ acpi_status acpi_ut_execute_CID(struct acpi_namespace_node *device_node, struct acpi_pnp_device_id_list ** return_cid_list); +acpi_status +acpi_ut_execute_CLS(struct acpi_namespace_node *device_node, + struct acpi_pnp_device_id **return_id); + /* * utlock - reader/writer locks */ @@ -564,7 +517,7 @@ const struct acpi_exception_info *acpi_ut_validate_exception(acpi_status u8 acpi_ut_is_pci_root_bridge(char *id); -#if (defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP) +#if (defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP || defined ACPI_NAMES_APP) u8 acpi_ut_is_aml_table(struct acpi_table_header *table); #endif @@ -623,16 +576,6 @@ acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc, u8 **end_tag); /* * utstring - String and character utilities */ -void acpi_ut_strupr(char *src_string); - -#ifdef ACPI_ASL_COMPILER -void acpi_ut_strlwr(char *src_string); - -int acpi_ut_stricmp(char *string1, char *string2); -#endif - -acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer); - void acpi_ut_print_string(char *string, u16 max_length); #if defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP @@ -692,9 +635,7 @@ void acpi_ut_free_and_track(void *address, u32 component, const char *module, u32 line); -#ifdef ACPI_FUTURE_USAGE void acpi_ut_dump_allocation_info(void); -#endif /* ACPI_FUTURE_USAGE */ void acpi_ut_dump_allocations(u32 component, const char *module); diff --git a/kernel/drivers/acpi/acpica/amlcode.h b/kernel/drivers/acpi/acpica/amlcode.h index be9fd009c..883f20cfa 100644 --- a/kernel/drivers/acpi/acpica/amlcode.h +++ b/kernel/drivers/acpi/acpica/amlcode.h @@ -277,14 +277,15 @@ #define ARGI_TARGETREF 0x0F /* Target, subject to implicit conversion */ #define ARGI_FIXED_TARGET 0x10 /* Target, no implicit conversion */ #define ARGI_SIMPLE_TARGET 0x11 /* Name, Local, Arg -- no implicit conversion */ +#define ARGI_STORE_TARGET 0x12 /* Target for store is TARGETREF + package objects */ /* Multiple/complex types */ -#define ARGI_DATAOBJECT 0x12 /* Buffer, String, package or reference to a node - Used only by size_of operator */ -#define ARGI_COMPLEXOBJ 0x13 /* Buffer, String, or package (Used by INDEX op only) */ -#define ARGI_REF_OR_STRING 0x14 /* Reference or String (Used by DEREFOF op only) */ -#define ARGI_REGION_OR_BUFFER 0x15 /* Used by LOAD op only */ -#define ARGI_DATAREFOBJ 0x16 +#define ARGI_DATAOBJECT 0x13 /* Buffer, String, package or reference to a node - Used only by size_of operator */ +#define ARGI_COMPLEXOBJ 0x14 /* Buffer, String, or package (Used by INDEX op only) */ +#define ARGI_REF_OR_STRING 0x15 /* Reference or String (Used by DEREFOF op only) */ +#define ARGI_REGION_OR_BUFFER 0x16 /* Used by LOAD op only */ +#define ARGI_DATAREFOBJ 0x17 /* Note: types above can expand to 0x1F maximum */ diff --git a/kernel/drivers/acpi/acpica/dbcmds.c b/kernel/drivers/acpi/acpica/dbcmds.c new file mode 100644 index 000000000..30414b3d7 --- /dev/null +++ b/kernel/drivers/acpi/acpica/dbcmds.c @@ -0,0 +1,1187 @@ +/******************************************************************************* + * + * Module Name: dbcmds - Miscellaneous debug commands and output routines + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2015, 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 +#include "accommon.h" +#include "acevents.h" +#include "acdebug.h" +#include "acnamesp.h" +#include "acresrc.h" +#include "actables.h" + +#define _COMPONENT ACPI_CA_DEBUGGER +ACPI_MODULE_NAME("dbcmds") + +/* Local prototypes */ +static void +acpi_dm_compare_aml_resources(u8 *aml1_buffer, + acpi_rsdesc_size aml1_buffer_length, + u8 *aml2_buffer, + acpi_rsdesc_size aml2_buffer_length); + +static acpi_status +acpi_dm_test_resource_conversion(struct acpi_namespace_node *node, char *name); + +static acpi_status +acpi_db_resource_callback(struct acpi_resource *resource, void *context); + +static acpi_status +acpi_db_device_resources(acpi_handle obj_handle, + u32 nesting_level, void *context, void **return_value); + +static void acpi_db_do_one_sleep_state(u8 sleep_state); + +static char *acpi_db_trace_method_name = NULL; + +/******************************************************************************* + * + * FUNCTION: acpi_db_convert_to_node + * + * PARAMETERS: in_string - String to convert + * + * RETURN: Pointer to a NS node + * + * DESCRIPTION: Convert a string to a valid NS pointer. Handles numeric or + * alphanumeric strings. + * + ******************************************************************************/ + +struct acpi_namespace_node *acpi_db_convert_to_node(char *in_string) +{ + struct acpi_namespace_node *node; + acpi_size address; + + if ((*in_string >= 0x30) && (*in_string <= 0x39)) { + + /* Numeric argument, convert */ + + address = strtoul(in_string, NULL, 16); + node = ACPI_TO_POINTER(address); + if (!acpi_os_readable(node, sizeof(struct acpi_namespace_node))) { + acpi_os_printf("Address %p is invalid", node); + return (NULL); + } + + /* Make sure pointer is valid NS node */ + + if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) { + acpi_os_printf + ("Address %p is not a valid namespace node [%s]\n", + node, acpi_ut_get_descriptor_name(node)); + return (NULL); + } + } else { + /* + * Alpha argument: The parameter is a name string that must be + * resolved to a Namespace object. + */ + node = acpi_db_local_ns_lookup(in_string); + if (!node) { + acpi_os_printf + ("Could not find [%s] in namespace, defaulting to root node\n", + in_string); + node = acpi_gbl_root_node; + } + } + + return (node); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_sleep + * + * PARAMETERS: object_arg - Desired sleep state (0-5). NULL means + * invoke all possible sleep states. + * + * RETURN: Status + * + * DESCRIPTION: Simulate sleep/wake sequences + * + ******************************************************************************/ + +acpi_status acpi_db_sleep(char *object_arg) +{ + u8 sleep_state; + u32 i; + + ACPI_FUNCTION_TRACE(acpi_db_sleep); + + /* Null input (no arguments) means to invoke all sleep states */ + + if (!object_arg) { + acpi_os_printf("Invoking all possible sleep states, 0-%d\n", + ACPI_S_STATES_MAX); + + for (i = 0; i <= ACPI_S_STATES_MAX; i++) { + acpi_db_do_one_sleep_state((u8)i); + } + + return_ACPI_STATUS(AE_OK); + } + + /* Convert argument to binary and invoke the sleep state */ + + sleep_state = (u8)strtoul(object_arg, NULL, 0); + acpi_db_do_one_sleep_state(sleep_state); + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_do_one_sleep_state + * + * PARAMETERS: sleep_state - Desired sleep state (0-5) + * + * RETURN: None + * + * DESCRIPTION: Simulate a sleep/wake sequence + * + ******************************************************************************/ + +static void acpi_db_do_one_sleep_state(u8 sleep_state) +{ + acpi_status status; + u8 sleep_type_a; + u8 sleep_type_b; + + /* Validate parameter */ + + if (sleep_state > ACPI_S_STATES_MAX) { + acpi_os_printf("Sleep state %d out of range (%d max)\n", + sleep_state, ACPI_S_STATES_MAX); + return; + } + + acpi_os_printf("\n---- Invoking sleep state S%d (%s):\n", + sleep_state, acpi_gbl_sleep_state_names[sleep_state]); + + /* Get the values for the sleep type registers (for display only) */ + + status = + acpi_get_sleep_type_data(sleep_state, &sleep_type_a, &sleep_type_b); + if (ACPI_FAILURE(status)) { + acpi_os_printf("Could not evaluate [%s] method, %s\n", + acpi_gbl_sleep_state_names[sleep_state], + acpi_format_exception(status)); + return; + } + + acpi_os_printf + ("Register values for sleep state S%d: Sleep-A: %.2X, Sleep-B: %.2X\n", + sleep_state, sleep_type_a, sleep_type_b); + + /* Invoke the various sleep/wake interfaces */ + + acpi_os_printf("**** Sleep: Prepare to sleep (S%d) ****\n", + sleep_state); + status = acpi_enter_sleep_state_prep(sleep_state); + if (ACPI_FAILURE(status)) { + goto error_exit; + } + + acpi_os_printf("**** Sleep: Going to sleep (S%d) ****\n", sleep_state); + status = acpi_enter_sleep_state(sleep_state); + if (ACPI_FAILURE(status)) { + goto error_exit; + } + + acpi_os_printf("**** Wake: Prepare to return from sleep (S%d) ****\n", + sleep_state); + status = acpi_leave_sleep_state_prep(sleep_state); + if (ACPI_FAILURE(status)) { + goto error_exit; + } + + acpi_os_printf("**** Wake: Return from sleep (S%d) ****\n", + sleep_state); + status = acpi_leave_sleep_state(sleep_state); + if (ACPI_FAILURE(status)) { + goto error_exit; + } + + return; + +error_exit: + ACPI_EXCEPTION((AE_INFO, status, "During invocation of sleep state S%d", + sleep_state)); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_display_locks + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Display information about internal mutexes. + * + ******************************************************************************/ + +void acpi_db_display_locks(void) +{ + u32 i; + + for (i = 0; i < ACPI_MAX_MUTEX; i++) { + acpi_os_printf("%26s : %s\n", acpi_ut_get_mutex_name(i), + acpi_gbl_mutex_info[i].thread_id == + ACPI_MUTEX_NOT_ACQUIRED ? "Locked" : "Unlocked"); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_display_table_info + * + * PARAMETERS: table_arg - Name of table to be displayed + * + * RETURN: None + * + * DESCRIPTION: Display information about loaded tables. Current + * implementation displays all loaded tables. + * + ******************************************************************************/ + +void acpi_db_display_table_info(char *table_arg) +{ + u32 i; + struct acpi_table_desc *table_desc; + acpi_status status; + + /* Header */ + + acpi_os_printf("Idx ID Status Type " + "TableHeader (Sig, Address, Length, Misc)\n"); + + /* Walk the entire root table list */ + + for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) { + table_desc = &acpi_gbl_root_table_list.tables[i]; + + /* Index and Table ID */ + + acpi_os_printf("%3u %.2u ", i, table_desc->owner_id); + + /* Decode the table flags */ + + if (!(table_desc->flags & ACPI_TABLE_IS_LOADED)) { + acpi_os_printf("NotLoaded "); + } else { + acpi_os_printf(" Loaded "); + } + + switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) { + case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: + + acpi_os_printf("External/virtual "); + break; + + case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL: + + acpi_os_printf("Internal/physical "); + break; + + case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: + + acpi_os_printf("Internal/virtual "); + break; + + default: + + acpi_os_printf("INVALID TYPE "); + break; + } + + /* Make sure that the table is mapped */ + + status = acpi_tb_validate_table(table_desc); + if (ACPI_FAILURE(status)) { + return; + } + + /* Dump the table header */ + + if (table_desc->pointer) { + acpi_tb_print_table_header(table_desc->address, + table_desc->pointer); + } else { + /* If the pointer is null, the table has been unloaded */ + + ACPI_INFO((AE_INFO, "%4.4s - Table has been unloaded", + table_desc->signature.ascii)); + } + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_unload_acpi_table + * + * PARAMETERS: object_name - Namespace pathname for an object that + * is owned by the table to be unloaded + * + * RETURN: None + * + * DESCRIPTION: Unload an ACPI table, via any namespace node that is owned + * by the table. + * + ******************************************************************************/ + +void acpi_db_unload_acpi_table(char *object_name) +{ + struct acpi_namespace_node *node; + acpi_status status; + + /* Translate name to an Named object */ + + node = acpi_db_convert_to_node(object_name); + if (!node) { + return; + } + + status = acpi_unload_parent_table(ACPI_CAST_PTR(acpi_handle, node)); + if (ACPI_SUCCESS(status)) { + acpi_os_printf("Parent of [%s] (%p) unloaded and uninstalled\n", + object_name, node); + } else { + acpi_os_printf("%s, while unloading parent table of [%s]\n", + acpi_format_exception(status), object_name); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_send_notify + * + * PARAMETERS: name - Name of ACPI object where to send notify + * value - Value of the notify to send. + * + * RETURN: None + * + * DESCRIPTION: Send an ACPI notification. The value specified is sent to the + * named object as an ACPI notify. + * + ******************************************************************************/ + +void acpi_db_send_notify(char *name, u32 value) +{ + struct acpi_namespace_node *node; + acpi_status status; + + /* Translate name to an Named object */ + + node = acpi_db_convert_to_node(name); + if (!node) { + return; + } + + /* Dispatch the notify if legal */ + + if (acpi_ev_is_notify_object(node)) { + status = acpi_ev_queue_notify_request(node, value); + if (ACPI_FAILURE(status)) { + acpi_os_printf("Could not queue notify\n"); + } + } else { + acpi_os_printf("Named object [%4.4s] Type %s, " + "must be Device/Thermal/Processor type\n", + acpi_ut_get_node_name(node), + acpi_ut_get_type_name(node->type)); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_display_interfaces + * + * PARAMETERS: action_arg - Null, "install", or "remove" + * interface_name_arg - Name for install/remove options + * + * RETURN: None + * + * DESCRIPTION: Display or modify the global _OSI interface list + * + ******************************************************************************/ + +void acpi_db_display_interfaces(char *action_arg, char *interface_name_arg) +{ + struct acpi_interface_info *next_interface; + char *sub_string; + acpi_status status; + + /* If no arguments, just display current interface list */ + + if (!action_arg) { + (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, + ACPI_WAIT_FOREVER); + + next_interface = acpi_gbl_supported_interfaces; + while (next_interface) { + if (!(next_interface->flags & ACPI_OSI_INVALID)) { + acpi_os_printf("%s\n", next_interface->name); + } + + next_interface = next_interface->next; + } + + acpi_os_release_mutex(acpi_gbl_osi_mutex); + return; + } + + /* If action_arg exists, so must interface_name_arg */ + + if (!interface_name_arg) { + acpi_os_printf("Missing Interface Name argument\n"); + return; + } + + /* Uppercase the action for match below */ + + acpi_ut_strupr(action_arg); + + /* install - install an interface */ + + sub_string = strstr("INSTALL", action_arg); + if (sub_string) { + status = acpi_install_interface(interface_name_arg); + if (ACPI_FAILURE(status)) { + acpi_os_printf("%s, while installing \"%s\"\n", + acpi_format_exception(status), + interface_name_arg); + } + return; + } + + /* remove - remove an interface */ + + sub_string = strstr("REMOVE", action_arg); + if (sub_string) { + status = acpi_remove_interface(interface_name_arg); + if (ACPI_FAILURE(status)) { + acpi_os_printf("%s, while removing \"%s\"\n", + acpi_format_exception(status), + interface_name_arg); + } + return; + } + + /* Invalid action_arg */ + + acpi_os_printf("Invalid action argument: %s\n", action_arg); + return; +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_display_template + * + * PARAMETERS: buffer_arg - Buffer name or address + * + * RETURN: None + * + * DESCRIPTION: Dump a buffer that contains a resource template + * + ******************************************************************************/ + +void acpi_db_display_template(char *buffer_arg) +{ + struct acpi_namespace_node *node; + acpi_status status; + struct acpi_buffer return_buffer; + + /* Translate buffer_arg to an Named object */ + + node = acpi_db_convert_to_node(buffer_arg); + if (!node || (node == acpi_gbl_root_node)) { + acpi_os_printf("Invalid argument: %s\n", buffer_arg); + return; + } + + /* We must have a buffer object */ + + if (node->type != ACPI_TYPE_BUFFER) { + acpi_os_printf + ("Not a Buffer object, cannot be a template: %s\n", + buffer_arg); + return; + } + + return_buffer.length = ACPI_DEBUG_BUFFER_SIZE; + return_buffer.pointer = acpi_gbl_db_buffer; + + /* Attempt to convert the raw buffer to a resource list */ + + status = acpi_rs_create_resource_list(node->object, &return_buffer); + + acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT); + acpi_dbg_level |= ACPI_LV_RESOURCES; + + if (ACPI_FAILURE(status)) { + acpi_os_printf + ("Could not convert Buffer to a resource list: %s, %s\n", + buffer_arg, acpi_format_exception(status)); + goto dump_buffer; + } + + /* Now we can dump the resource list */ + + acpi_rs_dump_resource_list(ACPI_CAST_PTR(struct acpi_resource, + return_buffer.pointer)); + +dump_buffer: + acpi_os_printf("\nRaw data buffer:\n"); + acpi_ut_debug_dump_buffer((u8 *)node->object->buffer.pointer, + node->object->buffer.length, + DB_BYTE_DISPLAY, ACPI_UINT32_MAX); + + acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); + return; +} + +/******************************************************************************* + * + * FUNCTION: acpi_dm_compare_aml_resources + * + * PARAMETERS: aml1_buffer - Contains first resource list + * aml1_buffer_length - Length of first resource list + * aml2_buffer - Contains second resource list + * aml2_buffer_length - Length of second resource list + * + * RETURN: None + * + * DESCRIPTION: Compare two AML resource lists, descriptor by descriptor (in + * order to isolate a miscompare to an individual resource) + * + ******************************************************************************/ + +static void +acpi_dm_compare_aml_resources(u8 *aml1_buffer, + acpi_rsdesc_size aml1_buffer_length, + u8 *aml2_buffer, + acpi_rsdesc_size aml2_buffer_length) +{ + u8 *aml1; + u8 *aml2; + u8 *aml1_end; + u8 *aml2_end; + acpi_rsdesc_size aml1_length; + acpi_rsdesc_size aml2_length; + acpi_rsdesc_size offset = 0; + u8 resource_type; + u32 count = 0; + u32 i; + + /* Compare overall buffer sizes (may be different due to size rounding) */ + + if (aml1_buffer_length != aml2_buffer_length) { + acpi_os_printf("**** Buffer length mismatch in converted " + "AML: Original %X, New %X ****\n", + aml1_buffer_length, aml2_buffer_length); + } + + aml1 = aml1_buffer; + aml2 = aml2_buffer; + aml1_end = aml1_buffer + aml1_buffer_length; + aml2_end = aml2_buffer + aml2_buffer_length; + + /* Walk the descriptor lists, comparing each descriptor */ + + while ((aml1 < aml1_end) && (aml2 < aml2_end)) { + + /* Get the lengths of each descriptor */ + + aml1_length = acpi_ut_get_descriptor_length(aml1); + aml2_length = acpi_ut_get_descriptor_length(aml2); + resource_type = acpi_ut_get_resource_type(aml1); + + /* Check for descriptor length match */ + + if (aml1_length != aml2_length) { + acpi_os_printf + ("**** Length mismatch in descriptor [%.2X] type %2.2X, " + "Offset %8.8X Len1 %X, Len2 %X ****\n", count, + resource_type, offset, aml1_length, aml2_length); + } + + /* Check for descriptor byte match */ + + else if (memcmp(aml1, aml2, aml1_length)) { + acpi_os_printf + ("**** Data mismatch in descriptor [%.2X] type %2.2X, " + "Offset %8.8X ****\n", count, resource_type, + offset); + + for (i = 0; i < aml1_length; i++) { + if (aml1[i] != aml2[i]) { + acpi_os_printf + ("Mismatch at byte offset %.2X: is %2.2X, " + "should be %2.2X\n", i, aml2[i], + aml1[i]); + } + } + } + + /* Exit on end_tag descriptor */ + + if (resource_type == ACPI_RESOURCE_NAME_END_TAG) { + return; + } + + /* Point to next descriptor in each buffer */ + + count++; + offset += aml1_length; + aml1 += aml1_length; + aml2 += aml2_length; + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_dm_test_resource_conversion + * + * PARAMETERS: node - Parent device node + * name - resource method name (_CRS) + * + * RETURN: Status + * + * DESCRIPTION: Compare the original AML with a conversion of the AML to + * internal resource list, then back to AML. + * + ******************************************************************************/ + +static acpi_status +acpi_dm_test_resource_conversion(struct acpi_namespace_node *node, char *name) +{ + acpi_status status; + struct acpi_buffer return_buffer; + struct acpi_buffer resource_buffer; + struct acpi_buffer new_aml; + union acpi_object *original_aml; + + acpi_os_printf("Resource Conversion Comparison:\n"); + + new_aml.length = ACPI_ALLOCATE_LOCAL_BUFFER; + return_buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + resource_buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + + /* Get the original _CRS AML resource template */ + + status = acpi_evaluate_object(node, name, NULL, &return_buffer); + if (ACPI_FAILURE(status)) { + acpi_os_printf("Could not obtain %s: %s\n", + name, acpi_format_exception(status)); + return (status); + } + + /* Get the AML resource template, converted to internal resource structs */ + + status = acpi_get_current_resources(node, &resource_buffer); + if (ACPI_FAILURE(status)) { + acpi_os_printf("AcpiGetCurrentResources failed: %s\n", + acpi_format_exception(status)); + goto exit1; + } + + /* Convert internal resource list to external AML resource template */ + + status = acpi_rs_create_aml_resources(&resource_buffer, &new_aml); + if (ACPI_FAILURE(status)) { + acpi_os_printf("AcpiRsCreateAmlResources failed: %s\n", + acpi_format_exception(status)); + goto exit2; + } + + /* Compare original AML to the newly created AML resource list */ + + original_aml = return_buffer.pointer; + + acpi_dm_compare_aml_resources(original_aml->buffer.pointer, + (acpi_rsdesc_size) original_aml->buffer. + length, new_aml.pointer, + (acpi_rsdesc_size) new_aml.length); + + /* Cleanup and exit */ + + ACPI_FREE(new_aml.pointer); +exit2: + ACPI_FREE(resource_buffer.pointer); +exit1: + ACPI_FREE(return_buffer.pointer); + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_resource_callback + * + * PARAMETERS: acpi_walk_resource_callback + * + * RETURN: Status + * + * DESCRIPTION: Simple callback to exercise acpi_walk_resources and + * acpi_walk_resource_buffer. + * + ******************************************************************************/ + +static acpi_status +acpi_db_resource_callback(struct acpi_resource *resource, void *context) +{ + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_device_resources + * + * PARAMETERS: acpi_walk_callback + * + * RETURN: Status + * + * DESCRIPTION: Display the _PRT/_CRS/_PRS resources for a device object. + * + ******************************************************************************/ + +static acpi_status +acpi_db_device_resources(acpi_handle obj_handle, + u32 nesting_level, void *context, void **return_value) +{ + struct acpi_namespace_node *node; + struct acpi_namespace_node *prt_node = NULL; + struct acpi_namespace_node *crs_node = NULL; + struct acpi_namespace_node *prs_node = NULL; + struct acpi_namespace_node *aei_node = NULL; + char *parent_path; + struct acpi_buffer return_buffer; + acpi_status status; + + node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle); + parent_path = acpi_ns_get_external_pathname(node); + if (!parent_path) { + return (AE_NO_MEMORY); + } + + /* Get handles to the resource methods for this device */ + + (void)acpi_get_handle(node, METHOD_NAME__PRT, + ACPI_CAST_PTR(acpi_handle, &prt_node)); + (void)acpi_get_handle(node, METHOD_NAME__CRS, + ACPI_CAST_PTR(acpi_handle, &crs_node)); + (void)acpi_get_handle(node, METHOD_NAME__PRS, + ACPI_CAST_PTR(acpi_handle, &prs_node)); + (void)acpi_get_handle(node, METHOD_NAME__AEI, + ACPI_CAST_PTR(acpi_handle, &aei_node)); + + if (!prt_node && !crs_node && !prs_node && !aei_node) { + goto cleanup; /* Nothing to do */ + } + + acpi_os_printf("\nDevice: %s\n", parent_path); + + /* Prepare for a return object of arbitrary size */ + + return_buffer.pointer = acpi_gbl_db_buffer; + return_buffer.length = ACPI_DEBUG_BUFFER_SIZE; + + /* _PRT */ + + if (prt_node) { + acpi_os_printf("Evaluating _PRT\n"); + + status = + acpi_evaluate_object(prt_node, NULL, NULL, &return_buffer); + if (ACPI_FAILURE(status)) { + acpi_os_printf("Could not evaluate _PRT: %s\n", + acpi_format_exception(status)); + goto get_crs; + } + + return_buffer.pointer = acpi_gbl_db_buffer; + return_buffer.length = ACPI_DEBUG_BUFFER_SIZE; + + status = acpi_get_irq_routing_table(node, &return_buffer); + if (ACPI_FAILURE(status)) { + acpi_os_printf("GetIrqRoutingTable failed: %s\n", + acpi_format_exception(status)); + goto get_crs; + } + + acpi_rs_dump_irq_list(ACPI_CAST_PTR(u8, acpi_gbl_db_buffer)); + } + + /* _CRS */ + +get_crs: + if (crs_node) { + acpi_os_printf("Evaluating _CRS\n"); + + return_buffer.pointer = acpi_gbl_db_buffer; + return_buffer.length = ACPI_DEBUG_BUFFER_SIZE; + + status = + acpi_evaluate_object(crs_node, NULL, NULL, &return_buffer); + if (ACPI_FAILURE(status)) { + acpi_os_printf("Could not evaluate _CRS: %s\n", + acpi_format_exception(status)); + goto get_prs; + } + + /* This code exercises the acpi_walk_resources interface */ + + status = acpi_walk_resources(node, METHOD_NAME__CRS, + acpi_db_resource_callback, NULL); + if (ACPI_FAILURE(status)) { + acpi_os_printf("AcpiWalkResources failed: %s\n", + acpi_format_exception(status)); + goto get_prs; + } + + /* Get the _CRS resource list (test ALLOCATE buffer) */ + + return_buffer.pointer = NULL; + return_buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + + status = acpi_get_current_resources(node, &return_buffer); + if (ACPI_FAILURE(status)) { + acpi_os_printf("AcpiGetCurrentResources failed: %s\n", + acpi_format_exception(status)); + goto get_prs; + } + + /* This code exercises the acpi_walk_resource_buffer interface */ + + status = acpi_walk_resource_buffer(&return_buffer, + acpi_db_resource_callback, + NULL); + if (ACPI_FAILURE(status)) { + acpi_os_printf("AcpiWalkResourceBuffer failed: %s\n", + acpi_format_exception(status)); + goto end_crs; + } + + /* Dump the _CRS resource list */ + + acpi_rs_dump_resource_list(ACPI_CAST_PTR(struct acpi_resource, + return_buffer. + pointer)); + + /* + * Perform comparison of original AML to newly created AML. This + * tests both the AML->Resource conversion and the Resource->AML + * conversion. + */ + (void)acpi_dm_test_resource_conversion(node, METHOD_NAME__CRS); + + /* Execute _SRS with the resource list */ + + acpi_os_printf("Evaluating _SRS\n"); + + status = acpi_set_current_resources(node, &return_buffer); + if (ACPI_FAILURE(status)) { + acpi_os_printf("AcpiSetCurrentResources failed: %s\n", + acpi_format_exception(status)); + goto end_crs; + } + +end_crs: + ACPI_FREE(return_buffer.pointer); + } + + /* _PRS */ + +get_prs: + if (prs_node) { + acpi_os_printf("Evaluating _PRS\n"); + + return_buffer.pointer = acpi_gbl_db_buffer; + return_buffer.length = ACPI_DEBUG_BUFFER_SIZE; + + status = + acpi_evaluate_object(prs_node, NULL, NULL, &return_buffer); + if (ACPI_FAILURE(status)) { + acpi_os_printf("Could not evaluate _PRS: %s\n", + acpi_format_exception(status)); + goto get_aei; + } + + return_buffer.pointer = acpi_gbl_db_buffer; + return_buffer.length = ACPI_DEBUG_BUFFER_SIZE; + + status = acpi_get_possible_resources(node, &return_buffer); + if (ACPI_FAILURE(status)) { + acpi_os_printf("AcpiGetPossibleResources failed: %s\n", + acpi_format_exception(status)); + goto get_aei; + } + + acpi_rs_dump_resource_list(ACPI_CAST_PTR + (struct acpi_resource, + acpi_gbl_db_buffer)); + } + + /* _AEI */ + +get_aei: + if (aei_node) { + acpi_os_printf("Evaluating _AEI\n"); + + return_buffer.pointer = acpi_gbl_db_buffer; + return_buffer.length = ACPI_DEBUG_BUFFER_SIZE; + + status = + acpi_evaluate_object(aei_node, NULL, NULL, &return_buffer); + if (ACPI_FAILURE(status)) { + acpi_os_printf("Could not evaluate _AEI: %s\n", + acpi_format_exception(status)); + goto cleanup; + } + + return_buffer.pointer = acpi_gbl_db_buffer; + return_buffer.length = ACPI_DEBUG_BUFFER_SIZE; + + status = acpi_get_event_resources(node, &return_buffer); + if (ACPI_FAILURE(status)) { + acpi_os_printf("AcpiGetEventResources failed: %s\n", + acpi_format_exception(status)); + goto cleanup; + } + + acpi_rs_dump_resource_list(ACPI_CAST_PTR + (struct acpi_resource, + acpi_gbl_db_buffer)); + } + +cleanup: + ACPI_FREE(parent_path); + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_display_resources + * + * PARAMETERS: object_arg - String object name or object pointer. + * NULL or "*" means "display resources for + * all devices" + * + * RETURN: None + * + * DESCRIPTION: Display the resource objects associated with a device. + * + ******************************************************************************/ + +void acpi_db_display_resources(char *object_arg) +{ + struct acpi_namespace_node *node; + + acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT); + acpi_dbg_level |= ACPI_LV_RESOURCES; + + /* Asterisk means "display resources for all devices" */ + + if (!object_arg || (!strcmp(object_arg, "*"))) { + (void)acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, + acpi_db_device_resources, NULL, NULL, + NULL); + } else { + /* Convert string to object pointer */ + + node = acpi_db_convert_to_node(object_arg); + if (node) { + if (node->type != ACPI_TYPE_DEVICE) { + acpi_os_printf + ("%4.4s: Name is not a device object (%s)\n", + node->name.ascii, + acpi_ut_get_type_name(node->type)); + } else { + (void)acpi_db_device_resources(node, 0, NULL, + NULL); + } + } + } + + acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); +} + +#if (!ACPI_REDUCED_HARDWARE) +/******************************************************************************* + * + * FUNCTION: acpi_db_generate_gpe + * + * PARAMETERS: gpe_arg - Raw GPE number, ascii string + * block_arg - GPE block number, ascii string + * 0 or 1 for FADT GPE blocks + * + * RETURN: None + * + * DESCRIPTION: Simulate firing of a GPE + * + ******************************************************************************/ + +void acpi_db_generate_gpe(char *gpe_arg, char *block_arg) +{ + u32 block_number = 0; + u32 gpe_number; + struct acpi_gpe_event_info *gpe_event_info; + + gpe_number = strtoul(gpe_arg, NULL, 0); + + /* + * If no block arg, or block arg == 0 or 1, use the FADT-defined + * GPE blocks. + */ + if (block_arg) { + block_number = strtoul(block_arg, NULL, 0); + if (block_number == 1) { + block_number = 0; + } + } + + gpe_event_info = + acpi_ev_get_gpe_event_info(ACPI_TO_POINTER(block_number), + gpe_number); + if (!gpe_event_info) { + acpi_os_printf("Invalid GPE\n"); + return; + } + + (void)acpi_ev_gpe_dispatch(NULL, gpe_event_info, gpe_number); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_generate_sci + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Simulate an SCI -- just call the SCI dispatch. + * + ******************************************************************************/ + +void acpi_db_generate_sci(void) +{ + acpi_ev_sci_dispatch(); +} + +#endif /* !ACPI_REDUCED_HARDWARE */ + +/******************************************************************************* + * + * FUNCTION: acpi_db_trace + * + * PARAMETERS: enable_arg - ENABLE/AML to enable tracer + * DISABLE to disable tracer + * method_arg - Method to trace + * once_arg - Whether trace once + * + * RETURN: None + * + * DESCRIPTION: Control method tracing facility + * + ******************************************************************************/ + +void acpi_db_trace(char *enable_arg, char *method_arg, char *once_arg) +{ + u32 debug_level = 0; + u32 debug_layer = 0; + u32 flags = 0; + + if (enable_arg) { + acpi_ut_strupr(enable_arg); + } + + if (once_arg) { + acpi_ut_strupr(once_arg); + } + + if (method_arg) { + if (acpi_db_trace_method_name) { + ACPI_FREE(acpi_db_trace_method_name); + acpi_db_trace_method_name = NULL; + } + + acpi_db_trace_method_name = + ACPI_ALLOCATE(strlen(method_arg) + 1); + if (!acpi_db_trace_method_name) { + acpi_os_printf("Failed to allocate method name (%s)\n", + method_arg); + return; + } + + strcpy(acpi_db_trace_method_name, method_arg); + } + + if (!strcmp(enable_arg, "ENABLE") || + !strcmp(enable_arg, "METHOD") || !strcmp(enable_arg, "OPCODE")) { + if (!strcmp(enable_arg, "ENABLE")) { + + /* Inherit current console settings */ + + debug_level = acpi_gbl_db_console_debug_level; + debug_layer = acpi_dbg_layer; + } else { + /* Restrict console output to trace points only */ + + debug_level = ACPI_LV_TRACE_POINT; + debug_layer = ACPI_EXECUTER; + } + + flags = ACPI_TRACE_ENABLED; + + if (!strcmp(enable_arg, "OPCODE")) { + flags |= ACPI_TRACE_OPCODE; + } + + if (once_arg && !strcmp(once_arg, "ONCE")) { + flags |= ACPI_TRACE_ONESHOT; + } + } + + (void)acpi_debug_trace(acpi_db_trace_method_name, + debug_level, debug_layer, flags); +} diff --git a/kernel/drivers/acpi/acpica/dbconvert.c b/kernel/drivers/acpi/acpica/dbconvert.c new file mode 100644 index 000000000..a71632ca8 --- /dev/null +++ b/kernel/drivers/acpi/acpica/dbconvert.c @@ -0,0 +1,484 @@ +/******************************************************************************* + * + * Module Name: dbconvert - debugger miscellaneous conversion routines + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2015, 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 +#include "accommon.h" +#include "acdebug.h" + +#define _COMPONENT ACPI_CA_DEBUGGER +ACPI_MODULE_NAME("dbconvert") + +#define DB_DEFAULT_PKG_ELEMENTS 33 +/******************************************************************************* + * + * FUNCTION: acpi_db_hex_char_to_value + * + * PARAMETERS: hex_char - Ascii Hex digit, 0-9|a-f|A-F + * return_value - Where the converted value is returned + * + * RETURN: Status + * + * DESCRIPTION: Convert a single hex character to a 4-bit number (0-16). + * + ******************************************************************************/ +acpi_status acpi_db_hex_char_to_value(int hex_char, u8 *return_value) +{ + u8 value; + + /* Digit must be ascii [0-9a-fA-F] */ + + if (!isxdigit(hex_char)) { + return (AE_BAD_HEX_CONSTANT); + } + + if (hex_char <= 0x39) { + value = (u8)(hex_char - 0x30); + } else { + value = (u8)(toupper(hex_char) - 0x37); + } + + *return_value = value; + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_hex_byte_to_binary + * + * PARAMETERS: hex_byte - Double hex digit (0x00 - 0xFF) in format: + * hi_byte then lo_byte. + * return_value - Where the converted value is returned + * + * RETURN: Status + * + * DESCRIPTION: Convert two hex characters to an 8 bit number (0 - 255). + * + ******************************************************************************/ + +static acpi_status acpi_db_hex_byte_to_binary(char *hex_byte, u8 *return_value) +{ + u8 local0; + u8 local1; + acpi_status status; + + /* High byte */ + + status = acpi_db_hex_char_to_value(hex_byte[0], &local0); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Low byte */ + + status = acpi_db_hex_char_to_value(hex_byte[1], &local1); + if (ACPI_FAILURE(status)) { + return (status); + } + + *return_value = (u8)((local0 << 4) | local1); + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_convert_to_buffer + * + * PARAMETERS: string - Input string to be converted + * object - Where the buffer object is returned + * + * RETURN: Status + * + * DESCRIPTION: Convert a string to a buffer object. String is treated a list + * of buffer elements, each separated by a space or comma. + * + ******************************************************************************/ + +static acpi_status +acpi_db_convert_to_buffer(char *string, union acpi_object *object) +{ + u32 i; + u32 j; + u32 length; + u8 *buffer; + acpi_status status; + + /* Generate the final buffer length */ + + for (i = 0, length = 0; string[i];) { + i += 2; + length++; + + while (string[i] && ((string[i] == ',') || (string[i] == ' '))) { + i++; + } + } + + buffer = ACPI_ALLOCATE(length); + if (!buffer) { + return (AE_NO_MEMORY); + } + + /* Convert the command line bytes to the buffer */ + + for (i = 0, j = 0; string[i];) { + status = acpi_db_hex_byte_to_binary(&string[i], &buffer[j]); + if (ACPI_FAILURE(status)) { + ACPI_FREE(buffer); + return (status); + } + + j++; + i += 2; + while (string[i] && ((string[i] == ',') || (string[i] == ' '))) { + i++; + } + } + + object->type = ACPI_TYPE_BUFFER; + object->buffer.pointer = buffer; + object->buffer.length = length; + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_convert_to_package + * + * PARAMETERS: string - Input string to be converted + * object - Where the package object is returned + * + * RETURN: Status + * + * DESCRIPTION: Convert a string to a package object. Handles nested packages + * via recursion with acpi_db_convert_to_object. + * + ******************************************************************************/ + +acpi_status acpi_db_convert_to_package(char *string, union acpi_object * object) +{ + char *this; + char *next; + u32 i; + acpi_object_type type; + union acpi_object *elements; + acpi_status status; + + elements = + ACPI_ALLOCATE_ZEROED(DB_DEFAULT_PKG_ELEMENTS * + sizeof(union acpi_object)); + + this = string; + for (i = 0; i < (DB_DEFAULT_PKG_ELEMENTS - 1); i++) { + this = acpi_db_get_next_token(this, &next, &type); + if (!this) { + break; + } + + /* Recursive call to convert each package element */ + + status = acpi_db_convert_to_object(type, this, &elements[i]); + if (ACPI_FAILURE(status)) { + acpi_db_delete_objects(i + 1, elements); + ACPI_FREE(elements); + return (status); + } + + this = next; + } + + object->type = ACPI_TYPE_PACKAGE; + object->package.count = i; + object->package.elements = elements; + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_convert_to_object + * + * PARAMETERS: type - Object type as determined by parser + * string - Input string to be converted + * object - Where the new object is returned + * + * RETURN: Status + * + * DESCRIPTION: Convert a typed and tokenized string to an union acpi_object. Typing: + * 1) String objects were surrounded by quotes. + * 2) Buffer objects were surrounded by parentheses. + * 3) Package objects were surrounded by brackets "[]". + * 4) All standalone tokens are treated as integers. + * + ******************************************************************************/ + +acpi_status +acpi_db_convert_to_object(acpi_object_type type, + char *string, union acpi_object * object) +{ + acpi_status status = AE_OK; + + switch (type) { + case ACPI_TYPE_STRING: + + object->type = ACPI_TYPE_STRING; + object->string.pointer = string; + object->string.length = (u32)strlen(string); + break; + + case ACPI_TYPE_BUFFER: + + status = acpi_db_convert_to_buffer(string, object); + break; + + case ACPI_TYPE_PACKAGE: + + status = acpi_db_convert_to_package(string, object); + break; + + default: + + object->type = ACPI_TYPE_INTEGER; + status = acpi_ut_strtoul64(string, 16, &object->integer.value); + break; + } + + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_encode_pld_buffer + * + * PARAMETERS: pld_info - _PLD buffer struct (Using local struct) + * + * RETURN: Encode _PLD buffer suitable for return value from _PLD + * + * DESCRIPTION: Bit-packs a _PLD buffer struct. Used to test the _PLD macros + * + ******************************************************************************/ + +u8 *acpi_db_encode_pld_buffer(struct acpi_pld_info *pld_info) +{ + u32 *buffer; + u32 dword; + + buffer = ACPI_ALLOCATE_ZEROED(ACPI_PLD_BUFFER_SIZE); + if (!buffer) { + return (NULL); + } + + /* First 32 bits */ + + dword = 0; + ACPI_PLD_SET_REVISION(&dword, pld_info->revision); + ACPI_PLD_SET_IGNORE_COLOR(&dword, pld_info->ignore_color); + ACPI_PLD_SET_RED(&dword, pld_info->red); + ACPI_PLD_SET_GREEN(&dword, pld_info->green); + ACPI_PLD_SET_BLUE(&dword, pld_info->blue); + ACPI_MOVE_32_TO_32(&buffer[0], &dword); + + /* Second 32 bits */ + + dword = 0; + ACPI_PLD_SET_WIDTH(&dword, pld_info->width); + ACPI_PLD_SET_HEIGHT(&dword, pld_info->height); + ACPI_MOVE_32_TO_32(&buffer[1], &dword); + + /* Third 32 bits */ + + dword = 0; + ACPI_PLD_SET_USER_VISIBLE(&dword, pld_info->user_visible); + ACPI_PLD_SET_DOCK(&dword, pld_info->dock); + ACPI_PLD_SET_LID(&dword, pld_info->lid); + ACPI_PLD_SET_PANEL(&dword, pld_info->panel); + ACPI_PLD_SET_VERTICAL(&dword, pld_info->vertical_position); + ACPI_PLD_SET_HORIZONTAL(&dword, pld_info->horizontal_position); + ACPI_PLD_SET_SHAPE(&dword, pld_info->shape); + ACPI_PLD_SET_ORIENTATION(&dword, pld_info->group_orientation); + ACPI_PLD_SET_TOKEN(&dword, pld_info->group_token); + ACPI_PLD_SET_POSITION(&dword, pld_info->group_position); + ACPI_PLD_SET_BAY(&dword, pld_info->bay); + ACPI_MOVE_32_TO_32(&buffer[2], &dword); + + /* Fourth 32 bits */ + + dword = 0; + ACPI_PLD_SET_EJECTABLE(&dword, pld_info->ejectable); + ACPI_PLD_SET_OSPM_EJECT(&dword, pld_info->ospm_eject_required); + ACPI_PLD_SET_CABINET(&dword, pld_info->cabinet_number); + ACPI_PLD_SET_CARD_CAGE(&dword, pld_info->card_cage_number); + ACPI_PLD_SET_REFERENCE(&dword, pld_info->reference); + ACPI_PLD_SET_ROTATION(&dword, pld_info->rotation); + ACPI_PLD_SET_ORDER(&dword, pld_info->order); + ACPI_MOVE_32_TO_32(&buffer[3], &dword); + + if (pld_info->revision >= 2) { + + /* Fifth 32 bits */ + + dword = 0; + ACPI_PLD_SET_VERT_OFFSET(&dword, pld_info->vertical_offset); + ACPI_PLD_SET_HORIZ_OFFSET(&dword, pld_info->horizontal_offset); + ACPI_MOVE_32_TO_32(&buffer[4], &dword); + } + + return (ACPI_CAST_PTR(u8, buffer)); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_dump_pld_buffer + * + * PARAMETERS: obj_desc - Object returned from _PLD method + * + * RETURN: None. + * + * DESCRIPTION: Dumps formatted contents of a _PLD return buffer. + * + ******************************************************************************/ + +#define ACPI_PLD_OUTPUT "%20s : %-6X\n" + +void acpi_db_dump_pld_buffer(union acpi_object *obj_desc) +{ + union acpi_object *buffer_desc; + struct acpi_pld_info *pld_info; + u8 *new_buffer; + acpi_status status; + + /* Object must be of type Package with at least one Buffer element */ + + if (obj_desc->type != ACPI_TYPE_PACKAGE) { + return; + } + + buffer_desc = &obj_desc->package.elements[0]; + if (buffer_desc->type != ACPI_TYPE_BUFFER) { + return; + } + + /* Convert _PLD buffer to local _PLD struct */ + + status = acpi_decode_pld_buffer(buffer_desc->buffer.pointer, + buffer_desc->buffer.length, &pld_info); + if (ACPI_FAILURE(status)) { + return; + } + + /* Encode local _PLD struct back to a _PLD buffer */ + + new_buffer = acpi_db_encode_pld_buffer(pld_info); + if (!new_buffer) { + return; + } + + /* The two bit-packed buffers should match */ + + if (memcmp(new_buffer, buffer_desc->buffer.pointer, + buffer_desc->buffer.length)) { + acpi_os_printf + ("Converted _PLD buffer does not compare. New:\n"); + + acpi_ut_dump_buffer(new_buffer, + buffer_desc->buffer.length, DB_BYTE_DISPLAY, + 0); + } + + /* First 32-bit dword */ + + acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Revision", pld_info->revision); + acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_IgnoreColor", + pld_info->ignore_color); + acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Red", pld_info->red); + acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Green", pld_info->green); + acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Blue", pld_info->blue); + + /* Second 32-bit dword */ + + acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Width", pld_info->width); + acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Height", pld_info->height); + + /* Third 32-bit dword */ + + acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_UserVisible", + pld_info->user_visible); + acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Dock", pld_info->dock); + acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Lid", pld_info->lid); + acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Panel", pld_info->panel); + acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_VerticalPosition", + pld_info->vertical_position); + acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_HorizontalPosition", + pld_info->horizontal_position); + acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Shape", pld_info->shape); + acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_GroupOrientation", + pld_info->group_orientation); + acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_GroupToken", + pld_info->group_token); + acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_GroupPosition", + pld_info->group_position); + acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Bay", pld_info->bay); + + /* Fourth 32-bit dword */ + + acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Ejectable", pld_info->ejectable); + acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_EjectRequired", + pld_info->ospm_eject_required); + acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_CabinetNumber", + pld_info->cabinet_number); + acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_CardCageNumber", + pld_info->card_cage_number); + acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Reference", pld_info->reference); + acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Rotation", pld_info->rotation); + acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Order", pld_info->order); + + /* Fifth 32-bit dword */ + + if (buffer_desc->buffer.length > 16) { + acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_VerticalOffset", + pld_info->vertical_offset); + acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_HorizontalOffset", + pld_info->horizontal_offset); + } + + ACPI_FREE(pld_info); + ACPI_FREE(new_buffer); +} diff --git a/kernel/drivers/acpi/acpica/dbdisply.c b/kernel/drivers/acpi/acpica/dbdisply.c new file mode 100644 index 000000000..672977ec7 --- /dev/null +++ b/kernel/drivers/acpi/acpica/dbdisply.c @@ -0,0 +1,1108 @@ +/******************************************************************************* + * + * Module Name: dbdisply - debug display commands + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2015, 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 +#include "accommon.h" +#include "amlcode.h" +#include "acdispat.h" +#include "acnamesp.h" +#include "acparser.h" +#include "acinterp.h" +#include "acdebug.h" + +#define _COMPONENT ACPI_CA_DEBUGGER +ACPI_MODULE_NAME("dbdisply") + +/* Local prototypes */ +static void acpi_db_dump_parser_descriptor(union acpi_parse_object *op); + +static void *acpi_db_get_pointer(void *target); + +static acpi_status +acpi_db_display_non_root_handlers(acpi_handle obj_handle, + u32 nesting_level, + void *context, void **return_value); + +/* + * System handler information. + * Used for Handlers command, in acpi_db_display_handlers. + */ +#define ACPI_PREDEFINED_PREFIX "%25s (%.2X) : " +#define ACPI_HANDLER_NAME_STRING "%30s : " +#define ACPI_HANDLER_PRESENT_STRING "%-9s (%p)\n" +#define ACPI_HANDLER_PRESENT_STRING2 "%-9s (%p)" +#define ACPI_HANDLER_NOT_PRESENT_STRING "%-9s\n" + +/* All predefined Address Space IDs */ + +static acpi_adr_space_type acpi_gbl_space_id_list[] = { + ACPI_ADR_SPACE_SYSTEM_MEMORY, + ACPI_ADR_SPACE_SYSTEM_IO, + ACPI_ADR_SPACE_PCI_CONFIG, + ACPI_ADR_SPACE_EC, + ACPI_ADR_SPACE_SMBUS, + ACPI_ADR_SPACE_CMOS, + ACPI_ADR_SPACE_PCI_BAR_TARGET, + ACPI_ADR_SPACE_IPMI, + ACPI_ADR_SPACE_GPIO, + ACPI_ADR_SPACE_GSBUS, + ACPI_ADR_SPACE_DATA_TABLE, + ACPI_ADR_SPACE_FIXED_HARDWARE +}; + +/* Global handler information */ + +typedef struct acpi_handler_info { + void *handler; + char *name; + +} acpi_handler_info; + +static struct acpi_handler_info acpi_gbl_handler_list[] = { + {&acpi_gbl_global_notify[0].handler, "System Notifications"}, + {&acpi_gbl_global_notify[1].handler, "Device Notifications"}, + {&acpi_gbl_table_handler, "ACPI Table Events"}, + {&acpi_gbl_exception_handler, "Control Method Exceptions"}, + {&acpi_gbl_interface_handler, "OSI Invocations"} +}; + +/******************************************************************************* + * + * FUNCTION: acpi_db_get_pointer + * + * PARAMETERS: target - Pointer to string to be converted + * + * RETURN: Converted pointer + * + * DESCRIPTION: Convert an ascii pointer value to a real value + * + ******************************************************************************/ + +static void *acpi_db_get_pointer(void *target) +{ + void *obj_ptr; + acpi_size address; + + address = strtoul(target, NULL, 16); + obj_ptr = ACPI_TO_POINTER(address); + return (obj_ptr); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_dump_parser_descriptor + * + * PARAMETERS: op - A parser Op descriptor + * + * RETURN: None + * + * DESCRIPTION: Display a formatted parser object + * + ******************************************************************************/ + +static void acpi_db_dump_parser_descriptor(union acpi_parse_object *op) +{ + const struct acpi_opcode_info *info; + + info = acpi_ps_get_opcode_info(op->common.aml_opcode); + + acpi_os_printf("Parser Op Descriptor:\n"); + acpi_os_printf("%20.20s : %4.4X\n", "Opcode", op->common.aml_opcode); + + ACPI_DEBUG_ONLY_MEMBERS(acpi_os_printf("%20.20s : %s\n", "Opcode Name", + info->name)); + + acpi_os_printf("%20.20s : %p\n", "Value/ArgList", op->common.value.arg); + acpi_os_printf("%20.20s : %p\n", "Parent", op->common.parent); + acpi_os_printf("%20.20s : %p\n", "NextOp", op->common.next); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_decode_and_display_object + * + * PARAMETERS: target - String with object to be displayed. Names + * and hex pointers are supported. + * output_type - Byte, Word, Dword, or Qword (B|W|D|Q) + * + * RETURN: None + * + * DESCRIPTION: Display a formatted ACPI object + * + ******************************************************************************/ + +void acpi_db_decode_and_display_object(char *target, char *output_type) +{ + void *obj_ptr; + struct acpi_namespace_node *node; + union acpi_operand_object *obj_desc; + u32 display = DB_BYTE_DISPLAY; + char buffer[80]; + struct acpi_buffer ret_buf; + acpi_status status; + u32 size; + + if (!target) { + return; + } + + /* Decode the output type */ + + if (output_type) { + acpi_ut_strupr(output_type); + if (output_type[0] == 'W') { + display = DB_WORD_DISPLAY; + } else if (output_type[0] == 'D') { + display = DB_DWORD_DISPLAY; + } else if (output_type[0] == 'Q') { + display = DB_QWORD_DISPLAY; + } + } + + ret_buf.length = sizeof(buffer); + ret_buf.pointer = buffer; + + /* Differentiate between a number and a name */ + + if ((target[0] >= 0x30) && (target[0] <= 0x39)) { + obj_ptr = acpi_db_get_pointer(target); + if (!acpi_os_readable(obj_ptr, 16)) { + acpi_os_printf + ("Address %p is invalid in this address space\n", + obj_ptr); + return; + } + + /* Decode the object type */ + + switch (ACPI_GET_DESCRIPTOR_TYPE(obj_ptr)) { + case ACPI_DESC_TYPE_NAMED: + + /* This is a namespace Node */ + + if (!acpi_os_readable + (obj_ptr, sizeof(struct acpi_namespace_node))) { + acpi_os_printf + ("Cannot read entire Named object at address %p\n", + obj_ptr); + return; + } + + node = obj_ptr; + goto dump_node; + + case ACPI_DESC_TYPE_OPERAND: + + /* This is a ACPI OPERAND OBJECT */ + + if (!acpi_os_readable + (obj_ptr, sizeof(union acpi_operand_object))) { + acpi_os_printf + ("Cannot read entire ACPI object at address %p\n", + obj_ptr); + return; + } + + acpi_ut_debug_dump_buffer(obj_ptr, + sizeof(union + acpi_operand_object), + display, ACPI_UINT32_MAX); + acpi_ex_dump_object_descriptor(obj_ptr, 1); + break; + + case ACPI_DESC_TYPE_PARSER: + + /* This is a Parser Op object */ + + if (!acpi_os_readable + (obj_ptr, sizeof(union acpi_parse_object))) { + acpi_os_printf + ("Cannot read entire Parser object at address %p\n", + obj_ptr); + return; + } + + acpi_ut_debug_dump_buffer(obj_ptr, + sizeof(union + acpi_parse_object), + display, ACPI_UINT32_MAX); + acpi_db_dump_parser_descriptor((union acpi_parse_object + *)obj_ptr); + break; + + default: + + /* Is not a recognizeable object */ + + acpi_os_printf + ("Not a known ACPI internal object, descriptor type %2.2X\n", + ACPI_GET_DESCRIPTOR_TYPE(obj_ptr)); + + size = 16; + if (acpi_os_readable(obj_ptr, 64)) { + size = 64; + } + + /* Just dump some memory */ + + acpi_ut_debug_dump_buffer(obj_ptr, size, display, + ACPI_UINT32_MAX); + break; + } + + return; + } + + /* The parameter is a name string that must be resolved to a Named obj */ + + node = acpi_db_local_ns_lookup(target); + if (!node) { + return; + } + +dump_node: + /* Now dump the NS node */ + + status = acpi_get_name(node, ACPI_FULL_PATHNAME_NO_TRAILING, &ret_buf); + if (ACPI_FAILURE(status)) { + acpi_os_printf("Could not convert name to pathname\n"); + } + + else { + acpi_os_printf("Object (%p) Pathname: %s\n", + node, (char *)ret_buf.pointer); + } + + if (!acpi_os_readable(node, sizeof(struct acpi_namespace_node))) { + acpi_os_printf("Invalid Named object at address %p\n", node); + return; + } + + acpi_ut_debug_dump_buffer((void *)node, + sizeof(struct acpi_namespace_node), display, + ACPI_UINT32_MAX); + acpi_ex_dump_namespace_node(node, 1); + + obj_desc = acpi_ns_get_attached_object(node); + if (obj_desc) { + acpi_os_printf("\nAttached Object (%p):\n", obj_desc); + if (!acpi_os_readable + (obj_desc, sizeof(union acpi_operand_object))) { + acpi_os_printf + ("Invalid internal ACPI Object at address %p\n", + obj_desc); + return; + } + + acpi_ut_debug_dump_buffer((void *)obj_desc, + sizeof(union acpi_operand_object), + display, ACPI_UINT32_MAX); + acpi_ex_dump_object_descriptor(obj_desc, 1); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_display_method_info + * + * PARAMETERS: start_op - Root of the control method parse tree + * + * RETURN: None + * + * DESCRIPTION: Display information about the current method + * + ******************************************************************************/ + +void acpi_db_display_method_info(union acpi_parse_object *start_op) +{ + struct acpi_walk_state *walk_state; + union acpi_operand_object *obj_desc; + struct acpi_namespace_node *node; + union acpi_parse_object *root_op; + union acpi_parse_object *op; + const struct acpi_opcode_info *op_info; + u32 num_ops = 0; + u32 num_operands = 0; + u32 num_operators = 0; + u32 num_remaining_ops = 0; + u32 num_remaining_operands = 0; + u32 num_remaining_operators = 0; + u8 count_remaining = FALSE; + + walk_state = acpi_ds_get_current_walk_state(acpi_gbl_current_walk_list); + if (!walk_state) { + acpi_os_printf("There is no method currently executing\n"); + return; + } + + obj_desc = walk_state->method_desc; + node = walk_state->method_node; + + acpi_os_printf("Currently executing control method is [%4.4s]\n", + acpi_ut_get_node_name(node)); + acpi_os_printf("%X Arguments, SyncLevel = %X\n", + (u32)obj_desc->method.param_count, + (u32)obj_desc->method.sync_level); + + root_op = start_op; + while (root_op->common.parent) { + root_op = root_op->common.parent; + } + + op = root_op; + + while (op) { + if (op == start_op) { + count_remaining = TRUE; + } + + num_ops++; + if (count_remaining) { + num_remaining_ops++; + } + + /* Decode the opcode */ + + op_info = acpi_ps_get_opcode_info(op->common.aml_opcode); + switch (op_info->class) { + case AML_CLASS_ARGUMENT: + + if (count_remaining) { + num_remaining_operands++; + } + + num_operands++; + break; + + case AML_CLASS_UNKNOWN: + + /* Bad opcode or ASCII character */ + + continue; + + default: + + if (count_remaining) { + num_remaining_operators++; + } + + num_operators++; + break; + } + + op = acpi_ps_get_depth_next(start_op, op); + } + + acpi_os_printf + ("Method contains: %X AML Opcodes - %X Operators, %X Operands\n", + num_ops, num_operators, num_operands); + + acpi_os_printf + ("Remaining to execute: %X AML Opcodes - %X Operators, %X Operands\n", + num_remaining_ops, num_remaining_operators, + num_remaining_operands); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_display_locals + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Display all locals for the currently running control method + * + ******************************************************************************/ + +void acpi_db_display_locals(void) +{ + struct acpi_walk_state *walk_state; + + walk_state = acpi_ds_get_current_walk_state(acpi_gbl_current_walk_list); + if (!walk_state) { + acpi_os_printf("There is no method currently executing\n"); + return; + } + + acpi_db_decode_locals(walk_state); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_display_arguments + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Display all arguments for the currently running control method + * + ******************************************************************************/ + +void acpi_db_display_arguments(void) +{ + struct acpi_walk_state *walk_state; + + walk_state = acpi_ds_get_current_walk_state(acpi_gbl_current_walk_list); + if (!walk_state) { + acpi_os_printf("There is no method currently executing\n"); + return; + } + + acpi_db_decode_arguments(walk_state); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_display_results + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Display current contents of a method result stack + * + ******************************************************************************/ + +void acpi_db_display_results(void) +{ + u32 i; + struct acpi_walk_state *walk_state; + union acpi_operand_object *obj_desc; + u32 result_count = 0; + struct acpi_namespace_node *node; + union acpi_generic_state *frame; + u32 index; /* Index onto current frame */ + + walk_state = acpi_ds_get_current_walk_state(acpi_gbl_current_walk_list); + if (!walk_state) { + acpi_os_printf("There is no method currently executing\n"); + return; + } + + obj_desc = walk_state->method_desc; + node = walk_state->method_node; + + if (walk_state->results) { + result_count = walk_state->result_count; + } + + acpi_os_printf("Method [%4.4s] has %X stacked result objects\n", + acpi_ut_get_node_name(node), result_count); + + /* From the top element of result stack */ + + frame = walk_state->results; + index = (result_count - 1) % ACPI_RESULTS_FRAME_OBJ_NUM; + + for (i = 0; i < result_count; i++) { + obj_desc = frame->results.obj_desc[index]; + acpi_os_printf("Result%u: ", i); + acpi_db_display_internal_object(obj_desc, walk_state); + + if (index == 0) { + frame = frame->results.next; + index = ACPI_RESULTS_FRAME_OBJ_NUM; + } + + index--; + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_display_calling_tree + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Display current calling tree of nested control methods + * + ******************************************************************************/ + +void acpi_db_display_calling_tree(void) +{ + struct acpi_walk_state *walk_state; + struct acpi_namespace_node *node; + + walk_state = acpi_ds_get_current_walk_state(acpi_gbl_current_walk_list); + if (!walk_state) { + acpi_os_printf("There is no method currently executing\n"); + return; + } + + node = walk_state->method_node; + acpi_os_printf("Current Control Method Call Tree\n"); + + while (walk_state) { + node = walk_state->method_node; + acpi_os_printf(" [%4.4s]\n", acpi_ut_get_node_name(node)); + + walk_state = walk_state->next; + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_display_object_type + * + * PARAMETERS: name - User entered NS node handle or name + * + * RETURN: None + * + * DESCRIPTION: Display type of an arbitrary NS node + * + ******************************************************************************/ + +void acpi_db_display_object_type(char *name) +{ + struct acpi_namespace_node *node; + struct acpi_device_info *info; + acpi_status status; + u32 i; + + node = acpi_db_convert_to_node(name); + if (!node) { + return; + } + + status = acpi_get_object_info(ACPI_CAST_PTR(acpi_handle, node), &info); + if (ACPI_FAILURE(status)) { + acpi_os_printf("Could not get object info, %s\n", + acpi_format_exception(status)); + return; + } + + if (info->valid & ACPI_VALID_ADR) { + acpi_os_printf("ADR: %8.8X%8.8X, STA: %8.8X, Flags: %X\n", + ACPI_FORMAT_UINT64(info->address), + info->current_status, info->flags); + } + if (info->valid & ACPI_VALID_SXDS) { + acpi_os_printf("S1D-%2.2X S2D-%2.2X S3D-%2.2X S4D-%2.2X\n", + info->highest_dstates[0], + info->highest_dstates[1], + info->highest_dstates[2], + info->highest_dstates[3]); + } + if (info->valid & ACPI_VALID_SXWS) { + acpi_os_printf + ("S0W-%2.2X S1W-%2.2X S2W-%2.2X S3W-%2.2X S4W-%2.2X\n", + info->lowest_dstates[0], info->lowest_dstates[1], + info->lowest_dstates[2], info->lowest_dstates[3], + info->lowest_dstates[4]); + } + + if (info->valid & ACPI_VALID_HID) { + acpi_os_printf("HID: %s\n", info->hardware_id.string); + } + + if (info->valid & ACPI_VALID_UID) { + acpi_os_printf("UID: %s\n", info->unique_id.string); + } + + if (info->valid & ACPI_VALID_SUB) { + acpi_os_printf("SUB: %s\n", info->subsystem_id.string); + } + + if (info->valid & ACPI_VALID_CID) { + for (i = 0; i < info->compatible_id_list.count; i++) { + acpi_os_printf("CID %u: %s\n", i, + info->compatible_id_list.ids[i].string); + } + } + + ACPI_FREE(info); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_display_result_object + * + * PARAMETERS: obj_desc - Object to be displayed + * walk_state - Current walk state + * + * RETURN: None + * + * DESCRIPTION: Display the result of an AML opcode + * + * Note: Curently only displays the result object if we are single stepping. + * However, this output may be useful in other contexts and could be enabled + * to do so if needed. + * + ******************************************************************************/ + +void +acpi_db_display_result_object(union acpi_operand_object *obj_desc, + struct acpi_walk_state *walk_state) +{ + + /* Only display if single stepping */ + + if (!acpi_gbl_cm_single_step) { + return; + } + + acpi_os_printf("ResultObj: "); + acpi_db_display_internal_object(obj_desc, walk_state); + acpi_os_printf("\n"); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_display_argument_object + * + * PARAMETERS: obj_desc - Object to be displayed + * walk_state - Current walk state + * + * RETURN: None + * + * DESCRIPTION: Display the result of an AML opcode + * + ******************************************************************************/ + +void +acpi_db_display_argument_object(union acpi_operand_object *obj_desc, + struct acpi_walk_state *walk_state) +{ + + if (!acpi_gbl_cm_single_step) { + return; + } + + acpi_os_printf("ArgObj: "); + acpi_db_display_internal_object(obj_desc, walk_state); +} + +#if (!ACPI_REDUCED_HARDWARE) +/******************************************************************************* + * + * FUNCTION: acpi_db_display_gpes + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Display the current GPE structures + * + ******************************************************************************/ + +void acpi_db_display_gpes(void) +{ + struct acpi_gpe_block_info *gpe_block; + struct acpi_gpe_xrupt_info *gpe_xrupt_info; + struct acpi_gpe_event_info *gpe_event_info; + struct acpi_gpe_register_info *gpe_register_info; + char *gpe_type; + struct acpi_gpe_notify_info *notify; + u32 gpe_index; + u32 block = 0; + u32 i; + u32 j; + u32 count; + char buffer[80]; + struct acpi_buffer ret_buf; + acpi_status status; + + ret_buf.length = sizeof(buffer); + ret_buf.pointer = buffer; + + block = 0; + + /* Walk the GPE lists */ + + gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head; + while (gpe_xrupt_info) { + gpe_block = gpe_xrupt_info->gpe_block_list_head; + while (gpe_block) { + status = acpi_get_name(gpe_block->node, + ACPI_FULL_PATHNAME_NO_TRAILING, + &ret_buf); + if (ACPI_FAILURE(status)) { + acpi_os_printf + ("Could not convert name to pathname\n"); + } + + if (gpe_block->node == acpi_gbl_fadt_gpe_device) { + gpe_type = "FADT-defined GPE block"; + } else { + gpe_type = "GPE Block Device"; + } + + acpi_os_printf + ("\nBlock %u - Info %p DeviceNode %p [%s] - %s\n", + block, gpe_block, gpe_block->node, buffer, + gpe_type); + + acpi_os_printf(" Registers: %u (%u GPEs)\n", + gpe_block->register_count, + gpe_block->gpe_count); + + acpi_os_printf + (" GPE range: 0x%X to 0x%X on interrupt %u\n", + gpe_block->block_base_number, + gpe_block->block_base_number + + (gpe_block->gpe_count - 1), + gpe_xrupt_info->interrupt_number); + + acpi_os_printf + (" RegisterInfo: %p Status %8.8X%8.8X Enable %8.8X%8.8X\n", + gpe_block->register_info, + ACPI_FORMAT_UINT64(gpe_block->register_info-> + status_address.address), + ACPI_FORMAT_UINT64(gpe_block->register_info-> + enable_address.address)); + + acpi_os_printf(" EventInfo: %p\n", + gpe_block->event_info); + + /* Examine each GPE Register within the block */ + + for (i = 0; i < gpe_block->register_count; i++) { + gpe_register_info = + &gpe_block->register_info[i]; + + acpi_os_printf(" Reg %u: (GPE %.2X-%.2X) " + "RunEnable %2.2X WakeEnable %2.2X" + " Status %8.8X%8.8X Enable %8.8X%8.8X\n", + i, + gpe_register_info-> + base_gpe_number, + gpe_register_info-> + base_gpe_number + + (ACPI_GPE_REGISTER_WIDTH - 1), + gpe_register_info-> + enable_for_run, + gpe_register_info-> + enable_for_wake, + ACPI_FORMAT_UINT64 + (gpe_register_info-> + status_address.address), + ACPI_FORMAT_UINT64 + (gpe_register_info-> + enable_address.address)); + + /* Now look at the individual GPEs in this byte register */ + + for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { + gpe_index = + (i * ACPI_GPE_REGISTER_WIDTH) + j; + gpe_event_info = + &gpe_block->event_info[gpe_index]; + + if (ACPI_GPE_DISPATCH_TYPE + (gpe_event_info->flags) == + ACPI_GPE_DISPATCH_NONE) { + + /* This GPE is not used (no method or handler), ignore it */ + + continue; + } + + acpi_os_printf + (" GPE %.2X: %p RunRefs %2.2X Flags %2.2X (", + gpe_block->block_base_number + + gpe_index, gpe_event_info, + gpe_event_info->runtime_count, + gpe_event_info->flags); + + /* Decode the flags byte */ + + if (gpe_event_info-> + flags & ACPI_GPE_LEVEL_TRIGGERED) { + acpi_os_printf("Level, "); + } else { + acpi_os_printf("Edge, "); + } + + if (gpe_event_info-> + flags & ACPI_GPE_CAN_WAKE) { + acpi_os_printf("CanWake, "); + } else { + acpi_os_printf("RunOnly, "); + } + + switch (ACPI_GPE_DISPATCH_TYPE + (gpe_event_info->flags)) { + case ACPI_GPE_DISPATCH_NONE: + + acpi_os_printf("NotUsed"); + break; + + case ACPI_GPE_DISPATCH_METHOD: + + acpi_os_printf("Method"); + break; + + case ACPI_GPE_DISPATCH_HANDLER: + + acpi_os_printf("Handler"); + break; + + case ACPI_GPE_DISPATCH_NOTIFY: + + count = 0; + notify = + gpe_event_info->dispatch. + notify_list; + while (notify) { + count++; + notify = notify->next; + } + + acpi_os_printf + ("Implicit Notify on %u devices", + count); + break; + + case ACPI_GPE_DISPATCH_RAW_HANDLER: + + acpi_os_printf("RawHandler"); + break; + + default: + + acpi_os_printf("UNKNOWN: %X", + ACPI_GPE_DISPATCH_TYPE + (gpe_event_info-> + flags)); + break; + } + + acpi_os_printf(")\n"); + } + } + + block++; + gpe_block = gpe_block->next; + } + + gpe_xrupt_info = gpe_xrupt_info->next; + } +} +#endif /* !ACPI_REDUCED_HARDWARE */ + +/******************************************************************************* + * + * FUNCTION: acpi_db_display_handlers + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Display the currently installed global handlers + * + ******************************************************************************/ + +void acpi_db_display_handlers(void) +{ + union acpi_operand_object *obj_desc; + union acpi_operand_object *handler_obj; + acpi_adr_space_type space_id; + u32 i; + + /* Operation region handlers */ + + acpi_os_printf("\nOperation Region Handlers at the namespace root:\n"); + + obj_desc = acpi_ns_get_attached_object(acpi_gbl_root_node); + if (obj_desc) { + for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_gbl_space_id_list); i++) { + space_id = acpi_gbl_space_id_list[i]; + handler_obj = obj_desc->device.handler; + + acpi_os_printf(ACPI_PREDEFINED_PREFIX, + acpi_ut_get_region_name((u8)space_id), + space_id); + + while (handler_obj) { + if (acpi_gbl_space_id_list[i] == + handler_obj->address_space.space_id) { + acpi_os_printf + (ACPI_HANDLER_PRESENT_STRING, + (handler_obj->address_space. + handler_flags & + ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) + ? "Default" : "User", + handler_obj->address_space. + handler); + + goto found_handler; + } + + handler_obj = handler_obj->address_space.next; + } + + /* There is no handler for this space_id */ + + acpi_os_printf("None\n"); + +found_handler: ; + } + + /* Find all handlers for user-defined space_IDs */ + + handler_obj = obj_desc->device.handler; + while (handler_obj) { + if (handler_obj->address_space.space_id >= + ACPI_USER_REGION_BEGIN) { + acpi_os_printf(ACPI_PREDEFINED_PREFIX, + "User-defined ID", + handler_obj->address_space. + space_id); + acpi_os_printf(ACPI_HANDLER_PRESENT_STRING, + (handler_obj->address_space. + handler_flags & + ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) + ? "Default" : "User", + handler_obj->address_space. + handler); + } + + handler_obj = handler_obj->address_space.next; + } + } +#if (!ACPI_REDUCED_HARDWARE) + + /* Fixed event handlers */ + + acpi_os_printf("\nFixed Event Handlers:\n"); + + for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { + acpi_os_printf(ACPI_PREDEFINED_PREFIX, + acpi_ut_get_event_name(i), i); + if (acpi_gbl_fixed_event_handlers[i].handler) { + acpi_os_printf(ACPI_HANDLER_PRESENT_STRING, "User", + acpi_gbl_fixed_event_handlers[i]. + handler); + } else { + acpi_os_printf(ACPI_HANDLER_NOT_PRESENT_STRING, "None"); + } + } + +#endif /* !ACPI_REDUCED_HARDWARE */ + + /* Miscellaneous global handlers */ + + acpi_os_printf("\nMiscellaneous Global Handlers:\n"); + + for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_gbl_handler_list); i++) { + acpi_os_printf(ACPI_HANDLER_NAME_STRING, + acpi_gbl_handler_list[i].name); + + if (acpi_gbl_handler_list[i].handler) { + acpi_os_printf(ACPI_HANDLER_PRESENT_STRING, "User", + acpi_gbl_handler_list[i].handler); + } else { + acpi_os_printf(ACPI_HANDLER_NOT_PRESENT_STRING, "None"); + } + } + + /* Other handlers that are installed throughout the namespace */ + + acpi_os_printf("\nOperation Region Handlers for specific devices:\n"); + + (void)acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, + acpi_db_display_non_root_handlers, NULL, NULL, + NULL); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_display_non_root_handlers + * + * PARAMETERS: acpi_walk_callback + * + * RETURN: Status + * + * DESCRIPTION: Display information about all handlers installed for a + * device object. + * + ******************************************************************************/ + +static acpi_status +acpi_db_display_non_root_handlers(acpi_handle obj_handle, + u32 nesting_level, + void *context, void **return_value) +{ + struct acpi_namespace_node *node = + ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle); + union acpi_operand_object *obj_desc; + union acpi_operand_object *handler_obj; + char *pathname; + + obj_desc = acpi_ns_get_attached_object(node); + if (!obj_desc) { + return (AE_OK); + } + + pathname = acpi_ns_get_external_pathname(node); + if (!pathname) { + return (AE_OK); + } + + /* Display all handlers associated with this device */ + + handler_obj = obj_desc->device.handler; + while (handler_obj) { + acpi_os_printf(ACPI_PREDEFINED_PREFIX, + acpi_ut_get_region_name((u8)handler_obj-> + address_space.space_id), + handler_obj->address_space.space_id); + + acpi_os_printf(ACPI_HANDLER_PRESENT_STRING2, + (handler_obj->address_space.handler_flags & + ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) ? "Default" + : "User", handler_obj->address_space.handler); + + acpi_os_printf(" Device Name: %s (%p)\n", pathname, node); + + handler_obj = handler_obj->address_space.next; + } + + ACPI_FREE(pathname); + return (AE_OK); +} diff --git a/kernel/drivers/acpi/acpica/dbexec.c b/kernel/drivers/acpi/acpica/dbexec.c new file mode 100644 index 000000000..d713e2df6 --- /dev/null +++ b/kernel/drivers/acpi/acpica/dbexec.c @@ -0,0 +1,764 @@ +/******************************************************************************* + * + * Module Name: dbexec - debugger control method execution + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2015, 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 +#include "accommon.h" +#include "acdebug.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_CA_DEBUGGER +ACPI_MODULE_NAME("dbexec") + +static struct acpi_db_method_info acpi_gbl_db_method_info; + +/* Local prototypes */ + +static acpi_status +acpi_db_execute_method(struct acpi_db_method_info *info, + struct acpi_buffer *return_obj); + +static acpi_status acpi_db_execute_setup(struct acpi_db_method_info *info); + +static u32 acpi_db_get_outstanding_allocations(void); + +static void ACPI_SYSTEM_XFACE acpi_db_method_thread(void *context); + +static acpi_status +acpi_db_execution_walk(acpi_handle obj_handle, + u32 nesting_level, void *context, void **return_value); + +/******************************************************************************* + * + * FUNCTION: acpi_db_delete_objects + * + * PARAMETERS: count - Count of objects in the list + * objects - Array of ACPI_OBJECTs to be deleted + * + * RETURN: None + * + * DESCRIPTION: Delete a list of ACPI_OBJECTS. Handles packages and nested + * packages via recursion. + * + ******************************************************************************/ + +void acpi_db_delete_objects(u32 count, union acpi_object *objects) +{ + u32 i; + + for (i = 0; i < count; i++) { + switch (objects[i].type) { + case ACPI_TYPE_BUFFER: + + ACPI_FREE(objects[i].buffer.pointer); + break; + + case ACPI_TYPE_PACKAGE: + + /* Recursive call to delete package elements */ + + acpi_db_delete_objects(objects[i].package.count, + objects[i].package.elements); + + /* Free the elements array */ + + ACPI_FREE(objects[i].package.elements); + break; + + default: + + break; + } + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_execute_method + * + * PARAMETERS: info - Valid info segment + * return_obj - Where to put return object + * + * RETURN: Status + * + * DESCRIPTION: Execute a control method. + * + ******************************************************************************/ + +static acpi_status +acpi_db_execute_method(struct acpi_db_method_info *info, + struct acpi_buffer *return_obj) +{ + acpi_status status; + struct acpi_object_list param_objects; + union acpi_object params[ACPI_DEBUGGER_MAX_ARGS + 1]; + u32 i; + + ACPI_FUNCTION_TRACE(db_execute_method); + + if (acpi_gbl_db_output_to_file && !acpi_dbg_level) { + acpi_os_printf("Warning: debug output is not enabled!\n"); + } + + param_objects.count = 0; + param_objects.pointer = NULL; + + /* Pass through any command-line arguments */ + + if (info->args && info->args[0]) { + + /* Get arguments passed on the command line */ + + for (i = 0; (info->args[i] && *(info->args[i])); i++) { + + /* Convert input string (token) to an actual union acpi_object */ + + status = acpi_db_convert_to_object(info->types[i], + info->args[i], + ¶ms[i]); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "While parsing method arguments")); + goto cleanup; + } + } + + param_objects.count = i; + param_objects.pointer = params; + } + + /* Prepare for a return object of arbitrary size */ + + return_obj->pointer = acpi_gbl_db_buffer; + return_obj->length = ACPI_DEBUG_BUFFER_SIZE; + + /* Do the actual method execution */ + + acpi_gbl_method_executing = TRUE; + status = acpi_evaluate_object(NULL, info->pathname, + ¶m_objects, return_obj); + + acpi_gbl_cm_single_step = FALSE; + acpi_gbl_method_executing = FALSE; + + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "while executing %s from debugger", + info->pathname)); + + if (status == AE_BUFFER_OVERFLOW) { + ACPI_ERROR((AE_INFO, + "Possible overflow of internal debugger " + "buffer (size 0x%X needed 0x%X)", + ACPI_DEBUG_BUFFER_SIZE, + (u32)return_obj->length)); + } + } + +cleanup: + acpi_db_delete_objects(param_objects.count, params); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_execute_setup + * + * PARAMETERS: info - Valid method info + * + * RETURN: None + * + * DESCRIPTION: Setup info segment prior to method execution + * + ******************************************************************************/ + +static acpi_status acpi_db_execute_setup(struct acpi_db_method_info *info) +{ + acpi_status status; + + ACPI_FUNCTION_NAME(db_execute_setup); + + /* Catenate the current scope to the supplied name */ + + info->pathname[0] = 0; + if ((info->name[0] != '\\') && (info->name[0] != '/')) { + if (acpi_ut_safe_strcat(info->pathname, sizeof(info->pathname), + acpi_gbl_db_scope_buf)) { + status = AE_BUFFER_OVERFLOW; + goto error_exit; + } + } + + if (acpi_ut_safe_strcat(info->pathname, sizeof(info->pathname), + info->name)) { + status = AE_BUFFER_OVERFLOW; + goto error_exit; + } + + acpi_db_prep_namestring(info->pathname); + + acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT); + acpi_os_printf("Evaluating %s\n", info->pathname); + + if (info->flags & EX_SINGLE_STEP) { + acpi_gbl_cm_single_step = TRUE; + acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); + } + + else { + /* No single step, allow redirection to a file */ + + acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT); + } + + return (AE_OK); + +error_exit: + + ACPI_EXCEPTION((AE_INFO, status, "During setup for method execution")); + return (status); +} + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS +u32 acpi_db_get_cache_info(struct acpi_memory_list *cache) +{ + + return (cache->total_allocated - cache->total_freed - + cache->current_depth); +} +#endif + +/******************************************************************************* + * + * FUNCTION: acpi_db_get_outstanding_allocations + * + * PARAMETERS: None + * + * RETURN: Current global allocation count minus cache entries + * + * DESCRIPTION: Determine the current number of "outstanding" allocations -- + * those allocations that have not been freed and also are not + * in one of the various object caches. + * + ******************************************************************************/ + +static u32 acpi_db_get_outstanding_allocations(void) +{ + u32 outstanding = 0; + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + + outstanding += acpi_db_get_cache_info(acpi_gbl_state_cache); + outstanding += acpi_db_get_cache_info(acpi_gbl_ps_node_cache); + outstanding += acpi_db_get_cache_info(acpi_gbl_ps_node_ext_cache); + outstanding += acpi_db_get_cache_info(acpi_gbl_operand_cache); +#endif + + return (outstanding); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_execution_walk + * + * PARAMETERS: WALK_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Execute a control method. Name is relative to the current + * scope. + * + ******************************************************************************/ + +static acpi_status +acpi_db_execution_walk(acpi_handle obj_handle, + u32 nesting_level, void *context, void **return_value) +{ + union acpi_operand_object *obj_desc; + struct acpi_namespace_node *node = + (struct acpi_namespace_node *)obj_handle; + struct acpi_buffer return_obj; + acpi_status status; + + obj_desc = acpi_ns_get_attached_object(node); + if (obj_desc->method.param_count) { + return (AE_OK); + } + + return_obj.pointer = NULL; + return_obj.length = ACPI_ALLOCATE_BUFFER; + + acpi_ns_print_node_pathname(node, "Evaluating"); + + /* Do the actual method execution */ + + acpi_os_printf("\n"); + acpi_gbl_method_executing = TRUE; + + status = acpi_evaluate_object(node, NULL, NULL, &return_obj); + + acpi_os_printf("Evaluation of [%4.4s] returned %s\n", + acpi_ut_get_node_name(node), + acpi_format_exception(status)); + + acpi_gbl_method_executing = FALSE; + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_execute + * + * PARAMETERS: name - Name of method to execute + * args - Parameters to the method + * Types - + * flags - single step/no single step + * + * RETURN: None + * + * DESCRIPTION: Execute a control method. Name is relative to the current + * scope. + * + ******************************************************************************/ + +void +acpi_db_execute(char *name, char **args, acpi_object_type * types, u32 flags) +{ + acpi_status status; + struct acpi_buffer return_obj; + char *name_string; + +#ifdef ACPI_DEBUG_OUTPUT + u32 previous_allocations; + u32 allocations; +#endif + + /* + * Allow one execution to be performed by debugger or single step + * execution will be dead locked by the interpreter mutexes. + */ + if (acpi_gbl_method_executing) { + acpi_os_printf("Only one debugger execution is allowed.\n"); + return; + } +#ifdef ACPI_DEBUG_OUTPUT + /* Memory allocation tracking */ + + previous_allocations = acpi_db_get_outstanding_allocations(); +#endif + + if (*name == '*') { + (void)acpi_walk_namespace(ACPI_TYPE_METHOD, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, + acpi_db_execution_walk, NULL, NULL, + NULL); + return; + } else { + name_string = ACPI_ALLOCATE(strlen(name) + 1); + if (!name_string) { + return; + } + + memset(&acpi_gbl_db_method_info, 0, + sizeof(struct acpi_db_method_info)); + + strcpy(name_string, name); + acpi_ut_strupr(name_string); + acpi_gbl_db_method_info.name = name_string; + acpi_gbl_db_method_info.args = args; + acpi_gbl_db_method_info.types = types; + acpi_gbl_db_method_info.flags = flags; + + return_obj.pointer = NULL; + return_obj.length = ACPI_ALLOCATE_BUFFER; + + status = acpi_db_execute_setup(&acpi_gbl_db_method_info); + if (ACPI_FAILURE(status)) { + ACPI_FREE(name_string); + return; + } + + /* Get the NS node, determines existence also */ + + status = acpi_get_handle(NULL, acpi_gbl_db_method_info.pathname, + &acpi_gbl_db_method_info.method); + if (ACPI_SUCCESS(status)) { + status = + acpi_db_execute_method(&acpi_gbl_db_method_info, + &return_obj); + } + ACPI_FREE(name_string); + } + + /* + * Allow any handlers in separate threads to complete. + * (Such as Notify handlers invoked from AML executed above). + */ + acpi_os_sleep((u64)10); + +#ifdef ACPI_DEBUG_OUTPUT + + /* Memory allocation tracking */ + + allocations = + acpi_db_get_outstanding_allocations() - previous_allocations; + + acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT); + + if (allocations > 0) { + acpi_os_printf + ("0x%X Outstanding allocations after evaluation of %s\n", + allocations, acpi_gbl_db_method_info.pathname); + } +#endif + + if (ACPI_FAILURE(status)) { + acpi_os_printf("Evaluation of %s failed with status %s\n", + acpi_gbl_db_method_info.pathname, + acpi_format_exception(status)); + } else { + /* Display a return object, if any */ + + if (return_obj.length) { + acpi_os_printf("Evaluation of %s returned object %p, " + "external buffer length %X\n", + acpi_gbl_db_method_info.pathname, + return_obj.pointer, + (u32)return_obj.length); + + acpi_db_dump_external_object(return_obj.pointer, 1); + + /* Dump a _PLD buffer if present */ + + if (ACPI_COMPARE_NAME + ((ACPI_CAST_PTR + (struct acpi_namespace_node, + acpi_gbl_db_method_info.method)->name.ascii), + METHOD_NAME__PLD)) { + acpi_db_dump_pld_buffer(return_obj.pointer); + } + } else { + acpi_os_printf + ("No object was returned from evaluation of %s\n", + acpi_gbl_db_method_info.pathname); + } + } + + acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_method_thread + * + * PARAMETERS: context - Execution info segment + * + * RETURN: None + * + * DESCRIPTION: Debugger execute thread. Waits for a command line, then + * simply dispatches it. + * + ******************************************************************************/ + +static void ACPI_SYSTEM_XFACE acpi_db_method_thread(void *context) +{ + acpi_status status; + struct acpi_db_method_info *info = context; + struct acpi_db_method_info local_info; + u32 i; + u8 allow; + struct acpi_buffer return_obj; + + /* + * acpi_gbl_db_method_info.Arguments will be passed as method arguments. + * Prevent acpi_gbl_db_method_info from being modified by multiple threads + * concurrently. + * + * Note: The arguments we are passing are used by the ASL test suite + * (aslts). Do not change them without updating the tests. + */ + (void)acpi_os_wait_semaphore(info->info_gate, 1, ACPI_WAIT_FOREVER); + + if (info->init_args) { + acpi_db_uint32_to_hex_string(info->num_created, + info->index_of_thread_str); + acpi_db_uint32_to_hex_string((u32)acpi_os_get_thread_id(), + info->id_of_thread_str); + } + + if (info->threads && (info->num_created < info->num_threads)) { + info->threads[info->num_created++] = acpi_os_get_thread_id(); + } + + local_info = *info; + local_info.args = local_info.arguments; + local_info.arguments[0] = local_info.num_threads_str; + local_info.arguments[1] = local_info.id_of_thread_str; + local_info.arguments[2] = local_info.index_of_thread_str; + local_info.arguments[3] = NULL; + + local_info.types = local_info.arg_types; + + (void)acpi_os_signal_semaphore(info->info_gate, 1); + + for (i = 0; i < info->num_loops; i++) { + status = acpi_db_execute_method(&local_info, &return_obj); + if (ACPI_FAILURE(status)) { + acpi_os_printf + ("%s During evaluation of %s at iteration %X\n", + acpi_format_exception(status), info->pathname, i); + if (status == AE_ABORT_METHOD) { + break; + } + } +#if 0 + if ((i % 100) == 0) { + acpi_os_printf("%u loops, Thread 0x%x\n", + i, acpi_os_get_thread_id()); + } + + if (return_obj.length) { + acpi_os_printf + ("Evaluation of %s returned object %p Buflen %X\n", + info->pathname, return_obj.pointer, + (u32)return_obj.length); + acpi_db_dump_external_object(return_obj.pointer, 1); + } +#endif + } + + /* Signal our completion */ + + allow = 0; + (void)acpi_os_wait_semaphore(info->thread_complete_gate, + 1, ACPI_WAIT_FOREVER); + info->num_completed++; + + if (info->num_completed == info->num_threads) { + + /* Do signal for main thread once only */ + allow = 1; + } + + (void)acpi_os_signal_semaphore(info->thread_complete_gate, 1); + + if (allow) { + status = acpi_os_signal_semaphore(info->main_thread_gate, 1); + if (ACPI_FAILURE(status)) { + acpi_os_printf + ("Could not signal debugger thread sync semaphore, %s\n", + acpi_format_exception(status)); + } + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_create_execution_threads + * + * PARAMETERS: num_threads_arg - Number of threads to create + * num_loops_arg - Loop count for the thread(s) + * method_name_arg - Control method to execute + * + * RETURN: None + * + * DESCRIPTION: Create threads to execute method(s) + * + ******************************************************************************/ + +void +acpi_db_create_execution_threads(char *num_threads_arg, + char *num_loops_arg, char *method_name_arg) +{ + acpi_status status; + u32 num_threads; + u32 num_loops; + u32 i; + u32 size; + acpi_mutex main_thread_gate; + acpi_mutex thread_complete_gate; + acpi_mutex info_gate; + + /* Get the arguments */ + + num_threads = strtoul(num_threads_arg, NULL, 0); + num_loops = strtoul(num_loops_arg, NULL, 0); + + if (!num_threads || !num_loops) { + acpi_os_printf("Bad argument: Threads %X, Loops %X\n", + num_threads, num_loops); + return; + } + + /* + * Create the semaphore for synchronization of + * the created threads with the main thread. + */ + status = acpi_os_create_semaphore(1, 0, &main_thread_gate); + if (ACPI_FAILURE(status)) { + acpi_os_printf("Could not create semaphore for " + "synchronization with the main thread, %s\n", + acpi_format_exception(status)); + return; + } + + /* + * Create the semaphore for synchronization + * between the created threads. + */ + status = acpi_os_create_semaphore(1, 1, &thread_complete_gate); + if (ACPI_FAILURE(status)) { + acpi_os_printf("Could not create semaphore for " + "synchronization between the created threads, %s\n", + acpi_format_exception(status)); + + (void)acpi_os_delete_semaphore(main_thread_gate); + return; + } + + status = acpi_os_create_semaphore(1, 1, &info_gate); + if (ACPI_FAILURE(status)) { + acpi_os_printf("Could not create semaphore for " + "synchronization of AcpiGbl_DbMethodInfo, %s\n", + acpi_format_exception(status)); + + (void)acpi_os_delete_semaphore(thread_complete_gate); + (void)acpi_os_delete_semaphore(main_thread_gate); + return; + } + + memset(&acpi_gbl_db_method_info, 0, sizeof(struct acpi_db_method_info)); + + /* Array to store IDs of threads */ + + acpi_gbl_db_method_info.num_threads = num_threads; + size = sizeof(acpi_thread_id) * acpi_gbl_db_method_info.num_threads; + + acpi_gbl_db_method_info.threads = acpi_os_allocate(size); + if (acpi_gbl_db_method_info.threads == NULL) { + acpi_os_printf("No memory for thread IDs array\n"); + (void)acpi_os_delete_semaphore(main_thread_gate); + (void)acpi_os_delete_semaphore(thread_complete_gate); + (void)acpi_os_delete_semaphore(info_gate); + return; + } + memset(acpi_gbl_db_method_info.threads, 0, size); + + /* Setup the context to be passed to each thread */ + + acpi_gbl_db_method_info.name = method_name_arg; + acpi_gbl_db_method_info.flags = 0; + acpi_gbl_db_method_info.num_loops = num_loops; + acpi_gbl_db_method_info.main_thread_gate = main_thread_gate; + acpi_gbl_db_method_info.thread_complete_gate = thread_complete_gate; + acpi_gbl_db_method_info.info_gate = info_gate; + + /* Init arguments to be passed to method */ + + acpi_gbl_db_method_info.init_args = 1; + acpi_gbl_db_method_info.args = acpi_gbl_db_method_info.arguments; + acpi_gbl_db_method_info.arguments[0] = + acpi_gbl_db_method_info.num_threads_str; + acpi_gbl_db_method_info.arguments[1] = + acpi_gbl_db_method_info.id_of_thread_str; + acpi_gbl_db_method_info.arguments[2] = + acpi_gbl_db_method_info.index_of_thread_str; + acpi_gbl_db_method_info.arguments[3] = NULL; + + acpi_gbl_db_method_info.types = acpi_gbl_db_method_info.arg_types; + acpi_gbl_db_method_info.arg_types[0] = ACPI_TYPE_INTEGER; + acpi_gbl_db_method_info.arg_types[1] = ACPI_TYPE_INTEGER; + acpi_gbl_db_method_info.arg_types[2] = ACPI_TYPE_INTEGER; + + acpi_db_uint32_to_hex_string(num_threads, + acpi_gbl_db_method_info.num_threads_str); + + status = acpi_db_execute_setup(&acpi_gbl_db_method_info); + if (ACPI_FAILURE(status)) { + goto cleanup_and_exit; + } + + /* Get the NS node, determines existence also */ + + status = acpi_get_handle(NULL, acpi_gbl_db_method_info.pathname, + &acpi_gbl_db_method_info.method); + if (ACPI_FAILURE(status)) { + acpi_os_printf("%s Could not get handle for %s\n", + acpi_format_exception(status), + acpi_gbl_db_method_info.pathname); + goto cleanup_and_exit; + } + + /* Create the threads */ + + acpi_os_printf("Creating %X threads to execute %X times each\n", + num_threads, num_loops); + + for (i = 0; i < (num_threads); i++) { + status = + acpi_os_execute(OSL_DEBUGGER_EXEC_THREAD, + acpi_db_method_thread, + &acpi_gbl_db_method_info); + if (ACPI_FAILURE(status)) { + break; + } + } + + /* Wait for all threads to complete */ + + (void)acpi_os_wait_semaphore(main_thread_gate, 1, ACPI_WAIT_FOREVER); + + acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT); + acpi_os_printf("All threads (%X) have completed\n", num_threads); + acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); + +cleanup_and_exit: + + /* Cleanup and exit */ + + (void)acpi_os_delete_semaphore(main_thread_gate); + (void)acpi_os_delete_semaphore(thread_complete_gate); + (void)acpi_os_delete_semaphore(info_gate); + + acpi_os_free(acpi_gbl_db_method_info.threads); + acpi_gbl_db_method_info.threads = NULL; +} diff --git a/kernel/drivers/acpi/acpica/dbfileio.c b/kernel/drivers/acpi/acpica/dbfileio.c new file mode 100644 index 000000000..d0e6b20ce --- /dev/null +++ b/kernel/drivers/acpi/acpica/dbfileio.c @@ -0,0 +1,256 @@ +/******************************************************************************* + * + * Module Name: dbfileio - Debugger file I/O commands. These can't usually + * be used when running the debugger in Ring 0 (Kernel mode) + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2015, 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 +#include "accommon.h" +#include "acdebug.h" +#include "actables.h" + +#define _COMPONENT ACPI_CA_DEBUGGER +ACPI_MODULE_NAME("dbfileio") + +#ifdef ACPI_DEBUGGER +/******************************************************************************* + * + * FUNCTION: acpi_db_close_debug_file + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: If open, close the current debug output file + * + ******************************************************************************/ +void acpi_db_close_debug_file(void) +{ + +#ifdef ACPI_APPLICATION + + if (acpi_gbl_debug_file) { + fclose(acpi_gbl_debug_file); + acpi_gbl_debug_file = NULL; + acpi_gbl_db_output_to_file = FALSE; + acpi_os_printf("Debug output file %s closed\n", + acpi_gbl_db_debug_filename); + } +#endif +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_open_debug_file + * + * PARAMETERS: name - Filename to open + * + * RETURN: None + * + * DESCRIPTION: Open a file where debug output will be directed. + * + ******************************************************************************/ + +void acpi_db_open_debug_file(char *name) +{ + +#ifdef ACPI_APPLICATION + + acpi_db_close_debug_file(); + acpi_gbl_debug_file = fopen(name, "w+"); + if (!acpi_gbl_debug_file) { + acpi_os_printf("Could not open debug file %s\n", name); + return; + } + + acpi_os_printf("Debug output file %s opened\n", name); + strncpy(acpi_gbl_db_debug_filename, name, + sizeof(acpi_gbl_db_debug_filename)); + acpi_gbl_db_output_to_file = TRUE; + +#endif +} +#endif + +#ifdef ACPI_APPLICATION +#include "acapps.h" + +/******************************************************************************* + * + * FUNCTION: ae_local_load_table + * + * PARAMETERS: table - pointer to a buffer containing the entire + * table to be loaded + * + * RETURN: Status + * + * DESCRIPTION: This function is called to load a table from the caller's + * buffer. The buffer must contain an entire ACPI Table including + * a valid header. The header fields will be verified, and if it + * is determined that the table is invalid, the call will fail. + * + ******************************************************************************/ + +static acpi_status ae_local_load_table(struct acpi_table_header *table) +{ + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE(ae_local_load_table); + +#if 0 +/* struct acpi_table_desc table_info; */ + + if (!table) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + table_info.pointer = table; + status = acpi_tb_recognize_table(&table_info, ACPI_TABLE_ALL); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Install the new table into the local data structures */ + + status = acpi_tb_init_table_descriptor(&table_info); + if (ACPI_FAILURE(status)) { + if (status == AE_ALREADY_EXISTS) { + + /* Table already exists, no error */ + + status = AE_OK; + } + + /* Free table allocated by acpi_tb_get_table */ + + acpi_tb_delete_single_table(&table_info); + return_ACPI_STATUS(status); + } +#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) + + status = + acpi_ns_load_table(table_info.installed_desc, acpi_gbl_root_node); + if (ACPI_FAILURE(status)) { + + /* Uninstall table and free the buffer */ + + acpi_tb_delete_tables_by_type(ACPI_TABLE_ID_DSDT); + return_ACPI_STATUS(status); + } +#endif +#endif + + return_ACPI_STATUS(status); +} +#endif + +/******************************************************************************* + * + * FUNCTION: acpi_db_get_table_from_file + * + * PARAMETERS: filename - File where table is located + * return_table - Where a pointer to the table is returned + * + * RETURN: Status + * + * DESCRIPTION: Load an ACPI table from a file + * + ******************************************************************************/ + +acpi_status +acpi_db_get_table_from_file(char *filename, + struct acpi_table_header **return_table, + u8 must_be_aml_file) +{ +#ifdef ACPI_APPLICATION + acpi_status status; + struct acpi_table_header *table; + u8 is_aml_table = TRUE; + + status = acpi_ut_read_table_from_file(filename, &table); + if (ACPI_FAILURE(status)) { + return (status); + } + + if (must_be_aml_file) { + is_aml_table = acpi_ut_is_aml_table(table); + if (!is_aml_table) { + ACPI_EXCEPTION((AE_INFO, AE_OK, + "Input for -e is not an AML table: " + "\"%4.4s\" (must be DSDT/SSDT)", + table->signature)); + return (AE_TYPE); + } + } + + if (is_aml_table) { + + /* Attempt to recognize and install the table */ + + status = ae_local_load_table(table); + if (ACPI_FAILURE(status)) { + if (status == AE_ALREADY_EXISTS) { + acpi_os_printf + ("Table %4.4s is already installed\n", + table->signature); + } else { + acpi_os_printf("Could not install table, %s\n", + acpi_format_exception(status)); + } + + return (status); + } + + acpi_tb_print_table_header(0, table); + + fprintf(stderr, + "Acpi table [%4.4s] successfully installed and loaded\n", + table->signature); + } + + acpi_gbl_acpi_hardware_present = FALSE; + if (return_table) { + *return_table = table; + } + +#endif /* ACPI_APPLICATION */ + return (AE_OK); +} diff --git a/kernel/drivers/acpi/acpica/dbhistry.c b/kernel/drivers/acpi/acpica/dbhistry.c new file mode 100644 index 000000000..9c66a9ead --- /dev/null +++ b/kernel/drivers/acpi/acpica/dbhistry.c @@ -0,0 +1,239 @@ +/****************************************************************************** + * + * Module Name: dbhistry - debugger HISTORY command + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2015, 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 +#include "accommon.h" +#include "acdebug.h" + +#define _COMPONENT ACPI_CA_DEBUGGER +ACPI_MODULE_NAME("dbhistry") + +#define HI_NO_HISTORY 0 +#define HI_RECORD_HISTORY 1 +#define HISTORY_SIZE 40 +typedef struct history_info { + char *command; + u32 cmd_num; + +} HISTORY_INFO; + +static HISTORY_INFO acpi_gbl_history_buffer[HISTORY_SIZE]; +static u16 acpi_gbl_lo_history = 0; +static u16 acpi_gbl_num_history = 0; +static u16 acpi_gbl_next_history_index = 0; +u32 acpi_gbl_next_cmd_num = 1; + +/******************************************************************************* + * + * FUNCTION: acpi_db_add_to_history + * + * PARAMETERS: command_line - Command to add + * + * RETURN: None + * + * DESCRIPTION: Add a command line to the history buffer. + * + ******************************************************************************/ + +void acpi_db_add_to_history(char *command_line) +{ + u16 cmd_len; + u16 buffer_len; + + /* Put command into the next available slot */ + + cmd_len = (u16)strlen(command_line); + if (!cmd_len) { + return; + } + + if (acpi_gbl_history_buffer[acpi_gbl_next_history_index].command != + NULL) { + buffer_len = + (u16) + strlen(acpi_gbl_history_buffer[acpi_gbl_next_history_index]. + command); + + if (cmd_len > buffer_len) { + acpi_os_free(acpi_gbl_history_buffer + [acpi_gbl_next_history_index].command); + acpi_gbl_history_buffer[acpi_gbl_next_history_index]. + command = acpi_os_allocate(cmd_len + 1); + } + } else { + acpi_gbl_history_buffer[acpi_gbl_next_history_index].command = + acpi_os_allocate(cmd_len + 1); + } + + strcpy(acpi_gbl_history_buffer[acpi_gbl_next_history_index].command, + command_line); + + acpi_gbl_history_buffer[acpi_gbl_next_history_index].cmd_num = + acpi_gbl_next_cmd_num; + + /* Adjust indexes */ + + if ((acpi_gbl_num_history == HISTORY_SIZE) && + (acpi_gbl_next_history_index == acpi_gbl_lo_history)) { + acpi_gbl_lo_history++; + if (acpi_gbl_lo_history >= HISTORY_SIZE) { + acpi_gbl_lo_history = 0; + } + } + + acpi_gbl_next_history_index++; + if (acpi_gbl_next_history_index >= HISTORY_SIZE) { + acpi_gbl_next_history_index = 0; + } + + acpi_gbl_next_cmd_num++; + if (acpi_gbl_num_history < HISTORY_SIZE) { + acpi_gbl_num_history++; + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_display_history + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Display the contents of the history buffer + * + ******************************************************************************/ + +void acpi_db_display_history(void) +{ + u32 i; + u16 history_index; + + history_index = acpi_gbl_lo_history; + + /* Dump entire history buffer */ + + for (i = 0; i < acpi_gbl_num_history; i++) { + if (acpi_gbl_history_buffer[history_index].command) { + acpi_os_printf("%3ld %s\n", + acpi_gbl_history_buffer[history_index]. + cmd_num, + acpi_gbl_history_buffer[history_index]. + command); + } + + history_index++; + if (history_index >= HISTORY_SIZE) { + history_index = 0; + } + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_get_from_history + * + * PARAMETERS: command_num_arg - String containing the number of the + * command to be retrieved + * + * RETURN: Pointer to the retrieved command. Null on error. + * + * DESCRIPTION: Get a command from the history buffer + * + ******************************************************************************/ + +char *acpi_db_get_from_history(char *command_num_arg) +{ + u32 cmd_num; + + if (command_num_arg == NULL) { + cmd_num = acpi_gbl_next_cmd_num - 1; + } + + else { + cmd_num = strtoul(command_num_arg, NULL, 0); + } + + return (acpi_db_get_history_by_index(cmd_num)); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_get_history_by_index + * + * PARAMETERS: cmd_num - Index of the desired history entry. + * Values are 0...(acpi_gbl_next_cmd_num - 1) + * + * RETURN: Pointer to the retrieved command. Null on error. + * + * DESCRIPTION: Get a command from the history buffer + * + ******************************************************************************/ + +char *acpi_db_get_history_by_index(u32 cmd_num) +{ + u32 i; + u16 history_index; + + /* Search history buffer */ + + history_index = acpi_gbl_lo_history; + for (i = 0; i < acpi_gbl_num_history; i++) { + if (acpi_gbl_history_buffer[history_index].cmd_num == cmd_num) { + + /* Found the command, return it */ + + return (acpi_gbl_history_buffer[history_index].command); + } + + /* History buffer is circular */ + + history_index++; + if (history_index >= HISTORY_SIZE) { + history_index = 0; + } + } + + acpi_os_printf("Invalid history number: %u\n", history_index); + return (NULL); +} diff --git a/kernel/drivers/acpi/acpica/dbinput.c b/kernel/drivers/acpi/acpica/dbinput.c new file mode 100644 index 000000000..048025443 --- /dev/null +++ b/kernel/drivers/acpi/acpica/dbinput.c @@ -0,0 +1,1267 @@ +/******************************************************************************* + * + * Module Name: dbinput - user front-end to the AML debugger + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2015, 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 +#include "accommon.h" +#include "acdebug.h" + +#define _COMPONENT ACPI_CA_DEBUGGER +ACPI_MODULE_NAME("dbinput") + +/* Local prototypes */ +static u32 acpi_db_get_line(char *input_buffer); + +static u32 acpi_db_match_command(char *user_command); + +static void acpi_db_single_thread(void); + +static void acpi_db_display_command_info(char *command, u8 display_all); + +static void acpi_db_display_help(char *command); + +static u8 +acpi_db_match_command_help(char *command, + const struct acpi_db_command_help *help); + +/* + * Top-level debugger commands. + * + * This list of commands must match the string table below it + */ +enum acpi_ex_debugger_commands { + CMD_NOT_FOUND = 0, + CMD_NULL, + CMD_ALLOCATIONS, + CMD_ARGS, + CMD_ARGUMENTS, + CMD_BREAKPOINT, + CMD_BUSINFO, + CMD_CALL, + CMD_DEBUG, + CMD_DISASSEMBLE, + CMD_DISASM, + CMD_DUMP, + CMD_EVALUATE, + CMD_EXECUTE, + CMD_EXIT, + CMD_FIND, + CMD_GO, + CMD_HANDLERS, + CMD_HELP, + CMD_HELP2, + CMD_HISTORY, + CMD_HISTORY_EXE, + CMD_HISTORY_LAST, + CMD_INFORMATION, + CMD_INTEGRITY, + CMD_INTO, + CMD_LEVEL, + CMD_LIST, + CMD_LOCALS, + CMD_LOCKS, + CMD_METHODS, + CMD_NAMESPACE, + CMD_NOTIFY, + CMD_OBJECTS, + CMD_OSI, + CMD_OWNER, + CMD_PATHS, + CMD_PREDEFINED, + CMD_PREFIX, + CMD_QUIT, + CMD_REFERENCES, + CMD_RESOURCES, + CMD_RESULTS, + CMD_SET, + CMD_STATS, + CMD_STOP, + CMD_TABLES, + CMD_TEMPLATE, + CMD_TRACE, + CMD_TREE, + CMD_TYPE, +#ifdef ACPI_APPLICATION + CMD_ENABLEACPI, + CMD_EVENT, + CMD_GPE, + CMD_GPES, + CMD_SCI, + CMD_SLEEP, + + CMD_CLOSE, + CMD_LOAD, + CMD_OPEN, + CMD_UNLOAD, + + CMD_TERMINATE, + CMD_THREADS, + + CMD_TEST, +#endif +}; + +#define CMD_FIRST_VALID 2 + +/* Second parameter is the required argument count */ + +static const struct acpi_db_command_info acpi_gbl_db_commands[] = { + {"", 0}, + {"", 0}, + {"ALLOCATIONS", 0}, + {"ARGS", 0}, + {"ARGUMENTS", 0}, + {"BREAKPOINT", 1}, + {"BUSINFO", 0}, + {"CALL", 0}, + {"DEBUG", 1}, + {"DISASSEMBLE", 1}, + {"DISASM", 1}, + {"DUMP", 1}, + {"EVALUATE", 1}, + {"EXECUTE", 1}, + {"EXIT", 0}, + {"FIND", 1}, + {"GO", 0}, + {"HANDLERS", 0}, + {"HELP", 0}, + {"?", 0}, + {"HISTORY", 0}, + {"!", 1}, + {"!!", 0}, + {"INFORMATION", 0}, + {"INTEGRITY", 0}, + {"INTO", 0}, + {"LEVEL", 0}, + {"LIST", 0}, + {"LOCALS", 0}, + {"LOCKS", 0}, + {"METHODS", 0}, + {"NAMESPACE", 0}, + {"NOTIFY", 2}, + {"OBJECTS", 0}, + {"OSI", 0}, + {"OWNER", 1}, + {"PATHS", 0}, + {"PREDEFINED", 0}, + {"PREFIX", 0}, + {"QUIT", 0}, + {"REFERENCES", 1}, + {"RESOURCES", 0}, + {"RESULTS", 0}, + {"SET", 3}, + {"STATS", 1}, + {"STOP", 0}, + {"TABLES", 0}, + {"TEMPLATE", 1}, + {"TRACE", 1}, + {"TREE", 0}, + {"TYPE", 1}, +#ifdef ACPI_APPLICATION + {"ENABLEACPI", 0}, + {"EVENT", 1}, + {"GPE", 1}, + {"GPES", 0}, + {"SCI", 0}, + {"SLEEP", 0}, + + {"CLOSE", 0}, + {"LOAD", 1}, + {"OPEN", 1}, + {"UNLOAD", 1}, + + {"TERMINATE", 0}, + {"THREADS", 3}, + + {"TEST", 1}, +#endif + {NULL, 0} +}; + +/* + * Help for all debugger commands. First argument is the number of lines + * of help to output for the command. + */ +static const struct acpi_db_command_help acpi_gbl_db_command_help[] = { + {0, "\nGeneral-Purpose Commands:", "\n"}, + {1, " Allocations", "Display list of current memory allocations\n"}, + {2, " Dump
|", "\n"}, + {0, " [Byte|Word|Dword|Qword]", + "Display ACPI objects or memory\n"}, + {1, " Handlers", "Info about global handlers\n"}, + {1, " Help [Command]", "This help screen or individual command\n"}, + {1, " History", "Display command history buffer\n"}, + {1, " Level ] [console]", + "Get/Set debug level for file or console\n"}, + {1, " Locks", "Current status of internal mutexes\n"}, + {1, " Osi [Install|Remove ]", + "Display or modify global _OSI list\n"}, + {1, " Quit or Exit", "Exit this command\n"}, + {8, " Stats ", + "Display namespace and memory statistics\n"}, + {1, " Allocations", "Display list of current memory allocations\n"}, + {1, " Memory", "Dump internal memory lists\n"}, + {1, " Misc", "Namespace search and mutex stats\n"}, + {1, " Objects", "Summary of namespace objects\n"}, + {1, " Sizes", "Sizes for each of the internal objects\n"}, + {1, " Stack", "Display CPU stack usage\n"}, + {1, " Tables", "Info about current ACPI table(s)\n"}, + {1, " Tables", "Display info about loaded ACPI tables\n"}, + {1, " ! ", "Execute command from history buffer\n"}, + {1, " !!", "Execute last command again\n"}, + + {0, "\nNamespace Access Commands:", "\n"}, + {1, " Businfo", "Display system bus info\n"}, + {1, " Disassemble ", "Disassemble a control method\n"}, + {1, " Find (? is wildcard)", + "Find ACPI name(s) with wildcards\n"}, + {1, " Integrity", "Validate namespace integrity\n"}, + {1, " Methods", "Display list of loaded control methods\n"}, + {1, " Namespace [Object] [Depth]", + "Display loaded namespace tree/subtree\n"}, + {1, " Notify ", "Send a notification on Object\n"}, + {1, " Objects [ObjectType]", + "Display summary of all objects or just given type\n"}, + {1, " Owner [Depth]", + "Display loaded namespace by object owner\n"}, + {1, " Paths", "Display full pathnames of namespace objects\n"}, + {1, " Predefined", "Check all predefined names\n"}, + {1, " Prefix []", "Set or Get current execution prefix\n"}, + {1, " References ", "Find all references to object at addr\n"}, + {1, " Resources [DeviceName]", + "Display Device resources (no arg = all devices)\n"}, + {1, " Set N ", "Set value for named integer\n"}, + {1, " Template ", "Format/dump a Buffer/ResourceTemplate\n"}, + {1, " Type ", "Display object type\n"}, + + {0, "\nControl Method Execution Commands:", "\n"}, + {1, " Arguments (or Args)", "Display method arguments\n"}, + {1, " Breakpoint ", "Set an AML execution breakpoint\n"}, + {1, " Call", "Run to next control method invocation\n"}, + {1, " Debug [Arguments]", "Single Step a control method\n"}, + {6, " Evaluate", "Synonym for Execute\n"}, + {5, " Execute [Arguments]", "Execute control method\n"}, + {1, " Hex Integer", "Integer method argument\n"}, + {1, " \"Ascii String\"", "String method argument\n"}, + {1, " (Hex Byte List)", "Buffer method argument\n"}, + {1, " [Package Element List]", "Package method argument\n"}, + {1, " Go", "Allow method to run to completion\n"}, + {1, " Information", "Display info about the current method\n"}, + {1, " Into", "Step into (not over) a method call\n"}, + {1, " List [# of Aml Opcodes]", "Display method ASL statements\n"}, + {1, " Locals", "Display method local variables\n"}, + {1, " Results", "Display method result stack\n"}, + {1, " Set <#> ", "Set method data (Arguments/Locals)\n"}, + {1, " Stop", "Terminate control method\n"}, + {5, " Trace [] [Once]", + "Trace control method execution\n"}, + {1, " Enable", "Enable all messages\n"}, + {1, " Disable", "Disable tracing\n"}, + {1, " Method", "Enable method execution messages\n"}, + {1, " Opcode", "Enable opcode execution messages\n"}, + {1, " Tree", "Display control method calling tree\n"}, + {1, " ", "Single step next AML opcode (over calls)\n"}, + +#ifdef ACPI_APPLICATION + {0, "\nHardware Simulation Commands:", "\n"}, + {1, " EnableAcpi", "Enable ACPI (hardware) mode\n"}, + {1, " Event ", "Generate AcpiEvent (Fixed/GPE)\n"}, + {1, " Gpe [GpeBlockDevice]", "Simulate a GPE\n"}, + {1, " Gpes", "Display info on all GPE devices\n"}, + {1, " Sci", "Generate an SCI\n"}, + {1, " Sleep [SleepState]", "Simulate sleep/wake sequence(s) (0-5)\n"}, + + {0, "\nFile I/O Commands:", "\n"}, + {1, " Close", "Close debug output file\n"}, + {1, " Load ", "Load ACPI table from a file\n"}, + {1, " Open ", "Open a file for debug output\n"}, + {1, " Unload ", + "Unload an ACPI table via namespace object\n"}, + + {0, "\nUser Space Commands:", "\n"}, + {1, " Terminate", "Delete namespace and all internal objects\n"}, + {1, " Thread ", + "Spawn threads to execute method(s)\n"}, + + {0, "\nDebug Test Commands:", "\n"}, + {3, " Test ", "Invoke a debug test\n"}, + {1, " Objects", "Read/write/compare all namespace data objects\n"}, + {1, " Predefined", + "Execute all ACPI predefined names (_STA, etc.)\n"}, +#endif + {0, NULL, NULL} +}; + +/******************************************************************************* + * + * FUNCTION: acpi_db_match_command_help + * + * PARAMETERS: command - Command string to match + * help - Help table entry to attempt match + * + * RETURN: TRUE if command matched, FALSE otherwise + * + * DESCRIPTION: Attempt to match a command in the help table in order to + * print help information for a single command. + * + ******************************************************************************/ + +static u8 +acpi_db_match_command_help(char *command, + const struct acpi_db_command_help *help) +{ + char *invocation = help->invocation; + u32 line_count; + + /* Valid commands in the help table begin with a couple of spaces */ + + if (*invocation != ' ') { + return (FALSE); + } + + while (*invocation == ' ') { + invocation++; + } + + /* Match command name (full command or substring) */ + + while ((*command) && (*invocation) && (*invocation != ' ')) { + if (tolower((int)*command) != tolower((int)*invocation)) { + return (FALSE); + } + + invocation++; + command++; + } + + /* Print the appropriate number of help lines */ + + line_count = help->line_count; + while (line_count) { + acpi_os_printf("%-38s : %s", help->invocation, + help->description); + help++; + line_count--; + } + + return (TRUE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_display_command_info + * + * PARAMETERS: command - Command string to match + * display_all - Display all matching commands, or just + * the first one (substring match) + * + * RETURN: None + * + * DESCRIPTION: Display help information for a Debugger command. + * + ******************************************************************************/ + +static void acpi_db_display_command_info(char *command, u8 display_all) +{ + const struct acpi_db_command_help *next; + u8 matched; + + next = acpi_gbl_db_command_help; + while (next->invocation) { + matched = acpi_db_match_command_help(command, next); + if (!display_all && matched) { + return; + } + + next++; + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_display_help + * + * PARAMETERS: command - Optional command string to display help. + * if not specified, all debugger command + * help strings are displayed + * + * RETURN: None + * + * DESCRIPTION: Display help for a single debugger command, or all of them. + * + ******************************************************************************/ + +static void acpi_db_display_help(char *command) +{ + const struct acpi_db_command_help *next = acpi_gbl_db_command_help; + + if (!command) { + + /* No argument to help, display help for all commands */ + + while (next->invocation) { + acpi_os_printf("%-38s%s", next->invocation, + next->description); + next++; + } + } else { + /* Display help for all commands that match the subtring */ + + acpi_db_display_command_info(command, TRUE); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_get_next_token + * + * PARAMETERS: string - Command buffer + * next - Return value, end of next token + * + * RETURN: Pointer to the start of the next token. + * + * DESCRIPTION: Command line parsing. Get the next token on the command line + * + ******************************************************************************/ + +char *acpi_db_get_next_token(char *string, + char **next, acpi_object_type * return_type) +{ + char *start; + u32 depth; + acpi_object_type type = ACPI_TYPE_INTEGER; + + /* At end of buffer? */ + + if (!string || !(*string)) { + return (NULL); + } + + /* Remove any spaces at the beginning */ + + if (*string == ' ') { + while (*string && (*string == ' ')) { + string++; + } + + if (!(*string)) { + return (NULL); + } + } + + switch (*string) { + case '"': + + /* This is a quoted string, scan until closing quote */ + + string++; + start = string; + type = ACPI_TYPE_STRING; + + /* Find end of string */ + + while (*string && (*string != '"')) { + string++; + } + break; + + case '(': + + /* This is the start of a buffer, scan until closing paren */ + + string++; + start = string; + type = ACPI_TYPE_BUFFER; + + /* Find end of buffer */ + + while (*string && (*string != ')')) { + string++; + } + break; + + case '[': + + /* This is the start of a package, scan until closing bracket */ + + string++; + depth = 1; + start = string; + type = ACPI_TYPE_PACKAGE; + + /* Find end of package (closing bracket) */ + + while (*string) { + + /* Handle String package elements */ + + if (*string == '"') { + /* Find end of string */ + + string++; + while (*string && (*string != '"')) { + string++; + } + if (!(*string)) { + break; + } + } else if (*string == '[') { + depth++; /* A nested package declaration */ + } else if (*string == ']') { + depth--; + if (depth == 0) { /* Found final package closing bracket */ + break; + } + } + + string++; + } + break; + + default: + + start = string; + + /* Find end of token */ + + while (*string && (*string != ' ')) { + string++; + } + break; + } + + if (!(*string)) { + *next = NULL; + } else { + *string = 0; + *next = string + 1; + } + + *return_type = type; + return (start); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_get_line + * + * PARAMETERS: input_buffer - Command line buffer + * + * RETURN: Count of arguments to the command + * + * DESCRIPTION: Get the next command line from the user. Gets entire line + * up to the next newline + * + ******************************************************************************/ + +static u32 acpi_db_get_line(char *input_buffer) +{ + u32 i; + u32 count; + char *next; + char *this; + + if (acpi_ut_safe_strcpy + (acpi_gbl_db_parsed_buf, sizeof(acpi_gbl_db_parsed_buf), + input_buffer)) { + acpi_os_printf + ("Buffer overflow while parsing input line (max %u characters)\n", + sizeof(acpi_gbl_db_parsed_buf)); + return (0); + } + + this = acpi_gbl_db_parsed_buf; + for (i = 0; i < ACPI_DEBUGGER_MAX_ARGS; i++) { + acpi_gbl_db_args[i] = acpi_db_get_next_token(this, &next, + &acpi_gbl_db_arg_types + [i]); + if (!acpi_gbl_db_args[i]) { + break; + } + + this = next; + } + + /* Uppercase the actual command */ + + if (acpi_gbl_db_args[0]) { + acpi_ut_strupr(acpi_gbl_db_args[0]); + } + + count = i; + if (count) { + count--; /* Number of args only */ + } + + return (count); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_match_command + * + * PARAMETERS: user_command - User command line + * + * RETURN: Index into command array, -1 if not found + * + * DESCRIPTION: Search command array for a command match + * + ******************************************************************************/ + +static u32 acpi_db_match_command(char *user_command) +{ + u32 i; + + if (!user_command || user_command[0] == 0) { + return (CMD_NULL); + } + + for (i = CMD_FIRST_VALID; acpi_gbl_db_commands[i].name; i++) { + if (strstr(acpi_gbl_db_commands[i].name, user_command) == + acpi_gbl_db_commands[i].name) { + return (i); + } + } + + /* Command not recognized */ + + return (CMD_NOT_FOUND); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_command_dispatch + * + * PARAMETERS: input_buffer - Command line buffer + * walk_state - Current walk + * op - Current (executing) parse op + * + * RETURN: Status + * + * DESCRIPTION: Command dispatcher. + * + ******************************************************************************/ + +acpi_status +acpi_db_command_dispatch(char *input_buffer, + struct acpi_walk_state * walk_state, + union acpi_parse_object * op) +{ + u32 temp; + u32 command_index; + u32 param_count; + char *command_line; + acpi_status status = AE_CTRL_TRUE; + + /* If acpi_terminate has been called, terminate this thread */ + + if (acpi_gbl_db_terminate_loop) { + return (AE_CTRL_TERMINATE); + } + + /* Find command and add to the history buffer */ + + param_count = acpi_db_get_line(input_buffer); + command_index = acpi_db_match_command(acpi_gbl_db_args[0]); + temp = 0; + + /* + * We don't want to add the !! command to the history buffer. It + * would cause an infinite loop because it would always be the + * previous command. + */ + if (command_index != CMD_HISTORY_LAST) { + acpi_db_add_to_history(input_buffer); + } + + /* Verify that we have the minimum number of params */ + + if (param_count < acpi_gbl_db_commands[command_index].min_args) { + acpi_os_printf + ("%u parameters entered, [%s] requires %u parameters\n", + param_count, acpi_gbl_db_commands[command_index].name, + acpi_gbl_db_commands[command_index].min_args); + + acpi_db_display_command_info(acpi_gbl_db_commands + [command_index].name, FALSE); + return (AE_CTRL_TRUE); + } + + /* Decode and dispatch the command */ + + switch (command_index) { + case CMD_NULL: + + if (op) { + return (AE_OK); + } + break; + + case CMD_ALLOCATIONS: + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + acpi_ut_dump_allocations((u32)-1, NULL); +#endif + break; + + case CMD_ARGS: + case CMD_ARGUMENTS: + + acpi_db_display_arguments(); + break; + + case CMD_BREAKPOINT: + + acpi_db_set_method_breakpoint(acpi_gbl_db_args[1], walk_state, + op); + break; + + case CMD_BUSINFO: + + acpi_db_get_bus_info(); + break; + + case CMD_CALL: + + acpi_db_set_method_call_breakpoint(op); + status = AE_OK; + break; + + case CMD_DEBUG: + + acpi_db_execute(acpi_gbl_db_args[1], + &acpi_gbl_db_args[2], &acpi_gbl_db_arg_types[2], + EX_SINGLE_STEP); + break; + + case CMD_DISASSEMBLE: + case CMD_DISASM: + + (void)acpi_db_disassemble_method(acpi_gbl_db_args[1]); + break; + + case CMD_DUMP: + + acpi_db_decode_and_display_object(acpi_gbl_db_args[1], + acpi_gbl_db_args[2]); + break; + + case CMD_EVALUATE: + case CMD_EXECUTE: + + acpi_db_execute(acpi_gbl_db_args[1], + &acpi_gbl_db_args[2], &acpi_gbl_db_arg_types[2], + EX_NO_SINGLE_STEP); + break; + + case CMD_FIND: + + status = acpi_db_find_name_in_namespace(acpi_gbl_db_args[1]); + break; + + case CMD_GO: + + acpi_gbl_cm_single_step = FALSE; + return (AE_OK); + + case CMD_HANDLERS: + + acpi_db_display_handlers(); + break; + + case CMD_HELP: + case CMD_HELP2: + + acpi_db_display_help(acpi_gbl_db_args[1]); + break; + + case CMD_HISTORY: + + acpi_db_display_history(); + break; + + case CMD_HISTORY_EXE: /* ! command */ + + command_line = acpi_db_get_from_history(acpi_gbl_db_args[1]); + if (!command_line) { + return (AE_CTRL_TRUE); + } + + status = acpi_db_command_dispatch(command_line, walk_state, op); + return (status); + + case CMD_HISTORY_LAST: /* !! command */ + + command_line = acpi_db_get_from_history(NULL); + if (!command_line) { + return (AE_CTRL_TRUE); + } + + status = acpi_db_command_dispatch(command_line, walk_state, op); + return (status); + + case CMD_INFORMATION: + + acpi_db_display_method_info(op); + break; + + case CMD_INTEGRITY: + + acpi_db_check_integrity(); + break; + + case CMD_INTO: + + if (op) { + acpi_gbl_cm_single_step = TRUE; + return (AE_OK); + } + break; + + case CMD_LEVEL: + + if (param_count == 0) { + acpi_os_printf + ("Current debug level for file output is: %8.8lX\n", + acpi_gbl_db_debug_level); + acpi_os_printf + ("Current debug level for console output is: %8.8lX\n", + acpi_gbl_db_console_debug_level); + } else if (param_count == 2) { + temp = acpi_gbl_db_console_debug_level; + acpi_gbl_db_console_debug_level = + strtoul(acpi_gbl_db_args[1], NULL, 16); + acpi_os_printf + ("Debug Level for console output was %8.8lX, now %8.8lX\n", + temp, acpi_gbl_db_console_debug_level); + } else { + temp = acpi_gbl_db_debug_level; + acpi_gbl_db_debug_level = + strtoul(acpi_gbl_db_args[1], NULL, 16); + acpi_os_printf + ("Debug Level for file output was %8.8lX, now %8.8lX\n", + temp, acpi_gbl_db_debug_level); + } + break; + + case CMD_LIST: + + acpi_db_disassemble_aml(acpi_gbl_db_args[1], op); + break; + + case CMD_LOCKS: + + acpi_db_display_locks(); + break; + + case CMD_LOCALS: + + acpi_db_display_locals(); + break; + + case CMD_METHODS: + + status = acpi_db_display_objects("METHOD", acpi_gbl_db_args[1]); + break; + + case CMD_NAMESPACE: + + acpi_db_dump_namespace(acpi_gbl_db_args[1], + acpi_gbl_db_args[2]); + break; + + case CMD_NOTIFY: + + temp = strtoul(acpi_gbl_db_args[2], NULL, 0); + acpi_db_send_notify(acpi_gbl_db_args[1], temp); + break; + + case CMD_OBJECTS: + + acpi_ut_strupr(acpi_gbl_db_args[1]); + status = + acpi_db_display_objects(acpi_gbl_db_args[1], + acpi_gbl_db_args[2]); + break; + + case CMD_OSI: + + acpi_db_display_interfaces(acpi_gbl_db_args[1], + acpi_gbl_db_args[2]); + break; + + case CMD_OWNER: + + acpi_db_dump_namespace_by_owner(acpi_gbl_db_args[1], + acpi_gbl_db_args[2]); + break; + + case CMD_PATHS: + + acpi_db_dump_namespace_paths(); + break; + + case CMD_PREFIX: + + acpi_db_set_scope(acpi_gbl_db_args[1]); + break; + + case CMD_REFERENCES: + + acpi_db_find_references(acpi_gbl_db_args[1]); + break; + + case CMD_RESOURCES: + + acpi_db_display_resources(acpi_gbl_db_args[1]); + break; + + case CMD_RESULTS: + + acpi_db_display_results(); + break; + + case CMD_SET: + + acpi_db_set_method_data(acpi_gbl_db_args[1], + acpi_gbl_db_args[2], + acpi_gbl_db_args[3]); + break; + + case CMD_STATS: + + status = acpi_db_display_statistics(acpi_gbl_db_args[1]); + break; + + case CMD_STOP: + + return (AE_NOT_IMPLEMENTED); + + case CMD_TABLES: + + acpi_db_display_table_info(acpi_gbl_db_args[1]); + break; + + case CMD_TEMPLATE: + + acpi_db_display_template(acpi_gbl_db_args[1]); + break; + + case CMD_TRACE: + + acpi_db_trace(acpi_gbl_db_args[1], acpi_gbl_db_args[2], + acpi_gbl_db_args[3]); + break; + + case CMD_TREE: + + acpi_db_display_calling_tree(); + break; + + case CMD_TYPE: + + acpi_db_display_object_type(acpi_gbl_db_args[1]); + break; + +#ifdef ACPI_APPLICATION + + /* Hardware simulation commands. */ + + case CMD_ENABLEACPI: +#if (!ACPI_REDUCED_HARDWARE) + + status = acpi_enable(); + if (ACPI_FAILURE(status)) { + acpi_os_printf("AcpiEnable failed (Status=%X)\n", + status); + return (status); + } +#endif /* !ACPI_REDUCED_HARDWARE */ + break; + + case CMD_EVENT: + + acpi_os_printf("Event command not implemented\n"); + break; + + case CMD_GPE: + + acpi_db_generate_gpe(acpi_gbl_db_args[1], acpi_gbl_db_args[2]); + break; + + case CMD_GPES: + + acpi_db_display_gpes(); + break; + + case CMD_SCI: + + acpi_db_generate_sci(); + break; + + case CMD_SLEEP: + + status = acpi_db_sleep(acpi_gbl_db_args[1]); + break; + + /* File I/O commands. */ + + case CMD_CLOSE: + + acpi_db_close_debug_file(); + break; + + case CMD_LOAD: + + status = + acpi_db_get_table_from_file(acpi_gbl_db_args[1], NULL, + FALSE); + break; + + case CMD_OPEN: + + acpi_db_open_debug_file(acpi_gbl_db_args[1]); + break; + + /* User space commands. */ + + case CMD_TERMINATE: + + acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT); + acpi_ut_subsystem_shutdown(); + + /* + * TBD: [Restructure] Need some way to re-initialize without + * re-creating the semaphores! + */ + + acpi_gbl_db_terminate_loop = TRUE; + /* acpi_initialize (NULL); */ + break; + + case CMD_THREADS: + + acpi_db_create_execution_threads(acpi_gbl_db_args[1], + acpi_gbl_db_args[2], + acpi_gbl_db_args[3]); + break; + + /* Debug test commands. */ + + case CMD_PREDEFINED: + + acpi_db_check_predefined_names(); + break; + + case CMD_TEST: + + acpi_db_execute_test(acpi_gbl_db_args[1]); + break; + + case CMD_UNLOAD: + + acpi_db_unload_acpi_table(acpi_gbl_db_args[1]); + break; +#endif + + case CMD_EXIT: + case CMD_QUIT: + + if (op) { + acpi_os_printf("Method execution terminated\n"); + return (AE_CTRL_TERMINATE); + } + + if (!acpi_gbl_db_output_to_file) { + acpi_dbg_level = ACPI_DEBUG_DEFAULT; + } +#ifdef ACPI_APPLICATION + acpi_db_close_debug_file(); +#endif + acpi_gbl_db_terminate_loop = TRUE; + return (AE_CTRL_TERMINATE); + + case CMD_NOT_FOUND: + default: + + acpi_os_printf("%s: unknown command\n", acpi_gbl_db_args[0]); + return (AE_CTRL_TRUE); + } + + if (ACPI_SUCCESS(status)) { + status = AE_CTRL_TRUE; + } + + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_execute_thread + * + * PARAMETERS: context - Not used + * + * RETURN: None + * + * DESCRIPTION: Debugger execute thread. Waits for a command line, then + * simply dispatches it. + * + ******************************************************************************/ + +void ACPI_SYSTEM_XFACE acpi_db_execute_thread(void *context) +{ + acpi_status status = AE_OK; + acpi_status Mstatus; + + while (status != AE_CTRL_TERMINATE && !acpi_gbl_db_terminate_loop) { + acpi_gbl_method_executing = FALSE; + acpi_gbl_step_to_next_call = FALSE; + + Mstatus = acpi_os_acquire_mutex(acpi_gbl_db_command_ready, + ACPI_WAIT_FOREVER); + if (ACPI_FAILURE(Mstatus)) { + return; + } + + status = + acpi_db_command_dispatch(acpi_gbl_db_line_buf, NULL, NULL); + + acpi_os_release_mutex(acpi_gbl_db_command_complete); + } + acpi_gbl_db_threads_terminated = TRUE; +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_single_thread + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Debugger execute thread. Waits for a command line, then + * simply dispatches it. + * + ******************************************************************************/ + +static void acpi_db_single_thread(void) +{ + + acpi_gbl_method_executing = FALSE; + acpi_gbl_step_to_next_call = FALSE; + + (void)acpi_db_command_dispatch(acpi_gbl_db_line_buf, NULL, NULL); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_user_commands + * + * PARAMETERS: prompt - User prompt (depends on mode) + * op - Current executing parse op + * + * RETURN: None + * + * DESCRIPTION: Command line execution for the AML debugger. Commands are + * matched and dispatched here. + * + ******************************************************************************/ + +acpi_status acpi_db_user_commands(char prompt, union acpi_parse_object *op) +{ + acpi_status status = AE_OK; + + acpi_os_printf("\n"); + + /* TBD: [Restructure] Need a separate command line buffer for step mode */ + + while (!acpi_gbl_db_terminate_loop) { + + /* Force output to console until a command is entered */ + + acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); + + /* Different prompt if method is executing */ + + if (!acpi_gbl_method_executing) { + acpi_os_printf("%1c ", ACPI_DEBUGGER_COMMAND_PROMPT); + } else { + acpi_os_printf("%1c ", ACPI_DEBUGGER_EXECUTE_PROMPT); + } + + /* Get the user input line */ + + status = acpi_os_get_line(acpi_gbl_db_line_buf, + ACPI_DB_LINE_BUFFER_SIZE, NULL); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "While parsing command line")); + return (status); + } + + /* Check for single or multithreaded debug */ + + if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) { + /* + * Signal the debug thread that we have a command to execute, + * and wait for the command to complete. + */ + acpi_os_release_mutex(acpi_gbl_db_command_ready); + if (ACPI_FAILURE(status)) { + return (status); + } + + status = + acpi_os_acquire_mutex(acpi_gbl_db_command_complete, + ACPI_WAIT_FOREVER); + if (ACPI_FAILURE(status)) { + return (status); + } + } else { + /* Just call to the command line interpreter */ + + acpi_db_single_thread(); + } + } + + return (status); +} diff --git a/kernel/drivers/acpi/acpica/dbmethod.c b/kernel/drivers/acpi/acpica/dbmethod.c new file mode 100644 index 000000000..01e5a7114 --- /dev/null +++ b/kernel/drivers/acpi/acpica/dbmethod.c @@ -0,0 +1,369 @@ +/******************************************************************************* + * + * Module Name: dbmethod - Debug commands for control methods + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2015, 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 +#include "accommon.h" +#include "acdispat.h" +#include "acnamesp.h" +#include "acdebug.h" +#include "acparser.h" +#include "acpredef.h" + +#define _COMPONENT ACPI_CA_DEBUGGER +ACPI_MODULE_NAME("dbmethod") + +/******************************************************************************* + * + * FUNCTION: acpi_db_set_method_breakpoint + * + * PARAMETERS: location - AML offset of breakpoint + * walk_state - Current walk info + * op - Current Op (from parse walk) + * + * RETURN: None + * + * DESCRIPTION: Set a breakpoint in a control method at the specified + * AML offset + * + ******************************************************************************/ +void +acpi_db_set_method_breakpoint(char *location, + struct acpi_walk_state *walk_state, + union acpi_parse_object *op) +{ + u32 address; + u32 aml_offset; + + if (!op) { + acpi_os_printf("There is no method currently executing\n"); + return; + } + + /* Get and verify the breakpoint address */ + + address = strtoul(location, NULL, 16); + aml_offset = (u32)ACPI_PTR_DIFF(op->common.aml, + walk_state->parser_state.aml_start); + if (address <= aml_offset) { + acpi_os_printf("Breakpoint %X is beyond current address %X\n", + address, aml_offset); + } + + /* Save breakpoint in current walk */ + + walk_state->user_breakpoint = address; + acpi_os_printf("Breakpoint set at AML offset %X\n", address); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_set_method_call_breakpoint + * + * PARAMETERS: op - Current Op (from parse walk) + * + * RETURN: None + * + * DESCRIPTION: Set a breakpoint in a control method at the specified + * AML offset + * + ******************************************************************************/ + +void acpi_db_set_method_call_breakpoint(union acpi_parse_object *op) +{ + + if (!op) { + acpi_os_printf("There is no method currently executing\n"); + return; + } + + acpi_gbl_step_to_next_call = TRUE; +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_set_method_data + * + * PARAMETERS: type_arg - L for local, A for argument + * index_arg - which one + * value_arg - Value to set. + * + * RETURN: None + * + * DESCRIPTION: Set a local or argument for the running control method. + * NOTE: only object supported is Number. + * + ******************************************************************************/ + +void acpi_db_set_method_data(char *type_arg, char *index_arg, char *value_arg) +{ + char type; + u32 index; + u32 value; + struct acpi_walk_state *walk_state; + union acpi_operand_object *obj_desc; + acpi_status status; + struct acpi_namespace_node *node; + + /* Validate type_arg */ + + acpi_ut_strupr(type_arg); + type = type_arg[0]; + if ((type != 'L') && (type != 'A') && (type != 'N')) { + acpi_os_printf("Invalid SET operand: %s\n", type_arg); + return; + } + + value = strtoul(value_arg, NULL, 16); + + if (type == 'N') { + node = acpi_db_convert_to_node(index_arg); + if (!node) { + return; + } + + if (node->type != ACPI_TYPE_INTEGER) { + acpi_os_printf("Can only set Integer nodes\n"); + return; + } + obj_desc = node->object; + obj_desc->integer.value = value; + return; + } + + /* Get the index and value */ + + index = strtoul(index_arg, NULL, 16); + + walk_state = acpi_ds_get_current_walk_state(acpi_gbl_current_walk_list); + if (!walk_state) { + acpi_os_printf("There is no method currently executing\n"); + return; + } + + /* Create and initialize the new object */ + + obj_desc = acpi_ut_create_integer_object((u64)value); + if (!obj_desc) { + acpi_os_printf("Could not create an internal object\n"); + return; + } + + /* Store the new object into the target */ + + switch (type) { + case 'A': + + /* Set a method argument */ + + if (index > ACPI_METHOD_MAX_ARG) { + acpi_os_printf("Arg%u - Invalid argument name\n", + index); + goto cleanup; + } + + status = acpi_ds_store_object_to_local(ACPI_REFCLASS_ARG, + index, obj_desc, + walk_state); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + obj_desc = walk_state->arguments[index].object; + + acpi_os_printf("Arg%u: ", index); + acpi_db_display_internal_object(obj_desc, walk_state); + break; + + case 'L': + + /* Set a method local */ + + if (index > ACPI_METHOD_MAX_LOCAL) { + acpi_os_printf + ("Local%u - Invalid local variable name\n", index); + goto cleanup; + } + + status = acpi_ds_store_object_to_local(ACPI_REFCLASS_LOCAL, + index, obj_desc, + walk_state); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + obj_desc = walk_state->local_variables[index].object; + + acpi_os_printf("Local%u: ", index); + acpi_db_display_internal_object(obj_desc, walk_state); + break; + + default: + + break; + } + +cleanup: + acpi_ut_remove_reference(obj_desc); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_disassemble_aml + * + * PARAMETERS: statements - Number of statements to disassemble + * op - Current Op (from parse walk) + * + * RETURN: None + * + * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number + * of statements specified. + * + ******************************************************************************/ + +void acpi_db_disassemble_aml(char *statements, union acpi_parse_object *op) +{ + u32 num_statements = 8; + + if (!op) { + acpi_os_printf("There is no method currently executing\n"); + return; + } + + if (statements) { + num_statements = strtoul(statements, NULL, 0); + } +#ifdef ACPI_DISASSEMBLER + acpi_dm_disassemble(NULL, op, num_statements); +#endif +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_disassemble_method + * + * PARAMETERS: name - Name of control method + * + * RETURN: None + * + * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number + * of statements specified. + * + ******************************************************************************/ + +acpi_status acpi_db_disassemble_method(char *name) +{ + acpi_status status; + union acpi_parse_object *op; + struct acpi_walk_state *walk_state; + union acpi_operand_object *obj_desc; + struct acpi_namespace_node *method; + + method = acpi_db_convert_to_node(name); + if (!method) { + return (AE_BAD_PARAMETER); + } + + if (method->type != ACPI_TYPE_METHOD) { + ACPI_ERROR((AE_INFO, "%s (%s): Object must be a control method", + name, acpi_ut_get_type_name(method->type))); + return (AE_BAD_PARAMETER); + } + + obj_desc = method->object; + + op = acpi_ps_create_scope_op(obj_desc->method.aml_start); + if (!op) { + return (AE_NO_MEMORY); + } + + /* Create and initialize a new walk state */ + + walk_state = acpi_ds_create_walk_state(0, op, NULL, NULL); + if (!walk_state) { + return (AE_NO_MEMORY); + } + + status = acpi_ds_init_aml_walk(walk_state, op, NULL, + obj_desc->method.aml_start, + obj_desc->method.aml_length, NULL, + ACPI_IMODE_LOAD_PASS1); + if (ACPI_FAILURE(status)) { + return (status); + } + + status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id); + walk_state->owner_id = obj_desc->method.owner_id; + + /* Push start scope on scope stack and make it current */ + + status = acpi_ds_scope_stack_push(method, method->type, walk_state); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Parse the entire method AML including deferred operators */ + + walk_state->parse_flags &= ~ACPI_PARSE_DELETE_TREE; + walk_state->parse_flags |= ACPI_PARSE_DISASSEMBLE; + + status = acpi_ps_parse_aml(walk_state); + +#ifdef ACPI_DISASSEMBLER + (void)acpi_dm_parse_deferred_ops(op); + + /* Now we can disassemble the method */ + + acpi_gbl_dm_opt_verbose = FALSE; + acpi_dm_disassemble(NULL, op, 0); + acpi_gbl_dm_opt_verbose = TRUE; +#endif + + acpi_ps_delete_parse_tree(op); + + /* Method cleanup */ + + acpi_ns_delete_namespace_subtree(method); + acpi_ns_delete_namespace_by_owner(obj_desc->method.owner_id); + acpi_ut_release_owner_id(&obj_desc->method.owner_id); + return (AE_OK); +} diff --git a/kernel/drivers/acpi/acpica/dbnames.c b/kernel/drivers/acpi/acpica/dbnames.c new file mode 100644 index 000000000..04ff1ebfd --- /dev/null +++ b/kernel/drivers/acpi/acpica/dbnames.c @@ -0,0 +1,947 @@ +/******************************************************************************* + * + * Module Name: dbnames - Debugger commands for the acpi namespace + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2015, 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 +#include "accommon.h" +#include "acnamesp.h" +#include "acdebug.h" +#include "acpredef.h" + +#define _COMPONENT ACPI_CA_DEBUGGER +ACPI_MODULE_NAME("dbnames") + +/* Local prototypes */ +static acpi_status +acpi_db_walk_and_match_name(acpi_handle obj_handle, + u32 nesting_level, + void *context, void **return_value); + +static acpi_status +acpi_db_walk_for_predefined_names(acpi_handle obj_handle, + u32 nesting_level, + void *context, void **return_value); + +static acpi_status +acpi_db_walk_for_specific_objects(acpi_handle obj_handle, + u32 nesting_level, + void *context, void **return_value); + +static acpi_status +acpi_db_walk_for_object_counts(acpi_handle obj_handle, + u32 nesting_level, + void *context, void **return_value); + +static acpi_status +acpi_db_integrity_walk(acpi_handle obj_handle, + u32 nesting_level, void *context, void **return_value); + +static acpi_status +acpi_db_walk_for_references(acpi_handle obj_handle, + u32 nesting_level, + void *context, void **return_value); + +static acpi_status +acpi_db_bus_walk(acpi_handle obj_handle, + u32 nesting_level, void *context, void **return_value); + +/* + * Arguments for the Objects command + * These object types map directly to the ACPI_TYPES + */ +static struct acpi_db_argument_info acpi_db_object_types[] = { + {"ANY"}, + {"INTEGERS"}, + {"STRINGS"}, + {"BUFFERS"}, + {"PACKAGES"}, + {"FIELDS"}, + {"DEVICES"}, + {"EVENTS"}, + {"METHODS"}, + {"MUTEXES"}, + {"REGIONS"}, + {"POWERRESOURCES"}, + {"PROCESSORS"}, + {"THERMALZONES"}, + {"BUFFERFIELDS"}, + {"DDBHANDLES"}, + {"DEBUG"}, + {"REGIONFIELDS"}, + {"BANKFIELDS"}, + {"INDEXFIELDS"}, + {"REFERENCES"}, + {"ALIASES"}, + {"METHODALIASES"}, + {"NOTIFY"}, + {"ADDRESSHANDLER"}, + {"RESOURCE"}, + {"RESOURCEFIELD"}, + {"SCOPES"}, + {NULL} /* Must be null terminated */ +}; + +/******************************************************************************* + * + * FUNCTION: acpi_db_set_scope + * + * PARAMETERS: name - New scope path + * + * RETURN: Status + * + * DESCRIPTION: Set the "current scope" as maintained by this utility. + * The scope is used as a prefix to ACPI paths. + * + ******************************************************************************/ + +void acpi_db_set_scope(char *name) +{ + acpi_status status; + struct acpi_namespace_node *node; + + if (!name || name[0] == 0) { + acpi_os_printf("Current scope: %s\n", acpi_gbl_db_scope_buf); + return; + } + + acpi_db_prep_namestring(name); + + if (ACPI_IS_ROOT_PREFIX(name[0])) { + + /* Validate new scope from the root */ + + status = acpi_ns_get_node(acpi_gbl_root_node, name, + ACPI_NS_NO_UPSEARCH, &node); + if (ACPI_FAILURE(status)) { + goto error_exit; + } + + acpi_gbl_db_scope_buf[0] = 0; + } else { + /* Validate new scope relative to old scope */ + + status = acpi_ns_get_node(acpi_gbl_db_scope_node, name, + ACPI_NS_NO_UPSEARCH, &node); + if (ACPI_FAILURE(status)) { + goto error_exit; + } + } + + /* Build the final pathname */ + + if (acpi_ut_safe_strcat + (acpi_gbl_db_scope_buf, sizeof(acpi_gbl_db_scope_buf), name)) { + status = AE_BUFFER_OVERFLOW; + goto error_exit; + } + + if (acpi_ut_safe_strcat + (acpi_gbl_db_scope_buf, sizeof(acpi_gbl_db_scope_buf), "\\")) { + status = AE_BUFFER_OVERFLOW; + goto error_exit; + } + + acpi_gbl_db_scope_node = node; + acpi_os_printf("New scope: %s\n", acpi_gbl_db_scope_buf); + return; + +error_exit: + + acpi_os_printf("Could not attach scope: %s, %s\n", + name, acpi_format_exception(status)); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_dump_namespace + * + * PARAMETERS: start_arg - Node to begin namespace dump + * depth_arg - Maximum tree depth to be dumped + * + * RETURN: None + * + * DESCRIPTION: Dump entire namespace or a subtree. Each node is displayed + * with type and other information. + * + ******************************************************************************/ + +void acpi_db_dump_namespace(char *start_arg, char *depth_arg) +{ + acpi_handle subtree_entry = acpi_gbl_root_node; + u32 max_depth = ACPI_UINT32_MAX; + + /* No argument given, just start at the root and dump entire namespace */ + + if (start_arg) { + subtree_entry = acpi_db_convert_to_node(start_arg); + if (!subtree_entry) { + return; + } + + /* Now we can check for the depth argument */ + + if (depth_arg) { + max_depth = strtoul(depth_arg, NULL, 0); + } + } + + acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT); + acpi_os_printf("ACPI Namespace (from %4.4s (%p) subtree):\n", + ((struct acpi_namespace_node *)subtree_entry)->name. + ascii, subtree_entry); + + /* Display the subtree */ + + acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT); + acpi_ns_dump_objects(ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, max_depth, + ACPI_OWNER_ID_MAX, subtree_entry); + acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_dump_namespace_paths + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Dump entire namespace with full object pathnames and object + * type information. Alternative to "namespace" command. + * + ******************************************************************************/ + +void acpi_db_dump_namespace_paths(void) +{ + + acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT); + acpi_os_printf("ACPI Namespace (from root):\n"); + + /* Display the entire namespace */ + + acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT); + acpi_ns_dump_object_paths(ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, + ACPI_UINT32_MAX, ACPI_OWNER_ID_MAX, + acpi_gbl_root_node); + + acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_dump_namespace_by_owner + * + * PARAMETERS: owner_arg - Owner ID whose nodes will be displayed + * depth_arg - Maximum tree depth to be dumped + * + * RETURN: None + * + * DESCRIPTION: Dump elements of the namespace that are owned by the owner_id. + * + ******************************************************************************/ + +void acpi_db_dump_namespace_by_owner(char *owner_arg, char *depth_arg) +{ + acpi_handle subtree_entry = acpi_gbl_root_node; + u32 max_depth = ACPI_UINT32_MAX; + acpi_owner_id owner_id; + + owner_id = (acpi_owner_id) strtoul(owner_arg, NULL, 0); + + /* Now we can check for the depth argument */ + + if (depth_arg) { + max_depth = strtoul(depth_arg, NULL, 0); + } + + acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT); + acpi_os_printf("ACPI Namespace by owner %X:\n", owner_id); + + /* Display the subtree */ + + acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT); + acpi_ns_dump_objects(ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, max_depth, + owner_id, subtree_entry); + acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_walk_and_match_name + * + * PARAMETERS: Callback from walk_namespace + * + * RETURN: Status + * + * DESCRIPTION: Find a particular name/names within the namespace. Wildcards + * are supported -- '?' matches any character. + * + ******************************************************************************/ + +static acpi_status +acpi_db_walk_and_match_name(acpi_handle obj_handle, + u32 nesting_level, + void *context, void **return_value) +{ + acpi_status status; + char *requested_name = (char *)context; + u32 i; + struct acpi_buffer buffer; + struct acpi_walk_info info; + + /* Check for a name match */ + + for (i = 0; i < 4; i++) { + + /* Wildcard support */ + + if ((requested_name[i] != '?') && + (requested_name[i] != ((struct acpi_namespace_node *) + obj_handle)->name.ascii[i])) { + + /* No match, just exit */ + + return (AE_OK); + } + } + + /* Get the full pathname to this object */ + + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE); + if (ACPI_FAILURE(status)) { + acpi_os_printf("Could Not get pathname for object %p\n", + obj_handle); + } else { + info.owner_id = ACPI_OWNER_ID_MAX; + info.debug_level = ACPI_UINT32_MAX; + info.display_type = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT; + + acpi_os_printf("%32s", (char *)buffer.pointer); + (void)acpi_ns_dump_one_object(obj_handle, nesting_level, &info, + NULL); + ACPI_FREE(buffer.pointer); + } + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_find_name_in_namespace + * + * PARAMETERS: name_arg - The 4-character ACPI name to find. + * wildcards are supported. + * + * RETURN: None + * + * DESCRIPTION: Search the namespace for a given name (with wildcards) + * + ******************************************************************************/ + +acpi_status acpi_db_find_name_in_namespace(char *name_arg) +{ + char acpi_name[5] = "____"; + char *acpi_name_ptr = acpi_name; + + if (strlen(name_arg) > ACPI_NAME_SIZE) { + acpi_os_printf("Name must be no longer than 4 characters\n"); + return (AE_OK); + } + + /* Pad out name with underscores as necessary to create a 4-char name */ + + acpi_ut_strupr(name_arg); + while (*name_arg) { + *acpi_name_ptr = *name_arg; + acpi_name_ptr++; + name_arg++; + } + + /* Walk the namespace from the root */ + + (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, acpi_db_walk_and_match_name, + NULL, acpi_name, NULL); + + acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_walk_for_predefined_names + * + * PARAMETERS: Callback from walk_namespace + * + * RETURN: Status + * + * DESCRIPTION: Detect and display predefined ACPI names (names that start with + * an underscore) + * + ******************************************************************************/ + +static acpi_status +acpi_db_walk_for_predefined_names(acpi_handle obj_handle, + u32 nesting_level, + void *context, void **return_value) +{ + struct acpi_namespace_node *node = + (struct acpi_namespace_node *)obj_handle; + u32 *count = (u32 *)context; + const union acpi_predefined_info *predefined; + const union acpi_predefined_info *package = NULL; + char *pathname; + char string_buffer[48]; + + predefined = acpi_ut_match_predefined_method(node->name.ascii); + if (!predefined) { + return (AE_OK); + } + + pathname = acpi_ns_get_external_pathname(node); + if (!pathname) { + return (AE_OK); + } + + /* If method returns a package, the info is in the next table entry */ + + if (predefined->info.expected_btypes & ACPI_RTYPE_PACKAGE) { + package = predefined + 1; + } + + acpi_ut_get_expected_return_types(string_buffer, + predefined->info.expected_btypes); + + acpi_os_printf("%-32s Arguments %X, Return Types: %s", pathname, + METHOD_GET_ARG_COUNT(predefined->info.argument_list), + string_buffer); + + if (package) { + acpi_os_printf(" (PkgType %2.2X, ObjType %2.2X, Count %2.2X)", + package->ret_info.type, + package->ret_info.object_type1, + package->ret_info.count1); + } + + acpi_os_printf("\n"); + + /* Check that the declared argument count matches the ACPI spec */ + + acpi_ns_check_acpi_compliance(pathname, node, predefined); + + ACPI_FREE(pathname); + (*count)++; + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_check_predefined_names + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Validate all predefined names in the namespace + * + ******************************************************************************/ + +void acpi_db_check_predefined_names(void) +{ + u32 count = 0; + + /* Search all nodes in namespace */ + + (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, + acpi_db_walk_for_predefined_names, NULL, + (void *)&count, NULL); + + acpi_os_printf("Found %u predefined names in the namespace\n", count); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_walk_for_object_counts + * + * PARAMETERS: Callback from walk_namespace + * + * RETURN: Status + * + * DESCRIPTION: Display short info about objects in the namespace + * + ******************************************************************************/ + +static acpi_status +acpi_db_walk_for_object_counts(acpi_handle obj_handle, + u32 nesting_level, + void *context, void **return_value) +{ + struct acpi_object_info *info = (struct acpi_object_info *)context; + struct acpi_namespace_node *node = + (struct acpi_namespace_node *)obj_handle; + + if (node->type > ACPI_TYPE_NS_NODE_MAX) { + acpi_os_printf("[%4.4s]: Unknown object type %X\n", + node->name.ascii, node->type); + } else { + info->types[node->type]++; + } + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_walk_for_specific_objects + * + * PARAMETERS: Callback from walk_namespace + * + * RETURN: Status + * + * DESCRIPTION: Display short info about objects in the namespace + * + ******************************************************************************/ + +static acpi_status +acpi_db_walk_for_specific_objects(acpi_handle obj_handle, + u32 nesting_level, + void *context, void **return_value) +{ + struct acpi_walk_info *info = (struct acpi_walk_info *)context; + struct acpi_buffer buffer; + acpi_status status; + + info->count++; + + /* Get and display the full pathname to this object */ + + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE); + if (ACPI_FAILURE(status)) { + acpi_os_printf("Could Not get pathname for object %p\n", + obj_handle); + return (AE_OK); + } + + acpi_os_printf("%32s", (char *)buffer.pointer); + ACPI_FREE(buffer.pointer); + + /* Dump short info about the object */ + + (void)acpi_ns_dump_one_object(obj_handle, nesting_level, info, NULL); + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_display_objects + * + * PARAMETERS: obj_type_arg - Type of object to display + * display_count_arg - Max depth to display + * + * RETURN: None + * + * DESCRIPTION: Display objects in the namespace of the requested type + * + ******************************************************************************/ + +acpi_status acpi_db_display_objects(char *obj_type_arg, char *display_count_arg) +{ + struct acpi_walk_info info; + acpi_object_type type; + struct acpi_object_info *object_info; + u32 i; + u32 total_objects = 0; + + /* No argument means display summary/count of all object types */ + + if (!obj_type_arg) { + object_info = + ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_object_info)); + + /* Walk the namespace from the root */ + + (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, + acpi_db_walk_for_object_counts, NULL, + (void *)object_info, NULL); + + acpi_os_printf("\nSummary of namespace objects:\n\n"); + + for (i = 0; i < ACPI_TOTAL_TYPES; i++) { + acpi_os_printf("%8u %s\n", object_info->types[i], + acpi_ut_get_type_name(i)); + + total_objects += object_info->types[i]; + } + + acpi_os_printf("\n%8u Total namespace objects\n\n", + total_objects); + + ACPI_FREE(object_info); + return (AE_OK); + } + + /* Get the object type */ + + type = acpi_db_match_argument(obj_type_arg, acpi_db_object_types); + if (type == ACPI_TYPE_NOT_FOUND) { + acpi_os_printf("Invalid or unsupported argument\n"); + return (AE_OK); + } + + acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT); + acpi_os_printf + ("Objects of type [%s] defined in the current ACPI Namespace:\n", + acpi_ut_get_type_name(type)); + + acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT); + + info.count = 0; + info.owner_id = ACPI_OWNER_ID_MAX; + info.debug_level = ACPI_UINT32_MAX; + info.display_type = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT; + + /* Walk the namespace from the root */ + + (void)acpi_walk_namespace(type, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + acpi_db_walk_for_specific_objects, NULL, + (void *)&info, NULL); + + acpi_os_printf + ("\nFound %u objects of type [%s] in the current ACPI Namespace\n", + info.count, acpi_ut_get_type_name(type)); + + acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_integrity_walk + * + * PARAMETERS: Callback from walk_namespace + * + * RETURN: Status + * + * DESCRIPTION: Examine one NS node for valid values. + * + ******************************************************************************/ + +static acpi_status +acpi_db_integrity_walk(acpi_handle obj_handle, + u32 nesting_level, void *context, void **return_value) +{ + struct acpi_integrity_info *info = + (struct acpi_integrity_info *)context; + struct acpi_namespace_node *node = + (struct acpi_namespace_node *)obj_handle; + union acpi_operand_object *object; + u8 alias = TRUE; + + info->nodes++; + + /* Verify the NS node, and dereference aliases */ + + while (alias) { + if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) { + acpi_os_printf + ("Invalid Descriptor Type for Node %p [%s] - " + "is %2.2X should be %2.2X\n", node, + acpi_ut_get_descriptor_name(node), + ACPI_GET_DESCRIPTOR_TYPE(node), + ACPI_DESC_TYPE_NAMED); + return (AE_OK); + } + + if ((node->type == ACPI_TYPE_LOCAL_ALIAS) || + (node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) { + node = (struct acpi_namespace_node *)node->object; + } else { + alias = FALSE; + } + } + + if (node->type > ACPI_TYPE_LOCAL_MAX) { + acpi_os_printf("Invalid Object Type for Node %p, Type = %X\n", + node, node->type); + return (AE_OK); + } + + if (!acpi_ut_valid_acpi_name(node->name.ascii)) { + acpi_os_printf("Invalid AcpiName for Node %p\n", node); + return (AE_OK); + } + + object = acpi_ns_get_attached_object(node); + if (object) { + info->objects++; + if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) { + acpi_os_printf + ("Invalid Descriptor Type for Object %p [%s]\n", + object, acpi_ut_get_descriptor_name(object)); + } + } + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_check_integrity + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Check entire namespace for data structure integrity + * + ******************************************************************************/ + +void acpi_db_check_integrity(void) +{ + struct acpi_integrity_info info = { 0, 0 }; + + /* Search all nodes in namespace */ + + (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, acpi_db_integrity_walk, NULL, + (void *)&info, NULL); + + acpi_os_printf("Verified %u namespace nodes with %u Objects\n", + info.nodes, info.objects); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_walk_for_references + * + * PARAMETERS: Callback from walk_namespace + * + * RETURN: Status + * + * DESCRIPTION: Check if this namespace object refers to the target object + * that is passed in as the context value. + * + * Note: Currently doesn't check subobjects within the Node's object + * + ******************************************************************************/ + +static acpi_status +acpi_db_walk_for_references(acpi_handle obj_handle, + u32 nesting_level, + void *context, void **return_value) +{ + union acpi_operand_object *obj_desc = + (union acpi_operand_object *)context; + struct acpi_namespace_node *node = + (struct acpi_namespace_node *)obj_handle; + + /* Check for match against the namespace node itself */ + + if (node == (void *)obj_desc) { + acpi_os_printf("Object is a Node [%4.4s]\n", + acpi_ut_get_node_name(node)); + } + + /* Check for match against the object attached to the node */ + + if (acpi_ns_get_attached_object(node) == obj_desc) { + acpi_os_printf("Reference at Node->Object %p [%4.4s]\n", + node, acpi_ut_get_node_name(node)); + } + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_find_references + * + * PARAMETERS: object_arg - String with hex value of the object + * + * RETURN: None + * + * DESCRIPTION: Search namespace for all references to the input object + * + ******************************************************************************/ + +void acpi_db_find_references(char *object_arg) +{ + union acpi_operand_object *obj_desc; + acpi_size address; + + /* Convert string to object pointer */ + + address = strtoul(object_arg, NULL, 16); + obj_desc = ACPI_TO_POINTER(address); + + /* Search all nodes in namespace */ + + (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, acpi_db_walk_for_references, + NULL, (void *)obj_desc, NULL); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_bus_walk + * + * PARAMETERS: Callback from walk_namespace + * + * RETURN: Status + * + * DESCRIPTION: Display info about device objects that have a corresponding + * _PRT method. + * + ******************************************************************************/ + +static acpi_status +acpi_db_bus_walk(acpi_handle obj_handle, + u32 nesting_level, void *context, void **return_value) +{ + struct acpi_namespace_node *node = + (struct acpi_namespace_node *)obj_handle; + acpi_status status; + struct acpi_buffer buffer; + struct acpi_namespace_node *temp_node; + struct acpi_device_info *info; + u32 i; + + if ((node->type != ACPI_TYPE_DEVICE) && + (node->type != ACPI_TYPE_PROCESSOR)) { + return (AE_OK); + } + + /* Exit if there is no _PRT under this device */ + + status = acpi_get_handle(node, METHOD_NAME__PRT, + ACPI_CAST_PTR(acpi_handle, &temp_node)); + if (ACPI_FAILURE(status)) { + return (AE_OK); + } + + /* Get the full path to this device object */ + + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE); + if (ACPI_FAILURE(status)) { + acpi_os_printf("Could Not get pathname for object %p\n", + obj_handle); + return (AE_OK); + } + + status = acpi_get_object_info(obj_handle, &info); + if (ACPI_FAILURE(status)) { + return (AE_OK); + } + + /* Display the full path */ + + acpi_os_printf("%-32s Type %X", (char *)buffer.pointer, node->type); + ACPI_FREE(buffer.pointer); + + if (info->flags & ACPI_PCI_ROOT_BRIDGE) { + acpi_os_printf(" - Is PCI Root Bridge"); + } + acpi_os_printf("\n"); + + /* _PRT info */ + + acpi_os_printf("_PRT: %p\n", temp_node); + + /* Dump _ADR, _HID, _UID, _CID */ + + if (info->valid & ACPI_VALID_ADR) { + acpi_os_printf("_ADR: %8.8X%8.8X\n", + ACPI_FORMAT_UINT64(info->address)); + } else { + acpi_os_printf("_ADR: \n"); + } + + if (info->valid & ACPI_VALID_HID) { + acpi_os_printf("_HID: %s\n", info->hardware_id.string); + } else { + acpi_os_printf("_HID: \n"); + } + + if (info->valid & ACPI_VALID_UID) { + acpi_os_printf("_UID: %s\n", info->unique_id.string); + } else { + acpi_os_printf("_UID: \n"); + } + + if (info->valid & ACPI_VALID_CID) { + for (i = 0; i < info->compatible_id_list.count; i++) { + acpi_os_printf("_CID: %s\n", + info->compatible_id_list.ids[i].string); + } + } else { + acpi_os_printf("_CID: \n"); + } + + ACPI_FREE(info); + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_get_bus_info + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Display info about system busses. + * + ******************************************************************************/ + +void acpi_db_get_bus_info(void) +{ + /* Search all nodes in namespace */ + + (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, acpi_db_bus_walk, NULL, NULL, + NULL); +} diff --git a/kernel/drivers/acpi/acpica/dbobject.c b/kernel/drivers/acpi/acpica/dbobject.c new file mode 100644 index 000000000..116f6db8c --- /dev/null +++ b/kernel/drivers/acpi/acpica/dbobject.c @@ -0,0 +1,533 @@ +/******************************************************************************* + * + * Module Name: dbobject - ACPI object decode and display + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2015, 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 +#include "accommon.h" +#include "acnamesp.h" +#include "acdebug.h" + +#define _COMPONENT ACPI_CA_DEBUGGER +ACPI_MODULE_NAME("dbobject") + +/* Local prototypes */ +static void acpi_db_decode_node(struct acpi_namespace_node *node); + +/******************************************************************************* + * + * FUNCTION: acpi_db_dump_method_info + * + * PARAMETERS: status - Method execution status + * walk_state - Current state of the parse tree walk + * + * RETURN: None + * + * DESCRIPTION: Called when a method has been aborted because of an error. + * Dumps the method execution stack, and the method locals/args, + * and disassembles the AML opcode that failed. + * + ******************************************************************************/ + +void +acpi_db_dump_method_info(acpi_status status, struct acpi_walk_state *walk_state) +{ + struct acpi_thread_state *thread; + + /* Ignore control codes, they are not errors */ + + if ((status & AE_CODE_MASK) == AE_CODE_CONTROL) { + return; + } + + /* We may be executing a deferred opcode */ + + if (walk_state->deferred_node) { + acpi_os_printf("Executing subtree for Buffer/Package/Region\n"); + return; + } + + /* + * If there is no Thread, we are not actually executing a method. + * This can happen when the iASL compiler calls the interpreter + * to perform constant folding. + */ + thread = walk_state->thread; + if (!thread) { + return; + } + + /* Display the method locals and arguments */ + + acpi_os_printf("\n"); + acpi_db_decode_locals(walk_state); + acpi_os_printf("\n"); + acpi_db_decode_arguments(walk_state); + acpi_os_printf("\n"); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_decode_internal_object + * + * PARAMETERS: obj_desc - Object to be displayed + * + * RETURN: None + * + * DESCRIPTION: Short display of an internal object. Numbers/Strings/Buffers. + * + ******************************************************************************/ + +void acpi_db_decode_internal_object(union acpi_operand_object *obj_desc) +{ + u32 i; + + if (!obj_desc) { + acpi_os_printf(" Uninitialized"); + return; + } + + if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) { + acpi_os_printf(" %p [%s]", obj_desc, + acpi_ut_get_descriptor_name(obj_desc)); + return; + } + + acpi_os_printf(" %s", acpi_ut_get_object_type_name(obj_desc)); + + switch (obj_desc->common.type) { + case ACPI_TYPE_INTEGER: + + acpi_os_printf(" %8.8X%8.8X", + ACPI_FORMAT_UINT64(obj_desc->integer.value)); + break; + + case ACPI_TYPE_STRING: + + acpi_os_printf("(%u) \"%.24s", + obj_desc->string.length, + obj_desc->string.pointer); + + if (obj_desc->string.length > 24) { + acpi_os_printf("..."); + } else { + acpi_os_printf("\""); + } + break; + + case ACPI_TYPE_BUFFER: + + acpi_os_printf("(%u)", obj_desc->buffer.length); + for (i = 0; (i < 8) && (i < obj_desc->buffer.length); i++) { + acpi_os_printf(" %2.2X", obj_desc->buffer.pointer[i]); + } + break; + + default: + + acpi_os_printf(" %p", obj_desc); + break; + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_decode_node + * + * PARAMETERS: node - Object to be displayed + * + * RETURN: None + * + * DESCRIPTION: Short display of a namespace node + * + ******************************************************************************/ + +static void acpi_db_decode_node(struct acpi_namespace_node *node) +{ + + acpi_os_printf(" Name %4.4s", + acpi_ut_get_node_name(node)); + + if (node->flags & ANOBJ_METHOD_ARG) { + acpi_os_printf(" [Method Arg]"); + } + if (node->flags & ANOBJ_METHOD_LOCAL) { + acpi_os_printf(" [Method Local]"); + } + + switch (node->type) { + + /* These types have no attached object */ + + case ACPI_TYPE_DEVICE: + + acpi_os_printf(" Device"); + break; + + case ACPI_TYPE_THERMAL: + + acpi_os_printf(" Thermal Zone"); + break; + + default: + + acpi_db_decode_internal_object(acpi_ns_get_attached_object + (node)); + break; + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_display_internal_object + * + * PARAMETERS: obj_desc - Object to be displayed + * walk_state - Current walk state + * + * RETURN: None + * + * DESCRIPTION: Short display of an internal object + * + ******************************************************************************/ + +void +acpi_db_display_internal_object(union acpi_operand_object *obj_desc, + struct acpi_walk_state *walk_state) +{ + u8 type; + + acpi_os_printf("%p ", obj_desc); + + if (!obj_desc) { + acpi_os_printf("\n"); + return; + } + + /* Decode the object type */ + + switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) { + case ACPI_DESC_TYPE_PARSER: + + acpi_os_printf(" "); + break; + + case ACPI_DESC_TYPE_NAMED: + + acpi_db_decode_node((struct acpi_namespace_node *)obj_desc); + break; + + case ACPI_DESC_TYPE_OPERAND: + + type = obj_desc->common.type; + if (type > ACPI_TYPE_LOCAL_MAX) { + acpi_os_printf(" Type %X [Invalid Type]", (u32)type); + return; + } + + /* Decode the ACPI object type */ + + switch (obj_desc->common.type) { + case ACPI_TYPE_LOCAL_REFERENCE: + + acpi_os_printf("[%s] ", + acpi_ut_get_reference_name(obj_desc)); + + /* Decode the refererence */ + + switch (obj_desc->reference.class) { + case ACPI_REFCLASS_LOCAL: + + acpi_os_printf("%X ", + obj_desc->reference.value); + if (walk_state) { + obj_desc = walk_state->local_variables + [obj_desc->reference.value].object; + acpi_os_printf("%p", obj_desc); + acpi_db_decode_internal_object + (obj_desc); + } + break; + + case ACPI_REFCLASS_ARG: + + acpi_os_printf("%X ", + obj_desc->reference.value); + if (walk_state) { + obj_desc = walk_state->arguments + [obj_desc->reference.value].object; + acpi_os_printf("%p", obj_desc); + acpi_db_decode_internal_object + (obj_desc); + } + break; + + case ACPI_REFCLASS_INDEX: + + switch (obj_desc->reference.target_type) { + case ACPI_TYPE_BUFFER_FIELD: + + acpi_os_printf("%p", + obj_desc->reference. + object); + acpi_db_decode_internal_object + (obj_desc->reference.object); + break; + + case ACPI_TYPE_PACKAGE: + + acpi_os_printf("%p", + obj_desc->reference. + where); + if (!obj_desc->reference.where) { + acpi_os_printf + (" Uninitialized WHERE pointer"); + } else { + acpi_db_decode_internal_object(* + (obj_desc-> + reference. + where)); + } + break; + + default: + + acpi_os_printf + ("Unknown index target type"); + break; + } + break; + + case ACPI_REFCLASS_REFOF: + + if (!obj_desc->reference.object) { + acpi_os_printf + ("Uninitialized reference subobject pointer"); + break; + } + + /* Reference can be to a Node or an Operand object */ + + switch (ACPI_GET_DESCRIPTOR_TYPE + (obj_desc->reference.object)) { + case ACPI_DESC_TYPE_NAMED: + + acpi_db_decode_node(obj_desc->reference. + object); + break; + + case ACPI_DESC_TYPE_OPERAND: + + acpi_db_decode_internal_object + (obj_desc->reference.object); + break; + + default: + break; + } + break; + + case ACPI_REFCLASS_NAME: + + acpi_db_decode_node(obj_desc->reference.node); + break; + + case ACPI_REFCLASS_DEBUG: + case ACPI_REFCLASS_TABLE: + + acpi_os_printf("\n"); + break; + + default: /* Unknown reference class */ + + acpi_os_printf("%2.2X\n", + obj_desc->reference.class); + break; + } + break; + + default: + + acpi_os_printf(" "); + acpi_db_decode_internal_object(obj_desc); + break; + } + break; + + default: + + acpi_os_printf(" [%s]", + acpi_ut_get_descriptor_name(obj_desc)); + break; + } + + acpi_os_printf("\n"); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_decode_locals + * + * PARAMETERS: walk_state - State for current method + * + * RETURN: None + * + * DESCRIPTION: Display all locals for the currently running control method + * + ******************************************************************************/ + +void acpi_db_decode_locals(struct acpi_walk_state *walk_state) +{ + u32 i; + union acpi_operand_object *obj_desc; + struct acpi_namespace_node *node; + u8 display_locals = FALSE; + + obj_desc = walk_state->method_desc; + node = walk_state->method_node; + + if (!node) { + acpi_os_printf + ("No method node (Executing subtree for buffer or opregion)\n"); + return; + } + + if (node->type != ACPI_TYPE_METHOD) { + acpi_os_printf("Executing subtree for Buffer/Package/Region\n"); + return; + } + + /* Are any locals actually set? */ + + for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++) { + obj_desc = walk_state->local_variables[i].object; + if (obj_desc) { + display_locals = TRUE; + break; + } + } + + /* If any are set, only display the ones that are set */ + + if (display_locals) { + acpi_os_printf + ("\nInitialized Local Variables for method [%4.4s]:\n", + acpi_ut_get_node_name(node)); + + for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++) { + obj_desc = walk_state->local_variables[i].object; + if (obj_desc) { + acpi_os_printf(" Local%X: ", i); + acpi_db_display_internal_object(obj_desc, + walk_state); + } + } + } else { + acpi_os_printf + ("No Local Variables are initialized for method [%4.4s]\n", + acpi_ut_get_node_name(node)); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_decode_arguments + * + * PARAMETERS: walk_state - State for current method + * + * RETURN: None + * + * DESCRIPTION: Display all arguments for the currently running control method + * + ******************************************************************************/ + +void acpi_db_decode_arguments(struct acpi_walk_state *walk_state) +{ + u32 i; + union acpi_operand_object *obj_desc; + struct acpi_namespace_node *node; + u8 display_args = FALSE; + + node = walk_state->method_node; + obj_desc = walk_state->method_desc; + + if (!node) { + acpi_os_printf + ("No method node (Executing subtree for buffer or opregion)\n"); + return; + } + + if (node->type != ACPI_TYPE_METHOD) { + acpi_os_printf("Executing subtree for Buffer/Package/Region\n"); + return; + } + + /* Are any arguments actually set? */ + + for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) { + obj_desc = walk_state->arguments[i].object; + if (obj_desc) { + display_args = TRUE; + break; + } + } + + /* If any are set, only display the ones that are set */ + + if (display_args) { + acpi_os_printf("Initialized Arguments for Method [%4.4s]: " + "(%X arguments defined for method invocation)\n", + acpi_ut_get_node_name(node), + obj_desc->method.param_count); + + for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) { + obj_desc = walk_state->arguments[i].object; + if (obj_desc) { + acpi_os_printf(" Arg%u: ", i); + acpi_db_display_internal_object(obj_desc, + walk_state); + } + } + } else { + acpi_os_printf + ("No Arguments are initialized for method [%4.4s]\n", + acpi_ut_get_node_name(node)); + } +} diff --git a/kernel/drivers/acpi/acpica/dbstats.c b/kernel/drivers/acpi/acpica/dbstats.c new file mode 100644 index 000000000..4ba0a2081 --- /dev/null +++ b/kernel/drivers/acpi/acpica/dbstats.c @@ -0,0 +1,546 @@ +/******************************************************************************* + * + * Module Name: dbstats - Generation and display of ACPI table statistics + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2015, 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 +#include "accommon.h" +#include "acdebug.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_CA_DEBUGGER +ACPI_MODULE_NAME("dbstats") + +/* Local prototypes */ +static void acpi_db_count_namespace_objects(void); + +static void acpi_db_enumerate_object(union acpi_operand_object *obj_desc); + +static acpi_status +acpi_db_classify_one_object(acpi_handle obj_handle, + u32 nesting_level, + void *context, void **return_value); + +#if defined ACPI_DBG_TRACK_ALLOCATIONS || defined ACPI_USE_LOCAL_CACHE +static void acpi_db_list_info(struct acpi_memory_list *list); +#endif + +/* + * Statistics subcommands + */ +static struct acpi_db_argument_info acpi_db_stat_types[] = { + {"ALLOCATIONS"}, + {"OBJECTS"}, + {"MEMORY"}, + {"MISC"}, + {"TABLES"}, + {"SIZES"}, + {"STACK"}, + {NULL} /* Must be null terminated */ +}; + +#define CMD_STAT_ALLOCATIONS 0 +#define CMD_STAT_OBJECTS 1 +#define CMD_STAT_MEMORY 2 +#define CMD_STAT_MISC 3 +#define CMD_STAT_TABLES 4 +#define CMD_STAT_SIZES 5 +#define CMD_STAT_STACK 6 + +#if defined ACPI_DBG_TRACK_ALLOCATIONS || defined ACPI_USE_LOCAL_CACHE +/******************************************************************************* + * + * FUNCTION: acpi_db_list_info + * + * PARAMETERS: list - Memory list/cache to be displayed + * + * RETURN: None + * + * DESCRIPTION: Display information about the input memory list or cache. + * + ******************************************************************************/ + +static void acpi_db_list_info(struct acpi_memory_list *list) +{ +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + u32 outstanding; +#endif + + acpi_os_printf("\n%s\n", list->list_name); + + /* max_depth > 0 indicates a cache object */ + + if (list->max_depth > 0) { + acpi_os_printf + (" Cache: [Depth MaxD Avail Size] " + "%8.2X %8.2X %8.2X %8.2X\n", list->current_depth, + list->max_depth, list->max_depth - list->current_depth, + (list->current_depth * list->object_size)); + } +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + if (list->max_depth > 0) { + acpi_os_printf + (" Cache: [Requests Hits Misses ObjSize] " + "%8.2X %8.2X %8.2X %8.2X\n", list->requests, list->hits, + list->requests - list->hits, list->object_size); + } + + outstanding = acpi_db_get_cache_info(list); + + if (list->object_size) { + acpi_os_printf + (" Mem: [Alloc Free Max CurSize Outstanding] " + "%8.2X %8.2X %8.2X %8.2X %8.2X\n", list->total_allocated, + list->total_freed, list->max_occupied, + outstanding * list->object_size, outstanding); + } else { + acpi_os_printf + (" Mem: [Alloc Free Max CurSize Outstanding Total] " + "%8.2X %8.2X %8.2X %8.2X %8.2X %8.2X\n", + list->total_allocated, list->total_freed, + list->max_occupied, list->current_total_size, outstanding, + list->total_size); + } +#endif +} +#endif + +/******************************************************************************* + * + * FUNCTION: acpi_db_enumerate_object + * + * PARAMETERS: obj_desc - Object to be counted + * + * RETURN: None + * + * DESCRIPTION: Add this object to the global counts, by object type. + * Limited recursion handles subobjects and packages, and this + * is probably acceptable within the AML debugger only. + * + ******************************************************************************/ + +static void acpi_db_enumerate_object(union acpi_operand_object *obj_desc) +{ + u32 i; + + if (!obj_desc) { + return; + } + + /* Enumerate this object first */ + + acpi_gbl_num_objects++; + + if (obj_desc->common.type > ACPI_TYPE_NS_NODE_MAX) { + acpi_gbl_obj_type_count_misc++; + } else { + acpi_gbl_obj_type_count[obj_desc->common.type]++; + } + + /* Count the sub-objects */ + + switch (obj_desc->common.type) { + case ACPI_TYPE_PACKAGE: + + for (i = 0; i < obj_desc->package.count; i++) { + acpi_db_enumerate_object(obj_desc->package.elements[i]); + } + break; + + case ACPI_TYPE_DEVICE: + + acpi_db_enumerate_object(obj_desc->device.notify_list[0]); + acpi_db_enumerate_object(obj_desc->device.notify_list[1]); + acpi_db_enumerate_object(obj_desc->device.handler); + break; + + case ACPI_TYPE_BUFFER_FIELD: + + if (acpi_ns_get_secondary_object(obj_desc)) { + acpi_gbl_obj_type_count[ACPI_TYPE_BUFFER_FIELD]++; + } + break; + + case ACPI_TYPE_REGION: + + acpi_gbl_obj_type_count[ACPI_TYPE_LOCAL_REGION_FIELD]++; + acpi_db_enumerate_object(obj_desc->region.handler); + break; + + case ACPI_TYPE_POWER: + + acpi_db_enumerate_object(obj_desc->power_resource. + notify_list[0]); + acpi_db_enumerate_object(obj_desc->power_resource. + notify_list[1]); + break; + + case ACPI_TYPE_PROCESSOR: + + acpi_db_enumerate_object(obj_desc->processor.notify_list[0]); + acpi_db_enumerate_object(obj_desc->processor.notify_list[1]); + acpi_db_enumerate_object(obj_desc->processor.handler); + break; + + case ACPI_TYPE_THERMAL: + + acpi_db_enumerate_object(obj_desc->thermal_zone.notify_list[0]); + acpi_db_enumerate_object(obj_desc->thermal_zone.notify_list[1]); + acpi_db_enumerate_object(obj_desc->thermal_zone.handler); + break; + + default: + + break; + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_classify_one_object + * + * PARAMETERS: Callback for walk_namespace + * + * RETURN: Status + * + * DESCRIPTION: Enumerate both the object descriptor (including subobjects) and + * the parent namespace node. + * + ******************************************************************************/ + +static acpi_status +acpi_db_classify_one_object(acpi_handle obj_handle, + u32 nesting_level, + void *context, void **return_value) +{ + struct acpi_namespace_node *node; + union acpi_operand_object *obj_desc; + u32 type; + + acpi_gbl_num_nodes++; + + node = (struct acpi_namespace_node *)obj_handle; + obj_desc = acpi_ns_get_attached_object(node); + + acpi_db_enumerate_object(obj_desc); + + type = node->type; + if (type > ACPI_TYPE_NS_NODE_MAX) { + acpi_gbl_node_type_count_misc++; + } else { + acpi_gbl_node_type_count[type]++; + } + + return (AE_OK); + +#ifdef ACPI_FUTURE_IMPLEMENTATION + + /* TBD: These need to be counted during the initial parsing phase */ + + if (acpi_ps_is_named_op(op->opcode)) { + num_nodes++; + } + + if (is_method) { + num_method_elements++; + } + + num_grammar_elements++; + op = acpi_ps_get_depth_next(root, op); + + size_of_parse_tree = (num_grammar_elements - num_method_elements) * + (u32)sizeof(union acpi_parse_object); + size_of_method_trees = + num_method_elements * (u32)sizeof(union acpi_parse_object); + size_of_node_entries = + num_nodes * (u32)sizeof(struct acpi_namespace_node); + size_of_acpi_objects = + num_nodes * (u32)sizeof(union acpi_operand_object); +#endif +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_count_namespace_objects + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Count and classify the entire namespace, including all + * namespace nodes and attached objects. + * + ******************************************************************************/ + +static void acpi_db_count_namespace_objects(void) +{ + u32 i; + + acpi_gbl_num_nodes = 0; + acpi_gbl_num_objects = 0; + + acpi_gbl_obj_type_count_misc = 0; + for (i = 0; i < (ACPI_TYPE_NS_NODE_MAX - 1); i++) { + acpi_gbl_obj_type_count[i] = 0; + acpi_gbl_node_type_count[i] = 0; + } + + (void)acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, FALSE, + acpi_db_classify_one_object, NULL, NULL, + NULL); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_display_statistics + * + * PARAMETERS: type_arg - Subcommand + * + * RETURN: Status + * + * DESCRIPTION: Display various statistics + * + ******************************************************************************/ + +acpi_status acpi_db_display_statistics(char *type_arg) +{ + u32 i; + u32 temp; + + acpi_ut_strupr(type_arg); + temp = acpi_db_match_argument(type_arg, acpi_db_stat_types); + if (temp == ACPI_TYPE_NOT_FOUND) { + acpi_os_printf("Invalid or unsupported argument\n"); + return (AE_OK); + } + + switch (temp) { + case CMD_STAT_ALLOCATIONS: + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + acpi_ut_dump_allocation_info(); +#endif + break; + + case CMD_STAT_TABLES: + + acpi_os_printf("ACPI Table Information (not implemented):\n\n"); + break; + + case CMD_STAT_OBJECTS: + + acpi_db_count_namespace_objects(); + + acpi_os_printf + ("\nObjects defined in the current namespace:\n\n"); + + acpi_os_printf("%16.16s %10.10s %10.10s\n", + "ACPI_TYPE", "NODES", "OBJECTS"); + + for (i = 0; i < ACPI_TYPE_NS_NODE_MAX; i++) { + acpi_os_printf("%16.16s % 10ld% 10ld\n", + acpi_ut_get_type_name(i), + acpi_gbl_node_type_count[i], + acpi_gbl_obj_type_count[i]); + } + acpi_os_printf("%16.16s % 10ld% 10ld\n", "Misc/Unknown", + acpi_gbl_node_type_count_misc, + acpi_gbl_obj_type_count_misc); + + acpi_os_printf("%16.16s % 10ld% 10ld\n", "TOTALS:", + acpi_gbl_num_nodes, acpi_gbl_num_objects); + break; + + case CMD_STAT_MEMORY: + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + acpi_os_printf + ("\n----Object Statistics (all in hex)---------\n"); + + acpi_db_list_info(acpi_gbl_global_list); + acpi_db_list_info(acpi_gbl_ns_node_list); +#endif + +#ifdef ACPI_USE_LOCAL_CACHE + acpi_os_printf + ("\n----Cache Statistics (all in hex)---------\n"); + acpi_db_list_info(acpi_gbl_operand_cache); + acpi_db_list_info(acpi_gbl_ps_node_cache); + acpi_db_list_info(acpi_gbl_ps_node_ext_cache); + acpi_db_list_info(acpi_gbl_state_cache); +#endif + + break; + + case CMD_STAT_MISC: + + acpi_os_printf("\nMiscellaneous Statistics:\n\n"); + acpi_os_printf("Calls to AcpiPsFind:.. ........% 7ld\n", + acpi_gbl_ps_find_count); + acpi_os_printf("Calls to AcpiNsLookup:..........% 7ld\n", + acpi_gbl_ns_lookup_count); + + acpi_os_printf("\n"); + + acpi_os_printf("Mutex usage:\n\n"); + for (i = 0; i < ACPI_NUM_MUTEX; i++) { + acpi_os_printf("%-28s: % 7ld\n", + acpi_ut_get_mutex_name(i), + acpi_gbl_mutex_info[i].use_count); + } + break; + + case CMD_STAT_SIZES: + + acpi_os_printf("\nInternal object sizes:\n\n"); + + acpi_os_printf("Common %3d\n", + sizeof(struct acpi_object_common)); + acpi_os_printf("Number %3d\n", + sizeof(struct acpi_object_integer)); + acpi_os_printf("String %3d\n", + sizeof(struct acpi_object_string)); + acpi_os_printf("Buffer %3d\n", + sizeof(struct acpi_object_buffer)); + acpi_os_printf("Package %3d\n", + sizeof(struct acpi_object_package)); + acpi_os_printf("BufferField %3d\n", + sizeof(struct acpi_object_buffer_field)); + acpi_os_printf("Device %3d\n", + sizeof(struct acpi_object_device)); + acpi_os_printf("Event %3d\n", + sizeof(struct acpi_object_event)); + acpi_os_printf("Method %3d\n", + sizeof(struct acpi_object_method)); + acpi_os_printf("Mutex %3d\n", + sizeof(struct acpi_object_mutex)); + acpi_os_printf("Region %3d\n", + sizeof(struct acpi_object_region)); + acpi_os_printf("PowerResource %3d\n", + sizeof(struct acpi_object_power_resource)); + acpi_os_printf("Processor %3d\n", + sizeof(struct acpi_object_processor)); + acpi_os_printf("ThermalZone %3d\n", + sizeof(struct acpi_object_thermal_zone)); + acpi_os_printf("RegionField %3d\n", + sizeof(struct acpi_object_region_field)); + acpi_os_printf("BankField %3d\n", + sizeof(struct acpi_object_bank_field)); + acpi_os_printf("IndexField %3d\n", + sizeof(struct acpi_object_index_field)); + acpi_os_printf("Reference %3d\n", + sizeof(struct acpi_object_reference)); + acpi_os_printf("Notify %3d\n", + sizeof(struct acpi_object_notify_handler)); + acpi_os_printf("AddressSpace %3d\n", + sizeof(struct acpi_object_addr_handler)); + acpi_os_printf("Extra %3d\n", + sizeof(struct acpi_object_extra)); + acpi_os_printf("Data %3d\n", + sizeof(struct acpi_object_data)); + + acpi_os_printf("\n"); + + acpi_os_printf("ParseObject %3d\n", + sizeof(struct acpi_parse_obj_common)); + acpi_os_printf("ParseObjectNamed %3d\n", + sizeof(struct acpi_parse_obj_named)); + acpi_os_printf("ParseObjectAsl %3d\n", + sizeof(struct acpi_parse_obj_asl)); + acpi_os_printf("OperandObject %3d\n", + sizeof(union acpi_operand_object)); + acpi_os_printf("NamespaceNode %3d\n", + sizeof(struct acpi_namespace_node)); + acpi_os_printf("AcpiObject %3d\n", + sizeof(union acpi_object)); + + acpi_os_printf("\n"); + + acpi_os_printf("Generic State %3d\n", + sizeof(union acpi_generic_state)); + acpi_os_printf("Common State %3d\n", + sizeof(struct acpi_common_state)); + acpi_os_printf("Control State %3d\n", + sizeof(struct acpi_control_state)); + acpi_os_printf("Update State %3d\n", + sizeof(struct acpi_update_state)); + acpi_os_printf("Scope State %3d\n", + sizeof(struct acpi_scope_state)); + acpi_os_printf("Parse Scope %3d\n", + sizeof(struct acpi_pscope_state)); + acpi_os_printf("Package State %3d\n", + sizeof(struct acpi_pkg_state)); + acpi_os_printf("Thread State %3d\n", + sizeof(struct acpi_thread_state)); + acpi_os_printf("Result Values %3d\n", + sizeof(struct acpi_result_values)); + acpi_os_printf("Notify Info %3d\n", + sizeof(struct acpi_notify_info)); + break; + + case CMD_STAT_STACK: +#if defined(ACPI_DEBUG_OUTPUT) + + temp = + (u32)ACPI_PTR_DIFF(acpi_gbl_entry_stack_pointer, + acpi_gbl_lowest_stack_pointer); + + acpi_os_printf("\nSubsystem Stack Usage:\n\n"); + acpi_os_printf("Entry Stack Pointer %p\n", + acpi_gbl_entry_stack_pointer); + acpi_os_printf("Lowest Stack Pointer %p\n", + acpi_gbl_lowest_stack_pointer); + acpi_os_printf("Stack Use %X (%u)\n", temp, + temp); + acpi_os_printf("Deepest Procedure Nesting %u\n", + acpi_gbl_deepest_nesting); +#endif + break; + + default: + + break; + } + + acpi_os_printf("\n"); + return (AE_OK); +} diff --git a/kernel/drivers/acpi/acpica/dbtest.c b/kernel/drivers/acpi/acpica/dbtest.c new file mode 100644 index 000000000..10ea8bf9b --- /dev/null +++ b/kernel/drivers/acpi/acpica/dbtest.c @@ -0,0 +1,1057 @@ +/******************************************************************************* + * + * Module Name: dbtest - Various debug-related tests + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2015, 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 +#include "accommon.h" +#include "acdebug.h" +#include "acnamesp.h" +#include "acpredef.h" + +#define _COMPONENT ACPI_CA_DEBUGGER +ACPI_MODULE_NAME("dbtest") + +/* Local prototypes */ +static void acpi_db_test_all_objects(void); + +static acpi_status +acpi_db_test_one_object(acpi_handle obj_handle, + u32 nesting_level, void *context, void **return_value); + +static acpi_status +acpi_db_test_integer_type(struct acpi_namespace_node *node, u32 bit_length); + +static acpi_status +acpi_db_test_buffer_type(struct acpi_namespace_node *node, u32 bit_length); + +static acpi_status +acpi_db_test_string_type(struct acpi_namespace_node *node, u32 byte_length); + +static acpi_status +acpi_db_read_from_object(struct acpi_namespace_node *node, + acpi_object_type expected_type, + union acpi_object **value); + +static acpi_status +acpi_db_write_to_object(struct acpi_namespace_node *node, + union acpi_object *value); + +static void acpi_db_evaluate_all_predefined_names(char *count_arg); + +static acpi_status +acpi_db_evaluate_one_predefined_name(acpi_handle obj_handle, + u32 nesting_level, + void *context, void **return_value); + +/* + * Test subcommands + */ +static struct acpi_db_argument_info acpi_db_test_types[] = { + {"OBJECTS"}, + {"PREDEFINED"}, + {NULL} /* Must be null terminated */ +}; + +#define CMD_TEST_OBJECTS 0 +#define CMD_TEST_PREDEFINED 1 + +#define BUFFER_FILL_VALUE 0xFF + +/* + * Support for the special debugger read/write control methods. + * These methods are installed into the current namespace and are + * used to read and write the various namespace objects. The point + * is to force the AML interpreter do all of the work. + */ +#define ACPI_DB_READ_METHOD "\\_T98" +#define ACPI_DB_WRITE_METHOD "\\_T99" + +static acpi_handle read_handle = NULL; +static acpi_handle write_handle = NULL; + +/* ASL Definitions of the debugger read/write control methods */ + +#if 0 +definition_block("ssdt.aml", "SSDT", 2, "Intel", "DEBUG", 0x00000001) +{ + method(_T98, 1, not_serialized) { /* Read */ + return (de_ref_of(arg0)) + } +} + +definition_block("ssdt2.aml", "SSDT", 2, "Intel", "DEBUG", 0x00000001) +{ + method(_T99, 2, not_serialized) { /* Write */ + store(arg1, arg0) + } +} +#endif + +static unsigned char read_method_code[] = { + 0x53, 0x53, 0x44, 0x54, 0x2E, 0x00, 0x00, 0x00, /* 00000000 "SSDT...." */ + 0x02, 0xC9, 0x49, 0x6E, 0x74, 0x65, 0x6C, 0x00, /* 00000008 "..Intel." */ + 0x44, 0x45, 0x42, 0x55, 0x47, 0x00, 0x00, 0x00, /* 00000010 "DEBUG..." */ + 0x01, 0x00, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* 00000018 "....INTL" */ + 0x18, 0x12, 0x13, 0x20, 0x14, 0x09, 0x5F, 0x54, /* 00000020 "... .._T" */ + 0x39, 0x38, 0x01, 0xA4, 0x83, 0x68 /* 00000028 "98...h" */ +}; + +static unsigned char write_method_code[] = { + 0x53, 0x53, 0x44, 0x54, 0x2E, 0x00, 0x00, 0x00, /* 00000000 "SSDT...." */ + 0x02, 0x15, 0x49, 0x6E, 0x74, 0x65, 0x6C, 0x00, /* 00000008 "..Intel." */ + 0x44, 0x45, 0x42, 0x55, 0x47, 0x00, 0x00, 0x00, /* 00000010 "DEBUG..." */ + 0x01, 0x00, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C, /* 00000018 "....INTL" */ + 0x18, 0x12, 0x13, 0x20, 0x14, 0x09, 0x5F, 0x54, /* 00000020 "... .._T" */ + 0x39, 0x39, 0x02, 0x70, 0x69, 0x68 /* 00000028 "99.pih" */ +}; + +/******************************************************************************* + * + * FUNCTION: acpi_db_execute_test + * + * PARAMETERS: type_arg - Subcommand + * + * RETURN: None + * + * DESCRIPTION: Execute various debug tests. + * + * Note: Code is prepared for future expansion of the TEST command. + * + ******************************************************************************/ + +void acpi_db_execute_test(char *type_arg) +{ + u32 temp; + + acpi_ut_strupr(type_arg); + temp = acpi_db_match_argument(type_arg, acpi_db_test_types); + if (temp == ACPI_TYPE_NOT_FOUND) { + acpi_os_printf("Invalid or unsupported argument\n"); + return; + } + + switch (temp) { + case CMD_TEST_OBJECTS: + + acpi_db_test_all_objects(); + break; + + case CMD_TEST_PREDEFINED: + + acpi_db_evaluate_all_predefined_names(NULL); + break; + + default: + break; + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_test_all_objects + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: This test implements the OBJECTS subcommand. It exercises the + * namespace by reading/writing/comparing all data objects such + * as integers, strings, buffers, fields, buffer fields, etc. + * + ******************************************************************************/ + +static void acpi_db_test_all_objects(void) +{ + acpi_status status; + + /* Install the debugger read-object control method if necessary */ + + if (!read_handle) { + status = acpi_install_method(read_method_code); + if (ACPI_FAILURE(status)) { + acpi_os_printf + ("%s, Could not install debugger read method\n", + acpi_format_exception(status)); + return; + } + + status = + acpi_get_handle(NULL, ACPI_DB_READ_METHOD, &read_handle); + if (ACPI_FAILURE(status)) { + acpi_os_printf + ("Could not obtain handle for debug method %s\n", + ACPI_DB_READ_METHOD); + return; + } + } + + /* Install the debugger write-object control method if necessary */ + + if (!write_handle) { + status = acpi_install_method(write_method_code); + if (ACPI_FAILURE(status)) { + acpi_os_printf + ("%s, Could not install debugger write method\n", + acpi_format_exception(status)); + return; + } + + status = + acpi_get_handle(NULL, ACPI_DB_WRITE_METHOD, &write_handle); + if (ACPI_FAILURE(status)) { + acpi_os_printf + ("Could not obtain handle for debug method %s\n", + ACPI_DB_WRITE_METHOD); + return; + } + } + + /* Walk the entire namespace, testing each supported named data object */ + + (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, acpi_db_test_one_object, + NULL, NULL, NULL); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_test_one_object + * + * PARAMETERS: acpi_walk_callback + * + * RETURN: Status + * + * DESCRIPTION: Test one namespace object. Supported types are Integer, + * String, Buffer, buffer_field, and field_unit. All other object + * types are simply ignored. + * + * Note: Support for Packages is not implemented. + * + ******************************************************************************/ + +static acpi_status +acpi_db_test_one_object(acpi_handle obj_handle, + u32 nesting_level, void *context, void **return_value) +{ + struct acpi_namespace_node *node; + union acpi_operand_object *obj_desc; + union acpi_operand_object *region_obj; + acpi_object_type local_type; + u32 bit_length = 0; + u32 byte_length = 0; + acpi_status status = AE_OK; + + node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle); + obj_desc = node->object; + + /* + * For the supported types, get the actual bit length or + * byte length. Map the type to one of Integer/String/Buffer. + */ + switch (node->type) { + case ACPI_TYPE_INTEGER: + + /* Integer width is either 32 or 64 */ + + local_type = ACPI_TYPE_INTEGER; + bit_length = acpi_gbl_integer_bit_width; + break; + + case ACPI_TYPE_STRING: + + local_type = ACPI_TYPE_STRING; + byte_length = obj_desc->string.length; + break; + + case ACPI_TYPE_BUFFER: + + local_type = ACPI_TYPE_BUFFER; + byte_length = obj_desc->buffer.length; + bit_length = byte_length * 8; + break; + + case ACPI_TYPE_FIELD_UNIT: + case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_REGION_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + + local_type = ACPI_TYPE_INTEGER; + if (obj_desc) { + /* + * Returned object will be a Buffer if the field length + * is larger than the size of an Integer (32 or 64 bits + * depending on the DSDT version). + */ + bit_length = obj_desc->common_field.bit_length; + byte_length = ACPI_ROUND_BITS_UP_TO_BYTES(bit_length); + if (bit_length > acpi_gbl_integer_bit_width) { + local_type = ACPI_TYPE_BUFFER; + } + } + break; + + default: + + /* Ignore all other types */ + + return (AE_OK); + } + + /* Emit the common prefix: Type:Name */ + + acpi_os_printf("%14s: %4.4s", + acpi_ut_get_type_name(node->type), node->name.ascii); + if (!obj_desc) { + acpi_os_printf(" Ignoring, no attached object\n"); + return (AE_OK); + } + + /* + * Check for unsupported region types. Note: acpi_exec simulates + * access to system_memory, system_IO, PCI_Config, and EC. + */ + switch (node->type) { + case ACPI_TYPE_LOCAL_REGION_FIELD: + + region_obj = obj_desc->field.region_obj; + switch (region_obj->region.space_id) { + case ACPI_ADR_SPACE_SYSTEM_MEMORY: + case ACPI_ADR_SPACE_SYSTEM_IO: + case ACPI_ADR_SPACE_PCI_CONFIG: + case ACPI_ADR_SPACE_EC: + + break; + + default: + + acpi_os_printf + (" %s space is not supported [%4.4s]\n", + acpi_ut_get_region_name(region_obj->region. + space_id), + region_obj->region.node->name.ascii); + return (AE_OK); + } + break; + + default: + break; + } + + /* At this point, we have resolved the object to one of the major types */ + + switch (local_type) { + case ACPI_TYPE_INTEGER: + + status = acpi_db_test_integer_type(node, bit_length); + break; + + case ACPI_TYPE_STRING: + + status = acpi_db_test_string_type(node, byte_length); + break; + + case ACPI_TYPE_BUFFER: + + status = acpi_db_test_buffer_type(node, bit_length); + break; + + default: + + acpi_os_printf(" Ignoring, type not implemented (%2.2X)", + local_type); + break; + } + + switch (node->type) { + case ACPI_TYPE_LOCAL_REGION_FIELD: + + region_obj = obj_desc->field.region_obj; + acpi_os_printf(" (%s)", + acpi_ut_get_region_name(region_obj->region. + space_id)); + break; + + default: + break; + } + + acpi_os_printf("\n"); + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_test_integer_type + * + * PARAMETERS: node - Parent NS node for the object + * bit_length - Actual length of the object. Used for + * support of arbitrary length field_unit + * and buffer_field objects. + * + * RETURN: Status + * + * DESCRIPTION: Test read/write for an Integer-valued object. Performs a + * write/read/compare of an arbitrary new value, then performs + * a write/read/compare of the original value. + * + ******************************************************************************/ + +static acpi_status +acpi_db_test_integer_type(struct acpi_namespace_node *node, u32 bit_length) +{ + union acpi_object *temp1 = NULL; + union acpi_object *temp2 = NULL; + union acpi_object *temp3 = NULL; + union acpi_object write_value; + u64 value_to_write; + acpi_status status; + + if (bit_length > 64) { + acpi_os_printf(" Invalid length for an Integer: %u", + bit_length); + return (AE_OK); + } + + /* Read the original value */ + + status = acpi_db_read_from_object(node, ACPI_TYPE_INTEGER, &temp1); + if (ACPI_FAILURE(status)) { + return (status); + } + + acpi_os_printf(" (%4.4X/%3.3X) %8.8X%8.8X", + bit_length, ACPI_ROUND_BITS_UP_TO_BYTES(bit_length), + ACPI_FORMAT_UINT64(temp1->integer.value)); + + value_to_write = ACPI_UINT64_MAX >> (64 - bit_length); + if (temp1->integer.value == value_to_write) { + value_to_write = 0; + } + + /* Write a new value */ + + write_value.type = ACPI_TYPE_INTEGER; + write_value.integer.value = value_to_write; + status = acpi_db_write_to_object(node, &write_value); + if (ACPI_FAILURE(status)) { + goto exit; + } + + /* Ensure that we can read back the new value */ + + status = acpi_db_read_from_object(node, ACPI_TYPE_INTEGER, &temp2); + if (ACPI_FAILURE(status)) { + goto exit; + } + + if (temp2->integer.value != value_to_write) { + acpi_os_printf(" MISMATCH 2: %8.8X%8.8X, expecting %8.8X%8.8X", + ACPI_FORMAT_UINT64(temp2->integer.value), + ACPI_FORMAT_UINT64(value_to_write)); + } + + /* Write back the original value */ + + write_value.integer.value = temp1->integer.value; + status = acpi_db_write_to_object(node, &write_value); + if (ACPI_FAILURE(status)) { + goto exit; + } + + /* Ensure that we can read back the original value */ + + status = acpi_db_read_from_object(node, ACPI_TYPE_INTEGER, &temp3); + if (ACPI_FAILURE(status)) { + goto exit; + } + + if (temp3->integer.value != temp1->integer.value) { + acpi_os_printf(" MISMATCH 3: %8.8X%8.8X, expecting %8.8X%8.8X", + ACPI_FORMAT_UINT64(temp3->integer.value), + ACPI_FORMAT_UINT64(temp1->integer.value)); + } + +exit: + if (temp1) { + acpi_os_free(temp1); + } + if (temp2) { + acpi_os_free(temp2); + } + if (temp3) { + acpi_os_free(temp3); + } + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_test_buffer_type + * + * PARAMETERS: node - Parent NS node for the object + * bit_length - Actual length of the object. + * + * RETURN: Status + * + * DESCRIPTION: Test read/write for an Buffer-valued object. Performs a + * write/read/compare of an arbitrary new value, then performs + * a write/read/compare of the original value. + * + ******************************************************************************/ + +static acpi_status +acpi_db_test_buffer_type(struct acpi_namespace_node *node, u32 bit_length) +{ + union acpi_object *temp1 = NULL; + union acpi_object *temp2 = NULL; + union acpi_object *temp3 = NULL; + u8 *buffer; + union acpi_object write_value; + acpi_status status; + u32 byte_length; + u32 i; + u8 extra_bits; + + byte_length = ACPI_ROUND_BITS_UP_TO_BYTES(bit_length); + if (byte_length == 0) { + acpi_os_printf(" Ignoring zero length buffer"); + return (AE_OK); + } + + /* Allocate a local buffer */ + + buffer = ACPI_ALLOCATE_ZEROED(byte_length); + if (!buffer) { + return (AE_NO_MEMORY); + } + + /* Read the original value */ + + status = acpi_db_read_from_object(node, ACPI_TYPE_BUFFER, &temp1); + if (ACPI_FAILURE(status)) { + goto exit; + } + + /* Emit a few bytes of the buffer */ + + acpi_os_printf(" (%4.4X/%3.3X)", bit_length, temp1->buffer.length); + for (i = 0; ((i < 4) && (i < byte_length)); i++) { + acpi_os_printf(" %2.2X", temp1->buffer.pointer[i]); + } + acpi_os_printf("... "); + + /* + * Write a new value. + * + * Handle possible extra bits at the end of the buffer. Can + * happen for field_units larger than an integer, but the bit + * count is not an integral number of bytes. Zero out the + * unused bits. + */ + memset(buffer, BUFFER_FILL_VALUE, byte_length); + extra_bits = bit_length % 8; + if (extra_bits) { + buffer[byte_length - 1] = ACPI_MASK_BITS_ABOVE(extra_bits); + } + + write_value.type = ACPI_TYPE_BUFFER; + write_value.buffer.length = byte_length; + write_value.buffer.pointer = buffer; + + status = acpi_db_write_to_object(node, &write_value); + if (ACPI_FAILURE(status)) { + goto exit; + } + + /* Ensure that we can read back the new value */ + + status = acpi_db_read_from_object(node, ACPI_TYPE_BUFFER, &temp2); + if (ACPI_FAILURE(status)) { + goto exit; + } + + if (memcmp(temp2->buffer.pointer, buffer, byte_length)) { + acpi_os_printf(" MISMATCH 2: New buffer value"); + } + + /* Write back the original value */ + + write_value.buffer.length = byte_length; + write_value.buffer.pointer = temp1->buffer.pointer; + + status = acpi_db_write_to_object(node, &write_value); + if (ACPI_FAILURE(status)) { + goto exit; + } + + /* Ensure that we can read back the original value */ + + status = acpi_db_read_from_object(node, ACPI_TYPE_BUFFER, &temp3); + if (ACPI_FAILURE(status)) { + goto exit; + } + + if (memcmp(temp1->buffer.pointer, temp3->buffer.pointer, byte_length)) { + acpi_os_printf(" MISMATCH 3: While restoring original buffer"); + } + +exit: + ACPI_FREE(buffer); + if (temp1) { + acpi_os_free(temp1); + } + if (temp2) { + acpi_os_free(temp2); + } + if (temp3) { + acpi_os_free(temp3); + } + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_test_string_type + * + * PARAMETERS: node - Parent NS node for the object + * byte_length - Actual length of the object. + * + * RETURN: Status + * + * DESCRIPTION: Test read/write for an String-valued object. Performs a + * write/read/compare of an arbitrary new value, then performs + * a write/read/compare of the original value. + * + ******************************************************************************/ + +static acpi_status +acpi_db_test_string_type(struct acpi_namespace_node *node, u32 byte_length) +{ + union acpi_object *temp1 = NULL; + union acpi_object *temp2 = NULL; + union acpi_object *temp3 = NULL; + char *value_to_write = "Test String from AML Debugger"; + union acpi_object write_value; + acpi_status status; + + /* Read the original value */ + + status = acpi_db_read_from_object(node, ACPI_TYPE_STRING, &temp1); + if (ACPI_FAILURE(status)) { + return (status); + } + + acpi_os_printf(" (%4.4X/%3.3X) \"%s\"", (temp1->string.length * 8), + temp1->string.length, temp1->string.pointer); + + /* Write a new value */ + + write_value.type = ACPI_TYPE_STRING; + write_value.string.length = strlen(value_to_write); + write_value.string.pointer = value_to_write; + + status = acpi_db_write_to_object(node, &write_value); + if (ACPI_FAILURE(status)) { + goto exit; + } + + /* Ensure that we can read back the new value */ + + status = acpi_db_read_from_object(node, ACPI_TYPE_STRING, &temp2); + if (ACPI_FAILURE(status)) { + goto exit; + } + + if (strcmp(temp2->string.pointer, value_to_write)) { + acpi_os_printf(" MISMATCH 2: %s, expecting %s", + temp2->string.pointer, value_to_write); + } + + /* Write back the original value */ + + write_value.string.length = strlen(temp1->string.pointer); + write_value.string.pointer = temp1->string.pointer; + + status = acpi_db_write_to_object(node, &write_value); + if (ACPI_FAILURE(status)) { + goto exit; + } + + /* Ensure that we can read back the original value */ + + status = acpi_db_read_from_object(node, ACPI_TYPE_STRING, &temp3); + if (ACPI_FAILURE(status)) { + goto exit; + } + + if (strcmp(temp1->string.pointer, temp3->string.pointer)) { + acpi_os_printf(" MISMATCH 3: %s, expecting %s", + temp3->string.pointer, temp1->string.pointer); + } + +exit: + if (temp1) { + acpi_os_free(temp1); + } + if (temp2) { + acpi_os_free(temp2); + } + if (temp3) { + acpi_os_free(temp3); + } + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_read_from_object + * + * PARAMETERS: node - Parent NS node for the object + * expected_type - Object type expected from the read + * value - Where the value read is returned + * + * RETURN: Status + * + * DESCRIPTION: Performs a read from the specified object by invoking the + * special debugger control method that reads the object. Thus, + * the AML interpreter is doing all of the work, increasing the + * validity of the test. + * + ******************************************************************************/ + +static acpi_status +acpi_db_read_from_object(struct acpi_namespace_node *node, + acpi_object_type expected_type, + union acpi_object **value) +{ + union acpi_object *ret_value; + struct acpi_object_list param_objects; + union acpi_object params[2]; + struct acpi_buffer return_obj; + acpi_status status; + + params[0].type = ACPI_TYPE_LOCAL_REFERENCE; + params[0].reference.actual_type = node->type; + params[0].reference.handle = ACPI_CAST_PTR(acpi_handle, node); + + param_objects.count = 1; + param_objects.pointer = params; + + return_obj.length = ACPI_ALLOCATE_BUFFER; + + acpi_gbl_method_executing = TRUE; + status = acpi_evaluate_object(read_handle, NULL, + ¶m_objects, &return_obj); + acpi_gbl_method_executing = FALSE; + + if (ACPI_FAILURE(status)) { + acpi_os_printf("Could not read from object, %s", + acpi_format_exception(status)); + return (status); + } + + ret_value = (union acpi_object *)return_obj.pointer; + + switch (ret_value->type) { + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_BUFFER: + case ACPI_TYPE_STRING: + /* + * Did we receive the type we wanted? Most important for the + * Integer/Buffer case (when a field is larger than an Integer, + * it should return a Buffer). + */ + if (ret_value->type != expected_type) { + acpi_os_printf + (" Type mismatch: Expected %s, Received %s", + acpi_ut_get_type_name(expected_type), + acpi_ut_get_type_name(ret_value->type)); + + return (AE_TYPE); + } + + *value = ret_value; + break; + + default: + + acpi_os_printf(" Unsupported return object type, %s", + acpi_ut_get_type_name(ret_value->type)); + + acpi_os_free(return_obj.pointer); + return (AE_TYPE); + } + + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_write_to_object + * + * PARAMETERS: node - Parent NS node for the object + * value - Value to be written + * + * RETURN: Status + * + * DESCRIPTION: Performs a write to the specified object by invoking the + * special debugger control method that writes the object. Thus, + * the AML interpreter is doing all of the work, increasing the + * validity of the test. + * + ******************************************************************************/ + +static acpi_status +acpi_db_write_to_object(struct acpi_namespace_node *node, + union acpi_object *value) +{ + struct acpi_object_list param_objects; + union acpi_object params[2]; + acpi_status status; + + params[0].type = ACPI_TYPE_LOCAL_REFERENCE; + params[0].reference.actual_type = node->type; + params[0].reference.handle = ACPI_CAST_PTR(acpi_handle, node); + + /* Copy the incoming user parameter */ + + memcpy(¶ms[1], value, sizeof(union acpi_object)); + + param_objects.count = 2; + param_objects.pointer = params; + + acpi_gbl_method_executing = TRUE; + status = acpi_evaluate_object(write_handle, NULL, ¶m_objects, NULL); + acpi_gbl_method_executing = FALSE; + + if (ACPI_FAILURE(status)) { + acpi_os_printf("Could not write to object, %s", + acpi_format_exception(status)); + } + + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_evaluate_all_predefined_names + * + * PARAMETERS: count_arg - Max number of methods to execute + * + * RETURN: None + * + * DESCRIPTION: Namespace batch execution. Execute predefined names in the + * namespace, up to the max count, if specified. + * + ******************************************************************************/ + +static void acpi_db_evaluate_all_predefined_names(char *count_arg) +{ + struct acpi_db_execute_walk info; + + info.count = 0; + info.max_count = ACPI_UINT32_MAX; + + if (count_arg) { + info.max_count = strtoul(count_arg, NULL, 0); + } + + /* Search all nodes in namespace */ + + (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, + acpi_db_evaluate_one_predefined_name, NULL, + (void *)&info, NULL); + + acpi_os_printf("Evaluated %u predefined names in the namespace\n", + info.count); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_evaluate_one_predefined_name + * + * PARAMETERS: Callback from walk_namespace + * + * RETURN: Status + * + * DESCRIPTION: Batch execution module. Currently only executes predefined + * ACPI names. + * + ******************************************************************************/ + +static acpi_status +acpi_db_evaluate_one_predefined_name(acpi_handle obj_handle, + u32 nesting_level, + void *context, void **return_value) +{ + struct acpi_namespace_node *node = + (struct acpi_namespace_node *)obj_handle; + struct acpi_db_execute_walk *info = + (struct acpi_db_execute_walk *)context; + char *pathname; + const union acpi_predefined_info *predefined; + struct acpi_device_info *obj_info; + struct acpi_object_list param_objects; + union acpi_object params[ACPI_METHOD_NUM_ARGS]; + union acpi_object *this_param; + struct acpi_buffer return_obj; + acpi_status status; + u16 arg_type_list; + u8 arg_count; + u8 arg_type; + u32 i; + + /* The name must be a predefined ACPI name */ + + predefined = acpi_ut_match_predefined_method(node->name.ascii); + if (!predefined) { + return (AE_OK); + } + + if (node->type == ACPI_TYPE_LOCAL_SCOPE) { + return (AE_OK); + } + + pathname = acpi_ns_get_external_pathname(node); + if (!pathname) { + return (AE_OK); + } + + /* Get the object info for number of method parameters */ + + status = acpi_get_object_info(obj_handle, &obj_info); + if (ACPI_FAILURE(status)) { + ACPI_FREE(pathname); + return (status); + } + + param_objects.count = 0; + param_objects.pointer = NULL; + + if (obj_info->type == ACPI_TYPE_METHOD) { + + /* Setup default parameters (with proper types) */ + + arg_type_list = predefined->info.argument_list; + arg_count = METHOD_GET_ARG_COUNT(arg_type_list); + + /* + * Setup the ACPI-required number of arguments, regardless of what + * the actual method defines. If there is a difference, then the + * method is wrong and a warning will be issued during execution. + */ + this_param = params; + for (i = 0; i < arg_count; i++) { + arg_type = METHOD_GET_NEXT_TYPE(arg_type_list); + this_param->type = arg_type; + + switch (arg_type) { + case ACPI_TYPE_INTEGER: + + this_param->integer.value = 1; + break; + + case ACPI_TYPE_STRING: + + this_param->string.pointer = + "This is the default argument string"; + this_param->string.length = + strlen(this_param->string.pointer); + break; + + case ACPI_TYPE_BUFFER: + + this_param->buffer.pointer = (u8 *)params; /* just a garbage buffer */ + this_param->buffer.length = 48; + break; + + case ACPI_TYPE_PACKAGE: + + this_param->package.elements = NULL; + this_param->package.count = 0; + break; + + default: + + acpi_os_printf + ("%s: Unsupported argument type: %u\n", + pathname, arg_type); + break; + } + + this_param++; + } + + param_objects.count = arg_count; + param_objects.pointer = params; + } + + ACPI_FREE(obj_info); + return_obj.pointer = NULL; + return_obj.length = ACPI_ALLOCATE_BUFFER; + + /* Do the actual method execution */ + + acpi_gbl_method_executing = TRUE; + + status = acpi_evaluate_object(node, NULL, ¶m_objects, &return_obj); + + acpi_os_printf("%-32s returned %s\n", + pathname, acpi_format_exception(status)); + acpi_gbl_method_executing = FALSE; + ACPI_FREE(pathname); + + /* Ignore status from method execution */ + + status = AE_OK; + + /* Update count, check if we have executed enough methods */ + + info->count++; + if (info->count >= info->max_count) { + status = AE_CTRL_TERMINATE; + } + + return (status); +} diff --git a/kernel/drivers/acpi/acpica/dbutils.c b/kernel/drivers/acpi/acpica/dbutils.c new file mode 100644 index 000000000..86790e080 --- /dev/null +++ b/kernel/drivers/acpi/acpica/dbutils.c @@ -0,0 +1,457 @@ +/******************************************************************************* + * + * Module Name: dbutils - AML debugger utilities + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2015, 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 +#include "accommon.h" +#include "acnamesp.h" +#include "acdebug.h" + +#define _COMPONENT ACPI_CA_DEBUGGER +ACPI_MODULE_NAME("dbutils") + +/* Local prototypes */ +#ifdef ACPI_OBSOLETE_FUNCTIONS +acpi_status acpi_db_second_pass_parse(union acpi_parse_object *root); + +void acpi_db_dump_buffer(u32 address); +#endif + +static char *gbl_hex_to_ascii = "0123456789ABCDEF"; + +/******************************************************************************* + * + * FUNCTION: acpi_db_match_argument + * + * PARAMETERS: user_argument - User command line + * arguments - Array of commands to match against + * + * RETURN: Index into command array or ACPI_TYPE_NOT_FOUND if not found + * + * DESCRIPTION: Search command array for a command match + * + ******************************************************************************/ + +acpi_object_type +acpi_db_match_argument(char *user_argument, + struct acpi_db_argument_info *arguments) +{ + u32 i; + + if (!user_argument || user_argument[0] == 0) { + return (ACPI_TYPE_NOT_FOUND); + } + + for (i = 0; arguments[i].name; i++) { + if (strstr(arguments[i].name, user_argument) == + arguments[i].name) { + return (i); + } + } + + /* Argument not recognized */ + + return (ACPI_TYPE_NOT_FOUND); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_set_output_destination + * + * PARAMETERS: output_flags - Current flags word + * + * RETURN: None + * + * DESCRIPTION: Set the current destination for debugger output. Also sets + * the debug output level accordingly. + * + ******************************************************************************/ + +void acpi_db_set_output_destination(u32 output_flags) +{ + + acpi_gbl_db_output_flags = (u8)output_flags; + + if ((output_flags & ACPI_DB_REDIRECTABLE_OUTPUT) && + acpi_gbl_db_output_to_file) { + acpi_dbg_level = acpi_gbl_db_debug_level; + } else { + acpi_dbg_level = acpi_gbl_db_console_debug_level; + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_dump_external_object + * + * PARAMETERS: obj_desc - External ACPI object to dump + * level - Nesting level. + * + * RETURN: None + * + * DESCRIPTION: Dump the contents of an ACPI external object + * + ******************************************************************************/ + +void acpi_db_dump_external_object(union acpi_object *obj_desc, u32 level) +{ + u32 i; + + if (!obj_desc) { + acpi_os_printf("[Null Object]\n"); + return; + } + + for (i = 0; i < level; i++) { + acpi_os_printf(" "); + } + + switch (obj_desc->type) { + case ACPI_TYPE_ANY: + + acpi_os_printf("[Null Object] (Type=0)\n"); + break; + + case ACPI_TYPE_INTEGER: + + acpi_os_printf("[Integer] = %8.8X%8.8X\n", + ACPI_FORMAT_UINT64(obj_desc->integer.value)); + break; + + case ACPI_TYPE_STRING: + + acpi_os_printf("[String] Length %.2X = ", + obj_desc->string.length); + acpi_ut_print_string(obj_desc->string.pointer, ACPI_UINT8_MAX); + acpi_os_printf("\n"); + break; + + case ACPI_TYPE_BUFFER: + + acpi_os_printf("[Buffer] Length %.2X = ", + obj_desc->buffer.length); + if (obj_desc->buffer.length) { + if (obj_desc->buffer.length > 16) { + acpi_os_printf("\n"); + } + acpi_ut_debug_dump_buffer(ACPI_CAST_PTR + (u8, + obj_desc->buffer.pointer), + obj_desc->buffer.length, + DB_BYTE_DISPLAY, _COMPONENT); + } else { + acpi_os_printf("\n"); + } + break; + + case ACPI_TYPE_PACKAGE: + + acpi_os_printf("[Package] Contains %u Elements:\n", + obj_desc->package.count); + + for (i = 0; i < obj_desc->package.count; i++) { + acpi_db_dump_external_object(&obj_desc->package. + elements[i], level + 1); + } + break; + + case ACPI_TYPE_LOCAL_REFERENCE: + + acpi_os_printf("[Object Reference] = "); + acpi_db_display_internal_object(obj_desc->reference.handle, + NULL); + break; + + case ACPI_TYPE_PROCESSOR: + + acpi_os_printf("[Processor]\n"); + break; + + case ACPI_TYPE_POWER: + + acpi_os_printf("[Power Resource]\n"); + break; + + default: + + acpi_os_printf("[Unknown Type] %X\n", obj_desc->type); + break; + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_prep_namestring + * + * PARAMETERS: name - String to prepare + * + * RETURN: None + * + * DESCRIPTION: Translate all forward slashes and dots to backslashes. + * + ******************************************************************************/ + +void acpi_db_prep_namestring(char *name) +{ + + if (!name) { + return; + } + + acpi_ut_strupr(name); + + /* Convert a leading forward slash to a backslash */ + + if (*name == '/') { + *name = '\\'; + } + + /* Ignore a leading backslash, this is the root prefix */ + + if (ACPI_IS_ROOT_PREFIX(*name)) { + name++; + } + + /* Convert all slash path separators to dots */ + + while (*name) { + if ((*name == '/') || (*name == '\\')) { + *name = '.'; + } + + name++; + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_local_ns_lookup + * + * PARAMETERS: name - Name to lookup + * + * RETURN: Pointer to a namespace node, null on failure + * + * DESCRIPTION: Lookup a name in the ACPI namespace + * + * Note: Currently begins search from the root. Could be enhanced to use + * the current prefix (scope) node as the search beginning point. + * + ******************************************************************************/ + +struct acpi_namespace_node *acpi_db_local_ns_lookup(char *name) +{ + char *internal_path; + acpi_status status; + struct acpi_namespace_node *node = NULL; + + acpi_db_prep_namestring(name); + + /* Build an internal namestring */ + + status = acpi_ns_internalize_name(name, &internal_path); + if (ACPI_FAILURE(status)) { + acpi_os_printf("Invalid namestring: %s\n", name); + return (NULL); + } + + /* + * Lookup the name. + * (Uses root node as the search starting point) + */ + status = acpi_ns_lookup(NULL, internal_path, ACPI_TYPE_ANY, + ACPI_IMODE_EXECUTE, + ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE, + NULL, &node); + if (ACPI_FAILURE(status)) { + acpi_os_printf("Could not locate name: %s, %s\n", + name, acpi_format_exception(status)); + } + + ACPI_FREE(internal_path); + return (node); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_uint32_to_hex_string + * + * PARAMETERS: value - The value to be converted to string + * buffer - Buffer for result (not less than 11 bytes) + * + * RETURN: None + * + * DESCRIPTION: Convert the unsigned 32-bit value to the hexadecimal image + * + * NOTE: It is the caller's responsibility to ensure that the length of buffer + * is sufficient. + * + ******************************************************************************/ + +void acpi_db_uint32_to_hex_string(u32 value, char *buffer) +{ + int i; + + if (value == 0) { + strcpy(buffer, "0"); + return; + } + + buffer[8] = '\0'; + + for (i = 7; i >= 0; i--) { + buffer[i] = gbl_hex_to_ascii[value & 0x0F]; + value = value >> 4; + } +} + +#ifdef ACPI_OBSOLETE_FUNCTIONS +/******************************************************************************* + * + * FUNCTION: acpi_db_second_pass_parse + * + * PARAMETERS: root - Root of the parse tree + * + * RETURN: Status + * + * DESCRIPTION: Second pass parse of the ACPI tables. We need to wait until + * second pass to parse the control methods + * + ******************************************************************************/ + +acpi_status acpi_db_second_pass_parse(union acpi_parse_object *root) +{ + union acpi_parse_object *op = root; + union acpi_parse_object *method; + union acpi_parse_object *search_op; + union acpi_parse_object *start_op; + acpi_status status = AE_OK; + u32 base_aml_offset; + struct acpi_walk_state *walk_state; + + ACPI_FUNCTION_ENTRY(); + + acpi_os_printf("Pass two parse ....\n"); + + while (op) { + if (op->common.aml_opcode == AML_METHOD_OP) { + method = op; + + /* Create a new walk state for the parse */ + + walk_state = + acpi_ds_create_walk_state(0, NULL, NULL, NULL); + if (!walk_state) { + return (AE_NO_MEMORY); + } + + /* Init the Walk State */ + + walk_state->parser_state.aml = + walk_state->parser_state.aml_start = + method->named.data; + walk_state->parser_state.aml_end = + walk_state->parser_state.pkg_end = + method->named.data + method->named.length; + walk_state->parser_state.start_scope = op; + + walk_state->descending_callback = + acpi_ds_load1_begin_op; + walk_state->ascending_callback = acpi_ds_load1_end_op; + + /* Perform the AML parse */ + + status = acpi_ps_parse_aml(walk_state); + + base_aml_offset = + (method->common.value.arg)->common.aml_offset + 1; + start_op = (method->common.value.arg)->common.next; + search_op = start_op; + + while (search_op) { + search_op->common.aml_offset += base_aml_offset; + search_op = + acpi_ps_get_depth_next(start_op, search_op); + } + } + + if (op->common.aml_opcode == AML_REGION_OP) { + + /* TBD: [Investigate] this isn't quite the right thing to do! */ + /* + * + * Method = (ACPI_DEFERRED_OP *) Op; + * Status = acpi_ps_parse_aml (Op, Method->Body, Method->body_length); + */ + } + + if (ACPI_FAILURE(status)) { + break; + } + + op = acpi_ps_get_depth_next(root, op); + } + + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_dump_buffer + * + * PARAMETERS: address - Pointer to the buffer + * + * RETURN: None + * + * DESCRIPTION: Print a portion of a buffer + * + ******************************************************************************/ + +void acpi_db_dump_buffer(u32 address) +{ + + acpi_os_printf("\nLocation %X:\n", address); + + acpi_dbg_level |= ACPI_LV_TABLES; + acpi_ut_debug_dump_buffer(ACPI_TO_POINTER(address), 64, DB_BYTE_DISPLAY, + ACPI_UINT32_MAX); +} +#endif diff --git a/kernel/drivers/acpi/acpica/dbxface.c b/kernel/drivers/acpi/acpica/dbxface.c new file mode 100644 index 000000000..342298a6e --- /dev/null +++ b/kernel/drivers/acpi/acpica/dbxface.c @@ -0,0 +1,513 @@ +/******************************************************************************* + * + * Module Name: dbxface - AML Debugger external interfaces + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2015, 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 +#include "accommon.h" +#include "amlcode.h" +#include "acdebug.h" + +#define _COMPONENT ACPI_CA_DEBUGGER +ACPI_MODULE_NAME("dbxface") + +/* Local prototypes */ +static acpi_status +acpi_db_start_command(struct acpi_walk_state *walk_state, + union acpi_parse_object *op); + +#ifdef ACPI_OBSOLETE_FUNCTIONS +void acpi_db_method_end(struct acpi_walk_state *walk_state); +#endif + +/******************************************************************************* + * + * FUNCTION: acpi_db_start_command + * + * PARAMETERS: walk_state - Current walk + * op - Current executing Op, from AML interpreter + * + * RETURN: Status + * + * DESCRIPTION: Enter debugger command loop + * + ******************************************************************************/ + +static acpi_status +acpi_db_start_command(struct acpi_walk_state *walk_state, + union acpi_parse_object *op) +{ + acpi_status status; + + /* TBD: [Investigate] are there namespace locking issues here? */ + + /* acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); */ + + /* Go into the command loop and await next user command */ + + acpi_gbl_method_executing = TRUE; + status = AE_CTRL_TRUE; + while (status == AE_CTRL_TRUE) { + if (acpi_gbl_debugger_configuration == DEBUGGER_MULTI_THREADED) { + + /* Handshake with the front-end that gets user command lines */ + + acpi_os_release_mutex(acpi_gbl_db_command_complete); + + status = + acpi_os_acquire_mutex(acpi_gbl_db_command_ready, + ACPI_WAIT_FOREVER); + if (ACPI_FAILURE(status)) { + return (status); + } + } else { + /* Single threaded, we must get a command line ourselves */ + + /* Force output to console until a command is entered */ + + acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); + + /* Different prompt if method is executing */ + + if (!acpi_gbl_method_executing) { + acpi_os_printf("%1c ", + ACPI_DEBUGGER_COMMAND_PROMPT); + } else { + acpi_os_printf("%1c ", + ACPI_DEBUGGER_EXECUTE_PROMPT); + } + + /* Get the user input line */ + + status = acpi_os_get_line(acpi_gbl_db_line_buf, + ACPI_DB_LINE_BUFFER_SIZE, + NULL); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "While parsing command line")); + return (status); + } + } + + status = + acpi_db_command_dispatch(acpi_gbl_db_line_buf, walk_state, + op); + } + + /* acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); */ + + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_single_step + * + * PARAMETERS: walk_state - Current walk + * op - Current executing op (from aml interpreter) + * opcode_class - Class of the current AML Opcode + * + * RETURN: Status + * + * DESCRIPTION: Called just before execution of an AML opcode. + * + ******************************************************************************/ + +acpi_status +acpi_db_single_step(struct acpi_walk_state * walk_state, + union acpi_parse_object * op, u32 opcode_class) +{ + union acpi_parse_object *next; + acpi_status status = AE_OK; + u32 original_debug_level; + union acpi_parse_object *display_op; + union acpi_parse_object *parent_op; + u32 aml_offset; + + ACPI_FUNCTION_ENTRY(); + +#ifndef ACPI_APPLICATION + if (acpi_gbl_db_thread_id != acpi_os_get_thread_id()) { + return (AE_OK); + } +#endif + + /* Check the abort flag */ + + if (acpi_gbl_abort_method) { + acpi_gbl_abort_method = FALSE; + return (AE_ABORT_METHOD); + } + + aml_offset = (u32)ACPI_PTR_DIFF(op->common.aml, + walk_state->parser_state.aml_start); + + /* Check for single-step breakpoint */ + + if (walk_state->method_breakpoint && + (walk_state->method_breakpoint <= aml_offset)) { + + /* Check if the breakpoint has been reached or passed */ + /* Hit the breakpoint, resume single step, reset breakpoint */ + + acpi_os_printf("***Break*** at AML offset %X\n", aml_offset); + acpi_gbl_cm_single_step = TRUE; + acpi_gbl_step_to_next_call = FALSE; + walk_state->method_breakpoint = 0; + } + + /* Check for user breakpoint (Must be on exact Aml offset) */ + + else if (walk_state->user_breakpoint && + (walk_state->user_breakpoint == aml_offset)) { + acpi_os_printf("***UserBreakpoint*** at AML offset %X\n", + aml_offset); + acpi_gbl_cm_single_step = TRUE; + acpi_gbl_step_to_next_call = FALSE; + walk_state->method_breakpoint = 0; + } + + /* + * Check if this is an opcode that we are interested in -- + * namely, opcodes that have arguments + */ + if (op->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { + return (AE_OK); + } + + switch (opcode_class) { + case AML_CLASS_UNKNOWN: + case AML_CLASS_ARGUMENT: /* constants, literals, etc. do nothing */ + + return (AE_OK); + + default: + + /* All other opcodes -- continue */ + break; + } + + /* + * Under certain debug conditions, display this opcode and its operands + */ + if ((acpi_gbl_db_output_to_file) || + (acpi_gbl_cm_single_step) || (acpi_dbg_level & ACPI_LV_PARSE)) { + if ((acpi_gbl_db_output_to_file) || + (acpi_dbg_level & ACPI_LV_PARSE)) { + acpi_os_printf + ("\n[AmlDebug] Next AML Opcode to execute:\n"); + } + + /* + * Display this op (and only this op - zero out the NEXT field + * temporarily, and disable parser trace output for the duration of + * the display because we don't want the extraneous debug output) + */ + original_debug_level = acpi_dbg_level; + acpi_dbg_level &= ~(ACPI_LV_PARSE | ACPI_LV_FUNCTIONS); + next = op->common.next; + op->common.next = NULL; + + display_op = op; + parent_op = op->common.parent; + if (parent_op) { + if ((walk_state->control_state) && + (walk_state->control_state->common.state == + ACPI_CONTROL_PREDICATE_EXECUTING)) { + /* + * We are executing the predicate of an IF or WHILE statement + * Search upwards for the containing IF or WHILE so that the + * entire predicate can be displayed. + */ + while (parent_op) { + if ((parent_op->common.aml_opcode == + AML_IF_OP) + || (parent_op->common.aml_opcode == + AML_WHILE_OP)) { + display_op = parent_op; + break; + } + parent_op = parent_op->common.parent; + } + } else { + while (parent_op) { + if ((parent_op->common.aml_opcode == + AML_IF_OP) + || (parent_op->common.aml_opcode == + AML_ELSE_OP) + || (parent_op->common.aml_opcode == + AML_SCOPE_OP) + || (parent_op->common.aml_opcode == + AML_METHOD_OP) + || (parent_op->common.aml_opcode == + AML_WHILE_OP)) { + break; + } + display_op = parent_op; + parent_op = parent_op->common.parent; + } + } + } + + /* Now we can display it */ + +#ifdef ACPI_DISASSEMBLER + acpi_dm_disassemble(walk_state, display_op, ACPI_UINT32_MAX); +#endif + + if ((op->common.aml_opcode == AML_IF_OP) || + (op->common.aml_opcode == AML_WHILE_OP)) { + if (walk_state->control_state->common.value) { + acpi_os_printf + ("Predicate = [True], IF block was executed\n"); + } else { + acpi_os_printf + ("Predicate = [False], Skipping IF block\n"); + } + } else if (op->common.aml_opcode == AML_ELSE_OP) { + acpi_os_printf + ("Predicate = [False], ELSE block was executed\n"); + } + + /* Restore everything */ + + op->common.next = next; + acpi_os_printf("\n"); + if ((acpi_gbl_db_output_to_file) || + (acpi_dbg_level & ACPI_LV_PARSE)) { + acpi_os_printf("\n"); + } + acpi_dbg_level = original_debug_level; + } + + /* If we are not single stepping, just continue executing the method */ + + if (!acpi_gbl_cm_single_step) { + return (AE_OK); + } + + /* + * If we are executing a step-to-call command, + * Check if this is a method call. + */ + if (acpi_gbl_step_to_next_call) { + if (op->common.aml_opcode != AML_INT_METHODCALL_OP) { + + /* Not a method call, just keep executing */ + + return (AE_OK); + } + + /* Found a method call, stop executing */ + + acpi_gbl_step_to_next_call = FALSE; + } + + /* + * If the next opcode is a method call, we will "step over" it + * by default. + */ + if (op->common.aml_opcode == AML_INT_METHODCALL_OP) { + + /* Force no more single stepping while executing called method */ + + acpi_gbl_cm_single_step = FALSE; + + /* + * Set the breakpoint on/before the call, it will stop execution + * as soon as we return + */ + walk_state->method_breakpoint = 1; /* Must be non-zero! */ + } + + status = acpi_db_start_command(walk_state, op); + + /* User commands complete, continue execution of the interrupted method */ + + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_initialize_debugger + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Init and start debugger + * + ******************************************************************************/ + +acpi_status acpi_initialize_debugger(void) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_initialize_debugger); + + /* Init globals */ + + acpi_gbl_db_buffer = NULL; + acpi_gbl_db_filename = NULL; + acpi_gbl_db_output_to_file = FALSE; + + acpi_gbl_db_debug_level = ACPI_LV_VERBOSITY2; + acpi_gbl_db_console_debug_level = ACPI_NORMAL_DEFAULT | ACPI_LV_TABLES; + acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT; + + acpi_gbl_db_opt_no_ini_methods = FALSE; + + acpi_gbl_db_buffer = acpi_os_allocate(ACPI_DEBUG_BUFFER_SIZE); + if (!acpi_gbl_db_buffer) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + memset(acpi_gbl_db_buffer, 0, ACPI_DEBUG_BUFFER_SIZE); + + /* Initial scope is the root */ + + acpi_gbl_db_scope_buf[0] = AML_ROOT_PREFIX; + acpi_gbl_db_scope_buf[1] = 0; + acpi_gbl_db_scope_node = acpi_gbl_root_node; + + /* Initialize user commands loop */ + + acpi_gbl_db_terminate_loop = FALSE; + + /* + * If configured for multi-thread support, the debug executor runs in + * a separate thread so that the front end can be in another address + * space, environment, or even another machine. + */ + if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) { + + /* These were created with one unit, grab it */ + + status = acpi_os_acquire_mutex(acpi_gbl_db_command_complete, + ACPI_WAIT_FOREVER); + if (ACPI_FAILURE(status)) { + acpi_os_printf("Could not get debugger mutex\n"); + return_ACPI_STATUS(status); + } + + status = acpi_os_acquire_mutex(acpi_gbl_db_command_ready, + ACPI_WAIT_FOREVER); + if (ACPI_FAILURE(status)) { + acpi_os_printf("Could not get debugger mutex\n"); + return_ACPI_STATUS(status); + } + + /* Create the debug execution thread to execute commands */ + + acpi_gbl_db_threads_terminated = FALSE; + status = acpi_os_execute(OSL_DEBUGGER_MAIN_THREAD, + acpi_db_execute_thread, NULL); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Could not start debugger thread")); + acpi_gbl_db_threads_terminated = TRUE; + return_ACPI_STATUS(status); + } + } else { + acpi_gbl_db_thread_id = acpi_os_get_thread_id(); + } + + return_ACPI_STATUS(AE_OK); +} + +ACPI_EXPORT_SYMBOL(acpi_initialize_debugger) + +/******************************************************************************* + * + * FUNCTION: acpi_terminate_debugger + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Stop debugger + * + ******************************************************************************/ +void acpi_terminate_debugger(void) +{ + + /* Terminate the AML Debugger */ + + acpi_gbl_db_terminate_loop = TRUE; + + if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) { + acpi_os_release_mutex(acpi_gbl_db_command_ready); + + /* Wait the AML Debugger threads */ + + while (!acpi_gbl_db_threads_terminated) { + acpi_os_sleep(100); + } + } + + if (acpi_gbl_db_buffer) { + acpi_os_free(acpi_gbl_db_buffer); + acpi_gbl_db_buffer = NULL; + } + + /* Ensure that debug output is now disabled */ + + acpi_gbl_db_output_flags = ACPI_DB_DISABLE_OUTPUT; +} + +ACPI_EXPORT_SYMBOL(acpi_terminate_debugger) + +/******************************************************************************* + * + * FUNCTION: acpi_set_debugger_thread_id + * + * PARAMETERS: thread_id - Debugger thread ID + * + * RETURN: None + * + * DESCRIPTION: Set debugger thread ID + * + ******************************************************************************/ +void acpi_set_debugger_thread_id(acpi_thread_id thread_id) +{ + acpi_gbl_db_thread_id = thread_id; +} + +ACPI_EXPORT_SYMBOL(acpi_set_debugger_thread_id) diff --git a/kernel/drivers/acpi/acpica/dsargs.c b/kernel/drivers/acpi/acpica/dsargs.c index 3e6989738..e2ab59e39 100644 --- a/kernel/drivers/acpi/acpica/dsargs.c +++ b/kernel/drivers/acpi/acpica/dsargs.c @@ -86,7 +86,7 @@ acpi_ds_execute_arguments(struct acpi_namespace_node *node, /* Allocate a new parser op to be the root of the parsed tree */ - op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP); + op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP, aml_start); if (!op) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -129,7 +129,7 @@ acpi_ds_execute_arguments(struct acpi_namespace_node *node, /* Evaluate the deferred arguments */ - op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP); + op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP, aml_start); if (!op) { return_ACPI_STATUS(AE_NO_MEMORY); } diff --git a/kernel/drivers/acpi/acpica/dscontrol.c b/kernel/drivers/acpi/acpica/dscontrol.c index 39da9da62..435fc16e2 100644 --- a/kernel/drivers/acpi/acpica/dscontrol.c +++ b/kernel/drivers/acpi/acpica/dscontrol.c @@ -212,7 +212,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, */ control_state->control.loop_count++; if (control_state->control.loop_count > - ACPI_MAX_LOOP_ITERATIONS) { + acpi_gbl_max_loop_iterations) { status = AE_AML_INFINITE_LOOP; break; } diff --git a/kernel/drivers/acpi/acpica/dsdebug.c b/kernel/drivers/acpi/acpica/dsdebug.c new file mode 100644 index 000000000..309556efc --- /dev/null +++ b/kernel/drivers/acpi/acpica/dsdebug.c @@ -0,0 +1,231 @@ +/****************************************************************************** + * + * Module Name: dsdebug - Parser/Interpreter interface - debugging + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2015, 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 +#include "accommon.h" +#include "acdispat.h" +#include "acnamesp.h" +#ifdef ACPI_DISASSEMBLER +#include "acdisasm.h" +#endif +#include "acinterp.h" + +#define _COMPONENT ACPI_DISPATCHER +ACPI_MODULE_NAME("dsdebug") + +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) +/* Local prototypes */ +static void +acpi_ds_print_node_pathname(struct acpi_namespace_node *node, + const char *message); + +/******************************************************************************* + * + * FUNCTION: acpi_ds_print_node_pathname + * + * PARAMETERS: node - Object + * message - Prefix message + * + * DESCRIPTION: Print an object's full namespace pathname + * Manages allocation/freeing of a pathname buffer + * + ******************************************************************************/ + +static void +acpi_ds_print_node_pathname(struct acpi_namespace_node *node, + const char *message) +{ + struct acpi_buffer buffer; + acpi_status status; + + ACPI_FUNCTION_TRACE(ds_print_node_pathname); + + if (!node) { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH, "[NULL NAME]")); + return_VOID; + } + + /* Convert handle to full pathname and print it (with supplied message) */ + + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + + status = acpi_ns_handle_to_pathname(node, &buffer, TRUE); + if (ACPI_SUCCESS(status)) { + if (message) { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH, "%s ", + message)); + } + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH, "[%s] (Node %p)", + (char *)buffer.pointer, node)); + ACPI_FREE(buffer.pointer); + } + + return_VOID; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ds_dump_method_stack + * + * PARAMETERS: status - Method execution status + * walk_state - Current state of the parse tree walk + * op - Executing parse op + * + * RETURN: None + * + * DESCRIPTION: Called when a method has been aborted because of an error. + * Dumps the method execution stack. + * + ******************************************************************************/ + +void +acpi_ds_dump_method_stack(acpi_status status, + struct acpi_walk_state *walk_state, + union acpi_parse_object *op) +{ + union acpi_parse_object *next; + struct acpi_thread_state *thread; + struct acpi_walk_state *next_walk_state; + struct acpi_namespace_node *previous_method = NULL; + union acpi_operand_object *method_desc; + + ACPI_FUNCTION_TRACE(ds_dump_method_stack); + + /* Ignore control codes, they are not errors */ + + if ((status & AE_CODE_MASK) == AE_CODE_CONTROL) { + return_VOID; + } + + /* We may be executing a deferred opcode */ + + if (walk_state->deferred_node) { + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "Executing subtree for Buffer/Package/Region\n")); + return_VOID; + } + + /* + * If there is no Thread, we are not actually executing a method. + * This can happen when the iASL compiler calls the interpreter + * to perform constant folding. + */ + thread = walk_state->thread; + if (!thread) { + return_VOID; + } + + /* Display exception and method name */ + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "\n**** Exception %s during execution of method ", + acpi_format_exception(status))); + acpi_ds_print_node_pathname(walk_state->method_node, NULL); + + /* Display stack of executing methods */ + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH, + "\n\nMethod Execution Stack:\n")); + next_walk_state = thread->walk_state_list; + + /* Walk list of linked walk states */ + + while (next_walk_state) { + method_desc = next_walk_state->method_desc; + if (method_desc) { + acpi_ex_stop_trace_method((struct acpi_namespace_node *) + method_desc->method.node, + method_desc, walk_state); + } + + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + " Method [%4.4s] executing: ", + acpi_ut_get_node_name(next_walk_state-> + method_node))); + + /* First method is the currently executing method */ + + if (next_walk_state == walk_state) { + if (op) { + + /* Display currently executing ASL statement */ + + next = op->common.next; + op->common.next = NULL; + +#ifdef ACPI_DISASSEMBLER + acpi_dm_disassemble(next_walk_state, op, + ACPI_UINT32_MAX); +#endif + op->common.next = next; + } + } else { + /* + * This method has called another method + * NOTE: the method call parse subtree is already deleted at this + * point, so we cannot disassemble the method invocation. + */ + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH, + "Call to method ")); + acpi_ds_print_node_pathname(previous_method, NULL); + } + + previous_method = next_walk_state->method_node; + next_walk_state = next_walk_state->next; + ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH, "\n")); + } + + return_VOID; +} + +#else +void +acpi_ds_dump_method_stack(acpi_status status, + struct acpi_walk_state *walk_state, + union acpi_parse_object *op) +{ + return; +} + +#endif diff --git a/kernel/drivers/acpi/acpica/dsfield.c b/kernel/drivers/acpi/acpica/dsfield.c index 43b40de90..20de14859 100644 --- a/kernel/drivers/acpi/acpica/dsfield.c +++ b/kernel/drivers/acpi/acpica/dsfield.c @@ -502,7 +502,7 @@ acpi_ds_create_field(union acpi_parse_object *op, } } - ACPI_MEMSET(&info, 0, sizeof(struct acpi_create_field_info)); + memset(&info, 0, sizeof(struct acpi_create_field_info)); /* Second arg is the field flags */ diff --git a/kernel/drivers/acpi/acpica/dsinit.c b/kernel/drivers/acpi/acpica/dsinit.c index bbe74bceb..920f1b199 100644 --- a/kernel/drivers/acpi/acpica/dsinit.c +++ b/kernel/drivers/acpi/acpica/dsinit.c @@ -207,7 +207,7 @@ acpi_ds_initialize_objects(u32 table_index, /* Set all init info to zero */ - ACPI_MEMSET(&info, 0, sizeof(struct acpi_init_walk_info)); + memset(&info, 0, sizeof(struct acpi_init_walk_info)); info.owner_id = owner_id; info.table_index = table_index; @@ -237,12 +237,22 @@ acpi_ds_initialize_objects(u32 table_index, return_ACPI_STATUS(status); } + /* DSDT is always the first AML table */ + + if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_DSDT)) { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, + "\nInitializing Namespace objects:\n")); + } + + /* Summary of objects initialized */ + ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, - "Table [%4.4s] (id %4.4X) - %4u Objects with %3u Devices, " - "%3u Regions, %3u Methods (%u/%u/%u Serial/Non/Cvt)\n", - table->signature, owner_id, info.object_count, - info.device_count, info.op_region_count, - info.method_count, info.serial_method_count, + "Table [%4.4s:%8.8s] (id %.2X) - %4u Objects with %3u Devices, " + "%3u Regions, %4u Methods (%u/%u/%u Serial/Non/Cvt)\n", + table->signature, table->oem_table_id, owner_id, + info.object_count, info.device_count, + info.op_region_count, info.method_count, + info.serial_method_count, info.non_serial_method_count, info.serialized_method_count)); diff --git a/kernel/drivers/acpi/acpica/dsmethod.c b/kernel/drivers/acpi/acpica/dsmethod.c index d72565a3c..bc32f3194 100644 --- a/kernel/drivers/acpi/acpica/dsmethod.c +++ b/kernel/drivers/acpi/acpica/dsmethod.c @@ -46,11 +46,9 @@ #include "acdispat.h" #include "acinterp.h" #include "acnamesp.h" -#ifdef ACPI_DISASSEMBLER -#include "acdisasm.h" -#endif #include "acparser.h" #include "amlcode.h" +#include "acdebug.h" #define _COMPONENT ACPI_DISPATCHER ACPI_MODULE_NAME("dsmethod") @@ -103,7 +101,7 @@ acpi_ds_auto_serialize_method(struct acpi_namespace_node *node, /* Create/Init a root op for the method parse tree */ - op = acpi_ps_alloc_op(AML_METHOD_OP); + op = acpi_ps_alloc_op(AML_METHOD_OP, obj_desc->method.aml_start); if (!op) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -116,6 +114,7 @@ acpi_ds_auto_serialize_method(struct acpi_namespace_node *node, walk_state = acpi_ds_create_walk_state(node->owner_id, NULL, NULL, NULL); if (!walk_state) { + acpi_ps_free_op(op); return_ACPI_STATUS(AE_NO_MEMORY); } @@ -125,6 +124,7 @@ acpi_ds_auto_serialize_method(struct acpi_namespace_node *node, obj_desc->method.aml_length, NULL, 0); if (ACPI_FAILURE(status)) { acpi_ds_delete_walk_state(walk_state); + acpi_ps_free_op(op); return_ACPI_STATUS(status); } @@ -133,9 +133,6 @@ acpi_ds_auto_serialize_method(struct acpi_namespace_node *node, /* Parse the method, scan for creation of named objects */ status = acpi_ps_parse_aml(walk_state); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } acpi_ps_delete_parse_tree(op); return_ACPI_STATUS(status); @@ -206,7 +203,7 @@ acpi_ds_detect_named_opcodes(struct acpi_walk_state *walk_state, * RETURN: Status * * DESCRIPTION: Called on method error. Invoke the global exception handler if - * present, dump the method data if the disassembler is configured + * present, dump the method data if the debugger is configured * * Note: Allows the exception handler to change the status code * @@ -215,6 +212,8 @@ acpi_ds_detect_named_opcodes(struct acpi_walk_state *walk_state, acpi_status acpi_ds_method_error(acpi_status status, struct acpi_walk_state * walk_state) { + u32 aml_offset; + ACPI_FUNCTION_ENTRY(); /* Ignore AE_OK and control exception codes */ @@ -235,26 +234,30 @@ acpi_ds_method_error(acpi_status status, struct acpi_walk_state * walk_state) * Handler can map the exception code to anything it wants, including * AE_OK, in which case the executing method will not be aborted. */ + aml_offset = (u32)ACPI_PTR_DIFF(walk_state->aml, + walk_state->parser_state. + aml_start); + status = acpi_gbl_exception_handler(status, walk_state->method_node ? walk_state->method_node-> name.integer : 0, walk_state->opcode, - walk_state->aml_offset, - NULL); + aml_offset, NULL); acpi_ex_enter_interpreter(); } acpi_ds_clear_implicit_return(walk_state); -#ifdef ACPI_DISASSEMBLER if (ACPI_FAILURE(status)) { + acpi_ds_dump_method_stack(status, walk_state, walk_state->op); - /* Display method locals/args if disassembler is present */ + /* Display method locals/args if debugger is present */ - acpi_dm_dump_method_info(status, walk_state, walk_state->op); - } +#ifdef ACPI_DEBUGGER + acpi_db_dump_method_info(status, walk_state); #endif + } return (status); } @@ -329,6 +332,8 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, return_ACPI_STATUS(AE_NULL_ENTRY); } + acpi_ex_start_trace_method(method_node, obj_desc, walk_state); + /* Prevent wraparound of thread count */ if (obj_desc->method.thread_count == ACPI_UINT8_MAX) { @@ -575,9 +580,7 @@ cleanup: /* On error, we must terminate the method properly */ acpi_ds_terminate_control_method(obj_desc, next_walk_state); - if (next_walk_state) { - acpi_ds_delete_walk_state(next_walk_state); - } + acpi_ds_delete_walk_state(next_walk_state); return_ACPI_STATUS(status); } @@ -827,5 +830,8 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, } } + acpi_ex_stop_trace_method((struct acpi_namespace_node *)method_desc-> + method.node, method_desc, walk_state); + return_VOID; } diff --git a/kernel/drivers/acpi/acpica/dsobject.c b/kernel/drivers/acpi/acpica/dsobject.c index 8a7b07b6a..2beb7fd67 100644 --- a/kernel/drivers/acpi/acpica/dsobject.c +++ b/kernel/drivers/acpi/acpica/dsobject.c @@ -339,8 +339,8 @@ acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state, /* Initialize buffer from the byte_list (if present) */ if (byte_list) { - ACPI_MEMCPY(obj_desc->buffer.pointer, - byte_list->named.data, byte_list_length); + memcpy(obj_desc->buffer.pointer, byte_list->named.data, + byte_list_length); } } @@ -750,8 +750,7 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, case ACPI_TYPE_STRING: obj_desc->string.pointer = op->common.value.string; - obj_desc->string.length = - (u32) ACPI_STRLEN(op->common.value.string); + obj_desc->string.length = (u32)strlen(op->common.value.string); /* * The string is contained in the ACPI table, don't ever try diff --git a/kernel/drivers/acpi/acpica/dsopcode.c b/kernel/drivers/acpi/acpica/dsopcode.c index ea0cc4e08..81d7b9863 100644 --- a/kernel/drivers/acpi/acpica/dsopcode.c +++ b/kernel/drivers/acpi/acpica/dsopcode.c @@ -480,8 +480,8 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, union acpi_operand_object **operand; struct acpi_namespace_node *node; union acpi_parse_object *next_op; - u32 table_index; struct acpi_table_header *table; + u32 table_index; ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op); @@ -504,6 +504,8 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, return_ACPI_STATUS(status); } + operand = &walk_state->operands[0]; + /* * Resolve the Signature string, oem_id string, * and oem_table_id string operands @@ -511,32 +513,34 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, status = acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS, walk_state); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + goto cleanup; } - operand = &walk_state->operands[0]; - /* Find the ACPI table */ status = acpi_tb_find_table(operand[0]->string.pointer, operand[1]->string.pointer, operand[2]->string.pointer, &table_index); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + if (status == AE_NOT_FOUND) { + ACPI_ERROR((AE_INFO, + "ACPI Table [%4.4s] OEM:(%s, %s) not found in RSDT/XSDT", + operand[0]->string.pointer, + operand[1]->string.pointer, + operand[2]->string.pointer)); + } + goto cleanup; } - acpi_ut_remove_reference(operand[0]); - acpi_ut_remove_reference(operand[1]); - acpi_ut_remove_reference(operand[2]); - status = acpi_get_table_by_index(table_index, &table); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + goto cleanup; } obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { - return_ACPI_STATUS(AE_NOT_EXIST); + status = AE_NOT_EXIST; + goto cleanup; } obj_desc->region.address = ACPI_PTR_TO_PHYSADDR(table); @@ -551,6 +555,11 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, obj_desc->region.flags |= AOPOBJ_DATA_VALID; +cleanup: + acpi_ut_remove_reference(operand[0]); + acpi_ut_remove_reference(operand[1]); + acpi_ut_remove_reference(operand[2]); + return_ACPI_STATUS(status); } diff --git a/kernel/drivers/acpi/acpica/dsutils.c b/kernel/drivers/acpi/acpica/dsutils.c index deeddd6d2..ebc577bae 100644 --- a/kernel/drivers/acpi/acpica/dsutils.c +++ b/kernel/drivers/acpi/acpica/dsutils.c @@ -572,8 +572,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, obj_desc = acpi_ut_create_string_object((acpi_size) name_length); - ACPI_STRNCPY(obj_desc->string.pointer, - name_string, name_length); + strncpy(obj_desc->string.pointer, + name_string, name_length); status = AE_OK; } else { /* diff --git a/kernel/drivers/acpi/acpica/dswload.c b/kernel/drivers/acpi/acpica/dswload.c index 843942fb4..097188a6b 100644 --- a/kernel/drivers/acpi/acpica/dswload.c +++ b/kernel/drivers/acpi/acpica/dswload.c @@ -315,10 +315,19 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, flags = ACPI_NS_NO_UPSEARCH; if ((walk_state->opcode != AML_SCOPE_OP) && (!(walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP))) { - flags |= ACPI_NS_ERROR_IF_FOUND; - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "[%s] Cannot already exist\n", - acpi_ut_get_type_name(object_type))); + if (walk_state->namespace_override) { + flags |= ACPI_NS_OVERRIDE_IF_FOUND; + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "[%s] Override allowed\n", + acpi_ut_get_type_name + (object_type))); + } else { + flags |= ACPI_NS_ERROR_IF_FOUND; + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "[%s] Cannot already exist\n", + acpi_ut_get_type_name + (object_type))); + } } else { ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[%s] Both Find or Create allowed\n", @@ -379,7 +388,7 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, /* Create a new op */ - op = acpi_ps_alloc_op(walk_state->opcode); + op = acpi_ps_alloc_op(walk_state->opcode, walk_state->aml); if (!op) { return_ACPI_STATUS(AE_NO_MEMORY); } diff --git a/kernel/drivers/acpi/acpica/dswload2.c b/kernel/drivers/acpi/acpica/dswload2.c index fcaa30c61..e2c08cd79 100644 --- a/kernel/drivers/acpi/acpica/dswload2.c +++ b/kernel/drivers/acpi/acpica/dswload2.c @@ -335,7 +335,7 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, /* Create a new op */ - op = acpi_ps_alloc_op(walk_state->opcode); + op = acpi_ps_alloc_op(walk_state->opcode, walk_state->aml); if (!op) { return_ACPI_STATUS(AE_NO_MEMORY); } diff --git a/kernel/drivers/acpi/acpica/evgpeinit.c b/kernel/drivers/acpi/acpica/evgpeinit.c index 8840296d5..ea4c0d3fc 100644 --- a/kernel/drivers/acpi/acpica/evgpeinit.c +++ b/kernel/drivers/acpi/acpica/evgpeinit.c @@ -377,7 +377,7 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle, /* 4) The last two characters of the name are the hex GPE Number */ - gpe_number = ACPI_STRTOUL(&name[2], NULL, 16); + gpe_number = strtoul(&name[2], NULL, 16); if (gpe_number == ACPI_UINT32_MAX) { /* Conversion failed; invalid method, just ignore it */ diff --git a/kernel/drivers/acpi/acpica/evregion.c b/kernel/drivers/acpi/acpica/evregion.c index 2ba28a63f..5ee79a16f 100644 --- a/kernel/drivers/acpi/acpica/evregion.c +++ b/kernel/drivers/acpi/acpica/evregion.c @@ -626,9 +626,17 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, acpi_adr_space_type space_id) { acpi_status status; + struct acpi_reg_walk_info info; ACPI_FUNCTION_TRACE(ev_execute_reg_methods); + info.space_id = space_id; + info.reg_run_count = 0; + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_NAMES, + " Running _REG methods for SpaceId %s\n", + acpi_ut_get_region_name(info.space_id))); + /* * Run all _REG methods for all Operation Regions for this space ID. This * is a separate walk in order to handle any interdependencies between @@ -637,7 +645,7 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, */ status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run, - NULL, &space_id, NULL); + NULL, &info, NULL); /* Special case for EC: handle "orphan" _REG methods with no region */ @@ -645,6 +653,11 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, acpi_ev_orphan_ec_reg_method(node); } + ACPI_DEBUG_PRINT_RAW((ACPI_DB_NAMES, + " Executed %u _REG methods for SpaceId %s\n", + info.reg_run_count, + acpi_ut_get_region_name(info.space_id))); + return_ACPI_STATUS(status); } @@ -664,10 +677,10 @@ acpi_ev_reg_run(acpi_handle obj_handle, { union acpi_operand_object *obj_desc; struct acpi_namespace_node *node; - acpi_adr_space_type space_id; acpi_status status; + struct acpi_reg_walk_info *info; - space_id = *ACPI_CAST_PTR(acpi_adr_space_type, context); + info = ACPI_CAST_PTR(struct acpi_reg_walk_info, context); /* Convert and validate the device handle */ @@ -696,13 +709,14 @@ acpi_ev_reg_run(acpi_handle obj_handle, /* Object is a Region */ - if (obj_desc->region.space_id != space_id) { + if (obj_desc->region.space_id != info->space_id) { /* This region is for a different address space, just ignore it */ return (AE_OK); } + info->reg_run_count++; status = acpi_ev_execute_reg_method(obj_desc, ACPI_REG_CONNECT); return (status); } diff --git a/kernel/drivers/acpi/acpica/evxface.c b/kernel/drivers/acpi/acpica/evxface.c index 81f2d9e87..07d22bfba 100644 --- a/kernel/drivers/acpi/acpica/evxface.c +++ b/kernel/drivers/acpi/acpica/evxface.c @@ -405,7 +405,7 @@ cleanup: } ACPI_EXPORT_SYMBOL(acpi_install_exception_handler) -#endif /* ACPI_FUTURE_USAGE */ +#endif #if (!ACPI_REDUCED_HARDWARE) /******************************************************************************* diff --git a/kernel/drivers/acpi/acpica/evxfevnt.c b/kernel/drivers/acpi/acpica/evxfevnt.c index faad911d4..10ce48e16 100644 --- a/kernel/drivers/acpi/acpica/evxfevnt.c +++ b/kernel/drivers/acpi/acpica/evxfevnt.c @@ -71,7 +71,7 @@ acpi_status acpi_enable(void) /* ACPI tables must be present */ - if (!acpi_tb_tables_loaded()) { + if (acpi_gbl_fadt_index == ACPI_INVALID_TABLE_INDEX) { return_ACPI_STATUS(AE_NO_ACPI_TABLES); } diff --git a/kernel/drivers/acpi/acpica/exconfig.c b/kernel/drivers/acpi/acpica/exconfig.c index 6e0df2b9d..b540913c1 100644 --- a/kernel/drivers/acpi/acpica/exconfig.c +++ b/kernel/drivers/acpi/acpica/exconfig.c @@ -162,14 +162,6 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, ACPI_FUNCTION_TRACE(ex_load_table_op); - /* Validate lengths for the Signature, oem_id, and oem_table_id strings */ - - if ((operand[0]->string.length > ACPI_NAME_SIZE) || - (operand[1]->string.length > ACPI_OEM_ID_SIZE) || - (operand[2]->string.length > ACPI_OEM_TABLE_ID_SIZE)) { - return_ACPI_STATUS(AE_AML_STRING_LIMIT); - } - /* Find the ACPI table in the RSDT/XSDT */ status = acpi_tb_find_table(operand[0]->string.pointer, @@ -470,7 +462,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_NO_MEMORY); } - ACPI_MEMCPY(table, table_header, length); + memcpy(table, table_header, length); break; default: diff --git a/kernel/drivers/acpi/acpica/exconvrt.c b/kernel/drivers/acpi/acpica/exconvrt.c index 89a976b4c..1e4c5b6dc 100644 --- a/kernel/drivers/acpi/acpica/exconvrt.c +++ b/kernel/drivers/acpi/acpica/exconvrt.c @@ -227,9 +227,8 @@ acpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc, /* Copy the integer to the buffer, LSB first */ new_buf = return_desc->buffer.pointer; - ACPI_MEMCPY(new_buf, - &obj_desc->integer.value, - acpi_gbl_integer_byte_width); + memcpy(new_buf, + &obj_desc->integer.value, acpi_gbl_integer_byte_width); break; case ACPI_TYPE_STRING: @@ -252,8 +251,8 @@ acpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc, /* Copy the string to the buffer */ new_buf = return_desc->buffer.pointer; - ACPI_STRNCPY((char *)new_buf, (char *)obj_desc->string.pointer, - obj_desc->string.length); + strncpy((char *)new_buf, (char *)obj_desc->string.pointer, + obj_desc->string.length); break; default: @@ -619,6 +618,7 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type, break; case ARGI_TARGETREF: + case ARGI_STORE_TARGET: switch (destination_type) { case ACPI_TYPE_INTEGER: diff --git a/kernel/drivers/acpi/acpica/excreate.c b/kernel/drivers/acpi/acpica/excreate.c index aaeea4840..ccb7219bd 100644 --- a/kernel/drivers/acpi/acpica/excreate.c +++ b/kernel/drivers/acpi/acpica/excreate.c @@ -486,6 +486,7 @@ acpi_ex_create_method(u8 * aml_start, obj_desc->method.aml_start = aml_start; obj_desc->method.aml_length = aml_length; + obj_desc->method.node = operand[0]; /* * Disassemble the method flags. Split off the arg_count, Serialized diff --git a/kernel/drivers/acpi/acpica/exdebug.c b/kernel/drivers/acpi/acpica/exdebug.c index e67d0aca3..de9245823 100644 --- a/kernel/drivers/acpi/acpica/exdebug.c +++ b/kernel/drivers/acpi/acpica/exdebug.c @@ -43,11 +43,21 @@ #include #include "accommon.h" +#include "acnamesp.h" #include "acinterp.h" +#include "acparser.h" #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exdebug") +static union acpi_operand_object *acpi_gbl_trace_method_object = NULL; + +/* Local prototypes */ + +#ifdef ACPI_DEBUG_OUTPUT +static const char *acpi_ex_get_trace_event_name(acpi_trace_event_type type); +#endif + #ifndef ACPI_NO_ERROR_MESSAGES /******************************************************************************* * @@ -70,12 +80,15 @@ ACPI_MODULE_NAME("exdebug") * enabled if necessary. * ******************************************************************************/ + void acpi_ex_do_debug_object(union acpi_operand_object *source_desc, u32 level, u32 index) { u32 i; u32 timer; + union acpi_operand_object *object_desc; + u32 value; ACPI_FUNCTION_TRACE_PTR(ex_do_debug_object, source_desc); @@ -254,8 +267,44 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, object)->object, level + 4, 0); } else { - acpi_ex_do_debug_object(source_desc->reference. - object, level + 4, 0); + object_desc = source_desc->reference.object; + value = source_desc->reference.value; + + switch (object_desc->common.type) { + case ACPI_TYPE_BUFFER: + + acpi_os_printf("Buffer[%u] = 0x%2.2X\n", + value, + *source_desc->reference. + index_pointer); + break; + + case ACPI_TYPE_STRING: + + acpi_os_printf + ("String[%u] = \"%c\" (0x%2.2X)\n", + value, + *source_desc->reference. + index_pointer, + *source_desc->reference. + index_pointer); + break; + + case ACPI_TYPE_PACKAGE: + + acpi_os_printf("Package[%u] = ", value); + acpi_ex_do_debug_object(*source_desc-> + reference.where, + level + 4, 0); + break; + + default: + + acpi_os_printf + ("Unknown Reference object type %X\n", + object_desc->common.type); + break; + } } } break; @@ -270,3 +319,316 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, return_VOID; } #endif + +/******************************************************************************* + * + * FUNCTION: acpi_ex_interpreter_trace_enabled + * + * PARAMETERS: name - Whether method name should be matched, + * this should be checked before starting + * the tracer + * + * RETURN: TRUE if interpreter trace is enabled. + * + * DESCRIPTION: Check whether interpreter trace is enabled + * + ******************************************************************************/ + +static u8 acpi_ex_interpreter_trace_enabled(char *name) +{ + + /* Check if tracing is enabled */ + + if (!(acpi_gbl_trace_flags & ACPI_TRACE_ENABLED)) { + return (FALSE); + } + + /* + * Check if tracing is filtered: + * + * 1. If the tracer is started, acpi_gbl_trace_method_object should have + * been filled by the trace starter + * 2. If the tracer is not started, acpi_gbl_trace_method_name should be + * matched if it is specified + * 3. If the tracer is oneshot style, acpi_gbl_trace_method_name should + * not be cleared by the trace stopper during the first match + */ + if (acpi_gbl_trace_method_object) { + return (TRUE); + } + if (name && + (acpi_gbl_trace_method_name && + strcmp(acpi_gbl_trace_method_name, name))) { + return (FALSE); + } + if ((acpi_gbl_trace_flags & ACPI_TRACE_ONESHOT) && + !acpi_gbl_trace_method_name) { + return (FALSE); + } + + return (TRUE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_get_trace_event_name + * + * PARAMETERS: type - Trace event type + * + * RETURN: Trace event name. + * + * DESCRIPTION: Used to obtain the full trace event name. + * + ******************************************************************************/ + +#ifdef ACPI_DEBUG_OUTPUT + +static const char *acpi_ex_get_trace_event_name(acpi_trace_event_type type) +{ + switch (type) { + case ACPI_TRACE_AML_METHOD: + + return "Method"; + + case ACPI_TRACE_AML_OPCODE: + + return "Opcode"; + + case ACPI_TRACE_AML_REGION: + + return "Region"; + + default: + + return ""; + } +} + +#endif + +/******************************************************************************* + * + * FUNCTION: acpi_ex_trace_point + * + * PARAMETERS: type - Trace event type + * begin - TRUE if before execution + * aml - Executed AML address + * pathname - Object path + * + * RETURN: None + * + * DESCRIPTION: Internal interpreter execution trace. + * + ******************************************************************************/ + +void +acpi_ex_trace_point(acpi_trace_event_type type, + u8 begin, u8 *aml, char *pathname) +{ + + ACPI_FUNCTION_NAME(ex_trace_point); + + if (pathname) { + ACPI_DEBUG_PRINT((ACPI_DB_TRACE_POINT, + "%s %s [0x%p:%s] execution.\n", + acpi_ex_get_trace_event_name(type), + begin ? "Begin" : "End", aml, pathname)); + } else { + ACPI_DEBUG_PRINT((ACPI_DB_TRACE_POINT, + "%s %s [0x%p] execution.\n", + acpi_ex_get_trace_event_name(type), + begin ? "Begin" : "End", aml)); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_start_trace_method + * + * PARAMETERS: method_node - Node of the method + * obj_desc - The method object + * walk_state - current state, NULL if not yet executing + * a method. + * + * RETURN: None + * + * DESCRIPTION: Start control method execution trace + * + ******************************************************************************/ + +void +acpi_ex_start_trace_method(struct acpi_namespace_node *method_node, + union acpi_operand_object *obj_desc, + struct acpi_walk_state *walk_state) +{ + acpi_status status; + char *pathname = NULL; + u8 enabled = FALSE; + + ACPI_FUNCTION_NAME(ex_start_trace_method); + + if (method_node) { + pathname = acpi_ns_get_normalized_pathname(method_node, TRUE); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + goto exit; + } + + enabled = acpi_ex_interpreter_trace_enabled(pathname); + if (enabled && !acpi_gbl_trace_method_object) { + acpi_gbl_trace_method_object = obj_desc; + acpi_gbl_original_dbg_level = acpi_dbg_level; + acpi_gbl_original_dbg_layer = acpi_dbg_layer; + acpi_dbg_level = ACPI_TRACE_LEVEL_ALL; + acpi_dbg_layer = ACPI_TRACE_LAYER_ALL; + + if (acpi_gbl_trace_dbg_level) { + acpi_dbg_level = acpi_gbl_trace_dbg_level; + } + if (acpi_gbl_trace_dbg_layer) { + acpi_dbg_layer = acpi_gbl_trace_dbg_layer; + } + } + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + +exit: + if (enabled) { + ACPI_TRACE_POINT(ACPI_TRACE_AML_METHOD, TRUE, + obj_desc ? obj_desc->method.aml_start : NULL, + pathname); + } + if (pathname) { + ACPI_FREE(pathname); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_stop_trace_method + * + * PARAMETERS: method_node - Node of the method + * obj_desc - The method object + * walk_state - current state, NULL if not yet executing + * a method. + * + * RETURN: None + * + * DESCRIPTION: Stop control method execution trace + * + ******************************************************************************/ + +void +acpi_ex_stop_trace_method(struct acpi_namespace_node *method_node, + union acpi_operand_object *obj_desc, + struct acpi_walk_state *walk_state) +{ + acpi_status status; + char *pathname = NULL; + u8 enabled; + + ACPI_FUNCTION_NAME(ex_stop_trace_method); + + if (method_node) { + pathname = acpi_ns_get_normalized_pathname(method_node, TRUE); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + goto exit_path; + } + + enabled = acpi_ex_interpreter_trace_enabled(NULL); + + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + + if (enabled) { + ACPI_TRACE_POINT(ACPI_TRACE_AML_METHOD, FALSE, + obj_desc ? obj_desc->method.aml_start : NULL, + pathname); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + goto exit_path; + } + + /* Check whether the tracer should be stopped */ + + if (acpi_gbl_trace_method_object == obj_desc) { + + /* Disable further tracing if type is one-shot */ + + if (acpi_gbl_trace_flags & ACPI_TRACE_ONESHOT) { + acpi_gbl_trace_method_name = NULL; + } + + acpi_dbg_level = acpi_gbl_original_dbg_level; + acpi_dbg_layer = acpi_gbl_original_dbg_layer; + acpi_gbl_trace_method_object = NULL; + } + + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + +exit_path: + if (pathname) { + ACPI_FREE(pathname); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_start_trace_opcode + * + * PARAMETERS: op - The parser opcode object + * walk_state - current state, NULL if not yet executing + * a method. + * + * RETURN: None + * + * DESCRIPTION: Start opcode execution trace + * + ******************************************************************************/ + +void +acpi_ex_start_trace_opcode(union acpi_parse_object *op, + struct acpi_walk_state *walk_state) +{ + + ACPI_FUNCTION_NAME(ex_start_trace_opcode); + + if (acpi_ex_interpreter_trace_enabled(NULL) && + (acpi_gbl_trace_flags & ACPI_TRACE_OPCODE)) { + ACPI_TRACE_POINT(ACPI_TRACE_AML_OPCODE, TRUE, + op->common.aml, op->common.aml_op_name); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ex_stop_trace_opcode + * + * PARAMETERS: op - The parser opcode object + * walk_state - current state, NULL if not yet executing + * a method. + * + * RETURN: None + * + * DESCRIPTION: Stop opcode execution trace + * + ******************************************************************************/ + +void +acpi_ex_stop_trace_opcode(union acpi_parse_object *op, + struct acpi_walk_state *walk_state) +{ + + ACPI_FUNCTION_NAME(ex_stop_trace_opcode); + + if (acpi_ex_interpreter_trace_enabled(NULL) && + (acpi_gbl_trace_flags & ACPI_TRACE_OPCODE)) { + ACPI_TRACE_POINT(ACPI_TRACE_AML_OPCODE, FALSE, + op->common.aml, op->common.aml_op_name); + } +} diff --git a/kernel/drivers/acpi/acpica/exdump.c b/kernel/drivers/acpi/acpica/exdump.c index 1da52bef6..d836f888b 100644 --- a/kernel/drivers/acpi/acpica/exdump.c +++ b/kernel/drivers/acpi/acpica/exdump.c @@ -224,7 +224,7 @@ static struct acpi_exdump_info acpi_ex_dump_index_field[5] = { {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(index_field.data_obj), "Data Object"} }; -static struct acpi_exdump_info acpi_ex_dump_reference[8] = { +static struct acpi_exdump_info acpi_ex_dump_reference[9] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_reference), NULL}, {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(reference.class), "Class"}, {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(reference.target_type), "Target Type"}, @@ -232,6 +232,8 @@ static struct acpi_exdump_info acpi_ex_dump_reference[8] = { {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.object), "Object Desc"}, {ACPI_EXD_NODE, ACPI_EXD_OFFSET(reference.node), "Node"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.where), "Where"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(reference.index_pointer), + "Index Pointer"}, {ACPI_EXD_REFERENCE, 0, NULL} }; @@ -993,9 +995,8 @@ static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc) if (obj_desc->reference.class == ACPI_REFCLASS_NAME) { acpi_os_printf(" %p ", obj_desc->reference.node); - status = - acpi_ns_handle_to_pathname(obj_desc->reference.node, - &ret_buf); + status = acpi_ns_handle_to_pathname(obj_desc->reference.node, + &ret_buf, TRUE); if (ACPI_FAILURE(status)) { acpi_os_printf(" Could not convert name to pathname\n"); } else { @@ -1005,14 +1006,13 @@ static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc) } else if (obj_desc->reference.object) { if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_OPERAND) { - acpi_os_printf(" Target: %p", + acpi_os_printf("%22s %p", "Target :", obj_desc->reference.object); if (obj_desc->reference.class == ACPI_REFCLASS_TABLE) { acpi_os_printf(" Table Index: %X\n", obj_desc->reference.value); } else { - acpi_os_printf(" Target: %p [%s]\n", - obj_desc->reference.object, + acpi_os_printf(" [%s]\n", acpi_ut_get_type_name(((union acpi_operand_object *) diff --git a/kernel/drivers/acpi/acpica/exfield.c b/kernel/drivers/acpi/acpica/exfield.c index c161dd974..61fd9c7b8 100644 --- a/kernel/drivers/acpi/acpica/exfield.c +++ b/kernel/drivers/acpi/acpica/exfield.c @@ -428,7 +428,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, } buffer = buffer_desc->buffer.pointer; - ACPI_MEMCPY(buffer, source_desc->buffer.pointer, length); + memcpy(buffer, source_desc->buffer.pointer, length); /* Lock entire transaction if requested */ diff --git a/kernel/drivers/acpi/acpica/exfldio.c b/kernel/drivers/acpi/acpica/exfldio.c index 725a3746a..70b7bbbb8 100644 --- a/kernel/drivers/acpi/acpica/exfldio.c +++ b/kernel/drivers/acpi/acpica/exfldio.c @@ -416,22 +416,22 @@ acpi_ex_field_datum_io(union acpi_operand_object *obj_desc, * Copy the data from the source buffer. * Length is the field width in bytes. */ - ACPI_MEMCPY(value, - (obj_desc->buffer_field.buffer_obj)->buffer. - pointer + - obj_desc->buffer_field.base_byte_offset + - field_datum_byte_offset, - obj_desc->common_field.access_byte_width); + memcpy(value, + (obj_desc->buffer_field.buffer_obj)->buffer. + pointer + + obj_desc->buffer_field.base_byte_offset + + field_datum_byte_offset, + obj_desc->common_field.access_byte_width); } else { /* * Copy the data to the target buffer. * Length is the field width in bytes. */ - ACPI_MEMCPY((obj_desc->buffer_field.buffer_obj)->buffer. - pointer + - obj_desc->buffer_field.base_byte_offset + - field_datum_byte_offset, value, - obj_desc->common_field.access_byte_width); + memcpy((obj_desc->buffer_field.buffer_obj)->buffer. + pointer + + obj_desc->buffer_field.base_byte_offset + + field_datum_byte_offset, value, + obj_desc->common_field.access_byte_width); } status = AE_OK; @@ -703,7 +703,7 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_BUFFER_OVERFLOW); } - ACPI_MEMSET(buffer, 0, buffer_length); + memset(buffer, 0, buffer_length); access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width); /* Handle the simple case here */ @@ -720,7 +720,7 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc, status = acpi_ex_field_datum_io(obj_desc, 0, &raw_datum, ACPI_READ); - ACPI_MEMCPY(buffer, &raw_datum, buffer_length); + memcpy(buffer, &raw_datum, buffer_length); } return_ACPI_STATUS(status); @@ -793,9 +793,9 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc, /* Write merged datum to target buffer */ - ACPI_MEMCPY(((char *)buffer) + buffer_offset, &merged_datum, - ACPI_MIN(obj_desc->common_field.access_byte_width, - buffer_length - buffer_offset)); + memcpy(((char *)buffer) + buffer_offset, &merged_datum, + ACPI_MIN(obj_desc->common_field.access_byte_width, + buffer_length - buffer_offset)); buffer_offset += obj_desc->common_field.access_byte_width; merged_datum = @@ -811,9 +811,9 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc, /* Write the last datum to the buffer */ - ACPI_MEMCPY(((char *)buffer) + buffer_offset, &merged_datum, - ACPI_MIN(obj_desc->common_field.access_byte_width, - buffer_length - buffer_offset)); + memcpy(((char *)buffer) + buffer_offset, &merged_datum, + ACPI_MIN(obj_desc->common_field.access_byte_width, + buffer_length - buffer_offset)); return_ACPI_STATUS(AE_OK); } @@ -878,7 +878,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, * at Byte zero. All unused (upper) bytes of the * buffer will be 0. */ - ACPI_MEMCPY((char *)new_buffer, (char *)buffer, buffer_length); + memcpy((char *)new_buffer, (char *)buffer, buffer_length); buffer = new_buffer; buffer_length = required_length; } @@ -918,9 +918,9 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, /* Get initial Datum from the input buffer */ - ACPI_MEMCPY(&raw_datum, buffer, - ACPI_MIN(obj_desc->common_field.access_byte_width, - buffer_length - buffer_offset)); + memcpy(&raw_datum, buffer, + ACPI_MIN(obj_desc->common_field.access_byte_width, + buffer_length - buffer_offset)); merged_datum = raw_datum << obj_desc->common_field.start_field_bit_offset; @@ -970,9 +970,9 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, /* Get the next input datum from the buffer */ buffer_offset += obj_desc->common_field.access_byte_width; - ACPI_MEMCPY(&raw_datum, ((char *)buffer) + buffer_offset, - ACPI_MIN(obj_desc->common_field.access_byte_width, - buffer_length - buffer_offset)); + memcpy(&raw_datum, ((char *)buffer) + buffer_offset, + ACPI_MIN(obj_desc->common_field.access_byte_width, + buffer_length - buffer_offset)); merged_datum |= raw_datum << obj_desc->common_field.start_field_bit_offset; diff --git a/kernel/drivers/acpi/acpica/exmisc.c b/kernel/drivers/acpi/acpica/exmisc.c index b56fc9d6f..d02afece0 100644 --- a/kernel/drivers/acpi/acpica/exmisc.c +++ b/kernel/drivers/acpi/acpica/exmisc.c @@ -209,8 +209,8 @@ acpi_ex_concat_template(union acpi_operand_object *operand0, * end_tag descriptor is copied from Operand1. */ new_buf = return_desc->buffer.pointer; - ACPI_MEMCPY(new_buf, operand0->buffer.pointer, length0); - ACPI_MEMCPY(new_buf + length0, operand1->buffer.pointer, length1); + memcpy(new_buf, operand0->buffer.pointer, length0); + memcpy(new_buf + length0, operand1->buffer.pointer, length1); /* Insert end_tag and set the checksum to zero, means "ignore checksum" */ @@ -318,14 +318,14 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, /* Copy the first integer, LSB first */ - ACPI_MEMCPY(new_buf, &operand0->integer.value, - acpi_gbl_integer_byte_width); + memcpy(new_buf, &operand0->integer.value, + acpi_gbl_integer_byte_width); /* Copy the second integer (LSB first) after the first */ - ACPI_MEMCPY(new_buf + acpi_gbl_integer_byte_width, - &local_operand1->integer.value, - acpi_gbl_integer_byte_width); + memcpy(new_buf + acpi_gbl_integer_byte_width, + &local_operand1->integer.value, + acpi_gbl_integer_byte_width); break; case ACPI_TYPE_STRING: @@ -346,9 +346,9 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, /* Concatenate the strings */ - ACPI_STRCPY(new_buf, operand0->string.pointer); - ACPI_STRCPY(new_buf + operand0->string.length, - local_operand1->string.pointer); + strcpy(new_buf, operand0->string.pointer); + strcpy(new_buf + operand0->string.length, + local_operand1->string.pointer); break; case ACPI_TYPE_BUFFER: @@ -369,11 +369,11 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, /* Concatenate the buffers */ - ACPI_MEMCPY(new_buf, operand0->buffer.pointer, - operand0->buffer.length); - ACPI_MEMCPY(new_buf + operand0->buffer.length, - local_operand1->buffer.pointer, - local_operand1->buffer.length); + memcpy(new_buf, operand0->buffer.pointer, + operand0->buffer.length); + memcpy(new_buf + operand0->buffer.length, + local_operand1->buffer.pointer, + local_operand1->buffer.length); break; default: @@ -660,9 +660,9 @@ acpi_ex_do_logical_op(u16 opcode, /* Lexicographic compare: compare the data bytes */ - compare = ACPI_MEMCMP(operand0->buffer.pointer, - local_operand1->buffer.pointer, - (length0 > length1) ? length1 : length0); + compare = memcmp(operand0->buffer.pointer, + local_operand1->buffer.pointer, + (length0 > length1) ? length1 : length0); switch (opcode) { case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */ diff --git a/kernel/drivers/acpi/acpica/exnames.c b/kernel/drivers/acpi/acpica/exnames.c index 453b00c30..20e87813c 100644 --- a/kernel/drivers/acpi/acpica/exnames.c +++ b/kernel/drivers/acpi/acpica/exnames.c @@ -192,7 +192,7 @@ static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string) char_buf[4] = '\0'; if (name_string) { - ACPI_STRCAT(name_string, char_buf); + strcat(name_string, char_buf); ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Appended to - %s\n", name_string)); } else { diff --git a/kernel/drivers/acpi/acpica/exoparg2.c b/kernel/drivers/acpi/acpica/exoparg2.c index fcc618aa2..b8944ebb1 100644 --- a/kernel/drivers/acpi/acpica/exoparg2.c +++ b/kernel/drivers/acpi/acpica/exoparg2.c @@ -337,8 +337,8 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) * Copy the raw buffer data with no transform. * (NULL terminated already) */ - ACPI_MEMCPY(return_desc->string.pointer, - operand[0]->buffer.pointer, length); + memcpy(return_desc->string.pointer, + operand[0]->buffer.pointer, length); break; case AML_CONCAT_RES_OP: @@ -380,6 +380,8 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) return_desc->reference.target_type = ACPI_TYPE_BUFFER_FIELD; + return_desc->reference.index_pointer = + &(operand[0]->buffer.pointer[index]); break; case ACPI_TYPE_BUFFER: @@ -391,6 +393,8 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) return_desc->reference.target_type = ACPI_TYPE_BUFFER_FIELD; + return_desc->reference.index_pointer = + &(operand[0]->buffer.pointer[index]); break; case ACPI_TYPE_PACKAGE: diff --git a/kernel/drivers/acpi/acpica/exoparg3.c b/kernel/drivers/acpi/acpica/exoparg3.c index 1c64a988c..fa100b3b9 100644 --- a/kernel/drivers/acpi/acpica/exoparg3.c +++ b/kernel/drivers/acpi/acpica/exoparg3.c @@ -237,8 +237,8 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state) /* We have a buffer, copy the portion requested */ - ACPI_MEMCPY(buffer, operand[0]->string.pointer + index, - length); + memcpy(buffer, operand[0]->string.pointer + index, + length); } /* Set the length of the new String/Buffer */ diff --git a/kernel/drivers/acpi/acpica/exregion.c b/kernel/drivers/acpi/acpica/exregion.c index f6c2f5499..b4a5e44c0 100644 --- a/kernel/drivers/acpi/acpica/exregion.c +++ b/kernel/drivers/acpi/acpica/exregion.c @@ -517,15 +517,14 @@ acpi_ex_data_table_space_handler(u32 function, switch (function) { case ACPI_READ: - ACPI_MEMCPY(ACPI_CAST_PTR(char, value), - ACPI_PHYSADDR_TO_PTR(address), - ACPI_DIV_8(bit_width)); + memcpy(ACPI_CAST_PTR(char, value), + ACPI_PHYSADDR_TO_PTR(address), ACPI_DIV_8(bit_width)); break; case ACPI_WRITE: - ACPI_MEMCPY(ACPI_PHYSADDR_TO_PTR(address), - ACPI_CAST_PTR(char, value), ACPI_DIV_8(bit_width)); + memcpy(ACPI_PHYSADDR_TO_PTR(address), + ACPI_CAST_PTR(char, value), ACPI_DIV_8(bit_width)); break; default: diff --git a/kernel/drivers/acpi/acpica/exresnte.c b/kernel/drivers/acpi/acpica/exresnte.c index c7e3b929a..1b372ef69 100644 --- a/kernel/drivers/acpi/acpica/exresnte.c +++ b/kernel/drivers/acpi/acpica/exresnte.c @@ -126,7 +126,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, if (!source_desc) { ACPI_ERROR((AE_INFO, "No object attached to node [%4.4s] %p", node->name.ascii, node)); - return_ACPI_STATUS(AE_AML_NO_OPERAND); + return_ACPI_STATUS(AE_AML_UNINITIALIZED_NODE); } /* diff --git a/kernel/drivers/acpi/acpica/exresolv.c b/kernel/drivers/acpi/acpica/exresolv.c index b6b7f3af2..a1afe1a1e 100644 --- a/kernel/drivers/acpi/acpica/exresolv.c +++ b/kernel/drivers/acpi/acpica/exresolv.c @@ -209,7 +209,6 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, * (i.e., dereference the package index) * Delete the ref object, increment the returned object */ - acpi_ut_remove_reference(stack_desc); acpi_ut_add_reference(obj_desc); *stack_ptr = obj_desc; } else { @@ -337,8 +336,9 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, acpi_object_type * return_type, union acpi_operand_object **return_desc) { - union acpi_operand_object *obj_desc = (void *)operand; - struct acpi_namespace_node *node; + union acpi_operand_object *obj_desc = ACPI_CAST_PTR(void, operand); + struct acpi_namespace_node *node = + ACPI_CAST_PTR(struct acpi_namespace_node, operand); acpi_object_type type; acpi_status status; @@ -355,9 +355,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, case ACPI_DESC_TYPE_NAMED: type = ((struct acpi_namespace_node *)obj_desc)->type; - obj_desc = - acpi_ns_get_attached_object((struct acpi_namespace_node *) - obj_desc); + obj_desc = acpi_ns_get_attached_object(node); /* If we had an Alias node, use the attached object for type info */ @@ -368,6 +366,13 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, acpi_namespace_node *) obj_desc); } + + if (!obj_desc) { + ACPI_ERROR((AE_INFO, + "[%4.4s] Node is unresolved or uninitialized", + acpi_ut_get_node_name(node))); + return_ACPI_STATUS(AE_AML_UNINITIALIZED_NODE); + } break; default: diff --git a/kernel/drivers/acpi/acpica/exresop.c b/kernel/drivers/acpi/acpica/exresop.c index d2964af9a..424442d50 100644 --- a/kernel/drivers/acpi/acpica/exresop.c +++ b/kernel/drivers/acpi/acpica/exresop.c @@ -307,6 +307,8 @@ acpi_ex_resolve_operands(u16 opcode, case ARGI_TARGETREF: /* Allows implicit conversion rules before store */ case ARGI_FIXED_TARGET: /* No implicit conversion before store to target */ case ARGI_SIMPLE_TARGET: /* Name, Local, or arg - no implicit conversion */ + case ARGI_STORE_TARGET: + /* * Need an operand of type ACPI_TYPE_LOCAL_REFERENCE * A Namespace Node is OK as-is diff --git a/kernel/drivers/acpi/acpica/exstore.c b/kernel/drivers/acpi/acpica/exstore.c index a7eee2400..c076e9100 100644 --- a/kernel/drivers/acpi/acpica/exstore.c +++ b/kernel/drivers/acpi/acpica/exstore.c @@ -137,7 +137,7 @@ acpi_ex_store(union acpi_operand_object *source_desc, /* Destination is not a Reference object */ ACPI_ERROR((AE_INFO, - "Target is not a Reference or Constant object - %s [%p]", + "Target is not a Reference or Constant object - [%s] %p", acpi_ut_get_object_type_name(dest_desc), dest_desc)); @@ -189,7 +189,7 @@ acpi_ex_store(union acpi_operand_object *source_desc, * displayed and otherwise has no effect -- see ACPI Specification */ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "**** Write to Debug Object: Object %p %s ****:\n\n", + "**** Write to Debug Object: Object %p [%s] ****:\n\n", source_desc, acpi_ut_get_object_type_name(source_desc))); @@ -341,7 +341,7 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, /* All other types are invalid */ ACPI_ERROR((AE_INFO, - "Source must be Integer/Buffer/String type, not %s", + "Source must be type [Integer/Buffer/String], found [%s]", acpi_ut_get_object_type_name(source_desc))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -352,8 +352,9 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, break; default: - ACPI_ERROR((AE_INFO, "Target is not a Package or BufferField")); - status = AE_AML_OPERAND_TYPE; + ACPI_ERROR((AE_INFO, + "Target is not of type [Package/BufferField]")); + status = AE_AML_TARGET_TYPE; break; } @@ -373,20 +374,20 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, * * DESCRIPTION: Store the object to the named object. * - * The Assignment of an object to a named object is handled here - * The value passed in will replace the current value (if any) - * with the input value. + * The assignment of an object to a named object is handled here. + * The value passed in will replace the current value (if any) + * with the input value. * - * When storing into an object the data is converted to the - * target object type then stored in the object. This means - * that the target object type (for an initialized target) will - * not be changed by a store operation. A copy_object can change - * the target type, however. + * When storing into an object the data is converted to the + * target object type then stored in the object. This means + * that the target object type (for an initialized target) will + * not be changed by a store operation. A copy_object can change + * the target type, however. * - * The implicit_conversion flag is set to NO/FALSE only when - * storing to an arg_x -- as per the rules of the ACPI spec. + * The implicit_conversion flag is set to NO/FALSE only when + * storing to an arg_x -- as per the rules of the ACPI spec. * - * Assumes parameters are already validated. + * Assumes parameters are already validated. * ******************************************************************************/ @@ -408,11 +409,75 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, target_type = acpi_ns_get_type(node); target_desc = acpi_ns_get_attached_object(node); - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %p (%s) to node %p (%s)\n", + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %p [%s] to node %p [%s]\n", source_desc, acpi_ut_get_object_type_name(source_desc), node, acpi_ut_get_type_name(target_type))); + /* Only limited target types possible for everything except copy_object */ + + if (walk_state->opcode != AML_COPY_OP) { + /* + * Only copy_object allows all object types to be overwritten. For + * target_ref(s), there are restrictions on the object types that + * are allowed. + * + * Allowable operations/typing for Store: + * + * 1) Simple Store + * Integer --> Integer (Named/Local/Arg) + * String --> String (Named/Local/Arg) + * Buffer --> Buffer (Named/Local/Arg) + * Package --> Package (Named/Local/Arg) + * + * 2) Store with implicit conversion + * Integer --> String or Buffer (Named) + * String --> Integer or Buffer (Named) + * Buffer --> Integer or String (Named) + */ + switch (target_type) { + case ACPI_TYPE_PACKAGE: + /* + * Here, can only store a package to an existing package. + * Storing a package to a Local/Arg is OK, and handled + * elsewhere. + */ + if (walk_state->opcode == AML_STORE_OP) { + if (source_desc->common.type != + ACPI_TYPE_PACKAGE) { + ACPI_ERROR((AE_INFO, + "Cannot assign type [%s] to [Package] " + "(source must be type Pkg)", + acpi_ut_get_object_type_name + (source_desc))); + + return_ACPI_STATUS(AE_AML_TARGET_TYPE); + } + break; + } + + /* Fallthrough */ + + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_EVENT: + case ACPI_TYPE_MUTEX: + case ACPI_TYPE_REGION: + case ACPI_TYPE_POWER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + + ACPI_ERROR((AE_INFO, + "Target must be [Buffer/Integer/String/Reference], found [%s] (%4.4s)", + acpi_ut_get_type_name(node->type), + node->name.ascii)); + + return_ACPI_STATUS(AE_AML_TARGET_TYPE); + + default: + break; + } + } + /* * Resolve the source object to an actual value * (If it is a reference object) @@ -425,13 +490,13 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, /* Do the actual store operation */ switch (target_type) { - case ACPI_TYPE_INTEGER: - case ACPI_TYPE_STRING: - case ACPI_TYPE_BUFFER: /* * The simple data types all support implicit source operand * conversion before the store. */ + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: if ((walk_state->opcode == AML_COPY_OP) || !implicit_conversion) { /* @@ -467,7 +532,7 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, new_desc->common.type); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Store %s into %s via Convert/Attach\n", + "Store type [%s] into [%s] via Convert/Attach\n", acpi_ut_get_object_type_name (source_desc), acpi_ut_get_object_type_name @@ -491,15 +556,12 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, default: /* - * No conversions for all other types. Directly store a copy of - * the source object. This is the ACPI spec-defined behavior for - * the copy_object operator. + * copy_object operator: No conversions for all other types. + * Instead, directly store a copy of the source object. * - * NOTE: For the Store operator, this is a departure from the - * ACPI spec, which states "If conversion is impossible, abort - * the running control method". Instead, this code implements - * "If conversion is impossible, treat the Store operation as - * a CopyObject". + * This is the ACPI spec-defined behavior for the copy_object + * operator. (Note, for this default case, all normal + * Store/Target operations exited above with an error). */ status = acpi_ex_store_direct_to_node(source_desc, node, walk_state); diff --git a/kernel/drivers/acpi/acpica/exstoren.c b/kernel/drivers/acpi/acpica/exstoren.c index 3101607b4..d1841defa 100644 --- a/kernel/drivers/acpi/acpica/exstoren.c +++ b/kernel/drivers/acpi/acpica/exstoren.c @@ -122,9 +122,10 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr, /* Conversion successful but still not a valid type */ ACPI_ERROR((AE_INFO, - "Cannot assign type %s to %s (must be type Int/Str/Buf)", + "Cannot assign type [%s] to [%s] (must be type Int/Str/Buf)", acpi_ut_get_object_type_name(source_desc), acpi_ut_get_type_name(target_type))); + status = AE_AML_OPERAND_TYPE; } break; @@ -275,7 +276,7 @@ acpi_ex_store_object_to_object(union acpi_operand_object *source_desc, /* * All other types come here. */ - ACPI_WARNING((AE_INFO, "Store into type %s not implemented", + ACPI_WARNING((AE_INFO, "Store into type [%s] not implemented", acpi_ut_get_object_type_name(dest_desc))); status = AE_NOT_IMPLEMENTED; diff --git a/kernel/drivers/acpi/acpica/exstorob.c b/kernel/drivers/acpi/acpica/exstorob.c index 6fa3c8d8f..e1d4f4d51 100644 --- a/kernel/drivers/acpi/acpica/exstorob.c +++ b/kernel/drivers/acpi/acpica/exstorob.c @@ -100,9 +100,9 @@ acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc, /* Clear existing buffer and copy in the new one */ - ACPI_MEMSET(target_desc->buffer.pointer, 0, - target_desc->buffer.length); - ACPI_MEMCPY(target_desc->buffer.pointer, buffer, length); + memset(target_desc->buffer.pointer, 0, + target_desc->buffer.length); + memcpy(target_desc->buffer.pointer, buffer, length); #ifdef ACPI_OBSOLETE_BEHAVIOR /* @@ -129,8 +129,8 @@ acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc, } else { /* Truncate the source, copy only what will fit */ - ACPI_MEMCPY(target_desc->buffer.pointer, buffer, - target_desc->buffer.length); + memcpy(target_desc->buffer.pointer, buffer, + target_desc->buffer.length); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Truncating source buffer from %X to %X\n", @@ -187,9 +187,9 @@ acpi_ex_store_string_to_string(union acpi_operand_object *source_desc, * String will fit in existing non-static buffer. * Clear old string and copy in the new one */ - ACPI_MEMSET(target_desc->string.pointer, 0, - (acpi_size) target_desc->string.length + 1); - ACPI_MEMCPY(target_desc->string.pointer, buffer, length); + memset(target_desc->string.pointer, 0, + (acpi_size) target_desc->string.length + 1); + memcpy(target_desc->string.pointer, buffer, length); } else { /* * Free the current buffer, then allocate a new buffer @@ -210,7 +210,7 @@ acpi_ex_store_string_to_string(union acpi_operand_object *source_desc, } target_desc->common.flags &= ~AOPOBJ_STATIC_POINTER; - ACPI_MEMCPY(target_desc->string.pointer, buffer, length); + memcpy(target_desc->string.pointer, buffer, length); } /* Set the new target length */ diff --git a/kernel/drivers/acpi/acpica/exutils.c b/kernel/drivers/acpi/acpica/exutils.c index 3f4225e95..30c3f464f 100644 --- a/kernel/drivers/acpi/acpica/exutils.c +++ b/kernel/drivers/acpi/acpica/exutils.c @@ -378,6 +378,38 @@ void acpi_ex_integer_to_string(char *out_string, u64 value) } } +/******************************************************************************* + * + * FUNCTION: acpi_ex_pci_cls_to_string + * + * PARAMETERS: out_string - Where to put the converted string (7 bytes) + * PARAMETERS: class_code - PCI class code to be converted (3 bytes) + * + * RETURN: None + * + * DESCRIPTION: Convert 3-bytes PCI class code to string representation. + * Return buffer must be large enough to hold the string. The + * string returned is always exactly of length + * ACPI_PCICLS_STRING_SIZE (includes null terminator). + * + ******************************************************************************/ + +void acpi_ex_pci_cls_to_string(char *out_string, u8 class_code[3]) +{ + + ACPI_FUNCTION_ENTRY(); + + /* All 3 bytes are hexadecimal */ + + out_string[0] = acpi_ut_hex_to_ascii_char((u64)class_code[0], 4); + out_string[1] = acpi_ut_hex_to_ascii_char((u64)class_code[0], 0); + out_string[2] = acpi_ut_hex_to_ascii_char((u64)class_code[1], 4); + out_string[3] = acpi_ut_hex_to_ascii_char((u64)class_code[1], 0); + out_string[4] = acpi_ut_hex_to_ascii_char((u64)class_code[2], 4); + out_string[5] = acpi_ut_hex_to_ascii_char((u64)class_code[2], 0); + out_string[6] = 0; +} + /******************************************************************************* * * FUNCTION: acpi_is_valid_space_id diff --git a/kernel/drivers/acpi/acpica/hwpci.c b/kernel/drivers/acpi/acpica/hwpci.c index c5214dec4..f785ea788 100644 --- a/kernel/drivers/acpi/acpica/hwpci.c +++ b/kernel/drivers/acpi/acpica/hwpci.c @@ -123,7 +123,7 @@ acpi_hw_derive_pci_id(struct acpi_pci_id *pci_id, acpi_handle root_pci_device, acpi_handle pci_region) { acpi_status status; - struct acpi_pci_device *list_head = NULL; + struct acpi_pci_device *list_head; ACPI_FUNCTION_TRACE(hw_derive_pci_id); @@ -177,13 +177,13 @@ acpi_hw_build_pci_list(acpi_handle root_pci_device, acpi_handle parent_device; acpi_status status; struct acpi_pci_device *list_element; - struct acpi_pci_device *list_head = NULL; /* * Ascend namespace branch until the root_pci_device is reached, building * a list of device nodes. Loop will exit when either the PCI device is * found, or the root of the namespace is reached. */ + *return_list_head = NULL; current_device = pci_region; while (1) { status = acpi_get_parent(current_device, &parent_device); @@ -198,7 +198,6 @@ acpi_hw_build_pci_list(acpi_handle root_pci_device, /* Finished when we reach the PCI root device (PNP0A03 or PNP0A08) */ if (parent_device == root_pci_device) { - *return_list_head = list_head; return (AE_OK); } @@ -213,9 +212,9 @@ acpi_hw_build_pci_list(acpi_handle root_pci_device, /* Put new element at the head of the list */ - list_element->next = list_head; + list_element->next = *return_list_head; list_element->device = parent_device; - list_head = list_element; + *return_list_head = list_element; current_device = parent_device; } diff --git a/kernel/drivers/acpi/acpica/hwxfsleep.c b/kernel/drivers/acpi/acpica/hwxfsleep.c index 3b3767698..d62a61612 100644 --- a/kernel/drivers/acpi/acpica/hwxfsleep.c +++ b/kernel/drivers/acpi/acpica/hwxfsleep.c @@ -50,6 +50,13 @@ ACPI_MODULE_NAME("hwxfsleep") /* Local prototypes */ +#if (!ACPI_REDUCED_HARDWARE) +static acpi_status +acpi_hw_set_firmware_waking_vectors(struct acpi_table_facs *facs, + acpi_physical_address physical_address, + acpi_physical_address physical_address64); +#endif + static acpi_status acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id); /* @@ -72,6 +79,7 @@ static struct acpi_sleep_functions acpi_sleep_dispatch[] = { /* * These functions are removed for the ACPI_REDUCED_HARDWARE case: + * acpi_set_firmware_waking_vectors * acpi_set_firmware_waking_vector * acpi_set_firmware_waking_vector64 * acpi_enter_sleep_state_s4bios @@ -80,20 +88,26 @@ static struct acpi_sleep_functions acpi_sleep_dispatch[] = { #if (!ACPI_REDUCED_HARDWARE) /******************************************************************************* * - * FUNCTION: acpi_set_firmware_waking_vector + * FUNCTION: acpi_hw_set_firmware_waking_vectors * - * PARAMETERS: physical_address - 32-bit physical address of ACPI real mode + * PARAMETERS: facs - Pointer to FACS table + * physical_address - 32-bit physical address of ACPI real mode * entry point. + * physical_address64 - 64-bit physical address of ACPI protected + * mode entry point. * * RETURN: Status * - * DESCRIPTION: Sets the 32-bit firmware_waking_vector field of the FACS + * DESCRIPTION: Sets the firmware_waking_vector fields of the FACS * ******************************************************************************/ -acpi_status acpi_set_firmware_waking_vector(u32 physical_address) +static acpi_status +acpi_hw_set_firmware_waking_vectors(struct acpi_table_facs *facs, + acpi_physical_address physical_address, + acpi_physical_address physical_address64) { - ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector); + ACPI_FUNCTION_TRACE(acpi_hw_set_firmware_waking_vectors); /* @@ -106,17 +120,81 @@ acpi_status acpi_set_firmware_waking_vector(u32 physical_address) /* Set the 32-bit vector */ - acpi_gbl_FACS->firmware_waking_vector = physical_address; + facs->firmware_waking_vector = (u32)physical_address; + + if (facs->length > 32) { + if (facs->version >= 1) { + + /* Set the 64-bit vector */ + + facs->xfirmware_waking_vector = physical_address64; + } else { + /* Clear the 64-bit vector if it exists */ + + facs->xfirmware_waking_vector = 0; + } + } + + return_ACPI_STATUS(AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_set_firmware_waking_vectors + * + * PARAMETERS: physical_address - 32-bit physical address of ACPI real mode + * entry point. + * physical_address64 - 64-bit physical address of ACPI protected + * mode entry point. + * + * RETURN: Status + * + * DESCRIPTION: Sets the firmware_waking_vector fields of the FACS + * + ******************************************************************************/ + +acpi_status +acpi_set_firmware_waking_vectors(acpi_physical_address physical_address, + acpi_physical_address physical_address64) +{ - /* Clear the 64-bit vector if it exists */ + ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vectors); - if ((acpi_gbl_FACS->length > 32) && (acpi_gbl_FACS->version >= 1)) { - acpi_gbl_FACS->xfirmware_waking_vector = 0; + if (acpi_gbl_FACS) { + (void)acpi_hw_set_firmware_waking_vectors(acpi_gbl_FACS, + physical_address, + physical_address64); } return_ACPI_STATUS(AE_OK); } +ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vectors) + +/******************************************************************************* + * + * FUNCTION: acpi_set_firmware_waking_vector + * + * PARAMETERS: physical_address - 32-bit physical address of ACPI real mode + * entry point. + * + * RETURN: Status + * + * DESCRIPTION: Sets the 32-bit firmware_waking_vector field of the FACS + * + ******************************************************************************/ +acpi_status acpi_set_firmware_waking_vector(u32 physical_address) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector); + + status = acpi_set_firmware_waking_vectors((acpi_physical_address) + physical_address, 0); + + return_ACPI_STATUS(status); +} + ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector) #if ACPI_MACHINE_WIDTH == 64 @@ -136,25 +214,19 @@ ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector) ******************************************************************************/ acpi_status acpi_set_firmware_waking_vector64(u64 physical_address) { - ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector64); - - - /* Determine if the 64-bit vector actually exists */ + acpi_status status; - if ((acpi_gbl_FACS->length <= 32) || (acpi_gbl_FACS->version < 1)) { - return_ACPI_STATUS(AE_NOT_EXIST); - } + ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector64); - /* Clear 32-bit vector, set the 64-bit X_ vector */ + status = acpi_set_firmware_waking_vectors(0, + (acpi_physical_address) + physical_address); - acpi_gbl_FACS->firmware_waking_vector = 0; - acpi_gbl_FACS->xfirmware_waking_vector = physical_address; - return_ACPI_STATUS(AE_OK); + return_ACPI_STATUS(status); } ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector64) #endif - /******************************************************************************* * * FUNCTION: acpi_enter_sleep_state_s4bios diff --git a/kernel/drivers/acpi/acpica/nsaccess.c b/kernel/drivers/acpi/acpica/nsaccess.c index 24fa19a76..c687b9979 100644 --- a/kernel/drivers/acpi/acpica/nsaccess.c +++ b/kernel/drivers/acpi/acpica/nsaccess.c @@ -102,7 +102,7 @@ acpi_status acpi_ns_root_initialize(void) /* _OSI is optional for now, will be permanent later */ - if (!ACPI_STRCMP(init_val->name, "_OSI") + if (!strcmp(init_val->name, "_OSI") && !acpi_gbl_create_osi_method) { continue; } @@ -180,7 +180,7 @@ acpi_status acpi_ns_root_initialize(void) /* Build an object around the static string */ - obj_desc->string.length = (u32)ACPI_STRLEN(val); + obj_desc->string.length = (u32)strlen(val); obj_desc->string.pointer = val; obj_desc->common.flags |= AOPOBJ_STATIC_POINTER; break; @@ -203,7 +203,7 @@ acpi_status acpi_ns_root_initialize(void) /* Special case for ACPI Global Lock */ - if (ACPI_STRCMP(init_val->name, "_GL_") == 0) { + if (strcmp(init_val->name, "_GL_") == 0) { acpi_gbl_global_lock_mutex = obj_desc; /* Create additional counting semaphore for global lock */ @@ -304,7 +304,9 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, return_ACPI_STATUS(AE_BAD_PARAMETER); } - local_flags = flags & ~(ACPI_NS_ERROR_IF_FOUND | ACPI_NS_SEARCH_PARENT); + local_flags = flags & + ~(ACPI_NS_ERROR_IF_FOUND | ACPI_NS_OVERRIDE_IF_FOUND | + ACPI_NS_SEARCH_PARENT); *return_node = ACPI_ENTRY_NOT_FOUND; acpi_gbl_ns_lookup_count++; @@ -547,6 +549,12 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, if (flags & ACPI_NS_ERROR_IF_FOUND) { local_flags |= ACPI_NS_ERROR_IF_FOUND; } + + /* Set override flag according to caller */ + + if (flags & ACPI_NS_OVERRIDE_IF_FOUND) { + local_flags |= ACPI_NS_OVERRIDE_IF_FOUND; + } } /* Extract one ACPI name from the front of the pathname */ diff --git a/kernel/drivers/acpi/acpica/nsconvert.c b/kernel/drivers/acpi/acpica/nsconvert.c index 1a8b39c8d..da55a1c60 100644 --- a/kernel/drivers/acpi/acpica/nsconvert.c +++ b/kernel/drivers/acpi/acpica/nsconvert.c @@ -187,8 +187,8 @@ acpi_ns_convert_to_string(union acpi_operand_object *original_object, * Copy the raw buffer data with no transform. String is already NULL * terminated at Length+1. */ - ACPI_MEMCPY(new_object->string.pointer, - original_object->buffer.pointer, length); + memcpy(new_object->string.pointer, + original_object->buffer.pointer, length); break; default: @@ -251,9 +251,9 @@ acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, return (AE_NO_MEMORY); } - ACPI_MEMCPY(new_object->buffer.pointer, - original_object->string.pointer, - original_object->string.length); + memcpy(new_object->buffer.pointer, + original_object->string.pointer, + original_object->string.length); break; case ACPI_TYPE_PACKAGE: diff --git a/kernel/drivers/acpi/acpica/nsdump.c b/kernel/drivers/acpi/acpica/nsdump.c index d25939350..37aa5c45c 100644 --- a/kernel/drivers/acpi/acpica/nsdump.c +++ b/kernel/drivers/acpi/acpica/nsdump.c @@ -60,7 +60,6 @@ acpi_ns_dump_one_device(acpi_handle obj_handle, #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) -#ifdef ACPI_FUTURE_USAGE static acpi_status acpi_ns_dump_one_object_path(acpi_handle obj_handle, u32 level, void *context, void **return_value); @@ -68,7 +67,6 @@ acpi_ns_dump_one_object_path(acpi_handle obj_handle, static acpi_status acpi_ns_get_max_depth(acpi_handle obj_handle, u32 level, void *context, void **return_value); -#endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* * @@ -101,7 +99,7 @@ void acpi_ns_print_pathname(u32 num_segments, char *pathname) while (num_segments) { for (i = 0; i < 4; i++) { - ACPI_IS_PRINT(pathname[i]) ? + isprint((int)pathname[i]) ? acpi_os_printf("%c", pathname[i]) : acpi_os_printf("?"); } @@ -625,7 +623,6 @@ cleanup: return (AE_OK); } -#ifdef ACPI_FUTURE_USAGE /******************************************************************************* * * FUNCTION: acpi_ns_dump_objects @@ -680,9 +677,7 @@ acpi_ns_dump_objects(acpi_object_type type, (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); } -#endif /* ACPI_FUTURE_USAGE */ -#ifdef ACPI_FUTURE_USAGE /******************************************************************************* * * FUNCTION: acpi_ns_dump_one_object_path, acpi_ns_get_max_depth @@ -810,7 +805,6 @@ acpi_ns_dump_object_paths(acpi_object_type type, (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); } -#endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* * diff --git a/kernel/drivers/acpi/acpica/nseval.c b/kernel/drivers/acpi/acpica/nseval.c index 7bcc68f57..7eba578d3 100644 --- a/kernel/drivers/acpi/acpica/nseval.c +++ b/kernel/drivers/acpi/acpica/nseval.c @@ -59,15 +59,14 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj, * * FUNCTION: acpi_ns_evaluate * - * PARAMETERS: info - Evaluation info block, contains: + * PARAMETERS: info - Evaluation info block, contains these fields + * and more: * prefix_node - Prefix or Method/Object Node to execute * relative_path - Name of method to execute, If NULL, the * Node is the object to execute * parameters - List of parameters to pass to the method, * terminated by NULL. Params itself may be * NULL if no parameters are being passed. - * return_object - Where to put method's return value (if - * any). If NULL, no value is returned. * parameter_type - Type of Parameter list * return_object - Where to put method's return value (if * any). If NULL, no value is returned. @@ -275,6 +274,7 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info) acpi_ex_exit_interpreter(); if (ACPI_FAILURE(status)) { + info->return_object = NULL; goto cleanup; } @@ -440,7 +440,7 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj, /* Initialize the evaluation information block */ - ACPI_MEMSET(info, 0, sizeof(struct acpi_evaluate_info)); + memset(info, 0, sizeof(struct acpi_evaluate_info)); info->prefix_node = parent_node; /* @@ -465,7 +465,8 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj, status = acpi_ns_evaluate(info); - ACPI_DEBUG_PRINT((ACPI_DB_INIT, "Executed module-level code at %p\n", + ACPI_DEBUG_PRINT((ACPI_DB_INIT_NAMES, + "Executed module-level code at %p\n", method_obj->method.aml_start)); /* Delete a possible implicit return value (in slack mode) */ diff --git a/kernel/drivers/acpi/acpica/nsinit.c b/kernel/drivers/acpi/acpica/nsinit.c index 4a85c4517..b744a5361 100644 --- a/kernel/drivers/acpi/acpica/nsinit.c +++ b/kernel/drivers/acpi/acpica/nsinit.c @@ -90,7 +90,7 @@ acpi_status acpi_ns_initialize_objects(void) /* Set all init info to zero */ - ACPI_MEMSET(&info, 0, sizeof(struct acpi_init_walk_info)); + memset(&info, 0, sizeof(struct acpi_init_walk_info)); /* Walk entire namespace from the supplied root */ @@ -566,7 +566,7 @@ acpi_ns_init_one_device(acpi_handle obj_handle, ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, device_node, METHOD_NAME__INI)); - ACPI_MEMSET(info, 0, sizeof(struct acpi_evaluate_info)); + memset(info, 0, sizeof(struct acpi_evaluate_info)); info->prefix_node = device_node; info->relative_pathname = METHOD_NAME__INI; info->parameters = NULL; diff --git a/kernel/drivers/acpi/acpica/nsload.c b/kernel/drivers/acpi/acpica/nsload.c index bd6cd4a81..14ab83668 100644 --- a/kernel/drivers/acpi/acpica/nsload.c +++ b/kernel/drivers/acpi/acpica/nsload.c @@ -111,7 +111,21 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node) if (ACPI_SUCCESS(status)) { acpi_tb_set_table_loaded_flag(table_index, TRUE); } else { - (void)acpi_tb_release_owner_id(table_index); + /* + * On error, delete any namespace objects created by this table. + * We cannot initialize these objects, so delete them. There are + * a couple of expecially bad cases: + * AE_ALREADY_EXISTS - namespace collision. + * AE_NOT_FOUND - the target of a Scope operator does not + * exist. This target of Scope must already exist in the + * namespace, as per the ACPI specification. + */ + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + acpi_ns_delete_namespace_by_owner(acpi_gbl_root_table_list. + tables[table_index].owner_id); + acpi_tb_release_owner_id(table_index); + + return_ACPI_STATUS(status); } unlock: diff --git a/kernel/drivers/acpi/acpica/nsnames.c b/kernel/drivers/acpi/acpica/nsnames.c index d293d9748..8934b4edd 100644 --- a/kernel/drivers/acpi/acpica/nsnames.c +++ b/kernel/drivers/acpi/acpica/nsnames.c @@ -49,73 +49,6 @@ #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsnames") -/******************************************************************************* - * - * FUNCTION: acpi_ns_build_external_path - * - * PARAMETERS: node - NS node whose pathname is needed - * size - Size of the pathname - * *name_buffer - Where to return the pathname - * - * RETURN: Status - * Places the pathname into the name_buffer, in external format - * (name segments separated by path separators) - * - * DESCRIPTION: Generate a full pathaname - * - ******************************************************************************/ -acpi_status -acpi_ns_build_external_path(struct acpi_namespace_node *node, - acpi_size size, char *name_buffer) -{ - acpi_size index; - struct acpi_namespace_node *parent_node; - - ACPI_FUNCTION_ENTRY(); - - /* Special case for root */ - - index = size - 1; - if (index < ACPI_NAME_SIZE) { - name_buffer[0] = AML_ROOT_PREFIX; - name_buffer[1] = 0; - return (AE_OK); - } - - /* Store terminator byte, then build name backwards */ - - parent_node = node; - name_buffer[index] = 0; - - while ((index > ACPI_NAME_SIZE) && (parent_node != acpi_gbl_root_node)) { - index -= ACPI_NAME_SIZE; - - /* Put the name into the buffer */ - - ACPI_MOVE_32_TO_32((name_buffer + index), &parent_node->name); - parent_node = parent_node->parent; - - /* Prefix name with the path separator */ - - index--; - name_buffer[index] = ACPI_PATH_SEPARATOR; - } - - /* Overwrite final separator with the root prefix character */ - - name_buffer[index] = AML_ROOT_PREFIX; - - if (index != 0) { - ACPI_ERROR((AE_INFO, - "Could not construct external pathname; index=%u, size=%u, Path=%s", - (u32) index, (u32) size, &name_buffer[size])); - - return (AE_BAD_PARAMETER); - } - - return (AE_OK); -} - /******************************************************************************* * * FUNCTION: acpi_ns_get_external_pathname @@ -130,37 +63,13 @@ acpi_ns_build_external_path(struct acpi_namespace_node *node, * for error and debug statements. * ******************************************************************************/ - char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node) { - acpi_status status; char *name_buffer; - acpi_size size; ACPI_FUNCTION_TRACE_PTR(ns_get_external_pathname, node); - /* Calculate required buffer size based on depth below root */ - - size = acpi_ns_get_pathname_length(node); - if (!size) { - return_PTR(NULL); - } - - /* Allocate a buffer to be returned to caller */ - - name_buffer = ACPI_ALLOCATE_ZEROED(size); - if (!name_buffer) { - ACPI_ERROR((AE_INFO, "Could not allocate %u bytes", (u32)size)); - return_PTR(NULL); - } - - /* Build the path in the allocated buffer */ - - status = acpi_ns_build_external_path(node, size, name_buffer); - if (ACPI_FAILURE(status)) { - ACPI_FREE(name_buffer); - return_PTR(NULL); - } + name_buffer = acpi_ns_get_normalized_pathname(node, FALSE); return_PTR(name_buffer); } @@ -180,33 +89,12 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node) acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node) { acpi_size size; - struct acpi_namespace_node *next_node; ACPI_FUNCTION_ENTRY(); - /* - * Compute length of pathname as 5 * number of name segments. - * Go back up the parent tree to the root - */ - size = 0; - next_node = node; + size = acpi_ns_build_normalized_path(node, NULL, 0, FALSE); - while (next_node && (next_node != acpi_gbl_root_node)) { - if (ACPI_GET_DESCRIPTOR_TYPE(next_node) != ACPI_DESC_TYPE_NAMED) { - ACPI_ERROR((AE_INFO, - "Invalid Namespace Node (%p) while traversing namespace", - next_node)); - return (0); - } - size += ACPI_PATH_SEGMENT_LENGTH; - next_node = next_node->parent; - } - - if (!size) { - size = 1; /* Root node case */ - } - - return (size + 1); /* +1 for null string terminator */ + return (size); } /******************************************************************************* @@ -216,6 +104,8 @@ acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node) * PARAMETERS: target_handle - Handle of named object whose name is * to be found * buffer - Where the pathname is returned + * no_trailing - Remove trailing '_' for each name + * segment * * RETURN: Status, Buffer is filled with pathname if status is AE_OK * @@ -225,7 +115,7 @@ acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node) acpi_status acpi_ns_handle_to_pathname(acpi_handle target_handle, - struct acpi_buffer * buffer) + struct acpi_buffer * buffer, u8 no_trailing) { acpi_status status; struct acpi_namespace_node *node; @@ -240,7 +130,8 @@ acpi_ns_handle_to_pathname(acpi_handle target_handle, /* Determine size required for the caller buffer */ - required_size = acpi_ns_get_pathname_length(node); + required_size = + acpi_ns_build_normalized_path(node, NULL, 0, no_trailing); if (!required_size) { return_ACPI_STATUS(AE_BAD_PARAMETER); } @@ -254,8 +145,8 @@ acpi_ns_handle_to_pathname(acpi_handle target_handle, /* Build the path in the caller buffer */ - status = - acpi_ns_build_external_path(node, required_size, buffer->pointer); + (void)acpi_ns_build_normalized_path(node, buffer->pointer, + required_size, no_trailing); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -264,3 +155,149 @@ acpi_ns_handle_to_pathname(acpi_handle target_handle, (char *)buffer->pointer, (u32) required_size)); return_ACPI_STATUS(AE_OK); } + +/******************************************************************************* + * + * FUNCTION: acpi_ns_build_normalized_path + * + * PARAMETERS: node - Namespace node + * full_path - Where the path name is returned + * path_size - Size of returned path name buffer + * no_trailing - Remove trailing '_' from each name segment + * + * RETURN: Return 1 if the AML path is empty, otherwise returning (length + * of pathname + 1) which means the 'FullPath' contains a trailing + * null. + * + * DESCRIPTION: Build and return a full namespace pathname. + * Note that if the size of 'FullPath' isn't large enough to + * contain the namespace node's path name, the actual required + * buffer length is returned, and it should be greater than + * 'PathSize'. So callers are able to check the returning value + * to determine the buffer size of 'FullPath'. + * + ******************************************************************************/ + +u32 +acpi_ns_build_normalized_path(struct acpi_namespace_node *node, + char *full_path, u32 path_size, u8 no_trailing) +{ + u32 length = 0, i; + char name[ACPI_NAME_SIZE]; + u8 do_no_trailing; + char c, *left, *right; + struct acpi_namespace_node *next_node; + + ACPI_FUNCTION_TRACE_PTR(ns_build_normalized_path, node); + +#define ACPI_PATH_PUT8(path, size, byte, length) \ + do { \ + if ((length) < (size)) \ + { \ + (path)[(length)] = (byte); \ + } \ + (length)++; \ + } while (0) + + /* + * Make sure the path_size is correct, so that we don't need to + * validate both full_path and path_size. + */ + if (!full_path) { + path_size = 0; + } + + if (!node) { + goto build_trailing_null; + } + + next_node = node; + while (next_node && next_node != acpi_gbl_root_node) { + if (next_node != node) { + ACPI_PATH_PUT8(full_path, path_size, + AML_DUAL_NAME_PREFIX, length); + } + ACPI_MOVE_32_TO_32(name, &next_node->name); + do_no_trailing = no_trailing; + for (i = 0; i < 4; i++) { + c = name[4 - i - 1]; + if (do_no_trailing && c != '_') { + do_no_trailing = FALSE; + } + if (!do_no_trailing) { + ACPI_PATH_PUT8(full_path, path_size, c, length); + } + } + next_node = next_node->parent; + } + ACPI_PATH_PUT8(full_path, path_size, AML_ROOT_PREFIX, length); + + /* Reverse the path string */ + + if (length <= path_size) { + left = full_path; + right = full_path + length - 1; + while (left < right) { + c = *left; + *left++ = *right; + *right-- = c; + } + } + + /* Append the trailing null */ + +build_trailing_null: + ACPI_PATH_PUT8(full_path, path_size, '\0', length); + +#undef ACPI_PATH_PUT8 + + return_UINT32(length); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_get_normalized_pathname + * + * PARAMETERS: node - Namespace node whose pathname is needed + * no_trailing - Remove trailing '_' from each name segment + * + * RETURN: Pointer to storage containing the fully qualified name of + * the node, In external format (name segments separated by path + * separators.) + * + * DESCRIPTION: Used to obtain the full pathname to a namespace node, usually + * for error and debug statements. All trailing '_' will be + * removed from the full pathname if 'NoTrailing' is specified.. + * + ******************************************************************************/ + +char *acpi_ns_get_normalized_pathname(struct acpi_namespace_node *node, + u8 no_trailing) +{ + char *name_buffer; + acpi_size size; + + ACPI_FUNCTION_TRACE_PTR(ns_get_normalized_pathname, node); + + /* Calculate required buffer size based on depth below root */ + + size = acpi_ns_build_normalized_path(node, NULL, 0, no_trailing); + if (!size) { + return_PTR(NULL); + } + + /* Allocate a buffer to be returned to caller */ + + name_buffer = ACPI_ALLOCATE_ZEROED(size); + if (!name_buffer) { + ACPI_ERROR((AE_INFO, "Could not allocate %u bytes", (u32)size)); + return_PTR(NULL); + } + + /* Build the path in the allocated buffer */ + + (void)acpi_ns_build_normalized_path(node, name_buffer, size, + no_trailing); + + return_PTR(name_buffer); +} diff --git a/kernel/drivers/acpi/acpica/nsparse.c b/kernel/drivers/acpi/acpica/nsparse.c index c95a11976..3736d43b1 100644 --- a/kernel/drivers/acpi/acpica/nsparse.c +++ b/kernel/drivers/acpi/acpica/nsparse.c @@ -70,7 +70,7 @@ acpi_ns_one_complete_parse(u32 pass_number, { union acpi_parse_object *parse_root; acpi_status status; - u32 aml_length; + u32 aml_length; u8 *aml_start; struct acpi_walk_state *walk_state; struct acpi_table_header *table; @@ -78,6 +78,20 @@ acpi_ns_one_complete_parse(u32 pass_number, ACPI_FUNCTION_TRACE(ns_one_complete_parse); + status = acpi_get_table_by_index(table_index, &table); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Table must consist of at least a complete header */ + + if (table->length < sizeof(struct acpi_table_header)) { + return_ACPI_STATUS(AE_BAD_HEADER); + } + + aml_start = (u8 *)table + sizeof(struct acpi_table_header); + aml_length = table->length - sizeof(struct acpi_table_header); + status = acpi_tb_get_owner_id(table_index, &owner_id); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); @@ -85,7 +99,7 @@ acpi_ns_one_complete_parse(u32 pass_number, /* Create and init a Root Node */ - parse_root = acpi_ps_create_scope_op(); + parse_root = acpi_ps_create_scope_op(aml_start); if (!parse_root) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -98,28 +112,19 @@ acpi_ns_one_complete_parse(u32 pass_number, return_ACPI_STATUS(AE_NO_MEMORY); } - status = acpi_get_table_by_index(table_index, &table); + status = acpi_ds_init_aml_walk(walk_state, parse_root, NULL, + aml_start, aml_length, NULL, + (u8)pass_number); if (ACPI_FAILURE(status)) { acpi_ds_delete_walk_state(walk_state); - acpi_ps_free_op(parse_root); - return_ACPI_STATUS(status); + goto cleanup; } - /* Table must consist of at least a complete header */ + /* Found OSDT table, enable the namespace override feature */ - if (table->length < sizeof(struct acpi_table_header)) { - status = AE_BAD_HEADER; - } else { - aml_start = (u8 *) table + sizeof(struct acpi_table_header); - aml_length = table->length - sizeof(struct acpi_table_header); - status = acpi_ds_init_aml_walk(walk_state, parse_root, NULL, - aml_start, aml_length, NULL, - (u8) pass_number); - } - - if (ACPI_FAILURE(status)) { - acpi_ds_delete_walk_state(walk_state); - goto cleanup; + if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_OSDT) && + pass_number == ACPI_IMODE_LOAD_PASS1) { + walk_state->namespace_override = TRUE; } /* start_node is the default location to load the table */ diff --git a/kernel/drivers/acpi/acpica/nspredef.c b/kernel/drivers/acpi/acpica/nspredef.c index 0eb54315b..0c20980bb 100644 --- a/kernel/drivers/acpi/acpica/nspredef.c +++ b/kernel/drivers/acpi/acpica/nspredef.c @@ -226,7 +226,7 @@ acpi_ns_check_object_type(struct acpi_evaluate_info *info, { union acpi_operand_object *return_object = *return_object_ptr; acpi_status status = AE_OK; - char type_buffer[48]; /* Room for 5 types */ + char type_buffer[96]; /* Room for 10 types */ /* A Namespace node should not get here, but make sure */ diff --git a/kernel/drivers/acpi/acpica/nsprepkg.c b/kernel/drivers/acpi/acpica/nsprepkg.c index 8b79958b7..9bb251932 100644 --- a/kernel/drivers/acpi/acpica/nsprepkg.c +++ b/kernel/drivers/acpi/acpica/nsprepkg.c @@ -316,6 +316,13 @@ acpi_ns_check_package(struct acpi_evaluate_info *info, acpi_ns_check_package_list(info, package, elements, count); break; + case ACPI_PTYPE2_VAR_VAR: + /* + * Returns a variable list of packages, each with a variable list + * of objects. + */ + break; + case ACPI_PTYPE2_UUID_PAIR: /* The package must contain pairs of (UUID + type) */ @@ -487,6 +494,12 @@ acpi_ns_check_package_list(struct acpi_evaluate_info *info, } break; + case ACPI_PTYPE2_VAR_VAR: + /* + * Each subpackage has a fixed or variable number of elements + */ + break; + case ACPI_PTYPE2_FIXED: /* Each subpackage has a fixed length */ diff --git a/kernel/drivers/acpi/acpica/nsrepair.c b/kernel/drivers/acpi/acpica/nsrepair.c index 151fcd95b..77d8103d0 100644 --- a/kernel/drivers/acpi/acpica/nsrepair.c +++ b/kernel/drivers/acpi/acpica/nsrepair.c @@ -497,10 +497,10 @@ acpi_ns_remove_null_elements(struct acpi_evaluate_info *info, case ACPI_PTYPE2_MIN: case ACPI_PTYPE2_REV_FIXED: case ACPI_PTYPE2_FIX_VAR: - break; default: + case ACPI_PTYPE2_VAR_VAR: case ACPI_PTYPE1_FIXED: case ACPI_PTYPE1_OPTION: return; diff --git a/kernel/drivers/acpi/acpica/nsrepair2.c b/kernel/drivers/acpi/acpica/nsrepair2.c index c30672d23..0515a70f4 100644 --- a/kernel/drivers/acpi/acpica/nsrepair2.c +++ b/kernel/drivers/acpi/acpica/nsrepair2.c @@ -580,7 +580,7 @@ acpi_ns_repair_HID(struct acpi_evaluate_info *info, * # is a hex digit. */ for (dest = new_string->string.pointer; *source; dest++, source++) { - *dest = (char)ACPI_TOUPPER(*source); + *dest = (char)toupper((int)*source); } acpi_ut_remove_reference(return_object); diff --git a/kernel/drivers/acpi/acpica/nssearch.c b/kernel/drivers/acpi/acpica/nssearch.c index 4a9d4a660..d73904013 100644 --- a/kernel/drivers/acpi/acpica/nssearch.c +++ b/kernel/drivers/acpi/acpica/nssearch.c @@ -325,8 +325,41 @@ acpi_ns_search_and_enter(u32 target_name, * If we found it AND the request specifies that a find is an error, * return the error */ - if ((status == AE_OK) && (flags & ACPI_NS_ERROR_IF_FOUND)) { - status = AE_ALREADY_EXISTS; + if (status == AE_OK) { + + /* The node was found in the namespace */ + + /* + * If the namespace override feature is enabled for this node, + * delete any existing attached sub-object and make the node + * look like a new node that is owned by the override table. + */ + if (flags & ACPI_NS_OVERRIDE_IF_FOUND) { + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, + "Namespace override: %4.4s pass %u type %X Owner %X\n", + ACPI_CAST_PTR(char, + &target_name), + interpreter_mode, + (*return_node)->type, + walk_state->owner_id)); + + acpi_ns_delete_children(*return_node); + if (acpi_gbl_runtime_namespace_override) { + acpi_ut_remove_reference((*return_node)->object); + (*return_node)->object = NULL; + (*return_node)->owner_id = + walk_state->owner_id; + } else { + acpi_ns_remove_node(*return_node); + *return_node = ACPI_ENTRY_NOT_FOUND; + } + } + + /* Return an error if we don't expect to find the object */ + + else if (flags & ACPI_NS_ERROR_IF_FOUND) { + status = AE_ALREADY_EXISTS; + } } #ifdef ACPI_ASL_COMPILER if (*return_node && (*return_node)->type == ACPI_TYPE_ANY) { diff --git a/kernel/drivers/acpi/acpica/nsutils.c b/kernel/drivers/acpi/acpica/nsutils.c index 6ad02008c..de325ae04 100644 --- a/kernel/drivers/acpi/acpica/nsutils.c +++ b/kernel/drivers/acpi/acpica/nsutils.c @@ -83,7 +83,7 @@ acpi_ns_print_node_pathname(struct acpi_namespace_node *node, buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; - status = acpi_ns_handle_to_pathname(node, &buffer); + status = acpi_ns_handle_to_pathname(node, &buffer, TRUE); if (ACPI_SUCCESS(status)) { if (message) { acpi_os_printf("%s ", message); @@ -292,8 +292,7 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info) } else { /* Convert the character to uppercase and save it */ - result[i] = - (char)ACPI_TOUPPER((int)*external_name); + result[i] = (char)toupper((int)*external_name); external_name++; } } @@ -597,6 +596,23 @@ void acpi_ns_terminate(void) ACPI_FUNCTION_TRACE(ns_terminate); +#ifdef ACPI_EXEC_APP + { + union acpi_operand_object *prev; + union acpi_operand_object *next; + + /* Delete any module-level code blocks */ + + next = acpi_gbl_module_code_list; + while (next) { + prev = next; + next = next->method.mutex; + prev->method.mutex = NULL; /* Clear the Mutex (cheated) field */ + acpi_ut_remove_reference(prev); + } + } +#endif + /* * Free the entire namespace -- all nodes and all objects * attached to the nodes diff --git a/kernel/drivers/acpi/acpica/nsxfeval.c b/kernel/drivers/acpi/acpica/nsxfeval.c index b6030a2de..6ee1e52b9 100644 --- a/kernel/drivers/acpi/acpica/nsxfeval.c +++ b/kernel/drivers/acpi/acpica/nsxfeval.c @@ -696,7 +696,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, return (AE_CTRL_DEPTH); } - no_match = ACPI_STRCMP(hid->string, info->hid); + no_match = strcmp(hid->string, info->hid); ACPI_FREE(hid); if (no_match) { @@ -715,8 +715,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, found = FALSE; for (i = 0; i < cid->count; i++) { - if (ACPI_STRCMP(cid->ids[i].string, info->hid) - == 0) { + if (strcmp(cid->ids[i].string, info->hid) == 0) { /* Found a matching CID */ diff --git a/kernel/drivers/acpi/acpica/nsxfname.c b/kernel/drivers/acpi/acpica/nsxfname.c index d66c32648..4b4d2f43d 100644 --- a/kernel/drivers/acpi/acpica/nsxfname.c +++ b/kernel/drivers/acpi/acpica/nsxfname.c @@ -114,7 +114,7 @@ acpi_get_handle(acpi_handle parent, /* Special case for root-only, since we can't search for it */ - if (!ACPI_STRCMP(pathname, ACPI_NS_ROOT_PATH)) { + if (!strcmp(pathname, ACPI_NS_ROOT_PATH)) { *ret_handle = ACPI_CAST_PTR(acpi_handle, acpi_gbl_root_node); return (AE_OK); @@ -172,11 +172,15 @@ acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer) return (status); } - if (name_type == ACPI_FULL_PATHNAME) { + if (name_type == ACPI_FULL_PATHNAME || + name_type == ACPI_FULL_PATHNAME_NO_TRAILING) { /* Get the full pathname (From the namespace root) */ - status = acpi_ns_handle_to_pathname(handle, buffer); + status = acpi_ns_handle_to_pathname(handle, buffer, + name_type == + ACPI_FULL_PATHNAME ? FALSE : + TRUE); return (status); } @@ -242,7 +246,7 @@ static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest, /* Copy actual string and return a pointer to the next string area */ - ACPI_MEMCPY(string_area, source->string, source->length); + memcpy(string_area, source->string, source->length); return (string_area + source->length); } @@ -260,7 +264,7 @@ static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest, * control methods (Such as in the case of a device.) * * For Device and Processor objects, run the Device _HID, _UID, _CID, _SUB, - * _STA, _ADR, _sx_w, and _sx_d methods. + * _CLS, _STA, _ADR, _sx_w, and _sx_d methods. * * Note: Allocates the return buffer, must be freed by the caller. * @@ -276,11 +280,12 @@ acpi_get_object_info(acpi_handle handle, struct acpi_pnp_device_id *hid = NULL; struct acpi_pnp_device_id *uid = NULL; struct acpi_pnp_device_id *sub = NULL; + struct acpi_pnp_device_id *cls = NULL; char *next_id_string; acpi_object_type type; acpi_name name; u8 param_count = 0; - u8 valid = 0; + u16 valid = 0; u32 info_size; u32 i; acpi_status status; @@ -320,7 +325,7 @@ acpi_get_object_info(acpi_handle handle, if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) { /* * Get extra info for ACPI Device/Processor objects only: - * Run the Device _HID, _UID, _SUB, and _CID methods. + * Run the Device _HID, _UID, _SUB, _CID, and _CLS methods. * * Note: none of these methods are required, so they may or may * not be present for this device. The Info->Valid bitfield is used @@ -363,6 +368,14 @@ acpi_get_object_info(acpi_handle handle, sizeof(struct acpi_pnp_device_id_list)); valid |= ACPI_VALID_CID; } + + /* Execute the Device._CLS method */ + + status = acpi_ut_execute_CLS(node, &cls); + if (ACPI_SUCCESS(status)) { + info_size += cls->length; + valid |= ACPI_VALID_CLS; + } } /* @@ -486,6 +499,11 @@ acpi_get_object_info(acpi_handle handle, } } + if (cls) { + next_id_string = acpi_ns_copy_device_id(&info->class_code, + cls, next_id_string); + } + /* Copy the fixed-length data */ info->info_size = info_size; @@ -510,6 +528,9 @@ cleanup: if (cid_list) { ACPI_FREE(cid_list); } + if (cls) { + ACPI_FREE(cls); + } return (status); } @@ -620,7 +641,7 @@ acpi_status acpi_install_method(u8 *buffer) /* Copy the method AML to the local buffer */ - ACPI_MEMCPY(aml_buffer, aml_start, aml_length); + memcpy(aml_buffer, aml_start, aml_length); /* Initialize the method object with the new method's information */ diff --git a/kernel/drivers/acpi/acpica/psargs.c b/kernel/drivers/acpi/acpica/psargs.c index 6d0387705..29d8b7b01 100644 --- a/kernel/drivers/acpi/acpica/psargs.c +++ b/kernel/drivers/acpi/acpica/psargs.c @@ -287,7 +287,7 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, "Control Method - %p Desc %p Path=%p\n", node, method_desc, path)); - name_op = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP); + name_op = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP, start); if (!name_op) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -484,7 +484,7 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state, static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state *parser_state) { - u32 aml_offset; + u8 *aml; union acpi_parse_object *field; union acpi_parse_object *arg = NULL; u16 opcode; @@ -498,8 +498,7 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state ACPI_FUNCTION_TRACE(ps_get_next_field); - aml_offset = - (u32)ACPI_PTR_DIFF(parser_state->aml, parser_state->aml_start); + aml = parser_state->aml; /* Determine field type */ @@ -536,13 +535,11 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state /* Allocate a new field op */ - field = acpi_ps_alloc_op(opcode); + field = acpi_ps_alloc_op(opcode, aml); if (!field) { return_PTR(NULL); } - field->common.aml_offset = aml_offset; - /* Decode the field type */ switch (opcode) { @@ -604,6 +601,7 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state * Argument for Connection operator can be either a Buffer * (resource descriptor), or a name_string. */ + aml = parser_state->aml; if (ACPI_GET8(parser_state->aml) == AML_BUFFER_OP) { parser_state->aml++; @@ -616,7 +614,8 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state /* Non-empty list */ - arg = acpi_ps_alloc_op(AML_INT_BYTELIST_OP); + arg = + acpi_ps_alloc_op(AML_INT_BYTELIST_OP, aml); if (!arg) { acpi_ps_free_op(field); return_PTR(NULL); @@ -665,7 +664,7 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state parser_state->aml = pkg_end; } else { - arg = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP); + arg = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP, aml); if (!arg) { acpi_ps_free_op(field); return_PTR(NULL); @@ -730,7 +729,7 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, /* Constants, strings, and namestrings are all the same size */ - arg = acpi_ps_alloc_op(AML_BYTE_OP); + arg = acpi_ps_alloc_op(AML_BYTE_OP, parser_state->aml); if (!arg) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -777,7 +776,8 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, /* Non-empty list */ - arg = acpi_ps_alloc_op(AML_INT_BYTELIST_OP); + arg = acpi_ps_alloc_op(AML_INT_BYTELIST_OP, + parser_state->aml); if (!arg) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -807,7 +807,9 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, /* null_name or name_string */ - arg = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP); + arg = + acpi_ps_alloc_op(AML_INT_NAMEPATH_OP, + parser_state->aml); if (!arg) { return_ACPI_STATUS(AE_NO_MEMORY); } diff --git a/kernel/drivers/acpi/acpica/psloop.c b/kernel/drivers/acpi/acpica/psloop.c index 90437227d..03ac8c9a6 100644 --- a/kernel/drivers/acpi/acpica/psloop.c +++ b/kernel/drivers/acpi/acpica/psloop.c @@ -51,6 +51,7 @@ #include #include "accommon.h" +#include "acinterp.h" #include "acparser.h" #include "acdispat.h" #include "amlcode.h" @@ -125,10 +126,7 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, */ while (GET_CURRENT_ARG_TYPE(walk_state->arg_types) && !walk_state->arg_count) { - walk_state->aml_offset = - (u32) ACPI_PTR_DIFF(walk_state->parser_state.aml, - walk_state->parser_state. - aml_start); + walk_state->aml = walk_state->parser_state.aml; status = acpi_ps_get_next_arg(walk_state, @@ -140,7 +138,6 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, } if (arg) { - arg->common.aml_offset = walk_state->aml_offset; acpi_ps_append_arg(op, arg); } @@ -324,6 +321,8 @@ acpi_ps_link_module_code(union acpi_parse_object *parent_op, union acpi_operand_object *method_obj; struct acpi_namespace_node *parent_node; + ACPI_FUNCTION_TRACE(ps_link_module_code); + /* Get the tail of the list */ prev = next = acpi_gbl_module_code_list; @@ -343,9 +342,13 @@ acpi_ps_link_module_code(union acpi_parse_object *parent_op, method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD); if (!method_obj) { - return; + return_VOID; } + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, + "Create/Link new code block: %p\n", + method_obj)); + if (parent_op->common.node) { parent_node = parent_op->common.node; } else { @@ -370,8 +373,14 @@ acpi_ps_link_module_code(union acpi_parse_object *parent_op, prev->method.mutex = method_obj; } } else { + ACPI_DEBUG_PRINT((ACPI_DB_PARSE, + "Appending to existing code block: %p\n", + prev)); + prev->method.aml_length += aml_length; } + + return_VOID; } /******************************************************************************* @@ -494,16 +503,7 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) continue; } - op->common.aml_offset = walk_state->aml_offset; - - if (walk_state->op_info) { - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, - "Opcode %4.4X [%s] Op %p Aml %p AmlOffset %5.5X\n", - (u32) op->common.aml_opcode, - walk_state->op_info->name, op, - parser_state->aml, - op->common.aml_offset)); - } + acpi_ex_start_trace_opcode(op, walk_state); } /* diff --git a/kernel/drivers/acpi/acpica/psobject.c b/kernel/drivers/acpi/acpica/psobject.c index 2f5ddd806..e54bc2aa7 100644 --- a/kernel/drivers/acpi/acpica/psobject.c +++ b/kernel/drivers/acpi/acpica/psobject.c @@ -66,12 +66,11 @@ static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state); static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state) { + u32 aml_offset; ACPI_FUNCTION_TRACE_PTR(ps_get_aml_opcode, walk_state); - walk_state->aml_offset = - (u32)ACPI_PTR_DIFF(walk_state->parser_state.aml, - walk_state->parser_state.aml_start); + walk_state->aml = walk_state->parser_state.aml; walk_state->opcode = acpi_ps_peek_opcode(&(walk_state->parser_state)); /* @@ -98,10 +97,14 @@ static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state) /* The opcode is unrecognized. Complain and skip unknown opcodes */ if (walk_state->pass_number == 2) { + aml_offset = (u32)ACPI_PTR_DIFF(walk_state->aml, + walk_state-> + parser_state.aml_start); + ACPI_ERROR((AE_INFO, "Unknown opcode 0x%.2X at table offset 0x%.4X, ignoring", walk_state->opcode, - (u32)(walk_state->aml_offset + + (u32)(aml_offset + sizeof(struct acpi_table_header)))); ACPI_DUMP_BUFFER((walk_state->parser_state.aml - 16), @@ -115,14 +118,14 @@ static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state) acpi_os_printf ("/*\nError: Unknown opcode 0x%.2X at table offset 0x%.4X, context:\n", walk_state->opcode, - (u32)(walk_state->aml_offset + + (u32)(aml_offset + sizeof(struct acpi_table_header))); /* Dump the context surrounding the invalid opcode */ acpi_ut_dump_buffer(((u8 *)walk_state->parser_state. aml - 16), 48, DB_BYTE_DISPLAY, - (walk_state->aml_offset + + (aml_offset + sizeof(struct acpi_table_header) - 16)); acpi_os_printf(" */\n"); @@ -294,7 +297,7 @@ acpi_ps_create_op(struct acpi_walk_state *walk_state, /* Create Op structure and append to parent's argument list */ walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode); - op = acpi_ps_alloc_op(walk_state->opcode); + op = acpi_ps_alloc_op(walk_state->opcode, aml_op_start); if (!op) { return_ACPI_STATUS(AE_NO_MEMORY); } diff --git a/kernel/drivers/acpi/acpica/psopinfo.c b/kernel/drivers/acpi/acpica/psopinfo.c index 20e1a3516..58310907f 100644 --- a/kernel/drivers/acpi/acpica/psopinfo.c +++ b/kernel/drivers/acpi/acpica/psopinfo.c @@ -50,9 +50,6 @@ #define _COMPONENT ACPI_PARSER ACPI_MODULE_NAME("psopinfo") -extern const u8 acpi_gbl_short_op_index[]; -extern const u8 acpi_gbl_long_op_index[]; - static const u8 acpi_gbl_argument_count[] = { 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 6 }; diff --git a/kernel/drivers/acpi/acpica/psparse.c b/kernel/drivers/acpi/acpica/psparse.c index a555f7f7b..98001d7f6 100644 --- a/kernel/drivers/acpi/acpica/psparse.c +++ b/kernel/drivers/acpi/acpica/psparse.c @@ -147,6 +147,8 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, return_ACPI_STATUS(AE_OK); /* OK for now */ } + acpi_ex_stop_trace_opcode(op, walk_state); + /* Delete this op and the subtree below it if asked to */ if (((walk_state->parse_flags & ACPI_PARSE_TREE_MASK) != @@ -185,7 +187,8 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, * op must be replaced by a placeholder return op */ replacement_op = - acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP); + acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP, + op->common.aml); if (!replacement_op) { status = AE_NO_MEMORY; } @@ -209,7 +212,8 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, || (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) { replacement_op = - acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP); + acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP, + op->common.aml); if (!replacement_op) { status = AE_NO_MEMORY; } @@ -224,7 +228,8 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, AML_VAR_PACKAGE_OP)) { replacement_op = acpi_ps_alloc_op(op->common. - aml_opcode); + aml_opcode, + op->common.aml); if (!replacement_op) { status = AE_NO_MEMORY; } else { @@ -240,7 +245,8 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, default: replacement_op = - acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP); + acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP, + op->common.aml); if (!replacement_op) { status = AE_NO_MEMORY; } diff --git a/kernel/drivers/acpi/acpica/pstree.c b/kernel/drivers/acpi/acpica/pstree.c index 89984f30a..cf2f2faf4 100644 --- a/kernel/drivers/acpi/acpica/pstree.c +++ b/kernel/drivers/acpi/acpica/pstree.c @@ -183,7 +183,6 @@ acpi_ps_append_arg(union acpi_parse_object *op, union acpi_parse_object *arg) } } -#ifdef ACPI_FUTURE_USAGE /******************************************************************************* * * FUNCTION: acpi_ps_get_depth_next @@ -317,4 +316,3 @@ union acpi_parse_object *acpi_ps_get_child(union acpi_parse_object *op) return (child); } #endif -#endif /* ACPI_FUTURE_USAGE */ diff --git a/kernel/drivers/acpi/acpica/psutils.c b/kernel/drivers/acpi/acpica/psutils.c index 960505ab4..71d2877cd 100644 --- a/kernel/drivers/acpi/acpica/psutils.c +++ b/kernel/drivers/acpi/acpica/psutils.c @@ -60,11 +60,11 @@ ACPI_MODULE_NAME("psutils") * DESCRIPTION: Create a Scope and associated namepath op with the root name * ******************************************************************************/ -union acpi_parse_object *acpi_ps_create_scope_op(void) +union acpi_parse_object *acpi_ps_create_scope_op(u8 *aml) { union acpi_parse_object *scope_op; - scope_op = acpi_ps_alloc_op(AML_SCOPE_OP); + scope_op = acpi_ps_alloc_op(AML_SCOPE_OP, aml); if (!scope_op) { return (NULL); } @@ -93,10 +93,9 @@ void acpi_ps_init_op(union acpi_parse_object *op, u16 opcode) op->common.descriptor_type = ACPI_DESC_TYPE_PARSER; op->common.aml_opcode = opcode; - ACPI_DISASM_ONLY_MEMBERS(ACPI_STRNCPY(op->common.aml_op_name, - (acpi_ps_get_opcode_info - (opcode))->name, - sizeof(op->common.aml_op_name))); + ACPI_DISASM_ONLY_MEMBERS(strncpy(op->common.aml_op_name, + (acpi_ps_get_opcode_info(opcode))-> + name, sizeof(op->common.aml_op_name))); } /******************************************************************************* @@ -104,6 +103,7 @@ void acpi_ps_init_op(union acpi_parse_object *op, u16 opcode) * FUNCTION: acpi_ps_alloc_op * * PARAMETERS: opcode - Opcode that will be stored in the new Op + * aml - Address of the opcode * * RETURN: Pointer to the new Op, null on failure * @@ -113,7 +113,7 @@ void acpi_ps_init_op(union acpi_parse_object *op, u16 opcode) * ******************************************************************************/ -union acpi_parse_object *acpi_ps_alloc_op(u16 opcode) +union acpi_parse_object *acpi_ps_alloc_op(u16 opcode, u8 *aml) { union acpi_parse_object *op; const struct acpi_opcode_info *op_info; @@ -150,6 +150,7 @@ union acpi_parse_object *acpi_ps_alloc_op(u16 opcode) if (op) { acpi_ps_init_op(op, opcode); + op->common.aml = aml; op->common.flags = flags; } @@ -204,7 +205,6 @@ u8 acpi_ps_is_leading_char(u32 c) /* * Get op's name (4-byte name segment) or 0 if unnamed */ -#ifdef ACPI_FUTURE_USAGE u32 acpi_ps_get_name(union acpi_parse_object * op) { @@ -218,7 +218,6 @@ u32 acpi_ps_get_name(union acpi_parse_object * op) return (op->named.name); } -#endif /* ACPI_FUTURE_USAGE */ /* * Set op's name diff --git a/kernel/drivers/acpi/acpica/psxface.c b/kernel/drivers/acpi/acpica/psxface.c index 841a5ea06..4254805dd 100644 --- a/kernel/drivers/acpi/acpica/psxface.c +++ b/kernel/drivers/acpi/acpica/psxface.c @@ -47,15 +47,12 @@ #include "acdispat.h" #include "acinterp.h" #include "actables.h" +#include "acnamesp.h" #define _COMPONENT ACPI_PARSER ACPI_MODULE_NAME("psxface") /* Local Prototypes */ -static void acpi_ps_start_trace(struct acpi_evaluate_info *info); - -static void acpi_ps_stop_trace(struct acpi_evaluate_info *info); - static void acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action); @@ -76,7 +73,7 @@ acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action); ******************************************************************************/ acpi_status -acpi_debug_trace(char *name, u32 debug_level, u32 debug_layer, u32 flags) +acpi_debug_trace(const char *name, u32 debug_level, u32 debug_layer, u32 flags) { acpi_status status; @@ -85,108 +82,14 @@ acpi_debug_trace(char *name, u32 debug_level, u32 debug_layer, u32 flags) return (status); } - /* TBDs: Validate name, allow full path or just nameseg */ - - acpi_gbl_trace_method_name = *ACPI_CAST_PTR(u32, name); + acpi_gbl_trace_method_name = name; acpi_gbl_trace_flags = flags; - - if (debug_level) { - acpi_gbl_trace_dbg_level = debug_level; - } - if (debug_layer) { - acpi_gbl_trace_dbg_layer = debug_layer; - } + acpi_gbl_trace_dbg_level = debug_level; + acpi_gbl_trace_dbg_layer = debug_layer; + status = AE_OK; (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_start_trace - * - * PARAMETERS: info - Method info struct - * - * RETURN: None - * - * DESCRIPTION: Start control method execution trace - * - ******************************************************************************/ - -static void acpi_ps_start_trace(struct acpi_evaluate_info *info) -{ - acpi_status status; - - ACPI_FUNCTION_ENTRY(); - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return; - } - - if ((!acpi_gbl_trace_method_name) || - (acpi_gbl_trace_method_name != info->node->name.integer)) { - goto exit; - } - - acpi_gbl_original_dbg_level = acpi_dbg_level; - acpi_gbl_original_dbg_layer = acpi_dbg_layer; - - acpi_dbg_level = 0x00FFFFFF; - acpi_dbg_layer = ACPI_UINT32_MAX; - - if (acpi_gbl_trace_dbg_level) { - acpi_dbg_level = acpi_gbl_trace_dbg_level; - } - if (acpi_gbl_trace_dbg_layer) { - acpi_dbg_layer = acpi_gbl_trace_dbg_layer; - } - -exit: - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ps_stop_trace - * - * PARAMETERS: info - Method info struct - * - * RETURN: None - * - * DESCRIPTION: Stop control method execution trace - * - ******************************************************************************/ - -static void acpi_ps_stop_trace(struct acpi_evaluate_info *info) -{ - acpi_status status; - - ACPI_FUNCTION_ENTRY(); - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - return; - } - - if ((!acpi_gbl_trace_method_name) || - (acpi_gbl_trace_method_name != info->node->name.integer)) { - goto exit; - } - - /* Disable further tracing if type is one-shot */ - - if (acpi_gbl_trace_flags & 1) { - acpi_gbl_trace_method_name = 0; - acpi_gbl_trace_dbg_level = 0; - acpi_gbl_trace_dbg_layer = 0; - } - - acpi_dbg_level = acpi_gbl_original_dbg_level; - acpi_dbg_layer = acpi_gbl_original_dbg_layer; - -exit: - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return (status); } /******************************************************************************* @@ -212,7 +115,7 @@ exit: * ******************************************************************************/ -acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) +acpi_status acpi_ps_execute_method(struct acpi_evaluate_info * info) { acpi_status status; union acpi_parse_object *op; @@ -243,10 +146,6 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) */ acpi_ps_update_parameter_list(info, REF_INCREMENT); - /* Begin tracing if requested */ - - acpi_ps_start_trace(info); - /* * Execute the method. Performs parse simultaneously */ @@ -256,7 +155,7 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) /* Create and init a Root Node */ - op = acpi_ps_create_scope_op(); + op = acpi_ps_create_scope_op(info->obj_desc->method.aml_start); if (!op) { status = AE_NO_MEMORY; goto cleanup; @@ -326,10 +225,6 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) cleanup: acpi_ps_delete_parse_tree(op); - /* End optional tracing */ - - acpi_ps_stop_trace(info); - /* Take away the extra reference that we gave the parameters above */ acpi_ps_update_parameter_list(info, REF_DECREMENT); diff --git a/kernel/drivers/acpi/acpica/rscreate.c b/kernel/drivers/acpi/acpica/rscreate.c index 15434e4c9..a5344428f 100644 --- a/kernel/drivers/acpi/acpica/rscreate.c +++ b/kernel/drivers/acpi/acpica/rscreate.c @@ -348,18 +348,19 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, status = acpi_ns_handle_to_pathname((acpi_handle) node, - &path_buffer); + &path_buffer, + FALSE); /* +1 to include null terminator */ user_prt->length += - (u32) ACPI_STRLEN(user_prt->source) + 1; + (u32)strlen(user_prt->source) + 1; break; case ACPI_TYPE_STRING: - ACPI_STRCPY(user_prt->source, - obj_desc->string.pointer); + strcpy(user_prt->source, + obj_desc->string.pointer); /* * Add to the Length field the length of the string diff --git a/kernel/drivers/acpi/acpica/rsdump.c b/kernel/drivers/acpi/acpica/rsdump.c index c428bb332..2a09288e7 100644 --- a/kernel/drivers/acpi/acpica/rsdump.c +++ b/kernel/drivers/acpi/acpica/rsdump.c @@ -51,7 +51,6 @@ ACPI_MODULE_NAME("rsdump") /* * All functions in this module are used by the AML Debugger only */ -#if defined(ACPI_DEBUGGER) /* Local prototypes */ static void acpi_rs_out_string(char *title, char *value); @@ -565,5 +564,3 @@ static void acpi_rs_dump_word_list(u16 length, u16 *data) acpi_os_printf("%25s%2.2X : %4.4X\n", "Word", i, data[i]); } } - -#endif diff --git a/kernel/drivers/acpi/acpica/rsmisc.c b/kernel/drivers/acpi/acpica/rsmisc.c index 1fe49d223..ac37852e0 100644 --- a/kernel/drivers/acpi/acpica/rsmisc.c +++ b/kernel/drivers/acpi/acpica/rsmisc.c @@ -119,7 +119,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, /* * Get the resource type and the initial (minimum) length */ - ACPI_MEMSET(resource, 0, INIT_RESOURCE_LENGTH(info)); + memset(resource, 0, INIT_RESOURCE_LENGTH(info)); resource->type = INIT_RESOURCE_TYPE(info); resource->length = INIT_RESOURCE_LENGTH(info); break; @@ -324,13 +324,13 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, case ACPI_RSC_SET8: - ACPI_MEMSET(destination, info->aml_offset, info->value); + memset(destination, info->aml_offset, info->value); break; case ACPI_RSC_DATA8: target = ACPI_ADD_PTR(char, resource, info->value); - ACPI_MEMCPY(destination, source, ACPI_GET16(target)); + memcpy(destination, source, ACPI_GET16(target)); break; case ACPI_RSC_ADDRESS: @@ -502,7 +502,7 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, switch (info->opcode) { case ACPI_RSC_INITSET: - ACPI_MEMSET(aml, 0, INIT_RESOURCE_LENGTH(info)); + memset(aml, 0, INIT_RESOURCE_LENGTH(info)); aml_length = INIT_RESOURCE_LENGTH(info); acpi_rs_set_resource_header(INIT_RESOURCE_TYPE(info), aml_length, aml); diff --git a/kernel/drivers/acpi/acpica/rsutils.c b/kernel/drivers/acpi/acpica/rsutils.c index ece3cd60c..9486992ed 100644 --- a/kernel/drivers/acpi/acpica/rsutils.c +++ b/kernel/drivers/acpi/acpica/rsutils.c @@ -148,7 +148,7 @@ acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type) case ACPI_RSC_MOVE_SERIAL_VEN: case ACPI_RSC_MOVE_SERIAL_RES: - ACPI_MEMCPY(destination, source, item_count); + memcpy(destination, source, item_count); return; /* @@ -364,12 +364,11 @@ acpi_rs_get_resource_source(acpi_rs_length resource_length, * Zero the entire area of the buffer. */ total_length = - (u32) - ACPI_STRLEN(ACPI_CAST_PTR(char, &aml_resource_source[1])) + + (u32)strlen(ACPI_CAST_PTR(char, &aml_resource_source[1])) + 1; - total_length = (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(total_length); + total_length = (u32)ACPI_ROUND_UP_TO_NATIVE_WORD(total_length); - ACPI_MEMSET(resource_source->string_ptr, 0, total_length); + memset(resource_source->string_ptr, 0, total_length); /* Copy the resource_source string to the destination */ @@ -432,8 +431,8 @@ acpi_rs_set_resource_source(union aml_resource * aml, /* Copy the resource_source string */ - ACPI_STRCPY(ACPI_CAST_PTR(char, &aml_resource_source[1]), - resource_source->string_ptr); + strcpy(ACPI_CAST_PTR(char, &aml_resource_source[1]), + resource_source->string_ptr); /* * Add the length of the string (+ 1 for null terminator) to the @@ -565,7 +564,6 @@ acpi_rs_get_crs_method_data(struct acpi_namespace_node *node, * ******************************************************************************/ -#ifdef ACPI_FUTURE_USAGE acpi_status acpi_rs_get_prs_method_data(struct acpi_namespace_node *node, struct acpi_buffer *ret_buffer) @@ -597,7 +595,6 @@ acpi_rs_get_prs_method_data(struct acpi_namespace_node *node, acpi_ut_remove_reference(obj_desc); return_ACPI_STATUS(status); } -#endif /* ACPI_FUTURE_USAGE */ /******************************************************************************* * diff --git a/kernel/drivers/acpi/acpica/rsxface.c b/kernel/drivers/acpi/acpica/rsxface.c index 8e6276df0..1e8cd5723 100644 --- a/kernel/drivers/acpi/acpica/rsxface.c +++ b/kernel/drivers/acpi/acpica/rsxface.c @@ -220,7 +220,7 @@ acpi_get_current_resources(acpi_handle device_handle, } ACPI_EXPORT_SYMBOL(acpi_get_current_resources) -#ifdef ACPI_FUTURE_USAGE + /******************************************************************************* * * FUNCTION: acpi_get_possible_resources @@ -262,7 +262,7 @@ acpi_get_possible_resources(acpi_handle device_handle, } ACPI_EXPORT_SYMBOL(acpi_get_possible_resources) -#endif /* ACPI_FUTURE_USAGE */ + /******************************************************************************* * * FUNCTION: acpi_set_current_resources @@ -398,8 +398,8 @@ acpi_resource_to_address64(struct acpi_resource *resource, /* Simple copy for 64 bit source */ - ACPI_MEMCPY(out, &resource->data, - sizeof(struct acpi_resource_address64)); + memcpy(out, &resource->data, + sizeof(struct acpi_resource_address64)); break; default: @@ -499,7 +499,7 @@ acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context) */ if ((vendor->byte_length < (ACPI_UUID_LENGTH + 1)) || (vendor->uuid_subtype != info->uuid->subtype) || - (ACPI_MEMCMP(vendor->uuid, info->uuid->data, ACPI_UUID_LENGTH))) { + (memcmp(vendor->uuid, info->uuid->data, ACPI_UUID_LENGTH))) { return (AE_OK); } @@ -513,7 +513,7 @@ acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context) /* Found the correct resource, copy and return it */ - ACPI_MEMCPY(buffer->pointer, resource, resource->length); + memcpy(buffer->pointer, resource, resource->length); buffer->length = resource->length; /* Found the desired descriptor, terminate resource walk */ diff --git a/kernel/drivers/acpi/acpica/tbdata.c b/kernel/drivers/acpi/acpica/tbdata.c index d7f838645..5c9d5abf1 100644 --- a/kernel/drivers/acpi/acpica/tbdata.c +++ b/kernel/drivers/acpi/acpica/tbdata.c @@ -73,7 +73,7 @@ acpi_tb_init_table_descriptor(struct acpi_table_desc *table_desc, * 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)); + memset(table_desc, 0, sizeof(struct acpi_table_desc)); table_desc->address = address; table_desc->length = table->length; table_desc->flags = flags; @@ -465,9 +465,9 @@ acpi_status acpi_tb_resize_root_table_list(void) /* 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)); + 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); diff --git a/kernel/drivers/acpi/acpica/tbfadt.c b/kernel/drivers/acpi/acpica/tbfadt.c index 05be59c77..a6454f4a6 100644 --- a/kernel/drivers/acpi/acpica/tbfadt.c +++ b/kernel/drivers/acpi/acpica/tbfadt.c @@ -298,7 +298,7 @@ acpi_tb_select_address(char *register_name, u32 address32, u64 address64) * * FUNCTION: acpi_tb_parse_fadt * - * PARAMETERS: table_index - Index for the FADT + * PARAMETERS: None * * RETURN: None * @@ -307,7 +307,7 @@ acpi_tb_select_address(char *register_name, u32 address32, u64 address64) * ******************************************************************************/ -void acpi_tb_parse_fadt(u32 table_index) +void acpi_tb_parse_fadt(void) { u32 length; struct acpi_table_header *table; @@ -319,11 +319,11 @@ void acpi_tb_parse_fadt(u32 table_index) * Get a local copy of the FADT and convert it to a common format * Map entire FADT, assumed to be smaller than one page. */ - length = acpi_gbl_root_table_list.tables[table_index].length; + length = acpi_gbl_root_table_list.tables[acpi_gbl_fadt_index].length; table = - acpi_os_map_memory(acpi_gbl_root_table_list.tables[table_index]. - address, length); + acpi_os_map_memory(acpi_gbl_root_table_list. + tables[acpi_gbl_fadt_index].address, length); if (!table) { return; } @@ -345,7 +345,7 @@ void acpi_tb_parse_fadt(u32 table_index) /* Obtain the DSDT and FACS tables via their addresses within the FADT */ acpi_tb_install_fixed_table((acpi_physical_address) acpi_gbl_FADT.Xdsdt, - ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT); + ACPI_SIG_DSDT, &acpi_gbl_dsdt_index); /* If Hardware Reduced flag is set, there is no FACS */ @@ -354,13 +354,13 @@ void acpi_tb_parse_fadt(u32 table_index) acpi_tb_install_fixed_table((acpi_physical_address) acpi_gbl_FADT.facs, ACPI_SIG_FACS, - ACPI_TABLE_INDEX_FACS); + &acpi_gbl_facs_index); } if (acpi_gbl_FADT.Xfacs) { acpi_tb_install_fixed_table((acpi_physical_address) acpi_gbl_FADT.Xfacs, ACPI_SIG_FACS, - ACPI_TABLE_INDEX_X_FACS); + &acpi_gbl_xfacs_index); } } } @@ -398,12 +398,12 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) /* Clear the entire local FADT */ - ACPI_MEMSET(&acpi_gbl_FADT, 0, sizeof(struct acpi_table_fadt)); + memset(&acpi_gbl_FADT, 0, sizeof(struct acpi_table_fadt)); /* Copy the original FADT, up to sizeof (struct acpi_table_fadt) */ - ACPI_MEMCPY(&acpi_gbl_FADT, table, - ACPI_MIN(length, sizeof(struct acpi_table_fadt))); + memcpy(&acpi_gbl_FADT, table, + ACPI_MIN(length, sizeof(struct acpi_table_fadt))); /* Take a copy of the Hardware Reduced flag */ diff --git a/kernel/drivers/acpi/acpica/tbfind.c b/kernel/drivers/acpi/acpica/tbfind.c index 0b879fcfe..405529d49 100644 --- a/kernel/drivers/acpi/acpica/tbfind.c +++ b/kernel/drivers/acpi/acpica/tbfind.c @@ -68,24 +68,37 @@ acpi_status acpi_tb_find_table(char *signature, char *oem_id, char *oem_table_id, u32 *table_index) { - u32 i; acpi_status status; struct acpi_table_header header; + u32 i; ACPI_FUNCTION_TRACE(tb_find_table); + /* Validate the input table signature */ + + if (!acpi_is_valid_signature(signature)) { + return_ACPI_STATUS(AE_BAD_SIGNATURE); + } + + /* Don't allow the OEM strings to be too long */ + + if ((strlen(oem_id) > ACPI_OEM_ID_SIZE) || + (strlen(oem_table_id) > ACPI_OEM_TABLE_ID_SIZE)) { + return_ACPI_STATUS(AE_AML_STRING_LIMIT); + } + /* Normalize the input strings */ - ACPI_MEMSET(&header, 0, sizeof(struct acpi_table_header)); + memset(&header, 0, sizeof(struct acpi_table_header)); ACPI_MOVE_NAME(header.signature, signature); - ACPI_STRNCPY(header.oem_id, oem_id, ACPI_OEM_ID_SIZE); - ACPI_STRNCPY(header.oem_table_id, oem_table_id, ACPI_OEM_TABLE_ID_SIZE); + strncpy(header.oem_id, oem_id, ACPI_OEM_ID_SIZE); + strncpy(header.oem_table_id, oem_table_id, ACPI_OEM_TABLE_ID_SIZE); /* Search for the table */ for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) { - if (ACPI_MEMCMP(&(acpi_gbl_root_table_list.tables[i].signature), - header.signature, ACPI_NAME_SIZE)) { + if (memcmp(&(acpi_gbl_root_table_list.tables[i].signature), + header.signature, ACPI_NAME_SIZE)) { /* Not the requested table */ @@ -112,21 +125,20 @@ acpi_tb_find_table(char *signature, /* Check for table match on all IDs */ - if (!ACPI_MEMCMP + if (!memcmp (acpi_gbl_root_table_list.tables[i].pointer->signature, header.signature, ACPI_NAME_SIZE) && (!oem_id[0] || - !ACPI_MEMCMP + !memcmp (acpi_gbl_root_table_list. tables[i].pointer-> oem_id, header.oem_id, ACPI_OEM_ID_SIZE)) && (!oem_table_id[0] - || !ACPI_MEMCMP(acpi_gbl_root_table_list.tables[i]. - pointer->oem_table_id, - header.oem_table_id, - ACPI_OEM_TABLE_ID_SIZE))) { + || !memcmp(acpi_gbl_root_table_list.tables[i].pointer-> + oem_table_id, header.oem_table_id, + ACPI_OEM_TABLE_ID_SIZE))) { *table_index = i; ACPI_DEBUG_PRINT((ACPI_DB_TABLES, diff --git a/kernel/drivers/acpi/acpica/tbinstal.c b/kernel/drivers/acpi/acpica/tbinstal.c index 008a25178..6319b4242 100644 --- a/kernel/drivers/acpi/acpica/tbinstal.c +++ b/kernel/drivers/acpi/acpica/tbinstal.c @@ -87,8 +87,8 @@ acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index) * not just the header. */ is_identical = (u8)((table_desc->length != table_length || - ACPI_MEMCMP(table_desc->pointer, table, - table_length)) ? FALSE : TRUE); + memcmp(table_desc->pointer, table, table_length)) ? + FALSE : TRUE); /* Release the acquired table */ @@ -100,9 +100,9 @@ acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index) * * FUNCTION: acpi_tb_install_table_with_override * - * PARAMETERS: table_index - Index into root table array - * new_table_desc - New table descriptor to install + * PARAMETERS: new_table_desc - New table descriptor to install * override - Whether override should be performed + * table_index - Where the table index is returned * * RETURN: None * @@ -114,12 +114,14 @@ acpi_tb_compare_tables(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) +acpi_tb_install_table_with_override(struct acpi_table_desc *new_table_desc, + u8 override, u32 *table_index) { + u32 i; + acpi_status status; - if (table_index >= acpi_gbl_root_table_list.current_table_count) { + status = acpi_tb_get_next_table_descriptor(&i, NULL); + if (ACPI_FAILURE(status)) { return; } @@ -134,8 +136,7 @@ acpi_tb_install_table_with_override(u32 table_index, acpi_tb_override_table(new_table_desc); } - acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list. - tables[table_index], + acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list.tables[i], new_table_desc->address, new_table_desc->flags, new_table_desc->pointer); @@ -143,9 +144,13 @@ acpi_tb_install_table_with_override(u32 table_index, acpi_tb_print_table_header(new_table_desc->address, new_table_desc->pointer); + /* This synchronizes acpi_gbl_dsdt_index */ + + *table_index = i; + /* Set the global integer width (based upon revision of the DSDT) */ - if (table_index == ACPI_TABLE_INDEX_DSDT) { + if (i == acpi_gbl_dsdt_index) { acpi_ut_set_integer_width(new_table_desc->pointer->revision); } } @@ -157,7 +162,7 @@ acpi_tb_install_table_with_override(u32 table_index, * PARAMETERS: address - Physical address of DSDT or FACS * signature - Table signature, NULL if no need to * match - * table_index - Index into root table array + * table_index - Where the table index is returned * * RETURN: Status * @@ -168,7 +173,7 @@ acpi_tb_install_table_with_override(u32 table_index, acpi_status acpi_tb_install_fixed_table(acpi_physical_address address, - char *signature, u32 table_index) + char *signature, u32 *table_index) { struct acpi_table_desc new_table_desc; acpi_status status; @@ -200,7 +205,9 @@ acpi_tb_install_fixed_table(acpi_physical_address address, goto release_and_exit; } - acpi_tb_install_table_with_override(table_index, &new_table_desc, TRUE); + /* Add the table to the global root table list */ + + acpi_tb_install_table_with_override(&new_table_desc, TRUE, table_index); release_and_exit: @@ -289,8 +296,7 @@ acpi_tb_install_standard_table(acpi_physical_address address, 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))) - { + && (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", @@ -356,13 +362,8 @@ acpi_tb_install_standard_table(acpi_physical_address address, /* Add the table to the global root table list */ - status = acpi_tb_get_next_table_descriptor(&i, NULL); - if (ACPI_FAILURE(status)) { - goto release_and_exit; - } - - *table_index = i; - acpi_tb_install_table_with_override(i, &new_table_desc, override); + acpi_tb_install_table_with_override(&new_table_desc, override, + table_index); release_and_exit: diff --git a/kernel/drivers/acpi/acpica/tbprint.c b/kernel/drivers/acpi/acpica/tbprint.c index 77ba5c71c..709d5112f 100644 --- a/kernel/drivers/acpi/acpica/tbprint.c +++ b/kernel/drivers/acpi/acpica/tbprint.c @@ -73,7 +73,7 @@ static void acpi_tb_fix_string(char *string, acpi_size length) { while (length && *string) { - if (!ACPI_IS_PRINT(*string)) { + if (!isprint((int)*string)) { *string = '?'; } string++; @@ -100,7 +100,7 @@ acpi_tb_cleanup_table_header(struct acpi_table_header *out_header, struct acpi_table_header *header) { - ACPI_MEMCPY(out_header, header, sizeof(struct acpi_table_header)); + memcpy(out_header, header, sizeof(struct acpi_table_header)); acpi_tb_fix_string(out_header->signature, ACPI_NAME_SIZE); acpi_tb_fix_string(out_header->oem_id, ACPI_OEM_ID_SIZE); @@ -138,9 +138,9 @@ acpi_tb_print_table_header(acpi_physical_address address, /* RSDP has no common fields */ - ACPI_MEMCPY(local_header.oem_id, - ACPI_CAST_PTR(struct acpi_table_rsdp, - header)->oem_id, ACPI_OEM_ID_SIZE); + memcpy(local_header.oem_id, + ACPI_CAST_PTR(struct acpi_table_rsdp, header)->oem_id, + ACPI_OEM_ID_SIZE); acpi_tb_fix_string(local_header.oem_id, ACPI_OEM_ID_SIZE); ACPI_INFO((AE_INFO, "RSDP 0x%8.8X%8.8X %06X (v%.2d %-6.6s)", diff --git a/kernel/drivers/acpi/acpica/tbutils.c b/kernel/drivers/acpi/acpica/tbutils.c index 2fb1afaac..d8ddef38c 100644 --- a/kernel/drivers/acpi/acpica/tbutils.c +++ b/kernel/drivers/acpi/acpica/tbutils.c @@ -68,58 +68,35 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size); acpi_status acpi_tb_initialize_facs(void) { - struct acpi_table_facs *facs32; - struct acpi_table_facs *facs64; + struct acpi_table_facs *facs; /* If Hardware Reduced flag is set, there is no FACS */ if (acpi_gbl_reduced_hardware) { acpi_gbl_FACS = NULL; return (AE_OK); + } else if (acpi_gbl_FADT.Xfacs && + (!acpi_gbl_FADT.facs + || !acpi_gbl_use32_bit_facs_addresses)) { + (void)acpi_get_table_by_index(acpi_gbl_xfacs_index, + ACPI_CAST_INDIRECT_PTR(struct + acpi_table_header, + &facs)); + acpi_gbl_FACS = facs; + } else if (acpi_gbl_FADT.facs) { + (void)acpi_get_table_by_index(acpi_gbl_facs_index, + ACPI_CAST_INDIRECT_PTR(struct + acpi_table_header, + &facs)); + acpi_gbl_FACS = facs; } - (void)acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, - ACPI_CAST_INDIRECT_PTR(struct - acpi_table_header, - &facs32)); - (void)acpi_get_table_by_index(ACPI_TABLE_INDEX_X_FACS, - ACPI_CAST_INDIRECT_PTR(struct - acpi_table_header, - &facs64)); - - if (acpi_gbl_use32_bit_facs_addresses) { - acpi_gbl_FACS = facs32 ? facs32 : facs64; - } else { - acpi_gbl_FACS = facs64 ? facs64 : facs32; - } + /* If there is no FACS, just continue. There was already an error msg */ return (AE_OK); } #endif /* !ACPI_REDUCED_HARDWARE */ -/******************************************************************************* - * - * FUNCTION: acpi_tb_tables_loaded - * - * PARAMETERS: None - * - * RETURN: TRUE if required ACPI tables are loaded - * - * DESCRIPTION: Determine if the minimum required ACPI tables are present - * (FADT, FACS, DSDT) - * - ******************************************************************************/ - -u8 acpi_tb_tables_loaded(void) -{ - - if (acpi_gbl_root_table_list.current_table_count >= 4) { - return (TRUE); - } - - return (FALSE); -} - /******************************************************************************* * * FUNCTION: acpi_tb_check_dsdt_header @@ -187,11 +164,11 @@ struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index) return (NULL); } - ACPI_MEMCPY(new_table, table_desc->pointer, table_desc->length); + memcpy(new_table, table_desc->pointer, table_desc->length); acpi_tb_uninstall_table(table_desc); acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list. - tables[ACPI_TABLE_INDEX_DSDT], + tables[acpi_gbl_dsdt_index], ACPI_PTR_TO_PHYSADDR(new_table), ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL, new_table); @@ -368,13 +345,6 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address) table_entry_size); table_entry = ACPI_ADD_PTR(u8, table, sizeof(struct acpi_table_header)); - /* - * First three entries in the table array are reserved for the DSDT - * and 32bit/64bit FACS, which are not actually present in the - * RSDT/XSDT - they come from the FADT - */ - acpi_gbl_root_table_list.current_table_count = 3; - /* Initialize the root table array from the RSDT/XSDT */ for (i = 0; i < table_count; i++) { @@ -399,7 +369,8 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address) ACPI_COMPARE_NAME(&acpi_gbl_root_table_list. tables[table_index].signature, ACPI_SIG_FADT)) { - acpi_tb_parse_fadt(table_index); + acpi_gbl_fadt_index = table_index; + acpi_tb_parse_fadt(); } next_table: @@ -411,3 +382,36 @@ next_table: return_ACPI_STATUS(AE_OK); } + +/******************************************************************************* + * + * FUNCTION: acpi_is_valid_signature + * + * PARAMETERS: signature - Sig string to be validated + * + * RETURN: TRUE if signature is correct length and has valid characters + * + * DESCRIPTION: Validate an ACPI table signature. + * + ******************************************************************************/ + +u8 acpi_is_valid_signature(char *signature) +{ + u32 i; + + /* Validate the signature length */ + + if (strlen(signature) != ACPI_NAME_SIZE) { + return (FALSE); + } + + /* Validate each character in the signature */ + + for (i = 0; i < ACPI_NAME_SIZE; i++) { + if (!acpi_ut_valid_acpi_char(signature[i], i)) { + return (FALSE); + } + } + + return (TRUE); +} diff --git a/kernel/drivers/acpi/acpica/tbxface.c b/kernel/drivers/acpi/acpica/tbxface.c index 60e94f87f..5559e2c70 100644 --- a/kernel/drivers/acpi/acpica/tbxface.c +++ b/kernel/drivers/acpi/acpica/tbxface.c @@ -119,9 +119,9 @@ acpi_initialize_tables(struct acpi_table_desc * initial_table_array, } else { /* Root Table Array has been statically allocated by the host */ - ACPI_MEMSET(initial_table_array, 0, - (acpi_size) initial_table_count * - sizeof(struct acpi_table_desc)); + memset(initial_table_array, 0, + (acpi_size) initial_table_count * + sizeof(struct acpi_table_desc)); acpi_gbl_root_table_list.tables = initial_table_array; acpi_gbl_root_table_list.max_table_count = initial_table_count; @@ -242,8 +242,9 @@ acpi_get_table_header(char *signature, if (!header) { return (AE_NO_MEMORY); } - ACPI_MEMCPY(out_table_header, header, - sizeof(struct acpi_table_header)); + + memcpy(out_table_header, header, + sizeof(struct acpi_table_header)); acpi_os_unmap_memory(header, sizeof(struct acpi_table_header)); @@ -251,9 +252,9 @@ acpi_get_table_header(char *signature, return (AE_NOT_FOUND); } } else { - ACPI_MEMCPY(out_table_header, - acpi_gbl_root_table_list.tables[i].pointer, - sizeof(struct acpi_table_header)); + memcpy(out_table_header, + acpi_gbl_root_table_list.tables[i].pointer, + sizeof(struct acpi_table_header)); } return (AE_OK); } diff --git a/kernel/drivers/acpi/acpica/tbxfload.c b/kernel/drivers/acpi/acpica/tbxfload.c index b63e35d6d..55ee14ca9 100644 --- a/kernel/drivers/acpi/acpica/tbxfload.c +++ b/kernel/drivers/acpi/acpica/tbxfload.c @@ -51,9 +51,6 @@ #define _COMPONENT ACPI_TABLES ACPI_MODULE_NAME("tbxfload") -/* Local prototypes */ -static acpi_status acpi_tb_load_namespace(void); - /******************************************************************************* * * FUNCTION: acpi_load_tables @@ -65,7 +62,6 @@ static acpi_status acpi_tb_load_namespace(void); * DESCRIPTION: Load the ACPI tables from the RSDT/XSDT * ******************************************************************************/ - acpi_status __init acpi_load_tables(void) { acpi_status status; @@ -75,6 +71,13 @@ acpi_status __init acpi_load_tables(void) /* Load the namespace from the tables */ status = acpi_tb_load_namespace(); + + /* Don't let single failures abort the load */ + + if (status == AE_CTRL_TERMINATE) { + status = AE_OK; + } + if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "While loading namespace from ACPI tables")); @@ -97,11 +100,14 @@ ACPI_EXPORT_SYMBOL_INIT(acpi_load_tables) * the RSDT/XSDT. * ******************************************************************************/ -static acpi_status acpi_tb_load_namespace(void) +acpi_status acpi_tb_load_namespace(void) { acpi_status status; u32 i; struct acpi_table_header *new_dsdt; + struct acpi_table_desc *table; + u32 tables_loaded = 0; + u32 tables_failed = 0; ACPI_FUNCTION_TRACE(tb_load_namespace); @@ -111,15 +117,11 @@ static acpi_status acpi_tb_load_namespace(void) * Load the namespace. The DSDT is required, but any SSDT and * PSDT tables are optional. Verify the DSDT. */ + table = &acpi_gbl_root_table_list.tables[acpi_gbl_dsdt_index]; + if (!acpi_gbl_root_table_list.current_table_count || - !ACPI_COMPARE_NAME(& - (acpi_gbl_root_table_list. - tables[ACPI_TABLE_INDEX_DSDT].signature), - ACPI_SIG_DSDT) - || - ACPI_FAILURE(acpi_tb_validate_table - (&acpi_gbl_root_table_list. - tables[ACPI_TABLE_INDEX_DSDT]))) { + !ACPI_COMPARE_NAME(table->signature.ascii, ACPI_SIG_DSDT) || + ACPI_FAILURE(acpi_tb_validate_table(table))) { status = AE_NO_ACPI_TABLES; goto unlock_and_exit; } @@ -130,8 +132,7 @@ static acpi_status acpi_tb_load_namespace(void) * array can change dynamically as tables are loaded at run-time. Note: * .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; + acpi_gbl_DSDT = table->pointer; /* * Optionally copy the entire DSDT to local memory (instead of simply @@ -140,7 +141,7 @@ static acpi_status acpi_tb_load_namespace(void) * the DSDT. */ if (acpi_gbl_copy_dsdt_locally) { - new_dsdt = acpi_tb_copy_dsdt(ACPI_TABLE_INDEX_DSDT); + new_dsdt = acpi_tb_copy_dsdt(acpi_gbl_dsdt_index); if (new_dsdt) { acpi_gbl_DSDT = new_dsdt; } @@ -150,44 +151,72 @@ static acpi_status acpi_tb_load_namespace(void) * Save the original DSDT header for detection of table corruption * and/or replacement of the DSDT from outside the OS. */ - ACPI_MEMCPY(&acpi_gbl_original_dsdt_header, acpi_gbl_DSDT, - sizeof(struct acpi_table_header)); + memcpy(&acpi_gbl_original_dsdt_header, acpi_gbl_DSDT, + sizeof(struct acpi_table_header)); (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); /* Load and parse tables */ - status = acpi_ns_load_table(ACPI_TABLE_INDEX_DSDT, acpi_gbl_root_node); + status = acpi_ns_load_table(acpi_gbl_dsdt_index, acpi_gbl_root_node); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + ACPI_EXCEPTION((AE_INFO, status, "[DSDT] table load failed")); + tables_failed++; + } else { + tables_loaded++; } /* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */ (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) { + table = &acpi_gbl_root_table_list.tables[i]; + if (!acpi_gbl_root_table_list.tables[i].address || - (!ACPI_COMPARE_NAME - (&(acpi_gbl_root_table_list.tables[i].signature), - ACPI_SIG_SSDT) - && - !ACPI_COMPARE_NAME(& - (acpi_gbl_root_table_list.tables[i]. - signature), ACPI_SIG_PSDT)) - || - ACPI_FAILURE(acpi_tb_validate_table - (&acpi_gbl_root_table_list.tables[i]))) { + (!ACPI_COMPARE_NAME(table->signature.ascii, ACPI_SIG_SSDT) + && !ACPI_COMPARE_NAME(table->signature.ascii, + ACPI_SIG_PSDT) + && !ACPI_COMPARE_NAME(table->signature.ascii, + ACPI_SIG_OSDT)) + || ACPI_FAILURE(acpi_tb_validate_table(table))) { continue; } /* Ignore errors while loading tables, get as many as possible */ (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - (void)acpi_ns_load_table(i, acpi_gbl_root_node); + status = acpi_ns_load_table(i, acpi_gbl_root_node); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "(%4.4s:%8.8s) while loading table", + table->signature.ascii, + table->pointer->oem_table_id)); + tables_failed++; + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, + "Table [%4.4s:%8.8s] (id FF) - Table namespace load failed\n\n", + table->signature.ascii, + table->pointer->oem_table_id)); + } else { + tables_loaded++; + } + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); } - ACPI_INFO((AE_INFO, "All ACPI Tables successfully acquired")); + if (!tables_failed) { + ACPI_INFO((AE_INFO, + "%u ACPI AML tables successfully acquired and loaded", + tables_loaded)); + } else { + ACPI_ERROR((AE_INFO, + "%u table load failures, %u successful", + tables_failed, tables_loaded)); + + /* Indicate at least one failure */ + + status = AE_CTRL_TERMINATE; + } unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); @@ -220,9 +249,9 @@ acpi_install_table(acpi_physical_address address, u8 physical) ACPI_FUNCTION_TRACE(acpi_install_table); if (physical) { - flags = ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL; - } else { flags = ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL; + } else { + flags = ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL; } status = acpi_tb_install_standard_table(address, flags, diff --git a/kernel/drivers/acpi/acpica/utalloc.c b/kernel/drivers/acpi/acpica/utalloc.c index 61d8f6d18..7a4101f06 100644 --- a/kernel/drivers/acpi/acpica/utalloc.c +++ b/kernel/drivers/acpi/acpica/utalloc.c @@ -73,7 +73,7 @@ void *acpi_os_allocate_zeroed(acpi_size size) /* Clear the memory block */ - ACPI_MEMSET(allocation, 0, size); + memset(allocation, 0, size); } return (allocation); @@ -181,7 +181,7 @@ acpi_status acpi_ut_delete_caches(void) char buffer[7]; if (acpi_gbl_display_final_mem_stats) { - ACPI_STRCPY(buffer, "MEMORY"); + strcpy(buffer, "MEMORY"); (void)acpi_db_display_statistics(buffer); } #endif @@ -337,6 +337,6 @@ acpi_ut_initialize_buffer(struct acpi_buffer * buffer, /* Have a valid buffer, clear it */ - ACPI_MEMSET(buffer->pointer, 0, required_length); + memset(buffer->pointer, 0, required_length); return (AE_OK); } diff --git a/kernel/drivers/acpi/acpica/utbuffer.c b/kernel/drivers/acpi/acpica/utbuffer.c index a8c39643e..01c8709ca 100644 --- a/kernel/drivers/acpi/acpica/utbuffer.c +++ b/kernel/drivers/acpi/acpica/utbuffer.c @@ -159,7 +159,7 @@ void acpi_ut_dump_buffer(u8 *buffer, u32 count, u32 display, u32 base_offset) } buf_char = buffer[(acpi_size) i + j]; - if (ACPI_IS_PRINT(buf_char)) { + if (isprint(buf_char)) { acpi_os_printf("%c", buf_char); } else { acpi_os_printf("."); @@ -319,7 +319,7 @@ acpi_ut_dump_buffer_to_file(ACPI_FILE file, } buf_char = buffer[(acpi_size) i + j]; - if (ACPI_IS_PRINT(buf_char)) { + if (isprint(buf_char)) { acpi_ut_file_printf(file, "%c", buf_char); } else { acpi_ut_file_printf(file, "."); diff --git a/kernel/drivers/acpi/acpica/utcache.c b/kernel/drivers/acpi/acpica/utcache.c index eacc5eee3..0d21fbd99 100644 --- a/kernel/drivers/acpi/acpica/utcache.c +++ b/kernel/drivers/acpi/acpica/utcache.c @@ -84,7 +84,7 @@ acpi_os_create_cache(char *cache_name, /* Populate the cache object and return it */ - ACPI_MEMSET(cache, 0, sizeof(struct acpi_memory_list)); + memset(cache, 0, sizeof(struct acpi_memory_list)); cache->list_name = cache_name; cache->object_size = object_size; cache->max_depth = max_depth; @@ -212,7 +212,7 @@ acpi_os_release_object(struct acpi_memory_list * cache, void *object) /* Mark the object as cached */ - ACPI_MEMSET(object, 0xCA, cache->object_size); + memset(object, 0xCA, cache->object_size); ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_CACHED); /* Put the object at the head of the cache list */ @@ -281,7 +281,7 @@ void *acpi_os_acquire_object(struct acpi_memory_list *cache) /* Clear (zero) the previously used Object */ - ACPI_MEMSET(object, 0, cache->object_size); + memset(object, 0, cache->object_size); } else { /* The cache is empty, create a new object */ diff --git a/kernel/drivers/acpi/acpica/utcopy.c b/kernel/drivers/acpi/acpica/utcopy.c index c37ec5035..257221d45 100644 --- a/kernel/drivers/acpi/acpica/utcopy.c +++ b/kernel/drivers/acpi/acpica/utcopy.c @@ -129,7 +129,7 @@ acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object, /* Always clear the external object */ - ACPI_MEMSET(external_object, 0, sizeof(union acpi_object)); + memset(external_object, 0, sizeof(union acpi_object)); /* * In general, the external object will be the same type as @@ -149,9 +149,9 @@ acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object, string. length + 1); - ACPI_MEMCPY((void *)data_space, - (void *)internal_object->string.pointer, - (acpi_size) internal_object->string.length + 1); + memcpy((void *)data_space, + (void *)internal_object->string.pointer, + (acpi_size) internal_object->string.length + 1); break; case ACPI_TYPE_BUFFER: @@ -162,9 +162,9 @@ acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object, ACPI_ROUND_UP_TO_NATIVE_WORD(internal_object->string. length); - ACPI_MEMCPY((void *)data_space, - (void *)internal_object->buffer.pointer, - internal_object->buffer.length); + memcpy((void *)data_space, + (void *)internal_object->buffer.pointer, + internal_object->buffer.length); break; case ACPI_TYPE_INTEGER: @@ -502,9 +502,9 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, goto error_exit; } - ACPI_MEMCPY(internal_object->string.pointer, - external_object->string.pointer, - external_object->string.length); + memcpy(internal_object->string.pointer, + external_object->string.pointer, + external_object->string.length); internal_object->string.length = external_object->string.length; break; @@ -517,9 +517,9 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, goto error_exit; } - ACPI_MEMCPY(internal_object->buffer.pointer, - external_object->buffer.pointer, - external_object->buffer.length); + memcpy(internal_object->buffer.pointer, + external_object->buffer.pointer, + external_object->buffer.length); internal_object->buffer.length = external_object->buffer.length; @@ -694,8 +694,8 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc, copy_size = sizeof(struct acpi_namespace_node); } - ACPI_MEMCPY(ACPI_CAST_PTR(char, dest_desc), - ACPI_CAST_PTR(char, source_desc), copy_size); + memcpy(ACPI_CAST_PTR(char, dest_desc), + ACPI_CAST_PTR(char, source_desc), copy_size); /* Restore the saved fields */ @@ -725,9 +725,9 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc, /* Copy the actual buffer data */ - ACPI_MEMCPY(dest_desc->buffer.pointer, - source_desc->buffer.pointer, - source_desc->buffer.length); + memcpy(dest_desc->buffer.pointer, + source_desc->buffer.pointer, + source_desc->buffer.length); } break; @@ -747,9 +747,9 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc, /* Copy the actual string data */ - ACPI_MEMCPY(dest_desc->string.pointer, - source_desc->string.pointer, - (acpi_size) source_desc->string.length + 1); + memcpy(dest_desc->string.pointer, + source_desc->string.pointer, + (acpi_size) source_desc->string.length + 1); } break; diff --git a/kernel/drivers/acpi/acpica/utdebug.c b/kernel/drivers/acpi/acpica/utdebug.c index 4f3f888d3..414622910 100644 --- a/kernel/drivers/acpi/acpica/utdebug.c +++ b/kernel/drivers/acpi/acpica/utdebug.c @@ -45,6 +45,7 @@ #include #include "accommon.h" +#include "acinterp.h" #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utdebug") @@ -111,8 +112,8 @@ void acpi_ut_track_stack_ptr(void) * RETURN: Updated pointer to the function name * * DESCRIPTION: Remove the "Acpi" prefix from the function name, if present. - * This allows compiler macros such as __func__ to be used with no - * change to the debug output. + * This allows compiler macros such as __func__ to be used + * with no change to the debug output. * ******************************************************************************/ @@ -560,8 +561,37 @@ acpi_ut_ptr_exit(u32 line_number, } } +/******************************************************************************* + * + * FUNCTION: acpi_trace_point + * + * PARAMETERS: type - Trace event type + * begin - TRUE if before execution + * aml - Executed AML address + * pathname - Object path + * pointer - Pointer to the related object + * + * RETURN: None + * + * DESCRIPTION: Interpreter execution trace. + * + ******************************************************************************/ + +void +acpi_trace_point(acpi_trace_event_type type, u8 begin, u8 *aml, char *pathname) +{ + + ACPI_FUNCTION_ENTRY(); + + acpi_ex_trace_point(type, begin, aml, pathname); + +#ifdef ACPI_USE_SYSTEM_TRACER + acpi_os_trace_point(type, begin, aml, pathname); #endif +} +ACPI_EXPORT_SYMBOL(acpi_trace_point) +#endif #ifdef ACPI_APPLICATION /******************************************************************************* * @@ -575,7 +605,6 @@ acpi_ut_ptr_exit(u32 line_number, * DESCRIPTION: Print error message to the console, used by applications. * ******************************************************************************/ - void ACPI_INTERNAL_VAR_XFACE acpi_log_error(const char *format, ...) { va_list args; diff --git a/kernel/drivers/acpi/acpica/utdecode.c b/kernel/drivers/acpi/acpica/utdecode.c index 988e23b77..ecaaaffc0 100644 --- a/kernel/drivers/acpi/acpica/utdecode.c +++ b/kernel/drivers/acpi/acpica/utdecode.c @@ -232,12 +232,27 @@ char *acpi_ut_get_type_name(acpi_object_type type) char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc) { + ACPI_FUNCTION_TRACE(ut_get_object_type_name); if (!obj_desc) { - return ("[NULL Object Descriptor]"); + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Null Object Descriptor\n")); + return_PTR("[NULL Object Descriptor]"); } - return (acpi_ut_get_type_name(obj_desc->common.type)); + /* These descriptor types share a common area */ + + if ((ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) && + (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_NAMED)) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Invalid object descriptor type: 0x%2.2X [%s] (%p)\n", + ACPI_GET_DESCRIPTOR_TYPE(obj_desc), + acpi_ut_get_descriptor_name(obj_desc), + obj_desc)); + + return_PTR("Invalid object"); + } + + return_PTR(acpi_ut_get_type_name(obj_desc->common.type)); } /******************************************************************************* @@ -407,8 +422,6 @@ static char *acpi_gbl_mutex_names[ACPI_NUM_MUTEX] = { "ACPI_MTX_Events", "ACPI_MTX_Caches", "ACPI_MTX_Memory", - "ACPI_MTX_CommandComplete", - "ACPI_MTX_CommandReady" }; char *acpi_ut_get_mutex_name(u32 mutex_id) diff --git a/kernel/drivers/acpi/acpica/utdelete.c b/kernel/drivers/acpi/acpica/utdelete.c index 71fce389f..1638312e3 100644 --- a/kernel/drivers/acpi/acpica/utdelete.c +++ b/kernel/drivers/acpi/acpica/utdelete.c @@ -209,6 +209,9 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) acpi_ut_delete_object_desc(object->method.mutex); object->method.mutex = NULL; } + if (object->method.node) { + object->method.node = NULL; + } break; case ACPI_TYPE_REGION: diff --git a/kernel/drivers/acpi/acpica/utfileio.c b/kernel/drivers/acpi/acpica/utfileio.c index 7e1168be3..d435b7b7e 100644 --- a/kernel/drivers/acpi/acpica/utfileio.c +++ b/kernel/drivers/acpi/acpica/utfileio.c @@ -45,6 +45,7 @@ #include "accommon.h" #include "actables.h" #include "acapps.h" +#include "errno.h" #ifdef ACPI_ASL_COMPILER #include "aslcompiler.h" @@ -198,11 +199,8 @@ acpi_ut_read_table(FILE * fp, table_header.length, file_size); #ifdef ACPI_ASL_COMPILER - status = fl_check_for_ascii(fp, NULL, FALSE); - if (ACPI_SUCCESS(status)) { - acpi_os_printf - ("File appears to be ASCII only, must be binary\n"); - } + acpi_os_printf("File is corrupt or is ASCII text -- " + "it must be a binary file\n"); #endif return (AE_BAD_HEADER); } @@ -304,6 +302,11 @@ acpi_ut_read_table_from_file(char *filename, struct acpi_table_header ** table) file = fopen(filename, "rb"); if (!file) { perror("Could not open input file"); + + if (errno == ENOENT) { + return (AE_NOT_EXIST); + } + return (status); } @@ -315,7 +318,7 @@ acpi_ut_read_table_from_file(char *filename, struct acpi_table_header ** table) /* Get the entire file */ fprintf(stderr, - "Loading Acpi table from file %10s - Length %.8u (%06X)\n", + "Reading ACPI table from file %12s - Length %.8u (0x%06X)\n", filename, file_size, file_size); status = acpi_ut_read_table(file, table, &table_length); diff --git a/kernel/drivers/acpi/acpica/utglobal.c b/kernel/drivers/acpi/acpica/utglobal.c index 5e8df9177..a72685c1e 100644 --- a/kernel/drivers/acpi/acpica/utglobal.c +++ b/kernel/drivers/acpi/acpica/utglobal.c @@ -102,12 +102,19 @@ const struct acpi_predefined_names acpi_gbl_pre_defined_names[] = { {"_SB_", ACPI_TYPE_DEVICE, NULL}, {"_SI_", ACPI_TYPE_LOCAL_SCOPE, NULL}, {"_TZ_", ACPI_TYPE_DEVICE, NULL}, - {"_REV", ACPI_TYPE_INTEGER, (char *)ACPI_CA_SUPPORT_LEVEL}, + /* + * March, 2015: + * The _REV object is in the process of being deprecated, because + * other ACPI implementations permanently return 2. Thus, it + * has little or no value. Return 2 for compatibility with + * other ACPI implementations. + */ + {"_REV", ACPI_TYPE_INTEGER, ACPI_CAST_PTR(char, 2)}, {"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME}, - {"_GL_", ACPI_TYPE_MUTEX, (char *)1}, + {"_GL_", ACPI_TYPE_MUTEX, ACPI_CAST_PTR(char, 1)}, #if !defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY) - {"_OSI", ACPI_TYPE_METHOD, (char *)1}, + {"_OSI", ACPI_TYPE_METHOD, ACPI_CAST_PTR(char, 1)}, #endif /* Table terminator */ diff --git a/kernel/drivers/acpi/acpica/uthex.c b/kernel/drivers/acpi/acpica/uthex.c index aa448278b..fda8b3def 100644 --- a/kernel/drivers/acpi/acpica/uthex.c +++ b/kernel/drivers/acpi/acpica/uthex.c @@ -75,9 +75,9 @@ char acpi_ut_hex_to_ascii_char(u64 integer, u32 position) /******************************************************************************* * - * FUNCTION: acpi_ut_hex_char_to_value + * FUNCTION: acpi_ut_ascii_char_to_hex * - * PARAMETERS: ascii_char - Hex character in Ascii + * PARAMETERS: hex_char - Hex character in Ascii * * RETURN: The binary value of the ascii/hex character * diff --git a/kernel/drivers/acpi/acpica/utids.c b/kernel/drivers/acpi/acpica/utids.c index 27431cfc1..7956df1e2 100644 --- a/kernel/drivers/acpi/acpica/utids.c +++ b/kernel/drivers/acpi/acpica/utids.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Module Name: utids - support for device Ids - HID, UID, CID + * Module Name: utids - support for device Ids - HID, UID, CID, SUB, CLS * *****************************************************************************/ @@ -111,7 +111,7 @@ acpi_ut_execute_HID(struct acpi_namespace_node *device_node, if (obj_desc->common.type == ACPI_TYPE_INTEGER) { acpi_ex_eisa_id_to_string(hid->string, obj_desc->integer.value); } else { - ACPI_STRCPY(hid->string, obj_desc->string.pointer); + strcpy(hid->string, obj_desc->string.pointer); } hid->length = length; @@ -180,7 +180,7 @@ acpi_ut_execute_SUB(struct acpi_namespace_node *device_node, /* Simply copy existing string */ - ACPI_STRCPY(sub->string, obj_desc->string.pointer); + strcpy(sub->string, obj_desc->string.pointer); sub->length = length; *return_id = sub; @@ -256,7 +256,7 @@ acpi_ut_execute_UID(struct acpi_namespace_node *device_node, if (obj_desc->common.type == ACPI_TYPE_INTEGER) { acpi_ex_integer_to_string(uid->string, obj_desc->integer.value); } else { - ACPI_STRCPY(uid->string, obj_desc->string.pointer); + strcpy(uid->string, obj_desc->string.pointer); } uid->length = length; @@ -393,8 +393,7 @@ acpi_ut_execute_CID(struct acpi_namespace_node *device_node, /* Copy the String CID from the returned object */ - ACPI_STRCPY(next_id_string, - cid_objects[i]->string.pointer); + strcpy(next_id_string, cid_objects[i]->string.pointer); length = cid_objects[i]->string.length + 1; } @@ -416,3 +415,92 @@ cleanup: acpi_ut_remove_reference(obj_desc); return_ACPI_STATUS(status); } + +/******************************************************************************* + * + * FUNCTION: acpi_ut_execute_CLS + * + * PARAMETERS: device_node - Node for the device + * return_id - Where the _CLS is returned + * + * RETURN: Status + * + * DESCRIPTION: Executes the _CLS control method that returns PCI-defined + * class code of the device. The _CLS value is always a package + * containing PCI class information as a list of integers. + * The returned string has format "BBSSPP", where: + * BB = Base-class code + * SS = Sub-class code + * PP = Programming Interface code + * + ******************************************************************************/ + +acpi_status +acpi_ut_execute_CLS(struct acpi_namespace_node *device_node, + struct acpi_pnp_device_id **return_id) +{ + union acpi_operand_object *obj_desc; + union acpi_operand_object **cls_objects; + u32 count; + struct acpi_pnp_device_id *cls; + u32 length; + acpi_status status; + u8 class_code[3] = { 0, 0, 0 }; + + ACPI_FUNCTION_TRACE(ut_execute_CLS); + + status = acpi_ut_evaluate_object(device_node, METHOD_NAME__CLS, + ACPI_BTYPE_PACKAGE, &obj_desc); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Get the size of the String to be returned, includes null terminator */ + + length = ACPI_PCICLS_STRING_SIZE; + cls_objects = obj_desc->package.elements; + count = obj_desc->package.count; + + if (obj_desc->common.type == ACPI_TYPE_PACKAGE) { + if (count > 0 + && cls_objects[0]->common.type == ACPI_TYPE_INTEGER) { + class_code[0] = (u8)cls_objects[0]->integer.value; + } + if (count > 1 + && cls_objects[1]->common.type == ACPI_TYPE_INTEGER) { + class_code[1] = (u8)cls_objects[1]->integer.value; + } + if (count > 2 + && cls_objects[2]->common.type == ACPI_TYPE_INTEGER) { + class_code[2] = (u8)cls_objects[2]->integer.value; + } + } + + /* Allocate a buffer for the CLS */ + + cls = + ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) + + (acpi_size) length); + if (!cls) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Area for the string starts after PNP_DEVICE_ID struct */ + + cls->string = + ACPI_ADD_PTR(char, cls, sizeof(struct acpi_pnp_device_id)); + + /* Simply copy existing string */ + + acpi_ex_pci_cls_to_string(cls->string, class_code); + cls->length = length; + *return_id = cls; + +cleanup: + + /* On exit, we must delete the return object */ + + acpi_ut_remove_reference(obj_desc); + return_ACPI_STATUS(status); +} diff --git a/kernel/drivers/acpi/acpica/utinit.c b/kernel/drivers/acpi/acpica/utinit.c index e402e07b4..ccd0745f0 100644 --- a/kernel/drivers/acpi/acpica/utinit.c +++ b/kernel/drivers/acpi/acpica/utinit.c @@ -204,11 +204,10 @@ 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_dbg_level = 0; - acpi_gbl_trace_dbg_layer = 0; acpi_gbl_debugger_configuration = DEBUGGER_THREADING; acpi_gbl_osi_mutex = NULL; acpi_gbl_reg_methods_executed = FALSE; + acpi_gbl_max_loop_iterations = 0xFFFF; /* Hardware oriented */ @@ -242,8 +241,6 @@ acpi_status acpi_ut_init_globals(void) acpi_gbl_disable_mem_tracking = FALSE; #endif - ACPI_DEBUGGER_EXEC(acpi_gbl_db_terminate_threads = FALSE); - return_ACPI_STATUS(AE_OK); } @@ -285,6 +282,19 @@ void acpi_ut_subsystem_shutdown(void) { ACPI_FUNCTION_TRACE(ut_subsystem_shutdown); + /* Just exit if subsystem is already shutdown */ + + if (acpi_gbl_shutdown) { + ACPI_ERROR((AE_INFO, "ACPI Subsystem is already terminated")); + return_VOID; + } + + /* Subsystem appears active, go ahead and shut it down */ + + acpi_gbl_shutdown = TRUE; + acpi_gbl_startup_flags = 0; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n")); + #ifndef ACPI_ASL_COMPILER /* Close the acpi_event Handling */ diff --git a/kernel/drivers/acpi/acpica/utmisc.c b/kernel/drivers/acpi/acpica/utmisc.c index cbb7034d2..bd4443bdc 100644 --- a/kernel/drivers/acpi/acpica/utmisc.c +++ b/kernel/drivers/acpi/acpica/utmisc.c @@ -66,16 +66,16 @@ u8 acpi_ut_is_pci_root_bridge(char *id) * Check if this is a PCI root bridge. * ACPI 3.0+: check for a PCI Express root also. */ - if (!(ACPI_STRCMP(id, - PCI_ROOT_HID_STRING)) || - !(ACPI_STRCMP(id, PCI_EXPRESS_ROOT_HID_STRING))) { + if (!(strcmp(id, + PCI_ROOT_HID_STRING)) || + !(strcmp(id, PCI_EXPRESS_ROOT_HID_STRING))) { return (TRUE); } return (FALSE); } -#if (defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP) +#if (defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP || defined ACPI_NAMES_APP) /******************************************************************************* * * FUNCTION: acpi_ut_is_aml_table @@ -97,7 +97,8 @@ u8 acpi_ut_is_aml_table(struct acpi_table_header *table) if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_DSDT) || ACPI_COMPARE_NAME(table->signature, ACPI_SIG_PSDT) || - ACPI_COMPARE_NAME(table->signature, ACPI_SIG_SSDT)) { + ACPI_COMPARE_NAME(table->signature, ACPI_SIG_SSDT) || + ACPI_COMPARE_NAME(table->signature, ACPI_SIG_OSDT)) { return (TRUE); } @@ -375,7 +376,7 @@ acpi_ut_display_init_pathname(u8 type, /* Get the full pathname to the node */ buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; - status = acpi_ns_handle_to_pathname(obj_handle, &buffer); + status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE); if (ACPI_FAILURE(status)) { return; } diff --git a/kernel/drivers/acpi/acpica/utmutex.c b/kernel/drivers/acpi/acpica/utmutex.c index 938795507..41a75eb3a 100644 --- a/kernel/drivers/acpi/acpica/utmutex.c +++ b/kernel/drivers/acpi/acpica/utmutex.c @@ -108,6 +108,21 @@ acpi_status acpi_ut_mutex_initialize(void) /* Create the reader/writer lock for namespace access */ status = acpi_ut_create_rw_lock(&acpi_gbl_namespace_rw_lock); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } +#ifdef ACPI_DEBUGGER + + /* Debugger Support */ + + status = acpi_os_create_mutex(&acpi_gbl_db_command_ready); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + status = acpi_os_create_mutex(&acpi_gbl_db_command_complete); +#endif + return_ACPI_STATUS(status); } @@ -147,6 +162,12 @@ void acpi_ut_mutex_terminate(void) /* Delete the reader/writer lock */ acpi_ut_delete_rw_lock(&acpi_gbl_namespace_rw_lock); + +#ifdef ACPI_DEBUGGER + acpi_os_delete_mutex(acpi_gbl_db_command_ready); + acpi_os_delete_mutex(acpi_gbl_db_command_complete); +#endif + return_VOID; } diff --git a/kernel/drivers/acpi/acpica/utnonansi.c b/kernel/drivers/acpi/acpica/utnonansi.c new file mode 100644 index 000000000..1d5f6b17b --- /dev/null +++ b/kernel/drivers/acpi/acpica/utnonansi.c @@ -0,0 +1,380 @@ +/******************************************************************************* + * + * Module Name: utnonansi - Non-ansi C library functions + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2015, 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 +#include "accommon.h" + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utnonansi") + +/* + * Non-ANSI C library functions - strlwr, strupr, stricmp, and a 64-bit + * version of strtoul. + */ +/******************************************************************************* + * + * FUNCTION: acpi_ut_strlwr (strlwr) + * + * PARAMETERS: src_string - The source string to convert + * + * RETURN: None + * + * DESCRIPTION: Convert a string to lowercase + * + ******************************************************************************/ +void acpi_ut_strlwr(char *src_string) +{ + char *string; + + ACPI_FUNCTION_ENTRY(); + + if (!src_string) { + return; + } + + /* Walk entire string, lowercasing the letters */ + + for (string = src_string; *string; string++) { + *string = (char)tolower((int)*string); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_strupr (strupr) + * + * PARAMETERS: src_string - The source string to convert + * + * RETURN: None + * + * DESCRIPTION: Convert a string to uppercase + * + ******************************************************************************/ + +void acpi_ut_strupr(char *src_string) +{ + char *string; + + ACPI_FUNCTION_ENTRY(); + + if (!src_string) { + return; + } + + /* Walk entire string, uppercasing the letters */ + + for (string = src_string; *string; string++) { + *string = (char)toupper((int)*string); + } +} + +/****************************************************************************** + * + * FUNCTION: acpi_ut_stricmp (stricmp) + * + * PARAMETERS: string1 - first string to compare + * string2 - second string to compare + * + * RETURN: int that signifies string relationship. Zero means strings + * are equal. + * + * DESCRIPTION: Case-insensitive string compare. Implementation of the + * non-ANSI stricmp function. + * + ******************************************************************************/ + +int acpi_ut_stricmp(char *string1, char *string2) +{ + int c1; + int c2; + + do { + c1 = tolower((int)*string1); + c2 = tolower((int)*string2); + + string1++; + string2++; + } + while ((c1 == c2) && (c1)); + + return (c1 - c2); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_strtoul64 + * + * PARAMETERS: string - Null terminated string + * base - Radix of the string: 16 or ACPI_ANY_BASE; + * ACPI_ANY_BASE means 'in behalf of to_integer' + * ret_integer - Where the converted integer is returned + * + * RETURN: Status and Converted value + * + * DESCRIPTION: Convert a string into an unsigned value. Performs either a + * 32-bit or 64-bit conversion, depending on the current mode + * of the interpreter. + * + * NOTE: Does not support Octal strings, not needed. + * + ******************************************************************************/ + +acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer) +{ + u32 this_digit = 0; + u64 return_value = 0; + u64 quotient; + u64 dividend; + u32 to_integer_op = (base == ACPI_ANY_BASE); + u32 mode32 = (acpi_gbl_integer_byte_width == 4); + u8 valid_digits = 0; + u8 sign_of0x = 0; + u8 term = 0; + + ACPI_FUNCTION_TRACE_STR(ut_stroul64, string); + + switch (base) { + case ACPI_ANY_BASE: + case 16: + + break; + + default: + + /* Invalid Base */ + + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (!string) { + goto error_exit; + } + + /* Skip over any white space in the buffer */ + + while ((*string) && (isspace((int)*string) || *string == '\t')) { + string++; + } + + if (to_integer_op) { + /* + * Base equal to ACPI_ANY_BASE means 'ToInteger operation case'. + * We need to determine if it is decimal or hexadecimal. + */ + if ((*string == '0') && (tolower((int)*(string + 1)) == 'x')) { + sign_of0x = 1; + base = 16; + + /* Skip over the leading '0x' */ + string += 2; + } else { + base = 10; + } + } + + /* Any string left? Check that '0x' is not followed by white space. */ + + if (!(*string) || isspace((int)*string) || *string == '\t') { + if (to_integer_op) { + goto error_exit; + } else { + goto all_done; + } + } + + /* + * Perform a 32-bit or 64-bit conversion, depending upon the current + * execution mode of the interpreter + */ + dividend = (mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX; + + /* Main loop: convert the string to a 32- or 64-bit integer */ + + while (*string) { + if (isdigit((int)*string)) { + + /* Convert ASCII 0-9 to Decimal value */ + + this_digit = ((u8)*string) - '0'; + } else if (base == 10) { + + /* Digit is out of range; possible in to_integer case only */ + + term = 1; + } else { + this_digit = (u8)toupper((int)*string); + if (isxdigit((int)this_digit)) { + + /* Convert ASCII Hex char to value */ + + this_digit = this_digit - 'A' + 10; + } else { + term = 1; + } + } + + if (term) { + if (to_integer_op) { + goto error_exit; + } else { + break; + } + } else if ((valid_digits == 0) && (this_digit == 0) + && !sign_of0x) { + + /* Skip zeros */ + string++; + continue; + } + + valid_digits++; + + if (sign_of0x + && ((valid_digits > 16) + || ((valid_digits > 8) && mode32))) { + /* + * This is to_integer operation case. + * No any restrictions for string-to-integer conversion, + * see ACPI spec. + */ + goto error_exit; + } + + /* Divide the digit into the correct position */ + + (void)acpi_ut_short_divide((dividend - (u64)this_digit), + base, "ient, NULL); + + if (return_value > quotient) { + if (to_integer_op) { + goto error_exit; + } else { + break; + } + } + + return_value *= base; + return_value += this_digit; + string++; + } + + /* All done, normal exit */ + +all_done: + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n", + ACPI_FORMAT_UINT64(return_value))); + + *ret_integer = return_value; + return_ACPI_STATUS(AE_OK); + +error_exit: + /* Base was set/validated above */ + + if (base == 10) { + return_ACPI_STATUS(AE_BAD_DECIMAL_CONSTANT); + } else { + return_ACPI_STATUS(AE_BAD_HEX_CONSTANT); + } +} + +#if defined (ACPI_DEBUGGER) || defined (ACPI_APPLICATION) +/******************************************************************************* + * + * FUNCTION: acpi_ut_safe_strcpy, acpi_ut_safe_strcat, acpi_ut_safe_strncat + * + * PARAMETERS: Adds a "DestSize" parameter to each of the standard string + * functions. This is the size of the Destination buffer. + * + * RETURN: TRUE if the operation would overflow the destination buffer. + * + * DESCRIPTION: Safe versions of standard Clib string functions. Ensure that + * the result of the operation will not overflow the output string + * buffer. + * + * NOTE: These functions are typically only helpful for processing + * user input and command lines. For most ACPICA code, the + * required buffer length is precisely calculated before buffer + * allocation, so the use of these functions is unnecessary. + * + ******************************************************************************/ + +u8 acpi_ut_safe_strcpy(char *dest, acpi_size dest_size, char *source) +{ + + if (strlen(source) >= dest_size) { + return (TRUE); + } + + strcpy(dest, source); + return (FALSE); +} + +u8 acpi_ut_safe_strcat(char *dest, acpi_size dest_size, char *source) +{ + + if ((strlen(dest) + strlen(source)) >= dest_size) { + return (TRUE); + } + + strcat(dest, source); + return (FALSE); +} + +u8 +acpi_ut_safe_strncat(char *dest, + acpi_size dest_size, + char *source, acpi_size max_transfer_length) +{ + acpi_size actual_transfer_length; + + actual_transfer_length = ACPI_MIN(max_transfer_length, strlen(source)); + + if ((strlen(dest) + actual_transfer_length) >= dest_size) { + return (TRUE); + } + + strncat(dest, source, max_transfer_length); + return (FALSE); +} +#endif diff --git a/kernel/drivers/acpi/acpica/utosi.c b/kernel/drivers/acpi/acpica/utosi.c index 44035abdb..8f3d203ae 100644 --- a/kernel/drivers/acpi/acpica/utosi.c +++ b/kernel/drivers/acpi/acpica/utosi.c @@ -232,8 +232,7 @@ acpi_status acpi_ut_install_interface(acpi_string interface_name) return (AE_NO_MEMORY); } - interface_info->name = - ACPI_ALLOCATE_ZEROED(ACPI_STRLEN(interface_name) + 1); + interface_info->name = ACPI_ALLOCATE_ZEROED(strlen(interface_name) + 1); if (!interface_info->name) { ACPI_FREE(interface_info); return (AE_NO_MEMORY); @@ -241,7 +240,7 @@ acpi_status acpi_ut_install_interface(acpi_string interface_name) /* Initialize new info and insert at the head of the global list */ - ACPI_STRCPY(interface_info->name, interface_name); + strcpy(interface_info->name, interface_name); interface_info->flags = ACPI_OSI_DYNAMIC; interface_info->next = acpi_gbl_supported_interfaces; @@ -269,7 +268,7 @@ acpi_status acpi_ut_remove_interface(acpi_string interface_name) previous_interface = next_interface = acpi_gbl_supported_interfaces; while (next_interface) { - if (!ACPI_STRCMP(interface_name, next_interface->name)) { + if (!strcmp(interface_name, next_interface->name)) { /* Found: name is in either the static list or was added at runtime */ @@ -373,7 +372,7 @@ struct acpi_interface_info *acpi_ut_get_interface(acpi_string interface_name) next_interface = acpi_gbl_supported_interfaces; while (next_interface) { - if (!ACPI_STRCMP(interface_name, next_interface->name)) { + if (!strcmp(interface_name, next_interface->name)) { return (next_interface); } diff --git a/kernel/drivers/acpi/acpica/utpredef.c b/kernel/drivers/acpi/acpica/utpredef.c index 29e449935..97898ed71 100644 --- a/kernel/drivers/acpi/acpica/utpredef.c +++ b/kernel/drivers/acpi/acpica/utpredef.c @@ -148,7 +148,7 @@ void acpi_ut_get_expected_return_types(char *buffer, u32 expected_btypes) u32 j; if (!expected_btypes) { - ACPI_STRCPY(buffer, "NONE"); + strcpy(buffer, "NONE"); return; } @@ -161,7 +161,7 @@ void acpi_ut_get_expected_return_types(char *buffer, u32 expected_btypes) /* If one of the expected types, concatenate the name of this type */ if (expected_btypes & this_rtype) { - ACPI_STRCAT(buffer, &ut_rtype_names[i][j]); + strcat(buffer, &ut_rtype_names[i][j]); j = 0; /* Use name separator from now on */ } diff --git a/kernel/drivers/acpi/acpica/utprint.c b/kernel/drivers/acpi/acpica/utprint.c index 2be6bd4bd..b26297c5d 100644 --- a/kernel/drivers/acpi/acpica/utprint.c +++ b/kernel/drivers/acpi/acpica/utprint.c @@ -180,7 +180,7 @@ const char *acpi_ut_scan_number(const char *string, u64 *number_ptr) { u64 number = 0; - while (ACPI_IS_DIGIT(*string)) { + while (isdigit((int)*string)) { number *= 10; number += *(string++) - '0'; } @@ -405,7 +405,7 @@ acpi_ut_vsnprintf(char *string, /* Process width */ width = -1; - if (ACPI_IS_DIGIT(*format)) { + if (isdigit((int)*format)) { format = acpi_ut_scan_number(format, &number); width = (s32) number; } else if (*format == '*') { @@ -422,7 +422,7 @@ acpi_ut_vsnprintf(char *string, precision = -1; if (*format == '.') { ++format; - if (ACPI_IS_DIGIT(*format)) { + if (isdigit((int)*format)) { format = acpi_ut_scan_number(format, &number); precision = (s32) number; } else if (*format == '*') { diff --git a/kernel/drivers/acpi/acpica/utstring.c b/kernel/drivers/acpi/acpica/utstring.c index 83b6c5249..4ddd105d9 100644 --- a/kernel/drivers/acpi/acpica/utstring.c +++ b/kernel/drivers/acpi/acpica/utstring.c @@ -48,286 +48,6 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utstring") -/* - * Non-ANSI C library functions - strlwr, strupr, stricmp, and a 64-bit - * version of strtoul. - */ -#ifdef ACPI_ASL_COMPILER -/******************************************************************************* - * - * FUNCTION: acpi_ut_strlwr (strlwr) - * - * PARAMETERS: src_string - The source string to convert - * - * RETURN: None - * - * DESCRIPTION: Convert string to lowercase - * - * NOTE: This is not a POSIX function, so it appears here, not in utclib.c - * - ******************************************************************************/ -void acpi_ut_strlwr(char *src_string) -{ - char *string; - - ACPI_FUNCTION_ENTRY(); - - if (!src_string) { - return; - } - - /* Walk entire string, lowercasing the letters */ - - for (string = src_string; *string; string++) { - *string = (char)ACPI_TOLOWER(*string); - } - - return; -} - -/****************************************************************************** - * - * FUNCTION: acpi_ut_stricmp (stricmp) - * - * PARAMETERS: string1 - first string to compare - * string2 - second string to compare - * - * RETURN: int that signifies string relationship. Zero means strings - * are equal. - * - * DESCRIPTION: Implementation of the non-ANSI stricmp function (compare - * strings with no case sensitivity) - * - ******************************************************************************/ - -int acpi_ut_stricmp(char *string1, char *string2) -{ - int c1; - int c2; - - do { - c1 = tolower((int)*string1); - c2 = tolower((int)*string2); - - string1++; - string2++; - } - while ((c1 == c2) && (c1)); - - return (c1 - c2); -} -#endif - -/******************************************************************************* - * - * FUNCTION: acpi_ut_strupr (strupr) - * - * PARAMETERS: src_string - The source string to convert - * - * RETURN: None - * - * DESCRIPTION: Convert string to uppercase - * - * NOTE: This is not a POSIX function, so it appears here, not in utclib.c - * - ******************************************************************************/ - -void acpi_ut_strupr(char *src_string) -{ - char *string; - - ACPI_FUNCTION_ENTRY(); - - if (!src_string) { - return; - } - - /* Walk entire string, uppercasing the letters */ - - for (string = src_string; *string; string++) { - *string = (char)ACPI_TOUPPER(*string); - } - - return; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_strtoul64 - * - * PARAMETERS: string - Null terminated string - * base - Radix of the string: 16 or ACPI_ANY_BASE; - * ACPI_ANY_BASE means 'in behalf of to_integer' - * ret_integer - Where the converted integer is returned - * - * RETURN: Status and Converted value - * - * DESCRIPTION: Convert a string into an unsigned value. Performs either a - * 32-bit or 64-bit conversion, depending on the current mode - * of the interpreter. - * NOTE: Does not support Octal strings, not needed. - * - ******************************************************************************/ - -acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer) -{ - u32 this_digit = 0; - u64 return_value = 0; - u64 quotient; - u64 dividend; - u32 to_integer_op = (base == ACPI_ANY_BASE); - u32 mode32 = (acpi_gbl_integer_byte_width == 4); - u8 valid_digits = 0; - u8 sign_of0x = 0; - u8 term = 0; - - ACPI_FUNCTION_TRACE_STR(ut_stroul64, string); - - switch (base) { - case ACPI_ANY_BASE: - case 16: - - break; - - default: - - /* Invalid Base */ - - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - - if (!string) { - goto error_exit; - } - - /* Skip over any white space in the buffer */ - - while ((*string) && (ACPI_IS_SPACE(*string) || *string == '\t')) { - string++; - } - - if (to_integer_op) { - /* - * Base equal to ACPI_ANY_BASE means 'ToInteger operation case'. - * We need to determine if it is decimal or hexadecimal. - */ - if ((*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) { - sign_of0x = 1; - base = 16; - - /* Skip over the leading '0x' */ - string += 2; - } else { - base = 10; - } - } - - /* Any string left? Check that '0x' is not followed by white space. */ - - if (!(*string) || ACPI_IS_SPACE(*string) || *string == '\t') { - if (to_integer_op) { - goto error_exit; - } else { - goto all_done; - } - } - - /* - * Perform a 32-bit or 64-bit conversion, depending upon the current - * execution mode of the interpreter - */ - dividend = (mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX; - - /* Main loop: convert the string to a 32- or 64-bit integer */ - - while (*string) { - if (ACPI_IS_DIGIT(*string)) { - - /* Convert ASCII 0-9 to Decimal value */ - - this_digit = ((u8)*string) - '0'; - } else if (base == 10) { - - /* Digit is out of range; possible in to_integer case only */ - - term = 1; - } else { - this_digit = (u8)ACPI_TOUPPER(*string); - if (ACPI_IS_XDIGIT((char)this_digit)) { - - /* Convert ASCII Hex char to value */ - - this_digit = this_digit - 'A' + 10; - } else { - term = 1; - } - } - - if (term) { - if (to_integer_op) { - goto error_exit; - } else { - break; - } - } else if ((valid_digits == 0) && (this_digit == 0) - && !sign_of0x) { - - /* Skip zeros */ - string++; - continue; - } - - valid_digits++; - - if (sign_of0x - && ((valid_digits > 16) - || ((valid_digits > 8) && mode32))) { - /* - * This is to_integer operation case. - * No any restrictions for string-to-integer conversion, - * see ACPI spec. - */ - goto error_exit; - } - - /* Divide the digit into the correct position */ - - (void)acpi_ut_short_divide((dividend - (u64)this_digit), - base, "ient, NULL); - - if (return_value > quotient) { - if (to_integer_op) { - goto error_exit; - } else { - break; - } - } - - return_value *= base; - return_value += this_digit; - string++; - } - - /* All done, normal exit */ - -all_done: - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n", - ACPI_FORMAT_UINT64(return_value))); - - *ret_integer = return_value; - return_ACPI_STATUS(AE_OK); - -error_exit: - /* Base was set/validated above */ - - if (base == 10) { - return_ACPI_STATUS(AE_BAD_DECIMAL_CONSTANT); - } else { - return_ACPI_STATUS(AE_BAD_HEX_CONSTANT); - } -} - /******************************************************************************* * * FUNCTION: acpi_ut_print_string @@ -342,7 +62,6 @@ error_exit: * sequences. * ******************************************************************************/ - void acpi_ut_print_string(char *string, u16 max_length) { u32 i; @@ -404,7 +123,7 @@ void acpi_ut_print_string(char *string, u16 max_length) /* Check for printable character or hex escape */ - if (ACPI_IS_PRINT(string[i])) { + if (isprint((int)string[i])) { /* This is a normal character */ acpi_os_printf("%c", (int)string[i]); @@ -584,65 +303,3 @@ void ut_convert_backslashes(char *pathname) } } #endif - -#if defined (ACPI_DEBUGGER) || defined (ACPI_APPLICATION) -/******************************************************************************* - * - * FUNCTION: acpi_ut_safe_strcpy, acpi_ut_safe_strcat, acpi_ut_safe_strncat - * - * PARAMETERS: Adds a "DestSize" parameter to each of the standard string - * functions. This is the size of the Destination buffer. - * - * RETURN: TRUE if the operation would overflow the destination buffer. - * - * DESCRIPTION: Safe versions of standard Clib string functions. Ensure that - * the result of the operation will not overflow the output string - * buffer. - * - * NOTE: These functions are typically only helpful for processing - * user input and command lines. For most ACPICA code, the - * required buffer length is precisely calculated before buffer - * allocation, so the use of these functions is unnecessary. - * - ******************************************************************************/ - -u8 acpi_ut_safe_strcpy(char *dest, acpi_size dest_size, char *source) -{ - - if (ACPI_STRLEN(source) >= dest_size) { - return (TRUE); - } - - ACPI_STRCPY(dest, source); - return (FALSE); -} - -u8 acpi_ut_safe_strcat(char *dest, acpi_size dest_size, char *source) -{ - - if ((ACPI_STRLEN(dest) + ACPI_STRLEN(source)) >= dest_size) { - return (TRUE); - } - - ACPI_STRCAT(dest, source); - return (FALSE); -} - -u8 -acpi_ut_safe_strncat(char *dest, - acpi_size dest_size, - char *source, acpi_size max_transfer_length) -{ - acpi_size actual_transfer_length; - - actual_transfer_length = - ACPI_MIN(max_transfer_length, ACPI_STRLEN(source)); - - if ((ACPI_STRLEN(dest) + actual_transfer_length) >= dest_size) { - return (TRUE); - } - - ACPI_STRNCAT(dest, source, max_transfer_length); - return (FALSE); -} -#endif diff --git a/kernel/drivers/acpi/acpica/uttrack.c b/kernel/drivers/acpi/acpica/uttrack.c index 130dd9f96..9a7dc8196 100644 --- a/kernel/drivers/acpi/acpica/uttrack.c +++ b/kernel/drivers/acpi/acpica/uttrack.c @@ -100,7 +100,7 @@ acpi_ut_create_list(char *list_name, return (AE_NO_MEMORY); } - ACPI_MEMSET(cache, 0, sizeof(struct acpi_memory_list)); + memset(cache, 0, sizeof(struct acpi_memory_list)); cache->list_name = list_name; cache->object_size = object_size; @@ -402,7 +402,7 @@ acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation, allocation->component = component; allocation->line = line; - ACPI_STRNCPY(allocation->module, module, ACPI_MAX_MODULE_NAME); + strncpy(allocation->module, module, ACPI_MAX_MODULE_NAME); allocation->module[ACPI_MAX_MODULE_NAME - 1] = 0; if (!element) { @@ -497,7 +497,7 @@ acpi_ut_remove_allocation(struct acpi_debug_mem_block *allocation, /* Mark the segment as deleted */ - ACPI_MEMSET(&allocation->user_space, 0xEA, allocation->size); + memset(&allocation->user_space, 0xEA, allocation->size); status = acpi_ut_release_mutex(ACPI_MTX_MEMORY); return (status); @@ -595,7 +595,7 @@ void acpi_ut_dump_allocations(u32 component, const char *module) while (element) { if ((element->component & component) && ((module == NULL) - || (0 == ACPI_STRCMP(module, element->module)))) { + || (0 == strcmp(module, element->module)))) { descriptor = ACPI_CAST_PTR(union acpi_descriptor, &element->user_space); diff --git a/kernel/drivers/acpi/acpica/utxface.c b/kernel/drivers/acpi/acpica/utxface.c index 0929187bd..f9c8f9ce1 100644 --- a/kernel/drivers/acpi/acpica/utxface.c +++ b/kernel/drivers/acpi/acpica/utxface.c @@ -67,23 +67,6 @@ acpi_status __init acpi_terminate(void) ACPI_FUNCTION_TRACE(acpi_terminate); - /* Just exit if subsystem is already shutdown */ - - if (acpi_gbl_shutdown) { - ACPI_ERROR((AE_INFO, "ACPI Subsystem is already terminated")); - return_ACPI_STATUS(AE_OK); - } - - /* Subsystem appears active, go ahead and shut it down */ - - acpi_gbl_shutdown = TRUE; - acpi_gbl_startup_flags = 0; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n")); - - /* Terminate the AML Debugger if present */ - - ACPI_DEBUGGER_EXEC(acpi_gbl_db_terminate_threads = TRUE); - /* Shutdown and free all resources */ acpi_ut_subsystem_shutdown(); @@ -92,13 +75,6 @@ acpi_status __init acpi_terminate(void) acpi_ut_mutex_terminate(); -#ifdef ACPI_DEBUGGER - - /* Shut down the debugger */ - - acpi_db_terminate(); -#endif - /* Now we can shutdown the OS-dependent layer */ status = acpi_os_terminate(); @@ -234,8 +210,8 @@ acpi_status acpi_get_statistics(struct acpi_statistics *stats) stats->sci_count = acpi_sci_count; stats->gpe_count = acpi_gpe_count; - ACPI_MEMCPY(stats->fixed_event_count, acpi_fixed_event_count, - sizeof(acpi_fixed_event_count)); + memcpy(stats->fixed_event_count, acpi_fixed_event_count, + sizeof(acpi_fixed_event_count)); /* Other counters */ @@ -277,7 +253,7 @@ acpi_install_initialization_handler(acpi_init_handler handler, u32 function) } ACPI_EXPORT_SYMBOL(acpi_install_initialization_handler) -#endif /* ACPI_FUTURE_USAGE */ +#endif /***************************************************************************** * @@ -322,7 +298,7 @@ acpi_status acpi_install_interface(acpi_string interface_name) /* Parameter validation */ - if (!interface_name || (ACPI_STRLEN(interface_name) == 0)) { + if (!interface_name || (strlen(interface_name) == 0)) { return (AE_BAD_PARAMETER); } @@ -374,7 +350,7 @@ acpi_status acpi_remove_interface(acpi_string interface_name) /* Parameter validation */ - if (!interface_name || (ACPI_STRLEN(interface_name) == 0)) { + if (!interface_name || (strlen(interface_name) == 0)) { return (AE_BAD_PARAMETER); } @@ -517,7 +493,8 @@ acpi_decode_pld_buffer(u8 *in_buffer, /* Parameter validation */ - if (!in_buffer || !return_buffer || (length < 16)) { + if (!in_buffer || !return_buffer + || (length < ACPI_PLD_REV1_BUFFER_SIZE)) { return (AE_BAD_PARAMETER); } @@ -567,7 +544,7 @@ acpi_decode_pld_buffer(u8 *in_buffer, pld_info->rotation = ACPI_PLD_GET_ROTATION(&dword); pld_info->order = ACPI_PLD_GET_ORDER(&dword); - if (length >= ACPI_PLD_BUFFER_SIZE) { + if (length >= ACPI_PLD_REV2_BUFFER_SIZE) { /* Fifth 32-bit DWord (Revision 2 of _PLD) */ diff --git a/kernel/drivers/acpi/acpica/utxferror.c b/kernel/drivers/acpi/acpica/utxferror.c index 306e785f9..98d578753 100644 --- a/kernel/drivers/acpi/acpica/utxferror.c +++ b/kernel/drivers/acpi/acpica/utxferror.c @@ -107,9 +107,16 @@ acpi_exception(const char *module_name, va_list arg_list; ACPI_MSG_REDIRECT_BEGIN; - acpi_os_printf(ACPI_MSG_EXCEPTION "%s, ", - acpi_format_exception(status)); + /* For AE_OK, just print the message */ + + if (ACPI_SUCCESS(status)) { + acpi_os_printf(ACPI_MSG_EXCEPTION); + + } else { + acpi_os_printf(ACPI_MSG_EXCEPTION "%s, ", + acpi_format_exception(status)); + } va_start(arg_list, format); acpi_os_vprintf(format, arg_list); ACPI_MSG_SUFFIX; diff --git a/kernel/drivers/acpi/acpica/utxfinit.c b/kernel/drivers/acpi/acpica/utxfinit.c index 42a32a66e..a7137ec28 100644 --- a/kernel/drivers/acpi/acpica/utxfinit.c +++ b/kernel/drivers/acpi/acpica/utxfinit.c @@ -124,17 +124,6 @@ acpi_status __init acpi_initialize_subsystem(void) return_ACPI_STATUS(status); } - /* If configured, initialize the AML debugger */ - -#ifdef ACPI_DEBUGGER - status = acpi_db_initialize(); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "During Debugger initialization")); - return_ACPI_STATUS(status); - } -#endif - return_ACPI_STATUS(AE_OK); } -- cgit 1.2.3-korg