blob: 12568662c2f685298d87a05f063545ea348c4ce7 [file] [log] [blame]
xjb04a4022021-11-25 15:01:52 +08001/*
2 * Copyright (c) 2016 MediaTek Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24#include <app.h>
25#include <assert.h>
26#include <boot_mode.h>
27#include <errno.h>
28#include <libfdt.h>
29#include <kernel/event.h>
30#include <kernel/thread.h>
31#include <kernel/vm.h>
32#include <lib/dl_commands.h>
33#include <lib/mempool.h>
34#include <platform.h>
35#include <platform/mtk_key.h>
36#include <platform/mtk_wdt.h>
37#include <rpmb/include/rpmb_mac.h>
38
39#include "fit.h"
40#include "avb.h"
41
42/* BL33 load and entry point address */
43#define CFG_BL33_LOAD_EP_ADDR (BL33_ADDR)
44#define ERR_ADDR (0xffffffff)
45
46typedef void (*jump32_func_type)(uint32_t addr, uint32_t arg1, uint32_t arg2) __NO_RETURN;
47typedef void (*jump64_func_type)(uint64_t bl31_addr, uint64_t bl33_addr, uint64_t arg1) __NO_RETURN;
48
49struct fit_load_data {
50 char *part_name;
51 char *recovery_part_name;
52 void *buf;
53 u32 boot_mode;
54 ulong kernel_entry;
55 ulong dtb_load;
56 ulong trustedos_entry;
57};
58
59/* global variables, also used in dl_commands.c */
60void *kernel_buf;
61void *tz_buf;
62void *bl33_buf;
63
64#if ARCH_ARM64
65void mtk_sip(uint32_t smc_fid, uint64_t bl31_addr, uint64_t bl33_addr)
66{
67 jump64_func_type jump64_func = (jump64_func_type)bl31_addr;
68 (*jump64_func)(bl31_addr, bl33_addr, 0UL);
69}
70#endif
71
72void prepare_bl2_exit(ulong smc_fid, ulong bl31_addr, ulong bl33_addr, ulong arg1)
73{
74#if ARCH_ARM64
75 /* switch to el3 via smc, and will jump to mtk_sip from smc handler */
76 __asm__ volatile("smc #0\n\t");
77#else
78 jump32_func_type jump32_func = (jump32_func_type)bl31_addr;
79 (*jump32_func)(bl33_addr, 0, 0);
80#endif
81}
82
83static void setup_bl33(uint *bl33, ulong fdt, ulong kernel_ep)
84{
85 bl33[12] = (ulong)fdt;
86 bl33[14] = (unsigned)0;
87 bl33[16] = (unsigned)0;
88 bl33[18] = (unsigned)0;
89 bl33[20] = (ulong)kernel_ep;
90 bl33[21] = (ulong)0;
91 bl33[22] = (unsigned)MACH_TYPE;
92}
93
94static int extract_fdt(void *fdt, int size)
95{
96 int ret = 0;
97
98 /* DTB maximum size is 2MB */
99 ret = fdt_open_into(fdt, fdt, size);
100 if (ret) {
101 dprintf(CRITICAL, "open fdt failed\n");
102 return ret;
103 }
104 ret = fdt_check_header(fdt);
105 if (ret) {
106 dprintf(CRITICAL, "check fdt failed\n");
107 return ret;
108 }
109
110 return ret;
111}
112
113static bool check_uart_enter(void)
114{
115 char c;
116 platform_dgetc(&c, false);
117 return (c == 13);
118}
119
120static bool download_check(void)
121{
122 if (check_fastboot_mode()) {
123 set_clr_fastboot_mode(false);
124 return true;
125 } else {
126 return (check_uart_enter() || check_download_key());
127 }
128}
129
130static bool recovery_check(void)
131{
132 if (check_recovery_mode()) {
133 set_clr_recovery_mode(false);
134 return true;
135 } else
136 return false;
137}
138
139static int fit_load_images(void *fit, struct fit_load_data *fit_data,bool need_verified)
140{
141 int ret;
142
143 /* TODO: decide verify policy with config. */
144 dprintf(CRITICAL, "verify fit conf sig: %s\n", fit_data->part_name);
145 if (need_verified) {
146 ret = fit_conf_verify_sig(NULL, fit);
147 if (ret < 0)
148 return ret;
149 }
150
151 ret = fit_load_image(NULL, "kernel", fit, NULL, NULL,
152 (paddr_t *)&fit_data->kernel_entry, need_verified);
153 if (ret && (ret != -ENOENT)) {
154 dprintf(CRITICAL, "%s load kernel failed\n", fit_data->part_name);
155 return ret;
156 }
157
158 ret = fit_load_image(NULL, "tee", fit, NULL, NULL,
159 (paddr_t *)&fit_data->trustedos_entry, need_verified);
160 if (ret && (ret != -ENOENT)) {
161 dprintf(CRITICAL, "%s load trustedos failed\n", fit_data->part_name);
162 return ret;
163 }
164
165 ret = fit_load_image(NULL, "ramdisk", fit, NULL, NULL, NULL, need_verified);
166 if (ret && (ret != -ENOENT)) {
167 dprintf(CRITICAL, "%s load ramdisk failed\n", fit_data->part_name);
168 return ret;
169 }
170
171 ret = fit_load_image(NULL, "fdt", fit, (addr_t *)&fit_data->dtb_load, NULL,
172 NULL, need_verified);
173 if (ret && (ret != -ENOENT)) {
174 fit_data->dtb_load = ERR_ADDR;
175 dprintf(CRITICAL, "%s load fdt failed\n", fit_data->part_name);
176 return ret;
177 }
178
179 return 0;
180}
181
182
183static int fit_load_thread(void *arg,bool need_veriried)
184{
185 int err;
186 struct fit_load_data *fit_data = (struct fit_load_data *)arg;
187
188 if (fit_data->boot_mode == FASTBOOT_BOOT) {
189 err = fit_load_images(fit_data->buf, fit_data, need_veriried);
190 return err;
191 }
192
193 while (fit_data->boot_mode == NORMAL_BOOT) {
194 err = fit_get_image(fit_data->part_name, &fit_data->buf);
195 if (err)
196 break;
197
198 err = fit_load_images(fit_data->buf, fit_data, need_veriried);
199 if (err)
200 break;
201
202 return 0;
203 }
204
205 dprintf(CRITICAL, "%s try recovery mode !!\n", fit_data->recovery_part_name);
206 // RECOVERY_BOOT
207 err = fit_get_image(fit_data->recovery_part_name, &fit_data->buf);
208 if (err)
209 return err;
210
211 err = fit_load_images(fit_data->buf, fit_data, need_veriried);
212
213 return err;
214}
215
216#define MAX_CMDLINE_LENGTH 2048
217static int cmdlineoverlay(void *boot_dtb, char *cmdline, int len, char *ab_suffix)
218{
219 int chosen_node_offset = 0;
220 int ret = -1;
221 char *new_cmd;
222
223 new_cmd = mempool_alloc(MAX_CMDLINE_LENGTH,MEMPOOL_ANY);
224 memset(new_cmd,0,MAX_CMDLINE_LENGTH);
225
226 ret = extract_fdt(boot_dtb, MAX_DTB_SIZE);
227 if (ret != 0) {
228 dprintf(CRITICAL, "extract_fdt error.\n");
229 return -1;
230 }
231
232 chosen_node_offset = fdt_path_offset(boot_dtb, "/chosen");
233
234 const char *cmdline_read;
235 int length;
236 cmdline_read = fdt_getprop(boot_dtb, chosen_node_offset, "bootargs", &length);
237
238 memcpy(new_cmd,cmdline_read,strlen(cmdline_read));
239 new_cmd[strlen(cmdline_read)] = ' ';
240 memcpy(new_cmd+strlen(cmdline_read)+1,cmdline,strlen(cmdline));
241
242#ifdef AB_OTA_UPDATER
243 new_cmd[strlen(new_cmd)] = ' ';
244 memcpy(new_cmd+strlen(new_cmd),"androidboot.slot=",strlen("androidboot.slot="));
245 memcpy(new_cmd+strlen(new_cmd),ab_suffix+1,1);
246#else
247 //unused ab_suffix;
248#endif
249
250 dprintf(INFO, "new cmdline: %s ,length:%lu\n", new_cmd, strlen(new_cmd));
251
252 ret = fdt_setprop(boot_dtb, chosen_node_offset, "bootargs", new_cmd, strlen(new_cmd) + 1);
253
254 if (ret != 0) {
255 dprintf(CRITICAL, "fdt_setprop error.\n");
256 return -1;
257 }
258
259 ret = fdt_pack(boot_dtb);
260 if (ret != 0) {
261 dprintf(CRITICAL, "fdt_pack error.\n");
262 return -1;
263 }
264
265 return 0;
266}
267
268extern void ext_boot(void);
269static void avbboot_task(const struct app_descriptor *app, void *args)
270{
271 void *fit, *dtbo_buf;
272 struct fit_load_data tz,bootimg;
273 int ret_tz;
274 int ret;
275 u32 boot_mode = NORMAL_BOOT;
276 AvbSlotVerifyResult verify_result;
277 AvbSlotVerifyData *verify_data;
278
279 uint bl33[] = { 0xea000005, /* b BL33_32_ENTRY | ands x5, x0, x0 */
280 0x58000160, /* .word 0x58000160 | ldr x0, _X0 */
281 0x58000181, /* .word 0x58000181 | ldr x1, _X1 */
282 0x580001a2, /* .word 0x580001a2 | ldr x2, _X2 */
283 0x580001c3, /* .word 0x580001c3 | ldr x3, _X3 */
284 0x580001e4, /* .word 0x580001e4 | ldr x4, _X4 */
285 0xd61f0080, /* .word 0xd61f0080 | br x4 */
286 /* BL33_32_ENTRY: | */
287 0xe59f0030, /* ldr r0, _R0 | .word 0xe59f0030 */
288 0xe59f1030, /* ldr r1, _R1 | .word 0xe59f1030 */
289 0xe59f2004, /* ldr r2, _X0 | .word 0xe59f2004 */
290 0xe59ff020, /* ldr pc, _X4 | .word 0xe59ff020 */
291 0x00000000, /* .word 0x00000000 */
292 0x00000000, /* _X0: .word 0x00000000 */
293 0x00000000, /* .word 0x00000000 */
294 0x00000000, /* _X1: .word 0x00000000 */
295 0x00000000, /* .word 0x00000000 */
296 0x00000000, /* _X2: .word 0x00000000 */
297 0x00000000, /* .word 0x00000000 */
298 0x00000000, /* _X3: .word 0x00000000 */
299 0x00000000, /* .word 0x00000000 */
300 0x00000000, /* _X4: .word 0x00000000 */
301 0x00000000, /* _R0: .word 0x00000000 */
302 0x00000000, /* _R1: .word 0x00000000 */
303 0x00000000 /* .word 0x00000000 */
304 };
305
306#if (defined AVB_ENABLE_ANTIROLLBACK) || (defined AVB_ENABLE_DEVICE_STATE_CHANGE)
307 rpmb_init();
308#endif
309
310 /* recovery */
311 if (recovery_check()) {
312 boot_mode = RECOVERY_BOOT;
313 }
314
315 /* fastboot */
316 if (download_check()) {
317 ext_boot();
318 boot_mode = FASTBOOT_BOOT;
319 }
320
321 tz_buf = mempool_alloc(MAX_TEE_DRAM_SIZE, MEMPOOL_ANY);
322 if (!tz_buf) {
323 dprintf(CRITICAL, "alloc buf fail, kernel %p, tz %p\n",
324 kernel_buf, tz_buf);
325 return;
326 }
327
328 tz.part_name = (char *)TZ_PART_NAME;
329 tz.recovery_part_name = (char *)RECOVERY_TZ_PART_NAME;
330 tz.boot_mode = boot_mode;
331 tz.buf = tz_buf;
332
333 ret_tz = fit_load_thread(&tz, true);
334
335 if (ret_tz) {
336 dprintf(CRITICAL, "load tz image failed\n");
337 return;
338 }
339
340 verify_result = android_verified_boot_2_0(&verify_data);
341 if (verify_result == AVB_SLOT_VERIFY_RESULT_OK || is_device_unlocked()) {
342 bootimg.part_name = (char *)BOOT_PART_NAME;
343 fit = get_partition_data(bootimg.part_name, verify_data);
344 ret = fit_load_images(fit, &bootimg, false);
345 if (ret) {
346 dprintf(CRITICAL, "load boot image failed\n");
347 return;
348 }
349
350 if (cmdlineoverlay((void *)bootimg.dtb_load,verify_data->cmdline,strlen(verify_data->cmdline),verify_data->ab_suffix)) {
351 dprintf(CRITICAL, "cmdline overlay fail\n");
352 return;
353 }
354 } else {
355 bootimg.recovery_part_name = (char *)RECOVERY_BOOT_PART_NAME;
356 bootimg.boot_mode = RECOVERY_BOOT;
357 bootimg.buf = mempool_alloc(MAX_KERNEL_SIZE, MEMPOOL_ANY);
358 ret = fit_load_thread(&bootimg, true);
359 if (ret) {
360 dprintf(CRITICAL, "load recovery image failed\n");
361 return;
362 }
363 }
364
365 dtbo_buf = mempool_alloc(MAX_DTBO_SIZE, MEMPOOL_ANY);
366 if (!dtbo_buf) {
367 dprintf(CRITICAL, "alloc dtbo buf fail\n");
368 return;
369 }
370
371 /* check if dtbo is existed */
372 ret = fit_get_image(DTBO_PART_NAME, &dtbo_buf);
373 if (ret == 0) {
374 void *fdt_dtbo;
375 void *fdt_dtb;
376
377 if (bootimg.dtb_load == ERR_ADDR) {
378 dprintf(CRITICAL, "dtbo failed, no dtb\n");
379 return;
380 }
381 fdt_dtb = (void *)bootimg.dtb_load;
382
383 /* extract fdt */
384 ret = extract_fdt(fdt_dtb, MAX_DTB_SIZE);
385 if (ret) {
386 dprintf(CRITICAL, "extract fdt failed\n");
387 return;
388 }
389
390 dprintf(ALWAYS, "[fitboot] do overlay\n");
391 fdt_dtbo = (void *)dtbo_buf;
392 ret = fdt_overlay_apply(fdt_dtb, fdt_dtbo);
393 if (ret) {
394 dprintf(CRITICAL, "fdt merge failed, ret %d\n", ret);
395 return;
396 }
397
398 /* pack fdt */
399 ret = fdt_pack(fdt_dtb);
400 if (ret) {
401 dprintf(CRITICAL, "ft pack failed\n");
402 return;
403 }
404 }
405
406 /* load bl33 for tz to jump*/
407 extern __WEAK paddr_t kvaddr_to_paddr(void *ptr);
408 addr_t fdt_pa = kvaddr_to_paddr?kvaddr_to_paddr((void *)bootimg.dtb_load):bootimg.dtb_load;
409 setup_bl33(bl33, fdt_pa, (uint)(bootimg.kernel_entry));
410 memmove((void *)CFG_BL33_LOAD_EP_ADDR, bl33, sizeof(bl33));
411
412 ulong bl33_pa = CFG_BL33_LOAD_EP_ADDR;
413 ulong smc_fid = 0xc2000000UL; /* only used in ARCH_ARM64 */
414
415#if ARCH_ARM64 && WITH_KERNEL_VM
416 /* 64-bit LK use non identity mapping VA, VA to PA translation needed */
417 bl33_pa = (ulong)kvaddr_to_paddr((void *)CFG_BL33_LOAD_EP_ADDR);
418#endif
419 dprintf(ALWAYS, "LK run time: %lld (us)\n", current_time_hires());
420 dprintf(ALWAYS, "jump to tz %p\n", (void *)tz.kernel_entry);
421 arch_chain_load((void *)prepare_bl2_exit, smc_fid, tz.kernel_entry, bl33_pa, 0UL);
422}
423
424APP_START(avbboot)
425.entry = avbboot_task,
426 .flags = 0,
427 APP_END