From 1656621717731e4a04e9e0fc6a8eec1646786bbe Mon Sep 17 00:00:00 2001 From: Erik Kaneda Date: Mon, 31 Oct 2022 11:21:32 +0800 Subject: [PATCH 01/16] ACPICA: iASL: add disassembler support for PRMT mainline inclusion from mainline-v5.14 commit d71df85aacd26fe4ac5fbfd383e01e7552ccfcc3 category: feature bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I6HNB8 CVE: N/A Intel-SIG: commit d71df85aacd2 ACPICA: iASL: add disassembler support for PRMT. ACPI Platform Runtime Mechanism feature backport. -------------------------------- ACPICA commit f70e7593e37c9e29f19be8ad3ef93f3f34799368 Link: https://github.com/acpica/acpica/commit/f70e7593 Signed-off-by: Erik Kaneda Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki Signed-off-by: Aubrey Li --- include/acpi/actbl2.h | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index b45040bdd541..93792abc4496 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -40,6 +40,7 @@ #define ACPI_SIG_PDTT "PDTT" /* Platform Debug Trigger Table */ #define ACPI_SIG_PMTT "PMTT" /* Platform Memory Topology Table */ #define ACPI_SIG_PPTT "PPTT" /* Processor Properties Topology Table */ +#define ACPI_SIG_PRMT "PRMT" /* Platform Runtime Mechanism Table */ #define ACPI_SIG_RASF "RASF" /* RAS Feature table */ #define ACPI_SIG_SBST "SBST" /* Smart Battery Specification Table */ #define ACPI_SIG_SDEI "SDEI" /* Software Delegated Exception Interface Table */ @@ -1737,6 +1738,43 @@ struct acpi_pptt_id { u16 spin_rev; }; +/******************************************************************************* + * + * PRMT - Platform Runtime Mechanism Table + * Version 1 + * + ******************************************************************************/ + +struct acpi_table_prmt { + struct acpi_table_header header; /* Common ACPI table header */ +}; + +struct acpi_table_prmt_header { + u8 platform_guid[16]; + u32 module_info_offset; + u32 module_info_count; +}; + +struct acpi_prmt_module_info { + u16 revision; + u16 length; + u8 module_guid[16]; + u16 major_rev; + u16 minor_rev; + u16 handler_info_count; + u32 handler_info_offset; + u64 mmio_list_pointer; +}; + +struct acpi_prmt_handler_info { + u16 revision; + u16 length; + u8 handler_guid[16]; + u64 handler_address; + u64 static_data_buffer_address; + u64 acpi_param_buffer_address; +}; + /******************************************************************************* * * RASF - RAS Feature Table (ACPI 5.0) -- Gitee From 1f94c01c53413bf25d5014746a24ef377b44df7c Mon Sep 17 00:00:00 2001 From: Erik Kaneda Date: Fri, 4 Jun 2021 14:26:07 -0700 Subject: [PATCH 02/16] ACPICA: Add support for PlatformRtMechanism OperationRegion handler mainline inclusion from mainline-v5.14 commit 04da290dd22c806c401913bcc1ed6356599b09c3 category: feature bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I6HNB8 CVE: N/A Intel-SIG: commit 04da290dd22c ACPICA: Add support for PlatformRtMechanism OperationRegion handler. ACPI Platform Runtime Mechanism feature backport. -------------------------------- ACPICA commit cdf48b141d7da38e47fe4020310033ddd1971f9e Writing a buffer to a PlatformRtMechanism FieldUnit invokes a bidirectional transaction. The input buffer contains 26 bytes containing 9 bytes of status, a command byte and a 16-byte UUID. This change will will simply pass this incoming buffer to a handler registered by the OS. Link: https://github.com/acpica/acpica/commit/cdf48b14 Signed-off-by: Erik Kaneda Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki Signed-off-by: Aubrey Li --- drivers/acpi/acpica/acutils.h | 2 ++ drivers/acpi/acpica/exfield.c | 8 +++++-- drivers/acpi/acpica/exserial.c | 12 ++++++++++ drivers/acpi/acpica/utuuid.c | 41 ++++++++++++++++++++++++++++++++++ include/acpi/acconfig.h | 2 ++ 5 files changed, 63 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index 7c89b470ec81..29f453726e1d 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -736,6 +736,8 @@ const char *acpi_ah_match_uuid(u8 *data); */ #if (defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP || defined ACPI_HELP_APP) void acpi_ut_convert_string_to_uuid(char *in_string, u8 *uuid_buffer); + +acpi_status acpi_ut_convert_uuid_to_string(char *uuid_buffer, char *out_string); #endif #endif /* _ACUTILS_H */ diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c index b3230e511870..c69167dc18e9 100644 --- a/drivers/acpi/acpica/exfield.c +++ b/drivers/acpi/acpica/exfield.c @@ -139,7 +139,9 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, || obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS || obj_desc->field.region_obj->region.space_id == - ACPI_ADR_SPACE_IPMI)) { + ACPI_ADR_SPACE_IPMI + || obj_desc->field.region_obj->region.space_id == + ACPI_ADR_SPACE_PLATFORM_RT)) { /* SMBus, GSBus, IPMI serial */ @@ -301,7 +303,9 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, || obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS || obj_desc->field.region_obj->region.space_id == - ACPI_ADR_SPACE_IPMI)) { + ACPI_ADR_SPACE_IPMI + || obj_desc->field.region_obj->region.space_id == + ACPI_ADR_SPACE_PLATFORM_RT)) { /* SMBus, GSBus, IPMI serial */ diff --git a/drivers/acpi/acpica/exserial.c b/drivers/acpi/acpica/exserial.c index 760bc7cef55a..a71fa64ad099 100644 --- a/drivers/acpi/acpica/exserial.c +++ b/drivers/acpi/acpica/exserial.c @@ -195,6 +195,12 @@ acpi_ex_read_serial_bus(union acpi_operand_object *obj_desc, function = ACPI_READ | (accessor_type << 16); break; + case ACPI_ADR_SPACE_PLATFORM_RT: + + buffer_length = ACPI_PRM_INPUT_BUFFER_SIZE; + function = ACPI_READ; + break; + default: return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID); } @@ -311,6 +317,12 @@ acpi_ex_write_serial_bus(union acpi_operand_object *source_desc, function = ACPI_WRITE | (accessor_type << 16); break; + case ACPI_ADR_SPACE_PLATFORM_RT: + + buffer_length = ACPI_PRM_INPUT_BUFFER_SIZE; + function = ACPI_WRITE; + break; + default: return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID); } diff --git a/drivers/acpi/acpica/utuuid.c b/drivers/acpi/acpica/utuuid.c index b8039954b0d1..1874c094adaf 100644 --- a/drivers/acpi/acpica/utuuid.c +++ b/drivers/acpi/acpica/utuuid.c @@ -61,4 +61,45 @@ void acpi_ut_convert_string_to_uuid(char *in_string, u8 *uuid_buffer) 1]); } } + +/******************************************************************************* + * + * FUNCTION: acpi_ut_convert_uuid_to_string + * + * PARAMETERS: uuid_buffer - 16-byte UUID buffer + * out_string - 36-byte formatted UUID string + * + * RETURN: Status + * + * DESCRIPTION: Convert 16-byte UUID buffer to 36-byte formatted UUID string + * out_string must be 37 bytes to include null terminator. + * + ******************************************************************************/ + +acpi_status acpi_ut_convert_uuid_to_string(char *uuid_buffer, char *out_string) +{ + u32 i; + + if (!uuid_buffer || !out_string) { + return (AE_BAD_PARAMETER); + } + + for (i = 0; i < UUID_BUFFER_LENGTH; i++) { + out_string[acpi_gbl_map_to_uuid_offset[i]] = + acpi_ut_hex_to_ascii_char(uuid_buffer[i], 4); + + out_string[acpi_gbl_map_to_uuid_offset[i] + 1] = + acpi_ut_hex_to_ascii_char(uuid_buffer[i], 0); + } + + /* Insert required hyphens (dashes) */ + + out_string[UUID_HYPHEN1_OFFSET] = + out_string[UUID_HYPHEN2_OFFSET] = + out_string[UUID_HYPHEN3_OFFSET] = + out_string[UUID_HYPHEN4_OFFSET] = '-'; + + out_string[UUID_STRING_LENGTH] = 0; /* Null terminate */ + return (AE_OK); +} #endif diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index a225eff499c8..f3a140e75776 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -188,6 +188,8 @@ #define ACPI_MAX_GSBUS_DATA_SIZE 255 #define ACPI_MAX_GSBUS_BUFFER_SIZE ACPI_SERIAL_HEADER_SIZE + ACPI_MAX_GSBUS_DATA_SIZE +#define ACPI_PRM_INPUT_BUFFER_SIZE 26 + /* _sx_d and _sx_w control methods */ #define ACPI_NUM_sx_d_METHODS 4 -- Gitee From 7aa9b95b8fe8c2b948a7bb5f9bf2da44ded8c8b9 Mon Sep 17 00:00:00 2001 From: Erik Kaneda Date: Wed, 9 Jun 2021 20:41:51 -0700 Subject: [PATCH 03/16] ACPICA: Add PRMT module header to facilitate parsing mainline inclusion from mainline-v5.14 commit 9f8c7baedabc9693fbd7890f8fda40578bde4f73 category: feature bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I6HNB8 CVE: N/A Intel-SIG: commit 9f8c7baedabc ACPICA: Add PRMT module header to facilitate parsing. ACPI Platform Runtime Mechanism feature backport. -------------------------------- ACPICA commit bd46cb07e614fd85ea69e54c1f6f0ae0a5fb20ab This structure is used in to parse PRMT in other Operating Systems that relies on using subtable headers in order to parse ACPI tables. Although the PRMT doesn't have "subtables" it has a list of module information structures that act as subtables. Link: https://github.com/acpica/acpica/commit/bd46cb07 Signed-off-by: Erik Kaneda Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki Signed-off-by: Aubrey Li --- include/acpi/actbl2.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index 93792abc4496..cbe7b567ab3b 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -1755,6 +1755,11 @@ struct acpi_table_prmt_header { u32 module_info_count; }; +struct acpi_prmt_module_header { + u16 revision; + u16 length; +}; + struct acpi_prmt_module_info { u16 revision; u16 length; -- Gitee From 93449d3298407bf46b757ab05b96bc4bc5e8e9bd Mon Sep 17 00:00:00 2001 From: Erik Kaneda Date: Fri, 24 Feb 2023 15:35:29 +0800 Subject: [PATCH 04/16] ACPI: PRM: implement OperationRegion handler for the PlatformRtMechanism subtype mainline inclusion from mainline-v5.14 commit cefc7ca46235f01d5233e3abd4b79452af01d9e9 category: feature bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I6HNB8 CVE: N/A Intel-SIG: commit cefc7ca46235 ACPI: PRM: implement OperationRegion handler for the PlatformRtMechanism subtype. ACPI Platform Runtime Mechanism feature backport. -------------------------------- Platform Runtime Mechanism (PRM) is a firmware interface that exposes a set of binary executables that can either be called from the AML interpreter or device drivers by bypassing the AML interpreter. This change implements the AML interpreter path. According to the specification [1], PRM services are listed in an ACPI table called the PRMT. This patch parses module and handler information listed in the PRMT and registers the PlatformRtMechanism OpRegion handler before ACPI tables are loaded. Each service is defined by a 16-byte GUID and called from writing a 26-byte ASL buffer containing the identifier to a FieldUnit object defined inside a PlatformRtMechanism OperationRegion. OperationRegion (PRMR, PlatformRtMechanism, 0, 26) Field (PRMR, BufferAcc, NoLock, Preserve) { PRMF, 208 // Write to this field to invoke the OperationRegion Handler } The 26-byte ASL buffer is defined as the following: Byte Offset Byte Length Description ============================================================= 0 1 PRM OperationRegion handler status 1 8 PRM service status 9 1 PRM command 10 16 PRM handler GUID The ASL caller fills out a 26-byte buffer containing the PRM command and the PRM handler GUID like so: /* Local0 is the PRM data buffer */ Local0 = buffer (26){} /* Create byte fields over the buffer */ CreateByteField (Local0, 0x9, CMD) CreateField (Local0, 0x50, 0x80, GUID) /* Fill in the command and data fields of the data buffer */ CMD = 0 // run command GUID = ToUUID("xxxx-xx-xxx-xxxx") /* * Invoke PRM service with an ID that matches GUID and save the * result. */ Local0 = (\_SB.PRMT.PRMF = Local0) Byte offset 0 - 8 are written by the handler as a status passed back to AML and used by ASL like so: /* Create byte fields over the buffer */ CreateByteField (Local0, 0x0, PSTA) CreateQWordField (Local0, 0x1, USTA) In this ASL code, PSTA contains a status from the OperationRegion and USTA contains a status from the PRM service. The 26-byte buffer is recieved by acpi_platformrt_space_handler. This handler will look at the command value and the handler guid and take the approperiate actions. Command value Action ===================================================================== 0 Run the PRM service indicated by the PRM handler GUID (bytes 10-26) 1 Prevent PRM runtime updates from happening to the service's parent module 2 Allow PRM updates from happening to the service's parent module This patch enables command value 0. Link: https://uefi.org/sites/default/files/resources/Platform%20Runtime%20Mechanism%20-%20with%20legal%20notice.pdf # [1] Signed-off-by: Erik Kaneda [ rjw: Subject and changelog edits ] Signed-off-by: Rafael J. Wysocki Signed-off-by: Aubrey Li --- drivers/acpi/Kconfig | 5 + drivers/acpi/Makefile | 1 + drivers/acpi/bus.c | 2 + drivers/acpi/prmt.c | 303 ++++++++++++++++++++++++++++++++++++++++++ drivers/acpi/tables.c | 9 ++ include/linux/acpi.h | 1 + include/linux/prmt.h | 7 + 7 files changed, 328 insertions(+) create mode 100644 drivers/acpi/prmt.c create mode 100644 include/linux/prmt.h diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index b9753969b0db..2d5e379d1677 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -538,3 +538,8 @@ config X86_PM_TIMER You should nearly always say Y here because many modern systems require this timer. + +config ACPI_PRMT + bool "Platform Runtime Mechanism Support" + depends on EFI && X86_64 + default y diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 4466156474ee..6a1383e87b72 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -64,6 +64,7 @@ acpi-y += acpi_lpat.o acpi-$(CONFIG_ACPI_LPIT) += acpi_lpit.o acpi-$(CONFIG_ACPI_GENERIC_GSI) += irq.o acpi-$(CONFIG_ACPI_WATCHDOG) += acpi_watchdog.o +acpi-$(CONFIG_ACPI_PRMT) += prmt.o # Address translation acpi-$(CONFIG_ACPI_ADXL) += acpi_adxl.o diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 4ee50f4f6f01..81cd5c457cc7 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "internal.h" @@ -1246,6 +1247,7 @@ static int __init acpi_init(void) acpi_kobj = NULL; } + init_prmt(); result = acpi_bus_init(); if (result) { kobject_put(acpi_kobj); diff --git a/drivers/acpi/prmt.c b/drivers/acpi/prmt.c new file mode 100644 index 000000000000..33c274698d07 --- /dev/null +++ b/drivers/acpi/prmt.c @@ -0,0 +1,303 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Author: Erik Kaneda + * Copyright 2020 Intel Corporation + * + * prmt.c + * + * Each PRM service is an executable that is run in a restricted environment + * that is invoked by writing to the PlatformRtMechanism OperationRegion from + * AML bytecode. + * + * init_prmt initializes the Platform Runtime Mechanism (PRM) services by + * processing data in the PRMT as well as registering an ACPI OperationRegion + * handler for the PlatformRtMechanism subtype. + * + */ +#include +#include +#include +#include +#include + +#pragma pack(1) +struct prm_mmio_addr_range { + u64 phys_addr; + u64 virt_addr; + u32 length; +}; + +struct prm_mmio_info { + u64 mmio_count; + struct prm_mmio_addr_range addr_ranges[]; +}; + +struct prm_buffer { + u8 prm_status; + u64 efi_status; + u8 prm_cmd; + guid_t handler_guid; +}; + +struct prm_context_buffer { + char signature[ACPI_NAMESEG_SIZE]; + u16 revision; + u16 reserved; + guid_t identifier; + u64 static_data_buffer; + struct prm_mmio_info *mmio_ranges; +}; +#pragma pack() + + +LIST_HEAD(prm_module_list); + +struct prm_handler_info { + guid_t guid; + u64 handler_addr; + u64 static_data_buffer_addr; + u64 acpi_param_buffer_addr; + + struct list_head handler_list; +}; + +struct prm_module_info { + guid_t guid; + u16 major_rev; + u16 minor_rev; + u16 handler_count; + struct prm_mmio_info *mmio_info; + bool updatable; + + struct list_head module_list; + struct prm_handler_info handlers[]; +}; + + +static u64 efi_pa_va_lookup(u64 pa) +{ + efi_memory_desc_t *md; + u64 pa_offset = pa & ~PAGE_MASK; + u64 page = pa & PAGE_MASK; + + for_each_efi_memory_desc(md) { + if (md->phys_addr < pa && pa < md->phys_addr + PAGE_SIZE * md->num_pages) + return pa_offset + md->virt_addr + page - md->phys_addr; + } + + return 0; +} + + +#define get_first_handler(a) ((struct acpi_prmt_handler_info *) ((char *) (a) + a->handler_info_offset)) +#define get_next_handler(a) ((struct acpi_prmt_handler_info *) (sizeof(struct acpi_prmt_handler_info) + (char *) a)) + +static int __init +acpi_parse_prmt(union acpi_subtable_headers *header, const unsigned long end) +{ + struct acpi_prmt_module_info *module_info; + struct acpi_prmt_handler_info *handler_info; + struct prm_handler_info *th; + struct prm_module_info *tm; + u64 mmio_count = 0; + u64 cur_handler = 0; + u32 module_info_size = 0; + u64 mmio_range_size = 0; + void *temp_mmio; + + module_info = (struct acpi_prmt_module_info *) header; + module_info_size = struct_size(tm, handlers, module_info->handler_info_count); + tm = kmalloc(module_info_size, GFP_KERNEL); + + guid_copy(&tm->guid, (guid_t *) module_info->module_guid); + tm->major_rev = module_info->major_rev; + tm->minor_rev = module_info->minor_rev; + tm->handler_count = module_info->handler_info_count; + tm->updatable = true; + + if (module_info->mmio_list_pointer) { + /* + * Each module is associated with a list of addr + * ranges that it can use during the service + */ + mmio_count = *(u64 *) memremap(module_info->mmio_list_pointer, 8, MEMREMAP_WB); + mmio_range_size = struct_size(tm->mmio_info, addr_ranges, mmio_count); + tm->mmio_info = kmalloc(mmio_range_size, GFP_KERNEL); + temp_mmio = memremap(module_info->mmio_list_pointer, mmio_range_size, MEMREMAP_WB); + memmove(tm->mmio_info, temp_mmio, mmio_range_size); + } else { + mmio_range_size = struct_size(tm->mmio_info, addr_ranges, mmio_count); + tm->mmio_info = kmalloc(mmio_range_size, GFP_KERNEL); + tm->mmio_info->mmio_count = 0; + } + + INIT_LIST_HEAD(&tm->module_list); + list_add(&tm->module_list, &prm_module_list); + + handler_info = get_first_handler(module_info); + do { + th = &tm->handlers[cur_handler]; + + guid_copy(&th->guid, (guid_t *)handler_info->handler_guid); + th->handler_addr = efi_pa_va_lookup(handler_info->handler_address); + th->static_data_buffer_addr = efi_pa_va_lookup(handler_info->static_data_buffer_address); + th->acpi_param_buffer_addr = efi_pa_va_lookup(handler_info->acpi_param_buffer_address); + } while (++cur_handler < tm->handler_count && (handler_info = get_next_handler(handler_info))); + + return 0; +} + +#define GET_MODULE 0 +#define GET_HANDLER 1 + +static void *find_guid_info(const guid_t *guid, u8 mode) +{ + struct prm_handler_info *cur_handler; + struct prm_module_info *cur_module; + int i = 0; + + list_for_each_entry(cur_module, &prm_module_list, module_list) { + for (i = 0; i < cur_module->handler_count; ++i) { + cur_handler = &cur_module->handlers[i]; + if (guid_equal(guid, &cur_handler->guid)) { + if (mode == GET_MODULE) + return (void *)cur_module; + else + return (void *)cur_handler; + } + } + } + + return NULL; +} + + +static struct prm_module_info *find_prm_module(const guid_t *guid) +{ + return (struct prm_module_info *)find_guid_info(guid, GET_MODULE); +} + +static struct prm_handler_info *find_prm_handler(const guid_t *guid) +{ + return (struct prm_handler_info *) find_guid_info(guid, GET_HANDLER); +} + +/* In-coming PRM commands */ + +#define PRM_CMD_RUN_SERVICE 0 +#define PRM_CMD_START_TRANSACTION 1 +#define PRM_CMD_END_TRANSACTION 2 + +/* statuses that can be passed back to ASL */ + +#define PRM_HANDLER_SUCCESS 0 +#define PRM_HANDLER_ERROR 1 +#define INVALID_PRM_COMMAND 2 +#define PRM_HANDLER_GUID_NOT_FOUND 3 +#define UPDATE_LOCK_ALREADY_HELD 4 +#define UPDATE_UNLOCK_WITHOUT_LOCK 5 + +/* + * This is the PlatformRtMechanism opregion space handler. + * @function: indicates the read/write. In fact as the PlatformRtMechanism + * message is driven by command, only write is meaningful. + * + * @addr : not used + * @bits : not used. + * @value : it is an in/out parameter. It points to the PRM message buffer. + * @handler_context: not used + */ +static acpi_status acpi_platformrt_space_handler(u32 function, + acpi_physical_address addr, + u32 bits, acpi_integer *value, + void *handler_context, + void *region_context) +{ + struct prm_buffer *buffer = ACPI_CAST_PTR(struct prm_buffer, value); + struct prm_handler_info *handler; + struct prm_module_info *module; + efi_status_t status; + struct prm_context_buffer context; + + /* + * The returned acpi_status will always be AE_OK. Error values will be + * saved in the first byte of the PRM message buffer to be used by ASL. + */ + switch (buffer->prm_cmd) { + case PRM_CMD_RUN_SERVICE: + + handler = find_prm_handler(&buffer->handler_guid); + module = find_prm_module(&buffer->handler_guid); + if (!handler || !module) + goto invalid_guid; + + ACPI_COPY_NAMESEG(context.signature, "PRMC"); + context.revision = 0x0; + context.reserved = 0x0; + context.identifier = handler->guid; + context.static_data_buffer = handler->static_data_buffer_addr; + context.mmio_ranges = module->mmio_info; + + status = efi_call_virt_pointer(handler, handler_addr, + handler->acpi_param_buffer_addr, + &context); + if (status == EFI_SUCCESS) { + buffer->prm_status = PRM_HANDLER_SUCCESS; + } else { + buffer->prm_status = PRM_HANDLER_ERROR; + buffer->efi_status = status; + } + break; + + case PRM_CMD_START_TRANSACTION: + + module = find_prm_module(&buffer->handler_guid); + if (!module) + goto invalid_guid; + + if (module->updatable) + module->updatable = false; + else + buffer->prm_status = UPDATE_LOCK_ALREADY_HELD; + break; + + case PRM_CMD_END_TRANSACTION: + + module = find_prm_module(&buffer->handler_guid); + if (!module) + goto invalid_guid; + + if (module->updatable) + buffer->prm_status = UPDATE_UNLOCK_WITHOUT_LOCK; + else + module->updatable = true; + break; + + default: + + buffer->prm_status = INVALID_PRM_COMMAND; + break; + } + + return AE_OK; + +invalid_guid: + buffer->prm_status = PRM_HANDLER_GUID_NOT_FOUND; + return AE_OK; +} + +void __init init_prmt(void) +{ + acpi_status status; + int mc = acpi_table_parse_entries(ACPI_SIG_PRMT, sizeof(struct acpi_table_prmt) + + sizeof (struct acpi_table_prmt_header), + 0, acpi_parse_prmt, 0); + pr_info("PRM: found %u modules\n", mc); + + status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT, + ACPI_ADR_SPACE_PLATFORM_RT, + &acpi_platformrt_space_handler, + NULL, NULL); + if (ACPI_FAILURE(status)) + pr_alert("PRM: OperationRegion handler could not be installed\n"); +} diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index b36d9a22a07a..5943ae4f76bb 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -39,6 +39,7 @@ static int acpi_apic_instance __initdata; enum acpi_subtable_type { ACPI_SUBTABLE_COMMON, ACPI_SUBTABLE_HMAT, + ACPI_SUBTABLE_PRMT, }; struct acpi_subtable_entry { @@ -232,6 +233,8 @@ acpi_get_entry_type(struct acpi_subtable_entry *entry) return entry->hdr->common.type; case ACPI_SUBTABLE_HMAT: return entry->hdr->hmat.type; + case ACPI_SUBTABLE_PRMT: + return 0; } return 0; } @@ -244,6 +247,8 @@ acpi_get_entry_length(struct acpi_subtable_entry *entry) return entry->hdr->common.length; case ACPI_SUBTABLE_HMAT: return entry->hdr->hmat.length; + case ACPI_SUBTABLE_PRMT: + return entry->hdr->prmt.length; } return 0; } @@ -256,6 +261,8 @@ acpi_get_subtable_header_length(struct acpi_subtable_entry *entry) return sizeof(entry->hdr->common); case ACPI_SUBTABLE_HMAT: return sizeof(entry->hdr->hmat); + case ACPI_SUBTABLE_PRMT: + return sizeof(entry->hdr->prmt); } return 0; } @@ -265,6 +272,8 @@ acpi_get_subtable_type(char *id) { if (strncmp(id, ACPI_SIG_HMAT, 4) == 0) return ACPI_SUBTABLE_HMAT; + if (strncmp(id, ACPI_SIG_PRMT, 4) == 0) + return ACPI_SUBTABLE_PRMT; return ACPI_SUBTABLE_COMMON; } diff --git a/include/linux/acpi.h b/include/linux/acpi.h index b598dd608e7b..4feec5f5171e 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -133,6 +133,7 @@ enum acpi_address_range_id { union acpi_subtable_headers { struct acpi_subtable_header common; struct acpi_hmat_structure hmat; + struct acpi_prmt_module_header prmt; }; typedef int (*acpi_tbl_table_handler)(struct acpi_table_header *table); diff --git a/include/linux/prmt.h b/include/linux/prmt.h new file mode 100644 index 000000000000..24da8364b919 --- /dev/null +++ b/include/linux/prmt.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifdef CONFIG_ACPI_PRMT +void init_prmt(void); +#else +static inline void init_prmt(void) { } +#endif -- Gitee From 901cd8e01499509e81a07d7b32b11187e4283450 Mon Sep 17 00:00:00 2001 From: Erik Kaneda Date: Mon, 27 Feb 2023 11:13:19 +0800 Subject: [PATCH 05/16] ACPI: Add \_SB._OSC bit for PRM mainline inclusion from mainline-v5.14 commit 60faa8f1ac6e0588d53eb9a345adcdbcc96a8f47 category: feature bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I6HNB8 CVE: N/A Intel-SIG: commit 60faa8f1ac6e ACPI: Add \_SB._OSC bit for PRM. ACPI Platform Runtime Mechanism feature backport. -------------------------------- Signed-off-by: Erik Kaneda Signed-off-by: Rafael J. Wysocki Signed-off-by: Aubrey Li --- drivers/acpi/bus.c | 1 + include/linux/acpi.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 81cd5c457cc7..6e229bf8f37c 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -303,6 +303,7 @@ static void acpi_bus_osc_support(void) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT; capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PCLPI_SUPPORT; + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PRM_SUPPORT; #ifdef CONFIG_ARM64 capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_GENERIC_INITIATOR_SUPPORT; diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 4feec5f5171e..9e352975bbd0 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -553,6 +553,7 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context); #define OSC_SB_OSLPI_SUPPORT 0x00000100 #define OSC_SB_CPC_DIVERSE_HIGH_SUPPORT 0x00001000 #define OSC_SB_GENERIC_INITIATOR_SUPPORT 0x00002000 +#define OSC_SB_PRM_SUPPORT 0x00020000 extern bool osc_sb_apei_support_acked; extern bool osc_pc_lpi_support_confirmed; -- Gitee From b1f81024ad353cf83b977ef56191619f4cea151a Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 15 Jun 2021 17:21:57 +0000 Subject: [PATCH 06/16] ACPI: PRM: make symbol 'prm_module_list' static mainline inclusion from mainline-v5.14 commit d7a188bb87d8da78a1ef0dea53f1639f3daf0790 category: feature bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I6HNB8 CVE: N/A Intel-SIG: commit d7a188bb87d8 ACPI: PRM: make symbol 'prm_module_list' static. ACPI Platform Runtime Mechanism feature backport. -------------------------------- The sparse tool complains as follows: drivers/acpi/prmt.c:53:1: warning: symbol 'prm_module_list' was not declared. Should it be static? This symbol is not used outside of prmt.c, so marks it static. Fixes: cefc7ca46235 ("ACPI: PRM: implement OperationRegion handler for the PlatformRtMechanism subtype") Reported-by: Hulk Robot Signed-off-by: Wei Yongjun Signed-off-by: Rafael J. Wysocki Signed-off-by: Aubrey Li --- drivers/acpi/prmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/prmt.c b/drivers/acpi/prmt.c index 33c274698d07..31cf9aee5edd 100644 --- a/drivers/acpi/prmt.c +++ b/drivers/acpi/prmt.c @@ -50,7 +50,7 @@ struct prm_context_buffer { #pragma pack() -LIST_HEAD(prm_module_list); +static LIST_HEAD(prm_module_list); struct prm_handler_info { guid_t guid; -- Gitee From 295817c0cdfb8a05ec1f1e96c03da77ba42359db Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 1 Jul 2021 18:34:52 +0200 Subject: [PATCH 07/16] ACPI: Kconfig: Provide help text for the ACPI_PRMT option mainline inclusion from mainline-v5.14 commit 9b52363b9283376c868679bdcd6e19405a4aca5a category: feature bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I6HNB8 CVE: N/A Intel-SIG: commit 9b52363b9283 ACPI: Kconfig: Provide help text for the ACPI_PRMT option. ACPI Platform Runtime Mechanism feature backport. -------------------------------- Add missing help text for CONFIG_ACPI_PRMT. Fixes: cefc7ca46235 ("ACPI: PRM: implement OperationRegion handler for the PlatformRtMechanism subtype") Reported-by: Borislav Petkov Signed-off-by: Rafael J. Wysocki Signed-off-by: Aubrey Li --- drivers/acpi/Kconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 2d5e379d1677..435525c7acb3 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -543,3 +543,13 @@ config ACPI_PRMT bool "Platform Runtime Mechanism Support" depends on EFI && X86_64 default y + help + Platform Runtime Mechanism (PRM) is a firmware interface exposing a + set of binary executables that can be called from the AML interpreter + or directly from device drivers. + + Say Y to enable the AML interpreter to execute the PRM code. + + While this feature is optional in principle, leaving it out may + substantially increase computational overhead related to the + initialization of some server systems. -- Gitee From 389971cc07130fa473cdaad3e17c8a09ba4746d8 Mon Sep 17 00:00:00 2001 From: Aubrey Li Date: Mon, 27 Feb 2023 11:17:34 +0800 Subject: [PATCH 08/16] ACPI: Correct \_SB._OSC bit definition for PRM mainline inclusion from mainline-v5.14 commit bd7a94c0fa41dfbea8564556c7a28b05e353c5da category: feature bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I6HNB8 CVE: N/A Intel-SIG: commit bd7a94c0fa41 ACPI: Correct \_SB._OSC bit definition for PRM. ACPI Platform Runtime Mechanism feature backport. -------------------------------- According to Platform Runtime Mechanism Specification v1.0 [1], Page 42, \_SB._OSC bit 21 is used to indicate OS support for PRM. Update the definition of the PRM support bit in the code to match the specification. Link: https://uefi.org/sites/default/files/resources/Platform%20Runtime%20Mechanism%20-%20with%20legal%20notice.pdf # [1] Fixes: 60faa8f1ac6e ("ACPI: Add \_SB._OSC bit for PRM") Signed-off-by: Aubrey Li [ rjw: Changelog edits ] Signed-off-by: Rafael J. Wysocki Signed-off-by: Aubrey Li --- include/linux/acpi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 9e352975bbd0..473dbb701700 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -553,7 +553,7 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context); #define OSC_SB_OSLPI_SUPPORT 0x00000100 #define OSC_SB_CPC_DIVERSE_HIGH_SUPPORT 0x00001000 #define OSC_SB_GENERIC_INITIATOR_SUPPORT 0x00002000 -#define OSC_SB_PRM_SUPPORT 0x00020000 +#define OSC_SB_PRM_SUPPORT 0x00200000 extern bool osc_sb_apei_support_acked; extern bool osc_pc_lpi_support_confirmed; -- Gitee From 82f7bb79cb4e649c8a3b1014c8a357ddbc6c90a4 Mon Sep 17 00:00:00 2001 From: Aubrey Li Date: Fri, 2 Jul 2021 15:03:50 +0800 Subject: [PATCH 09/16] ACPI: Do not singal PRM support if not enabled mainline inclusion from mainline-v5.14 commit 392ed6a789803fbfd49994e95fe99cd07b07eb87 category: feature bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I6HNB8 CVE: N/A Intel-SIG: commit 392ed6a78980 ACPI: Do not singal PRM support if not enabled. ACPI Platform Runtime Mechanism feature backport. -------------------------------- If the OS confirms PRM (Platform Runtime Mechanism) support through the \_SB._OSC PRM bit, the BIOS may start relying on the presence of PRM support in the OS, so prevent the PRM bit from being set in the \_SB._OSC capabilities bitmask when PRM support is not built in so as to avoid confusing the BIOS in that case. Fixes: 60faa8f1ac6e ("ACPI: Add \_SB._OSC bit for PRM") Signed-off-by: Aubrey Li [ rjw: Rewrite subject and changelog, replace #ifdef with if (IS_ENABLED()) ] Signed-off-by: Rafael J. Wysocki Signed-off-by: Aubrey Li --- drivers/acpi/bus.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 6e229bf8f37c..a6a6161474c5 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -303,7 +303,8 @@ static void acpi_bus_osc_support(void) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT; capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PCLPI_SUPPORT; - capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PRM_SUPPORT; + if (IS_ENABLED(CONFIG_ACPI_PRMT)) + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PRM_SUPPORT; #ifdef CONFIG_ARM64 capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_GENERIC_INITIATOR_SUPPORT; -- Gitee From 4eb59dbc7455ffae607324d0e9e4c9c17cbd5e19 Mon Sep 17 00:00:00 2001 From: Aubrey Li Date: Fri, 6 Aug 2021 08:46:24 +0800 Subject: [PATCH 10/16] ACPI: PRM: Deal with table not present or no module found mainline inclusion from mainline-v5.14 commit 2bbfa0addd63fd06756b7af8bf146ae166e2abf5 category: feature bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I6HNB8 CVE: N/A Intel-SIG: commit 2bbfa0addd63 ACPI: PRM: Deal with table not present or no module found. ACPI Platform Runtime Mechanism feature backport. -------------------------------- On the system PRMT table is not present, dmesg output: $ dmesg | grep PRM [ 1.532237] ACPI: PRMT not present [ 1.532237] PRM: found 4294967277 modules The result of acpi_table_parse_entries need to be checked and return immediately if PRMT table is not present or no PRM module found. Signed-off-by: Aubrey Li Signed-off-by: Rafael J. Wysocki Signed-off-by: Aubrey Li --- drivers/acpi/prmt.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/acpi/prmt.c b/drivers/acpi/prmt.c index 31cf9aee5edd..1f6007abcf18 100644 --- a/drivers/acpi/prmt.c +++ b/drivers/acpi/prmt.c @@ -292,6 +292,12 @@ void __init init_prmt(void) int mc = acpi_table_parse_entries(ACPI_SIG_PRMT, sizeof(struct acpi_table_prmt) + sizeof (struct acpi_table_prmt_header), 0, acpi_parse_prmt, 0); + /* + * Return immediately if PRMT table is not present or no PRM module found. + */ + if (mc <= 0) + return; + pr_info("PRM: found %u modules\n", mc); status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT, -- Gitee From d0ef66050ff871da84620eb189abb0e05dcb877a Mon Sep 17 00:00:00 2001 From: Aubrey Li Date: Wed, 8 Sep 2021 18:55:45 +0800 Subject: [PATCH 11/16] ACPI: PRM: Find PRMT table before parsing it mainline inclusion from mainline-v5.15 commit 3265cc3ec52e75fc8daf189954cebda27ad26b2e category: feature bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I6HNB8 CVE: N/A Intel-SIG: commit 3265cc3ec52e ACPI: PRM: Find PRMT table before parsing it. ACPI Platform Runtime Mechanism feature backport. -------------------------------- Find and verify PRMT before parsing it, which eliminates a warning on machines without PRMT: [ 7.197173] ACPI: PRMT not present Fixes: cefc7ca46235 ("ACPI: PRM: implement OperationRegion handler for the PlatformRtMechanism subtype") Signed-off-by: Aubrey Li Tested-by: Paul Menzel Cc: 5.14+ # 5.14+ [ rjw: Subject and changelog edits ] Signed-off-by: Rafael J. Wysocki Signed-off-by: Aubrey Li --- drivers/acpi/prmt.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/prmt.c b/drivers/acpi/prmt.c index 1f6007abcf18..89c22bc55057 100644 --- a/drivers/acpi/prmt.c +++ b/drivers/acpi/prmt.c @@ -288,10 +288,18 @@ static acpi_status acpi_platformrt_space_handler(u32 function, void __init init_prmt(void) { + struct acpi_table_header *tbl; acpi_status status; - int mc = acpi_table_parse_entries(ACPI_SIG_PRMT, sizeof(struct acpi_table_prmt) + + int mc; + + status = acpi_get_table(ACPI_SIG_PRMT, 0, &tbl); + if (ACPI_FAILURE(status)) + return; + + mc = acpi_table_parse_entries(ACPI_SIG_PRMT, sizeof(struct acpi_table_prmt) + sizeof (struct acpi_table_prmt_header), 0, acpi_parse_prmt, 0); + acpi_put_table(tbl); /* * Return immediately if PRMT table is not present or no PRM module found. */ -- Gitee From 1f254d793ad66cc6fa9f774970cacf0c180e0fc6 Mon Sep 17 00:00:00 2001 From: Aubrey Li Date: Wed, 20 Oct 2021 11:23:16 +0800 Subject: [PATCH 12/16] ACPI: PRM: Remove unnecessary blank lines mainline inclusion from mainline-v5.16 commit caa2bd07f5c5f09acf62072906daeaa667e2b645 category: feature bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I6HNB8 CVE: N/A Intel-SIG: commit caa2bd07f5c5 ACPI: PRM: Remove unnecessary blank lines. ACPI Platform Runtime Mechanism feature backport. -------------------------------- Just remove unnecessary blank lines, no other code changes Signed-off-by: Aubrey Li Signed-off-by: Rafael J. Wysocki Signed-off-by: Aubrey Li --- drivers/acpi/prmt.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/acpi/prmt.c b/drivers/acpi/prmt.c index 89c22bc55057..aa02221f6ade 100644 --- a/drivers/acpi/prmt.c +++ b/drivers/acpi/prmt.c @@ -49,7 +49,6 @@ struct prm_context_buffer { }; #pragma pack() - static LIST_HEAD(prm_module_list); struct prm_handler_info { @@ -73,7 +72,6 @@ struct prm_module_info { struct prm_handler_info handlers[]; }; - static u64 efi_pa_va_lookup(u64 pa) { efi_memory_desc_t *md; @@ -88,7 +86,6 @@ static u64 efi_pa_va_lookup(u64 pa) return 0; } - #define get_first_handler(a) ((struct acpi_prmt_handler_info *) ((char *) (a) + a->handler_info_offset)) #define get_next_handler(a) ((struct acpi_prmt_handler_info *) (sizeof(struct acpi_prmt_handler_info) + (char *) a)) @@ -171,7 +168,6 @@ static void *find_guid_info(const guid_t *guid, u8 mode) return NULL; } - static struct prm_module_info *find_prm_module(const guid_t *guid) { return (struct prm_module_info *)find_guid_info(guid, GET_MODULE); -- Gitee From b37aa6e62871244f62012d60d2ad2013783f1599 Mon Sep 17 00:00:00 2001 From: Aubrey Li Date: Wed, 20 Oct 2021 11:23:17 +0800 Subject: [PATCH 13/16] ACPI: PRM: Handle memory allocation and memory remap failure mainline inclusion from mainline-v5.16 commit c52ca713279da78881d36b49acd36288a46bbec8 category: feature bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I6HNB8 CVE: N/A Intel-SIG: commit c52ca713279d ACPI: PRM: Handle memory allocation and memory remap failure. ACPI Platform Runtime Mechanism feature backport. -------------------------------- Handle memory allocation and memory remap failure in acpi_parse_prmt() when system runs out of memory to avoid the potential NULL pointer dereference errors. Signed-off-by: Aubrey Li Signed-off-by: Rafael J. Wysocki Signed-off-by: Aubrey Li --- drivers/acpi/prmt.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/drivers/acpi/prmt.c b/drivers/acpi/prmt.c index aa02221f6ade..4d3a219c67f8 100644 --- a/drivers/acpi/prmt.c +++ b/drivers/acpi/prmt.c @@ -96,7 +96,7 @@ acpi_parse_prmt(union acpi_subtable_headers *header, const unsigned long end) struct acpi_prmt_handler_info *handler_info; struct prm_handler_info *th; struct prm_module_info *tm; - u64 mmio_count = 0; + u64 *mmio_count; u64 cur_handler = 0; u32 module_info_size = 0; u64 mmio_range_size = 0; @@ -105,6 +105,8 @@ acpi_parse_prmt(union acpi_subtable_headers *header, const unsigned long end) module_info = (struct acpi_prmt_module_info *) header; module_info_size = struct_size(tm, handlers, module_info->handler_info_count); tm = kmalloc(module_info_size, GFP_KERNEL); + if (!tm) + goto parse_prmt_out1; guid_copy(&tm->guid, (guid_t *) module_info->module_guid); tm->major_rev = module_info->major_rev; @@ -117,14 +119,24 @@ acpi_parse_prmt(union acpi_subtable_headers *header, const unsigned long end) * Each module is associated with a list of addr * ranges that it can use during the service */ - mmio_count = *(u64 *) memremap(module_info->mmio_list_pointer, 8, MEMREMAP_WB); - mmio_range_size = struct_size(tm->mmio_info, addr_ranges, mmio_count); + mmio_count = (u64 *) memremap(module_info->mmio_list_pointer, 8, MEMREMAP_WB); + if (!mmio_count) + goto parse_prmt_out2; + + mmio_range_size = struct_size(tm->mmio_info, addr_ranges, *mmio_count); tm->mmio_info = kmalloc(mmio_range_size, GFP_KERNEL); + if (!tm->mmio_info) + goto parse_prmt_out3; + temp_mmio = memremap(module_info->mmio_list_pointer, mmio_range_size, MEMREMAP_WB); + if (!temp_mmio) + goto parse_prmt_out4; memmove(tm->mmio_info, temp_mmio, mmio_range_size); } else { - mmio_range_size = struct_size(tm->mmio_info, addr_ranges, mmio_count); - tm->mmio_info = kmalloc(mmio_range_size, GFP_KERNEL); + tm->mmio_info = kmalloc(sizeof(*tm->mmio_info), GFP_KERNEL); + if (!tm->mmio_info) + goto parse_prmt_out2; + tm->mmio_info->mmio_count = 0; } @@ -142,6 +154,15 @@ acpi_parse_prmt(union acpi_subtable_headers *header, const unsigned long end) } while (++cur_handler < tm->handler_count && (handler_info = get_next_handler(handler_info))); return 0; + +parse_prmt_out4: + kfree(tm->mmio_info); +parse_prmt_out3: + memunmap(mmio_count); +parse_prmt_out2: + kfree(tm); +parse_prmt_out1: + return -ENOMEM; } #define GET_MODULE 0 -- Gitee From cfa7172f9ee7318e434a67f7d1470e8061613680 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Tue, 28 Jun 2022 13:53:43 +0100 Subject: [PATCH 14/16] ACPI: PRM: Change handler_addr type to void pointer mainline inclusion from mainline-v6.0 commit 353efd5e97a7973d78f2634274b57309d0966e29 category: feature bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I6HNB8 CVE: N/A Intel-SIG: commit 353efd5e97a7 ACPI: PRM: Change handler_addr type to void pointer. ACPI Platform Runtime Mechanism feature backport. -------------------------------- handler_addr is a virtual address passed to efi_call_virt_pointer. While x86 currently type cast it into the pointer in it's arch specific arch_efi_call_virt() implementation, ARM64 is restrictive for right reasons. Convert the handler_addr type from u64 to void pointer. Signed-off-by: Sudeep Holla Acked-by: Rafael J. Wysocki Signed-off-by: Ard Biesheuvel Signed-off-by: Aubrey Li --- drivers/acpi/prmt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/prmt.c b/drivers/acpi/prmt.c index 4d3a219c67f8..998101cf16e4 100644 --- a/drivers/acpi/prmt.c +++ b/drivers/acpi/prmt.c @@ -53,7 +53,7 @@ static LIST_HEAD(prm_module_list); struct prm_handler_info { guid_t guid; - u64 handler_addr; + void *handler_addr; u64 static_data_buffer_addr; u64 acpi_param_buffer_addr; @@ -148,7 +148,7 @@ acpi_parse_prmt(union acpi_subtable_headers *header, const unsigned long end) th = &tm->handlers[cur_handler]; guid_copy(&th->guid, (guid_t *)handler_info->handler_guid); - th->handler_addr = efi_pa_va_lookup(handler_info->handler_address); + th->handler_addr = (void *)efi_pa_va_lookup(handler_info->handler_address); th->static_data_buffer_addr = efi_pa_va_lookup(handler_info->static_data_buffer_address); th->acpi_param_buffer_addr = efi_pa_va_lookup(handler_info->acpi_param_buffer_address); } while (++cur_handler < tm->handler_count && (handler_info = get_next_handler(handler_info))); -- Gitee From 0289b1bae5726f0e12088ff06105b464ff70cb09 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 12 Jan 2023 14:33:19 +0100 Subject: [PATCH 15/16] ACPI: PRM: Check whether EFI runtime is available mainline inclusion from mainline-v6.2 commit 182da6f2b81a78709c58021542fb694f8ed80774 category: feature bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I6HNB8 CVE: N/A Intel-SIG: commit 182da6f2b81a ACPI: PRM: Check whether EFI runtime is available. ACPI Platform Runtime Mechanism feature backport. -------------------------------- The ACPI PRM address space handler calls efi_call_virt_pointer() to execute PRM firmware code, but doing so is only permitted when the EFI runtime environment is available. Otherwise, such calls are guaranteed to result in a crash, and must therefore be avoided. Given that the EFI runtime services may become unavailable after a crash occurring in the firmware, we need to check this each time the PRM address space handler is invoked. If the EFI runtime services were not available at registration time to being with, don't install the address space handler at all. Fixes: cefc7ca46235 ("ACPI: PRM: implement OperationRegion handler for the PlatformRtMechanism subtype") Signed-off-by: Ard Biesheuvel Cc: All applicable Signed-off-by: Rafael J. Wysocki Signed-off-by: Aubrey Li --- drivers/acpi/prmt.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/acpi/prmt.c b/drivers/acpi/prmt.c index 998101cf16e4..3d4c4620f9f9 100644 --- a/drivers/acpi/prmt.c +++ b/drivers/acpi/prmt.c @@ -236,6 +236,11 @@ static acpi_status acpi_platformrt_space_handler(u32 function, efi_status_t status; struct prm_context_buffer context; + if (!efi_enabled(EFI_RUNTIME_SERVICES)) { + pr_err_ratelimited("PRM: EFI runtime services no longer available\n"); + return AE_NO_HANDLER; + } + /* * The returned acpi_status will always be AE_OK. Error values will be * saved in the first byte of the PRM message buffer to be used by ASL. @@ -325,6 +330,11 @@ void __init init_prmt(void) pr_info("PRM: found %u modules\n", mc); + if (!efi_enabled(EFI_RUNTIME_SERVICES)) { + pr_err("PRM: EFI runtime services unavailable\n"); + return; + } + status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT, ACPI_ADR_SPACE_PLATFORM_RT, &acpi_platformrt_space_handler, -- Gitee From ab5e9b99e73866849bbd9bcbec8099eb8f02b307 Mon Sep 17 00:00:00 2001 From: Aubrey Li Date: Fri, 24 Feb 2023 21:20:14 +0800 Subject: [PATCH 16/16] Enable ACPI Platform Runtime Mechanism(PRM) feature support driver inclusion category: feature bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I6HNB8 CVE: N/A Intel-SIG: openeuler_defconfig: Enable ACPI Platform Runtime Mechanism(PRM) feature support -------------------------------------------- Enable ACPI Platform Runtime Mechanism(PRM) feature support by default. For the purpose to validate PRM from user space, set: - CONFIG_ACPI_DEBUGGER = y - CONFIG_ACPI_DEBUGGER_USER = m Signed-off-by: Aubrey Li --- arch/x86/configs/openeuler_defconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/x86/configs/openeuler_defconfig b/arch/x86/configs/openeuler_defconfig index 33300dbc110d..bea07d020e1c 100644 --- a/arch/x86/configs/openeuler_defconfig +++ b/arch/x86/configs/openeuler_defconfig @@ -543,7 +543,8 @@ CONFIG_ACPI=y CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT=y -# CONFIG_ACPI_DEBUGGER is not set +CONFIG_ACPI_DEBUGGER=y +CONFIG_ACPI_DEBUGGER_USER=m CONFIG_ACPI_SPCR_TABLE=y CONFIG_ACPI_LPIT=y CONFIG_ACPI_SLEEP=y @@ -597,6 +598,7 @@ CONFIG_ACPI_ADXL=y # CONFIG_ACPI_CONFIGFS is not set CONFIG_PMIC_OPREGION=y CONFIG_X86_PM_TIMER=y +CONFIG_ACPI_PRMT=y CONFIG_SFI=y # -- Gitee