blob: ec8902e41f3a92cac19861974b90c2a93fa4f2f8 [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
Bo Lvcc445512024-03-21 13:48:45 +0800197 #ifdef CONFIG_MODIFY_INITRD_HIGH
198 env_set("initrd_high", "0D000000");
199 #endif
Bo Lv4a465022023-02-28 05:51:47 +0000200 if (image_get_magic((image_header_t *)images.os.image_start) == IH_MAGIC) {
201 #ifdef CONFIG_INITRD_HIGH_ADDR
202 env_set("initrd_high", CONFIG_INITRD_HIGH_ADDR);
203 #else
204 env_set("initrd_high", "0D000000");
205 #endif
206
207 #ifdef CONFIG_FDT_HIGH_ADDR
208 env_set("fdt_high", CONFIG_FDT_HIGH_ADDR);
209 #else
210 env_set("fdt_high", "0D000000");
211 #endif
212
213 images.os.arch = ((image_header_t *)(images.os.image_start))->ih_arch;
214 images.os.image_start += sizeof(image_header_t);
215 }
216 images.os.type = IH_TYPE_KERNEL;
217
218 if (images.os.arch == IH_ARCH_ARM)
219 images.os.comp = image_get_comp(os_hdr + 0x800);
220 else
221 images.os.comp = android_image_get_comp(os_hdr);
222
223 //images.os.comp = android_image_get_comp(os_hdr);
224 images.os.os = IH_OS_LINUX;
225
226 images.os.end = android_image_get_end(os_hdr);
227 images.os.load = android_image_get_kload(os_hdr);
228 if (images.os.load == 0x10008000)
229 images.os.load = 0x1080000;
230 images.ep = images.os.load;
231 ep_found = true;
232#else
Simon Glassb6396402014-06-12 07:24:46 -0600233 images.os.type = IH_TYPE_KERNEL;
Eugeniu Rosca829ceb22019-04-08 17:35:27 +0200234 images.os.comp = android_image_get_kcomp(os_hdr);
Simon Glassb6396402014-06-12 07:24:46 -0600235 images.os.os = IH_OS_LINUX;
Simon Glassb6396402014-06-12 07:24:46 -0600236
237 images.os.end = android_image_get_end(os_hdr);
238 images.os.load = android_image_get_kload(os_hdr);
Ahmad Draidi86f46952014-10-23 20:50:07 +0300239 images.ep = images.os.load;
240 ep_found = true;
Bo Lv4a465022023-02-28 05:51:47 +0000241#endif
Simon Glassb6396402014-06-12 07:24:46 -0600242 break;
243#endif
244 default:
245 puts("ERROR: unknown image format type!\n");
246 return 1;
247 }
248
Simon Glass90268b82014-10-19 21:11:24 -0600249 /* If we have a valid setup.bin, we will use that for entry (x86) */
Simon Glass5bda35c2014-10-10 08:21:57 -0600250 if (images.os.arch == IH_ARCH_I386 ||
251 images.os.arch == IH_ARCH_X86_64) {
Simon Glass90268b82014-10-19 21:11:24 -0600252 ulong len;
253
254 ret = boot_get_setup(&images, IH_ARCH_I386, &images.ep, &len);
255 if (ret < 0 && ret != -ENOENT) {
256 puts("Could not find a valid setup.bin for x86\n");
257 return 1;
258 }
259 /* Kernel entry point is the setup.bin */
260 } else if (images.legacy_hdr_valid) {
Simon Glassb6396402014-06-12 07:24:46 -0600261 images.ep = image_get_ep(&images.legacy_hdr_os_copy);
Simon Glassbf371b42021-09-25 19:43:20 -0600262#if CONFIG_IS_ENABLED(FIT)
Simon Glassb6396402014-06-12 07:24:46 -0600263 } else if (images.fit_uname_os) {
264 int ret;
265
266 ret = fit_image_get_entry(images.fit_hdr_os,
267 images.fit_noffset_os, &images.ep);
268 if (ret) {
269 puts("Can't get entry point property!\n");
270 return 1;
271 }
272#endif
273 } else if (!ep_found) {
274 puts("Could not find kernel entry point!\n");
275 return 1;
276 }
277
278 if (images.os.type == IH_TYPE_KERNEL_NOLOAD) {
Marek Vasut487b5fa2018-06-13 06:13:33 +0200279 if (CONFIG_IS_ENABLED(CMD_BOOTI) &&
280 images.os.arch == IH_ARCH_ARM64) {
281 ulong image_addr;
282 ulong image_size;
283
284 ret = booti_setup(images.os.image_start, &image_addr,
285 &image_size, true);
286 if (ret != 0)
287 return 1;
288
289 images.os.type = IH_TYPE_KERNEL;
290 images.os.load = image_addr;
291 images.ep = image_addr;
292 } else {
293 images.os.load = images.os.image_start;
294 images.ep += images.os.image_start;
295 }
Simon Glassb6396402014-06-12 07:24:46 -0600296 }
297
Simon Glass7a80de42016-02-24 09:14:42 -0700298 images.os.start = map_to_sysmem(os_hdr);
Simon Glassb6396402014-06-12 07:24:46 -0600299
300 return 0;
301}
302
Bo Lv81aadc32024-02-28 20:18:44 +0800303/*
304 * load dtb overlay partition to mem
305*/
306#if defined(CONFIG_OF_LIBFDT_OVERLAY) && defined(CONFIG_AMLOGIC_MODIFY)
307static int read_fdto_partition(void)
308{
309 char cmd[128];
310 void *dtbo_mem_addr = NULL;
311 char dtbo_partition[32] = {0};
312 char *s1;
313 struct dt_table_header hdr;
314
315 //run_command("get_valid_slot;", 0);
316 s1 = env_get("active_slot");
317 if (s1 && (strcmp(s1, "normal") == 0))
318 strcpy(dtbo_partition, "dtbo");
319 else if (s1 && (strcmp(s1, "_a") == 0))
320 strcpy(dtbo_partition, "dtbo_a");
321 else if (s1 && (strcmp(s1, "_b") == 0))
322 strcpy(dtbo_partition, "dtbo_b");
323
324 /*
325 * Though it is really no need to parse the adtimg infos
326 * here, but wasting time to read the whole dtbo image
327 * partition is unacceptable
328 */
329 pr_info("Start read %s partition datas!\n", dtbo_partition);
330 extern int store_read(const char *name, loff_t off, size_t size, void *buf);
331 if (store_read(dtbo_partition, 0,
332 sizeof(struct dt_table_header), &hdr) < 0) {
333 pr_err("Fail to read header of DTBO partition\n");
334 return -1;
335 }
336
337#ifdef CONFIG_CMD_ADTIMG
338 if (!android_dt_check_header((ulong)&hdr)) {
339 printf("DTBO partition header is incorrect\n");
340 return -1;
341 }
342#endif
343
344 dtbo_mem_addr = malloc(fdt32_to_cpu(hdr.total_size));
345 if (!dtbo_mem_addr) {
346 printf("out of memory\n");
347 return -1;
348 } else {
349 if (store_read(dtbo_partition, 0,
350 fdt32_to_cpu(hdr.total_size), dtbo_mem_addr) < 0) {
351 printf("Fail to read DTBO partition\n");
352 free(dtbo_mem_addr);
353 return -1;
354 }
355 else {
356 sprintf(cmd, "0x%p", dtbo_mem_addr);
357 env_set("dtbo_mem_addr",cmd);
358 }
359 }
360
361 return 0;
362}
363
364static int get_fdto_totalsize(u32 *tz)
365{
366#ifdef CONFIG_CMD_ADTIMG
367 unsigned long long dtbo_mem_addr = 0x0;
368#endif
369 int ret;
370
371 ret = read_fdto_partition();
372 if (ret != 0)
373 return ret;
374
375#ifdef CONFIG_CMD_ADTIMG
376 dtbo_mem_addr = simple_strtoul(env_get("dtbo_mem_addr"), NULL, 16);
377 *tz = android_dt_get_totalsize(dtbo_mem_addr);
378#endif
379 return 0;
380}
381
382static int do_fdt_overlay(void)
383{
384 unsigned long long dtbo_mem_addr = 0x0;
385 int dtbo_num = 0;
386 int i;
387 char cmd[128];
388 unsigned long long dtbo_start;
389 char *dtbo_idx = NULL;
390 char idx[32];
391
392 if (!env_get("dtbo_mem_addr")) {
393 pr_err("No valid dtbo image found\n");
394 return -1;
395 }
396
397 dtbo_mem_addr = simple_strtoul(env_get("dtbo_mem_addr"), NULL, 16);
398#ifdef CONFIG_CMD_ADTIMG
399 if (!android_dt_check_header(dtbo_mem_addr)) {
400 pr_err("Error: DTBO image header is incorrect\n");
401 return -1;
402 }
403#endif
404
405 /* android_dt_print_contents(dtbo_mem_addr); */
406 dtbo_num = fdt32_to_cpu((
407 (const struct dt_table_header *)dtbo_mem_addr)->dt_entry_count);
408 pr_info("find %d dtbos\n", dtbo_num);
409
410 dtbo_idx = env_get("androidboot.dtbo_idx");
411 if (!dtbo_idx) {
412 pr_info("No androidboot.dtbo_idx configured\n");
413 pr_info("And no dtbos will be applied\n");
414 return -1;
415 }
416 pr_info("dtbos to be applied: %s\n", dtbo_idx);
417
418 #ifndef CONFIG_CMD_ADTIMG
419 pr_info("Error: No adtimg support found\n");
420 return -1;
421 #endif
422
423 for (i = 0; i < dtbo_num; i++) {
424 memset(idx, 0x00, sizeof(idx));
425 sprintf(idx, "%d", i);
426 if (strstr(dtbo_idx, idx)) {
427 printf("Apply dtbo %d\n", i);
428 sprintf(cmd, "adtimg addr 0x%llx;adtimg get dt --index=%d dtbo_start 0x%llx",
429 dtbo_mem_addr, i, dtbo_mem_addr);
430 run_command(cmd, 0);
431 dtbo_start = simple_strtoul(
432 env_get("dtbo_start"), NULL, 16);
433
434 sprintf(cmd, "fdt apply 0x%llx", dtbo_start);
435 run_command(cmd, 0);
436 }
437 }
438
439 free((void *)dtbo_mem_addr);
440 return 0;
441}
442#endif
443
Karl Apsited52e8572015-05-21 09:52:49 -0400444/**
445 * bootm_find_images - wrapper to find and locate various images
446 * @flag: Ignored Argument
447 * @argc: command argument count
448 * @argv: command argument list
Tero Kristofbde7582020-06-12 15:41:20 +0300449 * @start: OS image start address
450 * @size: OS image size
Karl Apsited52e8572015-05-21 09:52:49 -0400451 *
452 * boot_find_images() will attempt to load an available ramdisk,
453 * flattened device tree, as well as specifically marked
454 * "loadable" images (loadables are FIT only)
455 *
456 * Note: bootm_find_images will skip an image if it is not found
457 *
458 * @return:
459 * 0, if all existing images were loaded correctly
460 * 1, if an image is found but corrupted, or invalid
461 */
Tero Kristofbde7582020-06-12 15:41:20 +0300462int bootm_find_images(int flag, int argc, char *const argv[], ulong start,
463 ulong size)
Simon Glassb6396402014-06-12 07:24:46 -0600464{
465 int ret;
466
Bo Lv81aadc32024-02-28 20:18:44 +0800467#if defined(CONFIG_OF_LIBFDT_OVERLAY) && defined(CONFIG_AMLOGIC_MODIFY)
468 u32 fdto_totalsize = 0;
469#endif
470
Simon Glassb6396402014-06-12 07:24:46 -0600471 /* find ramdisk */
472 ret = boot_get_ramdisk(argc, argv, &images, IH_INITRD_ARCH,
473 &images.rd_start, &images.rd_end);
474 if (ret) {
475 puts("Ramdisk image is corrupt or invalid\n");
476 return 1;
477 }
478
Tero Kristofbde7582020-06-12 15:41:20 +0300479 /* check if ramdisk overlaps OS image */
480 if (images.rd_start && (((ulong)images.rd_start >= start &&
Jaehoon Chungef4f4f12020-10-21 14:17:03 +0900481 (ulong)images.rd_start < start + size) ||
482 ((ulong)images.rd_end > start &&
483 (ulong)images.rd_end <= start + size) ||
484 ((ulong)images.rd_start < start &&
485 (ulong)images.rd_end >= start + size))) {
Tero Kristofbde7582020-06-12 15:41:20 +0300486 printf("ERROR: RD image overlaps OS image (OS=0x%lx..0x%lx)\n",
487 start, start + size);
488 return 1;
489 }
490
Simon Glass0c303f92021-09-25 19:43:21 -0600491#if CONFIG_IS_ENABLED(OF_LIBFDT)
Simon Glassb6396402014-06-12 07:24:46 -0600492 /* find flattened device tree */
493 ret = boot_get_fdt(flag, argc, argv, IH_ARCH_DEFAULT, &images,
494 &images.ft_addr, &images.ft_len);
495 if (ret) {
496 puts("Could not find a valid device tree\n");
497 return 1;
498 }
Tero Kristofbde7582020-06-12 15:41:20 +0300499
500 /* check if FDT overlaps OS image */
501 if (images.ft_addr &&
502 (((ulong)images.ft_addr >= start &&
Pali Rohár5acfdfb2022-08-27 14:48:10 +0200503 (ulong)images.ft_addr < start + size) ||
Tero Kristofbde7582020-06-12 15:41:20 +0300504 ((ulong)images.ft_addr + images.ft_len >= start &&
Pali Rohár5acfdfb2022-08-27 14:48:10 +0200505 (ulong)images.ft_addr + images.ft_len < start + size))) {
Tero Kristofbde7582020-06-12 15:41:20 +0300506 printf("ERROR: FDT image overlaps OS image (OS=0x%lx..0x%lx)\n",
507 start, start + size);
508 return 1;
509 }
510
Simon Goldschmidt596be5f2018-12-17 20:14:42 +0100511 if (CONFIG_IS_ENABLED(CMD_FDT))
512 set_working_fdt_addr(map_to_sysmem(images.ft_addr));
Bo Lv81aadc32024-02-28 20:18:44 +0800513
514#if defined(CONFIG_OF_LIBFDT_OVERLAY) && defined(CONFIG_AMLOGIC_MODIFY)
515 if (get_fdto_totalsize(&fdto_totalsize) == 0)
516 fdt_set_totalsize(images.ft_addr, fdt_get_header(images.ft_addr,
517 totalsize) + fdto_totalsize);
518 images.ft_len = fdt_get_header(images.ft_addr, totalsize);
519 do_fdt_overlay();
520#endif
Simon Glassb6396402014-06-12 07:24:46 -0600521#endif
522
Simon Glassbf371b42021-09-25 19:43:20 -0600523#if CONFIG_IS_ENABLED(FIT)
Simon Glass4ed37ab2021-09-25 07:03:20 -0600524 if (IS_ENABLED(CONFIG_FPGA)) {
525 /* find bitstreams */
526 ret = boot_get_fpga(argc, argv, &images, IH_ARCH_DEFAULT,
527 NULL, NULL);
528 if (ret) {
529 printf("FPGA image is corrupted or invalid\n");
530 return 1;
531 }
Michal Simek62afc602016-05-17 14:03:50 +0200532 }
Michal Simek62afc602016-05-17 14:03:50 +0200533
Karl Apsite84a07db2015-05-21 09:52:48 -0400534 /* find all of the loadables */
535 ret = boot_get_loadable(argc, argv, &images, IH_ARCH_DEFAULT,
536 NULL, NULL);
537 if (ret) {
538 printf("Loadable(s) is corrupt or invalid\n");
539 return 1;
540 }
Karl Apsite84a07db2015-05-21 09:52:48 -0400541#endif
542
Simon Glassb6396402014-06-12 07:24:46 -0600543 return 0;
544}
545
Simon Glass09140112020-05-10 11:40:03 -0600546static int bootm_find_other(struct cmd_tbl *cmdtp, int flag, int argc,
547 char *const argv[])
Simon Glassb6396402014-06-12 07:24:46 -0600548{
549 if (((images.os.type == IH_TYPE_KERNEL) ||
550 (images.os.type == IH_TYPE_KERNEL_NOLOAD) ||
551 (images.os.type == IH_TYPE_MULTI)) &&
552 (images.os.os == IH_OS_LINUX ||
553 images.os.os == IH_OS_VXWORKS))
Tero Kristofbde7582020-06-12 15:41:20 +0300554 return bootm_find_images(flag, argc, argv, 0, 0);
Simon Glassb6396402014-06-12 07:24:46 -0600555
556 return 0;
557}
Simon Glass40e59752014-12-02 13:17:30 -0700558#endif /* USE_HOSTC */
559
Julius Werner20908542019-07-24 19:37:54 -0700560#if !defined(USE_HOSTCC) || defined(CONFIG_FIT_SIGNATURE)
Simon Glass3086c052014-12-02 13:17:37 -0700561/**
562 * handle_decomp_error() - display a decompression error
563 *
564 * This function tries to produce a useful message. In the case where the
565 * uncompressed size is the same as the available space, we can assume that
566 * the image is too large for the buffer.
567 *
568 * @comp_type: Compression type being used (IH_COMP_...)
569 * @uncomp_size: Number of bytes uncompressed
Tom Rinic45568c2022-06-25 19:29:46 -0400570 * @buf_size: Number of bytes the decompresion buffer was
Julius Werner20908542019-07-24 19:37:54 -0700571 * @ret: errno error code received from compression library
Heinrich Schuchardt185f8122022-01-19 18:05:50 +0100572 * Return: Appropriate BOOTM_ERR_ error code
Simon Glass3086c052014-12-02 13:17:37 -0700573 */
Tom Rinic45568c2022-06-25 19:29:46 -0400574static int handle_decomp_error(int comp_type, size_t uncomp_size,
575 size_t buf_size, int ret)
Simon Glass40e59752014-12-02 13:17:30 -0700576{
Simon Glass3086c052014-12-02 13:17:37 -0700577 const char *name = genimg_get_comp_name(comp_type);
578
Julius Werner20908542019-07-24 19:37:54 -0700579 /* ENOSYS means unimplemented compression type, don't reset. */
580 if (ret == -ENOSYS)
581 return BOOTM_ERR_UNIMPLEMENTED;
582
Tom Rinic45568c2022-06-25 19:29:46 -0400583 if (uncomp_size >= buf_size)
Simon Glass3086c052014-12-02 13:17:37 -0700584 printf("Image too large: increase CONFIG_SYS_BOOTM_LEN\n");
Simon Glass40e59752014-12-02 13:17:30 -0700585 else
Simon Glass3086c052014-12-02 13:17:37 -0700586 printf("%s: uncompress error %d\n", name, ret);
587
588 /*
589 * The decompression routines are now safe, so will not write beyond
590 * their bounds. Probably it is not necessary to reset, but maintain
591 * the current behaviour for now.
592 */
593 printf("Must RESET board to recover\n");
Simon Glass40e59752014-12-02 13:17:30 -0700594#ifndef USE_HOSTCC
595 bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE);
596#endif
597
598 return BOOTM_ERR_RESET;
599}
Julius Werner20908542019-07-24 19:37:54 -0700600#endif
Simon Glass2b164f12014-06-12 07:24:52 -0600601
Simon Glassce1400f2014-06-12 07:24:53 -0600602#ifndef USE_HOSTCC
Simon Glassd9d7c202022-09-06 20:26:50 -0600603static int bootm_load_os(struct bootm_headers *images, int boot_progress)
Simon Glass2b164f12014-06-12 07:24:52 -0600604{
Simon Glassda79b2f2022-09-06 20:26:51 -0600605 struct image_info os = images->os;
Simon Glass2b164f12014-06-12 07:24:52 -0600606 ulong load = os.load;
Tom Rinicc955352018-05-01 12:32:37 -0400607 ulong load_end;
Simon Glass2b164f12014-06-12 07:24:52 -0600608 ulong blob_start = os.start;
609 ulong blob_end = os.end;
610 ulong image_start = os.image_start;
611 ulong image_len = os.image_len;
Bryan O'Donoghuebbac9222018-04-15 11:48:17 +0100612 ulong flush_start = ALIGN_DOWN(load, ARCH_DMA_MINALIGN);
Simon Glass2b164f12014-06-12 07:24:52 -0600613 bool no_overlap;
614 void *load_buf, *image_buf;
615 int err;
616
617 load_buf = map_sysmem(load, 0);
618 image_buf = map_sysmem(os.image_start, image_len);
Julius Werner20908542019-07-24 19:37:54 -0700619 err = image_decomp(os.comp, load, os.image_start, os.type,
620 load_buf, image_buf, image_len,
621 CONFIG_SYS_BOOTM_LEN, &load_end);
Simon Glass2b164f12014-06-12 07:24:52 -0600622 if (err) {
Tom Rinic45568c2022-06-25 19:29:46 -0400623 err = handle_decomp_error(os.comp, load_end - load,
624 CONFIG_SYS_BOOTM_LEN, err);
Simon Glass2b164f12014-06-12 07:24:52 -0600625 bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE);
626 return err;
627 }
Bo Lvda8d5b72023-07-31 14:58:21 +0800628
629#ifdef CONFIG_AMLOGIC_MODIFY
Bo Lv77426d62023-08-11 19:05:38 +0800630 extern uint32_t get_rsv_mem_size(void);
631 if (load_end >= IOTRACE_LOAD_ADDR && load < get_rsv_mem_size())
Bo Lvda8d5b72023-07-31 14:58:21 +0800632 printf("[Warning] kernel overlap iotrace, please reset decompress addr\n");
633#endif
634
Heinrich Schuchardt21d39462020-08-30 11:34:12 +0200635 /* We need the decompressed image size in the next steps */
636 images->os.image_len = load_end - load;
Bryan O'Donoghuebbac9222018-04-15 11:48:17 +0100637
Trent Piephob4353b32019-03-27 23:50:09 +0000638 flush_cache(flush_start, ALIGN(load_end, ARCH_DMA_MINALIGN) - flush_start);
Simon Glassb6396402014-06-12 07:24:46 -0600639
Tom Rinicc955352018-05-01 12:32:37 -0400640 debug(" kernel loaded at 0x%08lx, end = 0x%08lx\n", load, load_end);
Simon Glassb6396402014-06-12 07:24:46 -0600641 bootstage_mark(BOOTSTAGE_ID_KERNEL_LOADED);
642
Simon Glass2b164f12014-06-12 07:24:52 -0600643 no_overlap = (os.comp == IH_COMP_NONE && load == image_start);
644
Tom Rinicc955352018-05-01 12:32:37 -0400645 if (!no_overlap && load < blob_end && load_end > blob_start) {
Simon Glassb6396402014-06-12 07:24:46 -0600646 debug("images.os.start = 0x%lX, images.os.end = 0x%lx\n",
647 blob_start, blob_end);
648 debug("images.os.load = 0x%lx, load_end = 0x%lx\n", load,
Tom Rinicc955352018-05-01 12:32:37 -0400649 load_end);
Bo Lv4a465022023-02-28 05:51:47 +0000650#ifndef CONFIG_ANDROID_BOOT_IMAGE
Simon Glassb6396402014-06-12 07:24:46 -0600651 /* Check what type of image this is. */
652 if (images->legacy_hdr_valid) {
653 if (image_get_type(&images->legacy_hdr_os_copy)
654 == IH_TYPE_MULTI)
655 puts("WARNING: legacy format multi component image overwritten\n");
656 return BOOTM_ERR_OVERLAP;
657 } else {
658 puts("ERROR: new format image overwritten - must RESET the board to recover\n");
659 bootstage_error(BOOTSTAGE_ID_OVERWRITTEN);
660 return BOOTM_ERR_RESET;
661 }
Bo Lv4a465022023-02-28 05:51:47 +0000662#endif
Simon Glassb6396402014-06-12 07:24:46 -0600663 }
664
Tom Rinicc955352018-05-01 12:32:37 -0400665 lmb_reserve(&images->lmb, images->os.load, (load_end -
666 images->os.load));
Simon Glassb6396402014-06-12 07:24:46 -0600667 return 0;
668}
669
670/**
671 * bootm_disable_interrupts() - Disable interrupts in preparation for load/boot
672 *
Heinrich Schuchardt185f8122022-01-19 18:05:50 +0100673 * Return: interrupt flag (0 if interrupts were disabled, non-zero if they were
Simon Glassb6396402014-06-12 07:24:46 -0600674 * enabled)
675 */
676ulong bootm_disable_interrupts(void)
677{
678 ulong iflag;
679
680 /*
681 * We have reached the point of no return: we are going to
682 * overwrite all exception vector code, so we cannot easily
683 * recover from any failures any more...
684 */
685 iflag = disable_interrupts();
686#ifdef CONFIG_NETCONSOLE
687 /* Stop the ethernet stack if NetConsole could have left it up */
688 eth_halt();
Bernhard Nortmann4917c062015-09-14 15:29:45 +0200689# ifndef CONFIG_DM_ETH
Simon Glassb6396402014-06-12 07:24:46 -0600690 eth_unregister(eth_get_dev());
Bernhard Nortmann4917c062015-09-14 15:29:45 +0200691# endif
Simon Glassb6396402014-06-12 07:24:46 -0600692#endif
693
694#if defined(CONFIG_CMD_USB)
695 /*
696 * turn off USB to prevent the host controller from writing to the
697 * SDRAM while Linux is booting. This could happen (at least for OHCI
698 * controller), because the HCCA (Host Controller Communication Area)
699 * lies within the SDRAM and the host controller writes continously to
700 * this area (as busmaster!). The HccaFrameNumber is for example
701 * updated every 1 ms within the HCCA structure in SDRAM! For more
702 * details see the OpenHCI specification.
703 */
704 usb_stop();
705#endif
706 return iflag;
707}
708
Simon Glass6cd92b12020-11-05 10:33:42 -0700709#define CONSOLE_ARG "console="
Sean Andersonba9aa402022-05-19 18:26:05 -0400710#define NULL_CONSOLE (CONSOLE_ARG "ttynull")
711#define CONSOLE_ARG_SIZE sizeof(NULL_CONSOLE)
Simon Glassb6396402014-06-12 07:24:46 -0600712
Simon Glassb6386f32020-11-05 10:33:43 -0700713/**
714 * fixup_silent_linux() - Handle silencing the linux boot if required
715 *
716 * This uses the silent_linux envvar to control whether to add/set a "console="
717 * parameter to the command line
718 *
719 * @buf: Buffer containing the string to process
720 * @maxlen: Maximum length of buffer
Heinrich Schuchardt185f8122022-01-19 18:05:50 +0100721 * Return: 0 if OK, -ENOSPC if @maxlen is too small
Simon Glassb6386f32020-11-05 10:33:43 -0700722 */
723static int fixup_silent_linux(char *buf, int maxlen)
Simon Glassb6396402014-06-12 07:24:46 -0600724{
Simon Glassb6396402014-06-12 07:24:46 -0600725 int want_silent;
Simon Glassb6386f32020-11-05 10:33:43 -0700726 char *cmdline;
727 int size;
Simon Glassb6396402014-06-12 07:24:46 -0600728
Simon Glassb6386f32020-11-05 10:33:43 -0700729 /*
730 * Move the input string to the end of buffer. The output string will be
731 * built up at the start.
732 */
733 size = strlen(buf) + 1;
734 if (size * 2 > maxlen)
735 return -ENOSPC;
736 cmdline = buf + maxlen - size;
737 memmove(cmdline, buf, size);
Simon Glassb6396402014-06-12 07:24:46 -0600738 /*
739 * Only fix cmdline when requested. The environment variable can be:
740 *
741 * no - we never fixup
742 * yes - we always fixup
743 * unset - we rely on the console silent flag
744 */
Simon Glassbfebc8c2017-08-03 12:22:13 -0600745 want_silent = env_get_yesno("silent_linux");
Simon Glassb6396402014-06-12 07:24:46 -0600746 if (want_silent == 0)
Simon Glass4ae42642020-11-05 10:33:39 -0700747 return 0;
Simon Glassb6396402014-06-12 07:24:46 -0600748 else if (want_silent == -1 && !(gd->flags & GD_FLG_SILENT))
Simon Glass4ae42642020-11-05 10:33:39 -0700749 return 0;
Simon Glassb6396402014-06-12 07:24:46 -0600750
751 debug("before silent fix-up: %s\n", cmdline);
Simon Glassb6386f32020-11-05 10:33:43 -0700752 if (*cmdline) {
Simon Glassb6396402014-06-12 07:24:46 -0600753 char *start = strstr(cmdline, CONSOLE_ARG);
754
Simon Glassb6386f32020-11-05 10:33:43 -0700755 /* Check space for maximum possible new command line */
756 if (size + CONSOLE_ARG_SIZE > maxlen)
Simon Glass4ae42642020-11-05 10:33:39 -0700757 return -ENOSPC;
Simon Glassb6396402014-06-12 07:24:46 -0600758
759 if (start) {
760 char *end = strchr(start, ' ');
Simon Glass6cd92b12020-11-05 10:33:42 -0700761 int start_bytes;
Simon Glassb6396402014-06-12 07:24:46 -0600762
Sean Andersonba9aa402022-05-19 18:26:05 -0400763 start_bytes = start - cmdline;
Simon Glass6cd92b12020-11-05 10:33:42 -0700764 strncpy(buf, cmdline, start_bytes);
Sean Andersonba9aa402022-05-19 18:26:05 -0400765 strncpy(buf + start_bytes, NULL_CONSOLE, CONSOLE_ARG_SIZE);
Simon Glassb6396402014-06-12 07:24:46 -0600766 if (end)
Sean Andersonba9aa402022-05-19 18:26:05 -0400767 strcpy(buf + start_bytes + CONSOLE_ARG_SIZE - 1, end);
Simon Glassb6396402014-06-12 07:24:46 -0600768 else
Sean Andersonba9aa402022-05-19 18:26:05 -0400769 buf[start_bytes + CONSOLE_ARG_SIZE] = '\0';
Simon Glassb6396402014-06-12 07:24:46 -0600770 } else {
Sean Andersonba9aa402022-05-19 18:26:05 -0400771 sprintf(buf, "%s %s", cmdline, NULL_CONSOLE);
Simon Glassb6396402014-06-12 07:24:46 -0600772 }
Simon Glassb6386f32020-11-05 10:33:43 -0700773 if (buf + strlen(buf) >= cmdline)
774 return -ENOSPC;
Simon Glassb6396402014-06-12 07:24:46 -0600775 } else {
Sean Andersonba9aa402022-05-19 18:26:05 -0400776 if (maxlen < CONSOLE_ARG_SIZE)
Simon Glassb6386f32020-11-05 10:33:43 -0700777 return -ENOSPC;
Sean Andersonba9aa402022-05-19 18:26:05 -0400778 strcpy(buf, NULL_CONSOLE);
Simon Glassb6396402014-06-12 07:24:46 -0600779 }
Simon Glassb6386f32020-11-05 10:33:43 -0700780 debug("after silent fix-up: %s\n", buf);
Simon Glassb6396402014-06-12 07:24:46 -0600781
Simon Glassb6386f32020-11-05 10:33:43 -0700782 return 0;
783}
784
Simon Glass51bb3382020-11-05 10:33:48 -0700785/**
786 * process_subst() - Handle substitution of ${...} fields in the environment
787 *
788 * Handle variable substitution in the provided buffer
789 *
790 * @buf: Buffer containing the string to process
791 * @maxlen: Maximum length of buffer
Heinrich Schuchardt185f8122022-01-19 18:05:50 +0100792 * Return: 0 if OK, -ENOSPC if @maxlen is too small
Simon Glass51bb3382020-11-05 10:33:48 -0700793 */
794static int process_subst(char *buf, int maxlen)
795{
796 char *cmdline;
797 int size;
798 int ret;
799
800 /* Move to end of buffer */
801 size = strlen(buf) + 1;
802 cmdline = buf + maxlen - size;
803 if (buf + size > cmdline)
804 return -ENOSPC;
805 memmove(cmdline, buf, size);
806
807 ret = cli_simple_process_macros(cmdline, buf, cmdline - buf);
808
809 return ret;
810}
811
Simon Glass4448fe82020-11-05 10:33:45 -0700812int bootm_process_cmdline(char *buf, int maxlen, int flags)
813{
814 int ret;
815
816 /* Check config first to enable compiler to eliminate code */
817 if (IS_ENABLED(CONFIG_SILENT_CONSOLE) &&
818 !IS_ENABLED(CONFIG_SILENT_U_BOOT_ONLY) &&
Bo Lvaa183f82023-07-29 13:30:00 +0800819 (flags & BOOTM_CL_SILENT) &&
820 !IS_ENABLED(CONFIG_AMLOGIC_MODIFY)) {
Simon Glass4448fe82020-11-05 10:33:45 -0700821 ret = fixup_silent_linux(buf, maxlen);
822 if (ret)
823 return log_msg_ret("silent", ret);
824 }
Simon Glassa8d69622021-03-15 18:11:23 +1300825 if (IS_ENABLED(CONFIG_BOOTARGS_SUBST) && IS_ENABLED(CONFIG_CMDLINE) &&
826 (flags & BOOTM_CL_SUBST)) {
Simon Glass51bb3382020-11-05 10:33:48 -0700827 ret = process_subst(buf, maxlen);
828 if (ret)
Simon Glass185756e2021-02-06 09:57:35 -0700829 return log_msg_ret("subst", ret);
Simon Glass51bb3382020-11-05 10:33:48 -0700830 }
Simon Glass4448fe82020-11-05 10:33:45 -0700831
832 return 0;
833}
834
Simon Glassb3c01672020-11-05 10:33:44 -0700835int bootm_process_cmdline_env(int flags)
Simon Glassb6386f32020-11-05 10:33:43 -0700836{
837 const int maxlen = MAX_CMDLINE_SIZE;
Simon Glassb3c01672020-11-05 10:33:44 -0700838 bool do_silent;
Simon Glassb6386f32020-11-05 10:33:43 -0700839 const char *env;
840 char *buf;
841 int ret;
842
843 /* First check if any action is needed */
844 do_silent = IS_ENABLED(CONFIG_SILENT_CONSOLE) &&
Simon Glassb3c01672020-11-05 10:33:44 -0700845 !IS_ENABLED(CONFIG_SILENT_U_BOOT_ONLY) && (flags & BOOTM_CL_SILENT);
Simon Glass51bb3382020-11-05 10:33:48 -0700846 if (!do_silent && !IS_ENABLED(CONFIG_BOOTARGS_SUBST))
Simon Glassb6386f32020-11-05 10:33:43 -0700847 return 0;
848
849 env = env_get("bootargs");
850 if (env && strlen(env) >= maxlen)
851 return -E2BIG;
852 buf = malloc(maxlen);
853 if (!buf)
854 return -ENOMEM;
855 if (env)
856 strcpy(buf, env);
857 else
858 *buf = '\0';
Simon Glass4448fe82020-11-05 10:33:45 -0700859 ret = bootm_process_cmdline(buf, maxlen, flags);
Simon Glassb6386f32020-11-05 10:33:43 -0700860 if (!ret) {
861 ret = env_set("bootargs", buf);
862
863 /*
864 * If buf is "" and bootargs does not exist, this will produce
865 * an error trying to delete bootargs. Ignore it
866 */
867 if (ret == -ENOENT)
868 ret = 0;
869 }
Simon Glassb6396402014-06-12 07:24:46 -0600870 free(buf);
Simon Glassb6386f32020-11-05 10:33:43 -0700871 if (ret)
872 return log_msg_ret("env", ret);
Simon Glass4ae42642020-11-05 10:33:39 -0700873
874 return 0;
Simon Glassb6396402014-06-12 07:24:46 -0600875}
Simon Glassb6396402014-06-12 07:24:46 -0600876
877/**
878 * Execute selected states of the bootm command.
879 *
880 * Note the arguments to this state must be the first argument, Any 'bootm'
881 * or sub-command arguments must have already been taken.
882 *
883 * Note that if states contains more than one flag it MUST contain
884 * BOOTM_STATE_START, since this handles and consumes the command line args.
885 *
886 * Also note that aside from boot_os_fn functions and bootm_load_os no other
887 * functions we store the return value of in 'ret' may use a negative return
888 * value, without special handling.
889 *
890 * @param cmdtp Pointer to bootm command table entry
891 * @param flag Command flags (CMD_FLAG_...)
892 * @param argc Number of subcommand arguments (0 = no arguments)
893 * @param argv Arguments
894 * @param states Mask containing states to run (BOOTM_STATE_...)
895 * @param images Image header information
896 * @param boot_progress 1 to show boot progress, 0 to not do this
Heinrich Schuchardt185f8122022-01-19 18:05:50 +0100897 * Return: 0 if ok, something else on error. Some errors will cause this
Simon Glassb6396402014-06-12 07:24:46 -0600898 * function to perform a reboot! If states contains BOOTM_STATE_OS_GO
899 * then the intent is to boot an OS, so this function will not return
900 * unless the image type is standalone.
901 */
Simon Glass09140112020-05-10 11:40:03 -0600902int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc,
Simon Glassd9d7c202022-09-06 20:26:50 -0600903 char *const argv[], int states, struct bootm_headers *images,
Simon Glass09140112020-05-10 11:40:03 -0600904 int boot_progress)
Simon Glassb6396402014-06-12 07:24:46 -0600905{
906 boot_os_fn *boot_fn;
907 ulong iflag = 0;
908 int ret = 0, need_boot_fn;
909
910 images->state |= states;
911
912 /*
913 * Work through the states and see how far we get. We stop on
914 * any error.
915 */
916 if (states & BOOTM_STATE_START)
917 ret = bootm_start(cmdtp, flag, argc, argv);
918
Philippe Reynes9d46e632022-03-28 22:57:00 +0200919 if (!ret && (states & BOOTM_STATE_PRE_LOAD))
920 ret = bootm_pre_load(cmdtp, flag, argc, argv);
921
Simon Glassb6396402014-06-12 07:24:46 -0600922 if (!ret && (states & BOOTM_STATE_FINDOS))
923 ret = bootm_find_os(cmdtp, flag, argc, argv);
924
Zubair Lutfullah Kakakhelba079842016-09-09 09:18:58 +0100925 if (!ret && (states & BOOTM_STATE_FINDOTHER))
Simon Glassb6396402014-06-12 07:24:46 -0600926 ret = bootm_find_other(cmdtp, flag, argc, argv);
Simon Glassb6396402014-06-12 07:24:46 -0600927
dongqing.li994a05e2023-10-17 09:19:27 +0800928#if defined(CONFIG_MDUMP_COMPRESS) || \
929 ((defined CONFIG_SUPPORT_BL33Z) && \
930 (defined CONFIG_FULL_RAMDUMP))
931 extern void check_ramdump(void);
932 check_ramdump();
933#endif
934
Simon Glassb6396402014-06-12 07:24:46 -0600935 /* Load the OS */
936 if (!ret && (states & BOOTM_STATE_LOADOS)) {
Simon Glassb6396402014-06-12 07:24:46 -0600937 iflag = bootm_disable_interrupts();
Tom Rinicc955352018-05-01 12:32:37 -0400938 ret = bootm_load_os(images, 0);
939 if (ret && ret != BOOTM_ERR_OVERLAP)
Simon Glassb6396402014-06-12 07:24:46 -0600940 goto err;
941 else if (ret == BOOTM_ERR_OVERLAP)
942 ret = 0;
Simon Glassb6396402014-06-12 07:24:46 -0600943 }
944
945 /* Relocate the ramdisk */
946#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
947 if (!ret && (states & BOOTM_STATE_RAMDISK)) {
948 ulong rd_len = images->rd_end - images->rd_start;
949
950 ret = boot_ramdisk_high(&images->lmb, images->rd_start,
951 rd_len, &images->initrd_start, &images->initrd_end);
952 if (!ret) {
Simon Glass018f5302017-08-03 12:22:10 -0600953 env_set_hex("initrd_start", images->initrd_start);
954 env_set_hex("initrd_end", images->initrd_end);
Simon Glassb6396402014-06-12 07:24:46 -0600955 }
956 }
957#endif
Simon Glass0c303f92021-09-25 19:43:21 -0600958#if CONFIG_IS_ENABLED(OF_LIBFDT) && defined(CONFIG_LMB)
Simon Glassb6396402014-06-12 07:24:46 -0600959 if (!ret && (states & BOOTM_STATE_FDT)) {
960 boot_fdt_add_mem_rsv_regions(&images->lmb, images->ft_addr);
961 ret = boot_relocate_fdt(&images->lmb, &images->ft_addr,
962 &images->ft_len);
963 }
964#endif
965
Hangyu Lif6740182023-03-27 15:45:23 +0800966#ifdef CONFIG_AMLOGIC_MODIFY
967 /* Check reserved memory region */
968#ifdef CONFIG_CMD_RSVMEM
969 ret = run_command("rsvmem check", 0);
970 if (ret) {
971 puts("rsvmem check failed\n");
972 return ret;
973 }
974#endif
975#endif
976
Simon Glassb6396402014-06-12 07:24:46 -0600977 /* From now on, we need the OS boot function */
978 if (ret)
979 return ret;
980 boot_fn = bootm_os_get_boot_func(images->os.os);
981 need_boot_fn = states & (BOOTM_STATE_OS_CMDLINE |
982 BOOTM_STATE_OS_BD_T | BOOTM_STATE_OS_PREP |
983 BOOTM_STATE_OS_FAKE_GO | BOOTM_STATE_OS_GO);
984 if (boot_fn == NULL && need_boot_fn) {
985 if (iflag)
986 enable_interrupts();
987 printf("ERROR: booting os '%s' (%d) is not supported\n",
988 genimg_get_os_name(images->os.os), images->os.os);
989 bootstage_error(BOOTSTAGE_ID_CHECK_BOOT_OS);
990 return 1;
991 }
992
Hector Palacios19e86492016-07-11 12:34:37 +0200993
Simon Glassb6396402014-06-12 07:24:46 -0600994 /* Call various other states that are not generally used */
995 if (!ret && (states & BOOTM_STATE_OS_CMDLINE))
996 ret = boot_fn(BOOTM_STATE_OS_CMDLINE, argc, argv, images);
997 if (!ret && (states & BOOTM_STATE_OS_BD_T))
998 ret = boot_fn(BOOTM_STATE_OS_BD_T, argc, argv, images);
Hector Palacios19e86492016-07-11 12:34:37 +0200999 if (!ret && (states & BOOTM_STATE_OS_PREP)) {
Simon Glass51bb3382020-11-05 10:33:48 -07001000 ret = bootm_process_cmdline_env(images->os.os == IH_OS_LINUX);
Simon Glassd9477a02020-11-05 10:33:41 -07001001 if (ret) {
1002 printf("Cmdline setup failed (err=%d)\n", ret);
1003 ret = CMD_RET_FAILURE;
1004 goto err;
Simon Glass4ae42642020-11-05 10:33:39 -07001005 }
Simon Glassb6396402014-06-12 07:24:46 -06001006 ret = boot_fn(BOOTM_STATE_OS_PREP, argc, argv, images);
Hector Palacios19e86492016-07-11 12:34:37 +02001007 }
Simon Glassb6396402014-06-12 07:24:46 -06001008
1009#ifdef CONFIG_TRACE
1010 /* Pretend to run the OS, then run a user command */
1011 if (!ret && (states & BOOTM_STATE_OS_FAKE_GO)) {
Simon Glass00caae62017-08-03 12:22:12 -06001012 char *cmd_list = env_get("fakegocmd");
Simon Glassb6396402014-06-12 07:24:46 -06001013
1014 ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_FAKE_GO,
1015 images, boot_fn);
1016 if (!ret && cmd_list)
1017 ret = run_command_list(cmd_list, -1, flag);
1018 }
1019#endif
1020
1021 /* Check for unsupported subcommand. */
1022 if (ret) {
Simon Glass13819f02022-10-11 09:47:07 -06001023 printf("subcommand failed (err=%d)\n", ret);
Simon Glassb6396402014-06-12 07:24:46 -06001024 return ret;
1025 }
1026
1027 /* Now run the OS! We hope this doesn't return */
1028 if (!ret && (states & BOOTM_STATE_OS_GO))
1029 ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_GO,
1030 images, boot_fn);
1031
1032 /* Deal with any fallout */
1033err:
1034 if (iflag)
1035 enable_interrupts();
1036
1037 if (ret == BOOTM_ERR_UNIMPLEMENTED)
1038 bootstage_error(BOOTSTAGE_ID_DECOMP_UNIMPL);
1039 else if (ret == BOOTM_ERR_RESET)
1040 do_reset(cmdtp, flag, argc, argv);
1041
1042 return ret;
1043}
1044
Tom Rinic76c93a2019-05-23 07:14:07 -04001045#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)
Simon Glassb6396402014-06-12 07:24:46 -06001046/**
1047 * image_get_kernel - verify legacy format kernel image
1048 * @img_addr: in RAM address of the legacy format image to be verified
1049 * @verify: data CRC verification flag
1050 *
1051 * image_get_kernel() verifies legacy image integrity and returns pointer to
1052 * legacy image header if image verification was completed successfully.
1053 *
1054 * returns:
1055 * pointer to a legacy image header if valid image was found
1056 * otherwise return NULL
1057 */
Simon Glassf3543e62022-09-06 20:26:52 -06001058static struct legacy_img_hdr *image_get_kernel(ulong img_addr, int verify)
Simon Glassb6396402014-06-12 07:24:46 -06001059{
Simon Glassf3543e62022-09-06 20:26:52 -06001060 struct legacy_img_hdr *hdr = (struct legacy_img_hdr *)img_addr;
Simon Glassb6396402014-06-12 07:24:46 -06001061
1062 if (!image_check_magic(hdr)) {
1063 puts("Bad Magic Number\n");
1064 bootstage_error(BOOTSTAGE_ID_CHECK_MAGIC);
1065 return NULL;
1066 }
1067 bootstage_mark(BOOTSTAGE_ID_CHECK_HEADER);
1068
1069 if (!image_check_hcrc(hdr)) {
1070 puts("Bad Header Checksum\n");
1071 bootstage_error(BOOTSTAGE_ID_CHECK_HEADER);
1072 return NULL;
1073 }
1074
1075 bootstage_mark(BOOTSTAGE_ID_CHECK_CHECKSUM);
1076 image_print_contents(hdr);
1077
1078 if (verify) {
1079 puts(" Verifying Checksum ... ");
1080 if (!image_check_dcrc(hdr)) {
1081 printf("Bad Data CRC\n");
1082 bootstage_error(BOOTSTAGE_ID_CHECK_CHECKSUM);
1083 return NULL;
1084 }
1085 puts("OK\n");
1086 }
1087 bootstage_mark(BOOTSTAGE_ID_CHECK_ARCH);
1088
1089 if (!image_check_target_arch(hdr)) {
1090 printf("Unsupported Architecture 0x%x\n", image_get_arch(hdr));
1091 bootstage_error(BOOTSTAGE_ID_CHECK_ARCH);
1092 return NULL;
1093 }
1094 return hdr;
1095}
1096#endif
1097
1098/**
1099 * boot_get_kernel - find kernel image
1100 * @os_data: pointer to a ulong variable, will hold os data start address
1101 * @os_len: pointer to a ulong variable, will hold os data length
1102 *
1103 * boot_get_kernel() tries to find a kernel image, verifies its integrity
1104 * and locates kernel data.
1105 *
1106 * returns:
1107 * pointer to image header if valid image was found, plus kernel start
1108 * address and length, otherwise NULL
1109 */
Simon Glass09140112020-05-10 11:40:03 -06001110static const void *boot_get_kernel(struct cmd_tbl *cmdtp, int flag, int argc,
Simon Glassd9d7c202022-09-06 20:26:50 -06001111 char *const argv[], struct bootm_headers *images,
Simon Glassb6396402014-06-12 07:24:46 -06001112 ulong *os_data, ulong *os_len)
1113{
Tom Rinic76c93a2019-05-23 07:14:07 -04001114#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)
Simon Glassf3543e62022-09-06 20:26:52 -06001115 struct legacy_img_hdr *hdr;
Simon Glassb6396402014-06-12 07:24:46 -06001116#endif
1117 ulong img_addr;
1118 const void *buf;
Simon Glassb6396402014-06-12 07:24:46 -06001119 const char *fit_uname_config = NULL;
1120 const char *fit_uname_kernel = NULL;
Simon Glassbf371b42021-09-25 19:43:20 -06001121#if CONFIG_IS_ENABLED(FIT)
Simon Glassb6396402014-06-12 07:24:46 -06001122 int os_noffset;
1123#endif
1124
Bo Lv4a465022023-02-28 05:51:47 +00001125#ifdef CONFIG_AMLOGIC_MODIFY
1126 char *avb_s;
1127 avb_s = env_get("avb2");
Bo Lva1bffde2023-08-16 21:04:03 +08001128 if (avb_s)
1129 printf("avb2: %s\n", avb_s);
1130 if (avb_s && strcmp(avb_s, "1") != 0) {
Bo Lv4a465022023-02-28 05:51:47 +00001131#ifdef CONFIG_AML_ANTIROLLBACK
1132 boot_img_hdr_t **tmp_img_hdr = (boot_img_hdr_t **)&buf;
1133#endif
1134 }
1135#endif
1136
Bryan Wue6c88a62014-08-15 16:51:39 -07001137 img_addr = genimg_get_kernel_addr_fit(argc < 1 ? NULL : argv[0],
1138 &fit_uname_config,
1139 &fit_uname_kernel);
Simon Glassb6396402014-06-12 07:24:46 -06001140
Philippe Reynes9d46e632022-03-28 22:57:00 +02001141 if (CONFIG_IS_ENABLED(CMD_BOOTM_PRE_LOAD))
1142 img_addr += image_load_offset;
1143
Simon Glassb6396402014-06-12 07:24:46 -06001144 bootstage_mark(BOOTSTAGE_ID_CHECK_MAGIC);
1145
Simon Glassb6396402014-06-12 07:24:46 -06001146 /* check image type, for FIT images get FIT kernel node */
1147 *os_data = *os_len = 0;
1148 buf = map_sysmem(img_addr, 0);
1149 switch (genimg_get_format(buf)) {
Tom Rinic76c93a2019-05-23 07:14:07 -04001150#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)
Simon Glassb6396402014-06-12 07:24:46 -06001151 case IMAGE_FORMAT_LEGACY:
1152 printf("## Booting kernel from Legacy Image at %08lx ...\n",
1153 img_addr);
1154 hdr = image_get_kernel(img_addr, images->verify);
1155 if (!hdr)
1156 return NULL;
1157 bootstage_mark(BOOTSTAGE_ID_CHECK_IMAGETYPE);
1158
1159 /* get os_data and os_len */
1160 switch (image_get_type(hdr)) {
1161 case IH_TYPE_KERNEL:
1162 case IH_TYPE_KERNEL_NOLOAD:
1163 *os_data = image_get_data(hdr);
1164 *os_len = image_get_data_size(hdr);
1165 break;
1166 case IH_TYPE_MULTI:
1167 image_multi_getimg(hdr, 0, os_data, os_len);
1168 break;
1169 case IH_TYPE_STANDALONE:
1170 *os_data = image_get_data(hdr);
1171 *os_len = image_get_data_size(hdr);
1172 break;
1173 default:
1174 printf("Wrong Image Type for %s command\n",
1175 cmdtp->name);
1176 bootstage_error(BOOTSTAGE_ID_CHECK_IMAGETYPE);
1177 return NULL;
1178 }
1179
1180 /*
1181 * copy image header to allow for image overwrites during
1182 * kernel decompression.
1183 */
1184 memmove(&images->legacy_hdr_os_copy, hdr,
Simon Glassf3543e62022-09-06 20:26:52 -06001185 sizeof(struct legacy_img_hdr));
Simon Glassb6396402014-06-12 07:24:46 -06001186
1187 /* save pointer to image header */
1188 images->legacy_hdr_os = hdr;
1189
1190 images->legacy_hdr_valid = 1;
1191 bootstage_mark(BOOTSTAGE_ID_DECOMP_IMAGE);
1192 break;
1193#endif
Simon Glassbf371b42021-09-25 19:43:20 -06001194#if CONFIG_IS_ENABLED(FIT)
Simon Glassb6396402014-06-12 07:24:46 -06001195 case IMAGE_FORMAT_FIT:
Simon Glass126cc862014-06-12 07:24:47 -06001196 os_noffset = fit_image_load(images, img_addr,
Simon Glassb6396402014-06-12 07:24:46 -06001197 &fit_uname_kernel, &fit_uname_config,
1198 IH_ARCH_DEFAULT, IH_TYPE_KERNEL,
1199 BOOTSTAGE_ID_FIT_KERNEL_START,
1200 FIT_LOAD_IGNORED, os_data, os_len);
1201 if (os_noffset < 0)
1202 return NULL;
1203
1204 images->fit_hdr_os = map_sysmem(img_addr, 0);
1205 images->fit_uname_os = fit_uname_kernel;
1206 images->fit_uname_cfg = fit_uname_config;
1207 images->fit_noffset_os = os_noffset;
1208 break;
1209#endif
1210#ifdef CONFIG_ANDROID_BOOT_IMAGE
1211 case IMAGE_FORMAT_ANDROID:
1212 printf("## Booting Android Image at 0x%08lx ...\n", img_addr);
Bo Lv4a465022023-02-28 05:51:47 +00001213
1214#ifndef CONFIG_AMLOGIC_MODIFY
Simon Glass07c0cd72014-06-12 07:24:48 -06001215 if (android_image_get_kernel(buf, images->verify,
Simon Glassb6396402014-06-12 07:24:46 -06001216 os_data, os_len))
1217 return NULL;
Bo Lv4a465022023-02-28 05:51:47 +00001218#else
1219 if (!android_image_need_move(&img_addr, buf))
1220 buf = map_sysmem(img_addr, 0);
1221 else
1222 return NULL;
1223 if (android_image_get_kernel(buf, images->verify,
1224 os_data, os_len))
1225 return NULL;
1226
Bo Lva1bffde2023-08-16 21:04:03 +08001227 if (avb_s && strcmp(avb_s, "1") != 0) {
Bo Lv4a465022023-02-28 05:51:47 +00001228#ifdef CONFIG_AML_ANTIROLLBACK
1229 if (!check_antirollback((*tmp_img_hdr)->kernel_version)) {
1230 *os_len = 0;
1231 return NULL;
1232 }
1233#endif
1234 }
1235#endif
Simon Glassb6396402014-06-12 07:24:46 -06001236 break;
1237#endif
1238 default:
1239 printf("Wrong Image Format for %s command\n", cmdtp->name);
1240 bootstage_error(BOOTSTAGE_ID_FIT_KERNEL_INFO);
1241 return NULL;
1242 }
1243
1244 debug(" kernel data at 0x%08lx, len = 0x%08lx (%ld)\n",
1245 *os_data, *os_len, *os_len);
1246
1247 return buf;
1248}
Heinrich Schuchardtf6c6df72019-01-08 18:13:06 +01001249
1250/**
1251 * switch_to_non_secure_mode() - switch to non-secure mode
1252 *
1253 * This routine is overridden by architectures requiring this feature.
1254 */
1255void __weak switch_to_non_secure_mode(void)
1256{
1257}
1258
Simon Glassce1400f2014-06-12 07:24:53 -06001259#else /* USE_HOSTCC */
1260
Fabrice Fontaine93e07882019-05-03 22:37:05 +02001261#if defined(CONFIG_FIT_SIGNATURE)
Simon Glass8a9d0372020-03-18 11:44:02 -06001262static int bootm_host_load_image(const void *fit, int req_image_type,
1263 int cfg_noffset)
Simon Glassce1400f2014-06-12 07:24:53 -06001264{
1265 const char *fit_uname_config = NULL;
1266 ulong data, len;
Simon Glassd9d7c202022-09-06 20:26:50 -06001267 struct bootm_headers images;
Simon Glassce1400f2014-06-12 07:24:53 -06001268 int noffset;
Tom Rinic45568c2022-06-25 19:29:46 -04001269 ulong load_end, buf_size;
Simon Glassce1400f2014-06-12 07:24:53 -06001270 uint8_t image_type;
Daniel Golle0cd57f22022-08-27 04:14:42 +01001271 uint8_t image_comp;
Simon Glassce1400f2014-06-12 07:24:53 -06001272 void *load_buf;
1273 int ret;
1274
Simon Glass8a9d0372020-03-18 11:44:02 -06001275 fit_uname_config = fdt_get_name(fit, cfg_noffset, NULL);
Simon Glassce1400f2014-06-12 07:24:53 -06001276 memset(&images, '\0', sizeof(images));
1277 images.verify = 1;
1278 noffset = fit_image_load(&images, (ulong)fit,
1279 NULL, &fit_uname_config,
1280 IH_ARCH_DEFAULT, req_image_type, -1,
1281 FIT_LOAD_IGNORED, &data, &len);
1282 if (noffset < 0)
1283 return noffset;
1284 if (fit_image_get_type(fit, noffset, &image_type)) {
1285 puts("Can't get image type!\n");
1286 return -EINVAL;
1287 }
1288
Daniel Golle88de6c52022-08-27 04:17:28 +01001289 if (fit_image_get_comp(fit, noffset, &image_comp))
1290 image_comp = IH_COMP_NONE;
Simon Glassce1400f2014-06-12 07:24:53 -06001291
1292 /* Allow the image to expand by a factor of 4, should be safe */
Tom Rinic45568c2022-06-25 19:29:46 -04001293 buf_size = (1 << 20) + len * 4;
1294 load_buf = malloc(buf_size);
Daniel Golle0cd57f22022-08-27 04:14:42 +01001295 ret = image_decomp(image_comp, 0, data, image_type, load_buf,
Tom Rinic45568c2022-06-25 19:29:46 -04001296 (void *)data, len, buf_size, &load_end);
Simon Glassce1400f2014-06-12 07:24:53 -06001297 free(load_buf);
Simon Glass081cc192014-12-02 13:17:33 -07001298
Julius Werner20908542019-07-24 19:37:54 -07001299 if (ret) {
Daniel Golle0cd57f22022-08-27 04:14:42 +01001300 ret = handle_decomp_error(image_comp, load_end - 0, buf_size, ret);
Julius Werner20908542019-07-24 19:37:54 -07001301 if (ret != BOOTM_ERR_UNIMPLEMENTED)
1302 return ret;
1303 }
Simon Glassce1400f2014-06-12 07:24:53 -06001304
1305 return 0;
1306}
1307
1308int bootm_host_load_images(const void *fit, int cfg_noffset)
1309{
1310 static uint8_t image_types[] = {
1311 IH_TYPE_KERNEL,
1312 IH_TYPE_FLATDT,
1313 IH_TYPE_RAMDISK,
1314 };
1315 int err = 0;
1316 int i;
1317
1318 for (i = 0; i < ARRAY_SIZE(image_types); i++) {
1319 int ret;
1320
Simon Glass8a9d0372020-03-18 11:44:02 -06001321 ret = bootm_host_load_image(fit, image_types[i], cfg_noffset);
Simon Glassce1400f2014-06-12 07:24:53 -06001322 if (!err && ret && ret != -ENOENT)
1323 err = ret;
1324 }
1325
1326 /* Return the first error we found */
1327 return err;
1328}
Fabrice Fontaine93e07882019-05-03 22:37:05 +02001329#endif
Simon Glassea51a622014-06-12 07:24:51 -06001330
1331#endif /* ndef USE_HOSTCC */