blob: ff585fe3dd66e7b638a4d3f95471be50d9a6a228 [file] [log] [blame]
developer72bccc12022-06-26 21:50:32 +08001/*
2 * Copyright (c) 2022, Mediatek Inc. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
8#include <errno.h>
9#include <inttypes.h>
10#include <stdint.h>
11#include <common/debug.h>
12#include <common/runtime_svc.h>
13#include <lib/el3_runtime/context_mgmt.h>
14
15/* Vendors headers */
16#include <cold_boot.h>
17#include <lib/mtk_init/mtk_init.h>
18#include <mtk_sip_svc.h>
19
20static struct kernel_info k_info;
21static entry_point_info_t bl32_image_ep_info;
22static entry_point_info_t bl33_image_ep_info;
23static bool el1_is_2nd_bootloader = true;
24static struct atf_arg_t atfarg;
25
26static int init_mtk_bl32_arg(void)
27{
28 struct mtk_bl_param_t *p_mtk_bl_param;
29 struct atf_arg_t *p_atfarg;
30
31 p_mtk_bl_param = (struct mtk_bl_param_t *) get_mtk_bl31_fw_config(BOOT_ARG_FROM_BL2);
32 if (p_mtk_bl_param == NULL) {
33 ERROR("p_mtk_bl_param is NULL!\n");
34 return -1;
35 }
36 p_atfarg = (struct atf_arg_t *)p_mtk_bl_param->atf_arg_addr;
37 if (p_atfarg == NULL) {
38 ERROR("bl32 argument is NULL!\n");
39 return -1;
40 }
41 memcpy((void *)&atfarg, (void *)p_atfarg, sizeof(struct atf_arg_t));
42 return 0;
43}
44MTK_EARLY_PLAT_INIT(init_mtk_bl32_arg);
45
46static void save_kernel_info(uint64_t pc, uint64_t r0, uint64_t r1, uint64_t k32_64)
47{
48 k_info.k32_64 = k32_64;
49 k_info.pc = pc;
50
51 if (k32_64 == LINUX_KERNEL_32) {
52 /* for 32 bits kernel */
53 k_info.r0 = 0;
54 /* machtype */
55 k_info.r1 = r0;
56 /* tags */
57 k_info.r2 = r1;
58 } else {
59 /* for 64 bits kernel */
60 k_info.r0 = r0;
61 k_info.r1 = r1;
62 }
63}
64
65static uint32_t plat_get_spsr_for_bl32_64_entry(void)
66{
67 return SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
68}
69
70#if MTK_BL33_IS_64BIT
71static uint32_t plat_get_spsr_for_bl33_entry(void)
72{
73 uint32_t spsr;
74 uint32_t mode;
75
76 mode = MODE_EL1;
77 spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
78 return spsr;
79}
80#else
81static uint32_t plat_get_spsr_for_bl33_entry(void)
82{
83 unsigned int mode;
84 uint32_t spsr;
85 unsigned int ee;
86 unsigned long daif;
87
88 INFO("Secondary bootloader is AArch32\n");
89 mode = MODE32_svc;
90 ee = 0;
91 /*
92 * TODO: Choose async. exception bits if HYP mode is not
93 * implemented according to the values of SCR.{AW, FW} bits
94 */
95 daif = DAIF_ABT_BIT | DAIF_IRQ_BIT | DAIF_FIQ_BIT;
96
97 spsr = SPSR_MODE32(mode, 0, ee, daif);
98 return spsr;
99}
100#endif
101
102static void populate_bl32_image_ep(entry_point_info_t *bl32_ep_instance,
103 struct mtk_bl_param_t *p_mtk_bl_param)
104{
105 entry_point_info_t *populated_ep_bl32 = bl32_ep_instance;
106
107 if (p_mtk_bl_param == NULL) {
108 ERROR("p_mtk_bl_param is NULL!\n");
109 panic();
110 }
111 SET_SECURITY_STATE(bl32_ep_instance->h.attr, SECURE);
112 SET_PARAM_HEAD(populated_ep_bl32,
113 PARAM_EP,
114 VERSION_1,
115 populated_ep_bl32->h.attr);
116 populated_ep_bl32->pc = atfarg.tee_entry;
117 populated_ep_bl32->spsr = plat_get_spsr_for_bl32_64_entry();
118}
119
120static void populate_bl33_image_ep(entry_point_info_t *bl33_ep_instance,
121 struct mtk_bl_param_t *p_mtk_bl_param)
122{
123 entry_point_info_t *populated_ep_bl33 = bl33_ep_instance;
124
125 if (p_mtk_bl_param == NULL) {
126 ERROR("p_mtk_bl_param is NULL!\n");
127 panic();
128 }
129 SET_SECURITY_STATE(bl33_ep_instance->h.attr, NON_SECURE);
130 SET_PARAM_HEAD(populated_ep_bl33,
131 PARAM_EP,
132 VERSION_1,
133 populated_ep_bl33->h.attr);
134 populated_ep_bl33->pc = p_mtk_bl_param->bl33_start_addr;
135 /* standardize 2nd bootloader input argument */
136 populated_ep_bl33->args.arg0 = p_mtk_bl_param->bootarg_loc;
137 /* compatible to old GZ version */
138 populated_ep_bl33->args.arg4 = p_mtk_bl_param->bootarg_loc;
139 populated_ep_bl33->args.arg5 = p_mtk_bl_param->bootarg_size;
140 populated_ep_bl33->spsr = plat_get_spsr_for_bl33_entry();
141}
142
143static int populate_bl_images_ep(struct mtk_bl_param_t *p_mtk_bl_param)
144{
145 /*
146 * Tell BL31 where the non-trusted software image
147 * is located and the entry state information
148 */
149 populate_bl33_image_ep(&bl33_image_ep_info, p_mtk_bl_param);
150 populate_bl32_image_ep(&bl32_image_ep_info, p_mtk_bl_param);
151 return 0;
152}
153
154static int populate_bl_images_ep_init(void)
155{
156 return populate_bl_images_ep(get_mtk_bl31_fw_config(BOOT_ARG_FROM_BL2));
157}
158MTK_PLAT_SETUP_0_INIT(populate_bl_images_ep_init);
159
160static entry_point_info_t *bl31_plat_get_next_kernel64_ep_info(void)
161{
162 entry_point_info_t *next_image_info;
163 unsigned long el_status;
164 unsigned int mode;
165
166 el_status = 0;
167 mode = 0;
168
169 /* Kernel image is always non-secured */
170 next_image_info = &bl33_image_ep_info;
171
172 /* Figure out what mode we enter the non-secure world in */
173 el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
174 el_status &= ID_AA64PFR0_ELX_MASK;
175
176 INFO("Kernel_EL %d\n", el_status?2:1);
177 if (el_status) {
178 mode = MODE_EL2;
179 } else {
180 mode = MODE_EL1;
181 }
182 INFO("Kernel is 64Bit\n");
183 next_image_info->spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
184 next_image_info->pc = k_info.pc;
185 next_image_info->args.arg0 = k_info.r0;
186 next_image_info->args.arg1 = k_info.r1;
187
188 INFO("pc=0x%lx, r0=0x%" PRIx64 ", r1=0x%" PRIx64 "\n",
189 next_image_info->pc,
190 next_image_info->args.arg0,
191 next_image_info->args.arg1);
192
193 SET_SECURITY_STATE(next_image_info->h.attr, NON_SECURE);
194
195 /* None of the images on this platform can have 0x0 as the entrypoint */
196 if (next_image_info->pc) {
197 return next_image_info;
198 }
199
200 return NULL;
201}
202
203static entry_point_info_t *bl31_plat_get_next_kernel32_ep_info(void)
204{
205 entry_point_info_t *next_image_info;
206 unsigned int mode;
207
208 mode = 0;
209
210 /* Kernel image is always non-secured */
211 next_image_info = &bl33_image_ep_info;
212
213 /* Figure out what mode we enter the non-secure world in */
214 mode = MODE32_hyp;
215 /*
216 * TODO: Consider the possibility of specifying the SPSR in
217 * the FIP ToC and allowing the platform to have a say as
218 * well.
219 */
220
221 INFO("Kernel is 32Bit\n");
222 next_image_info->spsr = SPSR_MODE32(mode, SPSR_T_ARM, SPSR_E_LITTLE,
223 (DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT));
224 next_image_info->pc = k_info.pc;
225 next_image_info->args.arg0 = k_info.r0;
226 next_image_info->args.arg1 = k_info.r1;
227 next_image_info->args.arg2 = k_info.r2;
228
229 INFO("pc=0x%lx, r0=0x%" PRIx64 ", r1=0x%" PRIx64 ", r2=0x%" PRIx64 "\n",
230 next_image_info->pc,
231 next_image_info->args.arg0,
232 next_image_info->args.arg1,
233 next_image_info->args.arg2);
234
235 SET_SECURITY_STATE(next_image_info->h.attr, NON_SECURE);
236
237 /* None of the images on this platform can have 0x0 as the entrypoint */
238 if (next_image_info->pc) {
239 return next_image_info;
240 }
241
242 return NULL;
243}
244
245static void bl31_prepare_kernel_entry(uint64_t k32_64)
246{
247 entry_point_info_t *next_image_info = NULL;
248 uint32_t image_type;
249
250 /* Determine which image to execute next */
251 image_type = NON_SECURE; /* bl31_get_next_image_type(); */
252
253 /* Leave 2nd bootloader then jump to kernel */
254 el1_is_2nd_bootloader = false;
255
256 /* Program EL3 registers to enable entry into the next EL */
257 if (k32_64 == LINUX_KERNEL_32) {
258 next_image_info = bl31_plat_get_next_kernel32_ep_info();
259 } else {
260 next_image_info = bl31_plat_get_next_kernel64_ep_info();
261 }
262
263 assert(next_image_info);
264 assert(image_type == GET_SECURITY_STATE(next_image_info->h.attr));
265
266 INFO("BL31: Preparing for EL3 exit to %s world, Kernel\n",
267 (image_type == SECURE) ? "secure" : "normal");
268 INFO("BL31: Next image address = 0x%" PRIx64 "\n",
269 next_image_info->pc);
270 INFO("BL31: Next image spsr = 0x%x\n", next_image_info->spsr);
271 cm_init_my_context(next_image_info);
272 cm_prepare_el3_exit(image_type);
273}
274
275bool is_el1_2nd_bootloader(void)
276{
277 return el1_is_2nd_bootloader;
278}
279
280/*******************************************************************************
281 * Return a pointer to the 'entry_point_info' structure of the next image for
282 * the security state specified. BL33 corresponds to the non-secure image type
283 * while BL32 corresponds to the secure image type. A NULL pointer is returned
284 * if the image does not exist.
285 ******************************************************************************/
286entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
287{
288 entry_point_info_t *next_image_info;
289
290 next_image_info = (type == NON_SECURE) ? &bl33_image_ep_info : &bl32_image_ep_info;
291
292 /* None of the images on this platform can have 0x0 as the entrypoint */
293 if (next_image_info->pc) {
294 return next_image_info;
295 }
296 return NULL;
297}
298
299u_register_t boot_to_kernel(u_register_t x1,
300 u_register_t x2,
301 u_register_t x3,
302 u_register_t x4,
303 void *handle,
304 struct smccc_res *smccc_ret)
305{
306 static uint8_t kernel_boot_once_flag;
307
308 /* only support in booting flow */
309 if (kernel_boot_once_flag == 0) {
310 kernel_boot_once_flag = 1;
311
312 INFO("save kernel info\n");
313 save_kernel_info(x1, x2, x3, x4);
314 bl31_prepare_kernel_entry(x4);
315 INFO("el3_exit\n");
316 /*
317 * FIXME: no better way so far to prevent from
318 * SiP root handler wipe x0~x3 if not assign smccc_ret
319 * return register
320 */
321 smccc_ret->a1 = x3;
322
323 mtk_init_one_level(MTK_INIT_LVL_BL33_DEFER);
324
325#if MTK_CONSOLE_RUNTIME_DISABLE
326 INFO("Turn off BL31 console\n");
327 mtk_console_core_end();
328#endif
329
330 /* Re-assign as x0 register entering Linux kernel */
331 return x2;
332 }
333 return 0;
334}
335/* Register SiP SMC service */
336DECLARE_SMC_HANDLER(MTK_SIP_KERNEL_BOOT, boot_to_kernel);