From 4b4ba7b0ecb546a5671931253efa1a0db9f9350c Mon Sep 17 00:00:00 2001 From: patrick Date: Wed, 17 May 2023 23:12:04 +0000 Subject: [PATCH] Add support for the Peripheral Authentication Service SMC interface. These are used to authenticate and boot firmware images on the many coprocessors embedded in Qualcomm SoCs. ok kettenis@ --- sys/dev/fdt/qcscm.c | 98 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/sys/dev/fdt/qcscm.c b/sys/dev/fdt/qcscm.c index 4c590869515..c5d2daa9d30 100644 --- a/sys/dev/fdt/qcscm.c +++ b/sys/dev/fdt/qcscm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: qcscm.c,v 1.3 2023/04/28 10:19:07 patrick Exp $ */ +/* $OpenBSD: qcscm.c,v 1.4 2023/05/17 23:12:04 patrick Exp $ */ /* * Copyright (c) 2022 Patrick Wildt * @@ -43,6 +43,7 @@ #define ARM_SMCCC_STD_CALL (0U << 31) #define ARM_SMCCC_FAST_CALL (1U << 31) #define ARM_SMCCC_LP64 (1U << 30) +#define ARM_SMCCC_OWNER_SIP 2 #define QCTEE_TZ_OWNER_TZ_APPS 48 #define QCTEE_TZ_OWNER_QSEE_OS 50 @@ -68,6 +69,14 @@ #define QCTEE_UEFI_DEVICE_ERROR 0x80000007 #define QCTEE_UEFI_NOT_FOUND 0x8000000e +#define QCSCM_SVC_PIL 0x02 +#define QCSCM_PIL_PAS_INIT_IMAGE 0x01 +#define QCSCM_PIL_PAS_MEM_SETUP 0x02 +#define QCSCM_PIL_PAS_AUTH_AND_RESET 0x05 +#define QCSCM_PIL_PAS_SHUTDOWN 0x06 +#define QCSCM_PIL_PAS_IS_SUPPORTED 0x07 +#define QCSCM_PIL_PAS_MSS_RESET 0x0a + #define QCSCM_INTERRUPTED 1 #define QCSCM_ARGINFO_NUM(x) (((x) & 0xf) << 0) @@ -730,6 +739,93 @@ qcscm_uefi_rtc_set(uint32_t off) return 0; } +int +qcscm_pas_init_image(uint32_t peripheral, paddr_t metadata) +{ + struct qcscm_softc *sc = qcscm_sc; + uint64_t res[3]; + uint64_t args[2]; + uint32_t arginfo; + int ret; + + if (sc == NULL) + return ENXIO; + + arginfo = QCSCM_ARGINFO_NUM(nitems(args)); + arginfo |= QCSCM_ARGINFO_TYPE(0, QCSCM_ARGINFO_TYPE_VAL); + arginfo |= QCSCM_ARGINFO_TYPE(1, QCSCM_ARGINFO_TYPE_RW); + args[0] = peripheral; + args[1] = metadata; + + /* Make call into TEE */ + ret = qcscm_smc_call(sc, ARM_SMCCC_OWNER_SIP, QCSCM_SVC_PIL, + QCSCM_PIL_PAS_INIT_IMAGE, arginfo, args, nitems(args), res); + + /* If the call succeeded, check the response status */ + if (ret == 0) + ret = res[0]; + + return ret; +} + +int +qcscm_pas_mem_setup(uint32_t peripheral, paddr_t addr, size_t size) +{ + struct qcscm_softc *sc = qcscm_sc; + uint64_t res[3]; + uint64_t args[3]; + uint32_t arginfo; + int ret; + + if (sc == NULL) + return ENXIO; + + arginfo = QCSCM_ARGINFO_NUM(nitems(args)); + arginfo |= QCSCM_ARGINFO_TYPE(0, QCSCM_ARGINFO_TYPE_VAL); + arginfo |= QCSCM_ARGINFO_TYPE(1, QCSCM_ARGINFO_TYPE_VAL); + arginfo |= QCSCM_ARGINFO_TYPE(2, QCSCM_ARGINFO_TYPE_VAL); + args[0] = peripheral; + args[1] = addr; + args[2] = size; + + /* Make call into TEE */ + ret = qcscm_smc_call(sc, ARM_SMCCC_OWNER_SIP, QCSCM_SVC_PIL, + QCSCM_PIL_PAS_MEM_SETUP, arginfo, args, nitems(args), res); + + /* If the call succeeded, check the response status */ + if (ret == 0) + ret = res[0]; + + return ret; +} + +int +qcscm_pas_auth_and_reset(uint32_t peripheral) +{ + struct qcscm_softc *sc = qcscm_sc; + uint64_t res[3]; + uint64_t args[1]; + uint32_t arginfo; + int ret; + + if (sc == NULL) + return ENXIO; + + arginfo = QCSCM_ARGINFO_NUM(nitems(args)); + arginfo |= QCSCM_ARGINFO_TYPE(0, QCSCM_ARGINFO_TYPE_VAL); + args[0] = peripheral; + + /* Make call into TEE */ + ret = qcscm_smc_call(sc, ARM_SMCCC_OWNER_SIP, QCSCM_SVC_PIL, + QCSCM_PIL_PAS_AUTH_AND_RESET, arginfo, args, nitems(args), res); + + /* If the call succeeded, check the response status */ + if (ret == 0) + ret = res[0]; + + return ret; +} + /* DMA code */ struct qcscm_dmamem * qcscm_dmamem_alloc(struct qcscm_softc *sc, bus_size_t size, bus_size_t align) -- 2.20.1