// SPDX-License-Identifier: GPL-2.0-only /* * Author: Erik Kaneda <erik.kaneda@intel.com> * 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 <linux/kernel.h> #include <linux/efi.h> #include <linux/acpi.h> #include <linux/prmt.h> #include <asm/efi.h>
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); if (!mmio_count) goto parse_prmt_out2;
/* * Print an error message if handler_address is NULL, the parse of VA also * can be skipped.
*/ if (unlikely(!handler_info->handler_address)) {
pr_info("Skipping handler with NULL address for GUID: %pUL",
(guid_t *)handler_info->handler_guid); continue;
}
th->handler_addr =
(void *)efi_pa_va_lookup(&th->guid, handler_info->handler_address); /* * Print a warning message and skip the parse of VA if handler_addr is zero * which is not expected to ever happen.
*/ if (unlikely(!th->handler_addr)) {
pr_warn("Failed to find VA of handler for GUID: %pUL, PA: 0x%llx",
&th->guid, handler_info->handler_address); continue;
}
th->static_data_buffer_addr =
efi_pa_va_lookup(&th->guid, handler_info->static_data_buffer_address); /* * According to the PRM specification, static_data_buffer_address can be zero, * so avoid printing a warning message in that case. Otherwise, if the * return value of efi_pa_va_lookup() is zero, print the message.
*/ if (unlikely(!th->static_data_buffer_addr && handler_info->static_data_buffer_address))
pr_warn("Failed to find VA of static data buffer for GUID: %pUL, PA: 0x%llx",
&th->guid, handler_info->static_data_buffer_address);
/* * According to the PRM specification, acpi_param_buffer_address can be zero, * so avoid printing a warning message in that case. Otherwise, if the * return value of efi_pa_va_lookup() is zero, print the message.
*/ if (unlikely(!th->acpi_param_buffer_addr && handler_info->acpi_param_buffer_address))
pr_warn("Failed to find VA of acpi param buffer for GUID: %pUL, PA: 0x%llx",
&th->guid, handler_info->acpi_param_buffer_address);
} while (++cur_handler < tm->handler_count && (handler_info = get_next_handler(handler_info)));
/* * 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;
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.
*/ switch (buffer->prm_cmd) { case PRM_CMD_RUN_SERVICE:
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.
*/ if (mc <= 0) return;
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,
NULL, NULL); if (ACPI_FAILURE(status))
pr_alert("PRM: OperationRegion handler could not be installed\n");
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.