Merge "chore: add encrypt_fw to gitignore" into integration
diff --git a/docs/components/spd/optee-dispatcher.rst b/docs/components/spd/optee-dispatcher.rst
index 63baccc..81476f1 100644
--- a/docs/components/spd/optee-dispatcher.rst
+++ b/docs/components/spd/optee-dispatcher.rst
@@ -6,9 +6,26 @@
To build and execute OP-TEE follow the instructions at
`OP-TEE build.git`_
+There are two different modes for loading the OP-TEE OS. The default mode will
+load it as the BL32 payload during boot, and is the recommended technique for
+platforms to use. There is also another technique that will load OP-TEE OS after
+boot via an SMC call by enabling the option for OPTEE_ALLOW_SMC_LOAD that was
+specifically added for ChromeOS. Loading OP-TEE via an SMC call may be insecure
+depending upon the platform configuration. If using that option, be sure to
+understand the risks involved with allowing the Trusted OS to be loaded this
+way. ChromeOS uses a boot flow where it verifies the signature of the firmware
+before executing it, and then only if the signature is valid will the 'secrets'
+used by the TEE become accessible. The firmware then verifies the signature of
+the kernel using depthcharge, and the kernel verifies the rootfs using
+dm-verity. The SMC call to load OP-TEE is then invoked immediately after the
+kernel finishes loading and before any attack vectors can be opened up by
+mounting writable filesystems or opening network/device connections. this
+ensures the platform is 'closed' and running signed code through the point where
+OP-TEE is loaded.
+
--------------
-*Copyright (c) 2014-2018, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2014-2023, Arm Limited and Contributors. All rights reserved.*
.. _OP-TEE OS: https://github.com/OP-TEE/build
.. _OP-TEE build.git: https://github.com/OP-TEE/build
diff --git a/docs/plat/xilinx-versal-net.rst b/docs/plat/xilinx-versal-net.rst
index 5d2e663..5d04639 100644
--- a/docs/plat/xilinx-versal-net.rst
+++ b/docs/plat/xilinx-versal-net.rst
@@ -14,6 +14,11 @@
make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal_net bl31
```
+To build TF-A for JTAG DCC console:
+```bash
+make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal_net VERSAL_NET_CONSOLE=dcc bl31
+```
+
Xilinx Versal NET platform specific build options
-------------------------------------------------
@@ -23,8 +28,9 @@
* `VERSAL_NET_BL32_MEM_SIZE`: Specifies the size of the memory region of the bl32 binary.
* `VERSAL_NET_CONSOLE`: Select the console driver. Options:
- - `pl011`, `pl011_0`: ARM pl011 UART 0
+ - `pl011`, `pl011_0`: ARM pl011 UART 0 (default)
- `pl011_1` : ARM pl011 UART 1
+ - `dcc` : JTAG Debug Communication Channel(DCC)
* `TFA_NO_PM` : Platform Management support.
- 0 : Enable Platform Management (Default)
diff --git a/docs/threat_model/threat_model.rst b/docs/threat_model/threat_model.rst
index 99bbb3a..0e967ba 100644
--- a/docs/threat_model/threat_model.rst
+++ b/docs/threat_model/threat_model.rst
@@ -918,9 +918,54 @@
| Mitigations | | Yes / Platform specific |
+------------------------+-----------------------------------------------------+
++------------------------+-----------------------------------------------------+
+| ID | 14 |
++========================+=====================================================+
+| Threat | | **Security vulnerabilities in the Non-secure OS |
+| | can lead to secure world compromise if the option |
+| | OPTEE_ALLOW_SMC_LOAD is enabled.** |
+| | |
+| | | This option trusts the non-secure world up until |
+| | the point it issues the SMC call to load the |
+| | Secure BL32 payload. If a compromise occurs |
+| | before the SMC call is invoked, then arbitrary |
+| | code execution in S-EL1 can occur or arbitrary |
+| | memory in EL3 can be overwritten. |
++------------------------+-----------------------------------------------------+
+| Diagram Elements | DF5 |
++------------------------+-----------------------------------------------------+
+| Affected TF-A | BL31, BL32 |
+| Components | |
++------------------------+-----------------------------------------------------+
+| Assets | Code Execution, Sensitive Data |
++------------------------+-----------------------------------------------------+
+| Threat Agent | NSCode |
++------------------------+-----------------------------------------------------+
+| Threat Type | Tampering, Information Disclosure, |
+| | Elevation of privilege |
++------------------------+-----------------+-----------------+-----------------+
+| Application | Server | IoT | Mobile |
++------------------------+-----------------+-----------------+-----------------+
+| Impact | Critical (5) | Critical (5) | Critical (5) |
++------------------------+-----------------+-----------------+-----------------+
+| Likelihood | Low (2) | Low (2) | Low (2) |
++------------------------+-----------------+-----------------+-----------------+
+| Total Risk Rating | Medium (10) | Medium (10) | Medium (10) |
++------------------------+-----------------+-----------------+-----------------+
+| Mitigations | When enabling the option OPTEE_ALLOW_SMC_LOAD, |
+| | the non-secure OS must be considered a closed |
+| | platform up until the point the SMC can be invoked |
+| | to load OP-TEE. |
++------------------------+-----------------------------------------------------+
+| Mitigations | | None in TF-A itself. This option is only used by |
+| implemented? | ChromeOS currently which has other mechanisms to |
+| | to mitigate this threat which are described in |
+| | `OP-TEE Dispatcher`_. |
++------------------------+-----------------------------------------------------+
+
--------------
-*Copyright (c) 2021-2022, Arm Limited. All rights reserved.*
+*Copyright (c) 2021-2023, Arm Limited. All rights reserved.*
.. _STRIDE threat analysis technique: https://docs.microsoft.com/en-us/azure/security/develop/threat-modeling-tool-threats#stride-model
@@ -932,3 +977,4 @@
.. _TF-A error handling policy: https://trustedfirmware-a.readthedocs.io/en/latest/process/coding-guidelines.html#error-handling-and-robustness
.. _Secure Development Guidelines: https://trustedfirmware-a.readthedocs.io/en/latest/process/security-hardening.html#secure-development-guidelines
.. _Trusted Firmware-A Tests: https://git.trustedfirmware.org/TF-A/tf-a-tests.git/about/
+.. _OP-TEE Dispatcher: https://github.com/ARM-software/arm-trusted-firmware/blob/master/docs/components/spd/optee-dispatcher.rst
diff --git a/drivers/allwinner/axp/common.c b/drivers/allwinner/axp/common.c
index f1250b0..79f9089 100644
--- a/drivers/allwinner/axp/common.c
+++ b/drivers/allwinner/axp/common.c
@@ -9,6 +9,7 @@
#include <libfdt.h>
#include <common/debug.h>
+#include <common/fdt_wrappers.h>
#include <drivers/allwinner/axp.h>
int axp_check_id(void)
@@ -97,19 +98,9 @@
return 0;
}
-static bool is_node_disabled(const void *fdt, int node)
-{
- const char *cell;
- cell = fdt_getprop(fdt, node, "status", NULL);
- if (cell == NULL) {
- return false;
- }
- return strcmp(cell, "okay") != 0;
-}
-
static bool should_enable_regulator(const void *fdt, int node)
{
- if (is_node_disabled(fdt, node)) {
+ if (!fdt_node_is_enabled(fdt, node)) {
return false;
}
if (fdt_getprop(fdt, node, "phandle", NULL) != NULL) {
diff --git a/fdts/tc.dts b/fdts/tc.dts
index c10b7f8..4f27589 100644
--- a/fdts/tc.dts
+++ b/fdts/tc.dts
@@ -456,13 +456,25 @@
clock-names = "mclk", "apb_pclk";
};
+ gpu_clk: gpu_clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <1000000000>;
+ };
+
+ gpu_core_clk: gpu_core_clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <1000000000>;
+ };
+
gpu: gpu@2d000000 {
compatible = "arm,mali-midgard";
reg = <0x0 0x2d000000 0x0 0x200000>;
interrupts = <0 66 4>, <0 67 4>, <0 65 4>;
interrupt-names = "JOB", "MMU", "GPU";
- clocks = <&soc_refclk100mhz>;
- clock-names = "clk_mali";
+ clocks = <&gpu_clk>, <&gpu_core_clk>;
+ clock-names = "clk_mali", "shadercores";
iommus = <&smmu_700 0x200>;
operating-points = <
/* KHz uV */
@@ -470,6 +482,18 @@
>;
};
+ power_model@simple {
+ /*
+ * Numbers used are irrelevant to Titan,
+ * it helps suppressing the kernel warnings.
+ */
+ compatible = "arm,mali-simple-power-model";
+ static-coefficient = <2427750>;
+ dynamic-coefficient = <4687>;
+ ts = <20000 2000 (-20) 2>;
+ thermal-zone = "";
+ };
+
smmu_700: smmu_700@3f000000 {
#iommu-cells = <1>;
compatible = "arm,smmu-v3";
diff --git a/include/common/fdt_wrappers.h b/include/common/fdt_wrappers.h
index 2929fc2..b16510f 100644
--- a/include/common/fdt_wrappers.h
+++ b/include/common/fdt_wrappers.h
@@ -10,6 +10,7 @@
#define FDT_WRAPPERS_H
#include <libfdt_env.h>
+#include <libfdt.h>
/* Number of cells, given total length in bytes. Each cell is 4 bytes long */
#define NCELLS(len) ((len) / 4U)
@@ -53,6 +54,15 @@
return fdt32_to_cpu(dtb_header[1]);
}
+static inline bool fdt_node_is_enabled(const void *fdt, int node)
+{
+ int len;
+ const void *prop = fdt_getprop(fdt, node, "status", &len);
+
+ /* A non-existing status property means the device is enabled. */
+ return (prop == NULL) || (len == 5 && strcmp(prop, "okay") == 0);
+}
+
#define fdt_for_each_compatible_node(dtb, node, compatible_str) \
for (node = fdt_node_offset_by_compatible(dtb, -1, compatible_str); \
node >= 0; \
diff --git a/include/lib/optee_utils.h b/include/lib/optee_utils.h
index 06378eb..8224d50 100644
--- a/include/lib/optee_utils.h
+++ b/include/lib/optee_utils.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2023, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -17,4 +17,40 @@
image_info_t *pager_image_info,
image_info_t *paged_image_info);
+/*
+ * load_addr_hi and load_addr_lo: image load address.
+ * image_id: 0 - pager, 1 - paged
+ * size: image size in bytes.
+ */
+typedef struct optee_image {
+ uint32_t load_addr_hi;
+ uint32_t load_addr_lo;
+ uint32_t image_id;
+ uint32_t size;
+} optee_image_t;
+
+#define OPTEE_PAGER_IMAGE_ID 0
+#define OPTEE_PAGED_IMAGE_ID 1
+
+#define OPTEE_MAX_NUM_IMAGES 2u
+
+#define TEE_MAGIC_NUM_OPTEE 0x4554504f
+/*
+ * magic: header magic number.
+ * version: OPTEE header version:
+ * 1 - not supported
+ * 2 - supported
+ * arch: OPTEE os architecture type: 0 - AARCH32, 1 - AARCH64.
+ * flags: unused currently.
+ * nb_images: number of images.
+ */
+typedef struct optee_header {
+ uint32_t magic;
+ uint8_t version;
+ uint8_t arch;
+ uint16_t flags;
+ uint32_t nb_images;
+ optee_image_t optee_image_list[];
+} optee_header_t;
+
#endif /* OPTEE_UTILS_H */
diff --git a/include/lib/psa/psa_manifest/sid.h b/include/lib/psa/psa_manifest/sid.h
index 0bdeed4..be78bae 100644
--- a/include/lib/psa/psa_manifest/sid.h
+++ b/include/lib/psa/psa_manifest/sid.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2023, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -8,6 +8,9 @@
#ifndef PSA_MANIFEST_SID_H
#define PSA_MANIFEST_SID_H
+/******** RSS_SP_PLATFORM ********/
+#define RSS_PLATFORM_SERVICE_HANDLE (0x40000105U)
+
/******** PSA_SP_MEASURED_BOOT ********/
#define RSS_MEASURED_BOOT_HANDLE (0x40000110U)
diff --git a/include/lib/psa/rss_platform_api.h b/include/lib/psa/rss_platform_api.h
new file mode 100644
index 0000000..1dd7d05
--- /dev/null
+++ b/include/lib/psa/rss_platform_api.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef RSS_PLATFORM_API_H
+#define RSS_PLATFORM_API_H
+
+#include <stdint.h>
+
+#include "psa/error.h"
+
+#define RSS_PLATFORM_API_ID_NV_READ (1010)
+#define RSS_PLATFORM_API_ID_NV_INCREMENT (1011)
+
+/*
+ * Increments the given non-volatile (NV) counter by one
+ *
+ * counter_id NV counter ID.
+ *
+ * PSA_SUCCESS if the value is read correctly. Otherwise,
+ * it returns a PSA_ERROR.
+ */
+psa_status_t
+rss_platform_nv_counter_increment(uint32_t counter_id);
+
+/*
+ * Reads the given non-volatile (NV) counter
+ *
+ * counter_id NV counter ID.
+ * size Size of the buffer to store NV counter value
+ * in bytes.
+ * val Pointer to store the current NV counter value.
+ *
+ * PSA_SUCCESS if the value is read correctly. Otherwise,
+ * it returns a PSA_ERROR.
+ */
+psa_status_t
+rss_platform_nv_counter_read(uint32_t counter_id,
+ uint32_t size, uint8_t *val);
+
+#endif /* RSS_PLATFORM_API_H */
diff --git a/lib/optee/optee_utils.c b/lib/optee/optee_utils.c
index 6c87b0d..25272fc 100644
--- a/lib/optee/optee_utils.c
+++ b/lib/optee/optee_utils.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2023, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -11,42 +11,6 @@
#include <platform_def.h>
-/*
- * load_addr_hi and load_addr_lo: image load address.
- * image_id: 0 - pager, 1 - paged
- * size: image size in bytes.
- */
-typedef struct optee_image {
- uint32_t load_addr_hi;
- uint32_t load_addr_lo;
- uint32_t image_id;
- uint32_t size;
-} optee_image_t;
-
-#define OPTEE_PAGER_IMAGE_ID 0
-#define OPTEE_PAGED_IMAGE_ID 1
-
-#define OPTEE_MAX_NUM_IMAGES 2u
-
-#define TEE_MAGIC_NUM_OPTEE 0x4554504f
-/*
- * magic: header magic number.
- * version: OPTEE header version:
- * 1 - not supported
- * 2 - supported
- * arch: OPTEE os architecture type: 0 - AARCH32, 1 - AARCH64.
- * flags: unused currently.
- * nb_images: number of images.
- */
-typedef struct optee_header {
- uint32_t magic;
- uint8_t version;
- uint8_t arch;
- uint16_t flags;
- uint32_t nb_images;
- optee_image_t optee_image_list[];
-} optee_header_t;
-
/*******************************************************************************
* Check if it is a valid tee header
* Return true if valid
diff --git a/lib/psa/rss_platform.c b/lib/psa/rss_platform.c
new file mode 100644
index 0000000..359f894
--- /dev/null
+++ b/lib/psa/rss_platform.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+
+#include <psa/client.h>
+#include <psa_manifest/sid.h>
+#include <rss_platform_api.h>
+
+psa_status_t
+rss_platform_nv_counter_increment(uint32_t counter_id)
+{
+ struct psa_invec in_vec[1];
+
+ in_vec[0].base = &counter_id;
+ in_vec[0].len = sizeof(counter_id);
+
+ return psa_call(RSS_PLATFORM_SERVICE_HANDLE,
+ RSS_PLATFORM_API_ID_NV_INCREMENT,
+ in_vec, 1, NULL, 0);
+}
+
+psa_status_t
+rss_platform_nv_counter_read(uint32_t counter_id,
+ uint32_t size, uint8_t *val)
+{
+ struct psa_invec in_vec[1];
+ struct psa_outvec out_vec[1];
+
+ in_vec[0].base = &counter_id;
+ in_vec[0].len = sizeof(counter_id);
+
+ out_vec[0].base = val;
+ out_vec[0].len = size;
+
+ return psa_call(RSS_PLATFORM_SERVICE_HANDLE,
+ RSS_PLATFORM_API_ID_NV_READ,
+ in_vec, 1, out_vec, 1);
+}
diff --git a/plat/allwinner/sun50i_h6/sunxi_power.c b/plat/allwinner/sun50i_h6/sunxi_power.c
index d298e6b..1257076 100644
--- a/plat/allwinner/sun50i_h6/sunxi_power.c
+++ b/plat/allwinner/sun50i_h6/sunxi_power.c
@@ -8,8 +8,10 @@
#include <errno.h>
#include <common/debug.h>
+#include <common/fdt_wrappers.h>
#include <drivers/allwinner/axp.h>
#include <drivers/allwinner/sunxi_rsb.h>
+#include <libfdt.h>
#include <lib/mmio.h>
#include <sunxi_cpucfg.h>
@@ -63,7 +65,12 @@
int sunxi_pmic_setup(uint16_t socid, const void *fdt)
{
- int ret;
+ int node, ret;
+
+ node = fdt_node_offset_by_compatible(fdt, 0, "allwinner,sun8i-a23-rsb");
+ if ((node < 0) || !fdt_node_is_enabled(fdt, node)) {
+ return -ENODEV;
+ }
INFO("PMIC: Probing AXP805 on RSB\n");
diff --git a/plat/arm/common/fconf/fconf_ethosn_getter.c b/plat/arm/common/fconf/fconf_ethosn_getter.c
index 0b48a98..251471e 100644
--- a/plat/arm/common/fconf/fconf_ethosn_getter.c
+++ b/plat/arm/common/fconf/fconf_ethosn_getter.c
@@ -20,21 +20,6 @@
uint32_t stream_id;
};
-static bool fdt_node_is_enabled(const void *fdt, int node)
-{
- int len;
- const char *node_status;
-
- node_status = fdt_getprop(fdt, node, "status", &len);
- if (node_status == NULL ||
- (len == 5 && /* Includes null character */
- strncmp(node_status, "okay", 4U) == 0)) {
- return true;
- }
-
- return false;
-}
-
static bool fdt_node_has_reserved_memory(const void *fdt, int dev_node)
{
return fdt_get_property(fdt, dev_node, "memory-region", NULL) != NULL;
diff --git a/plat/xilinx/versal/aarch64/versal_common.c b/plat/xilinx/versal/aarch64/versal_common.c
index f55cde9..ed7f270 100644
--- a/plat/xilinx/versal/aarch64/versal_common.c
+++ b/plat/xilinx/versal/aarch64/versal_common.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (C) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -34,7 +35,7 @@
static void versal_print_platform_name(void)
{
- NOTICE("ATF running on Xilinx %s\n", PLATFORM_NAME);
+ NOTICE("TF-A running on %s\n", PLATFORM_NAME);
}
void versal_config_setup(void)
diff --git a/plat/xilinx/versal_net/bl31_versal_net_setup.c b/plat/xilinx/versal_net/bl31_versal_net_setup.c
index c9942d6..a7bae72 100644
--- a/plat/xilinx/versal_net/bl31_versal_net_setup.c
+++ b/plat/xilinx/versal_net/bl31_versal_net_setup.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
- * Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (C) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -14,6 +14,7 @@
#include <common/debug.h>
#include <common/fdt_fixup.h>
#include <common/fdt_wrappers.h>
+#include <drivers/arm/dcc.h>
#include <drivers/arm/pl011.h>
#include <drivers/console.h>
#include <lib/mmio.h>
@@ -28,7 +29,6 @@
static entry_point_info_t bl32_image_ep_info;
static entry_point_info_t bl33_image_ep_info;
-static console_t versal_net_runtime_console;
/*
* Return a pointer to the 'entry_point_info' structure of the next image for
@@ -95,18 +95,30 @@
panic();
}
- /* Initialize the console to provide early debug support */
- rc = console_pl011_register(VERSAL_NET_UART_BASE, uart_clock,
+ if (VERSAL_NET_CONSOLE_IS(pl011_0) || VERSAL_NET_CONSOLE_IS(pl011_1)) {
+ static console_t versal_net_runtime_console;
+
+ /* Initialize the console to provide early debug support */
+ rc = console_pl011_register(VERSAL_NET_UART_BASE, uart_clock,
VERSAL_NET_UART_BAUDRATE,
&versal_net_runtime_console);
- if (rc == 0) {
- panic();
- }
+ if (rc == 0) {
+ panic();
+ }
- console_set_scope(&versal_net_runtime_console, CONSOLE_FLAG_BOOT |
- CONSOLE_FLAG_RUNTIME);
+ console_set_scope(&versal_net_runtime_console, CONSOLE_FLAG_BOOT |
+ CONSOLE_FLAG_RUNTIME);
+ } else if (VERSAL_NET_CONSOLE_IS(dcc)) {
+ /* Initialize the dcc console for debug.
+ * dcc is over jtag and does not configures uart0 or uart1.
+ */
+ rc = console_dcc_register();
+ if (rc == 0) {
+ panic();
+ }
+ }
- NOTICE("TF-A running on Xilinx %s %d.%d\n", board_name_decode(),
+ NOTICE("TF-A running on %s %d.%d\n", board_name_decode(),
platform_version / 10U, platform_version % 10U);
/* Initialize the platform config for future decision making */
diff --git a/plat/xilinx/versal_net/include/versal_net_def.h b/plat/xilinx/versal_net/include/versal_net_def.h
index 14e63d5..9d1b7c2 100644
--- a/plat/xilinx/versal_net/include/versal_net_def.h
+++ b/plat/xilinx/versal_net/include/versal_net_def.h
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2021-2022, Xilinx, Inc. All rights reserved.
- * Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (C) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -24,6 +24,7 @@
#define VERSAL_NET_CONSOLE_ID_pl011 U(1)
#define VERSAL_NET_CONSOLE_ID_pl011_0 U(1)
#define VERSAL_NET_CONSOLE_ID_pl011_1 U(2)
+#define VERSAL_NET_CONSOLE_ID_dcc U(3)
#define VERSAL_NET_CONSOLE_IS(con) (VERSAL_NET_CONSOLE_ID_ ## con == VERSAL_NET_CONSOLE)
@@ -142,12 +143,11 @@
#define VERSAL_NET_UART_BAUDRATE 115200
-#if VERSAL_NET_CONSOLE_IS(pl011) || VERSAL_NET_CONSOLE_IS(pl011_0)
-#define VERSAL_NET_UART_BASE VERSAL_NET_UART0_BASE
-#elif VERSAL_NET_CONSOLE_IS(pl011_1)
+#if VERSAL_NET_CONSOLE_IS(pl011_1)
#define VERSAL_NET_UART_BASE VERSAL_NET_UART1_BASE
#else
-# error "invalid VERSAL_NET_CONSOLE"
+/* Default console is UART0 */
+#define VERSAL_NET_UART_BASE VERSAL_NET_UART0_BASE
#endif
#define PLAT_VERSAL_NET_CRASH_UART_BASE VERSAL_NET_UART_BASE
diff --git a/plat/xilinx/versal_net/platform.mk b/plat/xilinx/versal_net/platform.mk
index 622ae98..28e3295 100644
--- a/plat/xilinx/versal_net/platform.mk
+++ b/plat/xilinx/versal_net/platform.mk
@@ -53,7 +53,7 @@
HW_ASSISTED_COHERENCY := 1
VERSAL_NET_CONSOLE ?= pl011
-ifeq (${VERSAL_NET_CONSOLE}, $(filter ${VERSAL_NET_CONSOLE},pl011 pl011_0 pl011_1))
+ifeq (${VERSAL_NET_CONSOLE}, $(filter ${VERSAL_NET_CONSOLE},pl011 pl011_0 pl011_1 dcc))
else
$(error Please define VERSAL_NET_CONSOLE)
endif
@@ -72,6 +72,7 @@
include lib/libfdt/libfdt.mk
PLAT_BL_COMMON_SOURCES := \
+ drivers/arm/dcc/dcc_console.c \
drivers/delay_timer/delay_timer.c \
drivers/delay_timer/generic_delay_timer.c \
${GICV3_SOURCES} \
diff --git a/plat/xilinx/versal_net/versal_net_gicv3.c b/plat/xilinx/versal_net/versal_net_gicv3.c
index b7ac6ab..1d45a58 100644
--- a/plat/xilinx/versal_net/versal_net_gicv3.c
+++ b/plat/xilinx/versal_net/versal_net_gicv3.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
- * Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (C) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -30,14 +30,6 @@
/* The GICv3 driver only needs to be initialized in EL3 */
static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
-static const uintptr_t gicr_base_addrs[2] = {
- PLAT_VERSAL_NET_GICR_BASE, /* GICR Base address of the primary CPU */
- 0U /* Zero Termination */
-};
-
-/* List of zero terminated GICR frame addresses which CPUs will probe */
-static const uintptr_t *gicr_frames;
-
static const interrupt_prop_t versal_net_interrupt_props[] = {
PLAT_VERSAL_NET_G1S_IRQ_PROPS(INTR_GROUP1S),
PLAT_VERSAL_NET_G0_IRQ_PROPS(INTR_GROUP0)
@@ -72,7 +64,7 @@
static const gicv3_driver_data_t versal_net_gic_data __unused = {
.gicd_base = PLAT_VERSAL_NET_GICD_BASE,
- .gicr_base = 0U,
+ .gicr_base = PLAT_VERSAL_NET_GICR_BASE,
.interrupt_props = versal_net_interrupt_props,
.interrupt_props_num = ARRAY_SIZE(versal_net_interrupt_props),
.rdistif_num = PLATFORM_CORE_COUNT,
@@ -90,12 +82,6 @@
*/
#if IMAGE_BL31
gicv3_driver_init(&versal_net_gic_data);
- gicr_frames = gicr_base_addrs;
-
- if (gicv3_rdistif_probe(gicr_frames[0]) == -1) {
- ERROR("No GICR base frame found for Primary CPU\n");
- panic();
- }
#endif
}
@@ -131,25 +117,6 @@
*****************************************************************************/
void plat_versal_net_gic_pcpu_init(void)
{
- int32_t result;
- const uintptr_t *plat_gicr_frames = gicr_frames;
-
- do {
- result = gicv3_rdistif_probe(*plat_gicr_frames);
-
- /* If the probe is successful, no need to proceed further */
- if (result == 0) {
- break;
- }
-
- plat_gicr_frames++;
- } while (*plat_gicr_frames != 0U);
-
- if (result == -1) {
- ERROR("No GICR base frame found for CPU 0x%lx\n", read_mpidr());
- panic();
- }
-
gicv3_rdistif_init(plat_my_core_pos());
}
diff --git a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c
index 7bdd5bd..30af4d5 100644
--- a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c
+++ b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (C) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -303,10 +304,10 @@
maskid = ZYNQMP_CSU_IDCODE_XILINX_ID << ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT |
ZYNQMP_CSU_IDCODE_FAMILY << ZYNQMP_CSU_IDCODE_FAMILY_SHIFT;
if (tmp != maskid) {
- ERROR("Incorrect XILINX IDCODE 0x%x, maskid 0x%x\n", id, maskid);
+ ERROR("Incorrect IDCODE 0x%x, maskid 0x%x\n", id, maskid);
return "UNKN";
}
- VERBOSE("Xilinx IDCODE 0x%x\n", id);
+ VERBOSE("IDCODE 0x%x\n", id);
return zynqmp_get_silicon_idcode_name();
}
diff --git a/services/spd/opteed/opteed.mk b/services/spd/opteed/opteed.mk
index 643b054..477b45d 100644
--- a/services/spd/opteed/opteed.mk
+++ b/services/spd/opteed/opteed.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2023, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -16,3 +16,19 @@
# required so that optee code can control access to the timer registers
NS_TIMER_SWITCH := 1
+
+# WARNING: This enables loading of OP-TEE via an SMC, which can be potentially
+# insecure. This removes the boundary between the startup of the secure and
+# non-secure worlds until the point where this SMC is invoked. Only use this
+# setting if you can ensure that the non-secure OS can remain trusted up until
+# the point where this SMC is invoked.
+OPTEE_ALLOW_SMC_LOAD := 0
+ifeq ($(OPTEE_ALLOW_SMC_LOAD),1)
+ifeq ($(PLAT_XLAT_TABLES_DYNAMIC),0)
+$(error When OPTEE_ALLOW_SMC_LOAD=1, PLAT_XLAT_TABLES_DYNAMIC must also be 1)
+endif
+$(warning "OPTEE_ALLOW_SMC_LOAD is enabled which may result in an insecure \
+ platform")
+$(eval $(call add_define,PLAT_XLAT_TABLES_DYNAMIC))
+$(eval $(call add_define,OPTEE_ALLOW_SMC_LOAD))
+endif
diff --git a/services/spd/opteed/opteed_main.c b/services/spd/opteed/opteed_main.c
index 160a693..ff2aee0 100644
--- a/services/spd/opteed/opteed_main.c
+++ b/services/spd/opteed/opteed_main.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2023, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -16,6 +16,7 @@
******************************************************************************/
#include <assert.h>
#include <errno.h>
+#include <inttypes.h>
#include <stddef.h>
#include <arch_helpers.h>
@@ -24,12 +25,13 @@
#include <common/debug.h>
#include <common/runtime_svc.h>
#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/optee_utils.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
#include <plat/common/platform.h>
#include <tools_share/uuid.h>
#include "opteed_private.h"
#include "teesmc_opteed.h"
-#include "teesmc_opteed_macros.h"
/*******************************************************************************
* Address of the entrypoint vector table in OPTEE. It is
@@ -43,7 +45,16 @@
optee_context_t opteed_sp_context[OPTEED_CORE_COUNT];
uint32_t opteed_rw;
+#if OPTEE_ALLOW_SMC_LOAD
+static bool opteed_allow_load;
+#else
static int32_t opteed_init(void);
+#endif
+
+uint64_t dual32to64(uint32_t high, uint32_t low)
+{
+ return ((uint64_t)high << 32) | low;
+}
/*******************************************************************************
* This function is the handler registered for S-EL1 interrupts by the
@@ -93,6 +104,11 @@
******************************************************************************/
static int32_t opteed_setup(void)
{
+#if OPTEE_ALLOW_SMC_LOAD
+ opteed_allow_load = true;
+ INFO("Delaying OP-TEE setup until we receive an SMC call to load it\n");
+ return 0;
+#else
entry_point_info_t *optee_ep_info;
uint32_t linear_id;
uint64_t opteed_pageable_part;
@@ -142,6 +158,7 @@
bl31_register_bl32_init(&opteed_init);
return 0;
+#endif /* OPTEE_ALLOW_SMC_LOAD */
}
/*******************************************************************************
@@ -153,18 +170,12 @@
* non-secure state. This function performs a synchronous entry into
* OPTEE. OPTEE passes control back to this routine through a SMC.
******************************************************************************/
-static int32_t opteed_init(void)
+static int32_t
+opteed_init_with_entry_point(entry_point_info_t *optee_entry_point)
{
uint32_t linear_id = plat_my_core_pos();
optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
- entry_point_info_t *optee_entry_point;
uint64_t rc;
-
- /*
- * Get information about the OPTEE (BL32) image. Its
- * absence is a critical failure.
- */
- optee_entry_point = bl31_plat_get_next_image_ep_info(SECURE);
assert(optee_entry_point);
cm_init_my_context(optee_entry_point);
@@ -179,7 +190,116 @@
return rc;
}
+#if !OPTEE_ALLOW_SMC_LOAD
+static int32_t opteed_init(void)
+{
+ entry_point_info_t *optee_entry_point;
+ /*
+ * Get information about the OP-TEE (BL32) image. Its
+ * absence is a critical failure.
+ */
+ optee_entry_point = bl31_plat_get_next_image_ep_info(SECURE);
+ return opteed_init_with_entry_point(optee_entry_point);
+}
+#endif /* !OPTEE_ALLOW_SMC_LOAD */
+#if OPTEE_ALLOW_SMC_LOAD
+/*******************************************************************************
+ * This function is responsible for handling the SMC that loads the OP-TEE
+ * binary image via a non-secure SMC call. It takes the size and physical
+ * address of the payload as parameters.
+ ******************************************************************************/
+static int32_t opteed_handle_smc_load(uint64_t data_size, uint32_t data_pa)
+{
+ uintptr_t data_va = data_pa;
+ uint64_t mapped_data_pa;
+ uintptr_t mapped_data_va;
+ uint64_t data_map_size;
+ int32_t rc;
+ optee_header_t *image_header;
+ uint8_t *image_ptr;
+ uint64_t target_pa;
+ uint64_t target_end_pa;
+ uint64_t image_pa;
+ uintptr_t image_va;
+ optee_image_t *curr_image;
+ uintptr_t target_va;
+ uint64_t target_size;
+ entry_point_info_t optee_ep_info;
+ uint32_t linear_id = plat_my_core_pos();
+
+ mapped_data_pa = page_align(data_pa, DOWN);
+ mapped_data_va = mapped_data_pa;
+ data_map_size = page_align(data_size + (mapped_data_pa - data_pa), UP);
+
+ rc = mmap_add_dynamic_region(mapped_data_pa, mapped_data_va,
+ data_map_size, MT_MEMORY | MT_RO | MT_NS);
+ if (rc != 0) {
+ return rc;
+ }
+
+ image_header = (optee_header_t *)data_va;
+ if (image_header->magic != TEE_MAGIC_NUM_OPTEE ||
+ image_header->version != 2 || image_header->nb_images != 1) {
+ mmap_remove_dynamic_region(mapped_data_va, data_map_size);
+ return -EINVAL;
+ }
+
+ image_ptr = (uint8_t *)data_va + sizeof(optee_header_t) +
+ sizeof(optee_image_t);
+ if (image_header->arch == 1) {
+ opteed_rw = OPTEE_AARCH64;
+ } else {
+ opteed_rw = OPTEE_AARCH32;
+ }
+
+ curr_image = &image_header->optee_image_list[0];
+ image_pa = dual32to64(curr_image->load_addr_hi,
+ curr_image->load_addr_lo);
+ image_va = image_pa;
+ target_end_pa = image_pa + curr_image->size;
+
+ /* Now also map the memory we want to copy it to. */
+ target_pa = page_align(image_pa, DOWN);
+ target_va = target_pa;
+ target_size = page_align(target_end_pa, UP) - target_pa;
+
+ rc = mmap_add_dynamic_region(target_pa, target_va, target_size,
+ MT_MEMORY | MT_RW | MT_SECURE);
+ if (rc != 0) {
+ mmap_remove_dynamic_region(mapped_data_va, data_map_size);
+ return rc;
+ }
+
+ INFO("Loaded OP-TEE via SMC: size %d addr 0x%" PRIx64 "\n",
+ curr_image->size, image_va);
+
+ memcpy((void *)image_va, image_ptr, curr_image->size);
+ flush_dcache_range(target_pa, target_size);
+
+ mmap_remove_dynamic_region(mapped_data_va, data_map_size);
+ mmap_remove_dynamic_region(target_va, target_size);
+
+ /* Save the non-secure state */
+ cm_el1_sysregs_context_save(NON_SECURE);
+
+ opteed_init_optee_ep_state(&optee_ep_info,
+ opteed_rw,
+ image_pa,
+ 0,
+ 0,
+ 0,
+ &opteed_sp_context[linear_id]);
+ rc = opteed_init_with_entry_point(&optee_ep_info);
+
+ /* Restore non-secure state */
+ cm_el1_sysregs_context_restore(NON_SECURE);
+ cm_set_next_eret_context(NON_SECURE);
+
+ return rc;
+}
+#endif /* OPTEE_ALLOW_SMC_LOAD */
+
/*******************************************************************************
* This function is responsible for handling all SMCs in the Trusted OS/App
* range from the non-secure state as defined in the SMC Calling Convention
@@ -207,6 +327,34 @@
*/
if (is_caller_non_secure(flags)) {
+#if OPTEE_ALLOW_SMC_LOAD
+ if (smc_fid == NSSMC_OPTEED_CALL_LOAD_IMAGE) {
+ /*
+ * TODO: Consider wiping the code for SMC loading from
+ * memory after it has been invoked similar to what is
+ * done under RECLAIM_INIT, but extended to happen
+ * later.
+ */
+ if (!opteed_allow_load) {
+ SMC_RET1(handle, -EPERM);
+ }
+
+ opteed_allow_load = false;
+ uint64_t data_size = dual32to64(x1, x2);
+ uint64_t data_pa = dual32to64(x3, x4);
+ if (!data_size || !data_pa) {
+ /*
+ * This is invoked when the OP-TEE image didn't
+ * load correctly in the kernel but we want to
+ * block off loading of it later for security
+ * reasons.
+ */
+ SMC_RET1(handle, -EINVAL);
+ }
+ SMC_RET1(handle, opteed_handle_smc_load(
+ data_size, data_pa));
+ }
+#endif /* OPTEE_ALLOW_SMC_LOAD */
/*
* This is a fresh request from the non-secure client.
* The parameters are in x1 and x2. Figure out which
@@ -219,8 +367,18 @@
/*
* We are done stashing the non-secure context. Ask the
- * OPTEE to do the work now.
+ * OP-TEE to do the work now. If we are loading vi an SMC,
+ * then we also need to init this CPU context if not done
+ * already.
*/
+ if (optee_vector_table == NULL) {
+ SMC_RET1(handle, -EINVAL);
+ }
+
+ if (get_optee_pstate(optee_ctx->state) ==
+ OPTEE_PSTATE_UNKNOWN) {
+ opteed_cpu_on_finish_handler(0);
+ }
/*
* Verify if there is a valid context to use, copy the
diff --git a/services/spd/opteed/opteed_pm.c b/services/spd/opteed/opteed_pm.c
index 719eeb7..fa724a1 100644
--- a/services/spd/opteed/opteed_pm.c
+++ b/services/spd/opteed/opteed_pm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2023, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -32,6 +32,10 @@
uint32_t linear_id = plat_my_core_pos();
optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
+ if (get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_UNKNOWN) {
+ return 0;
+ }
+
assert(optee_vector_table);
assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
@@ -65,6 +69,10 @@
uint32_t linear_id = plat_my_core_pos();
optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
+ if (get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_UNKNOWN) {
+ return;
+ }
+
assert(optee_vector_table);
assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
@@ -92,7 +100,7 @@
* after initialising minimal architectural state that guarantees safe
* execution.
******************************************************************************/
-static void opteed_cpu_on_finish_handler(u_register_t unused)
+void opteed_cpu_on_finish_handler(u_register_t unused)
{
int32_t rc = 0;
uint32_t linear_id = plat_my_core_pos();
@@ -100,7 +108,8 @@
entry_point_info_t optee_on_entrypoint;
assert(optee_vector_table);
- assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_OFF);
+ assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_OFF ||
+ get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_UNKNOWN);
opteed_init_optee_ep_state(&optee_on_entrypoint, opteed_rw,
(uint64_t)&optee_vector_table->cpu_on_entry,
@@ -134,6 +143,10 @@
uint32_t linear_id = plat_my_core_pos();
optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
+ if (get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_UNKNOWN) {
+ return;
+ }
+
assert(optee_vector_table);
assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_SUSPEND);
@@ -173,6 +186,14 @@
uint32_t linear_id = plat_my_core_pos();
optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
+ /*
+ * OP-TEE must have been initialized in order to reach this location so
+ * it is safe to init the CPU context if not already done for this core.
+ */
+ if (get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_UNKNOWN) {
+ opteed_cpu_on_finish_handler(0);
+ }
+
assert(optee_vector_table);
assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
@@ -193,6 +214,14 @@
uint32_t linear_id = plat_my_core_pos();
optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
+ /*
+ * OP-TEE must have been initialized in order to reach this location so
+ * it is safe to init the CPU context if not already done for this core.
+ */
+ if (get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_UNKNOWN) {
+ opteed_cpu_on_finish_handler(0);
+ }
+
assert(optee_vector_table);
assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
diff --git a/services/spd/opteed/opteed_private.h b/services/spd/opteed/opteed_private.h
index 242154f..ab6e4cd 100644
--- a/services/spd/opteed/opteed_private.h
+++ b/services/spd/opteed/opteed_private.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2023, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -18,9 +18,10 @@
* OPTEE PM state information e.g. OPTEE is suspended, uninitialised etc
* and macros to access the state information in the per-cpu 'state' flags
******************************************************************************/
-#define OPTEE_PSTATE_OFF 0
-#define OPTEE_PSTATE_ON 1
-#define OPTEE_PSTATE_SUSPEND 2
+#define OPTEE_PSTATE_OFF 1
+#define OPTEE_PSTATE_ON 2
+#define OPTEE_PSTATE_SUSPEND 3
+#define OPTEE_PSTATE_UNKNOWN 0
#define OPTEE_PSTATE_SHIFT 0
#define OPTEE_PSTATE_MASK 0x3
#define get_optee_pstate(state) ((state >> OPTEE_PSTATE_SHIFT) & \
@@ -153,6 +154,7 @@
uint64_t mem_limit,
uint64_t dt_addr,
optee_context_t *optee_ctx);
+void opteed_cpu_on_finish_handler(u_register_t unused);
extern optee_context_t opteed_sp_context[OPTEED_CORE_COUNT];
extern uint32_t opteed_rw;
diff --git a/services/spd/opteed/teesmc_opteed.h b/services/spd/opteed/teesmc_opteed.h
index c82b58a..eae3ed2 100644
--- a/services/spd/opteed/teesmc_opteed.h
+++ b/services/spd/opteed/teesmc_opteed.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2023, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -9,8 +9,10 @@
#ifndef TEESMC_OPTEED_H
#define TEESMC_OPTEED_H
+#include "teesmc_opteed_macros.h"
+
/*
- * This file specifies SMC function IDs used when returning from TEE to the
+ * This section specifies SMC function IDs used when returning from TEE to the
* secure monitor.
*
* All SMC Function IDs indicates SMC32 Calling Convention but will carry
@@ -120,4 +122,39 @@
#define TEESMC_OPTEED_RETURN_SYSTEM_RESET_DONE \
TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_SYSTEM_RESET_DONE)
+/*
+ * This section specifies SMC function IDs used when the secure monitor is
+ * invoked from the non-secure world.
+ */
+
+/*
+ * Load OP-TEE image from the payload specified in the registers.
+ *
+ * WARNING: Use this cautiously as it could lead to insecure loading of the
+ * Trusted OS. Further details are in opteed.mk.
+ *
+ * Call register usage:
+ * x0 SMC Function ID, OPTEE_SMC_CALL_LOAD_IMAGE
+ * x1 Upper 32bit of a 64bit size for the payload
+ * x2 Lower 32bit of a 64bit size for the payload
+ * x3 Upper 32bit of the physical address for the payload
+ * x4 Lower 32bit of the physical address for the payload
+ *
+ * The payload consists of a optee_header struct that contains optee_image
+ * structs in a flex array, immediately following that in memory is the data
+ * referenced by the optee_image structs.
+ * Example:
+ *
+ * struct optee_header (with n images specified)
+ * image 0 data
+ * image 1 data
+ * ...
+ * image n-1 data
+ *
+ * Returns 0 on success and an error code otherwise.
+ */
+#define NSSMC_OPTEED_FUNCID_LOAD_IMAGE 2
+#define NSSMC_OPTEED_CALL_LOAD_IMAGE \
+ NSSMC_OPTEED_CALL(NSSMC_OPTEED_FUNCID_LOAD_IMAGE)
+
#endif /*TEESMC_OPTEED_H*/
diff --git a/services/spd/opteed/teesmc_opteed_macros.h b/services/spd/opteed/teesmc_opteed_macros.h
index 9d8a169..ad3ed75 100644
--- a/services/spd/opteed/teesmc_opteed_macros.h
+++ b/services/spd/opteed/teesmc_opteed_macros.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2023, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -14,4 +14,10 @@
(62 << FUNCID_OEN_SHIFT) | \
((func_num) & FUNCID_NUM_MASK))
+#define NSSMC_OPTEED_CALL(func_num) \
+ ((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) | \
+ ((SMC_32) << FUNCID_CC_SHIFT) | \
+ (50 << FUNCID_OEN_SHIFT) | \
+ ((func_num) & FUNCID_NUM_MASK))
+
#endif /* TEESMC_OPTEED_MACROS_H */