Calling OPTEE_SMC_CALL_GET_OS_UUID from driver code
Sumit Garg
sumit.garg at linaro.org
Wed Feb 21 22:05:09 PST 2024
On Wed, 21 Feb 2024 at 22:28, Marc Gonzalez <mgonzalez at freebox.fr> wrote:
>
> On 21/02/2024 08:40, Sumit Garg wrote:
>
> > Hi Marc,
> >
> > On Tue, 20 Feb 2024 at 22:59, Marc Gonzalez wrote:
> >>
> >> Hello,
> >>
> >> The driver code I'm working on hard-codes
> >>
> >> #define TEE_SMC_FAST_CALL_VAL(func_num) \
> >> ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
> >> ARM_SMCCC_OWNER_TRUSTED_OS, (func_num))
> >>
> >> #define TEE_SMC_FUNCID_CALLS_UID 0xFF01
> >> #define TEE_SMC_CALLS_UID \
> >> ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
> >> ARM_SMCCC_OWNER_TRUSTED_OS_END, \
> >> TEE_SMC_FUNCID_CALLS_UID)
> >>
> >> arm_smccc_smc(TEE_SMC_CALLS_UID,
> >> 0, 0, 0/*is_swap*/, 0, 0, 0, 0, &res);
> >> dev_err(dev, "TEE UID %x %x %x %x\n", res.a0, res.a1, res.a2, res.a3);
> >>
> >>
> >> but it seems I would be required to somehow use
> >> OPTEE_SMC_CALL_GET_OS_UUID
> >>
> >> But it's not exported, and no code seems to use it...?
> >
> > Can you describe your use-case to require direct
> > OPTEE_SMC_CALL_GET_OS_UUID invocation?
>
> Turns out the GET_OS_UUID call was just debug code to make sure
> we were getting the expected reply.
>
> I have removed it from the production code.
> Below is the current code.
>
> diff --git a/drivers/staging/media/meson/vdec/vdec_1.c b/drivers/staging/media/meson/vdec/vdec_1.c
> index 3fe2de0c9331f..120bb1847aa38 100644
> --- a/drivers/staging/media/meson/vdec/vdec_1.c
> +++ b/drivers/staging/media/meson/vdec/vdec_1.c
> @@ -8,7 +8,10 @@
> */
>
> #include <linux/firmware.h>
> +#include <linux/delay.h>
> #include <linux/clk.h>
> +#include <linux/arm-smccc.h>
> +#include <soc/amlogic/socinfo.h>
>
> #include "vdec_1.h"
> #include "vdec_helpers.h"
> @@ -22,6 +25,45 @@
>
> #define MC_SIZE (4096 * 4)
>
> +static int
> +vdec_1_load_firmware_optee(struct amvdec_session *sess)
> +{
> + struct amvdec_codec_ops *codec_ops = sess->fmt_out->codec_ops;
> + struct amvdec_core *core = sess->core;
> + struct device *dev = core->dev_dec;
> + struct arm_smccc_res res;
> + u32 pixfmt = sess->fmt_out->pixfmt;
> + int fw_id = -1;
> +
> +#define TEE_SMC_FAST_CALL_VAL(func_num) \
> + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, ARM_SMCCC_OWNER_TRUSTED_OS, (func_num))
> +
> +#define TEE_SMC_FUNCID_LOAD_VIDEO_FW 15
> +#define TEE_SMC_LOAD_VIDEO_FW TEE_SMC_FAST_CALL_VAL(TEE_SMC_FUNCID_LOAD_VIDEO_FW)
> +#define OPTEE_VDEC_LEGACY 0
> +#define VIDEO_DEC_MPEG12 0
> +#define VIDEO_DEC_H264 11
> +
> + // Load wrong firmware, so that TA will reset hw component for us
> + arm_smccc_smc(TEE_SMC_LOAD_VIDEO_FW, 1, OPTEE_VDEC_LEGACY, 0, 0, 0, 0, 0, &res);
> +
> + if (pixfmt == V4L2_PIX_FMT_H264)
> + fw_id = 11;
> +
> + if (pixfmt == V4L2_PIX_FMT_MPEG1 || pixfmt == V4L2_PIX_FMT_MPEG2)
> + fw_id = 0;
> +
> + arm_smccc_smc(TEE_SMC_LOAD_VIDEO_FW, fw_id, OPTEE_VDEC_LEGACY, 0, 0, 0, 0, 0, &res);
> + dev_info(dev, "Load firmware %d: ret=%d\n", fw_id, res.a0);
> +
> + msleep(100);
> +
> + if (codec_ops->load_extended_firmware)
> + codec_ops->load_extended_firmware(sess, 0, 0);
> +
> + return 0;
> +}
> +
> static int
> vdec_1_load_firmware(struct amvdec_session *sess, const char *fwname)
> {
> @@ -209,7 +251,11 @@ static int vdec_1_start(struct amvdec_session *sess)
>
> vdec_1_stbuf_power_up(sess);
>
> - ret = vdec_1_load_firmware(sess, sess->fmt_out->firmware_path);
> + if (meson_get_secure_boot_state() == 1)
> + ret = vdec_1_load_firmware_optee(sess);
> + else
> + ret = vdec_1_load_firmware(sess, sess->fmt_out->firmware_path);
> +
> if (ret)
> goto stop;
>
> @@ -232,6 +278,13 @@ static int vdec_1_start(struct amvdec_session *sess)
> /* Let the firmware settle */
> usleep_range(10, 20);
>
> + /*
> + * When running secure boot, it looks like the codec needs
> + * more time to settle (perhaps to authenticate the image?)
> + */
> + if (meson_get_secure_boot_state() == 1)
> + msleep(100);
> +
> return 0;
>
> stop:
>
>
> >> $ git grep OPTEE_SMC_CALL_GET_OS_UUID
> >> Documentation/tee/op-tee.rst:- OPTEE_SMC_CALL_GET_OS_UUID returns the particular OP-TEE implementation, used
> >> drivers/tee/optee/optee_smc.h:#define OPTEE_SMC_CALL_GET_OS_UUID \
> >>
> >> How do I make calls to OP-TEE from driver code?
> >
> > The TEE driver API documentation is here [1] and you can refer to the
> > existing OP-TEE RNG driver here for reference.
> >
> > [1] https://docs.kernel.org/driver-api/tee.html
> > [2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/char/hw_random/optee-rng.c
>
> Wow, this looks very different from our code.
>
> Are we not supposed to call arm_smccc_smc() from driver code?
Yes, all OP-TEE invocations are abstracted out via the TEE bus driver
framework. You can find other examples with a simple grep like:
$ git grep -nr "tee_bus_type"
> Looks like no one else is calling arm_smccc_smc with an owner
> equal to ARM_SMCCC_OWNER_TRUSTED_OS...
>
BTW, looking at your use-case it sounds somewhat similar (load a
firmware via OP-TEE) to this [1]. So you can take that as a reference
for your driver development.
[1] https://lore.kernel.org/linux-arm-kernel/20240214172127.1022199-3-arnaud.pouliquen@foss.st.com/T/
-Sumit
More information about the linux-arm-kernel
mailing list