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