diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-07-23 23:13:09 +0200 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-07-23 23:13:09 +0200 |
commit | 9c14cc44575ab7faae6bcb5821e6cad5f0d8238d (patch) | |
tree | 7480b5871c89b03b4fdd8c639241d664cbafab4a | |
parent | 9a3c4145af32125c5ee39c0272662b47307a8323 (diff) | |
parent | c12f07d17c12193256a99e20c9a0f130fb8f7be8 (diff) |
Merge branch 'acpica' into acpi-gpe
38 files changed, 3340 insertions, 404 deletions
diff --git a/drivers/acpi/acpi_extlog.c b/drivers/acpi/acpi_extlog.c index 185334114d7..340d09518f8 100644 --- a/drivers/acpi/acpi_extlog.c +++ b/drivers/acpi/acpi_extlog.c @@ -69,11 +69,11 @@ static u32 l1_percpu_entry; #define ELOG_ENTRY_ADDR(phyaddr) \ (phyaddr - elog_base + (u8 *)elog_addr) -static struct acpi_generic_status *extlog_elog_entry_check(int cpu, int bank) +static struct acpi_hest_generic_status *extlog_elog_entry_check(int cpu, int bank) { int idx; u64 data; - struct acpi_generic_status *estatus; + struct acpi_hest_generic_status *estatus; WARN_ON(cpu < 0); idx = ELOG_IDX(cpu, bank); @@ -82,7 +82,7 @@ static struct acpi_generic_status *extlog_elog_entry_check(int cpu, int bank) return NULL; data &= EXT_ELOG_ENTRY_MASK; - estatus = (struct acpi_generic_status *)ELOG_ENTRY_ADDR(data); + estatus = (struct acpi_hest_generic_status *)ELOG_ENTRY_ADDR(data); /* if no valid data in elog entry, just return */ if (estatus->block_status == 0) @@ -92,7 +92,7 @@ static struct acpi_generic_status *extlog_elog_entry_check(int cpu, int bank) } static void __print_extlog_rcd(const char *pfx, - struct acpi_generic_status *estatus, int cpu) + struct acpi_hest_generic_status *estatus, int cpu) { static atomic_t seqno; unsigned int curr_seqno; @@ -111,7 +111,7 @@ static void __print_extlog_rcd(const char *pfx, } static int print_extlog_rcd(const char *pfx, - struct acpi_generic_status *estatus, int cpu) + struct acpi_hest_generic_status *estatus, int cpu) { /* Not more than 2 messages every 5 seconds */ static DEFINE_RATELIMIT_STATE(ratelimit_corrected, 5*HZ, 2); @@ -137,7 +137,7 @@ static int extlog_print(struct notifier_block *nb, unsigned long val, struct mce *mce = (struct mce *)data; int bank = mce->bank; int cpu = mce->extcpu; - struct acpi_generic_status *estatus; + struct acpi_hest_generic_status *estatus; int rc; estatus = extlog_elog_entry_check(cpu, bank); @@ -148,7 +148,7 @@ static int extlog_print(struct notifier_block *nb, unsigned long val, /* clear record status to enable BIOS to update it again */ estatus->block_status = 0; - rc = print_extlog_rcd(NULL, (struct acpi_generic_status *)elog_buf, cpu); + rc = print_extlog_rcd(NULL, (struct acpi_hest_generic_status *)elog_buf, cpu); return NOTIFY_STOP; } diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index 8bb43f06e11..6b9ec239d57 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile @@ -175,5 +175,5 @@ acpi-y += \ utxferror.o \ utxfmutex.o -acpi-$(ACPI_FUTURE_USAGE) += uttrack.o utcache.o +acpi-$(ACPI_FUTURE_USAGE) += utfileio.o utprint.o uttrack.o utcache.o diff --git a/drivers/acpi/acpica/acapps.h b/drivers/acpi/acpica/acapps.h index 8698ffba6f3..3d2c88289da 100644 --- a/drivers/acpi/acpica/acapps.h +++ b/drivers/acpi/acpica/acapps.h @@ -79,10 +79,13 @@ /* Macros for usage messages */ #define ACPI_USAGE_HEADER(usage) \ - printf ("Usage: %s\nOptions:\n", usage); + acpi_os_printf ("Usage: %s\nOptions:\n", usage); + +#define ACPI_USAGE_TEXT(description) \ + acpi_os_printf (description); #define ACPI_OPTION(name, description) \ - printf (" %-18s%s\n", name, description); + acpi_os_printf (" %-18s%s\n", name, description); #define FILE_SUFFIX_DISASSEMBLY "dsl" #define ACPI_TABLE_FILE_SUFFIX ".dat" @@ -102,7 +105,7 @@ extern char *acpi_gbl_optarg; /* * cmfsize - Common get file size function */ -u32 cm_get_file_size(FILE * file); +u32 cm_get_file_size(ACPI_FILE file); #ifndef ACPI_DUMP_APP /* diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h index 68a91eb0fa4..1d026ff1683 100644 --- a/drivers/acpi/acpica/acdebug.h +++ b/drivers/acpi/acpica/acdebug.h @@ -233,9 +233,6 @@ 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_status -acpi_db_read_table_from_file(char *filename, struct acpi_table_header **table); - /* * dbhistry - debugger HISTORY command */ diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 115eedcade1..ebf02cc10a4 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -297,7 +297,7 @@ ACPI_GLOBAL(u32, acpi_gbl_trace_dbg_layer); * ****************************************************************************/ -ACPI_GLOBAL(u8, acpi_gbl_db_output_flags); +ACPI_INIT_GLOBAL(u8, acpi_gbl_db_output_flags, ACPI_DB_CONSOLE_OUTPUT); #ifdef ACPI_DISASSEMBLER @@ -362,6 +362,12 @@ ACPI_GLOBAL(u32, acpi_gbl_num_objects); #ifdef ACPI_APPLICATION ACPI_INIT_GLOBAL(ACPI_FILE, acpi_gbl_debug_file, NULL); +ACPI_INIT_GLOBAL(ACPI_FILE, acpi_gbl_output_file, NULL); + +/* Print buffer */ + +ACPI_GLOBAL(acpi_spinlock, acpi_gbl_print_lock); /* For print buffer */ +ACPI_GLOBAL(char, acpi_gbl_print_buffer[1024]); #endif /* ACPI_APPLICATION */ diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index 1e256c5bda2..ed614f4b218 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -95,7 +95,6 @@ extern const char *acpi_gbl_pt_decode[]; #ifdef ACPI_ASL_COMPILER #include <stdio.h> -extern FILE *acpi_gbl_output_file; #define ACPI_MSG_REDIRECT_BEGIN \ FILE *output_file = acpi_gbl_output_file; \ @@ -211,6 +210,8 @@ void acpi_ut_subsystem_shutdown(void); 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, @@ -257,7 +258,7 @@ extern const u8 _acpi_ctype[]; #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_SP | _ACPI_PU)) +#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 */ @@ -352,6 +353,13 @@ acpi_ut_debug_dump_buffer(u8 *buffer, u32 count, u32 display, u32 component_id); void acpi_ut_dump_buffer(u8 *buffer, u32 count, u32 display, u32 offset); +#ifdef ACPI_APPLICATION +void +acpi_ut_dump_buffer_to_file(ACPI_FILE file, + u8 *buffer, + u32 count, u32 display, u32 base_offset); +#endif + void acpi_ut_report_error(char *module_name, u32 line_number); void acpi_ut_report_info(char *module_name, u32 line_number); @@ -394,6 +402,14 @@ acpi_ut_execute_power_methods(struct acpi_namespace_node *device_node, u8 method_count, u8 *out_values); /* + * utfileio - file operations + */ +#ifdef ACPI_APPLICATION +acpi_status +acpi_ut_read_table_from_file(char *filename, struct acpi_table_header **table); +#endif + +/* * utids - device ID support */ acpi_status @@ -743,4 +759,23 @@ const struct ah_predefined_name *acpi_ah_match_predefined_name(char *nameseg); const struct ah_device_id *acpi_ah_match_hardware_id(char *hid); +/* + * utprint - printf/vprintf output functions + */ +const char *acpi_ut_scan_number(const char *string, u64 *number_ptr); + +const char *acpi_ut_print_number(char *string, u64 number); + +int +acpi_ut_vsnprintf(char *string, + acpi_size size, const char *format, va_list args); + +int acpi_ut_snprintf(char *string, acpi_size size, const char *format, ...); + +#ifdef ACPI_APPLICATION +int acpi_ut_file_vprintf(ACPI_FILE file, const char *format, va_list args); + +int acpi_ut_file_printf(ACPI_FILE file, const char *format, ...); +#endif + #endif /* _ACUTILS_H */ diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index 48f70013b48..e4ba4dec86a 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -698,21 +698,6 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, } /* - * If edge-triggered, clear the GPE status bit now. Note that - * level-triggered events are cleared after the GPE is serviced. - */ - if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == - ACPI_GPE_EDGE_TRIGGERED) { - status = acpi_hw_clear_gpe(gpe_event_info); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, - "Unable to clear GPE %02X", - gpe_number)); - return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); - } - } - - /* * Always disable the GPE so that it does not keep firing before * any asynchronous activity completes (either from the execution * of a GPE method or an asynchronous GPE handler.) @@ -729,6 +714,23 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, } /* + * If edge-triggered, clear the GPE status bit now. Note that + * level-triggered events are cleared after the GPE is serviced. + */ + if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == + ACPI_GPE_EDGE_TRIGGERED) { + status = acpi_hw_clear_gpe(gpe_event_info); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Unable to clear GPE %02X", + gpe_number)); + (void)acpi_hw_low_set_gpe(gpe_event_info, + ACPI_GPE_CONDITIONAL_ENABLE); + return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); + } + } + + /* * Dispatch the GPE to either an installed handler or the control * method associated with this GPE (_Lxx or _Exx). If a handler * exists, we invoke it and do not attempt to run the method. diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c index cb534faf536..0cf159cc6e6 100644 --- a/drivers/acpi/acpica/evxfgpe.c +++ b/drivers/acpi/acpica/evxfgpe.c @@ -126,11 +126,19 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); - /* Ensure that we have a valid GPE number */ - + /* + * Ensure that we have a valid GPE number and that there is some way + * of handling the GPE (handler or a GPE method). In other words, we + * won't allow a valid GPE to be enabled if there is no way to handle it. + */ gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); if (gpe_event_info) { - status = acpi_ev_add_gpe_reference(gpe_event_info); + if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) != + ACPI_GPE_DISPATCH_NONE) { + status = acpi_ev_add_gpe_reference(gpe_event_info); + } else { + status = AE_NO_HANDLER; + } } acpi_os_release_lock(acpi_gbl_gpe_lock, flags); @@ -179,6 +187,53 @@ ACPI_EXPORT_SYMBOL(acpi_disable_gpe) /******************************************************************************* * + * FUNCTION: acpi_mark_gpe_for_wake + * + * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 + * gpe_number - GPE level within the GPE block + * + * RETURN: Status + * + * DESCRIPTION: Mark a GPE as having the ability to wake the system. Simply + * sets the ACPI_GPE_CAN_WAKE flag. + * + * Some potential callers of acpi_setup_gpe_for_wake may know in advance that + * there won't be any notify handlers installed for device wake notifications + * from the given GPE (one example is a button GPE in Linux). For these cases, + * acpi_mark_gpe_for_wake should be used instead of acpi_setup_gpe_for_wake. + * This will set the ACPI_GPE_CAN_WAKE flag for the GPE without trying to + * setup implicit wake notification for it (since there's no handler method). + * + ******************************************************************************/ +acpi_status acpi_mark_gpe_for_wake(acpi_handle gpe_device, u32 gpe_number) +{ + struct acpi_gpe_event_info *gpe_event_info; + acpi_status status = AE_BAD_PARAMETER; + acpi_cpu_flags flags; + + ACPI_FUNCTION_TRACE(acpi_mark_gpe_for_wake); + + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + + /* Ensure that we have a valid GPE number */ + + gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); + if (gpe_event_info) { + + /* Mark the GPE as a possible wake event */ + + gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; + status = AE_OK; + } + + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_mark_gpe_for_wake) + +/******************************************************************************* + * * FUNCTION: acpi_setup_gpe_for_wake * * PARAMETERS: wake_device - Device associated with the GPE (via _PRW) diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c index 12878e1982f..1ff42c07b42 100644 --- a/drivers/acpi/acpica/exfield.c +++ b/drivers/acpi/acpica/exfield.c @@ -56,7 +56,7 @@ acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length); /******************************************************************************* * - * FUNCTION: acpi_get_serial_access_bytes + * FUNCTION: acpi_ex_get_serial_access_length * * PARAMETERS: accessor_type - The type of the protocol indicated by region * field access attributes @@ -103,7 +103,7 @@ acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length) case AML_FIELD_ATTRIB_BLOCK_CALL: default: - length = ACPI_GSBUS_BUFFER_SIZE; + length = ACPI_GSBUS_BUFFER_SIZE - 2; break; } diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index e0fd9b4978c..a4c34d2c556 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c @@ -278,8 +278,9 @@ acpi_status acpi_hw_clear_acpi_status(void) acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags); - if (ACPI_FAILURE(status)) + if (ACPI_FAILURE(status)) { goto exit; + } /* Clear the GPE Bits in all GPE registers in all GPE blocks */ diff --git a/drivers/acpi/acpica/nsobject.c b/drivers/acpi/acpica/nsobject.c index fe54a8c73b8..a42ee9d6970 100644 --- a/drivers/acpi/acpica/nsobject.c +++ b/drivers/acpi/acpica/nsobject.c @@ -237,6 +237,16 @@ void acpi_ns_detach_object(struct acpi_namespace_node *node) (node->object->common.type != ACPI_TYPE_LOCAL_DATA)) { node->object = node->object->common.next_object; } + + /* + * Detach the object from any data objects (which are still held by + * the namespace node) + */ + if (obj_desc->common.next_object && + ((obj_desc->common.next_object)->common.type == + ACPI_TYPE_LOCAL_DATA)) { + obj_desc->common.next_object = NULL; + } } /* Reset the node type to untyped */ diff --git a/drivers/acpi/acpica/utbuffer.c b/drivers/acpi/acpica/utbuffer.c index 3c169974065..038ea887f56 100644 --- a/drivers/acpi/acpica/utbuffer.c +++ b/drivers/acpi/acpica/utbuffer.c @@ -199,3 +199,131 @@ acpi_ut_debug_dump_buffer(u8 *buffer, u32 count, u32 display, u32 component_id) acpi_ut_dump_buffer(buffer, count, display, 0); } + +#ifdef ACPI_APPLICATION +/******************************************************************************* + * + * FUNCTION: acpi_ut_dump_buffer_to_file + * + * PARAMETERS: file - File descriptor + * buffer - Buffer to dump + * count - Amount to dump, in bytes + * display - BYTE, WORD, DWORD, or QWORD display: + * DB_BYTE_DISPLAY + * DB_WORD_DISPLAY + * DB_DWORD_DISPLAY + * DB_QWORD_DISPLAY + * base_offset - Beginning buffer offset (display only) + * + * RETURN: None + * + * DESCRIPTION: Generic dump buffer in both hex and ascii to a file. + * + ******************************************************************************/ + +void +acpi_ut_dump_buffer_to_file(ACPI_FILE file, + u8 *buffer, u32 count, u32 display, u32 base_offset) +{ + u32 i = 0; + u32 j; + u32 temp32; + u8 buf_char; + + if (!buffer) { + acpi_ut_file_printf(file, + "Null Buffer Pointer in DumpBuffer!\n"); + return; + } + + if ((count < 4) || (count & 0x01)) { + display = DB_BYTE_DISPLAY; + } + + /* Nasty little dump buffer routine! */ + + while (i < count) { + + /* Print current offset */ + + acpi_ut_file_printf(file, "%6.4X: ", (base_offset + i)); + + /* Print 16 hex chars */ + + for (j = 0; j < 16;) { + if (i + j >= count) { + + /* Dump fill spaces */ + + acpi_ut_file_printf(file, "%*s", + ((display * 2) + 1), " "); + j += display; + continue; + } + + switch (display) { + case DB_BYTE_DISPLAY: + default: /* Default is BYTE display */ + + acpi_ut_file_printf(file, "%02X ", + buffer[(acpi_size) i + j]); + break; + + case DB_WORD_DISPLAY: + + ACPI_MOVE_16_TO_32(&temp32, + &buffer[(acpi_size) i + j]); + acpi_ut_file_printf(file, "%04X ", temp32); + break; + + case DB_DWORD_DISPLAY: + + ACPI_MOVE_32_TO_32(&temp32, + &buffer[(acpi_size) i + j]); + acpi_ut_file_printf(file, "%08X ", temp32); + break; + + case DB_QWORD_DISPLAY: + + ACPI_MOVE_32_TO_32(&temp32, + &buffer[(acpi_size) i + j]); + acpi_ut_file_printf(file, "%08X", temp32); + + ACPI_MOVE_32_TO_32(&temp32, + &buffer[(acpi_size) i + j + + 4]); + acpi_ut_file_printf(file, "%08X ", temp32); + break; + } + + j += display; + } + + /* + * Print the ASCII equivalent characters but watch out for the bad + * unprintable ones (printable chars are 0x20 through 0x7E) + */ + acpi_ut_file_printf(file, " "); + for (j = 0; j < 16; j++) { + if (i + j >= count) { + acpi_ut_file_printf(file, "\n"); + return; + } + + buf_char = buffer[(acpi_size) i + j]; + if (ACPI_IS_PRINT(buf_char)) { + acpi_ut_file_printf(file, "%c", buf_char); + } else { + acpi_ut_file_printf(file, "."); + } + } + + /* Done with that line. */ + + acpi_ut_file_printf(file, "\n"); + i += 16; + } + + return; +} +#endif diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c index 270c16464dd..ff601c0f7c7 100644 --- a/drivers/acpi/acpica/utcopy.c +++ b/drivers/acpi/acpica/utcopy.c @@ -1001,5 +1001,11 @@ acpi_ut_copy_iobject_to_iobject(union acpi_operand_object *source_desc, status = acpi_ut_copy_simple_object(source_desc, *dest_desc); } + /* Delete the allocated object if copy failed */ + + if (ACPI_FAILURE(status)) { + acpi_ut_remove_reference(*dest_desc); + } + return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c index 21a20ac5b1e..e516254c63b 100644 --- a/drivers/acpi/acpica/utdebug.c +++ b/drivers/acpi/acpica/utdebug.c @@ -561,3 +561,29 @@ acpi_ut_ptr_exit(u32 line_number, } #endif + +#ifdef ACPI_APPLICATION +/******************************************************************************* + * + * FUNCTION: acpi_log_error + * + * PARAMETERS: format - Printf format field + * ... - Optional printf arguments + * + * RETURN: None + * + * DESCRIPTION: Print error message to the console, used by applications. + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE acpi_log_error(const char *format, ...) +{ + va_list args; + + va_start(args, format); + (void)acpi_ut_file_vprintf(ACPI_FILE_ERR, format, args); + va_end(args); +} + +ACPI_EXPORT_SYMBOL(acpi_log_error) +#endif diff --git a/drivers/acpi/acpica/utfileio.c b/drivers/acpi/acpica/utfileio.c new file mode 100644 index 00000000000..bdf9914733c --- /dev/null +++ b/drivers/acpi/acpica/utfileio.c @@ -0,0 +1,332 @@ +/******************************************************************************* + * + * Module Name: utfileio - simple file I/O routines + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" +#include "actables.h" +#include "acapps.h" + +#ifdef ACPI_ASL_COMPILER +#include "aslcompiler.h" +#endif + +#define _COMPONENT ACPI_CA_DEBUGGER +ACPI_MODULE_NAME("utfileio") + +#ifdef ACPI_APPLICATION +/* Local prototypes */ +static acpi_status +acpi_ut_check_text_mode_corruption(u8 *table, + u32 table_length, u32 file_length); + +static acpi_status +acpi_ut_read_table(FILE * fp, + struct acpi_table_header **table, u32 *table_length); + +/******************************************************************************* + * + * FUNCTION: acpi_ut_check_text_mode_corruption + * + * PARAMETERS: table - Table buffer + * table_length - Length of table from the table header + * file_length - Length of the file that contains the table + * + * RETURN: Status + * + * DESCRIPTION: Check table for text mode file corruption where all linefeed + * characters (LF) have been replaced by carriage return linefeed + * pairs (CR/LF). + * + ******************************************************************************/ + +static acpi_status +acpi_ut_check_text_mode_corruption(u8 *table, u32 table_length, u32 file_length) +{ + u32 i; + u32 pairs = 0; + + if (table_length != file_length) { + ACPI_WARNING((AE_INFO, + "File length (0x%X) is not the same as the table length (0x%X)", + file_length, table_length)); + } + + /* Scan entire table to determine if each LF has been prefixed with a CR */ + + for (i = 1; i < file_length; i++) { + if (table[i] == 0x0A) { + if (table[i - 1] != 0x0D) { + + /* The LF does not have a preceding CR, table not corrupted */ + + return (AE_OK); + } else { + /* Found a CR/LF pair */ + + pairs++; + } + i++; + } + } + + if (!pairs) { + return (AE_OK); + } + + /* + * Entire table scanned, each CR is part of a CR/LF pair -- + * meaning that the table was treated as a text file somewhere. + * + * NOTE: We can't "fix" the table, because any existing CR/LF pairs in the + * original table are left untouched by the text conversion process -- + * meaning that we cannot simply replace CR/LF pairs with LFs. + */ + acpi_os_printf("Table has been corrupted by text mode conversion\n"); + acpi_os_printf("All LFs (%u) were changed to CR/LF pairs\n", pairs); + acpi_os_printf("Table cannot be repaired!\n"); + return (AE_BAD_VALUE); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_read_table + * + * PARAMETERS: fp - File that contains table + * table - Return value, buffer with table + * table_length - Return value, length of table + * + * RETURN: Status + * + * DESCRIPTION: Load the DSDT from the file pointer + * + ******************************************************************************/ + +static acpi_status +acpi_ut_read_table(FILE * fp, + struct acpi_table_header **table, u32 *table_length) +{ + struct acpi_table_header table_header; + u32 actual; + acpi_status status; + u32 file_size; + u8 standard_header = TRUE; + s32 count; + + /* Get the file size */ + + file_size = cm_get_file_size(fp); + if (file_size == ACPI_UINT32_MAX) { + return (AE_ERROR); + } + + if (file_size < 4) { + return (AE_BAD_HEADER); + } + + /* Read the signature */ + + fseek(fp, 0, SEEK_SET); + + count = fread(&table_header, 1, sizeof(struct acpi_table_header), fp); + if (count != sizeof(struct acpi_table_header)) { + acpi_os_printf("Could not read the table header\n"); + return (AE_BAD_HEADER); + } + + /* The RSDP table does not have standard ACPI header */ + + if (ACPI_VALIDATE_RSDP_SIG(table_header.signature)) { + *table_length = file_size; + standard_header = FALSE; + } else { + +#if 0 + /* Validate the table header/length */ + + status = acpi_tb_validate_table_header(&table_header); + if (ACPI_FAILURE(status)) { + acpi_os_printf("Table header is invalid!\n"); + return (status); + } +#endif + + /* File size must be at least as long as the Header-specified length */ + + if (table_header.length > file_size) { + acpi_os_printf + ("TableHeader length [0x%X] greater than the input file size [0x%X]\n", + 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", + table_header.length, file_size); + } +#endif + return (AE_BAD_HEADER); + } +#ifdef ACPI_OBSOLETE_CODE + /* We only support a limited number of table types */ + + if (!ACPI_COMPARE_NAME + ((char *)table_header.signature, ACPI_SIG_DSDT) + && !ACPI_COMPARE_NAME((char *)table_header.signature, + ACPI_SIG_PSDT) + && !ACPI_COMPARE_NAME((char *)table_header.signature, + ACPI_SIG_SSDT)) { + acpi_os_printf + ("Table signature [%4.4s] is invalid or not supported\n", + (char *)table_header.signature); + ACPI_DUMP_BUFFER(&table_header, + sizeof(struct acpi_table_header)); + return (AE_ERROR); + } +#endif + + *table_length = table_header.length; + } + + /* Allocate a buffer for the table */ + + *table = acpi_os_allocate((size_t) file_size); + if (!*table) { + acpi_os_printf + ("Could not allocate memory for ACPI table %4.4s (size=0x%X)\n", + table_header.signature, *table_length); + return (AE_NO_MEMORY); + } + + /* Get the rest of the table */ + + fseek(fp, 0, SEEK_SET); + actual = fread(*table, 1, (size_t) file_size, fp); + if (actual == file_size) { + if (standard_header) { + + /* Now validate the checksum */ + + status = acpi_tb_verify_checksum((void *)*table, + ACPI_CAST_PTR(struct + acpi_table_header, + *table)-> + length); + + if (status == AE_BAD_CHECKSUM) { + status = + acpi_ut_check_text_mode_corruption((u8 *) + *table, + file_size, + (*table)-> + length); + return (status); + } + } + return (AE_OK); + } + + if (actual > 0) { + acpi_os_printf("Warning - reading table, asked for %X got %X\n", + file_size, actual); + return (AE_OK); + } + + acpi_os_printf("Error - could not read the table file\n"); + acpi_os_free(*table); + *table = NULL; + *table_length = 0; + return (AE_ERROR); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_read_table_from_file + * + * PARAMETERS: filename - File where table is located + * table - Where a pointer to the table is returned + * + * RETURN: Status + * + * DESCRIPTION: Get an ACPI table from a file + * + ******************************************************************************/ + +acpi_status +acpi_ut_read_table_from_file(char *filename, struct acpi_table_header ** table) +{ + FILE *file; + u32 file_size; + u32 table_length; + acpi_status status = AE_ERROR; + + /* Open the file, get current size */ + + file = fopen(filename, "rb"); + if (!file) { + perror("Could not open input file"); + return (status); + } + + file_size = cm_get_file_size(file); + if (file_size == ACPI_UINT32_MAX) { + goto exit; + } + + /* Get the entire file */ + + fprintf(stderr, + "Loading Acpi table from file %10s - Length %.8u (%06X)\n", + filename, file_size, file_size); + + status = acpi_ut_read_table(file, table, &table_length); + if (ACPI_FAILURE(status)) { + acpi_os_printf("Could not get table from the file\n"); + } + +exit: + fclose(file); + return (status); +} + +#endif diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index d69be3cb3fa..77ceac715f2 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -214,152 +214,6 @@ struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS] = }; #endif /* !ACPI_REDUCED_HARDWARE */ -/******************************************************************************* - * - * FUNCTION: acpi_ut_init_globals - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Initialize ACPICA globals. All globals that require specific - * initialization should be initialized here. This allows for - * a warm restart. - * - ******************************************************************************/ - -acpi_status acpi_ut_init_globals(void) -{ - acpi_status status; - u32 i; - - ACPI_FUNCTION_TRACE(ut_init_globals); - - /* Create all memory caches */ - - status = acpi_ut_create_caches(); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Address Range lists */ - - for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) { - acpi_gbl_address_range_list[i] = NULL; - } - - /* Mutex locked flags */ - - for (i = 0; i < ACPI_NUM_MUTEX; i++) { - acpi_gbl_mutex_info[i].mutex = NULL; - acpi_gbl_mutex_info[i].thread_id = ACPI_MUTEX_NOT_ACQUIRED; - acpi_gbl_mutex_info[i].use_count = 0; - } - - for (i = 0; i < ACPI_NUM_OWNERID_MASKS; i++) { - acpi_gbl_owner_id_mask[i] = 0; - } - - /* Last owner_ID is never valid */ - - acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS - 1] = 0x80000000; - - /* Event counters */ - - acpi_method_count = 0; - acpi_sci_count = 0; - acpi_gpe_count = 0; - - for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { - acpi_fixed_event_count[i] = 0; - } - -#if (!ACPI_REDUCED_HARDWARE) - - /* GPE/SCI support */ - - acpi_gbl_all_gpes_initialized = FALSE; - acpi_gbl_gpe_xrupt_list_head = NULL; - acpi_gbl_gpe_fadt_blocks[0] = NULL; - acpi_gbl_gpe_fadt_blocks[1] = NULL; - acpi_current_gpe_count = 0; - - acpi_gbl_global_event_handler = NULL; - acpi_gbl_sci_handler_list = NULL; - -#endif /* !ACPI_REDUCED_HARDWARE */ - - /* Global handlers */ - - acpi_gbl_global_notify[0].handler = NULL; - acpi_gbl_global_notify[1].handler = NULL; - acpi_gbl_exception_handler = NULL; - acpi_gbl_init_handler = NULL; - acpi_gbl_table_handler = NULL; - acpi_gbl_interface_handler = NULL; - - /* Global Lock support */ - - acpi_gbl_global_lock_semaphore = NULL; - acpi_gbl_global_lock_mutex = NULL; - acpi_gbl_global_lock_acquired = FALSE; - acpi_gbl_global_lock_handle = 0; - acpi_gbl_global_lock_present = FALSE; - - /* Miscellaneous variables */ - - acpi_gbl_DSDT = NULL; - acpi_gbl_cm_single_step = FALSE; - acpi_gbl_shutdown = FALSE; - acpi_gbl_ns_lookup_count = 0; - acpi_gbl_ps_find_count = 0; - 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_db_output_flags = ACPI_DB_CONSOLE_OUTPUT; - acpi_gbl_osi_mutex = NULL; - acpi_gbl_reg_methods_executed = FALSE; - - /* Hardware oriented */ - - acpi_gbl_events_initialized = FALSE; - acpi_gbl_system_awake_and_running = TRUE; - - /* Namespace */ - - acpi_gbl_module_code_list = NULL; - acpi_gbl_root_node = NULL; - acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME; - acpi_gbl_root_node_struct.descriptor_type = ACPI_DESC_TYPE_NAMED; - acpi_gbl_root_node_struct.type = ACPI_TYPE_DEVICE; - acpi_gbl_root_node_struct.parent = NULL; - acpi_gbl_root_node_struct.child = NULL; - acpi_gbl_root_node_struct.peer = NULL; - acpi_gbl_root_node_struct.object = NULL; - -#ifdef ACPI_DISASSEMBLER - acpi_gbl_external_list = NULL; - acpi_gbl_num_external_methods = 0; - acpi_gbl_resolved_external_methods = 0; -#endif - -#ifdef ACPI_DEBUG_OUTPUT - acpi_gbl_lowest_stack_pointer = ACPI_CAST_PTR(acpi_size, ACPI_SIZE_MAX); -#endif - -#ifdef ACPI_DBG_TRACK_ALLOCATIONS - acpi_gbl_display_final_mem_stats = FALSE; - acpi_gbl_disable_mem_tracking = FALSE; -#endif - - ACPI_DEBUGGER_EXEC(acpi_gbl_db_terminate_threads = FALSE); - - return_ACPI_STATUS(AE_OK); -} - /* Public globals */ ACPI_EXPORT_SYMBOL(acpi_gbl_FADT) diff --git a/drivers/acpi/acpica/utinit.c b/drivers/acpi/acpica/utinit.c index 5f56fc49021..77120ec9ea8 100644 --- a/drivers/acpi/acpica/utinit.c +++ b/drivers/acpi/acpica/utinit.c @@ -102,6 +102,151 @@ static void acpi_ut_free_gpe_lists(void) } #endif /* !ACPI_REDUCED_HARDWARE */ +/******************************************************************************* + * + * FUNCTION: acpi_ut_init_globals + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initialize ACPICA globals. All globals that require specific + * initialization should be initialized here. This allows for + * a warm restart. + * + ******************************************************************************/ + +acpi_status acpi_ut_init_globals(void) +{ + acpi_status status; + u32 i; + + ACPI_FUNCTION_TRACE(ut_init_globals); + + /* Create all memory caches */ + + status = acpi_ut_create_caches(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Address Range lists */ + + for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) { + acpi_gbl_address_range_list[i] = NULL; + } + + /* Mutex locked flags */ + + for (i = 0; i < ACPI_NUM_MUTEX; i++) { + acpi_gbl_mutex_info[i].mutex = NULL; + acpi_gbl_mutex_info[i].thread_id = ACPI_MUTEX_NOT_ACQUIRED; + acpi_gbl_mutex_info[i].use_count = 0; + } + + for (i = 0; i < ACPI_NUM_OWNERID_MASKS; i++) { + acpi_gbl_owner_id_mask[i] = 0; + } + + /* Last owner_ID is never valid */ + + acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS - 1] = 0x80000000; + + /* Event counters */ + + acpi_method_count = 0; + acpi_sci_count = 0; + acpi_gpe_count = 0; + + for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { + acpi_fixed_event_count[i] = 0; + } + +#if (!ACPI_REDUCED_HARDWARE) + + /* GPE/SCI support */ + + acpi_gbl_all_gpes_initialized = FALSE; + acpi_gbl_gpe_xrupt_list_head = NULL; + acpi_gbl_gpe_fadt_blocks[0] = NULL; + acpi_gbl_gpe_fadt_blocks[1] = NULL; + acpi_current_gpe_count = 0; + + acpi_gbl_global_event_handler = NULL; + acpi_gbl_sci_handler_list = NULL; + +#endif /* !ACPI_REDUCED_HARDWARE */ + + /* Global handlers */ + + acpi_gbl_global_notify[0].handler = NULL; + acpi_gbl_global_notify[1].handler = NULL; + acpi_gbl_exception_handler = NULL; + acpi_gbl_init_handler = NULL; + acpi_gbl_table_handler = NULL; + acpi_gbl_interface_handler = NULL; + + /* Global Lock support */ + + acpi_gbl_global_lock_semaphore = NULL; + acpi_gbl_global_lock_mutex = NULL; + acpi_gbl_global_lock_acquired = FALSE; + acpi_gbl_global_lock_handle = 0; + acpi_gbl_global_lock_present = FALSE; + + /* Miscellaneous variables */ + + acpi_gbl_DSDT = NULL; + acpi_gbl_cm_single_step = FALSE; + acpi_gbl_shutdown = FALSE; + acpi_gbl_ns_lookup_count = 0; + acpi_gbl_ps_find_count = 0; + 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; + + /* Hardware oriented */ + + acpi_gbl_events_initialized = FALSE; + acpi_gbl_system_awake_and_running = TRUE; + + /* Namespace */ + + acpi_gbl_module_code_list = NULL; + acpi_gbl_root_node = NULL; + acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME; + acpi_gbl_root_node_struct.descriptor_type = ACPI_DESC_TYPE_NAMED; + acpi_gbl_root_node_struct.type = ACPI_TYPE_DEVICE; + acpi_gbl_root_node_struct.parent = NULL; + acpi_gbl_root_node_struct.child = NULL; + acpi_gbl_root_node_struct.peer = NULL; + acpi_gbl_root_node_struct.object = NULL; + +#ifdef ACPI_DISASSEMBLER + acpi_gbl_external_list = NULL; + acpi_gbl_num_external_methods = 0; + acpi_gbl_resolved_external_methods = 0; +#endif + +#ifdef ACPI_DEBUG_OUTPUT + acpi_gbl_lowest_stack_pointer = ACPI_CAST_PTR(acpi_size, ACPI_SIZE_MAX); +#endif + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + acpi_gbl_display_final_mem_stats = FALSE; + acpi_gbl_disable_mem_tracking = FALSE; +#endif + + ACPI_DEBUGGER_EXEC(acpi_gbl_db_terminate_threads = FALSE); + + return_ACPI_STATUS(AE_OK); +} + /****************************************************************************** * * FUNCTION: acpi_ut_terminate diff --git a/drivers/acpi/acpica/utprint.c b/drivers/acpi/acpica/utprint.c new file mode 100644 index 00000000000..10311648f70 --- /dev/null +++ b/drivers/acpi/acpica/utprint.c @@ -0,0 +1,661 @@ +/****************************************************************************** + * + * Module Name: utprint - Formatted printing routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include "accommon.h" + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utprint") + +#define ACPI_FORMAT_SIGN 0x01 +#define ACPI_FORMAT_SIGN_PLUS 0x02 +#define ACPI_FORMAT_SIGN_PLUS_SPACE 0x04 +#define ACPI_FORMAT_ZERO 0x08 +#define ACPI_FORMAT_LEFT 0x10 +#define ACPI_FORMAT_UPPER 0x20 +#define ACPI_FORMAT_PREFIX 0x40 +/* Local prototypes */ +static acpi_size +acpi_ut_bound_string_length(const char *string, acpi_size count); + +static char *acpi_ut_bound_string_output(char *string, const char *end, char c); + +static char *acpi_ut_format_number(char *string, + char *end, + u64 number, + u8 base, s32 width, s32 precision, u8 type); + +static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper); + +/* Module globals */ + +static const char acpi_gbl_lower_hex_digits[] = "0123456789abcdef"; +static const char acpi_gbl_upper_hex_digits[] = "0123456789ABCDEF"; + +/******************************************************************************* + * + * FUNCTION: acpi_ut_bound_string_length + * + * PARAMETERS: string - String with boundary + * count - Boundary of the string + * + * RETURN: Length of the string. Less than or equal to Count. + * + * DESCRIPTION: Calculate the length of a string with boundary. + * + ******************************************************************************/ + +static acpi_size +acpi_ut_bound_string_length(const char *string, acpi_size count) +{ + u32 length = 0; + + while (*string && count) { + length++; + string++; + count--; + } + + return (length); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_bound_string_output + * + * PARAMETERS: string - String with boundary + * end - Boundary of the string + * c - Character to be output to the string + * + * RETURN: Updated position for next valid character + * + * DESCRIPTION: Output a character into a string with boundary check. + * + ******************************************************************************/ + +static char *acpi_ut_bound_string_output(char *string, const char *end, char c) +{ + + if (string < end) { + *string = c; + } + + ++string; + return (string); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_put_number + * + * PARAMETERS: string - Buffer to hold reverse-ordered string + * number - Integer to be converted + * base - Base of the integer + * upper - Whether or not using upper cased digits + * + * RETURN: Updated position for next valid character + * + * DESCRIPTION: Convert an integer into a string, note that, the string holds a + * reversed ordered number without the trailing zero. + * + ******************************************************************************/ + +static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper) +{ + const char *digits; + u64 digit_index; + char *pos; + + pos = string; + digits = upper ? acpi_gbl_upper_hex_digits : acpi_gbl_lower_hex_digits; + + if (number == 0) { + *(pos++) = '0'; + } else { + while (number) { + (void)acpi_ut_divide(number, base, &number, + &digit_index); + *(pos++) = digits[digit_index]; + } + } + + /* *(Pos++) = '0'; */ + return (pos); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_scan_number + * + * PARAMETERS: string - String buffer + * number_ptr - Where the number is returned + * + * RETURN: Updated position for next valid character + * + * DESCRIPTION: Scan a string for a decimal integer. + * + ******************************************************************************/ + +const char *acpi_ut_scan_number(const char *string, u64 *number_ptr) +{ + u64 number = 0; + + while (ACPI_IS_DIGIT(*string)) { + number *= 10; + number += *(string++) - '0'; + } + + *number_ptr = number; + return (string); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_print_number + * + * PARAMETERS: string - String buffer + * number - The number to be converted + * + * RETURN: Updated position for next valid character + * + * DESCRIPTION: Print a decimal integer into a string. + * + ******************************************************************************/ + +const char *acpi_ut_print_number(char *string, u64 number) +{ + char ascii_string[20]; + const char *pos1; + char *pos2; + + pos1 = acpi_ut_put_number(ascii_string, number, 10, FALSE); + pos2 = string; + + while (pos1 != ascii_string) { + *(pos2++) = *(--pos1); + } + + *pos2 = 0; + return (string); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_format_number + * + * PARAMETERS: string - String buffer with boundary + * end - Boundary of the string + * number - The number to be converted + * base - Base of the integer + * width - Field width + * precision - Precision of the integer + * type - Special printing flags + * + * RETURN: Updated position for next valid character + * + * DESCRIPTION: Print an integer into a string with any base and any precision. + * + ******************************************************************************/ + +static char *acpi_ut_format_number(char *string, + char *end, + u64 number, + u8 base, s32 width, s32 precision, u8 type) +{ + char sign; + char zero; + u8 need_prefix; + u8 upper; + s32 i; + char reversed_string[66]; + + /* Parameter validation */ + + if (base < 2 || base > 16) { + return (NULL); + } + + if (type & ACPI_FORMAT_LEFT) { + type &= ~ACPI_FORMAT_ZERO; + } + + need_prefix = ((type & ACPI_FORMAT_PREFIX) + && base != 10) ? TRUE : FALSE; + upper = (type & ACPI_FORMAT_UPPER) ? TRUE : FALSE; + zero = (type & ACPI_FORMAT_ZERO) ? '0' : ' '; + + /* Calculate size according to sign and prefix */ + + sign = '\0'; + if (type & ACPI_FORMAT_SIGN) { + if ((s64) number < 0) { + sign = '-'; + number = -(s64) number; + width--; + } else if (type & ACPI_FORMAT_SIGN_PLUS) { + sign = '+'; + width--; + } else if (type & ACPI_FORMAT_SIGN_PLUS_SPACE) { + sign = ' '; + width--; + } + } + if (need_prefix) { + width--; + if (base == 16) { + width--; + } + } + + /* Generate full string in reverse order */ + + i = ACPI_PTR_DIFF(acpi_ut_put_number + (reversed_string, number, base, upper), + reversed_string); + + /* Printing 100 using %2d gives "100", not "00" */ + + if (i > precision) { + precision = i; + } + + width -= precision; + + /* Output the string */ + + if (!(type & (ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT))) { + while (--width >= 0) { + string = acpi_ut_bound_string_output(string, end, ' '); + } + } + if (sign) { + string = acpi_ut_bound_string_output(string, end, sign); + } + if (need_prefix) { + string = acpi_ut_bound_string_output(string, end, '0'); + if (base == 16) { + string = acpi_ut_bound_string_output(string, end, + upper ? 'X' : 'x'); + } + } + if (!(type & ACPI_FORMAT_LEFT)) { + while (--width >= 0) { + string = acpi_ut_bound_string_output(string, end, zero); + } + } + + while (i <= --precision) { + string = acpi_ut_bound_string_output(string, end, '0'); + } + while (--i >= 0) { + string = acpi_ut_bound_string_output(string, end, + reversed_string[i]); + } + while (--width >= 0) { + string = acpi_ut_bound_string_output(string, end, ' '); + } + + return (string); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_vsnprintf + * + * PARAMETERS: string - String with boundary + * size - Boundary of the string + * format - Standard printf format + * args - Argument list + * + * RETURN: Number of bytes actually written. + * + * DESCRIPTION: Formatted output to a string using argument list pointer. + * + ******************************************************************************/ + +int +acpi_ut_vsnprintf(char *string, + acpi_size size, const char *format, va_list args) +{ + u8 base = 10; + u8 type = 0; + s32 width = -1; + s32 precision = -1; + char qualifier = 0; + u64 number; + char *pos; + char *end; + char c; + const char *s; + const void *p; + s32 length; + int i; + + pos = string; + end = string + size; + + for (; *format; ++format) { + if (*format != '%') { + pos = acpi_ut_bound_string_output(pos, end, *format); + continue; + } + + /* Process sign */ + + do { + ++format; + if (*format == '#') { + type |= ACPI_FORMAT_PREFIX; + } else if (*format == '0') { + type |= ACPI_FORMAT_ZERO; + } else if (*format == '+') { + type |= ACPI_FORMAT_SIGN_PLUS; + } else if (*format == ' ') { + type |= ACPI_FORMAT_SIGN_PLUS_SPACE; + } else if (*format == '-') { + type |= ACPI_FORMAT_LEFT; + } else { + break; + } + } while (1); + + /* Process width */ + + if (ACPI_IS_DIGIT(*format)) { + format = acpi_ut_scan_number(format, &number); + width = (s32) number; + } else if (*format == '*') { + ++format; + width = va_arg(args, int); + if (width < 0) { + width = -width; + type |= ACPI_FORMAT_LEFT; + } + } + + /* Process precision */ + + if (*format == '.') { + ++format; + if (ACPI_IS_DIGIT(*format)) { + format = acpi_ut_scan_number(format, &number); + precision = (s32) number; + } else if (*format == '*') { + ++format; + precision = va_arg(args, int); + } + if (precision < 0) { + precision = 0; + } + } + + /* Process qualifier */ + + if (*format == 'h' || *format == 'l' || *format == 'L') { + qualifier = *format; + ++format; + + if (qualifier == 'l' && *format == 'l') { + qualifier = 'L'; + ++format; + } + } + + switch (*format) { + case '%': + + pos = acpi_ut_bound_string_output(pos, end, '%'); + continue; + + case 'c': + + if (!(type & ACPI_FORMAT_LEFT)) { + while (--width > 0) { + pos = + acpi_ut_bound_string_output(pos, + end, + ' '); + } + } + + c = (char)va_arg(args, int); + pos = acpi_ut_bound_string_output(pos, end, c); + + while (--width > 0) { + pos = + acpi_ut_bound_string_output(pos, end, ' '); + } + continue; + + case 's': + + s = va_arg(args, char *); + if (!s) { + s = "<NULL>"; + } + length = acpi_ut_bound_string_length(s, precision); + if (!(type & ACPI_FORMAT_LEFT)) { + while (length < width--) { + pos = + acpi_ut_bound_string_output(pos, + end, + ' '); + } + } + for (i = 0; i < length; ++i) { + pos = acpi_ut_bound_string_output(pos, end, *s); + ++s; + } + while (length < width--) { + pos = + acpi_ut_bound_string_output(pos, end, ' '); + } + continue; + + case 'o': + + base = 8; + break; + + case 'X': + + type |= ACPI_FORMAT_UPPER; + + case 'x': + + base = 16; + break; + + case 'd': + case 'i': + + type |= ACPI_FORMAT_SIGN; + + case 'u': + + break; + + case 'p': + + if (width == -1) { + width = 2 * sizeof(void *); + type |= ACPI_FORMAT_ZERO; + } + + p = va_arg(args, void *); + pos = acpi_ut_format_number(pos, end, + ACPI_TO_INTEGER(p), 16, + width, precision, type); + continue; + + default: + + pos = acpi_ut_bound_string_output(pos, end, '%'); + if (*format) { + pos = + acpi_ut_bound_string_output(pos, end, + *format); + } else { + --format; + } + continue; + } + + if (qualifier == 'L') { + number = va_arg(args, u64); + if (type & ACPI_FORMAT_SIGN) { + number = (s64) number; + } + } else if (qualifier == 'l') { + number = va_arg(args, unsigned long); + if (type & ACPI_FORMAT_SIGN) { + number = (s32) number; + } + } else if (qualifier == 'h') { + number = (u16)va_arg(args, int); + if (type & ACPI_FORMAT_SIGN) { + number = (s16) number; + } + } else { + number = va_arg(args, unsigned int); + if (type & ACPI_FORMAT_SIGN) { + number = (signed int)number; + } + } + + pos = acpi_ut_format_number(pos, end, number, base, + width, precision, type); + } + + if (size > 0) { + if (pos < end) { + *pos = '\0'; + } else { + end[-1] = '\0'; + } + } + + return (ACPI_PTR_DIFF(pos, string)); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_snprintf + * + * PARAMETERS: string - String with boundary + * size - Boundary of the string + * Format, ... - Standard printf format + * + * RETURN: Number of bytes actually written. + * + * DESCRIPTION: Formatted output to a string. + * + ******************************************************************************/ + +int acpi_ut_snprintf(char *string, acpi_size size, const char *format, ...) +{ + va_list args; + int length; + + va_start(args, format); + length = acpi_ut_vsnprintf(string, size, format, args); + va_end(args); + + return (length); +} + +#ifdef ACPI_APPLICATION +/******************************************************************************* + * + * FUNCTION: acpi_ut_file_vprintf + * + * PARAMETERS: file - File descriptor + * format - Standard printf format + * args - Argument list + * + * RETURN: Number of bytes actually written. + * + * DESCRIPTION: Formatted output to a file using argument list pointer. + * + ******************************************************************************/ + +int acpi_ut_file_vprintf(ACPI_FILE file, const char *format, va_list args) +{ + acpi_cpu_flags flags; + int length; + + flags = acpi_os_acquire_lock(acpi_gbl_print_lock); + length = acpi_ut_vsnprintf(acpi_gbl_print_buffer, + sizeof(acpi_gbl_print_buffer), format, args); + + (void)acpi_os_write_file(file, acpi_gbl_print_buffer, length, 1); + acpi_os_release_lock(acpi_gbl_print_lock, flags); + + return (length); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_file_printf + * + * PARAMETERS: file - File descriptor + * Format, ... - Standard printf format + * + * RETURN: Number of bytes actually written. + * + * DESCRIPTION: Formatted output to a file. + * + ******************************************************************************/ + +int acpi_ut_file_printf(ACPI_FILE file, const char *format, ...) +{ + va_list args; + int length; + + va_start(args, format); + length = acpi_ut_file_vprintf(file, format, args); + va_end(args); + + return (length); +} +#endif diff --git a/drivers/acpi/apei/apei-internal.h b/drivers/acpi/apei/apei-internal.h index e5bcd919d4e..16129c78b48 100644 --- a/drivers/acpi/apei/apei-internal.h +++ b/drivers/acpi/apei/apei-internal.h @@ -121,11 +121,11 @@ struct dentry; struct dentry *apei_get_debugfs_dir(void); #define apei_estatus_for_each_section(estatus, section) \ - for (section = (struct acpi_generic_data *)(estatus + 1); \ + for (section = (struct acpi_hest_generic_data *)(estatus + 1); \ (void *)section - (void *)estatus < estatus->data_length; \ section = (void *)(section+1) + section->error_data_length) -static inline u32 cper_estatus_len(struct acpi_generic_status *estatus) +static inline u32 cper_estatus_len(struct acpi_hest_generic_status *estatus) { if (estatus->raw_data_length) return estatus->raw_data_offset + \ @@ -135,9 +135,9 @@ static inline u32 cper_estatus_len(struct acpi_generic_status *estatus) } void cper_estatus_print(const char *pfx, - const struct acpi_generic_status *estatus); -int cper_estatus_check_header(const struct acpi_generic_status *estatus); -int cper_estatus_check(const struct acpi_generic_status *estatus); + const struct acpi_hest_generic_status *estatus); +int cper_estatus_check_header(const struct acpi_hest_generic_status *estatus); +int cper_estatus_check(const struct acpi_hest_generic_status *estatus); int apei_osc_setup(void); #endif diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index dab7cb7349d..7a38d1465b6 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -74,13 +74,13 @@ #define GHES_ESTATUS_CACHE_LEN(estatus_len) \ (sizeof(struct ghes_estatus_cache) + (estatus_len)) #define GHES_ESTATUS_FROM_CACHE(estatus_cache) \ - ((struct acpi_generic_status *) \ + ((struct acpi_hest_generic_status *) \ ((struct ghes_estatus_cache *)(estatus_cache) + 1)) #define GHES_ESTATUS_NODE_LEN(estatus_len) \ (sizeof(struct ghes_estatus_node) + (estatus_len)) #define GHES_ESTATUS_FROM_NODE(estatus_node) \ - ((struct acpi_generic_status *) \ + ((struct acpi_hest_generic_status *) \ ((struct ghes_estatus_node *)(estatus_node) + 1)) bool ghes_disable; @@ -408,7 +408,7 @@ static void ghes_clear_estatus(struct ghes *ghes) ghes->flags &= ~GHES_TO_CLEAR; } -static void ghes_handle_memory_failure(struct acpi_generic_data *gdata, int sev) +static void ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, int sev) { #ifdef CONFIG_ACPI_APEI_MEMORY_FAILURE unsigned long pfn; @@ -441,10 +441,10 @@ static void ghes_handle_memory_failure(struct acpi_generic_data *gdata, int sev) } static void ghes_do_proc(struct ghes *ghes, - const struct acpi_generic_status *estatus) + const struct acpi_hest_generic_status *estatus) { int sev, sec_sev; - struct acpi_generic_data *gdata; + struct acpi_hest_generic_data *gdata; sev = ghes_severity(estatus->error_severity); apei_estatus_for_each_section(estatus, gdata) { @@ -498,7 +498,7 @@ static void ghes_do_proc(struct ghes *ghes, static void __ghes_print_estatus(const char *pfx, const struct acpi_hest_generic *generic, - const struct acpi_generic_status *estatus) + const struct acpi_hest_generic_status *estatus) { static atomic_t seqno; unsigned int curr_seqno; @@ -520,7 +520,7 @@ static void __ghes_print_estatus(const char *pfx, static int ghes_print_estatus(const char *pfx, const struct acpi_hest_generic *generic, - const struct acpi_generic_status *estatus) + const struct acpi_hest_generic_status *estatus) { /* Not more than 2 messages every 5 seconds */ static DEFINE_RATELIMIT_STATE(ratelimit_corrected, 5*HZ, 2); @@ -542,13 +542,13 @@ static int ghes_print_estatus(const char *pfx, * GHES error status reporting throttle, to report more kinds of * errors, instead of just most frequently occurred errors. */ -static int ghes_estatus_cached(struct acpi_generic_status *estatus) +static int ghes_estatus_cached(struct acpi_hest_generic_status *estatus) { u32 len; int i, cached = 0; unsigned long long now; struct ghes_estatus_cache *cache; - struct acpi_generic_status *cache_estatus; + struct acpi_hest_generic_status *cache_estatus; len = cper_estatus_len(estatus); rcu_read_lock(); @@ -573,12 +573,12 @@ static int ghes_estatus_cached(struct acpi_generic_status *estatus) static struct ghes_estatus_cache *ghes_estatus_cache_alloc( struct acpi_hest_generic *generic, - struct acpi_generic_status *estatus) + struct acpi_hest_generic_status *estatus) { int alloced; u32 len, cache_len; struct ghes_estatus_cache *cache; - struct acpi_generic_status *cache_estatus; + struct acpi_hest_generic_status *cache_estatus; alloced = atomic_add_return(1, &ghes_estatus_cache_alloced); if (alloced > GHES_ESTATUS_CACHE_ALLOCED_MAX) { @@ -621,7 +621,7 @@ static void ghes_estatus_cache_rcu_free(struct rcu_head *head) static void ghes_estatus_cache_add( struct acpi_hest_generic *generic, - struct acpi_generic_status *estatus) + struct acpi_hest_generic_status *estatus) { int i, slot = -1, count; unsigned long long now, duration, period, max_period = 0; @@ -753,7 +753,7 @@ static void ghes_proc_in_irq(struct irq_work *irq_work) struct llist_node *llnode, *next; struct ghes_estatus_node *estatus_node; struct acpi_hest_generic *generic; - struct acpi_generic_status *estatus; + struct acpi_hest_generic_status *estatus; u32 len, node_len; llnode = llist_del_all(&ghes_estatus_llist); @@ -786,7 +786,7 @@ static void ghes_print_queued_estatus(void) struct llist_node *llnode; struct ghes_estatus_node *estatus_node; struct acpi_hest_generic *generic; - struct acpi_generic_status *estatus; + struct acpi_hest_generic_status *estatus; u32 len, node_len; llnode = llist_del_all(&ghes_estatus_llist); @@ -845,7 +845,7 @@ static int ghes_notify_nmi(unsigned int cmd, struct pt_regs *regs) #ifdef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG u32 len, node_len; struct ghes_estatus_node *estatus_node; - struct acpi_generic_status *estatus; + struct acpi_hest_generic_status *estatus; #endif if (!(ghes->flags & GHES_TO_CLEAR)) continue; @@ -925,7 +925,7 @@ static int ghes_probe(struct platform_device *ghes_dev) rc = -EIO; if (generic->error_block_length < - sizeof(struct acpi_generic_status)) { + sizeof(struct acpi_hest_generic_status)) { pr_warning(FW_BUG GHES_PFX "Invalid error block length: %u for generic hardware error source: %d\n", generic->error_block_length, generic->header.source_id); diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c index 1491dd4f08f..65f2f3fdde2 100644 --- a/drivers/firmware/efi/cper.c +++ b/drivers/firmware/efi/cper.c @@ -262,7 +262,7 @@ static const char *cper_pcie_port_type_strs[] = { }; static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie, - const struct acpi_generic_data *gdata) + const struct acpi_hest_generic_data *gdata) { if (pcie->validation_bits & CPER_PCIE_VALID_PORT_TYPE) printk("%s""port_type: %d, %s\n", pfx, pcie->port_type, @@ -298,7 +298,7 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie, } static void cper_estatus_print_section( - const char *pfx, const struct acpi_generic_data *gdata, int sec_no) + const char *pfx, const struct acpi_hest_generic_data *gdata, int sec_no) { uuid_le *sec_type = (uuid_le *)gdata->section_type; __u16 severity; @@ -344,9 +344,9 @@ err_section_too_small: } void cper_estatus_print(const char *pfx, - const struct acpi_generic_status *estatus) + const struct acpi_hest_generic_status *estatus) { - struct acpi_generic_data *gdata; + struct acpi_hest_generic_data *gdata; unsigned int data_len, gedata_len; int sec_no = 0; char newpfx[64]; @@ -359,7 +359,7 @@ void cper_estatus_print(const char *pfx, "and requires no further action"); printk("%s""event severity: %s\n", pfx, cper_severity_str(severity)); data_len = estatus->data_length; - gdata = (struct acpi_generic_data *)(estatus + 1); + gdata = (struct acpi_hest_generic_data *)(estatus + 1); snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP); while (data_len >= sizeof(*gdata)) { gedata_len = gdata->error_data_length; @@ -371,10 +371,10 @@ void cper_estatus_print(const char *pfx, } EXPORT_SYMBOL_GPL(cper_estatus_print); -int cper_estatus_check_header(const struct acpi_generic_status *estatus) +int cper_estatus_check_header(const struct acpi_hest_generic_status *estatus) { if (estatus->data_length && - estatus->data_length < sizeof(struct acpi_generic_data)) + estatus->data_length < sizeof(struct acpi_hest_generic_data)) return -EINVAL; if (estatus->raw_data_length && estatus->raw_data_offset < sizeof(*estatus) + estatus->data_length) @@ -384,9 +384,9 @@ int cper_estatus_check_header(const struct acpi_generic_status *estatus) } EXPORT_SYMBOL_GPL(cper_estatus_check_header); -int cper_estatus_check(const struct acpi_generic_status *estatus) +int cper_estatus_check(const struct acpi_hest_generic_status *estatus) { - struct acpi_generic_data *gdata; + struct acpi_hest_generic_data *gdata; unsigned int data_len, gedata_len; int rc; @@ -394,7 +394,7 @@ int cper_estatus_check(const struct acpi_generic_status *estatus) if (rc) return rc; data_len = estatus->data_length; - gdata = (struct acpi_generic_data *)(estatus + 1); + gdata = (struct acpi_hest_generic_data *)(estatus + 1); while (data_len >= sizeof(*gdata)) { gedata_len = gdata->error_data_length; if (gedata_len > data_len - sizeof(*gdata)) diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h index f6f5f8af211..03b3e6d405f 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h @@ -399,4 +399,35 @@ char *acpi_os_get_next_filename(void *dir_handle); void acpi_os_close_directory(void *dir_handle); #endif +/* + * File I/O and related support + */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_open_file +ACPI_FILE acpi_os_open_file(const char *path, u8 modes); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_close_file +void acpi_os_close_file(ACPI_FILE file); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_read_file +int +acpi_os_read_file(ACPI_FILE file, + void *buffer, acpi_size size, acpi_size count); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_write_file +int +acpi_os_write_file(ACPI_FILE file, + void *buffer, acpi_size size, acpi_size count); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_file_offset +long acpi_os_get_file_offset(ACPI_FILE file); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_set_file_offset +acpi_status acpi_os_set_file_offset(ACPI_FILE file, long offset, u8 from); +#endif + #endif /* __ACPIOSXF_H__ */ diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 35b525c1971..508e5649dda 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -46,7 +46,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20140424 +#define ACPI_CA_VERSION 0x20140627 #include <acpi/acconfig.h> #include <acpi/actypes.h> @@ -335,6 +335,23 @@ ACPI_GLOBAL(u8, acpi_gbl_system_awake_and_running); #endif /* ACPI_DEBUG_OUTPUT */ +/* + * Application prototypes + * + * All interfaces used by application will be configured + * out of the ACPICA build unless the ACPI_APPLICATION + * flag is defined. + */ +#ifdef ACPI_APPLICATION +#define ACPI_APP_DEPENDENT_RETURN_VOID(prototype) \ + prototype; + +#else +#define ACPI_APP_DEPENDENT_RETURN_VOID(prototype) \ + static ACPI_INLINE prototype {return;} + +#endif /* ACPI_APPLICATION */ + /***************************************************************************** * * ACPICA public interface prototypes @@ -658,6 +675,10 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status u32 gpe_number)) ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status + acpi_mark_gpe_for_wake(acpi_handle gpe_device, + u32 gpe_number)) + +ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_setup_gpe_for_wake(acpi_handle parent_device, acpi_handle gpe_device, @@ -861,6 +882,9 @@ ACPI_DBG_DEPENDENT_RETURN_VOID(ACPI_PRINTF_LIKE(6) const char *module_name, u32 component_id, const char *format, ...)) +ACPI_APP_DEPENDENT_RETURN_VOID(ACPI_PRINTF_LIKE(1) + void ACPI_INTERNAL_VAR_XFACE + acpi_log_error(const char *format, ...)) /* * Divergences diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h index 4ad7da80518..9613e8e9796 100644 --- a/include/acpi/actbl1.h +++ b/include/acpi/actbl1.h @@ -604,7 +604,7 @@ struct acpi_hest_generic { /* Generic Error Status block */ -struct acpi_generic_status { +struct acpi_hest_generic_status { u32 block_status; u32 raw_data_offset; u32 raw_data_length; @@ -614,15 +614,15 @@ struct acpi_generic_status { /* Values for block_status flags above */ -#define ACPI_GEN_ERR_UC BIT(0) -#define ACPI_GEN_ERR_CE BIT(1) -#define ACPI_GEN_ERR_MULTI_UC BIT(2) -#define ACPI_GEN_ERR_MULTI_CE BIT(3) -#define ACPI_GEN_ERR_COUNT_SHIFT (0xFF<<4) /* 8 bits, error count */ +#define ACPI_HEST_UNCORRECTABLE (1) +#define ACPI_HEST_CORRECTABLE (1<<1) +#define ACPI_HEST_MULTIPLE_UNCORRECTABLE (1<<2) +#define ACPI_HEST_MULTIPLE_CORRECTABLE (1<<3) +#define ACPI_HEST_ERROR_ENTRY_COUNT (0xFF<<4) /* 8 bits, error count */ /* Generic Error Data entry */ -struct acpi_generic_data { +struct acpi_hest_generic_data { u8 section_type[16]; u32 error_severity; u16 revision; diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index 860e5c883eb..21314d37cb0 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -516,7 +516,7 @@ struct acpi_dmar_andd { struct acpi_dmar_header header; u8 reserved[3]; u8 device_number; - u8 object_name[]; + char object_name[1]; }; /******************************************************************************* diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 19b26bb69a7..608a0401937 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -126,6 +126,7 @@ typedef unsigned char u8; typedef unsigned char u8; typedef unsigned short u16; +typedef short s16; typedef COMPILER_DEPENDENT_UINT64 u64; typedef COMPILER_DEPENDENT_INT64 s64; @@ -1244,4 +1245,17 @@ struct acpi_memory_list { #define ACPI_OSI_WIN_7 0x0B #define ACPI_OSI_WIN_8 0x0C +/* Definitions of file IO */ + +#define ACPI_FILE_READING 0x01 +#define ACPI_FILE_WRITING 0x02 +#define ACPI_FILE_BINARY 0x04 + +#define ACPI_FILE_BEGIN 0x01 +#define ACPI_FILE_END 0x02 + +/* Definitions of getopt */ + +#define ACPI_OPT_END -1 + #endif /* __ACTYPES_H__ */ diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h index dfd60d0bfd2..720446cb243 100644 --- a/include/acpi/ghes.h +++ b/include/acpi/ghes.h @@ -14,7 +14,7 @@ struct ghes { struct acpi_hest_generic *generic; - struct acpi_generic_status *estatus; + struct acpi_hest_generic_status *estatus; u64 buffer_paddr; unsigned long flags; union { diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h index e863dd5c4e0..5f8cc1fa327 100644 --- a/include/acpi/platform/acenv.h +++ b/include/acpi/platform/acenv.h @@ -87,20 +87,14 @@ #define ACPI_DBG_TRACK_ALLOCATIONS #endif -/* acpi_names configuration. Single threaded with debugger output enabled. */ - -#ifdef ACPI_NAMES_APP -#define ACPI_DEBUGGER -#define ACPI_APPLICATION -#define ACPI_SINGLE_THREADED -#endif - /* - * acpi_bin/acpi_dump/acpi_src/acpi_xtract/Example configuration. All single - * threaded, with no debug output. + * acpi_bin/acpi_dump/acpi_help/acpi_names/acpi_src/acpi_xtract/Example configuration. + * All single threaded. */ #if (defined ACPI_BIN_APP) || \ (defined ACPI_DUMP_APP) || \ + (defined ACPI_HELP_APP) || \ + (defined ACPI_NAMES_APP) || \ (defined ACPI_SRC_APP) || \ (defined ACPI_XTRACT_APP) || \ (defined ACPI_EXAMPLE_APP) @@ -108,12 +102,40 @@ #define ACPI_SINGLE_THREADED #endif +/* acpi_help configuration. Error messages disabled. */ + #ifdef ACPI_HELP_APP -#define ACPI_APPLICATION -#define ACPI_SINGLE_THREADED #define ACPI_NO_ERROR_MESSAGES #endif +/* acpi_names configuration. Debug output enabled. */ + +#ifdef ACPI_NAMES_APP +#define ACPI_DEBUG_OUTPUT +#endif + +/* acpi_exec/acpi_names/Example configuration. Native RSDP used. */ + +#if (defined ACPI_EXEC_APP) || \ + (defined ACPI_EXAMPLE_APP) || \ + (defined ACPI_NAMES_APP) +#define ACPI_USE_NATIVE_RSDP_POINTER +#endif + +/* acpi_dump configuration. Native mapping used if provied by OSPMs */ + +#ifdef ACPI_DUMP_APP +#define ACPI_USE_NATIVE_MEMORY_MAPPING +#define USE_NATIVE_ALLOCATE_ZEROED +#endif + +/* acpi_names/Example configuration. Hardware disabled */ + +#if (defined ACPI_EXAMPLE_APP) || \ + (defined ACPI_NAMES_APP) +#define ACPI_REDUCED_HARDWARE 1 +#endif + /* Linkable ACPICA library */ #ifdef ACPI_LIBRARY @@ -185,6 +207,9 @@ #elif defined(_AED_EFI) #include "acefi.h" +#elif defined(_GNU_EFI) +#include "acefi.h" + #elif defined(__HAIKU__) #include "achaiku.h" @@ -399,8 +424,12 @@ typedef char *va_list; #ifdef ACPI_APPLICATION #include <stdio.h> #define ACPI_FILE FILE * +#define ACPI_FILE_OUT stdout +#define ACPI_FILE_ERR stderr #else #define ACPI_FILE void * +#define ACPI_FILE_OUT NULL +#define ACPI_FILE_ERR NULL #endif /* ACPI_APPLICATION */ #endif /* ACPI_FILE */ diff --git a/tools/power/acpi/Makefile b/tools/power/acpi/Makefile index e5a3c4be2a1..3d1537b93c6 100644 --- a/tools/power/acpi/Makefile +++ b/tools/power/acpi/Makefile @@ -108,13 +108,18 @@ DUMP_OBJS = \ apmain.o\ osunixdir.o\ osunixmap.o\ + osunixxf.o\ tbprint.o\ tbxfroot.o\ utbuffer.o\ + utdebug.o\ utexcep.o\ + utglobal.o\ utmath.o\ + utprint.o\ utstring.o\ utxferror.o\ + oslibcfs.o\ oslinuxtbl.o\ cmfsize.o\ getopt.o diff --git a/tools/power/acpi/common/cmfsize.c b/tools/power/acpi/common/cmfsize.c index 5140e5edae1..f4b953354ff 100644 --- a/tools/power/acpi/common/cmfsize.c +++ b/tools/power/acpi/common/cmfsize.c @@ -58,44 +58,46 @@ ACPI_MODULE_NAME("cmfsize") * RETURN: File Size. On error, -1 (ACPI_UINT32_MAX) * * DESCRIPTION: Get the size of a file. Uses seek-to-EOF. File must be open. - * Does not disturb the current file pointer. Uses perror for - * error messages. + * Does not disturb the current file pointer. * ******************************************************************************/ -u32 cm_get_file_size(FILE * file) +u32 cm_get_file_size(ACPI_FILE file) { long file_size; long current_offset; + acpi_status status; /* Save the current file pointer, seek to EOF to obtain file size */ - current_offset = ftell(file); + current_offset = acpi_os_get_file_offset(file); if (current_offset < 0) { goto offset_error; } - if (fseek(file, 0, SEEK_END)) { + status = acpi_os_set_file_offset(file, 0, ACPI_FILE_END); + if (ACPI_FAILURE(status)) { goto seek_error; } - file_size = ftell(file); + file_size = acpi_os_get_file_offset(file); if (file_size < 0) { goto offset_error; } /* Restore original file pointer */ - if (fseek(file, current_offset, SEEK_SET)) { + status = acpi_os_set_file_offset(file, current_offset, ACPI_FILE_BEGIN); + if (ACPI_FAILURE(status)) { goto seek_error; } return ((u32)file_size); offset_error: - perror("Could not get file offset"); + acpi_log_error("Could not get file offset"); return (ACPI_UINT32_MAX); seek_error: - perror("Could not seek file"); + acpi_log_error("Could not set file offset"); return (ACPI_UINT32_MAX); } diff --git a/tools/power/acpi/common/getopt.c b/tools/power/acpi/common/getopt.c index a302f52e4fd..2f0f34a36db 100644 --- a/tools/power/acpi/common/getopt.c +++ b/tools/power/acpi/common/getopt.c @@ -51,14 +51,12 @@ * "f|" - Option has required single-char sub-options */ -#include <stdio.h> -#include <string.h> #include <acpi/acpi.h> #include "accommon.h" #include "acapps.h" #define ACPI_OPTION_ERROR(msg, badchar) \ - if (acpi_gbl_opterr) {fprintf (stderr, "%s%c\n", msg, badchar);} + if (acpi_gbl_opterr) {acpi_log_error ("%s%c\n", msg, badchar);} int acpi_gbl_opterr = 1; int acpi_gbl_optind = 1; @@ -113,7 +111,7 @@ int acpi_getopt_argument(int argc, char **argv) * PARAMETERS: argc, argv - from main * opts - options info list * - * RETURN: Option character or EOF + * RETURN: Option character or ACPI_OPT_END * * DESCRIPTION: Get the next option * @@ -128,10 +126,10 @@ int acpi_getopt(int argc, char **argv, char *opts) if (acpi_gbl_optind >= argc || argv[acpi_gbl_optind][0] != '-' || argv[acpi_gbl_optind][1] == '\0') { - return (EOF); - } else if (strcmp(argv[acpi_gbl_optind], "--") == 0) { + return (ACPI_OPT_END); + } else if (ACPI_STRCMP(argv[acpi_gbl_optind], "--") == 0) { acpi_gbl_optind++; - return (EOF); + return (ACPI_OPT_END); } } @@ -142,7 +140,7 @@ int acpi_getopt(int argc, char **argv, char *opts) /* Make sure that the option is legal */ if (current_char == ':' || - (opts_ptr = strchr(opts, current_char)) == NULL) { + (opts_ptr = ACPI_STRCHR(opts, current_char)) == NULL) { ACPI_OPTION_ERROR("Illegal option: -", current_char); if (argv[acpi_gbl_optind][++current_char_ptr] == '\0') { diff --git a/tools/power/acpi/os_specific/service_layers/oslibcfs.c b/tools/power/acpi/os_specific/service_layers/oslibcfs.c new file mode 100644 index 00000000000..c13ff9c51d7 --- /dev/null +++ b/tools/power/acpi/os_specific/service_layers/oslibcfs.c @@ -0,0 +1,214 @@ +/****************************************************************************** + * + * Module Name: oslibcfs - C library OSL for file I/O + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include <acpi/acpi.h> +#include <stdio.h> +#include <stdarg.h> + +#define _COMPONENT ACPI_OS_SERVICES +ACPI_MODULE_NAME("oslibcfs") + +/******************************************************************************* + * + * FUNCTION: acpi_os_open_file + * + * PARAMETERS: path - File path + * modes - File operation type + * + * RETURN: File descriptor. + * + * DESCRIPTION: Open a file for reading (ACPI_FILE_READING) or/and writing + * (ACPI_FILE_WRITING). + * + ******************************************************************************/ +ACPI_FILE acpi_os_open_file(const char *path, u8 modes) +{ + ACPI_FILE file; + u32 i = 0; + char modes_str[4]; + + if (modes & ACPI_FILE_READING) { + modes_str[i++] = 'r'; + } + if (modes & ACPI_FILE_WRITING) { + modes_str[i++] = 'w'; + } + if (modes & ACPI_FILE_BINARY) { + modes_str[i++] = 'b'; + } + + modes_str[i++] = '\0'; + + file = fopen(path, modes_str); + if (!file) { + perror("Could not open file"); + } + + return (file); +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_close_file + * + * PARAMETERS: file - An open file descriptor + * + * RETURN: None. + * + * DESCRIPTION: Close a file opened via acpi_os_open_file. + * + ******************************************************************************/ + +void acpi_os_close_file(ACPI_FILE file) +{ + fclose(file); +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_read_file + * + * PARAMETERS: file - An open file descriptor + * buffer - Data buffer + * size - Data block size + * count - Number of data blocks + * + * RETURN: Number of bytes actually read. + * + * DESCRIPTION: Read from a file. + * + ******************************************************************************/ + +int +acpi_os_read_file(ACPI_FILE file, void *buffer, acpi_size size, acpi_size count) +{ + int length; + + length = fread(buffer, size, count, file); + if (length < 0) { + perror("Error reading file"); + } + + return (length); +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_write_file + * + * PARAMETERS: file - An open file descriptor + * buffer - Data buffer + * size - Data block size + * count - Number of data blocks + * + * RETURN: Number of bytes actually written. + * + * DESCRIPTION: Write to a file. + * + ******************************************************************************/ + +int +acpi_os_write_file(ACPI_FILE file, + void *buffer, acpi_size size, acpi_size count) +{ + int length; + + length = fwrite(buffer, size, count, file); + if (length < 0) { + perror("Error writing file"); + } + + return (length); +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_get_file_offset + * + * PARAMETERS: file - An open file descriptor + * + * RETURN: Current file pointer position. + * + * DESCRIPTION: Get current file offset. + * + ******************************************************************************/ + +long acpi_os_get_file_offset(ACPI_FILE file) +{ + long offset; + + offset = ftell(file); + return (offset); +} + +/******************************************************************************* + * + * FUNCTION: acpi_os_set_file_offset + * + * PARAMETERS: file - An open file descriptor + * offset - New file offset + * from - From begin/end of file + * + * RETURN: Status + * + * DESCRIPTION: Set current file offset. + * + ******************************************************************************/ + +acpi_status acpi_os_set_file_offset(ACPI_FILE file, long offset, u8 from) +{ + int ret = 0; + + if (from == ACPI_FILE_BEGIN) { + ret = fseek(file, offset, SEEK_SET); + } + if (from == ACPI_FILE_END) { + ret = fseek(file, offset, SEEK_END); + } + + if (ret < 0) { + return (AE_ERROR); + } else { + return (AE_OK); + } +} diff --git a/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c b/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c index 28c52008e85..0dc2485dedf 100644 --- a/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c +++ b/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c @@ -77,6 +77,9 @@ osl_map_table(acpi_size address, static void osl_unmap_table(struct acpi_table_header *table); +static acpi_physical_address +osl_find_rsdp_via_efi_by_keyword(FILE * file, const char *keyword); + static acpi_physical_address osl_find_rsdp_via_efi(void); static acpi_status osl_load_rsdp(void); @@ -417,6 +420,38 @@ acpi_os_get_table_by_index(u32 index, /****************************************************************************** * + * FUNCTION: osl_find_rsdp_via_efi_by_keyword + * + * PARAMETERS: keyword - Character string indicating ACPI GUID version + * in the EFI table + * + * RETURN: RSDP address if found + * + * DESCRIPTION: Find RSDP address via EFI using keyword indicating the ACPI + * GUID version. + * + *****************************************************************************/ + +static acpi_physical_address +osl_find_rsdp_via_efi_by_keyword(FILE * file, const char *keyword) +{ + char buffer[80]; + unsigned long long address = 0; + char format[32]; + + snprintf(format, 32, "%s=%s", keyword, "%llx"); + fseek(file, 0, SEEK_SET); + while (fgets(buffer, 80, file)) { + if (sscanf(buffer, format, &address) == 1) { + break; + } + } + + return ((acpi_physical_address) (address)); +} + +/****************************************************************************** + * * FUNCTION: osl_find_rsdp_via_efi * * PARAMETERS: None @@ -430,20 +465,19 @@ acpi_os_get_table_by_index(u32 index, static acpi_physical_address osl_find_rsdp_via_efi(void) { FILE *file; - char buffer[80]; - unsigned long address = 0; + acpi_physical_address address = 0; file = fopen(EFI_SYSTAB, "r"); if (file) { - while (fgets(buffer, 80, file)) { - if (sscanf(buffer, "ACPI20=0x%lx", &address) == 1) { - break; - } + address = osl_find_rsdp_via_efi_by_keyword(file, "ACPI20"); + if (!address) { + address = + osl_find_rsdp_via_efi_by_keyword(file, "ACPI"); } fclose(file); } - return ((acpi_physical_address) (address)); + return (address); } /****************************************************************************** diff --git a/tools/power/acpi/os_specific/service_layers/osunixxf.c b/tools/power/acpi/os_specific/service_layers/osunixxf.c new file mode 100644 index 00000000000..60b58cd1841 --- /dev/null +++ b/tools/power/acpi/os_specific/service_layers/osunixxf.c @@ -0,0 +1,1311 @@ +/****************************************************************************** + * + * Module Name: osunixxf - UNIX OSL interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2014, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +/* + * These interfaces are required in order to compile the ASL compiler and the + * various ACPICA tools under Linux or other Unix-like system. + */ +#include <acpi/acpi.h> +#include "accommon.h" +#include "amlcode.h" +#include "acparser.h" +#include "acdebug.h" + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <unistd.h> +#include <sys/time.h> +#include <semaphore.h> +#include <pthread.h> +#include <errno.h> + +#define _COMPONENT ACPI_OS_SERVICES +ACPI_MODULE_NAME("osunixxf") + +u8 acpi_gbl_debug_timeout = FALSE; + +/* Upcalls to acpi_exec */ + +void +ae_table_override(struct acpi_table_header *existing_table, + struct acpi_table_header **new_table); + +typedef void *(*PTHREAD_CALLBACK) (void *); + +/* Buffer used by acpi_os_vprintf */ + +#define ACPI_VPRINTF_BUFFER_SIZE 512 +#define _ASCII_NEWLINE '\n' + +/* Terminal support for acpi_exec only */ + +#ifdef ACPI_EXEC_APP +#include <termios.h> + +struct termios original_term_attributes; +int term_attributes_were_set = 0; + +acpi_status acpi_ut_read_line(char *buffer, u32 buffer_length, u32 *bytes_read); + +static void os_enter_line_edit_mode(void); + +static void os_exit_line_edit_mode(void); + +/****************************************************************************** + * + * FUNCTION: os_enter_line_edit_mode, os_exit_line_edit_mode + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Enter/Exit the raw character input mode for the terminal. + * + * Interactive line-editing support for the AML debugger. Used with the + * common/acgetline module. + * + * readline() is not used because of non-portability. It is not available + * on all systems, and if it is, often the package must be manually installed. + * + * Therefore, we use the POSIX tcgetattr/tcsetattr and do the minimal line + * editing that we need in acpi_os_get_line. + * + * If the POSIX tcgetattr/tcsetattr interfaces are unavailable, these + * calls will also work: + * For os_enter_line_edit_mode: system ("stty cbreak -echo") + * For os_exit_line_edit_mode: system ("stty cooked echo") + * + *****************************************************************************/ + +static void os_enter_line_edit_mode(void) +{ + struct termios local_term_attributes; + + /* Get and keep the original attributes */ + + if (tcgetattr(STDIN_FILENO, &original_term_attributes)) { + fprintf(stderr, "Could not get terminal attributes!\n"); + return; + } + + /* Set the new attributes to enable raw character input */ + + memcpy(&local_term_attributes, &original_term_attributes, + sizeof(struct termios)); + + local_term_attributes.c_lflag &= ~(ICANON | ECHO); + local_term_attributes.c_cc[VMIN] = 1; + local_term_attributes.c_cc[VTIME] = 0; + + if (tcsetattr(STDIN_FILENO, TCSANOW, &local_term_attributes)) { + fprintf(stderr, "Could not set terminal attributes!\n"); + return; + } + + term_attributes_were_set = 1; +} + +static void os_exit_line_edit_mode(void) +{ + + if (!term_attributes_were_set) { + return; + } + + /* Set terminal attributes back to the original values */ + + if (tcsetattr(STDIN_FILENO, TCSANOW, &original_term_attributes)) { + fprintf(stderr, "Could not restore terminal attributes!\n"); + } +} + +#else + +/* These functions are not needed for other ACPICA utilities */ + +#define os_enter_line_edit_mode() +#define os_exit_line_edit_mode() +#endif + +/****************************************************************************** + * + * FUNCTION: acpi_os_initialize, acpi_os_terminate + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initialize and terminate this module. + * + *****************************************************************************/ + +acpi_status acpi_os_initialize(void) +{ + acpi_status status; + + acpi_gbl_output_file = stdout; + + os_enter_line_edit_mode(); + + status = acpi_os_create_lock(&acpi_gbl_print_lock); + if (ACPI_FAILURE(status)) { + return (status); + } + + return (AE_OK); +} + +acpi_status acpi_os_terminate(void) +{ + + os_exit_line_edit_mode(); + return (AE_OK); +} + +#ifndef ACPI_USE_NATIVE_RSDP_POINTER +/****************************************************************************** + * + * FUNCTION: acpi_os_get_root_pointer + * + * PARAMETERS: None + * + * RETURN: RSDP physical address + * + * DESCRIPTION: Gets the ACPI root pointer (RSDP) + * + *****************************************************************************/ + +acpi_physical_address acpi_os_get_root_pointer(void) +{ + + return (0); +} +#endif + +/****************************************************************************** + * + * FUNCTION: acpi_os_predefined_override + * + * PARAMETERS: init_val - Initial value of the predefined object + * new_val - The new value for the object + * + * RETURN: Status, pointer to value. Null pointer returned if not + * overriding. + * + * DESCRIPTION: Allow the OS to override predefined names + * + *****************************************************************************/ + +acpi_status +acpi_os_predefined_override(const struct acpi_predefined_names * init_val, + acpi_string * new_val) +{ + + if (!init_val || !new_val) { + return (AE_BAD_PARAMETER); + } + + *new_val = NULL; + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_table_override + * + * PARAMETERS: existing_table - Header of current table (probably + * firmware) + * new_table - Where an entire new table is returned. + * + * RETURN: Status, pointer to new table. Null pointer returned if no + * table is available to override + * + * DESCRIPTION: Return a different version of a table if one is available + * + *****************************************************************************/ + +acpi_status +acpi_os_table_override(struct acpi_table_header * existing_table, + struct acpi_table_header ** new_table) +{ + + if (!existing_table || !new_table) { + return (AE_BAD_PARAMETER); + } + + *new_table = NULL; + +#ifdef ACPI_EXEC_APP + + ae_table_override(existing_table, new_table); + return (AE_OK); +#else + + return (AE_NO_ACPI_TABLES); +#endif +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_physical_table_override + * + * PARAMETERS: existing_table - Header of current table (probably firmware) + * new_address - Where new table address is returned + * (Physical address) + * new_table_length - Where new table length is returned + * + * RETURN: Status, address/length of new table. Null pointer returned + * if no table is available to override. + * + * DESCRIPTION: Returns AE_SUPPORT, function not used in user space. + * + *****************************************************************************/ + +acpi_status +acpi_os_physical_table_override(struct acpi_table_header * existing_table, + acpi_physical_address * new_address, + u32 *new_table_length) +{ + + return (AE_SUPPORT); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_redirect_output + * + * PARAMETERS: destination - An open file handle/pointer + * + * RETURN: None + * + * DESCRIPTION: Causes redirect of acpi_os_printf and acpi_os_vprintf + * + *****************************************************************************/ + +void acpi_os_redirect_output(void *destination) +{ + + acpi_gbl_output_file = destination; +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_printf + * + * PARAMETERS: fmt, ... - Standard printf format + * + * RETURN: None + * + * DESCRIPTION: Formatted output. Note: very similar to acpi_os_vprintf + * (performance), changes should be tracked in both functions. + * + *****************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE acpi_os_printf(const char *fmt, ...) +{ + va_list args; + u8 flags; + + flags = acpi_gbl_db_output_flags; + if (flags & ACPI_DB_REDIRECTABLE_OUTPUT) { + + /* Output is directable to either a file (if open) or the console */ + + if (acpi_gbl_debug_file) { + + /* Output file is open, send the output there */ + + va_start(args, fmt); + vfprintf(acpi_gbl_debug_file, fmt, args); + va_end(args); + } else { + /* No redirection, send output to console (once only!) */ + + flags |= ACPI_DB_CONSOLE_OUTPUT; + } + } + + if (flags & ACPI_DB_CONSOLE_OUTPUT) { + va_start(args, fmt); + vfprintf(acpi_gbl_output_file, fmt, args); + va_end(args); + } +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_vprintf + * + * PARAMETERS: fmt - Standard printf format + * args - Argument list + * + * RETURN: None + * + * DESCRIPTION: Formatted output with argument list pointer. Note: very + * similar to acpi_os_printf, changes should be tracked in both + * functions. + * + *****************************************************************************/ + +void acpi_os_vprintf(const char *fmt, va_list args) +{ + u8 flags; + char buffer[ACPI_VPRINTF_BUFFER_SIZE]; + + /* + * We build the output string in a local buffer because we may be + * outputting the buffer twice. Using vfprintf is problematic because + * some implementations modify the args pointer/structure during + * execution. Thus, we use the local buffer for portability. + * + * Note: Since this module is intended for use by the various ACPICA + * utilities/applications, we can safely declare the buffer on the stack. + * Also, This function is used for relatively small error messages only. + */ + vsnprintf(buffer, ACPI_VPRINTF_BUFFER_SIZE, fmt, args); + + flags = acpi_gbl_db_output_flags; + if (flags & ACPI_DB_REDIRECTABLE_OUTPUT) { + + /* Output is directable to either a file (if open) or the console */ + + if (acpi_gbl_debug_file) { + + /* Output file is open, send the output there */ + + fputs(buffer, acpi_gbl_debug_file); + } else { + /* No redirection, send output to console (once only!) */ + + flags |= ACPI_DB_CONSOLE_OUTPUT; + } + } + + if (flags & ACPI_DB_CONSOLE_OUTPUT) { + fputs(buffer, acpi_gbl_output_file); + } +} + +#ifndef ACPI_EXEC_APP +/****************************************************************************** + * + * FUNCTION: acpi_os_get_line + * + * PARAMETERS: buffer - Where to return the command line + * buffer_length - Maximum length of Buffer + * bytes_read - Where the actual byte count is returned + * + * RETURN: Status and actual bytes read + * + * DESCRIPTION: Get the next input line from the terminal. NOTE: For the + * acpi_exec utility, we use the acgetline module instead to + * provide line-editing and history support. + * + *****************************************************************************/ + +acpi_status acpi_os_get_line(char *buffer, u32 buffer_length, u32 *bytes_read) +{ + int input_char; + u32 end_of_line; + + /* Standard acpi_os_get_line for all utilities except acpi_exec */ + + for (end_of_line = 0;; end_of_line++) { + if (end_of_line >= buffer_length) { + return (AE_BUFFER_OVERFLOW); + } + + if ((input_char = getchar()) == EOF) { + return (AE_ERROR); + } + + if (!input_char || input_char == _ASCII_NEWLINE) { + break; + } + + buffer[end_of_line] = (char)input_char; + } + + /* Null terminate the buffer */ + + buffer[end_of_line] = 0; + + /* Return the number of bytes in the string */ + + if (bytes_read) { + *bytes_read = end_of_line; + } + + return (AE_OK); +} +#endif + +#ifndef ACPI_USE_NATIVE_MEMORY_MAPPING +/****************************************************************************** + * + * FUNCTION: acpi_os_map_memory + * + * PARAMETERS: where - Physical address of memory to be mapped + * length - How much memory to map + * + * RETURN: Pointer to mapped memory. Null on error. + * + * DESCRIPTION: Map physical memory into caller's address space + * + *****************************************************************************/ + +void *acpi_os_map_memory(acpi_physical_address where, acpi_size length) +{ + + return (ACPI_TO_POINTER((acpi_size) where)); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_unmap_memory + * + * PARAMETERS: where - Logical address of memory to be unmapped + * length - How much memory to unmap + * + * RETURN: None. + * + * DESCRIPTION: Delete a previously created mapping. Where and Length must + * correspond to a previous mapping exactly. + * + *****************************************************************************/ + +void acpi_os_unmap_memory(void *where, acpi_size length) +{ + + return; +} +#endif + +/****************************************************************************** + * + * FUNCTION: acpi_os_allocate + * + * PARAMETERS: size - Amount to allocate, in bytes + * + * RETURN: Pointer to the new allocation. Null on error. + * + * DESCRIPTION: Allocate memory. Algorithm is dependent on the OS. + * + *****************************************************************************/ + +void *acpi_os_allocate(acpi_size size) +{ + void *mem; + + mem = (void *)malloc((size_t) size); + return (mem); +} + +#ifdef USE_NATIVE_ALLOCATE_ZEROED +/****************************************************************************** + * + * FUNCTION: acpi_os_allocate_zeroed + * + * PARAMETERS: size - Amount to allocate, in bytes + * + * RETURN: Pointer to the new allocation. Null on error. + * + * DESCRIPTION: Allocate and zero memory. Algorithm is dependent on the OS. + * + *****************************************************************************/ + +void *acpi_os_allocate_zeroed(acpi_size size) +{ + void *mem; + + mem = (void *)calloc(1, (size_t) size); + return (mem); +} +#endif + +/****************************************************************************** + * + * FUNCTION: acpi_os_free + * + * PARAMETERS: mem - Pointer to previously allocated memory + * + * RETURN: None. + * + * DESCRIPTION: Free memory allocated via acpi_os_allocate + * + *****************************************************************************/ + +void acpi_os_free(void *mem) +{ + + free(mem); +} + +#ifdef ACPI_SINGLE_THREADED +/****************************************************************************** + * + * FUNCTION: Semaphore stub functions + * + * DESCRIPTION: Stub functions used for single-thread applications that do + * not require semaphore synchronization. Full implementations + * of these functions appear after the stubs. + * + *****************************************************************************/ + +acpi_status +acpi_os_create_semaphore(u32 max_units, + u32 initial_units, acpi_handle * out_handle) +{ + *out_handle = (acpi_handle) 1; + return (AE_OK); +} + +acpi_status acpi_os_delete_semaphore(acpi_handle handle) +{ + return (AE_OK); +} + +acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout) +{ + return (AE_OK); +} + +acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units) +{ + return (AE_OK); +} + +#else +/****************************************************************************** + * + * FUNCTION: acpi_os_create_semaphore + * + * PARAMETERS: initial_units - Units to be assigned to the new semaphore + * out_handle - Where a handle will be returned + * + * RETURN: Status + * + * DESCRIPTION: Create an OS semaphore + * + *****************************************************************************/ + +acpi_status +acpi_os_create_semaphore(u32 max_units, + u32 initial_units, acpi_handle * out_handle) +{ + sem_t *sem; + + if (!out_handle) { + return (AE_BAD_PARAMETER); + } +#ifdef __APPLE__ + { + char *semaphore_name = tmpnam(NULL); + + sem = + sem_open(semaphore_name, O_EXCL | O_CREAT, 0755, + initial_units); + if (!sem) { + return (AE_NO_MEMORY); + } + sem_unlink(semaphore_name); /* This just deletes the name */ + } + +#else + sem = acpi_os_allocate(sizeof(sem_t)); + if (!sem) { + return (AE_NO_MEMORY); + } + + if (sem_init(sem, 0, initial_units) == -1) { + acpi_os_free(sem); + return (AE_BAD_PARAMETER); + } +#endif + + *out_handle = (acpi_handle) sem; + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_delete_semaphore + * + * PARAMETERS: handle - Handle returned by acpi_os_create_semaphore + * + * RETURN: Status + * + * DESCRIPTION: Delete an OS semaphore + * + *****************************************************************************/ + +acpi_status acpi_os_delete_semaphore(acpi_handle handle) +{ + sem_t *sem = (sem_t *) handle; + + if (!sem) { + return (AE_BAD_PARAMETER); + } + + if (sem_destroy(sem) == -1) { + return (AE_BAD_PARAMETER); + } + + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_wait_semaphore + * + * PARAMETERS: handle - Handle returned by acpi_os_create_semaphore + * units - How many units to wait for + * msec_timeout - How long to wait (milliseconds) + * + * RETURN: Status + * + * DESCRIPTION: Wait for units + * + *****************************************************************************/ + +acpi_status +acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 msec_timeout) +{ + acpi_status status = AE_OK; + sem_t *sem = (sem_t *) handle; +#ifndef ACPI_USE_ALTERNATE_TIMEOUT + struct timespec time; + int ret_val; +#endif + + if (!sem) { + return (AE_BAD_PARAMETER); + } + + switch (msec_timeout) { + /* + * No Wait: + * -------- + * A zero timeout value indicates that we shouldn't wait - just + * acquire the semaphore if available otherwise return AE_TIME + * (a.k.a. 'would block'). + */ + case 0: + + if (sem_trywait(sem) == -1) { + status = (AE_TIME); + } + break; + + /* Wait Indefinitely */ + + case ACPI_WAIT_FOREVER: + + if (sem_wait(sem)) { + status = (AE_TIME); + } + break; + + /* Wait with msec_timeout */ + + default: + +#ifdef ACPI_USE_ALTERNATE_TIMEOUT + /* + * Alternate timeout mechanism for environments where + * sem_timedwait is not available or does not work properly. + */ + while (msec_timeout) { + if (sem_trywait(sem) == 0) { + + /* Got the semaphore */ + return (AE_OK); + } + + if (msec_timeout >= 10) { + msec_timeout -= 10; + usleep(10 * ACPI_USEC_PER_MSEC); /* ten milliseconds */ + } else { + msec_timeout--; + usleep(ACPI_USEC_PER_MSEC); /* one millisecond */ + } + } + status = (AE_TIME); +#else + /* + * The interface to sem_timedwait is an absolute time, so we need to + * get the current time, then add in the millisecond Timeout value. + */ + if (clock_gettime(CLOCK_REALTIME, &time) == -1) { + perror("clock_gettime"); + return (AE_TIME); + } + + time.tv_sec += (msec_timeout / ACPI_MSEC_PER_SEC); + time.tv_nsec += + ((msec_timeout % ACPI_MSEC_PER_SEC) * ACPI_NSEC_PER_MSEC); + + /* Handle nanosecond overflow (field must be less than one second) */ + + if (time.tv_nsec >= ACPI_NSEC_PER_SEC) { + time.tv_sec += (time.tv_nsec / ACPI_NSEC_PER_SEC); + time.tv_nsec = (time.tv_nsec % ACPI_NSEC_PER_SEC); + } + + while (((ret_val = sem_timedwait(sem, &time)) == -1) + && (errno == EINTR)) { + continue; + } + + if (ret_val != 0) { + if (errno != ETIMEDOUT) { + perror("sem_timedwait"); + } + status = (AE_TIME); + } +#endif + break; + } + + return (status); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_signal_semaphore + * + * PARAMETERS: handle - Handle returned by acpi_os_create_semaphore + * units - Number of units to send + * + * RETURN: Status + * + * DESCRIPTION: Send units + * + *****************************************************************************/ + +acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units) +{ + sem_t *sem = (sem_t *) handle; + + if (!sem) { + return (AE_BAD_PARAMETER); + } + + if (sem_post(sem) == -1) { + return (AE_LIMIT); + } + + return (AE_OK); +} + +#endif /* ACPI_SINGLE_THREADED */ + +/****************************************************************************** + * + * FUNCTION: Spinlock interfaces + * + * DESCRIPTION: Map these interfaces to semaphore interfaces + * + *****************************************************************************/ + +acpi_status acpi_os_create_lock(acpi_spinlock * out_handle) +{ + + return (acpi_os_create_semaphore(1, 1, out_handle)); +} + +void acpi_os_delete_lock(acpi_spinlock handle) +{ + acpi_os_delete_semaphore(handle); +} + +acpi_cpu_flags acpi_os_acquire_lock(acpi_handle handle) +{ + acpi_os_wait_semaphore(handle, 1, 0xFFFF); + return (0); +} + +void acpi_os_release_lock(acpi_spinlock handle, acpi_cpu_flags flags) +{ + acpi_os_signal_semaphore(handle, 1); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_install_interrupt_handler + * + * PARAMETERS: interrupt_number - Level handler should respond to. + * isr - Address of the ACPI interrupt handler + * except_ptr - Where status is returned + * + * RETURN: Handle to the newly installed handler. + * + * DESCRIPTION: Install an interrupt handler. Used to install the ACPI + * OS-independent handler. + * + *****************************************************************************/ + +u32 +acpi_os_install_interrupt_handler(u32 interrupt_number, + acpi_osd_handler service_routine, + void *context) +{ + + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_remove_interrupt_handler + * + * PARAMETERS: handle - Returned when handler was installed + * + * RETURN: Status + * + * DESCRIPTION: Uninstalls an interrupt handler. + * + *****************************************************************************/ + +acpi_status +acpi_os_remove_interrupt_handler(u32 interrupt_number, + acpi_osd_handler service_routine) +{ + + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_stall + * + * PARAMETERS: microseconds - Time to sleep + * + * RETURN: Blocks until sleep is completed. + * + * DESCRIPTION: Sleep at microsecond granularity + * + *****************************************************************************/ + +void acpi_os_stall(u32 microseconds) +{ + + if (microseconds) { + usleep(microseconds); + } +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_sleep + * + * PARAMETERS: milliseconds - Time to sleep + * + * RETURN: Blocks until sleep is completed. + * + * DESCRIPTION: Sleep at millisecond granularity + * + *****************************************************************************/ + +void acpi_os_sleep(u64 milliseconds) +{ + + /* Sleep for whole seconds */ + + sleep(milliseconds / ACPI_MSEC_PER_SEC); + + /* + * Sleep for remaining microseconds. + * Arg to usleep() is in usecs and must be less than 1,000,000 (1 second). + */ + usleep((milliseconds % ACPI_MSEC_PER_SEC) * ACPI_USEC_PER_MSEC); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_get_timer + * + * PARAMETERS: None + * + * RETURN: Current time in 100 nanosecond units + * + * DESCRIPTION: Get the current system time + * + *****************************************************************************/ + +u64 acpi_os_get_timer(void) +{ + struct timeval time; + + /* This timer has sufficient resolution for user-space application code */ + + gettimeofday(&time, NULL); + + /* (Seconds * 10^7 = 100ns(10^-7)) + (Microseconds(10^-6) * 10^1 = 100ns) */ + + return (((u64)time.tv_sec * ACPI_100NSEC_PER_SEC) + + ((u64)time.tv_usec * ACPI_100NSEC_PER_USEC)); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_read_pci_configuration + * + * PARAMETERS: pci_id - Seg/Bus/Dev + * pci_register - Device Register + * value - Buffer where value is placed + * width - Number of bits + * + * RETURN: Status + * + * DESCRIPTION: Read data from PCI configuration space + * + *****************************************************************************/ + +acpi_status +acpi_os_read_pci_configuration(struct acpi_pci_id *pci_id, + u32 pci_register, u64 *value, u32 width) +{ + + *value = 0; + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_write_pci_configuration + * + * PARAMETERS: pci_id - Seg/Bus/Dev + * pci_register - Device Register + * value - Value to be written + * width - Number of bits + * + * RETURN: Status. + * + * DESCRIPTION: Write data to PCI configuration space + * + *****************************************************************************/ + +acpi_status +acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, + u32 pci_register, u64 value, u32 width) +{ + + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_read_port + * + * PARAMETERS: address - Address of I/O port/register to read + * value - Where value is placed + * width - Number of bits + * + * RETURN: Value read from port + * + * DESCRIPTION: Read data from an I/O port or register + * + *****************************************************************************/ + +acpi_status acpi_os_read_port(acpi_io_address address, u32 *value, u32 width) +{ + + switch (width) { + case 8: + + *value = 0xFF; + break; + + case 16: + + *value = 0xFFFF; + break; + + case 32: + + *value = 0xFFFFFFFF; + break; + + default: + + return (AE_BAD_PARAMETER); + } + + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_write_port + * + * PARAMETERS: address - Address of I/O port/register to write + * value - Value to write + * width - Number of bits + * + * RETURN: None + * + * DESCRIPTION: Write data to an I/O port or register + * + *****************************************************************************/ + +acpi_status acpi_os_write_port(acpi_io_address address, u32 value, u32 width) +{ + + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_read_memory + * + * PARAMETERS: address - Physical Memory Address to read + * value - Where value is placed + * width - Number of bits (8,16,32, or 64) + * + * RETURN: Value read from physical memory address. Always returned + * as a 64-bit integer, regardless of the read width. + * + * DESCRIPTION: Read data from a physical memory address + * + *****************************************************************************/ + +acpi_status +acpi_os_read_memory(acpi_physical_address address, u64 *value, u32 width) +{ + + switch (width) { + case 8: + case 16: + case 32: + case 64: + + *value = 0; + break; + + default: + + return (AE_BAD_PARAMETER); + } + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_write_memory + * + * PARAMETERS: address - Physical Memory Address to write + * value - Value to write + * width - Number of bits (8,16,32, or 64) + * + * RETURN: None + * + * DESCRIPTION: Write data to a physical memory address + * + *****************************************************************************/ + +acpi_status +acpi_os_write_memory(acpi_physical_address address, u64 value, u32 width) +{ + + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_readable + * + * PARAMETERS: pointer - Area to be verified + * length - Size of area + * + * RETURN: TRUE if readable for entire length + * + * DESCRIPTION: Verify that a pointer is valid for reading + * + *****************************************************************************/ + +u8 acpi_os_readable(void *pointer, acpi_size length) +{ + + return (TRUE); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_writable + * + * PARAMETERS: pointer - Area to be verified + * length - Size of area + * + * RETURN: TRUE if writable for entire length + * + * DESCRIPTION: Verify that a pointer is valid for writing + * + *****************************************************************************/ + +u8 acpi_os_writable(void *pointer, acpi_size length) +{ + + return (TRUE); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_signal + * + * PARAMETERS: function - ACPI A signal function code + * info - Pointer to function-dependent structure + * + * RETURN: Status + * + * DESCRIPTION: Miscellaneous functions. Example implementation only. + * + *****************************************************************************/ + +acpi_status acpi_os_signal(u32 function, void *info) +{ + + switch (function) { + case ACPI_SIGNAL_FATAL: + + break; + + case ACPI_SIGNAL_BREAKPOINT: + + break; + + default: + + break; + } + + return (AE_OK); +} + +/* Optional multi-thread support */ + +#ifndef ACPI_SINGLE_THREADED +/****************************************************************************** + * + * FUNCTION: acpi_os_get_thread_id + * + * PARAMETERS: None + * + * RETURN: Id of the running thread + * + * DESCRIPTION: Get the ID of the current (running) thread + * + *****************************************************************************/ + +acpi_thread_id acpi_os_get_thread_id(void) +{ + pthread_t thread; + + thread = pthread_self(); + return (ACPI_CAST_PTHREAD_T(thread)); +} + +/****************************************************************************** + * + * FUNCTION: acpi_os_execute + * + * PARAMETERS: type - Type of execution + * function - Address of the function to execute + * context - Passed as a parameter to the function + * + * RETURN: Status. + * + * DESCRIPTION: Execute a new thread + * + *****************************************************************************/ + +acpi_status +acpi_os_execute(acpi_execute_type type, + acpi_osd_exec_callback function, void *context) +{ + pthread_t thread; + int ret; + + ret = + pthread_create(&thread, NULL, (PTHREAD_CALLBACK) function, context); + if (ret) { + acpi_os_printf("Create thread failed"); + } + return (0); +} + +#else /* ACPI_SINGLE_THREADED */ +acpi_thread_id acpi_os_get_thread_id(void) +{ + return (1); +} + +acpi_status +acpi_os_execute(acpi_execute_type type, + acpi_osd_exec_callback function, void *context) +{ + + function(context); + + return (AE_OK); +} + +#endif /* ACPI_SINGLE_THREADED */ + +/****************************************************************************** + * + * FUNCTION: acpi_os_wait_events_complete + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Wait for all asynchronous events to complete. This + * implementation does nothing. + * + *****************************************************************************/ + +void acpi_os_wait_events_complete(void) +{ + return; +} diff --git a/tools/power/acpi/tools/acpidump/acpidump.h b/tools/power/acpi/tools/acpidump/acpidump.h index 46f519597fe..a2d37d61063 100644 --- a/tools/power/acpi/tools/acpidump/acpidump.h +++ b/tools/power/acpi/tools/acpidump/acpidump.h @@ -47,7 +47,6 @@ #ifdef _DECLARE_GLOBALS #define EXTERN #define INIT_GLOBAL(a,b) a=b -#define DEFINE_ACPI_GLOBALS 1 #else #define EXTERN extern #define INIT_GLOBAL(a,b) a @@ -69,7 +68,7 @@ EXTERN u8 INIT_GLOBAL(gbl_verbose_mode, FALSE); EXTERN u8 INIT_GLOBAL(gbl_binary_mode, FALSE); EXTERN u8 INIT_GLOBAL(gbl_dump_customized_tables, FALSE); EXTERN u8 INIT_GLOBAL(gbl_do_not_dump_xsdt, FALSE); -EXTERN FILE INIT_GLOBAL(*gbl_output_file, NULL); +EXTERN ACPI_FILE INIT_GLOBAL(gbl_output_file, NULL); EXTERN char INIT_GLOBAL(*gbl_output_filename, NULL); EXTERN u64 INIT_GLOBAL(gbl_rsdp_base, 0); diff --git a/tools/power/acpi/tools/acpidump/apdump.c b/tools/power/acpi/tools/acpidump/apdump.c index 3cac1237836..53cee781e24 100644 --- a/tools/power/acpi/tools/acpidump/apdump.c +++ b/tools/power/acpi/tools/acpidump/apdump.c @@ -69,17 +69,16 @@ u8 ap_is_valid_header(struct acpi_table_header *table) /* Make sure signature is all ASCII and a valid ACPI name */ if (!acpi_ut_valid_acpi_name(table->signature)) { - fprintf(stderr, - "Table signature (0x%8.8X) is invalid\n", - *(u32 *)table->signature); + acpi_log_error("Table signature (0x%8.8X) is invalid\n", + *(u32 *)table->signature); return (FALSE); } /* Check for minimum table length */ if (table->length < sizeof(struct acpi_table_header)) { - fprintf(stderr, "Table length (0x%8.8X) is invalid\n", - table->length); + acpi_log_error("Table length (0x%8.8X) is invalid\n", + table->length); return (FALSE); } } @@ -116,8 +115,8 @@ u8 ap_is_valid_checksum(struct acpi_table_header *table) } if (ACPI_FAILURE(status)) { - fprintf(stderr, "%4.4s: Warning: wrong checksum in table\n", - table->signature); + acpi_log_error("%4.4s: Warning: wrong checksum in table\n", + table->signature); } return (AE_OK); @@ -196,12 +195,13 @@ ap_dump_table_buffer(struct acpi_table_header *table, * Note: simplest to just always emit a 64-bit address. acpi_xtract * utility can handle this. */ - printf("%4.4s @ 0x%8.8X%8.8X\n", table->signature, - ACPI_FORMAT_UINT64(address)); + acpi_ut_file_printf(gbl_output_file, "%4.4s @ 0x%8.8X%8.8X\n", + table->signature, ACPI_FORMAT_UINT64(address)); - acpi_ut_dump_buffer(ACPI_CAST_PTR(u8, table), table_length, - DB_BYTE_DISPLAY, 0); - printf("\n"); + acpi_ut_dump_buffer_to_file(gbl_output_file, + ACPI_CAST_PTR(u8, table), table_length, + DB_BYTE_DISPLAY, 0); + acpi_ut_file_printf(gbl_output_file, "\n"); return (0); } @@ -239,20 +239,20 @@ int ap_dump_all_tables(void) if (status == AE_LIMIT) { return (0); } else if (i == 0) { - fprintf(stderr, - "Could not get ACPI tables, %s\n", - acpi_format_exception(status)); + acpi_log_error + ("Could not get ACPI tables, %s\n", + acpi_format_exception(status)); return (-1); } else { - fprintf(stderr, - "Could not get ACPI table at index %u, %s\n", - i, acpi_format_exception(status)); + acpi_log_error + ("Could not get ACPI table at index %u, %s\n", + i, acpi_format_exception(status)); continue; } } table_status = ap_dump_table_buffer(table, instance, address); - free(table); + ACPI_FREE(table); if (table_status) { break; @@ -288,22 +288,22 @@ int ap_dump_table_by_address(char *ascii_address) status = acpi_ut_strtoul64(ascii_address, 0, &long_address); if (ACPI_FAILURE(status)) { - fprintf(stderr, "%s: Could not convert to a physical address\n", - ascii_address); + acpi_log_error("%s: Could not convert to a physical address\n", + ascii_address); return (-1); } address = (acpi_physical_address) long_address; status = acpi_os_get_table_by_address(address, &table); if (ACPI_FAILURE(status)) { - fprintf(stderr, "Could not get table at 0x%8.8X%8.8X, %s\n", - ACPI_FORMAT_UINT64(address), - acpi_format_exception(status)); + acpi_log_error("Could not get table at 0x%8.8X%8.8X, %s\n", + ACPI_FORMAT_UINT64(address), + acpi_format_exception(status)); return (-1); } table_status = ap_dump_table_buffer(table, 0, address); - free(table); + ACPI_FREE(table); return (table_status); } @@ -329,24 +329,24 @@ int ap_dump_table_by_name(char *signature) acpi_status status; int table_status; - if (strlen(signature) != ACPI_NAME_SIZE) { - fprintf(stderr, - "Invalid table signature [%s]: must be exactly 4 characters\n", - signature); + if (ACPI_STRLEN(signature) != ACPI_NAME_SIZE) { + acpi_log_error + ("Invalid table signature [%s]: must be exactly 4 characters\n", + signature); return (-1); } /* Table signatures are expected to be uppercase */ - strcpy(local_signature, signature); + ACPI_STRCPY(local_signature, signature); acpi_ut_strupr(local_signature); /* To be friendly, handle tables whose signatures do not match the name */ if (ACPI_COMPARE_NAME(local_signature, "FADT")) { - strcpy(local_signature, ACPI_SIG_FADT); + ACPI_STRCPY(local_signature, ACPI_SIG_FADT); } else if (ACPI_COMPARE_NAME(local_signature, "MADT")) { - strcpy(local_signature, ACPI_SIG_MADT); + ACPI_STRCPY(local_signature, ACPI_SIG_MADT); } /* Dump all instances of this signature (to handle multiple SSDTs) */ @@ -362,14 +362,14 @@ int ap_dump_table_by_name(char *signature) return (0); } - fprintf(stderr, - "Could not get ACPI table with signature [%s], %s\n", - local_signature, acpi_format_exception(status)); + acpi_log_error + ("Could not get ACPI table with signature [%s], %s\n", + local_signature, acpi_format_exception(status)); return (-1); } table_status = ap_dump_table_buffer(table, instance, address); - free(table); + ACPI_FREE(table); if (table_status) { break; @@ -409,43 +409,21 @@ int ap_dump_table_from_file(char *pathname) /* File must be at least as long as the table length */ if (table->length > file_size) { - fprintf(stderr, - "Table length (0x%X) is too large for input file (0x%X) %s\n", - table->length, file_size, pathname); + acpi_log_error + ("Table length (0x%X) is too large for input file (0x%X) %s\n", + table->length, file_size, pathname); goto exit; } if (gbl_verbose_mode) { - fprintf(stderr, - "Input file: %s contains table [%4.4s], 0x%X (%u) bytes\n", - pathname, table->signature, file_size, file_size); + acpi_log_error + ("Input file: %s contains table [%4.4s], 0x%X (%u) bytes\n", + pathname, table->signature, file_size, file_size); } table_status = ap_dump_table_buffer(table, 0, 0); exit: - free(table); + ACPI_FREE(table); return (table_status); } - -/****************************************************************************** - * - * FUNCTION: acpi_os* print functions - * - * DESCRIPTION: Used for linkage with ACPICA modules - * - ******************************************************************************/ - -void ACPI_INTERNAL_VAR_XFACE acpi_os_printf(const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - vfprintf(stdout, fmt, args); - va_end(args); -} - -void acpi_os_vprintf(const char *fmt, va_list args) -{ - vfprintf(stdout, fmt, args); -} diff --git a/tools/power/acpi/tools/acpidump/apfiles.c b/tools/power/acpi/tools/acpidump/apfiles.c index 4488accc010..d470046a6d8 100644 --- a/tools/power/acpi/tools/acpidump/apfiles.c +++ b/tools/power/acpi/tools/acpidump/apfiles.c @@ -44,6 +44,27 @@ #include "acpidump.h" #include "acapps.h" +/* Local prototypes */ + +static int ap_is_existing_file(char *pathname); + +static int ap_is_existing_file(char *pathname) +{ +#ifndef _GNU_EFI + struct stat stat_info; + + if (!stat(pathname, &stat_info)) { + acpi_log_error("Target path already exists, overwrite? [y|n] "); + + if (getchar() != 'y') { + return (-1); + } + } +#endif + + return 0; +} + /****************************************************************************** * * FUNCTION: ap_open_output_file @@ -59,25 +80,19 @@ int ap_open_output_file(char *pathname) { - struct stat stat_info; - FILE *file; + ACPI_FILE file; /* If file exists, prompt for overwrite */ - if (!stat(pathname, &stat_info)) { - fprintf(stderr, - "Target path already exists, overwrite? [y|n] "); - - if (getchar() != 'y') { - return (-1); - } + if (ap_is_existing_file(pathname) != 0) { + return (-1); } /* Point stdout to the file */ - file = freopen(pathname, "w", stdout); + file = acpi_os_open_file(pathname, ACPI_FILE_WRITING); if (!file) { - perror("Could not open output file"); + acpi_log_error("Could not open output file: %s\n", pathname); return (-1); } @@ -106,7 +121,7 @@ int ap_write_to_binary_file(struct acpi_table_header *table, u32 instance) { char filename[ACPI_NAME_SIZE + 16]; char instance_str[16]; - FILE *file; + ACPI_FILE file; size_t actual; u32 table_length; @@ -130,35 +145,37 @@ int ap_write_to_binary_file(struct acpi_table_header *table, u32 instance) /* Handle multiple SSDts - create different filenames for each */ if (instance > 0) { - sprintf(instance_str, "%u", instance); - strcat(filename, instance_str); + acpi_ut_snprintf(instance_str, sizeof(instance_str), "%u", + instance); + ACPI_STRCAT(filename, instance_str); } - strcat(filename, ACPI_TABLE_FILE_SUFFIX); + ACPI_STRCAT(filename, ACPI_TABLE_FILE_SUFFIX); if (gbl_verbose_mode) { - fprintf(stderr, - "Writing [%4.4s] to binary file: %s 0x%X (%u) bytes\n", - table->signature, filename, table->length, - table->length); + acpi_log_error + ("Writing [%4.4s] to binary file: %s 0x%X (%u) bytes\n", + table->signature, filename, table->length, table->length); } /* Open the file and dump the entire table in binary mode */ - file = fopen(filename, "wb"); + file = acpi_os_open_file(filename, + ACPI_FILE_WRITING | ACPI_FILE_BINARY); if (!file) { - perror("Could not open output file"); + acpi_log_error("Could not open output file: %s\n", filename); return (-1); } - actual = fwrite(table, 1, table_length, file); + actual = acpi_os_write_file(file, table, 1, table_length); if (actual != table_length) { - perror("Error writing binary output file"); - fclose(file); + acpi_log_error("Error writing binary output file: %s\n", + filename); + acpi_os_close_file(file); return (-1); } - fclose(file); + acpi_os_close_file(file); return (0); } @@ -179,15 +196,16 @@ struct acpi_table_header *ap_get_table_from_file(char *pathname, u32 *out_file_size) { struct acpi_table_header *buffer = NULL; - FILE *file; + ACPI_FILE file; u32 file_size; size_t actual; /* Must use binary mode */ - file = fopen(pathname, "rb"); + file = + acpi_os_open_file(pathname, ACPI_FILE_READING | ACPI_FILE_BINARY); if (!file) { - perror("Could not open input file"); + acpi_log_error("Could not open input file: %s\n", pathname); return (NULL); } @@ -195,27 +213,25 @@ struct acpi_table_header *ap_get_table_from_file(char *pathname, file_size = cm_get_file_size(file); if (file_size == ACPI_UINT32_MAX) { - fprintf(stderr, - "Could not get input file size: %s\n", pathname); + acpi_log_error("Could not get input file size: %s\n", pathname); goto cleanup; } /* Allocate a buffer for the entire file */ - buffer = calloc(1, file_size); + buffer = ACPI_ALLOCATE_ZEROED(file_size); if (!buffer) { - fprintf(stderr, - "Could not allocate file buffer of size: %u\n", - file_size); + acpi_log_error("Could not allocate file buffer of size: %u\n", + file_size); goto cleanup; } /* Read the entire file */ - actual = fread(buffer, 1, file_size, file); + actual = acpi_os_read_file(file, buffer, 1, file_size); if (actual != file_size) { - fprintf(stderr, "Could not read input file: %s\n", pathname); - free(buffer); + acpi_log_error("Could not read input file: %s\n", pathname); + ACPI_FREE(buffer); buffer = NULL; goto cleanup; } @@ -223,6 +239,6 @@ struct acpi_table_header *ap_get_table_from_file(char *pathname, *out_file_size = file_size; cleanup: - fclose(file); + acpi_os_close_file(file); return (buffer); } diff --git a/tools/power/acpi/tools/acpidump/apmain.c b/tools/power/acpi/tools/acpidump/apmain.c index 51e8d638db1..853b4da22c3 100644 --- a/tools/power/acpi/tools/acpidump/apmain.c +++ b/tools/power/acpi/tools/acpidump/apmain.c @@ -72,7 +72,7 @@ static void ap_display_usage(void); static int ap_do_options(int argc, char **argv); -static void ap_insert_action(char *argument, u32 to_be_done); +static int ap_insert_action(char *argument, u32 to_be_done); /* Table for deferred actions from command line options */ @@ -104,7 +104,7 @@ static void ap_display_usage(void) ACPI_OPTION("-v", "Display version information"); ACPI_OPTION("-z", "Verbose mode"); - printf("\nTable Options:\n"); + ACPI_USAGE_TEXT("\nTable Options:\n"); ACPI_OPTION("-a <Address>", "Get table via a physical address"); ACPI_OPTION("-f <BinaryFile>", "Get table via a binary file"); @@ -112,9 +112,9 @@ static void ap_display_usage(void) ACPI_OPTION("-x", "Do not use but dump XSDT"); ACPI_OPTION("-x -x", "Do not use or dump XSDT"); - printf("\n" - "Invocation without parameters dumps all available tables\n" - "Multiple mixed instances of -a, -f, and -n are supported\n\n"); + ACPI_USAGE_TEXT("\n" + "Invocation without parameters dumps all available tables\n" + "Multiple mixed instances of -a, -f, and -n are supported\n\n"); } /****************************************************************************** @@ -124,13 +124,13 @@ static void ap_display_usage(void) * PARAMETERS: argument - Pointer to the argument for this action * to_be_done - What to do to process this action * - * RETURN: None. Exits program if action table becomes full. + * RETURN: Status * * DESCRIPTION: Add an action item to the action table * ******************************************************************************/ -static void ap_insert_action(char *argument, u32 to_be_done) +static int ap_insert_action(char *argument, u32 to_be_done) { /* Insert action and check for table overflow */ @@ -140,10 +140,12 @@ static void ap_insert_action(char *argument, u32 to_be_done) current_action++; if (current_action > AP_MAX_ACTIONS) { - fprintf(stderr, "Too many table options (max %u)\n", - AP_MAX_ACTIONS); - exit(-1); + acpi_log_error("Too many table options (max %u)\n", + AP_MAX_ACTIONS); + return (-1); } + + return (0); } /****************************************************************************** @@ -166,7 +168,8 @@ static int ap_do_options(int argc, char **argv) /* Command line options */ - while ((j = acpi_getopt(argc, argv, AP_SUPPORTED_OPTIONS)) != EOF) + while ((j = + acpi_getopt(argc, argv, AP_SUPPORTED_OPTIONS)) != ACPI_OPT_END) switch (j) { /* * Global options @@ -185,12 +188,12 @@ static int ap_do_options(int argc, char **argv) case '?': ap_display_usage(); - exit(0); + return (1); case 'o': /* Redirect output to a single file */ if (ap_open_output_file(acpi_gbl_optarg)) { - exit(-1); + return (-1); } continue; @@ -200,10 +203,10 @@ static int ap_do_options(int argc, char **argv) acpi_ut_strtoul64(acpi_gbl_optarg, 0, &gbl_rsdp_base); if (ACPI_FAILURE(status)) { - fprintf(stderr, - "%s: Could not convert to a physical address\n", - acpi_gbl_optarg); - exit(-1); + acpi_log_error + ("%s: Could not convert to a physical address\n", + acpi_gbl_optarg); + return (-1); } continue; @@ -223,13 +226,13 @@ static int ap_do_options(int argc, char **argv) case 'v': /* Revision/version */ - printf(ACPI_COMMON_SIGNON(AP_UTILITY_NAME)); - exit(0); + acpi_os_printf(ACPI_COMMON_SIGNON(AP_UTILITY_NAME)); + return (1); case 'z': /* Verbose mode */ gbl_verbose_mode = TRUE; - fprintf(stderr, ACPI_COMMON_SIGNON(AP_UTILITY_NAME)); + acpi_log_error(ACPI_COMMON_SIGNON(AP_UTILITY_NAME)); continue; /* @@ -237,32 +240,40 @@ static int ap_do_options(int argc, char **argv) */ case 'a': /* Get table by physical address */ - ap_insert_action(acpi_gbl_optarg, - AP_DUMP_TABLE_BY_ADDRESS); + if (ap_insert_action + (acpi_gbl_optarg, AP_DUMP_TABLE_BY_ADDRESS)) { + return (-1); + } break; case 'f': /* Get table from a file */ - ap_insert_action(acpi_gbl_optarg, - AP_DUMP_TABLE_BY_FILE); + if (ap_insert_action + (acpi_gbl_optarg, AP_DUMP_TABLE_BY_FILE)) { + return (-1); + } break; case 'n': /* Get table by input name (signature) */ - ap_insert_action(acpi_gbl_optarg, - AP_DUMP_TABLE_BY_NAME); + if (ap_insert_action + (acpi_gbl_optarg, AP_DUMP_TABLE_BY_NAME)) { + return (-1); + } break; default: ap_display_usage(); - exit(-1); + return (-1); } /* If there are no actions, this means "get/dump all tables" */ if (current_action == 0) { - ap_insert_action(NULL, AP_DUMP_ALL_TABLES); + if (ap_insert_action(NULL, AP_DUMP_ALL_TABLES)) { + return (-1); + } } return (0); @@ -280,7 +291,11 @@ static int ap_do_options(int argc, char **argv) * ******************************************************************************/ +#ifndef _GNU_EFI int ACPI_SYSTEM_XFACE main(int argc, char *argv[]) +#else +int ACPI_SYSTEM_XFACE acpi_main(int argc, char *argv[]) +#endif { int status = 0; struct ap_dump_action *action; @@ -288,11 +303,17 @@ int ACPI_SYSTEM_XFACE main(int argc, char *argv[]) u32 i; ACPI_DEBUG_INITIALIZE(); /* For debug version only */ + acpi_os_initialize(); + gbl_output_file = ACPI_FILE_OUT; /* Process command line options */ - if (ap_do_options(argc, argv)) { - return (-1); + status = ap_do_options(argc, argv); + if (status > 0) { + return (0); + } + if (status < 0) { + return (status); } /* Get/dump ACPI table(s) as requested */ @@ -322,9 +343,8 @@ int ACPI_SYSTEM_XFACE main(int argc, char *argv[]) default: - fprintf(stderr, - "Internal error, invalid action: 0x%X\n", - action->to_be_done); + acpi_log_error("Internal error, invalid action: 0x%X\n", + action->to_be_done); return (-1); } @@ -333,18 +353,18 @@ int ACPI_SYSTEM_XFACE main(int argc, char *argv[]) } } - if (gbl_output_file) { + if (gbl_output_filename) { if (gbl_verbose_mode) { /* Summary for the output file */ file_size = cm_get_file_size(gbl_output_file); - fprintf(stderr, - "Output file %s contains 0x%X (%u) bytes\n\n", - gbl_output_filename, file_size, file_size); + acpi_log_error + ("Output file %s contains 0x%X (%u) bytes\n\n", + gbl_output_filename, file_size, file_size); } - fclose(gbl_output_file); + acpi_os_close_file(gbl_output_file); } return (status); |