Benjamin Doron has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/78284?usp=email )
Change subject: arch/arm64: Support calling a trusted monitor ......................................................................
arch/arm64: Support calling a trusted monitor
Implement support for generating an SMC to call a trusted monitor. Some functions are provided to read the SoC ID from the monitor, if supported.
Change-Id: I158db0b971aba722b3995d52162146aa406d1644 Signed-off-by: Benjamin Doron benjamin.doron@9elements.com --- M src/arch/arm64/Makefile.inc A src/arch/arm64/include/armv8/arch/monitor_services.h A src/arch/arm64/monitor_services.c 3 files changed, 165 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/84/78284/1
diff --git a/src/arch/arm64/Makefile.inc b/src/arch/arm64/Makefile.inc index 538d254..bcae5d4 100644 --- a/src/arch/arm64/Makefile.inc +++ b/src/arch/arm64/Makefile.inc @@ -30,6 +30,7 @@ decompressor-$(CONFIG_ARM64_USE_ARCH_TIMER) += arch_timer.c bootblock-$(CONFIG_ARM64_USE_ARCH_TIMER) += arch_timer.c bootblock-y += transition.c transition_asm.S +bootblock-y += monitor_services.c
decompressor-y += memset.S bootblock-y += memset.S @@ -69,6 +70,7 @@ verstage-y += memmove.S
verstage-y += transition.c transition_asm.S +verstage-y += monitor_services.c
endif # CONFIG_ARCH_VERSTAGE_ARM64
@@ -88,6 +90,7 @@ romstage-y += ramdetect.c romstage-y += romstage.c romstage-y += transition.c transition_asm.S +romstage-y += monitor_services.c
rmodules_arm64-y += memset.S rmodules_arm64-y += memcpy.S @@ -117,6 +120,7 @@ ramstage-y += memmove.S ramstage-$(CONFIG_ARM64_USE_ARM_TRUSTED_FIRMWARE) += bl31.c ramstage-y += transition.c transition_asm.S +ramstage-y += monitor_services.c ramstage-$(CONFIG_PAYLOAD_FIT_SUPPORT) += fit_payload.c ramstage-$(CONFIG_HAVE_ACPI_TABLES) += acpi.c
diff --git a/src/arch/arm64/include/armv8/arch/monitor_services.h b/src/arch/arm64/include/armv8/arch/monitor_services.h new file mode 100644 index 0000000..1b76167 --- /dev/null +++ b/src/arch/arm64/include/armv8/arch/monitor_services.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef ARM_ARM64_SMCCC_H +#define ARM_ARM64_SMCCC_H + +#include <stdint.h> + +struct smc_args { + uint64_t arg0; + uint64_t arg1; + uint64_t arg2; + uint64_t arg3; + uint64_t arg4; + uint64_t arg5; + uint64_t arg6; + uint64_t arg7; +}; + +enum smccc_return { + SMC_SUCCESS = 0, + SMC_NOT_SUPPORTED = -1, + SMC_NOT_REQUIRED = -2, + SMC_INVALID_PARAMETER = -3, +}; + +enum psci_return { + PSCI_SUCCESS = 0, + PSCI_NOT_SUPPORTED = -1, + PSCI_INVALID_PARAMETERS = -2, + PSCI_DENIED = -3, + PSCI_ALREADY_ON = -4, + PSCI_ON_PENDING = -5, + PSCI_INTERNAL_FAILURE = -6, + PSCI_NOT_PRESENT = -7, + PSCI_DISABLED = -8, + PSCI_INVALID_ADDRESS = -9, +}; + +struct smc_args smc_call(uint32_t func, uint64_t arg0, uint64_t arg1, uint64_t arg2, + uint64_t arg3, uint64_t arg4, uint64_t arg5, uint64_t arg6); +struct smc_args smc_call3(uint32_t func, uint64_t arg0, uint64_t arg1, uint64_t arg2); + +/* SMCCC defines */ +#define SMCCC_VERSION 0x80000000 +#define SMCCC_ARCH_FEATURES 0x80000001 +#define SMCCC_ARCH_SOC_ID 0x80000002 +#define SMCCC_GET_SOC_VERSION 0 +#define SMCCC_GET_SOC_REVISION 1 + +/* PSCI defines */ +#define PSCI_VERSION 0x84000000 +#define PSCI_FEATURES 0x8400000a + +/* SMCCC services */ +uint8_t smccc_supports_arch_soc_id(void); +void smccc_arch_soc_id(uint32_t *jep106code, uint32_t *soc_revision); + +#endif /* ARM_ARM64_SMCCC_H */ diff --git a/src/arch/arm64/monitor_services.c b/src/arch/arm64/monitor_services.c new file mode 100644 index 0000000..38b9db0 --- /dev/null +++ b/src/arch/arm64/monitor_services.c @@ -0,0 +1,103 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <arch/lib_helpers.h> +#include <arch/monitor_services.h> +#include <console/console.h> +#include <string.h> +#include <types.h> + +/* Implements helpers following the SMC calling convention */ + +struct smc_args smc_call(uint32_t func, uint64_t arg0, uint64_t arg1, uint64_t arg2, + uint64_t arg3, uint64_t arg4, uint64_t arg5, uint64_t arg6) +{ + struct smc_args ret_args; + + memset(&ret_args, 0, sizeof(ret_args)); + + if (current_el() == EL3) { + printk(BIOS_DEBUG, "coreboot executes in EL3, assuming no monitor present...\n"); + return ret_args; + } + + register uint64_t r0 __asm__("x0") = func; + register uint64_t r1 __asm__("x1") = arg0; + register uint64_t r2 __asm__("x2") = arg1; + register uint64_t r3 __asm__("x3") = arg2; + register uint64_t r4 __asm__("x4") = arg3; + register uint64_t r5 __asm__("x5") = arg4; + register uint64_t r6 __asm__("x6") = arg5; + register uint64_t r7 __asm__("x7") = arg6; + + /* Output registers, also used as inputs ('+' constraint). */ + __asm__ volatile("smc #0" + : "+r"(r0), "+r"(r1), "+r"(r2), "+r"(r3), + "+r"(r4), "+r"(r5), "+r"(r6), "+r"(r7)); + + ret_args.arg0 = r0; + ret_args.arg1 = r1; + ret_args.arg2 = r2; + ret_args.arg3 = r3; + ret_args.arg4 = r4; + ret_args.arg5 = r5; + ret_args.arg6 = r6; + ret_args.arg7 = r7; + + return ret_args; +} + +struct smc_args smc_call3(uint32_t func, uint64_t arg0, uint64_t arg1, uint64_t arg2) +{ + return smc_call(func, arg0, arg1, arg2, 0, 0, 0, 0); +} + +/* Assumes at least a PSCI implementation is present */ +uint8_t smccc_supports_arch_soc_id(void) +{ + static uint8_t supported = 0xff; + struct smc_args ret_args; + + if (supported != 0xff) + return supported; + + // PSCI_FEATURES mandatory from PSCI 1.0 + ret_args = smc_call3(PSCI_VERSION, 0, 0, 0); + if (ret_args.arg0 < 0x10000) + goto fail; + + ret_args = smc_call3(PSCI_FEATURES, SMCCC_VERSION, 0, 0); + if (ret_args.arg0 == PSCI_NOT_SUPPORTED) + goto fail; + + // SMCCC_ARCH_FEATURES supported from SMCCC 1.1 + ret_args = smc_call3(SMCCC_VERSION, 0, 0, 0); + if (ret_args.arg0 < 0x10001) + goto fail; + + ret_args = smc_call3(SMCCC_ARCH_FEATURES, SMCCC_ARCH_SOC_ID, 0, 0); + if (ret_args.arg0 != SMC_SUCCESS) + goto fail; + + supported = 1; + return supported; + +fail: + supported = 0; + return supported; +} + +void smccc_arch_soc_id(uint32_t *jep106code, uint32_t *soc_revision) +{ + struct smc_args ret_args; + + if (jep106code == NULL || soc_revision == NULL) + return; + + ret_args = smc_call3(SMCCC_ARCH_SOC_ID, SMCCC_GET_SOC_VERSION, 0, 0); + if (ret_args.arg0 != SMC_INVALID_PARAMETER) + *jep106code = ret_args.arg0; + + ret_args = smc_call3(SMCCC_ARCH_SOC_ID, SMCCC_GET_SOC_REVISION, 0, 0); + if (ret_args.arg0 != SMC_INVALID_PARAMETER) + *soc_revision = ret_args.arg0; +}