Message ID | 20230512121044.111574-10-abdellatif.elkhlifi@arm.com |
---|---|
State | Changes Requested |
Delegated to: | Ilias Apalodimas |
Headers | show |
Series | introduce Arm FF-A support | expand |
Hi Abdellatif I still have some concerns on this In the past [0] I asking why this needs to be a Kconfig option. Since FF-A is a mechanism we can use to discover SPs, in theory we dont need the ifdefery. We might need something if the code difference grows too much but I think we are fine for now. On top of that I am nissing how was this tested? did you test the current SMC to optee and the stmm for the RPMB backend? > +++ b/include/mm_communication.h > @@ -6,6 +6,9 @@ > * Copyright (c) 2017, Intel Corporation. All rights reserved. > * Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org> > * Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org> > + * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com> > + * Authors: > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> > */ > > #ifndef _MM_COMMUNICATION_H_ > @@ -13,6 +16,9 @@ > > #include <part_efi.h> > > +/* MM service UUID string (big-endian format). This UUID is common across all MM SPs */ > +#define MM_SP_UUID "33d532ed-e699-0942-c09c-a798d9cd722d" > + > /* > * Interface to the pseudo Trusted Application (TA), which provides a > * communication channel with the Standalone MM (Management Mode) > @@ -248,4 +254,11 @@ struct smm_variable_var_check_property { > u16 name[]; > }; > > +/* supported MM transports */ > +enum mm_comms_select { > + MM_COMMS_UNDEFINED, > + MM_COMMS_FFA, > + MM_COMMS_OPTEE > +}; > + > #endif /* _MM_COMMUNICATION_H_ */ > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig > index c5835e6ef6..08a6b84101 100644 > --- a/lib/efi_loader/Kconfig > +++ b/lib/efi_loader/Kconfig > @@ -55,13 +55,23 @@ config EFI_VARIABLE_FILE_STORE > stored as file /ubootefi.var on the EFI system partition. > > config EFI_MM_COMM_TEE > - bool "UEFI variables storage service via OP-TEE" > - depends on OPTEE > + bool "UEFI variables storage service via the trusted world" > + depends on OPTEE || ARM_FFA_TRANSPORT > help > + Allowing access to the MM SP services (SPs such as StandAlonneMM, smm-gateway). > + When using the u-boot OP-TEE driver, StandAlonneMM is supported. > + When using the u-boot FF-A driver any MM SP is supported. > + > If OP-TEE is present and running StandAloneMM, dispatch all UEFI > variable related operations to that. The application will verify, > authenticate and store the variables on an RPMB. > > + When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related > + operations to the MM SP running in the secure world. > + A door bell mechanism is used to notify the SP when there is data in the shared > + MM buffer. The data is copied by u-boot to the shared buffer before issuing > + the door bell event. > + > config EFI_VARIABLE_NO_STORE > bool "Don't persist non-volatile UEFI variables" > help > diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c > index dfef18435d..2effb705d7 100644 > --- a/lib/efi_loader/efi_variable_tee.c > +++ b/lib/efi_loader/efi_variable_tee.c > @@ -4,9 +4,14 @@ > * > * Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org> > * Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org> > + * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com> > + * > + * Authors: > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> > */ > > #include <common.h> > +#include <dm.h> > #include <efi.h> > #include <efi_api.h> > #include <efi_loader.h> > @@ -15,6 +20,36 @@ > #include <malloc.h> > #include <mm_communication.h> > > +#if IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT) > + > +#include <arm_ffa.h> > +#include <cpu_func.h> > +#include <mapmem.h> > + > +#ifndef FFA_SHARED_MM_BUFFER_SIZE > +#error "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h" > +#define FFA_SHARED_MM_BUFFER_SIZE 0 > +#endif > + > +#ifndef FFA_SHARED_MM_BUFFER_OFFSET > +#error "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/<board>.h" > +#define FFA_SHARED_MM_BUFFER_OFFSET 0 > +#endif > + > +#ifndef FFA_SHARED_MM_BUFFER_ADDR > +#error "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h" > +#define FFA_SHARED_MM_BUFFER_ADDR 0 > +#endif > + > +/* MM return codes */ > +#define MM_SUCCESS (0) > + > +static const char *mm_sp_svc_uuid = MM_SP_UUID; > + > +static u16 mm_sp_id; > + > +#endif > + > extern struct efi_var_file __efi_runtime_data *efi_var_buf; > static efi_uintn_t max_buffer_size; /* comm + var + func + data */ > static efi_uintn_t max_payload_size; /* func + data */ > @@ -24,6 +59,7 @@ struct mm_connection { > u32 session; > }; > > +#if (IS_ENABLED(CONFIG_OPTEE)) > /** > * get_connection() - Retrieve OP-TEE session for a specific UUID. > * [...] Isn't this problematic? At the moment there's not > 8.4 hardware out there. As a result the SPMC *is* implemented in OP-TEE. So how do we expect FF-A to work? [...] [0] https://lore.kernel.org/u-boot/Y3NV991bKRgas1zZ@hera/ Thanks /Ilias
Hi Ilias, > Hi Abdellatif > > I still have some concerns on this > > In the past [0] I asking why this needs to be a Kconfig option. Since FF-A > is a mechanism we can use to discover SPs, in theory we dont need the > ifdefery. We might need something if the code difference grows too much > but I think we are fine for now. Is my understanding correct you prefer that CONFIG_EFI_MM_COMM_TEE implies CONFIG_ARM_FFA_TRANSPORT ? So, no ifdefs anymore in efi_variable_tee.c. > > On top of that I am nissing how was this tested? did you test the current > SMC to optee and the stmm for the RPMB backend? We use Corstone-1000 platform for testing FF-A. U-Boot communicates with smm-gateway (leight version of stmm) using FF-A SMC ABIs. In the secure world we use TF-A, Optee OS and Trusted Services providing smm-gateway SP. In U-Boot we don't use the Optee driver because we use FF-A communication only. I hope this clears all doubts. Cheers Abdellatif > > > +++ b/include/mm_communication.h > > @@ -6,6 +6,9 @@ > > * Copyright (c) 2017, Intel Corporation. All rights reserved. > > * Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org> > > * Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org> > > + * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com> > > + * Authors: > > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> > > */ > > > > #ifndef _MM_COMMUNICATION_H_ > > @@ -13,6 +16,9 @@ > > > > #include <part_efi.h> > > > > +/* MM service UUID string (big-endian format). This UUID is common across all MM SPs */ > > +#define MM_SP_UUID "33d532ed-e699-0942-c09c-a798d9cd722d" > > + > > /* > > * Interface to the pseudo Trusted Application (TA), which provides a > > * communication channel with the Standalone MM (Management Mode) > > @@ -248,4 +254,11 @@ struct smm_variable_var_check_property { > > u16 name[]; > > }; > > > > +/* supported MM transports */ > > +enum mm_comms_select { > > + MM_COMMS_UNDEFINED, > > + MM_COMMS_FFA, > > + MM_COMMS_OPTEE > > +}; > > + > > #endif /* _MM_COMMUNICATION_H_ */ > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig > > index c5835e6ef6..08a6b84101 100644 > > --- a/lib/efi_loader/Kconfig > > +++ b/lib/efi_loader/Kconfig > > @@ -55,13 +55,23 @@ config EFI_VARIABLE_FILE_STORE > > stored as file /ubootefi.var on the EFI system partition. > > > > config EFI_MM_COMM_TEE > > - bool "UEFI variables storage service via OP-TEE" > > - depends on OPTEE > > + bool "UEFI variables storage service via the trusted world" > > + depends on OPTEE || ARM_FFA_TRANSPORT > > help > > + Allowing access to the MM SP services (SPs such as StandAlonneMM, smm-gateway). > > + When using the u-boot OP-TEE driver, StandAlonneMM is supported. > > + When using the u-boot FF-A driver any MM SP is supported. > > + > > If OP-TEE is present and running StandAloneMM, dispatch all UEFI > > variable related operations to that. The application will verify, > > authenticate and store the variables on an RPMB. > > > > + When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related > > + operations to the MM SP running in the secure world. > > + A door bell mechanism is used to notify the SP when there is data in the shared > > + MM buffer. The data is copied by u-boot to the shared buffer before issuing > > + the door bell event. > > + > > config EFI_VARIABLE_NO_STORE > > bool "Don't persist non-volatile UEFI variables" > > help > > diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c > > index dfef18435d..2effb705d7 100644 > > --- a/lib/efi_loader/efi_variable_tee.c > > +++ b/lib/efi_loader/efi_variable_tee.c > > @@ -4,9 +4,14 @@ > > * > > * Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org> > > * Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org> > > + * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com> > > + * > > + * Authors: > > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> > > */ > > > > #include <common.h> > > +#include <dm.h> > > #include <efi.h> > > #include <efi_api.h> > > #include <efi_loader.h> > > @@ -15,6 +20,36 @@ > > #include <malloc.h> > > #include <mm_communication.h> > > > > +#if IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT) > > + > > +#include <arm_ffa.h> > > +#include <cpu_func.h> > > +#include <mapmem.h> > > + > > +#ifndef FFA_SHARED_MM_BUFFER_SIZE > > +#error "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h" > > +#define FFA_SHARED_MM_BUFFER_SIZE 0 > > +#endif > > + > > +#ifndef FFA_SHARED_MM_BUFFER_OFFSET > > +#error "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/<board>.h" > > +#define FFA_SHARED_MM_BUFFER_OFFSET 0 > > +#endif > > + > > +#ifndef FFA_SHARED_MM_BUFFER_ADDR > > +#error "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h" > > +#define FFA_SHARED_MM_BUFFER_ADDR 0 > > +#endif > > + > > +/* MM return codes */ > > +#define MM_SUCCESS (0) > > + > > +static const char *mm_sp_svc_uuid = MM_SP_UUID; > > + > > +static u16 mm_sp_id; > > + > > +#endif > > + > > extern struct efi_var_file __efi_runtime_data *efi_var_buf; > > static efi_uintn_t max_buffer_size; /* comm + var + func + data */ > > static efi_uintn_t max_payload_size; /* func + data */ > > @@ -24,6 +59,7 @@ struct mm_connection { > > u32 session; > > }; > > > > +#if (IS_ENABLED(CONFIG_OPTEE)) > > > /** > > * get_connection() - Retrieve OP-TEE session for a specific UUID. > > * > > [...] > > Isn't this problematic? At the moment there's not > 8.4 hardware out > there. As a result the SPMC *is* implemented in OP-TEE. So how do we > expect FF-A to work? > > [...] > > [0] https://lore.kernel.org/u-boot/Y3NV991bKRgas1zZ@hera/ > > Thanks > /Ilias
On Fri, May 19, 2023 at 02:36:55PM +0100, Abdellatif El Khlifi wrote: > Hi Ilias, > > > Hi Abdellatif > > > > I still have some concerns on this > > > > In the past [0] I asking why this needs to be a Kconfig option. Since FF-A > > is a mechanism we can use to discover SPs, in theory we dont need the > > ifdefery. We might need something if the code difference grows too much > > but I think we are fine for now. > > Is my understanding correct you prefer that CONFIG_EFI_MM_COMM_TEE implies > CONFIG_ARM_FFA_TRANSPORT ? So, no ifdefs anymore in efi_variable_tee.c. I wonder what it takes to autodiscover that and get rid of all ifdefs (OPTEE and FF-A). In theory you could probe FF-A and if it's not there switch to the smc calling no? > > > > > On top of that I am nissing how was this tested? did you test the current > > SMC to optee and the stmm for the RPMB backend? > > We use Corstone-1000 platform for testing FF-A. > U-Boot communicates with smm-gateway (leight version of stmm) using FF-A SMC ABIs. > In the secure world we use TF-A, Optee OS and Trusted Services providing smm-gateway SP. > In U-Boot we don't use the Optee driver because we use FF-A communication only. > I hope this clears all doubts. Ok, but you will still need to load op-tee from BL2. My problem here is that this is a bit confusing from an architectural point of view and people need to be aware of what config options to choose, but if my understanding is correct we can automate that. Thanks /Ilias > > Cheers > Abdellatif > > > > > > +++ b/include/mm_communication.h > > > @@ -6,6 +6,9 @@ > > > * Copyright (c) 2017, Intel Corporation. All rights reserved. > > > * Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org> > > > * Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org> > > > + * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com> > > > + * Authors: > > > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> > > > */ > > > > > > #ifndef _MM_COMMUNICATION_H_ > > > @@ -13,6 +16,9 @@ > > > > > > #include <part_efi.h> > > > > > > +/* MM service UUID string (big-endian format). This UUID is common across all MM SPs */ > > > +#define MM_SP_UUID "33d532ed-e699-0942-c09c-a798d9cd722d" > > > + > > > /* > > > * Interface to the pseudo Trusted Application (TA), which provides a > > > * communication channel with the Standalone MM (Management Mode) > > > @@ -248,4 +254,11 @@ struct smm_variable_var_check_property { > > > u16 name[]; > > > }; > > > > > > +/* supported MM transports */ > > > +enum mm_comms_select { > > > + MM_COMMS_UNDEFINED, > > > + MM_COMMS_FFA, > > > + MM_COMMS_OPTEE > > > +}; > > > + > > > #endif /* _MM_COMMUNICATION_H_ */ > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig > > > index c5835e6ef6..08a6b84101 100644 > > > --- a/lib/efi_loader/Kconfig > > > +++ b/lib/efi_loader/Kconfig > > > @@ -55,13 +55,23 @@ config EFI_VARIABLE_FILE_STORE > > > stored as file /ubootefi.var on the EFI system partition. > > > > > > config EFI_MM_COMM_TEE > > > - bool "UEFI variables storage service via OP-TEE" > > > - depends on OPTEE > > > + bool "UEFI variables storage service via the trusted world" > > > + depends on OPTEE || ARM_FFA_TRANSPORT > > > help > > > + Allowing access to the MM SP services (SPs such as StandAlonneMM, smm-gateway). > > > + When using the u-boot OP-TEE driver, StandAlonneMM is supported. > > > + When using the u-boot FF-A driver any MM SP is supported. > > > + > > > If OP-TEE is present and running StandAloneMM, dispatch all UEFI > > > variable related operations to that. The application will verify, > > > authenticate and store the variables on an RPMB. > > > > > > + When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related > > > + operations to the MM SP running in the secure world. > > > + A door bell mechanism is used to notify the SP when there is data in the shared > > > + MM buffer. The data is copied by u-boot to the shared buffer before issuing > > > + the door bell event. > > > + > > > config EFI_VARIABLE_NO_STORE > > > bool "Don't persist non-volatile UEFI variables" > > > help > > > diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c > > > index dfef18435d..2effb705d7 100644 > > > --- a/lib/efi_loader/efi_variable_tee.c > > > +++ b/lib/efi_loader/efi_variable_tee.c > > > @@ -4,9 +4,14 @@ > > > * > > > * Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org> > > > * Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org> > > > + * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com> > > > + * > > > + * Authors: > > > + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> > > > */ > > > > > > #include <common.h> > > > +#include <dm.h> > > > #include <efi.h> > > > #include <efi_api.h> > > > #include <efi_loader.h> > > > @@ -15,6 +20,36 @@ > > > #include <malloc.h> > > > #include <mm_communication.h> > > > > > > +#if IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT) > > > + > > > +#include <arm_ffa.h> > > > +#include <cpu_func.h> > > > +#include <mapmem.h> > > > + > > > +#ifndef FFA_SHARED_MM_BUFFER_SIZE > > > +#error "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h" > > > +#define FFA_SHARED_MM_BUFFER_SIZE 0 > > > +#endif > > > + > > > +#ifndef FFA_SHARED_MM_BUFFER_OFFSET > > > +#error "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/<board>.h" > > > +#define FFA_SHARED_MM_BUFFER_OFFSET 0 > > > +#endif > > > + > > > +#ifndef FFA_SHARED_MM_BUFFER_ADDR > > > +#error "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h" > > > +#define FFA_SHARED_MM_BUFFER_ADDR 0 > > > +#endif > > > + > > > +/* MM return codes */ > > > +#define MM_SUCCESS (0) > > > + > > > +static const char *mm_sp_svc_uuid = MM_SP_UUID; > > > + > > > +static u16 mm_sp_id; > > > + > > > +#endif > > > + > > > extern struct efi_var_file __efi_runtime_data *efi_var_buf; > > > static efi_uintn_t max_buffer_size; /* comm + var + func + data */ > > > static efi_uintn_t max_payload_size; /* func + data */ > > > @@ -24,6 +59,7 @@ struct mm_connection { > > > u32 session; > > > }; > > > > > > +#if (IS_ENABLED(CONFIG_OPTEE)) > > > > > /** > > > * get_connection() - Retrieve OP-TEE session for a specific UUID. > > > * > > > > [...] > > > > Isn't this problematic? At the moment there's not > 8.4 hardware out > > there. As a result the SPMC *is* implemented in OP-TEE. So how do we > > expect FF-A to work? > > > > [...] > > > > [0] https://lore.kernel.org/u-boot/Y3NV991bKRgas1zZ@hera/ > > > > Thanks > > /Ilias
diff --git a/include/mm_communication.h b/include/mm_communication.h index e65fbde60d..f17847583b 100644 --- a/include/mm_communication.h +++ b/include/mm_communication.h @@ -6,6 +6,9 @@ * Copyright (c) 2017, Intel Corporation. All rights reserved. * Copyright (C) 2020 Linaro Ltd. <sughosh.ganu@linaro.org> * Copyright (C) 2020 Linaro Ltd. <ilias.apalodimas@linaro.org> + * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com> + * Authors: + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> */ #ifndef _MM_COMMUNICATION_H_ @@ -13,6 +16,9 @@ #include <part_efi.h> +/* MM service UUID string (big-endian format). This UUID is common across all MM SPs */ +#define MM_SP_UUID "33d532ed-e699-0942-c09c-a798d9cd722d" + /* * Interface to the pseudo Trusted Application (TA), which provides a * communication channel with the Standalone MM (Management Mode) @@ -248,4 +254,11 @@ struct smm_variable_var_check_property { u16 name[]; }; +/* supported MM transports */ +enum mm_comms_select { + MM_COMMS_UNDEFINED, + MM_COMMS_FFA, + MM_COMMS_OPTEE +}; + #endif /* _MM_COMMUNICATION_H_ */ diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index c5835e6ef6..08a6b84101 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -55,13 +55,23 @@ config EFI_VARIABLE_FILE_STORE stored as file /ubootefi.var on the EFI system partition. config EFI_MM_COMM_TEE - bool "UEFI variables storage service via OP-TEE" - depends on OPTEE + bool "UEFI variables storage service via the trusted world" + depends on OPTEE || ARM_FFA_TRANSPORT help + Allowing access to the MM SP services (SPs such as StandAlonneMM, smm-gateway). + When using the u-boot OP-TEE driver, StandAlonneMM is supported. + When using the u-boot FF-A driver any MM SP is supported. + If OP-TEE is present and running StandAloneMM, dispatch all UEFI variable related operations to that. The application will verify, authenticate and store the variables on an RPMB. + When ARM_FFA_TRANSPORT is used, dispatch all UEFI variable related + operations to the MM SP running in the secure world. + A door bell mechanism is used to notify the SP when there is data in the shared + MM buffer. The data is copied by u-boot to the shared buffer before issuing + the door bell event. + config EFI_VARIABLE_NO_STORE bool "Don't persist non-volatile UEFI variables" help diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c index dfef18435d..2effb705d7 100644 --- a/lib/efi_loader/efi_variable_tee.c +++ b/lib/efi_loader/efi_variable_tee.c @@ -4,9 +4,14 @@ * * Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org> * Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org> + * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com> + * + * Authors: + * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> */ #include <common.h> +#include <dm.h> #include <efi.h> #include <efi_api.h> #include <efi_loader.h> @@ -15,6 +20,36 @@ #include <malloc.h> #include <mm_communication.h> +#if IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT) + +#include <arm_ffa.h> +#include <cpu_func.h> +#include <mapmem.h> + +#ifndef FFA_SHARED_MM_BUFFER_SIZE +#error "FFA_SHARED_MM_BUFFER_SIZE must be defined in include/configs/<board>.h" +#define FFA_SHARED_MM_BUFFER_SIZE 0 +#endif + +#ifndef FFA_SHARED_MM_BUFFER_OFFSET +#error "FFA_SHARED_MM_BUFFER_OFFSET must be defined in include/configs/<board>.h" +#define FFA_SHARED_MM_BUFFER_OFFSET 0 +#endif + +#ifndef FFA_SHARED_MM_BUFFER_ADDR +#error "FFA_SHARED_MM_BUFFER_ADDR must be defined in include/configs/<board>.h" +#define FFA_SHARED_MM_BUFFER_ADDR 0 +#endif + +/* MM return codes */ +#define MM_SUCCESS (0) + +static const char *mm_sp_svc_uuid = MM_SP_UUID; + +static u16 mm_sp_id; + +#endif + extern struct efi_var_file __efi_runtime_data *efi_var_buf; static efi_uintn_t max_buffer_size; /* comm + var + func + data */ static efi_uintn_t max_payload_size; /* func + data */ @@ -24,6 +59,7 @@ struct mm_connection { u32 session; }; +#if (IS_ENABLED(CONFIG_OPTEE)) /** * get_connection() - Retrieve OP-TEE session for a specific UUID. * @@ -60,6 +96,7 @@ static int get_connection(struct mm_connection *conn) out: return rc; } +#endif /** * optee_mm_communicate() - Pass a buffer to StandaloneMM running in OP-TEE @@ -70,6 +107,7 @@ out: */ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize) { +#if (IS_ENABLED(CONFIG_OPTEE)) ulong buf_size; efi_status_t ret; struct efi_mm_communicate_header *mm_hdr; @@ -142,19 +180,246 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize) } return ret; +#else + log_err("EFI: Please enable CONFIG_OPTEE for MM comms\n"); + return EFI_UNSUPPORTED; +#endif } +#if IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT) + /** - * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send + * ffa_notify_mm_sp() - Announce there is data in the shared buffer + * + * Notify the MM partition in the trusted world that + * data is available in the shared buffer. + * This is a blocking call during which trusted world has exclusive access + * to the MM shared buffer. + * + * Return: + * + * 0 on success + */ +static int ffa_notify_mm_sp(void) +{ + struct ffa_send_direct_data msg = {0}; + int ret; + int sp_event_ret = -1; + struct udevice *dev; + + ret = uclass_first_device_err(UCLASS_FFA, &dev); + if (ret) { + log_err("EFI: Cannot find FF-A bus device, notify MM SP failure\n"); + return ret; + } + + msg.data0 = FFA_SHARED_MM_BUFFER_OFFSET; /* x3 */ + + ret = ffa_sync_send_receive(dev, mm_sp_id, &msg, 1); + if (ret) + return ret; + + sp_event_ret = msg.data0; /* x3 */ + + if (sp_event_ret == MM_SUCCESS) + return 0; + + /* Failure to notify the MM SP */ + + return -EACCES; +} + +/** + * ffa_discover_mm_sp_id() - Query the MM partition ID + * + * Use the FF-A driver to get the MM partition ID. + * If multiple partitions are found, use the first one. + * This is a boot time function. + * + * Return: + * + * 0 on success + */ +static int ffa_discover_mm_sp_id(void) +{ + u32 count = 0; + int ret; + struct ffa_partition_desc *descs; + struct udevice *dev; + + ret = uclass_first_device_err(UCLASS_FFA, &dev); + if (ret) { + log_err("EFI: Cannot find FF-A bus device, MM SP discovery failure\n"); + return ret; + } + + /* Ask the driver to fill the buffer with the SPs info */ + ret = ffa_partition_info_get(dev, mm_sp_svc_uuid, &count, &descs); + if (ret) { + log_err("EFI: Failure in querying SPs info (%d), MM SP discovery failure\n", ret); + return ret; + } + + /* MM SPs found , use the first one */ + + mm_sp_id = descs[0].info.id; + + log_info("EFI: MM partition ID 0x%x\n", mm_sp_id); + + return 0; +} +#endif + +/** + * ffa_mm_communicate() - Exchange EFI services data with the MM partition using FF-A + * @comm_buf: locally allocated communication buffer used for rx/tx + * @dsize: communication buffer size + * + * Issue a door bell event to notify the MM partition (SP) running in OP-TEE + * that there is data to read from the shared buffer. + * Communication with the MM SP is performed using FF-A transport. + * On the event, MM SP can read the data from the buffer and + * update the MM shared buffer with response data. + * The response data is copied back to the communication buffer. + * + * Return: + * + * EFI status code + */ +static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size) +{ +#if IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT) + ulong tx_data_size; + int ffa_ret; + efi_status_t efi_ret; + struct efi_mm_communicate_header *mm_hdr; + void *virt_shared_buf; + + if (!comm_buf) + return EFI_INVALID_PARAMETER; + + /* Discover MM partition ID at boot time */ + if (!mm_sp_id && ffa_discover_mm_sp_id()) { + log_err("EFI: Failure to discover MM SP ID at boot time, FF-A MM comms failure\n"); + return EFI_UNSUPPORTED; + } + + mm_hdr = (struct efi_mm_communicate_header *)comm_buf; + tx_data_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t); + + if (comm_buf_size != tx_data_size || tx_data_size > FFA_SHARED_MM_BUFFER_SIZE) + return EFI_INVALID_PARAMETER; + + /* Copy the data to the shared buffer */ + + virt_shared_buf = map_sysmem((phys_addr_t)FFA_SHARED_MM_BUFFER_ADDR, 0); + memcpy(virt_shared_buf, comm_buf, tx_data_size); + + /* + * The secure world might have cache disabled for + * the device region used for shared buffer (which is the case for Optee). + * In this case, the secure world reads the data from DRAM. + * Let's flush the cache so the DRAM is updated with the latest data. + */ +#ifdef CONFIG_ARM64 + invalidate_dcache_all(); +#endif + + /* Announce there is data in the shared buffer */ + + ffa_ret = ffa_notify_mm_sp(); + + switch (ffa_ret) { + case 0: { + ulong rx_data_size; + /* Copy the MM SP response from the shared buffer to the communication buffer */ + rx_data_size = ((struct efi_mm_communicate_header *)virt_shared_buf)->message_len + + sizeof(efi_guid_t) + + sizeof(size_t); + + if (rx_data_size > comm_buf_size) { + efi_ret = EFI_OUT_OF_RESOURCES; + break; + } + + memcpy(comm_buf, virt_shared_buf, rx_data_size); + efi_ret = EFI_SUCCESS; + break; + } + case -EINVAL: + efi_ret = EFI_DEVICE_ERROR; + break; + case -EPERM: + efi_ret = EFI_INVALID_PARAMETER; + break; + case -EACCES: + efi_ret = EFI_ACCESS_DENIED; + break; + case -EBUSY: + efi_ret = EFI_OUT_OF_RESOURCES; + break; + default: + efi_ret = EFI_ACCESS_DENIED; + } + + unmap_sysmem(virt_shared_buf); + return efi_ret; +#else + log_err("EFI: Please enable CONFIG_ARM_FFA_TRANSPORT for MM comms\n"); + return EFI_UNSUPPORTED; +#endif +} + +/** + * select_mm_comms() - detect the available MM transport + * + * If FF-A is compiled in, make sure the FF-A bus is probed successfully + * which means FF-A communication with secure world works and ready + * to be used. + * + * If FF-A is not detected, check if OPTEE support is compiled in. + * + * Return: + * + * On success MM_COMMS_FFA or MM_COMMS_OPTEE. Otherwise, MM_COMMS_UNDEFINED + */ +static enum mm_comms_select select_mm_comms(void) +{ + struct udevice *dev; + int ret; + + if (IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT)) { + ret = uclass_first_device_err(UCLASS_FFA, &dev); + if (ret) + log_err("EFI: Cannot find FF-A bus device, cannot select FF-A comms\n"); + else + return MM_COMMS_FFA; + } + + if (IS_ENABLED(CONFIG_OPTEE)) + return MM_COMMS_OPTEE; + + return MM_COMMS_UNDEFINED; +} + +/** + * mm_communicate() - Adjust the communication buffer to the MM SP and send * it to OP-TEE * - * @comm_buf: locally allocted communcation buffer + * @comm_buf: locally allocated communication buffer * @dsize: buffer size + * + * The SP (also called partition) can be any MM SP such as StandAlonneMM or smm-gateway. + * The comm_buf format is the same for both partitions. + * When using the u-boot OP-TEE driver, StandAlonneMM is supported. + * When using the u-boot FF-A driver, any MM SP is supported. + * * Return: status code */ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize) { efi_status_t ret; + enum mm_comms_select mm_comms; struct efi_mm_communicate_header *mm_hdr; struct smm_variable_communicate_header *var_hdr; @@ -162,7 +427,18 @@ static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize) mm_hdr = (struct efi_mm_communicate_header *)comm_buf; var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data; - ret = optee_mm_communicate(comm_buf, dsize); + mm_comms = select_mm_comms(); + switch (mm_comms) { + case MM_COMMS_UNDEFINED: + ret = EFI_UNSUPPORTED; + break; + case MM_COMMS_OPTEE: + ret = optee_mm_communicate(comm_buf, dsize); + break; + default: + ret = ffa_mm_communicate(comm_buf, dsize); + } + if (ret != EFI_SUCCESS) { log_err("%s failed!\n", __func__); return ret; @@ -258,6 +534,13 @@ efi_status_t EFIAPI get_max_payload(efi_uintn_t *size) goto out; } *size = var_payload->size; + + #if IS_ENABLED(CONFIG_ARM_FFA_TRANSPORT) + if (*size > FFA_SHARED_MM_BUFFER_SIZE) + *size = FFA_SHARED_MM_BUFFER_SIZE - MM_COMMUNICATE_HEADER_SIZE - + MM_VARIABLE_COMMUNICATE_SIZE; + #endif + /* * There seems to be a bug in EDK2 miscalculating the boundaries and * size checks, so deduct 2 more bytes to fulfill this requirement. Fix @@ -697,7 +980,7 @@ void efi_variables_boot_exit_notify(void) ret = EFI_NOT_FOUND; if (ret != EFI_SUCCESS) - log_err("Unable to notify StMM for ExitBootServices\n"); + log_err("Unable to notify the MM partition for ExitBootServices\n"); free(comm_buf); /*