blob: 46c2263676a6a62c928ad1fb030032e7b1ce5524 [file] [log] [blame]
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02001/*
2 * Copyright (c) 2018, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch_helpers.h>
8#include <assert.h>
9#include <debug.h>
10#include <errno.h>
11#include <image_loader.h>
12#include <io_fip.h>
13#include <io_storage.h>
14#include <mmio.h>
15#include <nvm.h>
16#include <platform.h>
17#include <platform_def.h>
18#include <smccc.h>
19#include <status.h>
20#include <string.h>
21#include <tftf.h>
22#include <tftf_lib.h>
23
24#define FWU_NON_SECURE (0x0)
25#define FWU_SECURE (0x1)
26
27#define FWU_NON_EXEC (0x0)
28#define FWU_EXEC (0x1)
29
30/* This size is used to exercise partial copy */
31#define FWU_COPY_PARTIAL_SIZE (0x10)
32
33extern const char version_string[];
34
35typedef void (*ns_bl2u_entrypoint_t)(unsigned long);
36
37void ns_bl1u_fwu_test_main(void);
38
39/*
40 * This structure will be used for:
41 * 1. Assigning unique image identifier.
42 * 2. Assigning attribute to FWU image.
43 * (FWU_NON_SECURE/FWU_SECURE)
44 * (FWU_NON_EXEC/FWU_EXEC)
45 */
46typedef struct fwu_image_load_desc {
47 unsigned int image_id;
48 unsigned int secure;
49 unsigned int execute;
50} fwu_image_load_desc_t;
51
52static const fwu_image_load_desc_t ns_bl1u_desc[] = {
53 [0] = {
54 /* Initialize FWU_CERT image params */
55 .image_id = FWU_CERT_ID,
56 .secure = FWU_SECURE,
57 },
58 [1] = {
59 /*
60 * Initialize SCP_BL2U image params
61 * Not needed for FVP platform.
62 */
63 .image_id = SCP_BL2U_IMAGE_ID,
64 .secure = FWU_SECURE,
65 },
66 [2] = {
67 /* Initialize BL2U image params */
68 .image_id = BL2U_IMAGE_ID,
69 .secure = FWU_SECURE,
70 .execute = FWU_EXEC
71 },
72 [3] = {
73 /* Initialize NS_BL2U image params */
74 .image_id = NS_BL2U_IMAGE_ID,
75 }
76};
77
78static long smc_result;
79
80#define CHECK_SMC_RESULT(_r) do { \
81 if (smc_result != _r) { \
82 ERROR("NS_BL1U: SMC call failed with result:%li\n", smc_result);\
83 panic(); \
84 } \
85 } while (0);
86
87static void ns_bl1u_fwu_smc_call(unsigned int smc_id,
88 unsigned long x1,
89 unsigned long x2,
90 unsigned long x3,
91 unsigned long x4)
92{
93 smc_ret_values fwu_result = {0};
94 smc_args fwu_params = {smc_id, x1, x2, x3, x4};
95 fwu_result = tftf_smc(&fwu_params);
96 smc_result = fwu_result.ret0;
97}
98
99
100/*******************************************************************************
101 * Following are the responsibilities of NS_BL1U image:
102 * Load FWU images from external NVM memory to NS RAM.
103 * Call SMC's to authenticate images.
104 * Jump to NS_BL2U which carries out next FWU steps.
105******************************************************************************/
106void ns_bl1u_main(void)
107{
108 int index;
109 unsigned int img_size;
110 int err;
111 unsigned long offset;
112 ns_bl2u_entrypoint_t ns_bl2u_entrypoint =
113 (ns_bl2u_entrypoint_t)NS_BL2U_BASE;
114 const fwu_image_load_desc_t *image_desc;
115
116 NOTICE("NS_BL1U: %s\n", version_string);
117 NOTICE("NS_BL1U: %s\n", build_message);
118
119 tftf_arch_setup();
120
121 plat_fwu_io_setup();
122
123#if FWU_BL_TEST
124 ns_bl1u_fwu_test_main();
125#endif
126
127 for (index = 0; index < ARRAY_SIZE(ns_bl1u_desc); index++) {
128
129 image_desc = &ns_bl1u_desc[index];
130
131#if PLAT_fvp
132 /* Skip SCP_BL2U loading for FVP */
133 if (image_desc->image_id == SCP_BL2U_IMAGE_ID)
134 continue;
135#endif
136
137 INFO("NS_BL1U: Loading image '%s' (ID:%u)\n",
138 get_image_name(image_desc->image_id),
139 image_desc->image_id);
140
141 img_size = get_image_size(image_desc->image_id);
142 INFO("NS_BL1U: Image size = %d\n", img_size);
143 if (img_size == 0) {
144 ERROR("NS_BL1U: Invalid image size\n");
145 panic();
146 }
147
148 if (image_desc->secure == FWU_SECURE) {
149
150 offset = get_image_offset(image_desc->image_id);
151
152 INFO("NS_BL1U: Calling COPY SMC for partial copy\n");
153 ns_bl1u_fwu_smc_call(FWU_SMC_IMAGE_COPY, image_desc->image_id,
154 offset, FWU_COPY_PARTIAL_SIZE, img_size);
155 CHECK_SMC_RESULT(0);
156
157 ns_bl1u_fwu_smc_call(FWU_SMC_IMAGE_COPY, image_desc->image_id,
158 (offset + FWU_COPY_PARTIAL_SIZE),
159 (img_size - FWU_COPY_PARTIAL_SIZE), img_size);
160 CHECK_SMC_RESULT(0);
161 } else {
162 /* The only non-secure image in ns_bl1u_desc[] should be NS_BL2U */
163 assert(image_desc->image_id == NS_BL2U_IMAGE_ID);
164
165 err = load_image(image_desc->image_id, NS_BL2U_BASE);
166 if (err) {
167 ERROR("NS_BL1U: Failed to load NS_BL2U\n");
168 panic();
169 }
170 offset = NS_BL2U_BASE;
171 }
172
173 INFO("NS_BL1U: Calling AUTH SMC\n");
174 ns_bl1u_fwu_smc_call(FWU_SMC_IMAGE_AUTH, image_desc->image_id,
175 offset, img_size, 0);
176 CHECK_SMC_RESULT(0);
177#if FWU_BL_TEST
178 /* Check if authenticating again the same image returns error. */
179 INFO("NS_BL1U: TEST Calling SMC to auth again\n");
180 ns_bl1u_fwu_smc_call(FWU_SMC_IMAGE_AUTH, ns_bl1u_desc[index].image_id,
181 offset, img_size, 0);
182 CHECK_SMC_RESULT(-EPERM);
183#endif
184 if (image_desc->execute == FWU_EXEC) {
185 INFO("NS_BL1U: Calling EXECUTE SMC\n");
186 ns_bl1u_fwu_smc_call(FWU_SMC_IMAGE_EXECUTE, image_desc->image_id,
187 0, 0, 0);
188 CHECK_SMC_RESULT(0);
189
190#if FWU_BL_TEST
191 /* Check if executing again the same image returns error. */
192 INFO("NS_BL1U: TEST Calling SMC to execute again\n");
193 ns_bl1u_fwu_smc_call(FWU_SMC_IMAGE_EXECUTE,
194 ns_bl1u_desc[index].image_id, 0, 0, 0);
195 CHECK_SMC_RESULT(-EPERM);
196#endif
197 } else {
198 /*
199 * If the image is not executable, its internal state
200 * needs to be reset, unless it is for later consumption
201 * by another CPU (like for the SCP_BL2U firmware).
202 */
203 if (image_desc->image_id != SCP_BL2U_IMAGE_ID) {
204 INFO("NS_BL1U: Calling RESET SMC\n");
205 ns_bl1u_fwu_smc_call(FWU_SMC_IMAGE_RESET,
206 image_desc->image_id,
207 0, 0, 0);
208 CHECK_SMC_RESULT(0);
209 }
210 }
211 }
212
213 /*
214 * Clean and invalidate the caches.
215 * And disable the MMU before jumping to NS_BL2U.
216 */
217 disable_mmu_icache();
218
219 /*
220 * The argument passed to NS_BL2U is not used currently.
221 * But keeping the argument passing mechanism for future use.
222 */
223 ns_bl2u_entrypoint(0);
224
225 panic();
226}