Fixes: cefc7ca46235 ("ACPI: PRM: implement OperationRegion handler for the PlatformRtMechanism subtype")
Signed-off-by: KobaK <kobak@xxxxxxxxxx>
Reviewed-by: Matthew R. Ochs <mochs@xxxxxxxxxx>
---
V2:
1. format the changelog and add more about error handling.
2. replace goto
V3: Warn if parts of handler are missed during va-pa translating.
V4: Fix the 0day
V5: Fix typo and pr_warn warning
---
drivers/acpi/prmt.c | 49 +++++++++++++++++++++++++++++++--------------
1 file changed, 34 insertions(+), 15 deletions(-)
diff --git a/drivers/acpi/prmt.c b/drivers/acpi/prmt.c
index c78453c74ef5..cd4a7f5491d6 100644
--- a/drivers/acpi/prmt.c
+++ b/drivers/acpi/prmt.c
@@ -72,15 +72,17 @@ struct prm_module_info {
struct prm_handler_info handlers[] __counted_by(handler_count);
};
-static u64 efi_pa_va_lookup(u64 pa)
+static u64 efi_pa_va_lookup(u64 pa, u32 type)
{
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)
+ if ((md->type == type) &&
+ (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;
@@ -148,9 +150,18 @@ 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 = (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);
+ th->handler_addr =
+ (void *)efi_pa_va_lookup(handler_info->handler_address, EFI_RUNTIME_SERVICES_CODE);
+ th->static_data_buffer_addr =
+ efi_pa_va_lookup(handler_info->static_data_buffer_address, EFI_RUNTIME_SERVICES_DATA);
+ th->acpi_param_buffer_addr =
+ efi_pa_va_lookup(handler_info->acpi_param_buffer_address, EFI_RUNTIME_SERVICES_DATA);
+
+ if (!th->handler_addr || !th->static_data_buffer_addr || !th->acpi_param_buffer_addr)
+ pr_warn(
+ "Idx: %llu, Parts of handler(GUID: %pUL) are missed, handler_addr %p, data_addr %p, param_addr %p",
+ cur_handler, &th->guid, th->handler_addr,
+ (void *)th->static_data_buffer_addr, (void *)th->acpi_param_buffer_addr);
} while (++cur_handler < tm->handler_count && (handler_info = get_next_handler(handler_info)));
return 0;
@@ -250,8 +261,16 @@ static acpi_status acpi_platformrt_space_handler(u32 function,
handler = find_prm_handler(&buffer->handler_guid);
module = find_prm_module(&buffer->handler_guid);
- if (!handler || !module)
- goto invalid_guid;
+ if (!handler || !module) {
+ buffer->prm_status = PRM_HANDLER_GUID_NOT_FOUND;
+ return AE_OK;
+ }
+
+ if (!handler->handler_addr || !handler->static_data_buffer_addr ||
+ !handler->acpi_param_buffer_addr) {
+ buffer->prm_status = PRM_HANDLER_ERROR;
+ return AE_OK;
+ }
ACPI_COPY_NAMESEG(context.signature, "PRMC");
context.revision = 0x0;
@@ -274,8 +293,10 @@ static acpi_status acpi_platformrt_space_handler(u32 function,
case PRM_CMD_START_TRANSACTION:
module = find_prm_module(&buffer->handler_guid);
- if (!module)
- goto invalid_guid;
+ if (!module) {
+ buffer->prm_status = PRM_HANDLER_GUID_NOT_FOUND;
+ return AE_OK;
+ }
if (module->updatable)
module->updatable = false;
@@ -286,8 +307,10 @@ static acpi_status acpi_platformrt_space_handler(u32 function,
case PRM_CMD_END_TRANSACTION:
module = find_prm_module(&buffer->handler_guid);
- if (!module)
- goto invalid_guid;
+ if (!module) {
+ buffer->prm_status = PRM_HANDLER_GUID_NOT_FOUND;
+ return AE_OK;
+ }
if (module->updatable)
buffer->prm_status = UPDATE_UNLOCK_WITHOUT_LOCK;
@@ -302,10 +325,6 @@ static acpi_status acpi_platformrt_space_handler(u32 function,
}
return AE_OK;
-
-invalid_guid:
- buffer->prm_status = PRM_HANDLER_GUID_NOT_FOUND;
- return AE_OK;
}
void __init init_prmt(void)
--
2.43.0