blob: 018bbab753fbcde425e9560b77f3a8a566301afc [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glassb6396402014-06-12 07:24:46 -06002/*
3 * (C) Copyright 2000-2009
4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
Simon Glassb6396402014-06-12 07:24:46 -06005 */
6
Simon Glassea51a622014-06-12 07:24:51 -06007#ifndef USE_HOSTCC
Simon Glassb6396402014-06-12 07:24:46 -06008#include <common.h>
Simon Glassea51a622014-06-12 07:24:51 -06009#include <bootstage.h>
Simon Glass51bb3382020-11-05 10:33:48 -070010#include <cli.h>
Simon Glass1eb69ae2019-11-14 12:57:39 -070011#include <cpu_func.h>
Simon Glassc7694dd2019-08-01 09:46:46 -060012#include <env.h>
Simon Glass90268b82014-10-19 21:11:24 -060013#include <errno.h>
Simon Glassb6396402014-06-12 07:24:46 -060014#include <fdt_support.h>
Simon Glass36bf4462019-11-14 12:57:42 -070015#include <irq_func.h>
Simon Glassb6396402014-06-12 07:24:46 -060016#include <lmb.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060017#include <log.h>
Simon Glassb6396402014-06-12 07:24:46 -060018#include <malloc.h>
Joe Hershberger0eb25b62015-03-22 17:08:59 -050019#include <mapmem.h>
Simon Glass90526e92020-05-10 11:39:56 -060020#include <net.h>
21#include <asm/cache.h>
Simon Glass401d1c42020-10-30 21:38:53 -060022#include <asm/global_data.h>
Simon Glassb6396402014-06-12 07:24:46 -060023#include <asm/io.h>
Simon Glassb6386f32020-11-05 10:33:43 -070024#include <linux/sizes.h>
Simon Glassb6396402014-06-12 07:24:46 -060025#if defined(CONFIG_CMD_USB)
26#include <usb.h>
27#endif
Simon Glassea51a622014-06-12 07:24:51 -060028#else
29#include "mkimage.h"
30#endif
Simon Glassb6396402014-06-12 07:24:46 -060031
Simon Glassea51a622014-06-12 07:24:51 -060032#include <command.h>
33#include <bootm.h>
34#include <image.h>
dongqing.li994a05e2023-10-17 09:19:27 +080035#include <version.h>
Simon Glassb6396402014-06-12 07:24:46 -060036
Bo Lv81aadc32024-02-28 20:18:44 +080037#if defined(CONFIG_OF_LIBFDT_OVERLAY) && defined(CONFIG_AMLOGIC_MODIFY)
38#include <dt_table.h>
39#include <image-android-dt.h>
40#endif
41
Simon Glassb6386f32020-11-05 10:33:43 -070042#define MAX_CMDLINE_SIZE SZ_4K
43
Simon Glassb6396402014-06-12 07:24:46 -060044#define IH_INITRD_ARCH IH_ARCH_DEFAULT
45
Simon Glassea51a622014-06-12 07:24:51 -060046#ifndef USE_HOSTCC
47
48DECLARE_GLOBAL_DATA_PTR;
49
Simon Glassd9d7c202022-09-06 20:26:50 -060050struct bootm_headers images; /* pointers to os/initrd/fdt images */
Tom Rini5db28902016-08-12 08:31:15 -040051
Simon Glass09140112020-05-10 11:40:03 -060052static const void *boot_get_kernel(struct cmd_tbl *cmdtp, int flag, int argc,
Simon Glassd9d7c202022-09-06 20:26:50 -060053 char *const argv[], struct bootm_headers *images,
Simon Glassb6396402014-06-12 07:24:46 -060054 ulong *os_data, ulong *os_len);
55
Simon Glass329da482018-05-16 09:42:25 -060056__weak void board_quiesce_devices(void)
57{
58}
59
Simon Glassb6396402014-06-12 07:24:46 -060060#ifdef CONFIG_LMB
Simon Glassd9d7c202022-09-06 20:26:50 -060061static void boot_start_lmb(struct bootm_headers *images)
Simon Glassb6396402014-06-12 07:24:46 -060062{
63 ulong mem_start;
64 phys_size_t mem_size;
65
Simon Glass723806c2017-08-03 12:22:15 -060066 mem_start = env_get_bootm_low();
67 mem_size = env_get_bootm_size();
Simon Glassb6396402014-06-12 07:24:46 -060068
Simon Goldschmidt9cc23232019-01-26 22:13:04 +010069 lmb_init_and_reserve_range(&images->lmb, (phys_addr_t)mem_start,
70 mem_size, NULL);
Simon Glassb6396402014-06-12 07:24:46 -060071}
72#else
73#define lmb_reserve(lmb, base, size)
Simon Glassd9d7c202022-09-06 20:26:50 -060074static inline void boot_start_lmb(struct bootm_headers *images) { }
Simon Glassb6396402014-06-12 07:24:46 -060075#endif
76
Simon Glass09140112020-05-10 11:40:03 -060077static int bootm_start(struct cmd_tbl *cmdtp, int flag, int argc,
78 char *const argv[])
Simon Glassb6396402014-06-12 07:24:46 -060079{
80 memset((void *)&images, 0, sizeof(images));
Simon Glassbfebc8c2017-08-03 12:22:13 -060081 images.verify = env_get_yesno("verify");
Simon Glassb6396402014-06-12 07:24:46 -060082
83 boot_start_lmb(&images);
84
85 bootstage_mark_name(BOOTSTAGE_ID_BOOTM_START, "bootm_start");
86 images.state = BOOTM_STATE_START;
87
88 return 0;
89}
90
Philippe Reynes9d46e632022-03-28 22:57:00 +020091static ulong bootm_data_addr(int argc, char *const argv[])
92{
93 ulong addr;
94
95 if (argc > 0)
96 addr = simple_strtoul(argv[0], NULL, 16);
97 else
98 addr = image_load_addr;
99
100 return addr;
101}
102
103static int bootm_pre_load(struct cmd_tbl *cmdtp, int flag, int argc,
104 char *const argv[])
105{
106 ulong data_addr = bootm_data_addr(argc, argv);
107 int ret = 0;
108
109 if (CONFIG_IS_ENABLED(CMD_BOOTM_PRE_LOAD))
110 ret = image_pre_load(data_addr);
111
112 if (ret)
113 ret = CMD_RET_FAILURE;
114
115 return ret;
116}
117
Simon Glass09140112020-05-10 11:40:03 -0600118static int bootm_find_os(struct cmd_tbl *cmdtp, int flag, int argc,
119 char *const argv[])
Simon Glassb6396402014-06-12 07:24:46 -0600120{
121 const void *os_hdr;
122 bool ep_found = false;
Simon Glass90268b82014-10-19 21:11:24 -0600123 int ret;
Simon Glassb6396402014-06-12 07:24:46 -0600124
125 /* get kernel image header, start address and length */
126 os_hdr = boot_get_kernel(cmdtp, flag, argc, argv,
127 &images, &images.os.image_start, &images.os.image_len);
128 if (images.os.image_len == 0) {
129 puts("ERROR: can't get kernel image!\n");
130 return 1;
131 }
132
133 /* get image parameters */
134 switch (genimg_get_format(os_hdr)) {
Tom Rinic76c93a2019-05-23 07:14:07 -0400135#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)
Simon Glassb6396402014-06-12 07:24:46 -0600136 case IMAGE_FORMAT_LEGACY:
137 images.os.type = image_get_type(os_hdr);
138 images.os.comp = image_get_comp(os_hdr);
139 images.os.os = image_get_os(os_hdr);
140
141 images.os.end = image_get_image_end(os_hdr);
142 images.os.load = image_get_load(os_hdr);
Simon Glass90268b82014-10-19 21:11:24 -0600143 images.os.arch = image_get_arch(os_hdr);
Bo Lv4a465022023-02-28 05:51:47 +0000144#ifdef CONFIG_AMLOGIC_MODIFY
145 if (images.os.arch == IH_ARCH_ARM) {
146 env_set("initrd_high", "0A000000");
147 env_set("fdt_high", "0A000000");
148 }
149#endif
Simon Glassb6396402014-06-12 07:24:46 -0600150 break;
151#endif
Simon Glassbf371b42021-09-25 19:43:20 -0600152#if CONFIG_IS_ENABLED(FIT)
Simon Glassb6396402014-06-12 07:24:46 -0600153 case IMAGE_FORMAT_FIT:
154 if (fit_image_get_type(images.fit_hdr_os,
155 images.fit_noffset_os,
156 &images.os.type)) {
157 puts("Can't get image type!\n");
158 bootstage_error(BOOTSTAGE_ID_FIT_TYPE);
159 return 1;
160 }
161
162 if (fit_image_get_comp(images.fit_hdr_os,
163 images.fit_noffset_os,
164 &images.os.comp)) {
165 puts("Can't get image compression!\n");
166 bootstage_error(BOOTSTAGE_ID_FIT_COMPRESSION);
167 return 1;
168 }
169
170 if (fit_image_get_os(images.fit_hdr_os, images.fit_noffset_os,
171 &images.os.os)) {
172 puts("Can't get image OS!\n");
173 bootstage_error(BOOTSTAGE_ID_FIT_OS);
174 return 1;
175 }
176
Simon Glass90268b82014-10-19 21:11:24 -0600177 if (fit_image_get_arch(images.fit_hdr_os,
178 images.fit_noffset_os,
179 &images.os.arch)) {
180 puts("Can't get image ARCH!\n");
181 return 1;
182 }
183
Simon Glassb6396402014-06-12 07:24:46 -0600184 images.os.end = fit_get_end(images.fit_hdr_os);
185
186 if (fit_image_get_load(images.fit_hdr_os, images.fit_noffset_os,
187 &images.os.load)) {
188 puts("Can't get image load address!\n");
189 bootstage_error(BOOTSTAGE_ID_FIT_LOADADDR);
190 return 1;
191 }
192 break;
193#endif
194#ifdef CONFIG_ANDROID_BOOT_IMAGE
195 case IMAGE_FORMAT_ANDROID:
Bo Lv4a465022023-02-28 05:51:47 +0000196#ifdef CONFIG_AMLOGIC_MODIFY
197 if (image_get_magic((image_header_t *)images.os.image_start) == IH_MAGIC) {
198 #ifdef CONFIG_INITRD_HIGH_ADDR
199 env_set("initrd_high", CONFIG_INITRD_HIGH_ADDR);
200 #else
201 env_set("initrd_high", "0D000000");
202 #endif
203
204 #ifdef CONFIG_FDT_HIGH_ADDR
205 env_set("fdt_high", CONFIG_FDT_HIGH_ADDR);
206 #else
207 env_set("fdt_high", "0D000000");
208 #endif
209
210 images.os.arch = ((image_header_t *)(images.os.image_start))->ih_arch;
211 images.os.image_start += sizeof(image_header_t);
212 }
213 images.os.type = IH_TYPE_KERNEL;
214
215 if (images.os.arch == IH_ARCH_ARM)
216 images.os.comp = image_get_comp(os_hdr + 0x800);
217 else
218 images.os.comp = android_image_get_comp(os_hdr);
219
220 //images.os.comp = android_image_get_comp(os_hdr);
221 images.os.os = IH_OS_LINUX;
222
223 images.os.end = android_image_get_end(os_hdr);
224 images.os.load = android_image_get_kload(os_hdr);
225 if (images.os.load == 0x10008000)
226 images.os.load = 0x1080000;
227 images.ep = images.os.load;
228 ep_found = true;
229#else
Simon Glassb6396402014-06-12 07:24:46 -0600230 images.os.type = IH_TYPE_KERNEL;
Eugeniu Rosca829ceb22019-04-08 17:35:27 +0200231 images.os.comp = android_image_get_kcomp(os_hdr);
Simon Glassb6396402014-06-12 07:24:46 -0600232 images.os.os = IH_OS_LINUX;
Simon Glassb6396402014-06-12 07:24:46 -0600233
234 images.os.end = android_image_get_end(os_hdr);
235 images.os.load = android_image_get_kload(os_hdr);
Ahmad Draidi86f46952014-10-23 20:50:07 +0300236 images.ep = images.os.load;
237 ep_found = true;
Bo Lv4a465022023-02-28 05:51:47 +0000238#endif
Simon Glassb6396402014-06-12 07:24:46 -0600239 break;
240#endif
241 default:
242 puts("ERROR: unknown image format type!\n");
243 return 1;
244 }
245
Simon Glass90268b82014-10-19 21:11:24 -0600246 /* If we have a valid setup.bin, we will use that for entry (x86) */
Simon Glass5bda35c2014-10-10 08:21:57 -0600247 if (images.os.arch == IH_ARCH_I386 ||
248 images.os.arch == IH_ARCH_X86_64) {
Simon Glass90268b82014-10-19 21:11:24 -0600249 ulong len;
250
251 ret = boot_get_setup(&images, IH_ARCH_I386, &images.ep, &len);
252 if (ret < 0 && ret != -ENOENT) {
253 puts("Could not find a valid setup.bin for x86\n");
254 return 1;
255 }
256 /* Kernel entry point is the setup.bin */
257 } else if (images.legacy_hdr_valid) {
Simon Glassb6396402014-06-12 07:24:46 -0600258 images.ep = image_get_ep(&images.legacy_hdr_os_copy);
Simon Glassbf371b42021-09-25 19:43:20 -0600259#if CONFIG_IS_ENABLED(FIT)
Simon Glassb6396402014-06-12 07:24:46 -0600260 } else if (images.fit_uname_os) {
261 int ret;
262
263 ret = fit_image_get_entry(images.fit_hdr_os,
264 images.fit_noffset_os, &images.ep);
265 if (ret) {
266 puts("Can't get entry point property!\n");
267 return 1;
268 }
269#endif
270 } else if (!ep_found) {
271 puts("Could not find kernel entry point!\n");
272 return 1;
273 }
274
275 if (images.os.type == IH_TYPE_KERNEL_NOLOAD) {
Marek Vasut487b5fa2018-06-13 06:13:33 +0200276 if (CONFIG_IS_ENABLED(CMD_BOOTI) &&
277 images.os.arch == IH_ARCH_ARM64) {
278 ulong image_addr;
279 ulong image_size;
280
281 ret = booti_setup(images.os.image_start, &image_addr,
282 &image_size, true);
283 if (ret != 0)
284 return 1;
285
286 images.os.type = IH_TYPE_KERNEL;
287 images.os.load = image_addr;
288 images.ep = image_addr;
289 } else {
290 images.os.load = images.os.image_start;
291 images.ep += images.os.image_start;
292 }
Simon Glassb6396402014-06-12 07:24:46 -0600293 }
294
Simon Glass7a80de42016-02-24 09:14:42 -0700295 images.os.start = map_to_sysmem(os_hdr);
Simon Glassb6396402014-06-12 07:24:46 -0600296
297 return 0;
298}
299
Bo Lv81aadc32024-02-28 20:18:44 +0800300/*
301 * load dtb overlay partition to mem
302*/
303#if defined(CONFIG_OF_LIBFDT_OVERLAY) && defined(CONFIG_AMLOGIC_MODIFY)
304static int read_fdto_partition(void)
305{
306 char cmd[128];
307 void *dtbo_mem_addr = NULL;
308 char dtbo_partition[32] = {0};
309 char *s1;
310 struct dt_table_header hdr;
311
312 //run_command("get_valid_slot;", 0);
313 s1 = env_get("active_slot");
314 if (s1 && (strcmp(s1, "normal") == 0))
315 strcpy(dtbo_partition, "dtbo");
316 else if (s1 && (strcmp(s1, "_a") == 0))
317 strcpy(dtbo_partition, "dtbo_a");
318 else if (s1 && (strcmp(s1, "_b") == 0))
319 strcpy(dtbo_partition, "dtbo_b");
320
321 /*
322 * Though it is really no need to parse the adtimg infos
323 * here, but wasting time to read the whole dtbo image
324 * partition is unacceptable
325 */
326 pr_info("Start read %s partition datas!\n", dtbo_partition);
327 extern int store_read(const char *name, loff_t off, size_t size, void *buf);
328 if (store_read(dtbo_partition, 0,
329 sizeof(struct dt_table_header), &hdr) < 0) {
330 pr_err("Fail to read header of DTBO partition\n");
331 return -1;
332 }
333
334#ifdef CONFIG_CMD_ADTIMG
335 if (!android_dt_check_header((ulong)&hdr)) {
336 printf("DTBO partition header is incorrect\n");
337 return -1;
338 }
339#endif
340
341 dtbo_mem_addr = malloc(fdt32_to_cpu(hdr.total_size));
342 if (!dtbo_mem_addr) {
343 printf("out of memory\n");
344 return -1;
345 } else {
346 if (store_read(dtbo_partition, 0,
347 fdt32_to_cpu(hdr.total_size), dtbo_mem_addr) < 0) {
348 printf("Fail to read DTBO partition\n");
349 free(dtbo_mem_addr);
350 return -1;
351 }
352 else {
353 sprintf(cmd, "0x%p", dtbo_mem_addr);
354 env_set("dtbo_mem_addr",cmd);
355 }
356 }
357
358 return 0;
359}
360
361static int get_fdto_totalsize(u32 *tz)
362{
363#ifdef CONFIG_CMD_ADTIMG
364 unsigned long long dtbo_mem_addr = 0x0;
365#endif
366 int ret;
367
368 ret = read_fdto_partition();
369 if (ret != 0)
370 return ret;
371
372#ifdef CONFIG_CMD_ADTIMG
373 dtbo_mem_addr = simple_strtoul(env_get("dtbo_mem_addr"), NULL, 16);
374 *tz = android_dt_get_totalsize(dtbo_mem_addr);
375#endif
376 return 0;
377}
378
379static int do_fdt_overlay(void)
380{
381 unsigned long long dtbo_mem_addr = 0x0;
382 int dtbo_num = 0;
383 int i;
384 char cmd[128];
385 unsigned long long dtbo_start;
386 char *dtbo_idx = NULL;
387 char idx[32];
388
389 if (!env_get("dtbo_mem_addr")) {
390 pr_err("No valid dtbo image found\n");
391 return -1;
392 }
393
394 dtbo_mem_addr = simple_strtoul(env_get("dtbo_mem_addr"), NULL, 16);
395#ifdef CONFIG_CMD_ADTIMG
396 if (!android_dt_check_header(dtbo_mem_addr)) {
397 pr_err("Error: DTBO image header is incorrect\n");
398 return -1;
399 }
400#endif
401
402 /* android_dt_print_contents(dtbo_mem_addr); */
403 dtbo_num = fdt32_to_cpu((
404 (const struct dt_table_header *)dtbo_mem_addr)->dt_entry_count);
405 pr_info("find %d dtbos\n", dtbo_num);
406
407 dtbo_idx = env_get("androidboot.dtbo_idx");
408 if (!dtbo_idx) {
409 pr_info("No androidboot.dtbo_idx configured\n");
410 pr_info("And no dtbos will be applied\n");
411 return -1;
412 }
413 pr_info("dtbos to be applied: %s\n", dtbo_idx);
414
415 #ifndef CONFIG_CMD_ADTIMG
416 pr_info("Error: No adtimg support found\n");
417 return -1;
418 #endif
419
420 for (i = 0; i < dtbo_num; i++) {
421 memset(idx, 0x00, sizeof(idx));
422 sprintf(idx, "%d", i);
423 if (strstr(dtbo_idx, idx)) {
424 printf("Apply dtbo %d\n", i);
425 sprintf(cmd, "adtimg addr 0x%llx;adtimg get dt --index=%d dtbo_start 0x%llx",
426 dtbo_mem_addr, i, dtbo_mem_addr);
427 run_command(cmd, 0);
428 dtbo_start = simple_strtoul(
429 env_get("dtbo_start"), NULL, 16);
430
431 sprintf(cmd, "fdt apply 0x%llx", dtbo_start);
432 run_command(cmd, 0);
433 }
434 }
435
436 free((void *)dtbo_mem_addr);
437 return 0;
438}
439#endif
440
Karl Apsited52e8572015-05-21 09:52:49 -0400441/**
442 * bootm_find_images - wrapper to find and locate various images
443 * @flag: Ignored Argument
444 * @argc: command argument count
445 * @argv: command argument list
Tero Kristofbde7582020-06-12 15:41:20 +0300446 * @start: OS image start address
447 * @size: OS image size
Karl Apsited52e8572015-05-21 09:52:49 -0400448 *
449 * boot_find_images() will attempt to load an available ramdisk,
450 * flattened device tree, as well as specifically marked
451 * "loadable" images (loadables are FIT only)
452 *
453 * Note: bootm_find_images will skip an image if it is not found
454 *
455 * @return:
456 * 0, if all existing images were loaded correctly
457 * 1, if an image is found but corrupted, or invalid
458 */
Tero Kristofbde7582020-06-12 15:41:20 +0300459int bootm_find_images(int flag, int argc, char *const argv[], ulong start,
460 ulong size)
Simon Glassb6396402014-06-12 07:24:46 -0600461{
462 int ret;
463
Bo Lv81aadc32024-02-28 20:18:44 +0800464#if defined(CONFIG_OF_LIBFDT_OVERLAY) && defined(CONFIG_AMLOGIC_MODIFY)
465 u32 fdto_totalsize = 0;
466#endif
467
Simon Glassb6396402014-06-12 07:24:46 -0600468 /* find ramdisk */
469 ret = boot_get_ramdisk(argc, argv, &images, IH_INITRD_ARCH,
470 &images.rd_start, &images.rd_end);
471 if (ret) {
472 puts("Ramdisk image is corrupt or invalid\n");
473 return 1;
474 }
475
Tero Kristofbde7582020-06-12 15:41:20 +0300476 /* check if ramdisk overlaps OS image */
477 if (images.rd_start && (((ulong)images.rd_start >= start &&
Jaehoon Chungef4f4f12020-10-21 14:17:03 +0900478 (ulong)images.rd_start < start + size) ||
479 ((ulong)images.rd_end > start &&
480 (ulong)images.rd_end <= start + size) ||
481 ((ulong)images.rd_start < start &&
482 (ulong)images.rd_end >= start + size))) {
Tero Kristofbde7582020-06-12 15:41:20 +0300483 printf("ERROR: RD image overlaps OS image (OS=0x%lx..0x%lx)\n",
484 start, start + size);
485 return 1;
486 }
487
Simon Glass0c303f92021-09-25 19:43:21 -0600488#if CONFIG_IS_ENABLED(OF_LIBFDT)
Simon Glassb6396402014-06-12 07:24:46 -0600489 /* find flattened device tree */
490 ret = boot_get_fdt(flag, argc, argv, IH_ARCH_DEFAULT, &images,
491 &images.ft_addr, &images.ft_len);
492 if (ret) {
493 puts("Could not find a valid device tree\n");
494 return 1;
495 }
Tero Kristofbde7582020-06-12 15:41:20 +0300496
497 /* check if FDT overlaps OS image */
498 if (images.ft_addr &&
499 (((ulong)images.ft_addr >= start &&
Pali Rohár5acfdfb2022-08-27 14:48:10 +0200500 (ulong)images.ft_addr < start + size) ||
Tero Kristofbde7582020-06-12 15:41:20 +0300501 ((ulong)images.ft_addr + images.ft_len >= start &&
Pali Rohár5acfdfb2022-08-27 14:48:10 +0200502 (ulong)images.ft_addr + images.ft_len < start + size))) {
Tero Kristofbde7582020-06-12 15:41:20 +0300503 printf("ERROR: FDT image overlaps OS image (OS=0x%lx..0x%lx)\n",
504 start, start + size);
505 return 1;
506 }
507
Simon Goldschmidt596be5f2018-12-17 20:14:42 +0100508 if (CONFIG_IS_ENABLED(CMD_FDT))
509 set_working_fdt_addr(map_to_sysmem(images.ft_addr));
Bo Lv81aadc32024-02-28 20:18:44 +0800510
511#if defined(CONFIG_OF_LIBFDT_OVERLAY) && defined(CONFIG_AMLOGIC_MODIFY)
512 if (get_fdto_totalsize(&fdto_totalsize) == 0)
513 fdt_set_totalsize(images.ft_addr, fdt_get_header(images.ft_addr,
514 totalsize) + fdto_totalsize);
515 images.ft_len = fdt_get_header(images.ft_addr, totalsize);
516 do_fdt_overlay();
517#endif
Simon Glassb6396402014-06-12 07:24:46 -0600518#endif
519
Simon Glassbf371b42021-09-25 19:43:20 -0600520#if CONFIG_IS_ENABLED(FIT)
Simon Glass4ed37ab2021-09-25 07:03:20 -0600521 if (IS_ENABLED(CONFIG_FPGA)) {
522 /* find bitstreams */
523 ret = boot_get_fpga(argc, argv, &images, IH_ARCH_DEFAULT,
524 NULL, NULL);
525 if (ret) {
526 printf("FPGA image is corrupted or invalid\n");
527 return 1;
528 }
Michal Simek62afc602016-05-17 14:03:50 +0200529 }
Michal Simek62afc602016-05-17 14:03:50 +0200530
Karl Apsite84a07db2015-05-21 09:52:48 -0400531 /* find all of the loadables */
532 ret = boot_get_loadable(argc, argv, &images, IH_ARCH_DEFAULT,
533 NULL, NULL);
534 if (ret) {
535 printf("Loadable(s) is corrupt or invalid\n");
536 return 1;
537 }
Karl Apsite84a07db2015-05-21 09:52:48 -0400538#endif
539
Simon Glassb6396402014-06-12 07:24:46 -0600540 return 0;
541}
542
Simon Glass09140112020-05-10 11:40:03 -0600543static int bootm_find_other(struct cmd_tbl *cmdtp, int flag, int argc,
544 char *const argv[])
Simon Glassb6396402014-06-12 07:24:46 -0600545{
546 if (((images.os.type == IH_TYPE_KERNEL) ||
547 (images.os.type == IH_TYPE_KERNEL_NOLOAD) ||
548 (images.os.type == IH_TYPE_MULTI)) &&
549 (images.os.os == IH_OS_LINUX ||
550 images.os.os == IH_OS_VXWORKS))
Tero Kristofbde7582020-06-12 15:41:20 +0300551 return bootm_find_images(flag, argc, argv, 0, 0);
Simon Glassb6396402014-06-12 07:24:46 -0600552
553 return 0;
554}
Simon Glass40e59752014-12-02 13:17:30 -0700555#endif /* USE_HOSTC */
556
Julius Werner20908542019-07-24 19:37:54 -0700557#if !defined(USE_HOSTCC) || defined(CONFIG_FIT_SIGNATURE)
Simon Glass3086c052014-12-02 13:17:37 -0700558/**
559 * handle_decomp_error() - display a decompression error
560 *
561 * This function tries to produce a useful message. In the case where the
562 * uncompressed size is the same as the available space, we can assume that
563 * the image is too large for the buffer.
564 *
565 * @comp_type: Compression type being used (IH_COMP_...)
566 * @uncomp_size: Number of bytes uncompressed
Tom Rinic45568c2022-06-25 19:29:46 -0400567 * @buf_size: Number of bytes the decompresion buffer was
Julius Werner20908542019-07-24 19:37:54 -0700568 * @ret: errno error code received from compression library
Heinrich Schuchardt185f8122022-01-19 18:05:50 +0100569 * Return: Appropriate BOOTM_ERR_ error code
Simon Glass3086c052014-12-02 13:17:37 -0700570 */
Tom Rinic45568c2022-06-25 19:29:46 -0400571static int handle_decomp_error(int comp_type, size_t uncomp_size,
572 size_t buf_size, int ret)
Simon Glass40e59752014-12-02 13:17:30 -0700573{
Simon Glass3086c052014-12-02 13:17:37 -0700574 const char *name = genimg_get_comp_name(comp_type);
575
Julius Werner20908542019-07-24 19:37:54 -0700576 /* ENOSYS means unimplemented compression type, don't reset. */
577 if (ret == -ENOSYS)
578 return BOOTM_ERR_UNIMPLEMENTED;
579
Tom Rinic45568c2022-06-25 19:29:46 -0400580 if (uncomp_size >= buf_size)
Simon Glass3086c052014-12-02 13:17:37 -0700581 printf("Image too large: increase CONFIG_SYS_BOOTM_LEN\n");
Simon Glass40e59752014-12-02 13:17:30 -0700582 else
Simon Glass3086c052014-12-02 13:17:37 -0700583 printf("%s: uncompress error %d\n", name, ret);
584
585 /*
586 * The decompression routines are now safe, so will not write beyond
587 * their bounds. Probably it is not necessary to reset, but maintain
588 * the current behaviour for now.
589 */
590 printf("Must RESET board to recover\n");
Simon Glass40e59752014-12-02 13:17:30 -0700591#ifndef USE_HOSTCC
592 bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE);
593#endif
594
595 return BOOTM_ERR_RESET;
596}
Julius Werner20908542019-07-24 19:37:54 -0700597#endif
Simon Glass2b164f12014-06-12 07:24:52 -0600598
Simon Glassce1400f2014-06-12 07:24:53 -0600599#ifndef USE_HOSTCC
Simon Glassd9d7c202022-09-06 20:26:50 -0600600static int bootm_load_os(struct bootm_headers *images, int boot_progress)
Simon Glass2b164f12014-06-12 07:24:52 -0600601{
Simon Glassda79b2f2022-09-06 20:26:51 -0600602 struct image_info os = images->os;
Simon Glass2b164f12014-06-12 07:24:52 -0600603 ulong load = os.load;
Tom Rinicc955352018-05-01 12:32:37 -0400604 ulong load_end;
Simon Glass2b164f12014-06-12 07:24:52 -0600605 ulong blob_start = os.start;
606 ulong blob_end = os.end;
607 ulong image_start = os.image_start;
608 ulong image_len = os.image_len;
Bryan O'Donoghuebbac9222018-04-15 11:48:17 +0100609 ulong flush_start = ALIGN_DOWN(load, ARCH_DMA_MINALIGN);
Simon Glass2b164f12014-06-12 07:24:52 -0600610 bool no_overlap;
611 void *load_buf, *image_buf;
612 int err;
613
614 load_buf = map_sysmem(load, 0);
615 image_buf = map_sysmem(os.image_start, image_len);
Julius Werner20908542019-07-24 19:37:54 -0700616 err = image_decomp(os.comp, load, os.image_start, os.type,
617 load_buf, image_buf, image_len,
618 CONFIG_SYS_BOOTM_LEN, &load_end);
Simon Glass2b164f12014-06-12 07:24:52 -0600619 if (err) {
Tom Rinic45568c2022-06-25 19:29:46 -0400620 err = handle_decomp_error(os.comp, load_end - load,
621 CONFIG_SYS_BOOTM_LEN, err);
Simon Glass2b164f12014-06-12 07:24:52 -0600622 bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE);
623 return err;
624 }
Bo Lvda8d5b72023-07-31 14:58:21 +0800625
626#ifdef CONFIG_AMLOGIC_MODIFY
Bo Lv77426d62023-08-11 19:05:38 +0800627 extern uint32_t get_rsv_mem_size(void);
628 if (load_end >= IOTRACE_LOAD_ADDR && load < get_rsv_mem_size())
Bo Lvda8d5b72023-07-31 14:58:21 +0800629 printf("[Warning] kernel overlap iotrace, please reset decompress addr\n");
630#endif
631
Heinrich Schuchardt21d39462020-08-30 11:34:12 +0200632 /* We need the decompressed image size in the next steps */
633 images->os.image_len = load_end - load;
Bryan O'Donoghuebbac9222018-04-15 11:48:17 +0100634
Trent Piephob4353b32019-03-27 23:50:09 +0000635 flush_cache(flush_start, ALIGN(load_end, ARCH_DMA_MINALIGN) - flush_start);
Simon Glassb6396402014-06-12 07:24:46 -0600636
Tom Rinicc955352018-05-01 12:32:37 -0400637 debug(" kernel loaded at 0x%08lx, end = 0x%08lx\n", load, load_end);
Simon Glassb6396402014-06-12 07:24:46 -0600638 bootstage_mark(BOOTSTAGE_ID_KERNEL_LOADED);
639
Simon Glass2b164f12014-06-12 07:24:52 -0600640 no_overlap = (os.comp == IH_COMP_NONE && load == image_start);
641
Tom Rinicc955352018-05-01 12:32:37 -0400642 if (!no_overlap && load < blob_end && load_end > blob_start) {
Simon Glassb6396402014-06-12 07:24:46 -0600643 debug("images.os.start = 0x%lX, images.os.end = 0x%lx\n",
644 blob_start, blob_end);
645 debug("images.os.load = 0x%lx, load_end = 0x%lx\n", load,
Tom Rinicc955352018-05-01 12:32:37 -0400646 load_end);
Bo Lv4a465022023-02-28 05:51:47 +0000647#ifndef CONFIG_ANDROID_BOOT_IMAGE
Simon Glassb6396402014-06-12 07:24:46 -0600648 /* Check what type of image this is. */
649 if (images->legacy_hdr_valid) {
650 if (image_get_type(&images->legacy_hdr_os_copy)
651 == IH_TYPE_MULTI)
652 puts("WARNING: legacy format multi component image overwritten\n");
653 return BOOTM_ERR_OVERLAP;
654 } else {
655 puts("ERROR: new format image overwritten - must RESET the board to recover\n");
656 bootstage_error(BOOTSTAGE_ID_OVERWRITTEN);
657 return BOOTM_ERR_RESET;
658 }
Bo Lv4a465022023-02-28 05:51:47 +0000659#endif
Simon Glassb6396402014-06-12 07:24:46 -0600660 }
661
Tom Rinicc955352018-05-01 12:32:37 -0400662 lmb_reserve(&images->lmb, images->os.load, (load_end -
663 images->os.load));
Simon Glassb6396402014-06-12 07:24:46 -0600664 return 0;
665}
666
667/**
668 * bootm_disable_interrupts() - Disable interrupts in preparation for load/boot
669 *
Heinrich Schuchardt185f8122022-01-19 18:05:50 +0100670 * Return: interrupt flag (0 if interrupts were disabled, non-zero if they were
Simon Glassb6396402014-06-12 07:24:46 -0600671 * enabled)
672 */
673ulong bootm_disable_interrupts(void)
674{
675 ulong iflag;
676
677 /*
678 * We have reached the point of no return: we are going to
679 * overwrite all exception vector code, so we cannot easily
680 * recover from any failures any more...
681 */
682 iflag = disable_interrupts();
683#ifdef CONFIG_NETCONSOLE
684 /* Stop the ethernet stack if NetConsole could have left it up */
685 eth_halt();
Bernhard Nortmann4917c062015-09-14 15:29:45 +0200686# ifndef CONFIG_DM_ETH
Simon Glassb6396402014-06-12 07:24:46 -0600687 eth_unregister(eth_get_dev());
Bernhard Nortmann4917c062015-09-14 15:29:45 +0200688# endif
Simon Glassb6396402014-06-12 07:24:46 -0600689#endif
690
691#if defined(CONFIG_CMD_USB)
692 /*
693 * turn off USB to prevent the host controller from writing to the
694 * SDRAM while Linux is booting. This could happen (at least for OHCI
695 * controller), because the HCCA (Host Controller Communication Area)
696 * lies within the SDRAM and the host controller writes continously to
697 * this area (as busmaster!). The HccaFrameNumber is for example
698 * updated every 1 ms within the HCCA structure in SDRAM! For more
699 * details see the OpenHCI specification.
700 */
701 usb_stop();
702#endif
703 return iflag;
704}
705
Simon Glass6cd92b12020-11-05 10:33:42 -0700706#define CONSOLE_ARG "console="
Sean Andersonba9aa402022-05-19 18:26:05 -0400707#define NULL_CONSOLE (CONSOLE_ARG "ttynull")
708#define CONSOLE_ARG_SIZE sizeof(NULL_CONSOLE)
Simon Glassb6396402014-06-12 07:24:46 -0600709
Simon Glassb6386f32020-11-05 10:33:43 -0700710/**
711 * fixup_silent_linux() - Handle silencing the linux boot if required
712 *
713 * This uses the silent_linux envvar to control whether to add/set a "console="
714 * parameter to the command line
715 *
716 * @buf: Buffer containing the string to process
717 * @maxlen: Maximum length of buffer
Heinrich Schuchardt185f8122022-01-19 18:05:50 +0100718 * Return: 0 if OK, -ENOSPC if @maxlen is too small
Simon Glassb6386f32020-11-05 10:33:43 -0700719 */
720static int fixup_silent_linux(char *buf, int maxlen)
Simon Glassb6396402014-06-12 07:24:46 -0600721{
Simon Glassb6396402014-06-12 07:24:46 -0600722 int want_silent;
Simon Glassb6386f32020-11-05 10:33:43 -0700723 char *cmdline;
724 int size;
Simon Glassb6396402014-06-12 07:24:46 -0600725
Simon Glassb6386f32020-11-05 10:33:43 -0700726 /*
727 * Move the input string to the end of buffer. The output string will be
728 * built up at the start.
729 */
730 size = strlen(buf) + 1;
731 if (size * 2 > maxlen)
732 return -ENOSPC;
733 cmdline = buf + maxlen - size;
734 memmove(cmdline, buf, size);
Simon Glassb6396402014-06-12 07:24:46 -0600735 /*
736 * Only fix cmdline when requested. The environment variable can be:
737 *
738 * no - we never fixup
739 * yes - we always fixup
740 * unset - we rely on the console silent flag
741 */
Simon Glassbfebc8c2017-08-03 12:22:13 -0600742 want_silent = env_get_yesno("silent_linux");
Simon Glassb6396402014-06-12 07:24:46 -0600743 if (want_silent == 0)
Simon Glass4ae42642020-11-05 10:33:39 -0700744 return 0;
Simon Glassb6396402014-06-12 07:24:46 -0600745 else if (want_silent == -1 && !(gd->flags & GD_FLG_SILENT))
Simon Glass4ae42642020-11-05 10:33:39 -0700746 return 0;
Simon Glassb6396402014-06-12 07:24:46 -0600747
748 debug("before silent fix-up: %s\n", cmdline);
Simon Glassb6386f32020-11-05 10:33:43 -0700749 if (*cmdline) {
Simon Glassb6396402014-06-12 07:24:46 -0600750 char *start = strstr(cmdline, CONSOLE_ARG);
751
Simon Glassb6386f32020-11-05 10:33:43 -0700752 /* Check space for maximum possible new command line */
753 if (size + CONSOLE_ARG_SIZE > maxlen)
Simon Glass4ae42642020-11-05 10:33:39 -0700754 return -ENOSPC;
Simon Glassb6396402014-06-12 07:24:46 -0600755
756 if (start) {
757 char *end = strchr(start, ' ');
Simon Glass6cd92b12020-11-05 10:33:42 -0700758 int start_bytes;
Simon Glassb6396402014-06-12 07:24:46 -0600759
Sean Andersonba9aa402022-05-19 18:26:05 -0400760 start_bytes = start - cmdline;
Simon Glass6cd92b12020-11-05 10:33:42 -0700761 strncpy(buf, cmdline, start_bytes);
Sean Andersonba9aa402022-05-19 18:26:05 -0400762 strncpy(buf + start_bytes, NULL_CONSOLE, CONSOLE_ARG_SIZE);
Simon Glassb6396402014-06-12 07:24:46 -0600763 if (end)
Sean Andersonba9aa402022-05-19 18:26:05 -0400764 strcpy(buf + start_bytes + CONSOLE_ARG_SIZE - 1, end);
Simon Glassb6396402014-06-12 07:24:46 -0600765 else
Sean Andersonba9aa402022-05-19 18:26:05 -0400766 buf[start_bytes + CONSOLE_ARG_SIZE] = '\0';
Simon Glassb6396402014-06-12 07:24:46 -0600767 } else {
Sean Andersonba9aa402022-05-19 18:26:05 -0400768 sprintf(buf, "%s %s", cmdline, NULL_CONSOLE);
Simon Glassb6396402014-06-12 07:24:46 -0600769 }
Simon Glassb6386f32020-11-05 10:33:43 -0700770 if (buf + strlen(buf) >= cmdline)
771 return -ENOSPC;
Simon Glassb6396402014-06-12 07:24:46 -0600772 } else {
Sean Andersonba9aa402022-05-19 18:26:05 -0400773 if (maxlen < CONSOLE_ARG_SIZE)
Simon Glassb6386f32020-11-05 10:33:43 -0700774 return -ENOSPC;
Sean Andersonba9aa402022-05-19 18:26:05 -0400775 strcpy(buf, NULL_CONSOLE);
Simon Glassb6396402014-06-12 07:24:46 -0600776 }
Simon Glassb6386f32020-11-05 10:33:43 -0700777 debug("after silent fix-up: %s\n", buf);
Simon Glassb6396402014-06-12 07:24:46 -0600778
Simon Glassb6386f32020-11-05 10:33:43 -0700779 return 0;
780}
781
Simon Glass51bb3382020-11-05 10:33:48 -0700782/**
783 * process_subst() - Handle substitution of ${...} fields in the environment
784 *
785 * Handle variable substitution in the provided buffer
786 *
787 * @buf: Buffer containing the string to process
788 * @maxlen: Maximum length of buffer
Heinrich Schuchardt185f8122022-01-19 18:05:50 +0100789 * Return: 0 if OK, -ENOSPC if @maxlen is too small
Simon Glass51bb3382020-11-05 10:33:48 -0700790 */
791static int process_subst(char *buf, int maxlen)
792{
793 char *cmdline;
794 int size;
795 int ret;
796
797 /* Move to end of buffer */
798 size = strlen(buf) + 1;
799 cmdline = buf + maxlen - size;
800 if (buf + size > cmdline)
801 return -ENOSPC;
802 memmove(cmdline, buf, size);
803
804 ret = cli_simple_process_macros(cmdline, buf, cmdline - buf);
805
806 return ret;
807}
808
Simon Glass4448fe82020-11-05 10:33:45 -0700809int bootm_process_cmdline(char *buf, int maxlen, int flags)
810{
811 int ret;
812
813 /* Check config first to enable compiler to eliminate code */
814 if (IS_ENABLED(CONFIG_SILENT_CONSOLE) &&
815 !IS_ENABLED(CONFIG_SILENT_U_BOOT_ONLY) &&
Bo Lvaa183f82023-07-29 13:30:00 +0800816 (flags & BOOTM_CL_SILENT) &&
817 !IS_ENABLED(CONFIG_AMLOGIC_MODIFY)) {
Simon Glass4448fe82020-11-05 10:33:45 -0700818 ret = fixup_silent_linux(buf, maxlen);
819 if (ret)
820 return log_msg_ret("silent", ret);
821 }
Simon Glassa8d69622021-03-15 18:11:23 +1300822 if (IS_ENABLED(CONFIG_BOOTARGS_SUBST) && IS_ENABLED(CONFIG_CMDLINE) &&
823 (flags & BOOTM_CL_SUBST)) {
Simon Glass51bb3382020-11-05 10:33:48 -0700824 ret = process_subst(buf, maxlen);
825 if (ret)
Simon Glass185756e2021-02-06 09:57:35 -0700826 return log_msg_ret("subst", ret);
Simon Glass51bb3382020-11-05 10:33:48 -0700827 }
Simon Glass4448fe82020-11-05 10:33:45 -0700828
829 return 0;
830}
831
Simon Glassb3c01672020-11-05 10:33:44 -0700832int bootm_process_cmdline_env(int flags)
Simon Glassb6386f32020-11-05 10:33:43 -0700833{
834 const int maxlen = MAX_CMDLINE_SIZE;
Simon Glassb3c01672020-11-05 10:33:44 -0700835 bool do_silent;
Simon Glassb6386f32020-11-05 10:33:43 -0700836 const char *env;
837 char *buf;
838 int ret;
839
840 /* First check if any action is needed */
841 do_silent = IS_ENABLED(CONFIG_SILENT_CONSOLE) &&
Simon Glassb3c01672020-11-05 10:33:44 -0700842 !IS_ENABLED(CONFIG_SILENT_U_BOOT_ONLY) && (flags & BOOTM_CL_SILENT);
Simon Glass51bb3382020-11-05 10:33:48 -0700843 if (!do_silent && !IS_ENABLED(CONFIG_BOOTARGS_SUBST))
Simon Glassb6386f32020-11-05 10:33:43 -0700844 return 0;
845
846 env = env_get("bootargs");
847 if (env && strlen(env) >= maxlen)
848 return -E2BIG;
849 buf = malloc(maxlen);
850 if (!buf)
851 return -ENOMEM;
852 if (env)
853 strcpy(buf, env);
854 else
855 *buf = '\0';
Simon Glass4448fe82020-11-05 10:33:45 -0700856 ret = bootm_process_cmdline(buf, maxlen, flags);
Simon Glassb6386f32020-11-05 10:33:43 -0700857 if (!ret) {
858 ret = env_set("bootargs", buf);
859
860 /*
861 * If buf is "" and bootargs does not exist, this will produce
862 * an error trying to delete bootargs. Ignore it
863 */
864 if (ret == -ENOENT)
865 ret = 0;
866 }
Simon Glassb6396402014-06-12 07:24:46 -0600867 free(buf);
Simon Glassb6386f32020-11-05 10:33:43 -0700868 if (ret)
869 return log_msg_ret("env", ret);
Simon Glass4ae42642020-11-05 10:33:39 -0700870
871 return 0;
Simon Glassb6396402014-06-12 07:24:46 -0600872}
Simon Glassb6396402014-06-12 07:24:46 -0600873
874/**
875 * Execute selected states of the bootm command.
876 *
877 * Note the arguments to this state must be the first argument, Any 'bootm'
878 * or sub-command arguments must have already been taken.
879 *
880 * Note that if states contains more than one flag it MUST contain
881 * BOOTM_STATE_START, since this handles and consumes the command line args.
882 *
883 * Also note that aside from boot_os_fn functions and bootm_load_os no other
884 * functions we store the return value of in 'ret' may use a negative return
885 * value, without special handling.
886 *
887 * @param cmdtp Pointer to bootm command table entry
888 * @param flag Command flags (CMD_FLAG_...)
889 * @param argc Number of subcommand arguments (0 = no arguments)
890 * @param argv Arguments
891 * @param states Mask containing states to run (BOOTM_STATE_...)
892 * @param images Image header information
893 * @param boot_progress 1 to show boot progress, 0 to not do this
Heinrich Schuchardt185f8122022-01-19 18:05:50 +0100894 * Return: 0 if ok, something else on error. Some errors will cause this
Simon Glassb6396402014-06-12 07:24:46 -0600895 * function to perform a reboot! If states contains BOOTM_STATE_OS_GO
896 * then the intent is to boot an OS, so this function will not return
897 * unless the image type is standalone.
898 */
Simon Glass09140112020-05-10 11:40:03 -0600899int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc,
Simon Glassd9d7c202022-09-06 20:26:50 -0600900 char *const argv[], int states, struct bootm_headers *images,
Simon Glass09140112020-05-10 11:40:03 -0600901 int boot_progress)
Simon Glassb6396402014-06-12 07:24:46 -0600902{
903 boot_os_fn *boot_fn;
904 ulong iflag = 0;
905 int ret = 0, need_boot_fn;
906
907 images->state |= states;
908
909 /*
910 * Work through the states and see how far we get. We stop on
911 * any error.
912 */
913 if (states & BOOTM_STATE_START)
914 ret = bootm_start(cmdtp, flag, argc, argv);
915
Philippe Reynes9d46e632022-03-28 22:57:00 +0200916 if (!ret && (states & BOOTM_STATE_PRE_LOAD))
917 ret = bootm_pre_load(cmdtp, flag, argc, argv);
918
Simon Glassb6396402014-06-12 07:24:46 -0600919 if (!ret && (states & BOOTM_STATE_FINDOS))
920 ret = bootm_find_os(cmdtp, flag, argc, argv);
921
Zubair Lutfullah Kakakhelba079842016-09-09 09:18:58 +0100922 if (!ret && (states & BOOTM_STATE_FINDOTHER))
Simon Glassb6396402014-06-12 07:24:46 -0600923 ret = bootm_find_other(cmdtp, flag, argc, argv);
Simon Glassb6396402014-06-12 07:24:46 -0600924
dongqing.li994a05e2023-10-17 09:19:27 +0800925#if defined(CONFIG_MDUMP_COMPRESS) || \
926 ((defined CONFIG_SUPPORT_BL33Z) && \
927 (defined CONFIG_FULL_RAMDUMP))
928 extern void check_ramdump(void);
929 check_ramdump();
930#endif
931
Simon Glassb6396402014-06-12 07:24:46 -0600932 /* Load the OS */
933 if (!ret && (states & BOOTM_STATE_LOADOS)) {
Simon Glassb6396402014-06-12 07:24:46 -0600934 iflag = bootm_disable_interrupts();
Tom Rinicc955352018-05-01 12:32:37 -0400935 ret = bootm_load_os(images, 0);
936 if (ret && ret != BOOTM_ERR_OVERLAP)
Simon Glassb6396402014-06-12 07:24:46 -0600937 goto err;
938 else if (ret == BOOTM_ERR_OVERLAP)
939 ret = 0;
Simon Glassb6396402014-06-12 07:24:46 -0600940 }
941
942 /* Relocate the ramdisk */
943#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
944 if (!ret && (states & BOOTM_STATE_RAMDISK)) {
945 ulong rd_len = images->rd_end - images->rd_start;
946
947 ret = boot_ramdisk_high(&images->lmb, images->rd_start,
948 rd_len, &images->initrd_start, &images->initrd_end);
949 if (!ret) {
Simon Glass018f5302017-08-03 12:22:10 -0600950 env_set_hex("initrd_start", images->initrd_start);
951 env_set_hex("initrd_end", images->initrd_end);
Simon Glassb6396402014-06-12 07:24:46 -0600952 }
953 }
954#endif
Simon Glass0c303f92021-09-25 19:43:21 -0600955#if CONFIG_IS_ENABLED(OF_LIBFDT) && defined(CONFIG_LMB)
Simon Glassb6396402014-06-12 07:24:46 -0600956 if (!ret && (states & BOOTM_STATE_FDT)) {
957 boot_fdt_add_mem_rsv_regions(&images->lmb, images->ft_addr);
958 ret = boot_relocate_fdt(&images->lmb, &images->ft_addr,
959 &images->ft_len);
960 }
961#endif
962
Hangyu Lif6740182023-03-27 15:45:23 +0800963#ifdef CONFIG_AMLOGIC_MODIFY
964 /* Check reserved memory region */
965#ifdef CONFIG_CMD_RSVMEM
966 ret = run_command("rsvmem check", 0);
967 if (ret) {
968 puts("rsvmem check failed\n");
969 return ret;
970 }
971#endif
972#endif
973
Simon Glassb6396402014-06-12 07:24:46 -0600974 /* From now on, we need the OS boot function */
975 if (ret)
976 return ret;
977 boot_fn = bootm_os_get_boot_func(images->os.os);
978 need_boot_fn = states & (BOOTM_STATE_OS_CMDLINE |
979 BOOTM_STATE_OS_BD_T | BOOTM_STATE_OS_PREP |
980 BOOTM_STATE_OS_FAKE_GO | BOOTM_STATE_OS_GO);
981 if (boot_fn == NULL && need_boot_fn) {
982 if (iflag)
983 enable_interrupts();
984 printf("ERROR: booting os '%s' (%d) is not supported\n",
985 genimg_get_os_name(images->os.os), images->os.os);
986 bootstage_error(BOOTSTAGE_ID_CHECK_BOOT_OS);
987 return 1;
988 }
989
Hector Palacios19e86492016-07-11 12:34:37 +0200990
Simon Glassb6396402014-06-12 07:24:46 -0600991 /* Call various other states that are not generally used */
992 if (!ret && (states & BOOTM_STATE_OS_CMDLINE))
993 ret = boot_fn(BOOTM_STATE_OS_CMDLINE, argc, argv, images);
994 if (!ret && (states & BOOTM_STATE_OS_BD_T))
995 ret = boot_fn(BOOTM_STATE_OS_BD_T, argc, argv, images);
Hector Palacios19e86492016-07-11 12:34:37 +0200996 if (!ret && (states & BOOTM_STATE_OS_PREP)) {
Simon Glass51bb3382020-11-05 10:33:48 -0700997 ret = bootm_process_cmdline_env(images->os.os == IH_OS_LINUX);
Simon Glassd9477a02020-11-05 10:33:41 -0700998 if (ret) {
999 printf("Cmdline setup failed (err=%d)\n", ret);
1000 ret = CMD_RET_FAILURE;
1001 goto err;
Simon Glass4ae42642020-11-05 10:33:39 -07001002 }
Simon Glassb6396402014-06-12 07:24:46 -06001003 ret = boot_fn(BOOTM_STATE_OS_PREP, argc, argv, images);
Hector Palacios19e86492016-07-11 12:34:37 +02001004 }
Simon Glassb6396402014-06-12 07:24:46 -06001005
1006#ifdef CONFIG_TRACE
1007 /* Pretend to run the OS, then run a user command */
1008 if (!ret && (states & BOOTM_STATE_OS_FAKE_GO)) {
Simon Glass00caae62017-08-03 12:22:12 -06001009 char *cmd_list = env_get("fakegocmd");
Simon Glassb6396402014-06-12 07:24:46 -06001010
1011 ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_FAKE_GO,
1012 images, boot_fn);
1013 if (!ret && cmd_list)
1014 ret = run_command_list(cmd_list, -1, flag);
1015 }
1016#endif
1017
1018 /* Check for unsupported subcommand. */
1019 if (ret) {
Simon Glass13819f02022-10-11 09:47:07 -06001020 printf("subcommand failed (err=%d)\n", ret);
Simon Glassb6396402014-06-12 07:24:46 -06001021 return ret;
1022 }
1023
1024 /* Now run the OS! We hope this doesn't return */
1025 if (!ret && (states & BOOTM_STATE_OS_GO))
1026 ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_GO,
1027 images, boot_fn);
1028
1029 /* Deal with any fallout */
1030err:
1031 if (iflag)
1032 enable_interrupts();
1033
1034 if (ret == BOOTM_ERR_UNIMPLEMENTED)
1035 bootstage_error(BOOTSTAGE_ID_DECOMP_UNIMPL);
1036 else if (ret == BOOTM_ERR_RESET)
1037 do_reset(cmdtp, flag, argc, argv);
1038
1039 return ret;
1040}
1041
Tom Rinic76c93a2019-05-23 07:14:07 -04001042#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)
Simon Glassb6396402014-06-12 07:24:46 -06001043/**
1044 * image_get_kernel - verify legacy format kernel image
1045 * @img_addr: in RAM address of the legacy format image to be verified
1046 * @verify: data CRC verification flag
1047 *
1048 * image_get_kernel() verifies legacy image integrity and returns pointer to
1049 * legacy image header if image verification was completed successfully.
1050 *
1051 * returns:
1052 * pointer to a legacy image header if valid image was found
1053 * otherwise return NULL
1054 */
Simon Glassf3543e62022-09-06 20:26:52 -06001055static struct legacy_img_hdr *image_get_kernel(ulong img_addr, int verify)
Simon Glassb6396402014-06-12 07:24:46 -06001056{
Simon Glassf3543e62022-09-06 20:26:52 -06001057 struct legacy_img_hdr *hdr = (struct legacy_img_hdr *)img_addr;
Simon Glassb6396402014-06-12 07:24:46 -06001058
1059 if (!image_check_magic(hdr)) {
1060 puts("Bad Magic Number\n");
1061 bootstage_error(BOOTSTAGE_ID_CHECK_MAGIC);
1062 return NULL;
1063 }
1064 bootstage_mark(BOOTSTAGE_ID_CHECK_HEADER);
1065
1066 if (!image_check_hcrc(hdr)) {
1067 puts("Bad Header Checksum\n");
1068 bootstage_error(BOOTSTAGE_ID_CHECK_HEADER);
1069 return NULL;
1070 }
1071
1072 bootstage_mark(BOOTSTAGE_ID_CHECK_CHECKSUM);
1073 image_print_contents(hdr);
1074
1075 if (verify) {
1076 puts(" Verifying Checksum ... ");
1077 if (!image_check_dcrc(hdr)) {
1078 printf("Bad Data CRC\n");
1079 bootstage_error(BOOTSTAGE_ID_CHECK_CHECKSUM);
1080 return NULL;
1081 }
1082 puts("OK\n");
1083 }
1084 bootstage_mark(BOOTSTAGE_ID_CHECK_ARCH);
1085
1086 if (!image_check_target_arch(hdr)) {
1087 printf("Unsupported Architecture 0x%x\n", image_get_arch(hdr));
1088 bootstage_error(BOOTSTAGE_ID_CHECK_ARCH);
1089 return NULL;
1090 }
1091 return hdr;
1092}
1093#endif
1094
1095/**
1096 * boot_get_kernel - find kernel image
1097 * @os_data: pointer to a ulong variable, will hold os data start address
1098 * @os_len: pointer to a ulong variable, will hold os data length
1099 *
1100 * boot_get_kernel() tries to find a kernel image, verifies its integrity
1101 * and locates kernel data.
1102 *
1103 * returns:
1104 * pointer to image header if valid image was found, plus kernel start
1105 * address and length, otherwise NULL
1106 */
Simon Glass09140112020-05-10 11:40:03 -06001107static const void *boot_get_kernel(struct cmd_tbl *cmdtp, int flag, int argc,
Simon Glassd9d7c202022-09-06 20:26:50 -06001108 char *const argv[], struct bootm_headers *images,
Simon Glassb6396402014-06-12 07:24:46 -06001109 ulong *os_data, ulong *os_len)
1110{
Tom Rinic76c93a2019-05-23 07:14:07 -04001111#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)
Simon Glassf3543e62022-09-06 20:26:52 -06001112 struct legacy_img_hdr *hdr;
Simon Glassb6396402014-06-12 07:24:46 -06001113#endif
1114 ulong img_addr;
1115 const void *buf;
Simon Glassb6396402014-06-12 07:24:46 -06001116 const char *fit_uname_config = NULL;
1117 const char *fit_uname_kernel = NULL;
Simon Glassbf371b42021-09-25 19:43:20 -06001118#if CONFIG_IS_ENABLED(FIT)
Simon Glassb6396402014-06-12 07:24:46 -06001119 int os_noffset;
1120#endif
1121
Bo Lv4a465022023-02-28 05:51:47 +00001122#ifdef CONFIG_AMLOGIC_MODIFY
1123 char *avb_s;
1124 avb_s = env_get("avb2");
Bo Lva1bffde2023-08-16 21:04:03 +08001125 if (avb_s)
1126 printf("avb2: %s\n", avb_s);
1127 if (avb_s && strcmp(avb_s, "1") != 0) {
Bo Lv4a465022023-02-28 05:51:47 +00001128#ifdef CONFIG_AML_ANTIROLLBACK
1129 boot_img_hdr_t **tmp_img_hdr = (boot_img_hdr_t **)&buf;
1130#endif
1131 }
1132#endif
1133
Bryan Wue6c88a62014-08-15 16:51:39 -07001134 img_addr = genimg_get_kernel_addr_fit(argc < 1 ? NULL : argv[0],
1135 &fit_uname_config,
1136 &fit_uname_kernel);
Simon Glassb6396402014-06-12 07:24:46 -06001137
Philippe Reynes9d46e632022-03-28 22:57:00 +02001138 if (CONFIG_IS_ENABLED(CMD_BOOTM_PRE_LOAD))
1139 img_addr += image_load_offset;
1140
Simon Glassb6396402014-06-12 07:24:46 -06001141 bootstage_mark(BOOTSTAGE_ID_CHECK_MAGIC);
1142
Simon Glassb6396402014-06-12 07:24:46 -06001143 /* check image type, for FIT images get FIT kernel node */
1144 *os_data = *os_len = 0;
1145 buf = map_sysmem(img_addr, 0);
1146 switch (genimg_get_format(buf)) {
Tom Rinic76c93a2019-05-23 07:14:07 -04001147#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)
Simon Glassb6396402014-06-12 07:24:46 -06001148 case IMAGE_FORMAT_LEGACY:
1149 printf("## Booting kernel from Legacy Image at %08lx ...\n",
1150 img_addr);
1151 hdr = image_get_kernel(img_addr, images->verify);
1152 if (!hdr)
1153 return NULL;
1154 bootstage_mark(BOOTSTAGE_ID_CHECK_IMAGETYPE);
1155
1156 /* get os_data and os_len */
1157 switch (image_get_type(hdr)) {
1158 case IH_TYPE_KERNEL:
1159 case IH_TYPE_KERNEL_NOLOAD:
1160 *os_data = image_get_data(hdr);
1161 *os_len = image_get_data_size(hdr);
1162 break;
1163 case IH_TYPE_MULTI:
1164 image_multi_getimg(hdr, 0, os_data, os_len);
1165 break;
1166 case IH_TYPE_STANDALONE:
1167 *os_data = image_get_data(hdr);
1168 *os_len = image_get_data_size(hdr);
1169 break;
1170 default:
1171 printf("Wrong Image Type for %s command\n",
1172 cmdtp->name);
1173 bootstage_error(BOOTSTAGE_ID_CHECK_IMAGETYPE);
1174 return NULL;
1175 }
1176
1177 /*
1178 * copy image header to allow for image overwrites during
1179 * kernel decompression.
1180 */
1181 memmove(&images->legacy_hdr_os_copy, hdr,
Simon Glassf3543e62022-09-06 20:26:52 -06001182 sizeof(struct legacy_img_hdr));
Simon Glassb6396402014-06-12 07:24:46 -06001183
1184 /* save pointer to image header */
1185 images->legacy_hdr_os = hdr;
1186
1187 images->legacy_hdr_valid = 1;
1188 bootstage_mark(BOOTSTAGE_ID_DECOMP_IMAGE);
1189 break;
1190#endif
Simon Glassbf371b42021-09-25 19:43:20 -06001191#if CONFIG_IS_ENABLED(FIT)
Simon Glassb6396402014-06-12 07:24:46 -06001192 case IMAGE_FORMAT_FIT:
Simon Glass126cc862014-06-12 07:24:47 -06001193 os_noffset = fit_image_load(images, img_addr,
Simon Glassb6396402014-06-12 07:24:46 -06001194 &fit_uname_kernel, &fit_uname_config,
1195 IH_ARCH_DEFAULT, IH_TYPE_KERNEL,
1196 BOOTSTAGE_ID_FIT_KERNEL_START,
1197 FIT_LOAD_IGNORED, os_data, os_len);
1198 if (os_noffset < 0)
1199 return NULL;
1200
1201 images->fit_hdr_os = map_sysmem(img_addr, 0);
1202 images->fit_uname_os = fit_uname_kernel;
1203 images->fit_uname_cfg = fit_uname_config;
1204 images->fit_noffset_os = os_noffset;
1205 break;
1206#endif
1207#ifdef CONFIG_ANDROID_BOOT_IMAGE
1208 case IMAGE_FORMAT_ANDROID:
1209 printf("## Booting Android Image at 0x%08lx ...\n", img_addr);
Bo Lv4a465022023-02-28 05:51:47 +00001210
1211#ifndef CONFIG_AMLOGIC_MODIFY
Simon Glass07c0cd72014-06-12 07:24:48 -06001212 if (android_image_get_kernel(buf, images->verify,
Simon Glassb6396402014-06-12 07:24:46 -06001213 os_data, os_len))
1214 return NULL;
Bo Lv4a465022023-02-28 05:51:47 +00001215#else
1216 if (!android_image_need_move(&img_addr, buf))
1217 buf = map_sysmem(img_addr, 0);
1218 else
1219 return NULL;
1220 if (android_image_get_kernel(buf, images->verify,
1221 os_data, os_len))
1222 return NULL;
1223
Bo Lva1bffde2023-08-16 21:04:03 +08001224 if (avb_s && strcmp(avb_s, "1") != 0) {
Bo Lv4a465022023-02-28 05:51:47 +00001225#ifdef CONFIG_AML_ANTIROLLBACK
1226 if (!check_antirollback((*tmp_img_hdr)->kernel_version)) {
1227 *os_len = 0;
1228 return NULL;
1229 }
1230#endif
1231 }
1232#endif
Simon Glassb6396402014-06-12 07:24:46 -06001233 break;
1234#endif
1235 default:
1236 printf("Wrong Image Format for %s command\n", cmdtp->name);
1237 bootstage_error(BOOTSTAGE_ID_FIT_KERNEL_INFO);
1238 return NULL;
1239 }
1240
1241 debug(" kernel data at 0x%08lx, len = 0x%08lx (%ld)\n",
1242 *os_data, *os_len, *os_len);
1243
1244 return buf;
1245}
Heinrich Schuchardtf6c6df72019-01-08 18:13:06 +01001246
1247/**
1248 * switch_to_non_secure_mode() - switch to non-secure mode
1249 *
1250 * This routine is overridden by architectures requiring this feature.
1251 */
1252void __weak switch_to_non_secure_mode(void)
1253{
1254}
1255
Simon Glassce1400f2014-06-12 07:24:53 -06001256#else /* USE_HOSTCC */
1257
Fabrice Fontaine93e07882019-05-03 22:37:05 +02001258#if defined(CONFIG_FIT_SIGNATURE)
Simon Glass8a9d0372020-03-18 11:44:02 -06001259static int bootm_host_load_image(const void *fit, int req_image_type,
1260 int cfg_noffset)
Simon Glassce1400f2014-06-12 07:24:53 -06001261{
1262 const char *fit_uname_config = NULL;
1263 ulong data, len;
Simon Glassd9d7c202022-09-06 20:26:50 -06001264 struct bootm_headers images;
Simon Glassce1400f2014-06-12 07:24:53 -06001265 int noffset;
Tom Rinic45568c2022-06-25 19:29:46 -04001266 ulong load_end, buf_size;
Simon Glassce1400f2014-06-12 07:24:53 -06001267 uint8_t image_type;
Daniel Golle0cd57f22022-08-27 04:14:42 +01001268 uint8_t image_comp;
Simon Glassce1400f2014-06-12 07:24:53 -06001269 void *load_buf;
1270 int ret;
1271
Simon Glass8a9d0372020-03-18 11:44:02 -06001272 fit_uname_config = fdt_get_name(fit, cfg_noffset, NULL);
Simon Glassce1400f2014-06-12 07:24:53 -06001273 memset(&images, '\0', sizeof(images));
1274 images.verify = 1;
1275 noffset = fit_image_load(&images, (ulong)fit,
1276 NULL, &fit_uname_config,
1277 IH_ARCH_DEFAULT, req_image_type, -1,
1278 FIT_LOAD_IGNORED, &data, &len);
1279 if (noffset < 0)
1280 return noffset;
1281 if (fit_image_get_type(fit, noffset, &image_type)) {
1282 puts("Can't get image type!\n");
1283 return -EINVAL;
1284 }
1285
Daniel Golle88de6c52022-08-27 04:17:28 +01001286 if (fit_image_get_comp(fit, noffset, &image_comp))
1287 image_comp = IH_COMP_NONE;
Simon Glassce1400f2014-06-12 07:24:53 -06001288
1289 /* Allow the image to expand by a factor of 4, should be safe */
Tom Rinic45568c2022-06-25 19:29:46 -04001290 buf_size = (1 << 20) + len * 4;
1291 load_buf = malloc(buf_size);
Daniel Golle0cd57f22022-08-27 04:14:42 +01001292 ret = image_decomp(image_comp, 0, data, image_type, load_buf,
Tom Rinic45568c2022-06-25 19:29:46 -04001293 (void *)data, len, buf_size, &load_end);
Simon Glassce1400f2014-06-12 07:24:53 -06001294 free(load_buf);
Simon Glass081cc192014-12-02 13:17:33 -07001295
Julius Werner20908542019-07-24 19:37:54 -07001296 if (ret) {
Daniel Golle0cd57f22022-08-27 04:14:42 +01001297 ret = handle_decomp_error(image_comp, load_end - 0, buf_size, ret);
Julius Werner20908542019-07-24 19:37:54 -07001298 if (ret != BOOTM_ERR_UNIMPLEMENTED)
1299 return ret;
1300 }
Simon Glassce1400f2014-06-12 07:24:53 -06001301
1302 return 0;
1303}
1304
1305int bootm_host_load_images(const void *fit, int cfg_noffset)
1306{
1307 static uint8_t image_types[] = {
1308 IH_TYPE_KERNEL,
1309 IH_TYPE_FLATDT,
1310 IH_TYPE_RAMDISK,
1311 };
1312 int err = 0;
1313 int i;
1314
1315 for (i = 0; i < ARRAY_SIZE(image_types); i++) {
1316 int ret;
1317
Simon Glass8a9d0372020-03-18 11:44:02 -06001318 ret = bootm_host_load_image(fit, image_types[i], cfg_noffset);
Simon Glassce1400f2014-06-12 07:24:53 -06001319 if (!err && ret && ret != -ENOENT)
1320 err = ret;
1321 }
1322
1323 /* Return the first error we found */
1324 return err;
1325}
Fabrice Fontaine93e07882019-05-03 22:37:05 +02001326#endif
Simon Glassea51a622014-06-12 07:24:51 -06001327
1328#endif /* ndef USE_HOSTCC */