From 8381c54fc0b40e727086a7f61399ae3e09ca7a95 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Wed, 20 Sep 2017 10:00:11 +0800 Subject: [PATCH 1/8] ACPICA: Hardware: Enable 64-bit support of hardware accesses ACPICA commit 6b0a604d171334f61a18bc92b44ec0437b11bf98 This patch enable 64-bit support for acpi_hw_read()/acpi_hw_write() and then convert acpi_read()/acpi_write() to invoke them. BZ 1287, fixed by Lv Zheng. Link: https://github.com/acpica/acpica/commit/6b0a604d1713 Link: https://bugs.acpica.org/show_bug.cgi?id=1287 Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/achware.h | 4 +- drivers/acpi/acpica/evgpe.c | 6 +- drivers/acpi/acpica/hwgpe.c | 4 +- drivers/acpi/acpica/hwregs.c | 72 +++++++++++---------- drivers/acpi/acpica/hwxface.c | 118 +--------------------------------- 5 files changed, 49 insertions(+), 155 deletions(-) diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h index fd4f3cacb356..cd722d8edacb 100644 --- a/drivers/acpi/acpica/achware.h +++ b/drivers/acpi/acpica/achware.h @@ -66,9 +66,9 @@ acpi_status acpi_hw_validate_register(struct acpi_generic_address *reg, u8 max_bit_width, u64 *address); -acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg); +acpi_status acpi_hw_read(u64 *value, struct acpi_generic_address *reg); -acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg); +acpi_status acpi_hw_write(u64 value, struct acpi_generic_address *reg); struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id); diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index 229382035550..263d8fc4a9e2 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -390,8 +390,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list) struct acpi_gpe_handler_info *gpe_handler_info; u32 int_status = ACPI_INTERRUPT_NOT_HANDLED; u8 enabled_status_byte; - u32 status_reg; - u32 enable_reg; + u64 status_reg; + u64 enable_reg; acpi_cpu_flags flags; u32 i; u32 j; @@ -472,7 +472,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list) gpe_register_info->base_gpe_number, gpe_register_info->base_gpe_number + (ACPI_GPE_REGISTER_WIDTH - 1), - status_reg, enable_reg, + (u32)status_reg, (u32)enable_reg, gpe_register_info->enable_for_run, gpe_register_info->enable_for_wake)); diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c index 5eb11b30a79e..09b6822aa5cc 100644 --- a/drivers/acpi/acpica/hwgpe.c +++ b/drivers/acpi/acpica/hwgpe.c @@ -99,7 +99,7 @@ acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action) { struct acpi_gpe_register_info *gpe_register_info; acpi_status status = AE_OK; - u32 enable_mask; + u64 enable_mask; u32 register_bit; ACPI_FUNCTION_ENTRY(); @@ -214,7 +214,7 @@ acpi_status acpi_hw_get_gpe_status(struct acpi_gpe_event_info *gpe_event_info, acpi_event_status *event_status) { - u32 in_byte; + u64 in_byte; u32 register_bit; struct acpi_gpe_register_info *gpe_register_info; acpi_event_status local_event_status = 0; diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index acb417b58bbb..aa6e00081915 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c @@ -220,16 +220,15 @@ acpi_hw_validate_register(struct acpi_generic_address *reg, * * RETURN: Status * - * DESCRIPTION: Read from either memory or IO space. This is a 32-bit max - * version of acpi_read, used internally since the overhead of - * 64-bit values is not needed. + * DESCRIPTION: Read from either memory or IO space. This is a 64-bit max + * version of acpi_read. * * LIMITATIONS: * space_ID must be system_memory or system_IO. * ******************************************************************************/ -acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg) +acpi_status acpi_hw_read(u64 *value, struct acpi_generic_address *reg) { u64 address; u8 access_width; @@ -244,17 +243,17 @@ acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg) /* Validate contents of the GAS register */ - status = acpi_hw_validate_register(reg, 32, &address); + status = acpi_hw_validate_register(reg, 64, &address); if (ACPI_FAILURE(status)) { return (status); } /* - * Initialize entire 32-bit return value to zero, convert access_width + * Initialize entire 64-bit return value to zero, convert access_width * into number of bits based */ *value = 0; - access_width = acpi_hw_get_access_bit_width(address, reg, 32); + access_width = acpi_hw_get_access_bit_width(address, reg, 64); bit_width = reg->bit_offset + reg->bit_width; bit_offset = reg->bit_offset; @@ -265,7 +264,7 @@ acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg) index = 0; while (bit_width) { if (bit_offset >= access_width) { - value32 = 0; + value64 = 0; bit_offset -= access_width; } else { if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { @@ -276,7 +275,6 @@ acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg) ACPI_DIV_8 (access_width), &value64, access_width); - value32 = (u32)value64; } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ status = acpi_hw_read_port((acpi_io_address) @@ -286,15 +284,16 @@ acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg) (access_width), &value32, access_width); + value64 = (u64)value32; } } /* * Use offset style bit writes because "Index * AccessWidth" is - * ensured to be less than 32-bits by acpi_hw_validate_register(). + * ensured to be less than 64-bits by acpi_hw_validate_register(). */ ACPI_SET_BITS(value, index * access_width, - ACPI_MASK_BITS_ABOVE_32(access_width), value32); + ACPI_MASK_BITS_ABOVE_64(access_width), value64); bit_width -= bit_width > access_width ? access_width : bit_width; @@ -302,8 +301,9 @@ acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg) } ACPI_DEBUG_PRINT((ACPI_DB_IO, - "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n", - *value, access_width, ACPI_FORMAT_UINT64(address), + "Read: %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n", + ACPI_FORMAT_UINT64(*value), access_width, + ACPI_FORMAT_UINT64(address), acpi_ut_get_region_name(reg->space_id))); return (status); @@ -318,20 +318,18 @@ acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg) * * RETURN: Status * - * DESCRIPTION: Write to either memory or IO space. This is a 32-bit max - * version of acpi_write, used internally since the overhead of - * 64-bit values is not needed. + * DESCRIPTION: Write to either memory or IO space. This is a 64-bit max + * version of acpi_write. * ******************************************************************************/ -acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg) +acpi_status acpi_hw_write(u64 value, struct acpi_generic_address *reg) { u64 address; u8 access_width; u32 bit_width; u8 bit_offset; u64 value64; - u32 value32; u8 index; acpi_status status; @@ -339,14 +337,14 @@ acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg) /* Validate contents of the GAS register */ - status = acpi_hw_validate_register(reg, 32, &address); + status = acpi_hw_validate_register(reg, 64, &address); if (ACPI_FAILURE(status)) { return (status); } /* Convert access_width into number of bits based */ - access_width = acpi_hw_get_access_bit_width(address, reg, 32); + access_width = acpi_hw_get_access_bit_width(address, reg, 64); bit_width = reg->bit_offset + reg->bit_width; bit_offset = reg->bit_offset; @@ -358,16 +356,15 @@ acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg) while (bit_width) { /* * Use offset style bit reads because "Index * AccessWidth" is - * ensured to be less than 32-bits by acpi_hw_validate_register(). + * ensured to be less than 64-bits by acpi_hw_validate_register(). */ - value32 = ACPI_GET_BITS(&value, index * access_width, - ACPI_MASK_BITS_ABOVE_32(access_width)); + value64 = ACPI_GET_BITS(&value, index * access_width, + ACPI_MASK_BITS_ABOVE_64(access_width)); if (bit_offset >= access_width) { bit_offset -= access_width; } else { if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { - value64 = (u64)value32; status = acpi_os_write_memory((acpi_physical_address) address + @@ -382,7 +379,7 @@ acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg) index * ACPI_DIV_8 (access_width), - value32, + (u32)value64, access_width); } } @@ -397,8 +394,9 @@ acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg) } ACPI_DEBUG_PRINT((ACPI_DB_IO, - "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n", - value, access_width, ACPI_FORMAT_UINT64(address), + "Wrote: %8.8X%8.8X width %2d to %8.8X%8.8X (%s)\n", + ACPI_FORMAT_UINT64(value), access_width, + ACPI_FORMAT_UINT64(address), acpi_ut_get_region_name(reg->space_id))); return (status); @@ -526,6 +524,7 @@ acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control) acpi_status acpi_hw_register_read(u32 register_id, u32 *return_value) { u32 value = 0; + u64 value64; acpi_status status; ACPI_FUNCTION_TRACE(hw_register_read); @@ -564,12 +563,14 @@ acpi_status acpi_hw_register_read(u32 register_id, u32 *return_value) case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ status = - acpi_hw_read(&value, &acpi_gbl_FADT.xpm2_control_block); + acpi_hw_read(&value64, &acpi_gbl_FADT.xpm2_control_block); + value = (u32)value64; break; case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ - status = acpi_hw_read(&value, &acpi_gbl_FADT.xpm_timer_block); + status = acpi_hw_read(&value64, &acpi_gbl_FADT.xpm_timer_block); + value = (u32)value64; break; case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ @@ -586,7 +587,7 @@ acpi_status acpi_hw_register_read(u32 register_id, u32 *return_value) } if (ACPI_SUCCESS(status)) { - *return_value = value; + *return_value = (u32)value; } return_ACPI_STATUS(status); @@ -622,6 +623,7 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) { acpi_status status; u32 read_value; + u64 read_value64; ACPI_FUNCTION_TRACE(hw_register_write); @@ -685,11 +687,12 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) * as per the ACPI spec. */ status = - acpi_hw_read(&read_value, + acpi_hw_read(&read_value64, &acpi_gbl_FADT.xpm2_control_block); if (ACPI_FAILURE(status)) { goto exit; } + read_value = (u32)read_value64; /* Insert the bits to be preserved */ @@ -745,22 +748,25 @@ acpi_hw_read_multiple(u32 *value, { u32 value_a = 0; u32 value_b = 0; + u64 value64; acpi_status status; /* The first register is always required */ - status = acpi_hw_read(&value_a, register_a); + status = acpi_hw_read(&value64, register_a); if (ACPI_FAILURE(status)) { return (status); } + value_a = (u32)value64; /* Second register is optional */ if (register_b->address) { - status = acpi_hw_read(&value_b, register_b); + status = acpi_hw_read(&value64, register_b); if (ACPI_FAILURE(status)) { return (status); } + value_b = (u32)value64; } /* diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index 34684ae89981..b3c6e439933c 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c @@ -125,76 +125,12 @@ ACPI_EXPORT_SYMBOL(acpi_reset) ******************************************************************************/ acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg) { - u32 value_lo; - u32 value_hi; - u32 width; - u64 address; acpi_status status; ACPI_FUNCTION_NAME(acpi_read); - if (!return_value) { - return (AE_BAD_PARAMETER); - } - - /* Validate contents of the GAS register. Allow 64-bit transfers */ - - status = acpi_hw_validate_register(reg, 64, &address); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* - * Two address spaces supported: Memory or I/O. PCI_Config is - * not supported here because the GAS structure is insufficient - */ - if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { - status = acpi_os_read_memory((acpi_physical_address) - address, return_value, - reg->bit_width); - if (ACPI_FAILURE(status)) { - return (status); - } - } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ - - value_lo = 0; - value_hi = 0; - - width = reg->bit_width; - if (width == 64) { - width = 32; /* Break into two 32-bit transfers */ - } - - status = acpi_hw_read_port((acpi_io_address) - address, &value_lo, width); - if (ACPI_FAILURE(status)) { - return (status); - } - - if (reg->bit_width == 64) { - - /* Read the top 32 bits */ - - status = acpi_hw_read_port((acpi_io_address) - (address + 4), &value_hi, - 32); - if (ACPI_FAILURE(status)) { - return (status); - } - } - - /* Set the return value only if status is AE_OK */ - - *return_value = (value_lo | ((u64)value_hi << 32)); - } - - ACPI_DEBUG_PRINT((ACPI_DB_IO, - "Read: %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n", - ACPI_FORMAT_UINT64(*return_value), reg->bit_width, - ACPI_FORMAT_UINT64(address), - acpi_ut_get_region_name(reg->space_id))); - - return (AE_OK); + status = acpi_hw_read(return_value, reg); + return (status); } ACPI_EXPORT_SYMBOL(acpi_read) @@ -213,59 +149,11 @@ ACPI_EXPORT_SYMBOL(acpi_read) ******************************************************************************/ acpi_status acpi_write(u64 value, struct acpi_generic_address *reg) { - u32 width; - u64 address; acpi_status status; ACPI_FUNCTION_NAME(acpi_write); - /* Validate contents of the GAS register. Allow 64-bit transfers */ - - status = acpi_hw_validate_register(reg, 64, &address); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* - * Two address spaces supported: Memory or IO. PCI_Config is - * not supported here because the GAS structure is insufficient - */ - if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { - status = acpi_os_write_memory((acpi_physical_address) - address, value, reg->bit_width); - if (ACPI_FAILURE(status)) { - return (status); - } - } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ - - width = reg->bit_width; - if (width == 64) { - width = 32; /* Break into two 32-bit transfers */ - } - - status = acpi_hw_write_port((acpi_io_address) - address, ACPI_LODWORD(value), - width); - if (ACPI_FAILURE(status)) { - return (status); - } - - if (reg->bit_width == 64) { - status = acpi_hw_write_port((acpi_io_address) - (address + 4), - ACPI_HIDWORD(value), 32); - if (ACPI_FAILURE(status)) { - return (status); - } - } - } - - ACPI_DEBUG_PRINT((ACPI_DB_IO, - "Wrote: %8.8X%8.8X width %2d to %8.8X%8.8X (%s)\n", - ACPI_FORMAT_UINT64(value), reg->bit_width, - ACPI_FORMAT_UINT64(address), - acpi_ut_get_region_name(reg->space_id))); - + status = acpi_hw_write(value, reg); return (status); } From 979fba9452b8111a83f555becea0a63c377e4e73 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Wed, 20 Sep 2017 10:00:20 +0800 Subject: [PATCH 2/8] ACPICA: acpiexec: Add testability of deferred table verification ACPICA commit 04c28c7549e694ea85f40bcc816039e5fbb4169c This patch adds testability of deferred table verification mechanism. As acpiexec uses dynamically allocated root table list from its very early stage, a change to acpi_reallocate_root_table() is required to allow deferred table verification mechanism to be triggered in such an environment. Note that acpi_gbl_enable_table_validation is still TRUE by default, thus: 1. Developers need to manually set acpi_gbl_enable_table_validation to FALSE for acpiexec to enable this test. 2. For all other OSPMs (Linux, BSDs, etc.), this commit is a no-op. Link: https://github.com/acpica/acpica/commit/04c28c7549e6 Signed-off-by: Lv Zheng Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/tbxface.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index 26ad596c973e..5ecb8d2e6834 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -173,10 +173,13 @@ acpi_status ACPI_INIT_FUNCTION acpi_reallocate_root_table(void) ACPI_FUNCTION_TRACE(acpi_reallocate_root_table); /* - * Only reallocate the root table if the host provided a static buffer - * for the table array in the call to acpi_initialize_tables. + * If there are tables unverified, it is required to reallocate the + * root table list to clean up invalid table entries. Otherwise only + * reallocate the root table list if the host provided a static buffer + * for the table array in the call to acpi_initialize_tables(). */ - if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { + if ((acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) && + acpi_gbl_enable_table_validation) { return_ACPI_STATUS(AE_SUPPORT); } From 81b7cb92958f50da1e0997de3289c09031c044c5 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 20 Sep 2017 10:00:30 +0800 Subject: [PATCH 3/8] ACPICA: Header support for the PDTT ACPI table ACPICA commit 9951c78746b52da7d23da4531fcfba6bf8c95b6a This is an ACPI 6.2 table. Link: https://github.com/acpica/acpica/commit/9951c78746b5 Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- include/acpi/actbl1.h | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h index 6b8714a428b6..7a89e6de94da 100644 --- a/include/acpi/actbl1.h +++ b/include/acpi/actbl1.h @@ -69,6 +69,7 @@ #define ACPI_SIG_HEST "HEST" /* Hardware Error Source Table */ #define ACPI_SIG_MADT "APIC" /* Multiple APIC Description Table */ #define ACPI_SIG_MSCT "MSCT" /* Maximum System Characteristics Table */ +#define ACPI_SIG_PDTT "PDTT" /* Processor Debug Trigger Table */ #define ACPI_SIG_PPTT "PPTT" /* Processor Properties Topology Table */ #define ACPI_SIG_SBST "SBST" /* Smart Battery Specification Table */ #define ACPI_SIG_SLIT "SLIT" /* System Locality Distance Information Table */ @@ -1280,6 +1281,35 @@ struct acpi_nfit_flush_address { u64 hint_address[1]; /* Variable length */ }; +/******************************************************************************* + * + * PDTT - Processor Debug Trigger Table (ACPI 6.2) + * Version 0 + * + ******************************************************************************/ + +struct acpi_table_pdtt { + struct acpi_table_header header; /* Common ACPI table header */ + u8 trigger_count; + u8 reserved[3]; + u32 array_offset; +}; + +/* + * PDTT Communication Channel Identifier Structure. + * The number of these structures is defined by trigger_count above, + * starting at array_offset. + */ +struct acpi_pdtt_channel { + u16 sub_channel_id; +}; + +/* Mask and Flags for above */ + +#define ACPI_PDTT_SUBCHANNEL_ID_MASK 0x00FF +#define ACPI_PDTT_RUNTIME_TRIGGER (1<<8) +#define ACPI_PPTT_WAIT_COMPLETION (1<<9) + /******************************************************************************* * * PPTT - Processor Properties Topology Table (ACPI 6.2) From fe97d28704147ba72f7d7859909f80b4bb5a17d4 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 20 Sep 2017 10:00:36 +0800 Subject: [PATCH 4/8] ACPICA: Restructure/cleanup all string-to-integer conversion functions ACPICA commit 610046d444ad781cc36673bf1f030abe50cbc61f Improve adherence to ACPI spec for implicit and explicit conversions Adds octal support for constants in ASL code Adds integer overflow errors for constants during ASL compilation Eliminates most of the existing complex flags parameters Simplify support for implicit/explicit runtime conversions Adds one new file, utilities/utstrsuppt.c Link: https://github.com/acpica/acpica/commit/610046d444ad Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/Makefile | 1 + drivers/acpi/acpica/acinterp.h | 6 +- drivers/acpi/acpica/acutils.h | 31 +- drivers/acpi/acpica/dbconvert.c | 5 +- drivers/acpi/acpica/dswexec.c | 2 +- drivers/acpi/acpica/exconcat.c | 2 +- drivers/acpi/acpica/exconvrt.c | 30 +- drivers/acpi/acpica/exmisc.c | 2 +- drivers/acpi/acpica/exresop.c | 2 +- drivers/acpi/acpica/nsconvert.c | 4 +- drivers/acpi/acpica/utstrsuppt.c | 417 ++++++++++++++++++++++ drivers/acpi/acpica/utstrtoul64.c | 432 +++++++++++------------ include/acpi/acexcep.h | 16 +- tools/power/acpi/tools/acpidump/Makefile | 1 + tools/power/acpi/tools/acpidump/apdump.c | 3 +- tools/power/acpi/tools/acpidump/apmain.c | 4 +- 16 files changed, 696 insertions(+), 262 deletions(-) create mode 100644 drivers/acpi/acpica/utstrsuppt.c diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index 1709551bc4aa..2d09b0249ac8 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile @@ -177,6 +177,7 @@ acpi-y += \ utresrc.o \ utstate.o \ utstring.o \ + utstrsuppt.o \ utstrtoul64.o \ utxface.o \ utxfinit.o \ diff --git a/drivers/acpi/acpica/acinterp.h b/drivers/acpi/acpica/acinterp.h index 29a863c85318..29555c8789a3 100644 --- a/drivers/acpi/acpica/acinterp.h +++ b/drivers/acpi/acpica/acinterp.h @@ -101,7 +101,8 @@ typedef const struct acpi_exdump_info { */ acpi_status acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, - union acpi_operand_object **result_desc, u32 flags); + union acpi_operand_object **result_desc, + u32 implicit_conversion); acpi_status acpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc, @@ -424,9 +425,6 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, struct acpi_walk_state *walk_state, u8 implicit_conversion); -#define ACPI_IMPLICIT_CONVERSION TRUE -#define ACPI_NO_IMPLICIT_CONVERSION FALSE - /* * exstoren - resolve/store object */ diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index 745134ade35f..7a568c604a75 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -141,6 +141,11 @@ extern const char *acpi_gbl_ptyp_decode[]; #define ACPI_MSG_SUFFIX \ acpi_os_printf (" (%8.8X/%s-%u)\n", ACPI_CA_VERSION, module_name, line_number) +/* Flags to indicate implicit or explicit string-to-integer conversion */ + +#define ACPI_IMPLICIT_CONVERSION TRUE +#define ACPI_NO_IMPLICIT_CONVERSION FALSE + /* Types for Resource descriptor entries */ #define ACPI_INVALID_RESOURCE 0 @@ -197,15 +202,29 @@ void acpi_ut_strlwr(char *src_string); int acpi_ut_stricmp(char *string1, char *string2); -acpi_status acpi_ut_strtoul64(char *string, u32 flags, u64 *ret_integer); +/* + * utstrsuppt - string-to-integer conversion support functions + */ +acpi_status acpi_ut_convert_octal_string(char *string, u64 *return_value); + +acpi_status acpi_ut_convert_decimal_string(char *string, u64 *return_value_ptr); + +acpi_status acpi_ut_convert_hex_string(char *string, u64 *return_value_ptr); + +char acpi_ut_remove_leading_zeros(char **string); + +u8 acpi_ut_detect_hex_prefix(char **string); + +u8 acpi_ut_detect_octal_prefix(char **string); /* - * Values for Flags above - * Note: LIMIT values correspond to acpi_gbl_integer_byte_width values (4/8) + * utstrtoul64 - string-to-integer conversion functions */ -#define ACPI_STRTOUL_32BIT 0x04 /* 4 bytes */ -#define ACPI_STRTOUL_64BIT 0x08 /* 8 bytes */ -#define ACPI_STRTOUL_BASE16 0x10 /* Default: Base10/16 */ +acpi_status acpi_ut_strtoul64(char *string, u64 *ret_integer); + +u64 acpi_ut_explicit_strtoul64(char *string); + +u64 acpi_ut_implicit_strtoul64(char *string); /* * utglobal - Global data structures and procedures diff --git a/drivers/acpi/acpica/dbconvert.c b/drivers/acpi/acpica/dbconvert.c index 857dbc43a9b1..32d546f0db2f 100644 --- a/drivers/acpi/acpica/dbconvert.c +++ b/drivers/acpi/acpica/dbconvert.c @@ -277,10 +277,7 @@ acpi_db_convert_to_object(acpi_object_type type, default: object->type = ACPI_TYPE_INTEGER; - status = acpi_ut_strtoul64(string, - (acpi_gbl_integer_byte_width | - ACPI_STRTOUL_BASE16), - &object->integer.value); + status = acpi_ut_strtoul64(string, &object->integer.value); break; } diff --git a/drivers/acpi/acpica/dswexec.c b/drivers/acpi/acpica/dswexec.c index 20d7744b06ae..22f45d090733 100644 --- a/drivers/acpi/acpica/dswexec.c +++ b/drivers/acpi/acpica/dswexec.c @@ -134,7 +134,7 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state, * object. Implicitly convert the argument if necessary. */ status = acpi_ex_convert_to_integer(obj_desc, &local_obj_desc, - ACPI_STRTOUL_BASE16); + ACPI_IMPLICIT_CONVERSION); if (ACPI_FAILURE(status)) { goto cleanup; } diff --git a/drivers/acpi/acpica/exconcat.c b/drivers/acpi/acpica/exconcat.c index 76bfb7dcae2f..59b8de2f07d3 100644 --- a/drivers/acpi/acpica/exconcat.c +++ b/drivers/acpi/acpica/exconcat.c @@ -156,7 +156,7 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, status = acpi_ex_convert_to_integer(local_operand1, &temp_operand1, - ACPI_STRTOUL_BASE16); + ACPI_IMPLICIT_CONVERSION); break; case ACPI_TYPE_BUFFER: diff --git a/drivers/acpi/acpica/exconvrt.c b/drivers/acpi/acpica/exconvrt.c index f71028e334ee..23ebadb06a95 100644 --- a/drivers/acpi/acpica/exconvrt.c +++ b/drivers/acpi/acpica/exconvrt.c @@ -57,10 +57,10 @@ acpi_ex_convert_to_ascii(u64 integer, u16 base, u8 *string, u8 max_length); * * FUNCTION: acpi_ex_convert_to_integer * - * PARAMETERS: obj_desc - Object to be converted. Must be an - * Integer, Buffer, or String - * result_desc - Where the new Integer object is returned - * flags - Used for string conversion + * PARAMETERS: obj_desc - Object to be converted. Must be an + * Integer, Buffer, or String + * result_desc - Where the new Integer object is returned + * implicit_conversion - Used for string conversion * * RETURN: Status * @@ -70,14 +70,14 @@ acpi_ex_convert_to_ascii(u64 integer, u16 base, u8 *string, u8 max_length); acpi_status acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, - union acpi_operand_object **result_desc, u32 flags) + union acpi_operand_object **result_desc, + u32 implicit_conversion) { union acpi_operand_object *return_desc; u8 *pointer; u64 result; u32 i; u32 count; - acpi_status status; ACPI_FUNCTION_TRACE_PTR(ex_convert_to_integer, obj_desc); @@ -123,12 +123,18 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, * hexadecimal as per the ACPI specification. The only exception (as * of ACPI 3.0) is that the to_integer() operator allows both decimal * and hexadecimal strings (hex prefixed with "0x"). + * + * Explicit conversion is used only by to_integer. + * All other string-to-integer conversions are implicit conversions. */ - status = acpi_ut_strtoul64(ACPI_CAST_PTR(char, pointer), - (acpi_gbl_integer_byte_width | - flags), &result); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + if (implicit_conversion) { + result = + acpi_ut_implicit_strtoul64(ACPI_CAST_PTR + (char, pointer)); + } else { + result = + acpi_ut_explicit_strtoul64(ACPI_CAST_PTR + (char, pointer)); } break; @@ -631,7 +637,7 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type, */ status = acpi_ex_convert_to_integer(source_desc, result_desc, - ACPI_STRTOUL_BASE16); + ACPI_IMPLICIT_CONVERSION); break; case ACPI_TYPE_STRING: diff --git a/drivers/acpi/acpica/exmisc.c b/drivers/acpi/acpica/exmisc.c index 1e7649ce0a7b..dbad3ebd7df5 100644 --- a/drivers/acpi/acpica/exmisc.c +++ b/drivers/acpi/acpica/exmisc.c @@ -330,7 +330,7 @@ acpi_ex_do_logical_op(u16 opcode, case ACPI_TYPE_INTEGER: status = acpi_ex_convert_to_integer(operand1, &local_operand1, - ACPI_STRTOUL_BASE16); + ACPI_IMPLICIT_CONVERSION); break; case ACPI_TYPE_STRING: diff --git a/drivers/acpi/acpica/exresop.c b/drivers/acpi/acpica/exresop.c index c4852429e2ff..1c7c9962b0de 100644 --- a/drivers/acpi/acpica/exresop.c +++ b/drivers/acpi/acpica/exresop.c @@ -415,7 +415,7 @@ acpi_ex_resolve_operands(u16 opcode, * Known as "Implicit Source Operand Conversion" */ status = acpi_ex_convert_to_integer(obj_desc, stack_ptr, - ACPI_STRTOUL_BASE16); + ACPI_IMPLICIT_CONVERSION); if (ACPI_FAILURE(status)) { if (status == AE_TYPE) { ACPI_ERROR((AE_INFO, diff --git a/drivers/acpi/acpica/nsconvert.c b/drivers/acpi/acpica/nsconvert.c index e4a7da8a11f0..539d775bbc92 100644 --- a/drivers/acpi/acpica/nsconvert.c +++ b/drivers/acpi/acpica/nsconvert.c @@ -78,8 +78,8 @@ acpi_ns_convert_to_integer(union acpi_operand_object *original_object, /* String-to-Integer conversion */ - status = acpi_ut_strtoul64(original_object->string.pointer, - acpi_gbl_integer_byte_width, &value); + status = + acpi_ut_strtoul64(original_object->string.pointer, &value); if (ACPI_FAILURE(status)) { return (status); } diff --git a/drivers/acpi/acpica/utstrsuppt.c b/drivers/acpi/acpica/utstrsuppt.c new file mode 100644 index 000000000000..ca41f037fd9a --- /dev/null +++ b/drivers/acpi/acpica/utstrsuppt.c @@ -0,0 +1,417 @@ +/******************************************************************************* + * + * Module Name: utstrsuppt - string-to-integer conversion support functions + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2017, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include "accommon.h" + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utstrsuppt") + +/* Local prototypes */ +static acpi_status +acpi_ut_insert_digit(u64 *accumulated_value, u32 base, int ascii_digit); + +static acpi_status +acpi_ut_strtoul_multiply64(u64 multiplicand, u64 multiplier, u64 *out_product); + +static acpi_status +acpi_ut_strtoul_add64(u64 addend1, u64 addend2, u64 *out_sum); + +/******************************************************************************* + * + * FUNCTION: acpi_ut_convert_octal_string + * + * PARAMETERS: string - Null terminated input string + * return_value_ptr - Where the converted value is returned + * + * RETURN: Status and 64-bit converted integer + * + * DESCRIPTION: Performs a base 8 conversion of the input string to an + * integer value, either 32 or 64 bits. + * + * NOTE: Maximum 64-bit unsigned octal value is 01777777777777777777777 + * Maximum 32-bit unsigned octal value is 037777777777 + * + ******************************************************************************/ + +acpi_status acpi_ut_convert_octal_string(char *string, u64 *return_value_ptr) +{ + u64 accumulated_value = 0; + acpi_status status = AE_OK; + + /* Convert each ASCII byte in the input string */ + + while (*string) { + + /* Must be ASCII 0-7, otherwise terminate with no error */ + + if (!(ACPI_IS_OCTAL_DIGIT(*string))) { + break; + } + + /* Convert and insert this octal digit into the accumulator */ + + status = acpi_ut_insert_digit(&accumulated_value, 8, *string); + if (ACPI_FAILURE(status)) { + status = AE_OCTAL_OVERFLOW; + break; + } + + string++; + } + + /* Always return the value that has been accumulated */ + + *return_value_ptr = accumulated_value; + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_convert_decimal_string + * + * PARAMETERS: string - Null terminated input string + * return_value_ptr - Where the converted value is returned + * + * RETURN: Status and 64-bit converted integer + * + * DESCRIPTION: Performs a base 10 conversion of the input string to an + * integer value, either 32 or 64 bits. + * + * NOTE: Maximum 64-bit unsigned decimal value is 18446744073709551615 + * Maximum 32-bit unsigned decimal value is 4294967295 + * + ******************************************************************************/ + +acpi_status acpi_ut_convert_decimal_string(char *string, u64 *return_value_ptr) +{ + u64 accumulated_value = 0; + acpi_status status = AE_OK; + + /* Convert each ASCII byte in the input string */ + + while (*string) { + + /* Must be ASCII 0-9, otherwise terminate with no error */ + + if (!isdigit(*string)) { + break; + } + + /* Convert and insert this decimal digit into the accumulator */ + + status = acpi_ut_insert_digit(&accumulated_value, 10, *string); + if (ACPI_FAILURE(status)) { + status = AE_DECIMAL_OVERFLOW; + break; + } + + string++; + } + + /* Always return the value that has been accumulated */ + + *return_value_ptr = accumulated_value; + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_convert_hex_string + * + * PARAMETERS: string - Null terminated input string + * return_value_ptr - Where the converted value is returned + * + * RETURN: Status and 64-bit converted integer + * + * DESCRIPTION: Performs a base 16 conversion of the input string to an + * integer value, either 32 or 64 bits. + * + * NOTE: Maximum 64-bit unsigned hex value is 0xFFFFFFFFFFFFFFFF + * Maximum 32-bit unsigned hex value is 0xFFFFFFFF + * + ******************************************************************************/ + +acpi_status acpi_ut_convert_hex_string(char *string, u64 *return_value_ptr) +{ + u64 accumulated_value = 0; + acpi_status status = AE_OK; + + /* Convert each ASCII byte in the input string */ + + while (*string) { + + /* Must be ASCII A-F, a-f, or 0-9, otherwise terminate with no error */ + + if (!isxdigit(*string)) { + break; + } + + /* Convert and insert this hex digit into the accumulator */ + + status = acpi_ut_insert_digit(&accumulated_value, 16, *string); + if (ACPI_FAILURE(status)) { + status = AE_HEX_OVERFLOW; + break; + } + + string++; + } + + /* Always return the value that has been accumulated */ + + *return_value_ptr = accumulated_value; + return (status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_remove_leading_zeros + * + * PARAMETERS: string - Pointer to input ASCII string + * + * RETURN: Next character after the leading zeros. This behavior may be + * Used by the caller to detect end-of-string. + * + * DESCRIPTION: Remove all leading zeros in the input string. Return the + * next character after the final zero to check for the end + * of the string (NULL terminator). + * + ******************************************************************************/ + +char acpi_ut_remove_leading_zeros(char **string) +{ + /* Skip all leading zeros */ + + while (**string == ACPI_ASCII_ZERO) { + *string += 1; + } + + return (**string); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_detect_hex_prefix + * + * PARAMETERS: string - Pointer to input ASCII string + * + * RETURN: TRUE if a 0x prefix was found + * + * DESCRIPTION: Detect and remove a hex 0x prefix + * + ******************************************************************************/ + +u8 acpi_ut_detect_hex_prefix(char **string) +{ + + if ((**string == ACPI_ASCII_ZERO) && + (tolower((int)*(*string + 1)) == 'x')) { + *string += 2; /* Go past the leading 0x */ + return (TRUE); + } + + return (FALSE); /* Not a hex string */ +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_detect_octal_prefix + * + * PARAMETERS: string - Pointer to input ASCII string + * + * RETURN: True if an octal 0 prefix was found + * + * DESCRIPTION: Detect and remove an octal prefix (zero) + * + ******************************************************************************/ + +u8 acpi_ut_detect_octal_prefix(char **string) +{ + + if (**string == ACPI_ASCII_ZERO) { + *string += 1; /* Go past the leading 0 */ + return (TRUE); + } + + return (FALSE); /* Not an octal string */ +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_insert_digit + * + * PARAMETERS: accumulated_value - Current value of the integer value + * accumulator. The New value is + * returned here. + * base - Radix, either 8/10/16 supported + * ascii_digit - ASCII single digit to be inserted + * + * RETURN: Status and result of convert/insert operation. The only + * exception is numeric overflow of either the multiply or the + * add operations. + * + * DESCRIPTION: Generic conversion and insertion function for all bases: + * + * 1) Multiply the current accumulated converted value by the + * base in order to make room for the new character. + * + * 2) Add the current accumulated/converted value the new + * character (after the character has been converted to a binary + * value). + * + * Note: The only possible exception indicates an integer + * overflow (AE_NUMERIC_OVERFLOW) + * + ******************************************************************************/ + +static acpi_status +acpi_ut_insert_digit(u64 *accumulated_value, u32 base, int ascii_digit) +{ + acpi_status status; + u64 product; + + /* Make room in the accumulated value for the incoming digit */ + + status = acpi_ut_strtoul_multiply64(*accumulated_value, base, &product); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Add in the new digit, and store to the caller's accumulated value */ + + status = + acpi_ut_strtoul_add64(product, + acpi_ut_ascii_char_to_hex(ascii_digit), + accumulated_value); + if (ACPI_FAILURE(status)) { + return (status); + } + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_strtoul_multiply64 + * + * PARAMETERS: multiplicand - Current accumulated converted integer + * multiplier - Base/Radix + * out_product - Where the product is returned + * + * RETURN: Status and 64-bit product + * + * DESCRIPTION: Multiply two 64-bit values, with checking for 64-bit overflow as + * well as 32-bit overflow if necessary (if the current global + * integer width is 32). + * + ******************************************************************************/ + +static acpi_status +acpi_ut_strtoul_multiply64(u64 multiplicand, u64 multiplier, u64 *out_product) +{ + u64 val; + + /* Exit if either operand is zero */ + + *out_product = 0; + if (!multiplicand || !multiplier) { + return (AE_OK); + } + + /* Check for 64-bit overflow before the actual multiplication */ + + acpi_ut_short_divide(ACPI_UINT64_MAX, (u32)multiplier, &val, NULL); + if (multiplicand > val) { + return (AE_NUMERIC_OVERFLOW); + } + + val = multiplicand * multiplier; + + /* Check for 32-bit overflow if necessary */ + + if ((acpi_gbl_integer_bit_width == 32) && (val > ACPI_UINT32_MAX)) { + return (AE_NUMERIC_OVERFLOW); + } + + *out_product = val; + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_strtoul_add64 + * + * PARAMETERS: addend1 - Current accumulated converted integer + * addend2 - New hex value/char + * out_sum - Where sum is returned (Accumulator) + * + * RETURN: Status and 64-bit sum + * + * DESCRIPTION: Add two 64-bit values, with checking for 64-bit overflow as + * well as 32-bit overflow if necessary (if the current global + * integer width is 32). + * + ******************************************************************************/ + +static acpi_status acpi_ut_strtoul_add64(u64 addend1, u64 addend2, u64 *out_sum) +{ + u64 sum; + + /* Check for 64-bit overflow before the actual addition */ + + if ((addend1 > 0) && (addend2 > (ACPI_UINT64_MAX - addend1))) { + return (AE_NUMERIC_OVERFLOW); + } + + sum = addend1 + addend2; + + /* Check for 32-bit overflow if necessary */ + + if ((acpi_gbl_integer_bit_width == 32) && (sum > ACPI_UINT32_MAX)) { + return (AE_NUMERIC_OVERFLOW); + } + + *out_sum = sum; + return (AE_OK); +} diff --git a/drivers/acpi/acpica/utstrtoul64.c b/drivers/acpi/acpica/utstrtoul64.c index 9633ee142855..e5a2df3f16e5 100644 --- a/drivers/acpi/acpica/utstrtoul64.c +++ b/drivers/acpi/acpica/utstrtoul64.c @@ -1,6 +1,7 @@ /******************************************************************************* * - * Module Name: utstrtoul64 - string to 64-bit integer support + * Module Name: utstrtoul64 - string-to-integer support for both 64-bit + * and 32-bit integers * ******************************************************************************/ @@ -44,106 +45,20 @@ #include #include "accommon.h" -/******************************************************************************* - * - * The functions in this module satisfy the need for 64-bit string-to-integer - * conversions on both 32-bit and 64-bit platforms. - * - ******************************************************************************/ - #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utstrtoul64") -/* Local prototypes */ -static u64 acpi_ut_strtoul_base10(char *string, u32 flags); - -static u64 acpi_ut_strtoul_base16(char *string, u32 flags); - /******************************************************************************* * - * String conversion rules as written in the ACPI specification. The error - * conditions and behavior are different depending on the type of conversion. + * This module contains the external string to 64/32-bit unsigned integer + * conversion functions: * + * 1) Standard strtoul() function with 64-bit support. This is mostly used by + * the iASL compiler. + * 2) Runtime "Explicit conversion" as defined in the ACPI specification. + * 3) Runtime "Implicit conversion" as defined in the ACPI specification. * - * Implicit data type conversion: string-to-integer - * -------------------------------------------------- - * - * Base is always 16. This is the ACPI_STRTOUL_BASE16 case. - * - * Example: - * Add ("BA98", Arg0, Local0) - * - * The integer is initialized to the value zero. - * The ASCII string is interpreted as a hexadecimal constant. - * - * 1) A "0x" prefix is not allowed. However, ACPICA allows this for - * compatibility with previous ACPICA. (NO ERROR) - * - * 2) Terminates when the size of an integer is reached (32 or 64 bits). - * (NO ERROR) - * - * 3) The first non-hex character terminates the conversion without error. - * (NO ERROR) - * - * 4) Conversion of a null (zero-length) string to an integer is not - * allowed. However, ACPICA allows this for compatibility with previous - * ACPICA. This conversion returns the value 0. (NO ERROR) - * - * - * Explicit data type conversion: to_integer() with string operand - * --------------------------------------------------------------- - * - * Base is either 10 (default) or 16 (with 0x prefix) - * - * Examples: - * to_integer ("1000") - * to_integer ("0xABCD") - * - * 1) Can be (must be) either a decimal or hexadecimal numeric string. - * A hex value must be prefixed by "0x" or it is interpreted as a decimal. - * - * 2) The value must not exceed the maximum of an integer value. ACPI spec - * states the behavior is "unpredictable", so ACPICA matches the behavior - * of the implicit conversion case.(NO ERROR) - * - * 3) Behavior on the first non-hex character is not specified by the ACPI - * spec, so ACPICA matches the behavior of the implicit conversion case - * and terminates. (NO ERROR) - * - * 4) A null (zero-length) string is illegal. - * However, ACPICA allows this for compatibility with previous ACPICA. - * This conversion returns the value 0. (NO ERROR) - * - ******************************************************************************/ - -/******************************************************************************* - * - * FUNCTION: acpi_ut_strtoul64 - * - * PARAMETERS: string - Null terminated input string - * flags - Conversion info, see below - * return_value - Where the converted integer is - * returned - * - * RETURN: Status and Converted value - * - * DESCRIPTION: Convert a string into an unsigned value. Performs either a - * 32-bit or 64-bit conversion, depending on the input integer - * size in Flags (often the current mode of the interpreter). - * - * Values for Flags: - * ACPI_STRTOUL_32BIT - Max integer value is 32 bits - * ACPI_STRTOUL_64BIT - Max integer value is 64 bits - * ACPI_STRTOUL_BASE16 - Input string is hexadecimal. Default - * is 10/16 based on string prefix (0x). - * - * NOTES: - * Negative numbers are not supported, as they are not supported by ACPI. - * - * Supports only base 16 or base 10 strings/values. Does not - * support Octal strings, as these are not supported by ACPI. - * - * Current users of this support: + * Current users of this module: * * interpreter - Implicit and explicit conversions, GPE method names * debugger - Command line input string conversion @@ -153,43 +68,51 @@ static u64 acpi_ut_strtoul_base16(char *string, u32 flags); * acpi_dump - Input table addresses * acpi_exec - Testing of the acpi_ut_strtoul64 function * - * Note concerning callers: - * acpi_gbl_integer_byte_width can be used to set the 32/64 limit. If used, - * this global should be set to the proper width. For the core ACPICA code, - * this width depends on the DSDT version. For iASL, the default byte - * width is always 8 for the parser, but error checking is performed later - * to flag cases where a 64-bit constant is defined in a 32-bit DSDT/SSDT. + * Notes concerning users of these interfaces: + * + * acpi_gbl_integer_byte_width is used to set the 32/64 bit limit. This global + * must be set to the proper width. For the core ACPICA code, the width + * depends on the DSDT version. For iASL, the default width is 64 bits for + * all parsers, but error checking is performed later to flag cases where + * a 64-bit constant is wrongly defined in a 32-bit DSDT/SSDT. + * + * In ACPI, the only place where octal numbers are supported is within + * the ASL language itself. There is no runtime support for octal. * ******************************************************************************/ - -acpi_status acpi_ut_strtoul64(char *string, u32 flags, u64 *return_value) +/******************************************************************************* + * + * FUNCTION: acpi_ut_strtoul64 + * + * PARAMETERS: string - Null terminated input string. + * Must be a valid pointer + * return_value - Where the converted integer is + * returned. Must be a valid pointer + * + * RETURN: Status and converted integer + * Returns an exception on numeric overflow + * + * DESCRIPTION: Convert a string into an unsigned integer. Performs either a + * 32-bit or 64-bit conversion, depending on the current global + * integer width. Supports Decimal, Hex, and Octal strings. + * + * Current users of this function: + * + * iASL - Preprocessor (constant math expressions) + * iASL - Main parser, conversion of ASL constants to integers + * iASL - Data Table Compiler parser (constant math expressions) + * + ******************************************************************************/ +acpi_status acpi_ut_strtoul64(char *string, u64 *return_value) { acpi_status status = AE_OK; - u32 base; + u32 base = 10; /* Default is decimal */ ACPI_FUNCTION_TRACE_STR(ut_strtoul64, string); - /* Parameter validation */ - - if (!string || !return_value) { - return_ACPI_STATUS(AE_BAD_PARAMETER); - } - *return_value = 0; - /* Check for zero-length string, returns 0 */ - - if (*string == 0) { - return_ACPI_STATUS(AE_OK); - } - - /* Skip over any white space at start of string */ - - while (isspace((int)*string)) { - string++; - } - - /* End of string? return 0 */ + /* Null return string returns a value of zero */ if (*string == 0) { return_ACPI_STATUS(AE_OK); @@ -198,45 +121,45 @@ acpi_status acpi_ut_strtoul64(char *string, u32 flags, u64 *return_value) /* * 1) The "0x" prefix indicates base 16. Per the ACPI specification, * the "0x" prefix is only allowed for implicit (non-strict) conversions. - * However, we always allow it for compatibility with older ACPICA. + * However, we always allow it for compatibility with older ACPICA and + * just plain on principle. */ - if ((*string == ACPI_ASCII_ZERO) && - (tolower((int)*(string + 1)) == 'x')) { - string += 2; /* Go past the 0x */ - if (*string == 0) { - return_ACPI_STATUS(AE_OK); /* Return value 0 */ - } - + if (acpi_ut_detect_hex_prefix(&string)) { base = 16; } - /* 2) Force to base 16 (implicit conversion case) */ - - else if (flags & ACPI_STRTOUL_BASE16) { - base = 16; + /* + * 2) Check for an octal constant, defined to be a leading zero + * followed by an valid octal digit (0-7) + */ + else if (acpi_ut_detect_octal_prefix(&string)) { + base = 8; } - /* 3) Default fallback is to Base 10 */ - - else { - base = 10; + if (!acpi_ut_remove_leading_zeros(&string)) { + return_ACPI_STATUS(AE_OK); /* Return value 0 */ } - /* Skip all leading zeros */ + /* + * Perform the base 8, 10, or 16 conversion. A numeric overflow will + * return an exception. + */ + switch (base) { + case 8: + status = acpi_ut_convert_octal_string(string, return_value); + break; - while (*string == ACPI_ASCII_ZERO) { - string++; - if (*string == 0) { - return_ACPI_STATUS(AE_OK); /* Return value 0 */ - } - } + case 10: + status = acpi_ut_convert_decimal_string(string, return_value); + break; - /* Perform the base 16 or 10 conversion */ + case 16: + status = acpi_ut_convert_hex_string(string, return_value); + break; - if (base == 16) { - *return_value = acpi_ut_strtoul_base16(string, flags); - } else { - *return_value = acpi_ut_strtoul_base10(string, flags); + default: + status = AE_AML_INTERNAL; /* Should never happen */ + break; } return_ACPI_STATUS(status); @@ -244,104 +167,167 @@ acpi_status acpi_ut_strtoul64(char *string, u32 flags, u64 *return_value) /******************************************************************************* * - * FUNCTION: acpi_ut_strtoul_base10 + * FUNCTION: acpi_ut_implicit_strtoul64 * - * PARAMETERS: string - Null terminated input string - * flags - Conversion info + * PARAMETERS: string - Null terminated input string. + * Must be a valid pointer * - * RETURN: 64-bit converted integer + * RETURN: Converted integer * - * DESCRIPTION: Performs a base 10 conversion of the input string to an - * integer value, either 32 or 64 bits. - * Note: String must be valid and non-null. + * DESCRIPTION: Perform a 64-bit conversion with restrictions placed upon + * an "implicit conversion" by the ACPI specification. Used by + * many ASL operators that require an integer operand, and support + * an automatic (implicit) conversion from a string operand + * to the final integer operand. The restriction is that only + * hex strings are supported. + * + * ----------------------------------------------------------------------------- + * + * Base is always 16, either with or without the 0x prefix. + * + * Examples (both are hex values): + * Add ("BA98", Arg0, Local0) + * Subtract ("0x12345678", Arg1, Local1) + * + * Rules extracted from the ACPI specification: + * + * The converted integer is initialized to the value zero. + * The ASCII string is interpreted as a hexadecimal constant. + * + * 1) A "0x" prefix is not allowed. However, ACPICA allows this as an + * ACPI extension on general principle. (NO ERROR) + * + * 2) Terminates when the size of an integer is reached (32 or 64 bits). + * There are no numeric overflow conditions. (NO ERROR) + * + * 3) The first non-hex character terminates the conversion and returns + * the current accumulated value of the converted integer (NO ERROR). + * + * 4) Conversion of a null (zero-length) string to an integer is + * technically allowed. However, ACPICA allows as an ACPI extension. + * The conversion returns the value 0. (NO ERROR) + * + * Note: there are no error conditions returned by this function. At + * the minimum, a value of zero is returned. + * + * Current users of this function: + * + * interpreter - All runtime implicit conversions, as per ACPI specification + * iASL - Data Table Compiler parser (constant math expressions) * ******************************************************************************/ -static u64 acpi_ut_strtoul_base10(char *string, u32 flags) +u64 acpi_ut_implicit_strtoul64(char *string) { - int ascii_digit; - u64 next_value; - u64 return_value = 0; + u64 converted_integer = 0; - /* Main loop: convert each ASCII byte in the input string */ + ACPI_FUNCTION_TRACE_STR(ut_implicit_strtoul64, string); - while (*string) { - ascii_digit = *string; - if (!isdigit(ascii_digit)) { + /* + * Per the ACPI specification, only hexadecimal is supported for + * implicit conversions, and the "0x" prefix is "not allowed". + * However, allow a "0x" prefix as an ACPI extension. + */ + acpi_ut_detect_hex_prefix(&string); - /* Not ASCII 0-9, terminate */ - - goto exit; - } - - /* Convert and insert (add) the decimal digit */ - - acpi_ut_short_multiply(return_value, 10, &next_value); - next_value += (ascii_digit - ACPI_ASCII_ZERO); - - /* Check for overflow (32 or 64 bit) - return current converted value */ - - if (((flags & ACPI_STRTOUL_32BIT) && (next_value > ACPI_UINT32_MAX)) || (next_value < return_value)) { /* 64-bit overflow case */ - goto exit; - } - - return_value = next_value; - string++; + if (!acpi_ut_remove_leading_zeros(&string)) { + return_VALUE(0); } -exit: - return (return_value); + /* + * Ignore overflow as per the ACPI specification. This is implemented by + * ignoring the return status below. On overflow, the input string is + * simply truncated. + */ + acpi_ut_convert_hex_string(string, &converted_integer); + return_VALUE(converted_integer); } /******************************************************************************* * - * FUNCTION: acpi_ut_strtoul_base16 + * FUNCTION: acpi_ut_explicit_strtoul64 * - * PARAMETERS: string - Null terminated input string - * flags - conversion info + * PARAMETERS: string - Null terminated input string. + * Must be a valid pointer * - * RETURN: 64-bit converted integer + * RETURN: Converted integer * - * DESCRIPTION: Performs a base 16 conversion of the input string to an - * integer value, either 32 or 64 bits. - * Note: String must be valid and non-null. + * DESCRIPTION: Perform a 64-bit conversion with the restrictions placed upon + * an "explicit conversion" by the ACPI specification. The + * main restriction is that only hex and decimal are supported. + * + * ----------------------------------------------------------------------------- + * + * Base is either 10 (default) or 16 (with 0x prefix). There is no octal + * (base 8), as per the ACPI specification. + * + * Examples: + * to_integer ("1000") Decimal + * to_integer ("0xABCD") Hex + * + * Rules extracted from the ACPI specification: + * + * 1) Thi input string is either a decimal or hexadecimal numeric string. + * A hex value must be prefixed by "0x" or it is interpreted as decimal. + * + * 2) The value must not exceed the maximum of an integer value + * (32 or 64 bits). The ACPI specification states the behavior is + * "unpredictable", so ACPICA matches the behavior of the implicit + * conversion case. There are no numeric overflow conditions. (NO ERROR) + * + * 3) Behavior on the first non-hex character is not specified by the ACPI + * specification (for the to_integer operator), so ACPICA matches the + * behavior of the implicit conversion case. It terminates the + * conversion and returns the current accumulated value of the converted + * integer. (NO ERROR) + * + * 4) Conversion of a null (zero-length) string to an integer is + * technically allowed. However, ACPICA allows as an ACPI extension. + * The conversion returns the value 0. (NO ERROR) + * + * Note: there are no error conditions returned by this function. At + * the minimum, a value of zero is returned. + * + * Current users of this function: + * + * interpreter - Runtime ASL to_integer operator, as per the ACPI specification * ******************************************************************************/ -static u64 acpi_ut_strtoul_base16(char *string, u32 flags) +u64 acpi_ut_explicit_strtoul64(char *string) { - int ascii_digit; - u32 valid_digits = 1; - u64 return_value = 0; + u64 converted_integer = 0; + u32 base = 10; /* Default is decimal */ - /* Main loop: convert each ASCII byte in the input string */ + ACPI_FUNCTION_TRACE_STR(ut_explicit_strtoul64, string); - while (*string) { - - /* Check for overflow (32 or 64 bit) - return current converted value */ - - if ((valid_digits > 16) || - ((valid_digits > 8) && (flags & ACPI_STRTOUL_32BIT))) { - goto exit; - } - - ascii_digit = *string; - if (!isxdigit(ascii_digit)) { - - /* Not Hex ASCII A-F, a-f, or 0-9, terminate */ - - goto exit; - } - - /* Convert and insert the hex digit */ - - acpi_ut_short_shift_left(return_value, 4, &return_value); - return_value |= acpi_ut_ascii_char_to_hex(ascii_digit); - - string++; - valid_digits++; + /* + * Only Hex and Decimal are supported, as per the ACPI specification. + * 0x prefix means hex; otherwise decimal is assumed. + */ + if (acpi_ut_detect_hex_prefix(&string)) { + base = 16; } -exit: - return (return_value); + if (!acpi_ut_remove_leading_zeros(&string)) { + return_VALUE(0); + } + + /* + * Ignore overflow as per the ACPI specification. This is implemented by + * ignoring the return status below. On overflow, the input string is + * simply truncated. + */ + switch (base) { + case 10: + default: + acpi_ut_convert_decimal_string(string, &converted_integer); + break; + + case 16: + acpi_ut_convert_hex_string(string, &converted_integer); + break; + } + + return_VALUE(converted_integer); } diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h index ad54610ea6cd..17d61b1f2511 100644 --- a/include/acpi/acexcep.h +++ b/include/acpi/acexcep.h @@ -126,8 +126,12 @@ struct acpi_exception_info { #define AE_NOT_CONFIGURED EXCEP_ENV (0x001C) #define AE_ACCESS EXCEP_ENV (0x001D) #define AE_IO_ERROR EXCEP_ENV (0x001E) +#define AE_NUMERIC_OVERFLOW EXCEP_ENV (0x001F) +#define AE_HEX_OVERFLOW EXCEP_ENV (0x0020) +#define AE_DECIMAL_OVERFLOW EXCEP_ENV (0x0021) +#define AE_OCTAL_OVERFLOW EXCEP_ENV (0x0022) -#define AE_CODE_ENV_MAX 0x001E +#define AE_CODE_ENV_MAX 0x0022 /* * Programmer exceptions @@ -263,7 +267,15 @@ static const struct acpi_exception_info acpi_gbl_exception_names_env[] = { EXCEP_TXT("AE_NOT_CONFIGURED", "The interface is not part of the current subsystem configuration"), EXCEP_TXT("AE_ACCESS", "Permission denied for the requested operation"), - EXCEP_TXT("AE_IO_ERROR", "An I/O error occurred") + EXCEP_TXT("AE_IO_ERROR", "An I/O error occurred"), + EXCEP_TXT("AE_NUMERIC_OVERFLOW", + "Overflow during string-to-integer conversion"), + EXCEP_TXT("AE_HEX_OVERFLOW", + "Overflow during ASCII hex-to-binary conversion"), + EXCEP_TXT("AE_DECIMAL_OVERFLOW", + "Overflow during ASCII decimal-to-binary conversion"), + EXCEP_TXT("AE_OCTAL_OVERFLOW", + "Overflow during ASCII octal-to-binary conversion") }; static const struct acpi_exception_info acpi_gbl_exception_names_pgm[] = { diff --git a/tools/power/acpi/tools/acpidump/Makefile b/tools/power/acpi/tools/acpidump/Makefile index f7c7af1f9258..b436f8675f6a 100644 --- a/tools/power/acpi/tools/acpidump/Makefile +++ b/tools/power/acpi/tools/acpidump/Makefile @@ -39,6 +39,7 @@ TOOL_OBJS = \ utnonansi.o\ utprint.o\ utstring.o\ + utstrsuppt.o\ utstrtoul64.o\ utxferror.o\ oslinuxtbl.o\ diff --git a/tools/power/acpi/tools/acpidump/apdump.c b/tools/power/acpi/tools/acpidump/apdump.c index 60df1fbd4a77..0634449156d8 100644 --- a/tools/power/acpi/tools/acpidump/apdump.c +++ b/tools/power/acpi/tools/acpidump/apdump.c @@ -287,8 +287,7 @@ int ap_dump_table_by_address(char *ascii_address) /* Convert argument to an integer physical address */ - status = acpi_ut_strtoul64(ascii_address, ACPI_STRTOUL_64BIT, - &long_address); + status = acpi_ut_strtoul64(ascii_address, &long_address); if (ACPI_FAILURE(status)) { fprintf(stderr, "%s: Could not convert to a physical address\n", ascii_address); diff --git a/tools/power/acpi/tools/acpidump/apmain.c b/tools/power/acpi/tools/acpidump/apmain.c index 943b6b614683..22c3b4ee1617 100644 --- a/tools/power/acpi/tools/acpidump/apmain.c +++ b/tools/power/acpi/tools/acpidump/apmain.c @@ -208,9 +208,7 @@ static int ap_do_options(int argc, char **argv) case 'r': /* Dump tables from specified RSDP */ status = - acpi_ut_strtoul64(acpi_gbl_optarg, - ACPI_STRTOUL_64BIT, - &gbl_rsdp_base); + acpi_ut_strtoul64(acpi_gbl_optarg, &gbl_rsdp_base); if (ACPI_FAILURE(status)) { fprintf(stderr, "%s: Could not convert to a physical address\n", From 72a2935502cc0f23567df649ebc644038d24abcf Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 20 Sep 2017 10:00:43 +0800 Subject: [PATCH 5/8] ACPICA: String conversions: Cleanup/format comments. No functional changes ACPICA commit 33e38cd2406709b13fa0a7821e588505b3771163 Cleanup some of the language used in the large comments, especially the ones that reference the rules in the ACPI spec. Fixed some typos. Link: https://github.com/acpica/acpica/commit/33e38cd24067 Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/utstrsuppt.c | 48 +++++++------- drivers/acpi/acpica/utstrtoul64.c | 104 +++++++++++++++--------------- 2 files changed, 74 insertions(+), 78 deletions(-) diff --git a/drivers/acpi/acpica/utstrsuppt.c b/drivers/acpi/acpica/utstrsuppt.c index ca41f037fd9a..2526ba3b4f12 100644 --- a/drivers/acpi/acpica/utstrsuppt.c +++ b/drivers/acpi/acpica/utstrsuppt.c @@ -1,6 +1,6 @@ /******************************************************************************* * - * Module Name: utstrsuppt - string-to-integer conversion support functions + * Module Name: utstrsuppt - Support functions for string-to-integer conversion * ******************************************************************************/ @@ -83,7 +83,7 @@ acpi_status acpi_ut_convert_octal_string(char *string, u64 *return_value_ptr) while (*string) { - /* Must be ASCII 0-7, otherwise terminate with no error */ + /* Character must be ASCII 0-7, otherwise terminate with no error */ if (!(ACPI_IS_OCTAL_DIGIT(*string))) { break; @@ -132,7 +132,7 @@ acpi_status acpi_ut_convert_decimal_string(char *string, u64 *return_value_ptr) while (*string) { - /* Must be ASCII 0-9, otherwise terminate with no error */ + /* Character must be ASCII 0-9, otherwise terminate with no error */ if (!isdigit(*string)) { break; @@ -210,18 +210,17 @@ acpi_status acpi_ut_convert_hex_string(char *string, u64 *return_value_ptr) * * PARAMETERS: string - Pointer to input ASCII string * - * RETURN: Next character after the leading zeros. This behavior may be - * Used by the caller to detect end-of-string. + * RETURN: Next character after any leading zeros. This character may be + * used by the caller to detect end-of-string. * - * DESCRIPTION: Remove all leading zeros in the input string. Return the - * next character after the final zero to check for the end - * of the string (NULL terminator). + * DESCRIPTION: Remove any leading zeros in the input string. Return the + * next character after the final ASCII zero to enable the caller + * to check for the end of the string (NULL terminator). * ******************************************************************************/ char acpi_ut_remove_leading_zeros(char **string) { - /* Skip all leading zeros */ while (**string == ACPI_ASCII_ZERO) { *string += 1; @@ -236,9 +235,9 @@ char acpi_ut_remove_leading_zeros(char **string) * * PARAMETERS: string - Pointer to input ASCII string * - * RETURN: TRUE if a 0x prefix was found + * RETURN: TRUE if a "0x" prefix was found at the start of the string * - * DESCRIPTION: Detect and remove a hex 0x prefix + * DESCRIPTION: Detect and remove a hex "0x" prefix * ******************************************************************************/ @@ -260,7 +259,8 @@ u8 acpi_ut_detect_hex_prefix(char **string) * * PARAMETERS: string - Pointer to input ASCII string * - * RETURN: True if an octal 0 prefix was found + * RETURN: True if an octal "0" prefix was found at the start of the + * string * * DESCRIPTION: Detect and remove an octal prefix (zero) * @@ -282,23 +282,22 @@ u8 acpi_ut_detect_octal_prefix(char **string) * FUNCTION: acpi_ut_insert_digit * * PARAMETERS: accumulated_value - Current value of the integer value - * accumulator. The New value is + * accumulator. The new value is * returned here. - * base - Radix, either 8/10/16 supported + * base - Radix, either 8/10/16 * ascii_digit - ASCII single digit to be inserted * - * RETURN: Status and result of convert/insert operation. The only - * exception is numeric overflow of either the multiply or the - * add operations. + * RETURN: Status and result of the convert/insert operation. The only + * possible returned exception code is numeric overflow of + * either the multiply or add conversion operations. * * DESCRIPTION: Generic conversion and insertion function for all bases: * - * 1) Multiply the current accumulated converted value by the + * 1) Multiply the current accumulated/converted value by the * base in order to make room for the new character. * - * 2) Add the current accumulated/converted value the new - * character (after the character has been converted to a binary - * value). + * 2) Convert the new character to binary and add it to the + * current accumulated value. * * Note: The only possible exception indicates an integer * overflow (AE_NUMERIC_OVERFLOW) @@ -318,17 +317,14 @@ acpi_ut_insert_digit(u64 *accumulated_value, u32 base, int ascii_digit) return (status); } - /* Add in the new digit, and store to the caller's accumulated value */ + /* Add in the new digit, and store the sum to the accumulated value */ status = acpi_ut_strtoul_add64(product, acpi_ut_ascii_char_to_hex(ascii_digit), accumulated_value); - if (ACPI_FAILURE(status)) { - return (status); - } - return (AE_OK); + return (status); } /******************************************************************************* diff --git a/drivers/acpi/acpica/utstrtoul64.c b/drivers/acpi/acpica/utstrtoul64.c index e5a2df3f16e5..67a39d97a6d6 100644 --- a/drivers/acpi/acpica/utstrtoul64.c +++ b/drivers/acpi/acpica/utstrtoul64.c @@ -1,7 +1,7 @@ /******************************************************************************* * - * Module Name: utstrtoul64 - string-to-integer support for both 64-bit - * and 32-bit integers + * Module Name: utstrtoul64 - String-to-integer conversion support for both + * 64-bit and 32-bit integers * ******************************************************************************/ @@ -50,21 +50,23 @@ ACPI_MODULE_NAME("utstrtoul64") /******************************************************************************* * - * This module contains the external string to 64/32-bit unsigned integer + * This module contains the top-level string to 64/32-bit unsigned integer * conversion functions: * - * 1) Standard strtoul() function with 64-bit support. This is mostly used by - * the iASL compiler. + * 1) A standard strtoul() function that supports 64-bit integers, base + * 8/10/16, with integer overflow support. This is used mainly by the + * iASL compiler, which implements tighter constraints on integer + * constants than the runtime (interpreter) integer-to-string conversions. * 2) Runtime "Explicit conversion" as defined in the ACPI specification. * 3) Runtime "Implicit conversion" as defined in the ACPI specification. * * Current users of this module: * + * iASL - Preprocessor (constants and math expressions) + * iASL - Main parser, conversion of constants to integers + * iASL - Data Table Compiler parser (constants and math expressions) * interpreter - Implicit and explicit conversions, GPE method names * debugger - Command line input string conversion - * iASL - Main parser, conversion of constants to integers - * iASL - Data Table Compiler parser (constant math expressions) - * iASL - Preprocessor (constant math expressions) * acpi_dump - Input table addresses * acpi_exec - Testing of the acpi_ut_strtoul64 function * @@ -77,15 +79,17 @@ ACPI_MODULE_NAME("utstrtoul64") * a 64-bit constant is wrongly defined in a 32-bit DSDT/SSDT. * * In ACPI, the only place where octal numbers are supported is within - * the ASL language itself. There is no runtime support for octal. + * the ASL language itself. This is implemented via the main acpi_ut_strtoul64 + * interface. According the ACPI specification, there is no ACPI runtime + * support for octal string conversions. * ******************************************************************************/ /******************************************************************************* * * FUNCTION: acpi_ut_strtoul64 * - * PARAMETERS: string - Null terminated input string. - * Must be a valid pointer + * PARAMETERS: string - Null terminated input string, + * must be a valid pointer * return_value - Where the converted integer is * returned. Must be a valid pointer * @@ -98,9 +102,9 @@ ACPI_MODULE_NAME("utstrtoul64") * * Current users of this function: * - * iASL - Preprocessor (constant math expressions) - * iASL - Main parser, conversion of ASL constants to integers - * iASL - Data Table Compiler parser (constant math expressions) + * iASL - Preprocessor (constants and math expressions) + * iASL - Main ASL parser, conversion of ASL constants to integers + * iASL - Data Table Compiler parser (constants and math expressions) * ******************************************************************************/ acpi_status acpi_ut_strtoul64(char *string, u64 *return_value) @@ -112,17 +116,14 @@ acpi_status acpi_ut_strtoul64(char *string, u64 *return_value) *return_value = 0; - /* Null return string returns a value of zero */ + /* A NULL return string returns a value of zero */ if (*string == 0) { return_ACPI_STATUS(AE_OK); } /* - * 1) The "0x" prefix indicates base 16. Per the ACPI specification, - * the "0x" prefix is only allowed for implicit (non-strict) conversions. - * However, we always allow it for compatibility with older ACPICA and - * just plain on principle. + * 1) Check for a hex constant. A "0x" prefix indicates base 16. */ if (acpi_ut_detect_hex_prefix(&string)) { base = 16; @@ -130,7 +131,7 @@ acpi_status acpi_ut_strtoul64(char *string, u64 *return_value) /* * 2) Check for an octal constant, defined to be a leading zero - * followed by an valid octal digit (0-7) + * followed by sequence of octal digits (0-7) */ else if (acpi_ut_detect_octal_prefix(&string)) { base = 8; @@ -142,7 +143,7 @@ acpi_status acpi_ut_strtoul64(char *string, u64 *return_value) /* * Perform the base 8, 10, or 16 conversion. A numeric overflow will - * return an exception. + * return an exception (to allow iASL to flag the statement). */ switch (base) { case 8: @@ -154,11 +155,8 @@ acpi_status acpi_ut_strtoul64(char *string, u64 *return_value) break; case 16: - status = acpi_ut_convert_hex_string(string, return_value); - break; - default: - status = AE_AML_INTERNAL; /* Should never happen */ + status = acpi_ut_convert_hex_string(string, return_value); break; } @@ -169,8 +167,8 @@ acpi_status acpi_ut_strtoul64(char *string, u64 *return_value) * * FUNCTION: acpi_ut_implicit_strtoul64 * - * PARAMETERS: string - Null terminated input string. - * Must be a valid pointer + * PARAMETERS: string - Null terminated input string, + * must be a valid pointer * * RETURN: Converted integer * @@ -178,42 +176,44 @@ acpi_status acpi_ut_strtoul64(char *string, u64 *return_value) * an "implicit conversion" by the ACPI specification. Used by * many ASL operators that require an integer operand, and support * an automatic (implicit) conversion from a string operand - * to the final integer operand. The restriction is that only - * hex strings are supported. + * to the final integer operand. The major restriction is that + * only hex strings are supported. * * ----------------------------------------------------------------------------- * - * Base is always 16, either with or without the 0x prefix. + * Base is always 16, either with or without the 0x prefix. Decimal and + * Octal strings are not supported, as per the ACPI specification. * * Examples (both are hex values): * Add ("BA98", Arg0, Local0) * Subtract ("0x12345678", Arg1, Local1) * - * Rules extracted from the ACPI specification: + * Conversion rules as extracted from the ACPI specification: * * The converted integer is initialized to the value zero. - * The ASCII string is interpreted as a hexadecimal constant. + * The ASCII string is always interpreted as a hexadecimal constant. * - * 1) A "0x" prefix is not allowed. However, ACPICA allows this as an - * ACPI extension on general principle. (NO ERROR) + * 1) According to the ACPI specification, a "0x" prefix is not allowed. + * However, ACPICA allows this as an ACPI extension on general + * principle. (NO ERROR) * - * 2) Terminates when the size of an integer is reached (32 or 64 bits). - * There are no numeric overflow conditions. (NO ERROR) + * 2) The conversion terminates when the size of an integer is reached + * (32 or 64 bits). There are no numeric overflow conditions. (NO ERROR) * * 3) The first non-hex character terminates the conversion and returns * the current accumulated value of the converted integer (NO ERROR). * * 4) Conversion of a null (zero-length) string to an integer is - * technically allowed. However, ACPICA allows as an ACPI extension. - * The conversion returns the value 0. (NO ERROR) + * technically not allowed. However, ACPICA allows this as an ACPI + * extension. The conversion returns the value 0. (NO ERROR) * - * Note: there are no error conditions returned by this function. At + * NOTE: There are no error conditions returned by this function. At * the minimum, a value of zero is returned. * * Current users of this function: * * interpreter - All runtime implicit conversions, as per ACPI specification - * iASL - Data Table Compiler parser (constant math expressions) + * iASL - Data Table Compiler parser (constants and math expressions) * ******************************************************************************/ @@ -247,8 +247,8 @@ u64 acpi_ut_implicit_strtoul64(char *string) * * FUNCTION: acpi_ut_explicit_strtoul64 * - * PARAMETERS: string - Null terminated input string. - * Must be a valid pointer + * PARAMETERS: string - Null terminated input string, + * must be a valid pointer * * RETURN: Converted integer * @@ -258,16 +258,16 @@ u64 acpi_ut_implicit_strtoul64(char *string) * * ----------------------------------------------------------------------------- * - * Base is either 10 (default) or 16 (with 0x prefix). There is no octal - * (base 8), as per the ACPI specification. + * Base is either 10 (default) or 16 (with 0x prefix). Octal (base 8) strings + * are not supported, as per the ACPI specification. * * Examples: * to_integer ("1000") Decimal * to_integer ("0xABCD") Hex * - * Rules extracted from the ACPI specification: + * Conversion rules as extracted from the ACPI specification: * - * 1) Thi input string is either a decimal or hexadecimal numeric string. + * 1) The input string is either a decimal or hexadecimal numeric string. * A hex value must be prefixed by "0x" or it is interpreted as decimal. * * 2) The value must not exceed the maximum of an integer value @@ -275,18 +275,18 @@ u64 acpi_ut_implicit_strtoul64(char *string) * "unpredictable", so ACPICA matches the behavior of the implicit * conversion case. There are no numeric overflow conditions. (NO ERROR) * - * 3) Behavior on the first non-hex character is not specified by the ACPI + * 3) Behavior on the first non-hex character is not defined by the ACPI * specification (for the to_integer operator), so ACPICA matches the * behavior of the implicit conversion case. It terminates the * conversion and returns the current accumulated value of the converted * integer. (NO ERROR) * * 4) Conversion of a null (zero-length) string to an integer is - * technically allowed. However, ACPICA allows as an ACPI extension. - * The conversion returns the value 0. (NO ERROR) + * technically not allowed. However, ACPICA allows this as an ACPI + * extension. The conversion returns the value 0. (NO ERROR) * - * Note: there are no error conditions returned by this function. At - * the minimum, a value of zero is returned. + * NOTE: There are no error conditions returned by this function. At the + * minimum, a value of zero is returned. * * Current users of this function: * @@ -303,7 +303,7 @@ u64 acpi_ut_explicit_strtoul64(char *string) /* * Only Hex and Decimal are supported, as per the ACPI specification. - * 0x prefix means hex; otherwise decimal is assumed. + * A "0x" prefix indicates hex; otherwise decimal is assumed. */ if (acpi_ut_detect_hex_prefix(&string)) { base = 16; From c2e56e54b2b426fdce62e1a08a77ce8e6f4b915c Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 20 Sep 2017 10:00:49 +0800 Subject: [PATCH 6/8] ACPICA: String conversions: Update to add new behaviors ACPICA commit e3574138af82a25d76324559848689946982dbd0 1) Allow whitespace in string before the constant 2) ut_strtoul64 now always creates a 64-bit integer; iASL will truncate this to the lower 32-bits if the table being compiled is a 32-bit table (DSDT revision less than 2). Link: https://github.com/acpica/acpica/commit/e3574138af82 Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acutils.h | 2 + drivers/acpi/acpica/utstrsuppt.c | 25 +++++++++++ drivers/acpi/acpica/utstrtoul64.c | 72 ++++++++++++++++++++++--------- 3 files changed, 78 insertions(+), 21 deletions(-) diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index 7a568c604a75..83b75e9db7ef 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -211,6 +211,8 @@ acpi_status acpi_ut_convert_decimal_string(char *string, u64 *return_value_ptr); acpi_status acpi_ut_convert_hex_string(char *string, u64 *return_value_ptr); +char acpi_ut_remove_whitespace(char **string); + char acpi_ut_remove_leading_zeros(char **string); u8 acpi_ut_detect_hex_prefix(char **string); diff --git a/drivers/acpi/acpica/utstrsuppt.c b/drivers/acpi/acpica/utstrsuppt.c index 2526ba3b4f12..965fb5cec94f 100644 --- a/drivers/acpi/acpica/utstrsuppt.c +++ b/drivers/acpi/acpica/utstrsuppt.c @@ -229,6 +229,31 @@ char acpi_ut_remove_leading_zeros(char **string) return (**string); } +/******************************************************************************* + * + * FUNCTION: acpi_ut_remove_whitespace + * + * PARAMETERS: string - Pointer to input ASCII string + * + * RETURN: Next character after any whitespace. This character may be + * used by the caller to detect end-of-string. + * + * DESCRIPTION: Remove any leading whitespace in the input string. Return the + * next character after the final ASCII zero to enable the caller + * to check for the end of the string (NULL terminator). + * + ******************************************************************************/ + +char acpi_ut_remove_whitespace(char **string) +{ + + while (isspace((u8)**string)) { + *string += 1; + } + + return (**string); +} + /******************************************************************************* * * FUNCTION: acpi_ut_detect_hex_prefix diff --git a/drivers/acpi/acpica/utstrtoul64.c b/drivers/acpi/acpica/utstrtoul64.c index 67a39d97a6d6..e2067dcb9389 100644 --- a/drivers/acpi/acpica/utstrtoul64.c +++ b/drivers/acpi/acpica/utstrtoul64.c @@ -66,22 +66,25 @@ ACPI_MODULE_NAME("utstrtoul64") * iASL - Main parser, conversion of constants to integers * iASL - Data Table Compiler parser (constants and math expressions) * interpreter - Implicit and explicit conversions, GPE method names + * interpreter - Repair code for return values from predefined names * debugger - Command line input string conversion - * acpi_dump - Input table addresses - * acpi_exec - Testing of the acpi_ut_strtoul64 function + * acpi_dump - ACPI table physical addresses + * acpi_exec - Support for namespace overrides * * Notes concerning users of these interfaces: * - * acpi_gbl_integer_byte_width is used to set the 32/64 bit limit. This global - * must be set to the proper width. For the core ACPICA code, the width - * depends on the DSDT version. For iASL, the default width is 64 bits for - * all parsers, but error checking is performed later to flag cases where - * a 64-bit constant is wrongly defined in a 32-bit DSDT/SSDT. + * acpi_gbl_integer_byte_width is used to set the 32/64 bit limit for explicit + * and implicit conversions. This global must be set to the proper width. + * For the core ACPICA code, the width depends on the DSDT version. For the + * acpi_ut_strtoul64 interface, all conversions are 64 bits. This interface is + * used primarily for iASL, where the default width is 64 bits for all parsers, + * but error checking is performed later to flag cases where a 64-bit constant + * is wrongly defined in a 32-bit DSDT/SSDT. * - * In ACPI, the only place where octal numbers are supported is within - * the ASL language itself. This is implemented via the main acpi_ut_strtoul64 - * interface. According the ACPI specification, there is no ACPI runtime - * support for octal string conversions. + * In ACPI, the only place where octal numbers are supported is within + * the ASL language itself. This is implemented via the main acpi_ut_strtoul64 + * interface. According the ACPI specification, there is no ACPI runtime + * support (explicit/implicit) for octal string conversions. * ******************************************************************************/ /******************************************************************************* @@ -93,11 +96,11 @@ ACPI_MODULE_NAME("utstrtoul64") * return_value - Where the converted integer is * returned. Must be a valid pointer * - * RETURN: Status and converted integer - * Returns an exception on numeric overflow + * RETURN: Status and converted integer. Returns an exception on a + * 64-bit numeric overflow * - * DESCRIPTION: Convert a string into an unsigned integer. Performs either a - * 32-bit or 64-bit conversion, depending on the current global + * DESCRIPTION: Convert a string into an unsigned integer. Always performs a + * full 64-bit conversion, regardless of the current global * integer width. Supports Decimal, Hex, and Octal strings. * * Current users of this function: @@ -105,11 +108,15 @@ ACPI_MODULE_NAME("utstrtoul64") * iASL - Preprocessor (constants and math expressions) * iASL - Main ASL parser, conversion of ASL constants to integers * iASL - Data Table Compiler parser (constants and math expressions) + * interpreter - Repair code for return values from predefined names + * acpi_dump - ACPI table physical addresses + * acpi_exec - Support for namespace overrides * ******************************************************************************/ acpi_status acpi_ut_strtoul64(char *string, u64 *return_value) { acpi_status status = AE_OK; + u8 original_bit_width; u32 base = 10; /* Default is decimal */ ACPI_FUNCTION_TRACE_STR(ut_strtoul64, string); @@ -122,6 +129,10 @@ acpi_status acpi_ut_strtoul64(char *string, u64 *return_value) return_ACPI_STATUS(AE_OK); } + if (!acpi_ut_remove_whitespace(&string)) { + return_ACPI_STATUS(AE_OK); + } + /* * 1) Check for a hex constant. A "0x" prefix indicates base 16. */ @@ -142,8 +153,16 @@ acpi_status acpi_ut_strtoul64(char *string, u64 *return_value) } /* - * Perform the base 8, 10, or 16 conversion. A numeric overflow will - * return an exception (to allow iASL to flag the statement). + * Force a full 64-bit conversion. The caller (usually iASL) must + * check for a 32-bit overflow later as necessary (If current mode + * is 32-bit, meaning a 32-bit DSDT). + */ + original_bit_width = acpi_gbl_integer_bit_width; + acpi_gbl_integer_bit_width = 64; + + /* + * Perform the base 8, 10, or 16 conversion. A 64-bit numeric overflow + * will return an exception (to allow iASL to flag the statement). */ switch (base) { case 8: @@ -160,6 +179,9 @@ acpi_status acpi_ut_strtoul64(char *string, u64 *return_value) break; } + /* Only possible exception from above is a 64-bit overflow */ + + acpi_gbl_integer_bit_width = original_bit_width; return_ACPI_STATUS(status); } @@ -223,6 +245,10 @@ u64 acpi_ut_implicit_strtoul64(char *string) ACPI_FUNCTION_TRACE_STR(ut_implicit_strtoul64, string); + if (!acpi_ut_remove_whitespace(&string)) { + return_VALUE(0); + } + /* * Per the ACPI specification, only hexadecimal is supported for * implicit conversions, and the "0x" prefix is "not allowed". @@ -236,8 +262,8 @@ u64 acpi_ut_implicit_strtoul64(char *string) /* * Ignore overflow as per the ACPI specification. This is implemented by - * ignoring the return status below. On overflow, the input string is - * simply truncated. + * ignoring the return status from the conversion function called below. + * On overflow, the input string is simply truncated. */ acpi_ut_convert_hex_string(string, &converted_integer); return_VALUE(converted_integer); @@ -301,6 +327,10 @@ u64 acpi_ut_explicit_strtoul64(char *string) ACPI_FUNCTION_TRACE_STR(ut_explicit_strtoul64, string); + if (!acpi_ut_remove_whitespace(&string)) { + return_VALUE(0); + } + /* * Only Hex and Decimal are supported, as per the ACPI specification. * A "0x" prefix indicates hex; otherwise decimal is assumed. @@ -315,8 +345,8 @@ u64 acpi_ut_explicit_strtoul64(char *string) /* * Ignore overflow as per the ACPI specification. This is implemented by - * ignoring the return status below. On overflow, the input string is - * simply truncated. + * ignoring the return status from the conversion functions called below. + * On overflow, the input string is simply truncated. */ switch (base) { case 10: From 8092936dacde0fd00e201390f30d8c219b818f36 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 20 Sep 2017 10:00:56 +0800 Subject: [PATCH 7/8] ACPICA: Update acpi_get_timer for 64-bit interface to acpi_hw_read ACPICA commit 1cdcf16447c15694faa564c0cd8e357b910344a0 Return value from acpi_hw_read is now 64 bits, but the ACPI PM Timer is defined by the ACPI spec to be 32 bits. Link: https://github.com/acpica/acpica/commit/1cdcf16447c1 Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/hwtimer.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/acpica/hwtimer.c b/drivers/acpi/acpica/hwtimer.c index b3c5d8c754bb..a2f4e25d45b1 100644 --- a/drivers/acpi/acpica/hwtimer.c +++ b/drivers/acpi/acpica/hwtimer.c @@ -94,6 +94,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_timer_resolution) acpi_status acpi_get_timer(u32 * ticks) { acpi_status status; + u64 timer_value; ACPI_FUNCTION_TRACE(acpi_get_timer); @@ -107,7 +108,14 @@ acpi_status acpi_get_timer(u32 * ticks) return_ACPI_STATUS(AE_SUPPORT); } - status = acpi_hw_read(ticks, &acpi_gbl_FADT.xpm_timer_block); + status = acpi_hw_read(&timer_value, &acpi_gbl_FADT.xpm_timer_block); + if (ACPI_SUCCESS(status)) { + + /* ACPI PM Timer is defined to be 32 bits (PM_TMR_LEN) */ + + *ticks = (u32)timer_value; + } + return_ACPI_STATUS(status); } From d954f94cfa4488f4281db2b698d90e1b03facb4d Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 20 Sep 2017 10:01:02 +0800 Subject: [PATCH 8/8] ACPICA: Update version to 20170831 ACPICA commit faa9fdfbd035a14347e6a875be2a0cddb3e6fc00 Version 20170831. Link: https://github.com/acpica/acpica/commit/faa9fdfbd035 Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- include/acpi/acpixf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 53c5e2f7bcec..e1dd1a8d42b6 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 0x20170728 +#define ACPI_CA_VERSION 0x20170831 #include #include