aboutsummaryrefslogtreecommitdiff
path: root/fwu/ns_bl1u/ns_bl1u_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'fwu/ns_bl1u/ns_bl1u_main.c')
-rw-r--r--fwu/ns_bl1u/ns_bl1u_main.c226
1 files changed, 226 insertions, 0 deletions
diff --git a/fwu/ns_bl1u/ns_bl1u_main.c b/fwu/ns_bl1u/ns_bl1u_main.c
new file mode 100644
index 000000000..46c226367
--- /dev/null
+++ b/fwu/ns_bl1u/ns_bl1u_main.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <errno.h>
+#include <image_loader.h>
+#include <io_fip.h>
+#include <io_storage.h>
+#include <mmio.h>
+#include <nvm.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <smccc.h>
+#include <status.h>
+#include <string.h>
+#include <tftf.h>
+#include <tftf_lib.h>
+
+#define FWU_NON_SECURE (0x0)
+#define FWU_SECURE (0x1)
+
+#define FWU_NON_EXEC (0x0)
+#define FWU_EXEC (0x1)
+
+/* This size is used to exercise partial copy */
+#define FWU_COPY_PARTIAL_SIZE (0x10)
+
+extern const char version_string[];
+
+typedef void (*ns_bl2u_entrypoint_t)(unsigned long);
+
+void ns_bl1u_fwu_test_main(void);
+
+/*
+ * This structure will be used for:
+ * 1. Assigning unique image identifier.
+ * 2. Assigning attribute to FWU image.
+ * (FWU_NON_SECURE/FWU_SECURE)
+ * (FWU_NON_EXEC/FWU_EXEC)
+ */
+typedef struct fwu_image_load_desc {
+ unsigned int image_id;
+ unsigned int secure;
+ unsigned int execute;
+} fwu_image_load_desc_t;
+
+static const fwu_image_load_desc_t ns_bl1u_desc[] = {
+ [0] = {
+ /* Initialize FWU_CERT image params */
+ .image_id = FWU_CERT_ID,
+ .secure = FWU_SECURE,
+ },
+ [1] = {
+ /*
+ * Initialize SCP_BL2U image params
+ * Not needed for FVP platform.
+ */
+ .image_id = SCP_BL2U_IMAGE_ID,
+ .secure = FWU_SECURE,
+ },
+ [2] = {
+ /* Initialize BL2U image params */
+ .image_id = BL2U_IMAGE_ID,
+ .secure = FWU_SECURE,
+ .execute = FWU_EXEC
+ },
+ [3] = {
+ /* Initialize NS_BL2U image params */
+ .image_id = NS_BL2U_IMAGE_ID,
+ }
+};
+
+static long smc_result;
+
+#define CHECK_SMC_RESULT(_r) do { \
+ if (smc_result != _r) { \
+ ERROR("NS_BL1U: SMC call failed with result:%li\n", smc_result);\
+ panic(); \
+ } \
+ } while (0);
+
+static void ns_bl1u_fwu_smc_call(unsigned int smc_id,
+ unsigned long x1,
+ unsigned long x2,
+ unsigned long x3,
+ unsigned long x4)
+{
+ smc_ret_values fwu_result = {0};
+ smc_args fwu_params = {smc_id, x1, x2, x3, x4};
+ fwu_result = tftf_smc(&fwu_params);
+ smc_result = fwu_result.ret0;
+}
+
+
+/*******************************************************************************
+ * Following are the responsibilities of NS_BL1U image:
+ * Load FWU images from external NVM memory to NS RAM.
+ * Call SMC's to authenticate images.
+ * Jump to NS_BL2U which carries out next FWU steps.
+******************************************************************************/
+void ns_bl1u_main(void)
+{
+ int index;
+ unsigned int img_size;
+ int err;
+ unsigned long offset;
+ ns_bl2u_entrypoint_t ns_bl2u_entrypoint =
+ (ns_bl2u_entrypoint_t)NS_BL2U_BASE;
+ const fwu_image_load_desc_t *image_desc;
+
+ NOTICE("NS_BL1U: %s\n", version_string);
+ NOTICE("NS_BL1U: %s\n", build_message);
+
+ tftf_arch_setup();
+
+ plat_fwu_io_setup();
+
+#if FWU_BL_TEST
+ ns_bl1u_fwu_test_main();
+#endif
+
+ for (index = 0; index < ARRAY_SIZE(ns_bl1u_desc); index++) {
+
+ image_desc = &ns_bl1u_desc[index];
+
+#if PLAT_fvp
+ /* Skip SCP_BL2U loading for FVP */
+ if (image_desc->image_id == SCP_BL2U_IMAGE_ID)
+ continue;
+#endif
+
+ INFO("NS_BL1U: Loading image '%s' (ID:%u)\n",
+ get_image_name(image_desc->image_id),
+ image_desc->image_id);
+
+ img_size = get_image_size(image_desc->image_id);
+ INFO("NS_BL1U: Image size = %d\n", img_size);
+ if (img_size == 0) {
+ ERROR("NS_BL1U: Invalid image size\n");
+ panic();
+ }
+
+ if (image_desc->secure == FWU_SECURE) {
+
+ offset = get_image_offset(image_desc->image_id);
+
+ INFO("NS_BL1U: Calling COPY SMC for partial copy\n");
+ ns_bl1u_fwu_smc_call(FWU_SMC_IMAGE_COPY, image_desc->image_id,
+ offset, FWU_COPY_PARTIAL_SIZE, img_size);
+ CHECK_SMC_RESULT(0);
+
+ ns_bl1u_fwu_smc_call(FWU_SMC_IMAGE_COPY, image_desc->image_id,
+ (offset + FWU_COPY_PARTIAL_SIZE),
+ (img_size - FWU_COPY_PARTIAL_SIZE), img_size);
+ CHECK_SMC_RESULT(0);
+ } else {
+ /* The only non-secure image in ns_bl1u_desc[] should be NS_BL2U */
+ assert(image_desc->image_id == NS_BL2U_IMAGE_ID);
+
+ err = load_image(image_desc->image_id, NS_BL2U_BASE);
+ if (err) {
+ ERROR("NS_BL1U: Failed to load NS_BL2U\n");
+ panic();
+ }
+ offset = NS_BL2U_BASE;
+ }
+
+ INFO("NS_BL1U: Calling AUTH SMC\n");
+ ns_bl1u_fwu_smc_call(FWU_SMC_IMAGE_AUTH, image_desc->image_id,
+ offset, img_size, 0);
+ CHECK_SMC_RESULT(0);
+#if FWU_BL_TEST
+ /* Check if authenticating again the same image returns error. */
+ INFO("NS_BL1U: TEST Calling SMC to auth again\n");
+ ns_bl1u_fwu_smc_call(FWU_SMC_IMAGE_AUTH, ns_bl1u_desc[index].image_id,
+ offset, img_size, 0);
+ CHECK_SMC_RESULT(-EPERM);
+#endif
+ if (image_desc->execute == FWU_EXEC) {
+ INFO("NS_BL1U: Calling EXECUTE SMC\n");
+ ns_bl1u_fwu_smc_call(FWU_SMC_IMAGE_EXECUTE, image_desc->image_id,
+ 0, 0, 0);
+ CHECK_SMC_RESULT(0);
+
+#if FWU_BL_TEST
+ /* Check if executing again the same image returns error. */
+ INFO("NS_BL1U: TEST Calling SMC to execute again\n");
+ ns_bl1u_fwu_smc_call(FWU_SMC_IMAGE_EXECUTE,
+ ns_bl1u_desc[index].image_id, 0, 0, 0);
+ CHECK_SMC_RESULT(-EPERM);
+#endif
+ } else {
+ /*
+ * If the image is not executable, its internal state
+ * needs to be reset, unless it is for later consumption
+ * by another CPU (like for the SCP_BL2U firmware).
+ */
+ if (image_desc->image_id != SCP_BL2U_IMAGE_ID) {
+ INFO("NS_BL1U: Calling RESET SMC\n");
+ ns_bl1u_fwu_smc_call(FWU_SMC_IMAGE_RESET,
+ image_desc->image_id,
+ 0, 0, 0);
+ CHECK_SMC_RESULT(0);
+ }
+ }
+ }
+
+ /*
+ * Clean and invalidate the caches.
+ * And disable the MMU before jumping to NS_BL2U.
+ */
+ disable_mmu_icache();
+
+ /*
+ * The argument passed to NS_BL2U is not used currently.
+ * But keeping the argument passing mechanism for future use.
+ */
+ ns_bl2u_entrypoint(0);
+
+ panic();
+}