blob: c362461f1ec6f7af9e1f422c5a4cb4885bdd7e68 [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) {
Bo Lvae6e7052024-04-26 18:05:18 +0800146 env_set("initrd_high", "0D000000");
147 env_set("fdt_high", "0D000000");
Bo Lv4a465022023-02-28 05:51:47 +0000148 }
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) {
Bo Lv6a9c2962024-03-27 11:23:21 +0800201 #ifdef CONFIG_INITRD_FDT_HIGH_ADDR
202 switch (env_get_bootm_size()) {
203 case 0x8000000:
204 env_set("initrd_high", "06000000");
205 env_set("fdt_high", "06000000");
206 break;
207 case 0x10000000:
208 case 0x20000000:
209 env_set("initrd_high", "0F400000");
210 env_set("fdt_high", "0F400000");
211 break;
212 default:
213 env_set("initrd_high", "0D000000");
214 env_set("fdt_high", "0D000000");
215 break;
216 }
Bo Lv4a465022023-02-28 05:51:47 +0000217 #else
218 env_set("initrd_high", "0D000000");
Bo Lv4a465022023-02-28 05:51:47 +0000219 env_set("fdt_high", "0D000000");
220 #endif
221
222 images.os.arch = ((image_header_t *)(images.os.image_start))->ih_arch;
223 images.os.image_start += sizeof(image_header_t);
224 }
225 images.os.type = IH_TYPE_KERNEL;
226
227 if (images.os.arch == IH_ARCH_ARM)
228 images.os.comp = image_get_comp(os_hdr + 0x800);
229 else
230 images.os.comp = android_image_get_comp(os_hdr);
231
232 //images.os.comp = android_image_get_comp(os_hdr);
233 images.os.os = IH_OS_LINUX;
234
235 images.os.end = android_image_get_end(os_hdr);
236 images.os.load = android_image_get_kload(os_hdr);
237 if (images.os.load == 0x10008000)
238 images.os.load = 0x1080000;
239 images.ep = images.os.load;
240 ep_found = true;
241#else
Simon Glassb6396402014-06-12 07:24:46 -0600242 images.os.type = IH_TYPE_KERNEL;
Eugeniu Rosca829ceb22019-04-08 17:35:27 +0200243 images.os.comp = android_image_get_kcomp(os_hdr);
Simon Glassb6396402014-06-12 07:24:46 -0600244 images.os.os = IH_OS_LINUX;
Simon Glassb6396402014-06-12 07:24:46 -0600245
246 images.os.end = android_image_get_end(os_hdr);
247 images.os.load = android_image_get_kload(os_hdr);
Ahmad Draidi86f46952014-10-23 20:50:07 +0300248 images.ep = images.os.load;
249 ep_found = true;
Bo Lv4a465022023-02-28 05:51:47 +0000250#endif
Simon Glassb6396402014-06-12 07:24:46 -0600251 break;
252#endif
253 default:
254 puts("ERROR: unknown image format type!\n");
255 return 1;
256 }
257
Simon Glass90268b82014-10-19 21:11:24 -0600258 /* If we have a valid setup.bin, we will use that for entry (x86) */
Simon Glass5bda35c2014-10-10 08:21:57 -0600259 if (images.os.arch == IH_ARCH_I386 ||
260 images.os.arch == IH_ARCH_X86_64) {
Simon Glass90268b82014-10-19 21:11:24 -0600261 ulong len;
262
263 ret = boot_get_setup(&images, IH_ARCH_I386, &images.ep, &len);
264 if (ret < 0 && ret != -ENOENT) {
265 puts("Could not find a valid setup.bin for x86\n");
266 return 1;
267 }
268 /* Kernel entry point is the setup.bin */
269 } else if (images.legacy_hdr_valid) {
Simon Glassb6396402014-06-12 07:24:46 -0600270 images.ep = image_get_ep(&images.legacy_hdr_os_copy);
Simon Glassbf371b42021-09-25 19:43:20 -0600271#if CONFIG_IS_ENABLED(FIT)
Simon Glassb6396402014-06-12 07:24:46 -0600272 } else if (images.fit_uname_os) {
273 int ret;
274
275 ret = fit_image_get_entry(images.fit_hdr_os,
276 images.fit_noffset_os, &images.ep);
277 if (ret) {
278 puts("Can't get entry point property!\n");
279 return 1;
280 }
281#endif
282 } else if (!ep_found) {
283 puts("Could not find kernel entry point!\n");
284 return 1;
285 }
286
287 if (images.os.type == IH_TYPE_KERNEL_NOLOAD) {
Marek Vasut487b5fa2018-06-13 06:13:33 +0200288 if (CONFIG_IS_ENABLED(CMD_BOOTI) &&
289 images.os.arch == IH_ARCH_ARM64) {
290 ulong image_addr;
291 ulong image_size;
292
293 ret = booti_setup(images.os.image_start, &image_addr,
294 &image_size, true);
295 if (ret != 0)
296 return 1;
297
298 images.os.type = IH_TYPE_KERNEL;
299 images.os.load = image_addr;
300 images.ep = image_addr;
301 } else {
302 images.os.load = images.os.image_start;
303 images.ep += images.os.image_start;
304 }
Simon Glassb6396402014-06-12 07:24:46 -0600305 }
306
Simon Glass7a80de42016-02-24 09:14:42 -0700307 images.os.start = map_to_sysmem(os_hdr);
Simon Glassb6396402014-06-12 07:24:46 -0600308
309 return 0;
310}
311
Bo Lv81aadc32024-02-28 20:18:44 +0800312/*
313 * load dtb overlay partition to mem
314*/
315#if defined(CONFIG_OF_LIBFDT_OVERLAY) && defined(CONFIG_AMLOGIC_MODIFY)
316static int read_fdto_partition(void)
317{
318 char cmd[128];
319 void *dtbo_mem_addr = NULL;
320 char dtbo_partition[32] = {0};
321 char *s1;
322 struct dt_table_header hdr;
323
324 //run_command("get_valid_slot;", 0);
325 s1 = env_get("active_slot");
326 if (s1 && (strcmp(s1, "normal") == 0))
327 strcpy(dtbo_partition, "dtbo");
328 else if (s1 && (strcmp(s1, "_a") == 0))
329 strcpy(dtbo_partition, "dtbo_a");
330 else if (s1 && (strcmp(s1, "_b") == 0))
331 strcpy(dtbo_partition, "dtbo_b");
332
333 /*
334 * Though it is really no need to parse the adtimg infos
335 * here, but wasting time to read the whole dtbo image
336 * partition is unacceptable
337 */
338 pr_info("Start read %s partition datas!\n", dtbo_partition);
339 extern int store_read(const char *name, loff_t off, size_t size, void *buf);
340 if (store_read(dtbo_partition, 0,
341 sizeof(struct dt_table_header), &hdr) < 0) {
342 pr_err("Fail to read header of DTBO partition\n");
343 return -1;
344 }
345
346#ifdef CONFIG_CMD_ADTIMG
347 if (!android_dt_check_header((ulong)&hdr)) {
348 printf("DTBO partition header is incorrect\n");
349 return -1;
350 }
351#endif
352
353 dtbo_mem_addr = malloc(fdt32_to_cpu(hdr.total_size));
354 if (!dtbo_mem_addr) {
355 printf("out of memory\n");
356 return -1;
357 } else {
358 if (store_read(dtbo_partition, 0,
359 fdt32_to_cpu(hdr.total_size), dtbo_mem_addr) < 0) {
360 printf("Fail to read DTBO partition\n");
361 free(dtbo_mem_addr);
362 return -1;
363 }
364 else {
365 sprintf(cmd, "0x%p", dtbo_mem_addr);
366 env_set("dtbo_mem_addr",cmd);
367 }
368 }
369
370 return 0;
371}
372
373static int get_fdto_totalsize(u32 *tz)
374{
375#ifdef CONFIG_CMD_ADTIMG
376 unsigned long long dtbo_mem_addr = 0x0;
377#endif
378 int ret;
379
380 ret = read_fdto_partition();
381 if (ret != 0)
382 return ret;
383
384#ifdef CONFIG_CMD_ADTIMG
385 dtbo_mem_addr = simple_strtoul(env_get("dtbo_mem_addr"), NULL, 16);
386 *tz = android_dt_get_totalsize(dtbo_mem_addr);
387#endif
388 return 0;
389}
390
391static int do_fdt_overlay(void)
392{
393 unsigned long long dtbo_mem_addr = 0x0;
394 int dtbo_num = 0;
395 int i;
396 char cmd[128];
397 unsigned long long dtbo_start;
398 char *dtbo_idx = NULL;
399 char idx[32];
400
401 if (!env_get("dtbo_mem_addr")) {
402 pr_err("No valid dtbo image found\n");
403 return -1;
404 }
405
406 dtbo_mem_addr = simple_strtoul(env_get("dtbo_mem_addr"), NULL, 16);
407#ifdef CONFIG_CMD_ADTIMG
408 if (!android_dt_check_header(dtbo_mem_addr)) {
409 pr_err("Error: DTBO image header is incorrect\n");
410 return -1;
411 }
412#endif
413
414 /* android_dt_print_contents(dtbo_mem_addr); */
415 dtbo_num = fdt32_to_cpu((
416 (const struct dt_table_header *)dtbo_mem_addr)->dt_entry_count);
417 pr_info("find %d dtbos\n", dtbo_num);
418
419 dtbo_idx = env_get("androidboot.dtbo_idx");
420 if (!dtbo_idx) {
421 pr_info("No androidboot.dtbo_idx configured\n");
422 pr_info("And no dtbos will be applied\n");
423 return -1;
424 }
425 pr_info("dtbos to be applied: %s\n", dtbo_idx);
426
427 #ifndef CONFIG_CMD_ADTIMG
428 pr_info("Error: No adtimg support found\n");
429 return -1;
430 #endif
431
432 for (i = 0; i < dtbo_num; i++) {
433 memset(idx, 0x00, sizeof(idx));
434 sprintf(idx, "%d", i);
435 if (strstr(dtbo_idx, idx)) {
436 printf("Apply dtbo %d\n", i);
437 sprintf(cmd, "adtimg addr 0x%llx;adtimg get dt --index=%d dtbo_start 0x%llx",
438 dtbo_mem_addr, i, dtbo_mem_addr);
439 run_command(cmd, 0);
440 dtbo_start = simple_strtoul(
441 env_get("dtbo_start"), NULL, 16);
442
443 sprintf(cmd, "fdt apply 0x%llx", dtbo_start);
444 run_command(cmd, 0);
445 }
446 }
447
448 free((void *)dtbo_mem_addr);
449 return 0;
450}
451#endif
452
Karl Apsited52e8572015-05-21 09:52:49 -0400453/**
454 * bootm_find_images - wrapper to find and locate various images
455 * @flag: Ignored Argument
456 * @argc: command argument count
457 * @argv: command argument list
Tero Kristofbde7582020-06-12 15:41:20 +0300458 * @start: OS image start address
459 * @size: OS image size
Karl Apsited52e8572015-05-21 09:52:49 -0400460 *
461 * boot_find_images() will attempt to load an available ramdisk,
462 * flattened device tree, as well as specifically marked
463 * "loadable" images (loadables are FIT only)
464 *
465 * Note: bootm_find_images will skip an image if it is not found
466 *
467 * @return:
468 * 0, if all existing images were loaded correctly
469 * 1, if an image is found but corrupted, or invalid
470 */
Tero Kristofbde7582020-06-12 15:41:20 +0300471int bootm_find_images(int flag, int argc, char *const argv[], ulong start,
472 ulong size)
Simon Glassb6396402014-06-12 07:24:46 -0600473{
474 int ret;
475
Bo Lv81aadc32024-02-28 20:18:44 +0800476#if defined(CONFIG_OF_LIBFDT_OVERLAY) && defined(CONFIG_AMLOGIC_MODIFY)
477 u32 fdto_totalsize = 0;
478#endif
479
Simon Glassb6396402014-06-12 07:24:46 -0600480 /* find ramdisk */
481 ret = boot_get_ramdisk(argc, argv, &images, IH_INITRD_ARCH,
482 &images.rd_start, &images.rd_end);
483 if (ret) {
484 puts("Ramdisk image is corrupt or invalid\n");
485 return 1;
486 }
487
Tero Kristofbde7582020-06-12 15:41:20 +0300488 /* check if ramdisk overlaps OS image */
489 if (images.rd_start && (((ulong)images.rd_start >= start &&
Jaehoon Chungef4f4f12020-10-21 14:17:03 +0900490 (ulong)images.rd_start < start + size) ||
491 ((ulong)images.rd_end > start &&
492 (ulong)images.rd_end <= start + size) ||
493 ((ulong)images.rd_start < start &&
494 (ulong)images.rd_end >= start + size))) {
Tero Kristofbde7582020-06-12 15:41:20 +0300495 printf("ERROR: RD image overlaps OS image (OS=0x%lx..0x%lx)\n",
496 start, start + size);
497 return 1;
498 }
499
Simon Glass0c303f92021-09-25 19:43:21 -0600500#if CONFIG_IS_ENABLED(OF_LIBFDT)
Simon Glassb6396402014-06-12 07:24:46 -0600501 /* find flattened device tree */
502 ret = boot_get_fdt(flag, argc, argv, IH_ARCH_DEFAULT, &images,
503 &images.ft_addr, &images.ft_len);
504 if (ret) {
505 puts("Could not find a valid device tree\n");
506 return 1;
507 }
Tero Kristofbde7582020-06-12 15:41:20 +0300508
509 /* check if FDT overlaps OS image */
510 if (images.ft_addr &&
511 (((ulong)images.ft_addr >= start &&
Pali Rohár5acfdfb2022-08-27 14:48:10 +0200512 (ulong)images.ft_addr < start + size) ||
Tero Kristofbde7582020-06-12 15:41:20 +0300513 ((ulong)images.ft_addr + images.ft_len >= start &&
Pali Rohár5acfdfb2022-08-27 14:48:10 +0200514 (ulong)images.ft_addr + images.ft_len < start + size))) {
Tero Kristofbde7582020-06-12 15:41:20 +0300515 printf("ERROR: FDT image overlaps OS image (OS=0x%lx..0x%lx)\n",
516 start, start + size);
517 return 1;
518 }
519
Simon Goldschmidt596be5f2018-12-17 20:14:42 +0100520 if (CONFIG_IS_ENABLED(CMD_FDT))
521 set_working_fdt_addr(map_to_sysmem(images.ft_addr));
Bo Lv81aadc32024-02-28 20:18:44 +0800522
523#if defined(CONFIG_OF_LIBFDT_OVERLAY) && defined(CONFIG_AMLOGIC_MODIFY)
524 if (get_fdto_totalsize(&fdto_totalsize) == 0)
525 fdt_set_totalsize(images.ft_addr, fdt_get_header(images.ft_addr,
526 totalsize) + fdto_totalsize);
527 images.ft_len = fdt_get_header(images.ft_addr, totalsize);
528 do_fdt_overlay();
529#endif
Simon Glassb6396402014-06-12 07:24:46 -0600530#endif
531
Simon Glassbf371b42021-09-25 19:43:20 -0600532#if CONFIG_IS_ENABLED(FIT)
Simon Glass4ed37ab2021-09-25 07:03:20 -0600533 if (IS_ENABLED(CONFIG_FPGA)) {
534 /* find bitstreams */
535 ret = boot_get_fpga(argc, argv, &images, IH_ARCH_DEFAULT,
536 NULL, NULL);
537 if (ret) {
538 printf("FPGA image is corrupted or invalid\n");
539 return 1;
540 }
Michal Simek62afc602016-05-17 14:03:50 +0200541 }
Michal Simek62afc602016-05-17 14:03:50 +0200542
Karl Apsite84a07db2015-05-21 09:52:48 -0400543 /* find all of the loadables */
544 ret = boot_get_loadable(argc, argv, &images, IH_ARCH_DEFAULT,
545 NULL, NULL);
546 if (ret) {
547 printf("Loadable(s) is corrupt or invalid\n");
548 return 1;
549 }
Karl Apsite84a07db2015-05-21 09:52:48 -0400550#endif
551
Simon Glassb6396402014-06-12 07:24:46 -0600552 return 0;
553}
554
Simon Glass09140112020-05-10 11:40:03 -0600555static int bootm_find_other(struct cmd_tbl *cmdtp, int flag, int argc,
556 char *const argv[])
Simon Glassb6396402014-06-12 07:24:46 -0600557{
558 if (((images.os.type == IH_TYPE_KERNEL) ||
559 (images.os.type == IH_TYPE_KERNEL_NOLOAD) ||
560 (images.os.type == IH_TYPE_MULTI)) &&
561 (images.os.os == IH_OS_LINUX ||
562 images.os.os == IH_OS_VXWORKS))
Tero Kristofbde7582020-06-12 15:41:20 +0300563 return bootm_find_images(flag, argc, argv, 0, 0);
Simon Glassb6396402014-06-12 07:24:46 -0600564
565 return 0;
566}
Simon Glass40e59752014-12-02 13:17:30 -0700567#endif /* USE_HOSTC */
568
Julius Werner20908542019-07-24 19:37:54 -0700569#if !defined(USE_HOSTCC) || defined(CONFIG_FIT_SIGNATURE)
Simon Glass3086c052014-12-02 13:17:37 -0700570/**
571 * handle_decomp_error() - display a decompression error
572 *
573 * This function tries to produce a useful message. In the case where the
574 * uncompressed size is the same as the available space, we can assume that
575 * the image is too large for the buffer.
576 *
577 * @comp_type: Compression type being used (IH_COMP_...)
578 * @uncomp_size: Number of bytes uncompressed
Tom Rinic45568c2022-06-25 19:29:46 -0400579 * @buf_size: Number of bytes the decompresion buffer was
Julius Werner20908542019-07-24 19:37:54 -0700580 * @ret: errno error code received from compression library
Heinrich Schuchardt185f8122022-01-19 18:05:50 +0100581 * Return: Appropriate BOOTM_ERR_ error code
Simon Glass3086c052014-12-02 13:17:37 -0700582 */
Tom Rinic45568c2022-06-25 19:29:46 -0400583static int handle_decomp_error(int comp_type, size_t uncomp_size,
584 size_t buf_size, int ret)
Simon Glass40e59752014-12-02 13:17:30 -0700585{
Simon Glass3086c052014-12-02 13:17:37 -0700586 const char *name = genimg_get_comp_name(comp_type);
587
Julius Werner20908542019-07-24 19:37:54 -0700588 /* ENOSYS means unimplemented compression type, don't reset. */
589 if (ret == -ENOSYS)
590 return BOOTM_ERR_UNIMPLEMENTED;
591
Tom Rinic45568c2022-06-25 19:29:46 -0400592 if (uncomp_size >= buf_size)
Simon Glass3086c052014-12-02 13:17:37 -0700593 printf("Image too large: increase CONFIG_SYS_BOOTM_LEN\n");
Simon Glass40e59752014-12-02 13:17:30 -0700594 else
Simon Glass3086c052014-12-02 13:17:37 -0700595 printf("%s: uncompress error %d\n", name, ret);
596
597 /*
598 * The decompression routines are now safe, so will not write beyond
599 * their bounds. Probably it is not necessary to reset, but maintain
600 * the current behaviour for now.
601 */
602 printf("Must RESET board to recover\n");
Simon Glass40e59752014-12-02 13:17:30 -0700603#ifndef USE_HOSTCC
604 bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE);
605#endif
606
607 return BOOTM_ERR_RESET;
608}
Julius Werner20908542019-07-24 19:37:54 -0700609#endif
Simon Glass2b164f12014-06-12 07:24:52 -0600610
Simon Glassce1400f2014-06-12 07:24:53 -0600611#ifndef USE_HOSTCC
Simon Glassd9d7c202022-09-06 20:26:50 -0600612static int bootm_load_os(struct bootm_headers *images, int boot_progress)
Simon Glass2b164f12014-06-12 07:24:52 -0600613{
Simon Glassda79b2f2022-09-06 20:26:51 -0600614 struct image_info os = images->os;
Simon Glass2b164f12014-06-12 07:24:52 -0600615 ulong load = os.load;
Tom Rinicc955352018-05-01 12:32:37 -0400616 ulong load_end;
Simon Glass2b164f12014-06-12 07:24:52 -0600617 ulong blob_start = os.start;
618 ulong blob_end = os.end;
619 ulong image_start = os.image_start;
620 ulong image_len = os.image_len;
Bryan O'Donoghuebbac9222018-04-15 11:48:17 +0100621 ulong flush_start = ALIGN_DOWN(load, ARCH_DMA_MINALIGN);
Simon Glass2b164f12014-06-12 07:24:52 -0600622 bool no_overlap;
623 void *load_buf, *image_buf;
624 int err;
625
626 load_buf = map_sysmem(load, 0);
627 image_buf = map_sysmem(os.image_start, image_len);
Julius Werner20908542019-07-24 19:37:54 -0700628 err = image_decomp(os.comp, load, os.image_start, os.type,
629 load_buf, image_buf, image_len,
630 CONFIG_SYS_BOOTM_LEN, &load_end);
Simon Glass2b164f12014-06-12 07:24:52 -0600631 if (err) {
Tom Rinic45568c2022-06-25 19:29:46 -0400632 err = handle_decomp_error(os.comp, load_end - load,
633 CONFIG_SYS_BOOTM_LEN, err);
Simon Glass2b164f12014-06-12 07:24:52 -0600634 bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE);
635 return err;
636 }
Bo Lvda8d5b72023-07-31 14:58:21 +0800637
638#ifdef CONFIG_AMLOGIC_MODIFY
Bo Lv77426d62023-08-11 19:05:38 +0800639 extern uint32_t get_rsv_mem_size(void);
640 if (load_end >= IOTRACE_LOAD_ADDR && load < get_rsv_mem_size())
Bo Lvda8d5b72023-07-31 14:58:21 +0800641 printf("[Warning] kernel overlap iotrace, please reset decompress addr\n");
642#endif
643
Heinrich Schuchardt21d39462020-08-30 11:34:12 +0200644 /* We need the decompressed image size in the next steps */
645 images->os.image_len = load_end - load;
Bryan O'Donoghuebbac9222018-04-15 11:48:17 +0100646
Trent Piephob4353b32019-03-27 23:50:09 +0000647 flush_cache(flush_start, ALIGN(load_end, ARCH_DMA_MINALIGN) - flush_start);
Simon Glassb6396402014-06-12 07:24:46 -0600648
Tom Rinicc955352018-05-01 12:32:37 -0400649 debug(" kernel loaded at 0x%08lx, end = 0x%08lx\n", load, load_end);
Simon Glassb6396402014-06-12 07:24:46 -0600650 bootstage_mark(BOOTSTAGE_ID_KERNEL_LOADED);
651
Simon Glass2b164f12014-06-12 07:24:52 -0600652 no_overlap = (os.comp == IH_COMP_NONE && load == image_start);
653
Tom Rinicc955352018-05-01 12:32:37 -0400654 if (!no_overlap && load < blob_end && load_end > blob_start) {
Simon Glassb6396402014-06-12 07:24:46 -0600655 debug("images.os.start = 0x%lX, images.os.end = 0x%lx\n",
656 blob_start, blob_end);
657 debug("images.os.load = 0x%lx, load_end = 0x%lx\n", load,
Tom Rinicc955352018-05-01 12:32:37 -0400658 load_end);
Bo Lv4a465022023-02-28 05:51:47 +0000659#ifndef CONFIG_ANDROID_BOOT_IMAGE
Simon Glassb6396402014-06-12 07:24:46 -0600660 /* Check what type of image this is. */
661 if (images->legacy_hdr_valid) {
662 if (image_get_type(&images->legacy_hdr_os_copy)
663 == IH_TYPE_MULTI)
664 puts("WARNING: legacy format multi component image overwritten\n");
665 return BOOTM_ERR_OVERLAP;
666 } else {
667 puts("ERROR: new format image overwritten - must RESET the board to recover\n");
668 bootstage_error(BOOTSTAGE_ID_OVERWRITTEN);
669 return BOOTM_ERR_RESET;
670 }
Bo Lv4a465022023-02-28 05:51:47 +0000671#endif
Simon Glassb6396402014-06-12 07:24:46 -0600672 }
673
Tom Rinicc955352018-05-01 12:32:37 -0400674 lmb_reserve(&images->lmb, images->os.load, (load_end -
675 images->os.load));
Simon Glassb6396402014-06-12 07:24:46 -0600676 return 0;
677}
678
679/**
680 * bootm_disable_interrupts() - Disable interrupts in preparation for load/boot
681 *
Heinrich Schuchardt185f8122022-01-19 18:05:50 +0100682 * Return: interrupt flag (0 if interrupts were disabled, non-zero if they were
Simon Glassb6396402014-06-12 07:24:46 -0600683 * enabled)
684 */
685ulong bootm_disable_interrupts(void)
686{
687 ulong iflag;
688
689 /*
690 * We have reached the point of no return: we are going to
691 * overwrite all exception vector code, so we cannot easily
692 * recover from any failures any more...
693 */
694 iflag = disable_interrupts();
695#ifdef CONFIG_NETCONSOLE
696 /* Stop the ethernet stack if NetConsole could have left it up */
697 eth_halt();
Bernhard Nortmann4917c062015-09-14 15:29:45 +0200698# ifndef CONFIG_DM_ETH
Simon Glassb6396402014-06-12 07:24:46 -0600699 eth_unregister(eth_get_dev());
Bernhard Nortmann4917c062015-09-14 15:29:45 +0200700# endif
Simon Glassb6396402014-06-12 07:24:46 -0600701#endif
702
703#if defined(CONFIG_CMD_USB)
704 /*
705 * turn off USB to prevent the host controller from writing to the
706 * SDRAM while Linux is booting. This could happen (at least for OHCI
707 * controller), because the HCCA (Host Controller Communication Area)
708 * lies within the SDRAM and the host controller writes continously to
709 * this area (as busmaster!). The HccaFrameNumber is for example
710 * updated every 1 ms within the HCCA structure in SDRAM! For more
711 * details see the OpenHCI specification.
712 */
713 usb_stop();
714#endif
715 return iflag;
716}
717
Simon Glass6cd92b12020-11-05 10:33:42 -0700718#define CONSOLE_ARG "console="
Sean Andersonba9aa402022-05-19 18:26:05 -0400719#define NULL_CONSOLE (CONSOLE_ARG "ttynull")
720#define CONSOLE_ARG_SIZE sizeof(NULL_CONSOLE)
Simon Glassb6396402014-06-12 07:24:46 -0600721
Simon Glassb6386f32020-11-05 10:33:43 -0700722/**
723 * fixup_silent_linux() - Handle silencing the linux boot if required
724 *
725 * This uses the silent_linux envvar to control whether to add/set a "console="
726 * parameter to the command line
727 *
728 * @buf: Buffer containing the string to process
729 * @maxlen: Maximum length of buffer
Heinrich Schuchardt185f8122022-01-19 18:05:50 +0100730 * Return: 0 if OK, -ENOSPC if @maxlen is too small
Simon Glassb6386f32020-11-05 10:33:43 -0700731 */
732static int fixup_silent_linux(char *buf, int maxlen)
Simon Glassb6396402014-06-12 07:24:46 -0600733{
Simon Glassb6396402014-06-12 07:24:46 -0600734 int want_silent;
Simon Glassb6386f32020-11-05 10:33:43 -0700735 char *cmdline;
736 int size;
Simon Glassb6396402014-06-12 07:24:46 -0600737
Simon Glassb6386f32020-11-05 10:33:43 -0700738 /*
739 * Move the input string to the end of buffer. The output string will be
740 * built up at the start.
741 */
742 size = strlen(buf) + 1;
743 if (size * 2 > maxlen)
744 return -ENOSPC;
745 cmdline = buf + maxlen - size;
746 memmove(cmdline, buf, size);
Simon Glassb6396402014-06-12 07:24:46 -0600747 /*
748 * Only fix cmdline when requested. The environment variable can be:
749 *
750 * no - we never fixup
751 * yes - we always fixup
752 * unset - we rely on the console silent flag
753 */
Simon Glassbfebc8c2017-08-03 12:22:13 -0600754 want_silent = env_get_yesno("silent_linux");
Simon Glassb6396402014-06-12 07:24:46 -0600755 if (want_silent == 0)
Simon Glass4ae42642020-11-05 10:33:39 -0700756 return 0;
Simon Glassb6396402014-06-12 07:24:46 -0600757 else if (want_silent == -1 && !(gd->flags & GD_FLG_SILENT))
Simon Glass4ae42642020-11-05 10:33:39 -0700758 return 0;
Simon Glassb6396402014-06-12 07:24:46 -0600759
760 debug("before silent fix-up: %s\n", cmdline);
Simon Glassb6386f32020-11-05 10:33:43 -0700761 if (*cmdline) {
Simon Glassb6396402014-06-12 07:24:46 -0600762 char *start = strstr(cmdline, CONSOLE_ARG);
763
Simon Glassb6386f32020-11-05 10:33:43 -0700764 /* Check space for maximum possible new command line */
765 if (size + CONSOLE_ARG_SIZE > maxlen)
Simon Glass4ae42642020-11-05 10:33:39 -0700766 return -ENOSPC;
Simon Glassb6396402014-06-12 07:24:46 -0600767
768 if (start) {
769 char *end = strchr(start, ' ');
Simon Glass6cd92b12020-11-05 10:33:42 -0700770 int start_bytes;
Simon Glassb6396402014-06-12 07:24:46 -0600771
Sean Andersonba9aa402022-05-19 18:26:05 -0400772 start_bytes = start - cmdline;
Simon Glass6cd92b12020-11-05 10:33:42 -0700773 strncpy(buf, cmdline, start_bytes);
Sean Andersonba9aa402022-05-19 18:26:05 -0400774 strncpy(buf + start_bytes, NULL_CONSOLE, CONSOLE_ARG_SIZE);
Simon Glassb6396402014-06-12 07:24:46 -0600775 if (end)
Sean Andersonba9aa402022-05-19 18:26:05 -0400776 strcpy(buf + start_bytes + CONSOLE_ARG_SIZE - 1, end);
Simon Glassb6396402014-06-12 07:24:46 -0600777 else
Sean Andersonba9aa402022-05-19 18:26:05 -0400778 buf[start_bytes + CONSOLE_ARG_SIZE] = '\0';
Simon Glassb6396402014-06-12 07:24:46 -0600779 } else {
Sean Andersonba9aa402022-05-19 18:26:05 -0400780 sprintf(buf, "%s %s", cmdline, NULL_CONSOLE);
Simon Glassb6396402014-06-12 07:24:46 -0600781 }
Simon Glassb6386f32020-11-05 10:33:43 -0700782 if (buf + strlen(buf) >= cmdline)
783 return -ENOSPC;
Simon Glassb6396402014-06-12 07:24:46 -0600784 } else {
Sean Andersonba9aa402022-05-19 18:26:05 -0400785 if (maxlen < CONSOLE_ARG_SIZE)
Simon Glassb6386f32020-11-05 10:33:43 -0700786 return -ENOSPC;
Sean Andersonba9aa402022-05-19 18:26:05 -0400787 strcpy(buf, NULL_CONSOLE);
Simon Glassb6396402014-06-12 07:24:46 -0600788 }
Simon Glassb6386f32020-11-05 10:33:43 -0700789 debug("after silent fix-up: %s\n", buf);
Simon Glassb6396402014-06-12 07:24:46 -0600790
Simon Glassb6386f32020-11-05 10:33:43 -0700791 return 0;
792}
793
Simon Glass51bb3382020-11-05 10:33:48 -0700794/**
795 * process_subst() - Handle substitution of ${...} fields in the environment
796 *
797 * Handle variable substitution in the provided buffer
798 *
799 * @buf: Buffer containing the string to process
800 * @maxlen: Maximum length of buffer
Heinrich Schuchardt185f8122022-01-19 18:05:50 +0100801 * Return: 0 if OK, -ENOSPC if @maxlen is too small
Simon Glass51bb3382020-11-05 10:33:48 -0700802 */
803static int process_subst(char *buf, int maxlen)
804{
805 char *cmdline;
806 int size;
807 int ret;
808
809 /* Move to end of buffer */
810 size = strlen(buf) + 1;
811 cmdline = buf + maxlen - size;
812 if (buf + size > cmdline)
813 return -ENOSPC;
814 memmove(cmdline, buf, size);
815
816 ret = cli_simple_process_macros(cmdline, buf, cmdline - buf);
817
818 return ret;
819}
820
Simon Glass4448fe82020-11-05 10:33:45 -0700821int bootm_process_cmdline(char *buf, int maxlen, int flags)
822{
823 int ret;
824
825 /* Check config first to enable compiler to eliminate code */
826 if (IS_ENABLED(CONFIG_SILENT_CONSOLE) &&
827 !IS_ENABLED(CONFIG_SILENT_U_BOOT_ONLY) &&
Bo Lvaa183f82023-07-29 13:30:00 +0800828 (flags & BOOTM_CL_SILENT) &&
829 !IS_ENABLED(CONFIG_AMLOGIC_MODIFY)) {
Simon Glass4448fe82020-11-05 10:33:45 -0700830 ret = fixup_silent_linux(buf, maxlen);
831 if (ret)
832 return log_msg_ret("silent", ret);
833 }
Simon Glassa8d69622021-03-15 18:11:23 +1300834 if (IS_ENABLED(CONFIG_BOOTARGS_SUBST) && IS_ENABLED(CONFIG_CMDLINE) &&
835 (flags & BOOTM_CL_SUBST)) {
Simon Glass51bb3382020-11-05 10:33:48 -0700836 ret = process_subst(buf, maxlen);
837 if (ret)
Simon Glass185756e2021-02-06 09:57:35 -0700838 return log_msg_ret("subst", ret);
Simon Glass51bb3382020-11-05 10:33:48 -0700839 }
Simon Glass4448fe82020-11-05 10:33:45 -0700840
841 return 0;
842}
843
Simon Glassb3c01672020-11-05 10:33:44 -0700844int bootm_process_cmdline_env(int flags)
Simon Glassb6386f32020-11-05 10:33:43 -0700845{
846 const int maxlen = MAX_CMDLINE_SIZE;
Simon Glassb3c01672020-11-05 10:33:44 -0700847 bool do_silent;
Simon Glassb6386f32020-11-05 10:33:43 -0700848 const char *env;
849 char *buf;
850 int ret;
851
852 /* First check if any action is needed */
853 do_silent = IS_ENABLED(CONFIG_SILENT_CONSOLE) &&
Simon Glassb3c01672020-11-05 10:33:44 -0700854 !IS_ENABLED(CONFIG_SILENT_U_BOOT_ONLY) && (flags & BOOTM_CL_SILENT);
Simon Glass51bb3382020-11-05 10:33:48 -0700855 if (!do_silent && !IS_ENABLED(CONFIG_BOOTARGS_SUBST))
Simon Glassb6386f32020-11-05 10:33:43 -0700856 return 0;
857
858 env = env_get("bootargs");
859 if (env && strlen(env) >= maxlen)
860 return -E2BIG;
861 buf = malloc(maxlen);
862 if (!buf)
863 return -ENOMEM;
864 if (env)
865 strcpy(buf, env);
866 else
867 *buf = '\0';
Simon Glass4448fe82020-11-05 10:33:45 -0700868 ret = bootm_process_cmdline(buf, maxlen, flags);
Simon Glassb6386f32020-11-05 10:33:43 -0700869 if (!ret) {
870 ret = env_set("bootargs", buf);
871
872 /*
873 * If buf is "" and bootargs does not exist, this will produce
874 * an error trying to delete bootargs. Ignore it
875 */
876 if (ret == -ENOENT)
877 ret = 0;
878 }
Simon Glassb6396402014-06-12 07:24:46 -0600879 free(buf);
Simon Glassb6386f32020-11-05 10:33:43 -0700880 if (ret)
881 return log_msg_ret("env", ret);
Simon Glass4ae42642020-11-05 10:33:39 -0700882
883 return 0;
Simon Glassb6396402014-06-12 07:24:46 -0600884}
Simon Glassb6396402014-06-12 07:24:46 -0600885
886/**
887 * Execute selected states of the bootm command.
888 *
889 * Note the arguments to this state must be the first argument, Any 'bootm'
890 * or sub-command arguments must have already been taken.
891 *
892 * Note that if states contains more than one flag it MUST contain
893 * BOOTM_STATE_START, since this handles and consumes the command line args.
894 *
895 * Also note that aside from boot_os_fn functions and bootm_load_os no other
896 * functions we store the return value of in 'ret' may use a negative return
897 * value, without special handling.
898 *
899 * @param cmdtp Pointer to bootm command table entry
900 * @param flag Command flags (CMD_FLAG_...)
901 * @param argc Number of subcommand arguments (0 = no arguments)
902 * @param argv Arguments
903 * @param states Mask containing states to run (BOOTM_STATE_...)
904 * @param images Image header information
905 * @param boot_progress 1 to show boot progress, 0 to not do this
Heinrich Schuchardt185f8122022-01-19 18:05:50 +0100906 * Return: 0 if ok, something else on error. Some errors will cause this
Simon Glassb6396402014-06-12 07:24:46 -0600907 * function to perform a reboot! If states contains BOOTM_STATE_OS_GO
908 * then the intent is to boot an OS, so this function will not return
909 * unless the image type is standalone.
910 */
Simon Glass09140112020-05-10 11:40:03 -0600911int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc,
Simon Glassd9d7c202022-09-06 20:26:50 -0600912 char *const argv[], int states, struct bootm_headers *images,
Simon Glass09140112020-05-10 11:40:03 -0600913 int boot_progress)
Simon Glassb6396402014-06-12 07:24:46 -0600914{
915 boot_os_fn *boot_fn;
916 ulong iflag = 0;
917 int ret = 0, need_boot_fn;
918
919 images->state |= states;
920
921 /*
922 * Work through the states and see how far we get. We stop on
923 * any error.
924 */
925 if (states & BOOTM_STATE_START)
926 ret = bootm_start(cmdtp, flag, argc, argv);
927
Philippe Reynes9d46e632022-03-28 22:57:00 +0200928 if (!ret && (states & BOOTM_STATE_PRE_LOAD))
929 ret = bootm_pre_load(cmdtp, flag, argc, argv);
930
Simon Glassb6396402014-06-12 07:24:46 -0600931 if (!ret && (states & BOOTM_STATE_FINDOS))
932 ret = bootm_find_os(cmdtp, flag, argc, argv);
933
Zubair Lutfullah Kakakhelba079842016-09-09 09:18:58 +0100934 if (!ret && (states & BOOTM_STATE_FINDOTHER))
Simon Glassb6396402014-06-12 07:24:46 -0600935 ret = bootm_find_other(cmdtp, flag, argc, argv);
Simon Glassb6396402014-06-12 07:24:46 -0600936
dongqing.li994a05e2023-10-17 09:19:27 +0800937#if defined(CONFIG_MDUMP_COMPRESS) || \
938 ((defined CONFIG_SUPPORT_BL33Z) && \
939 (defined CONFIG_FULL_RAMDUMP))
940 extern void check_ramdump(void);
941 check_ramdump();
942#endif
943
Simon Glassb6396402014-06-12 07:24:46 -0600944 /* Load the OS */
945 if (!ret && (states & BOOTM_STATE_LOADOS)) {
Simon Glassb6396402014-06-12 07:24:46 -0600946 iflag = bootm_disable_interrupts();
Tom Rinicc955352018-05-01 12:32:37 -0400947 ret = bootm_load_os(images, 0);
948 if (ret && ret != BOOTM_ERR_OVERLAP)
Simon Glassb6396402014-06-12 07:24:46 -0600949 goto err;
950 else if (ret == BOOTM_ERR_OVERLAP)
951 ret = 0;
Simon Glassb6396402014-06-12 07:24:46 -0600952 }
953
954 /* Relocate the ramdisk */
955#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
956 if (!ret && (states & BOOTM_STATE_RAMDISK)) {
957 ulong rd_len = images->rd_end - images->rd_start;
958
959 ret = boot_ramdisk_high(&images->lmb, images->rd_start,
960 rd_len, &images->initrd_start, &images->initrd_end);
961 if (!ret) {
Simon Glass018f5302017-08-03 12:22:10 -0600962 env_set_hex("initrd_start", images->initrd_start);
963 env_set_hex("initrd_end", images->initrd_end);
Simon Glassb6396402014-06-12 07:24:46 -0600964 }
965 }
966#endif
Simon Glass0c303f92021-09-25 19:43:21 -0600967#if CONFIG_IS_ENABLED(OF_LIBFDT) && defined(CONFIG_LMB)
Simon Glassb6396402014-06-12 07:24:46 -0600968 if (!ret && (states & BOOTM_STATE_FDT)) {
969 boot_fdt_add_mem_rsv_regions(&images->lmb, images->ft_addr);
970 ret = boot_relocate_fdt(&images->lmb, &images->ft_addr,
971 &images->ft_len);
972 }
973#endif
974
Hangyu Lif6740182023-03-27 15:45:23 +0800975#ifdef CONFIG_AMLOGIC_MODIFY
976 /* Check reserved memory region */
977#ifdef CONFIG_CMD_RSVMEM
978 ret = run_command("rsvmem check", 0);
979 if (ret) {
980 puts("rsvmem check failed\n");
981 return ret;
982 }
983#endif
984#endif
985
Simon Glassb6396402014-06-12 07:24:46 -0600986 /* From now on, we need the OS boot function */
987 if (ret)
988 return ret;
989 boot_fn = bootm_os_get_boot_func(images->os.os);
990 need_boot_fn = states & (BOOTM_STATE_OS_CMDLINE |
991 BOOTM_STATE_OS_BD_T | BOOTM_STATE_OS_PREP |
992 BOOTM_STATE_OS_FAKE_GO | BOOTM_STATE_OS_GO);
993 if (boot_fn == NULL && need_boot_fn) {
994 if (iflag)
995 enable_interrupts();
996 printf("ERROR: booting os '%s' (%d) is not supported\n",
997 genimg_get_os_name(images->os.os), images->os.os);
998 bootstage_error(BOOTSTAGE_ID_CHECK_BOOT_OS);
999 return 1;
1000 }
1001
Hector Palacios19e86492016-07-11 12:34:37 +02001002
Simon Glassb6396402014-06-12 07:24:46 -06001003 /* Call various other states that are not generally used */
1004 if (!ret && (states & BOOTM_STATE_OS_CMDLINE))
1005 ret = boot_fn(BOOTM_STATE_OS_CMDLINE, argc, argv, images);
1006 if (!ret && (states & BOOTM_STATE_OS_BD_T))
1007 ret = boot_fn(BOOTM_STATE_OS_BD_T, argc, argv, images);
Hector Palacios19e86492016-07-11 12:34:37 +02001008 if (!ret && (states & BOOTM_STATE_OS_PREP)) {
Simon Glass51bb3382020-11-05 10:33:48 -07001009 ret = bootm_process_cmdline_env(images->os.os == IH_OS_LINUX);
Simon Glassd9477a02020-11-05 10:33:41 -07001010 if (ret) {
1011 printf("Cmdline setup failed (err=%d)\n", ret);
1012 ret = CMD_RET_FAILURE;
1013 goto err;
Simon Glass4ae42642020-11-05 10:33:39 -07001014 }
Simon Glassb6396402014-06-12 07:24:46 -06001015 ret = boot_fn(BOOTM_STATE_OS_PREP, argc, argv, images);
Hector Palacios19e86492016-07-11 12:34:37 +02001016 }
Simon Glassb6396402014-06-12 07:24:46 -06001017
1018#ifdef CONFIG_TRACE
1019 /* Pretend to run the OS, then run a user command */
1020 if (!ret && (states & BOOTM_STATE_OS_FAKE_GO)) {
Simon Glass00caae62017-08-03 12:22:12 -06001021 char *cmd_list = env_get("fakegocmd");
Simon Glassb6396402014-06-12 07:24:46 -06001022
1023 ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_FAKE_GO,
1024 images, boot_fn);
1025 if (!ret && cmd_list)
1026 ret = run_command_list(cmd_list, -1, flag);
1027 }
1028#endif
1029
1030 /* Check for unsupported subcommand. */
1031 if (ret) {
Simon Glass13819f02022-10-11 09:47:07 -06001032 printf("subcommand failed (err=%d)\n", ret);
Simon Glassb6396402014-06-12 07:24:46 -06001033 return ret;
1034 }
1035
1036 /* Now run the OS! We hope this doesn't return */
1037 if (!ret && (states & BOOTM_STATE_OS_GO))
1038 ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_GO,
1039 images, boot_fn);
1040
1041 /* Deal with any fallout */
1042err:
1043 if (iflag)
1044 enable_interrupts();
1045
1046 if (ret == BOOTM_ERR_UNIMPLEMENTED)
1047 bootstage_error(BOOTSTAGE_ID_DECOMP_UNIMPL);
1048 else if (ret == BOOTM_ERR_RESET)
1049 do_reset(cmdtp, flag, argc, argv);
1050
1051 return ret;
1052}
1053
Tom Rinic76c93a2019-05-23 07:14:07 -04001054#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)
Simon Glassb6396402014-06-12 07:24:46 -06001055/**
1056 * image_get_kernel - verify legacy format kernel image
1057 * @img_addr: in RAM address of the legacy format image to be verified
1058 * @verify: data CRC verification flag
1059 *
1060 * image_get_kernel() verifies legacy image integrity and returns pointer to
1061 * legacy image header if image verification was completed successfully.
1062 *
1063 * returns:
1064 * pointer to a legacy image header if valid image was found
1065 * otherwise return NULL
1066 */
Simon Glassf3543e62022-09-06 20:26:52 -06001067static struct legacy_img_hdr *image_get_kernel(ulong img_addr, int verify)
Simon Glassb6396402014-06-12 07:24:46 -06001068{
Simon Glassf3543e62022-09-06 20:26:52 -06001069 struct legacy_img_hdr *hdr = (struct legacy_img_hdr *)img_addr;
Simon Glassb6396402014-06-12 07:24:46 -06001070
1071 if (!image_check_magic(hdr)) {
1072 puts("Bad Magic Number\n");
1073 bootstage_error(BOOTSTAGE_ID_CHECK_MAGIC);
1074 return NULL;
1075 }
1076 bootstage_mark(BOOTSTAGE_ID_CHECK_HEADER);
1077
1078 if (!image_check_hcrc(hdr)) {
1079 puts("Bad Header Checksum\n");
1080 bootstage_error(BOOTSTAGE_ID_CHECK_HEADER);
1081 return NULL;
1082 }
1083
1084 bootstage_mark(BOOTSTAGE_ID_CHECK_CHECKSUM);
1085 image_print_contents(hdr);
1086
1087 if (verify) {
1088 puts(" Verifying Checksum ... ");
1089 if (!image_check_dcrc(hdr)) {
1090 printf("Bad Data CRC\n");
1091 bootstage_error(BOOTSTAGE_ID_CHECK_CHECKSUM);
1092 return NULL;
1093 }
1094 puts("OK\n");
1095 }
1096 bootstage_mark(BOOTSTAGE_ID_CHECK_ARCH);
1097
1098 if (!image_check_target_arch(hdr)) {
1099 printf("Unsupported Architecture 0x%x\n", image_get_arch(hdr));
1100 bootstage_error(BOOTSTAGE_ID_CHECK_ARCH);
1101 return NULL;
1102 }
1103 return hdr;
1104}
1105#endif
1106
1107/**
1108 * boot_get_kernel - find kernel image
1109 * @os_data: pointer to a ulong variable, will hold os data start address
1110 * @os_len: pointer to a ulong variable, will hold os data length
1111 *
1112 * boot_get_kernel() tries to find a kernel image, verifies its integrity
1113 * and locates kernel data.
1114 *
1115 * returns:
1116 * pointer to image header if valid image was found, plus kernel start
1117 * address and length, otherwise NULL
1118 */
Simon Glass09140112020-05-10 11:40:03 -06001119static const void *boot_get_kernel(struct cmd_tbl *cmdtp, int flag, int argc,
Simon Glassd9d7c202022-09-06 20:26:50 -06001120 char *const argv[], struct bootm_headers *images,
Simon Glassb6396402014-06-12 07:24:46 -06001121 ulong *os_data, ulong *os_len)
1122{
Tom Rinic76c93a2019-05-23 07:14:07 -04001123#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)
Simon Glassf3543e62022-09-06 20:26:52 -06001124 struct legacy_img_hdr *hdr;
Simon Glassb6396402014-06-12 07:24:46 -06001125#endif
1126 ulong img_addr;
1127 const void *buf;
Simon Glassb6396402014-06-12 07:24:46 -06001128 const char *fit_uname_config = NULL;
1129 const char *fit_uname_kernel = NULL;
Simon Glassbf371b42021-09-25 19:43:20 -06001130#if CONFIG_IS_ENABLED(FIT)
Simon Glassb6396402014-06-12 07:24:46 -06001131 int os_noffset;
1132#endif
1133
Bo Lv4a465022023-02-28 05:51:47 +00001134#ifdef CONFIG_AMLOGIC_MODIFY
1135 char *avb_s;
1136 avb_s = env_get("avb2");
Bo Lva1bffde2023-08-16 21:04:03 +08001137 if (avb_s)
1138 printf("avb2: %s\n", avb_s);
1139 if (avb_s && strcmp(avb_s, "1") != 0) {
Bo Lv4a465022023-02-28 05:51:47 +00001140#ifdef CONFIG_AML_ANTIROLLBACK
1141 boot_img_hdr_t **tmp_img_hdr = (boot_img_hdr_t **)&buf;
1142#endif
1143 }
1144#endif
1145
Bryan Wue6c88a62014-08-15 16:51:39 -07001146 img_addr = genimg_get_kernel_addr_fit(argc < 1 ? NULL : argv[0],
1147 &fit_uname_config,
1148 &fit_uname_kernel);
Simon Glassb6396402014-06-12 07:24:46 -06001149
Philippe Reynes9d46e632022-03-28 22:57:00 +02001150 if (CONFIG_IS_ENABLED(CMD_BOOTM_PRE_LOAD))
1151 img_addr += image_load_offset;
1152
Simon Glassb6396402014-06-12 07:24:46 -06001153 bootstage_mark(BOOTSTAGE_ID_CHECK_MAGIC);
1154
Simon Glassb6396402014-06-12 07:24:46 -06001155 /* check image type, for FIT images get FIT kernel node */
1156 *os_data = *os_len = 0;
1157 buf = map_sysmem(img_addr, 0);
1158 switch (genimg_get_format(buf)) {
Tom Rinic76c93a2019-05-23 07:14:07 -04001159#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)
Simon Glassb6396402014-06-12 07:24:46 -06001160 case IMAGE_FORMAT_LEGACY:
1161 printf("## Booting kernel from Legacy Image at %08lx ...\n",
1162 img_addr);
1163 hdr = image_get_kernel(img_addr, images->verify);
1164 if (!hdr)
1165 return NULL;
1166 bootstage_mark(BOOTSTAGE_ID_CHECK_IMAGETYPE);
1167
1168 /* get os_data and os_len */
1169 switch (image_get_type(hdr)) {
1170 case IH_TYPE_KERNEL:
1171 case IH_TYPE_KERNEL_NOLOAD:
1172 *os_data = image_get_data(hdr);
1173 *os_len = image_get_data_size(hdr);
1174 break;
1175 case IH_TYPE_MULTI:
1176 image_multi_getimg(hdr, 0, os_data, os_len);
1177 break;
1178 case IH_TYPE_STANDALONE:
1179 *os_data = image_get_data(hdr);
1180 *os_len = image_get_data_size(hdr);
1181 break;
1182 default:
1183 printf("Wrong Image Type for %s command\n",
1184 cmdtp->name);
1185 bootstage_error(BOOTSTAGE_ID_CHECK_IMAGETYPE);
1186 return NULL;
1187 }
1188
1189 /*
1190 * copy image header to allow for image overwrites during
1191 * kernel decompression.
1192 */
1193 memmove(&images->legacy_hdr_os_copy, hdr,
Simon Glassf3543e62022-09-06 20:26:52 -06001194 sizeof(struct legacy_img_hdr));
Simon Glassb6396402014-06-12 07:24:46 -06001195
1196 /* save pointer to image header */
1197 images->legacy_hdr_os = hdr;
1198
1199 images->legacy_hdr_valid = 1;
1200 bootstage_mark(BOOTSTAGE_ID_DECOMP_IMAGE);
1201 break;
1202#endif
Simon Glassbf371b42021-09-25 19:43:20 -06001203#if CONFIG_IS_ENABLED(FIT)
Simon Glassb6396402014-06-12 07:24:46 -06001204 case IMAGE_FORMAT_FIT:
Simon Glass126cc862014-06-12 07:24:47 -06001205 os_noffset = fit_image_load(images, img_addr,
Simon Glassb6396402014-06-12 07:24:46 -06001206 &fit_uname_kernel, &fit_uname_config,
1207 IH_ARCH_DEFAULT, IH_TYPE_KERNEL,
1208 BOOTSTAGE_ID_FIT_KERNEL_START,
1209 FIT_LOAD_IGNORED, os_data, os_len);
1210 if (os_noffset < 0)
1211 return NULL;
1212
1213 images->fit_hdr_os = map_sysmem(img_addr, 0);
1214 images->fit_uname_os = fit_uname_kernel;
1215 images->fit_uname_cfg = fit_uname_config;
1216 images->fit_noffset_os = os_noffset;
1217 break;
1218#endif
1219#ifdef CONFIG_ANDROID_BOOT_IMAGE
1220 case IMAGE_FORMAT_ANDROID:
1221 printf("## Booting Android Image at 0x%08lx ...\n", img_addr);
Bo Lv4a465022023-02-28 05:51:47 +00001222
1223#ifndef CONFIG_AMLOGIC_MODIFY
Simon Glass07c0cd72014-06-12 07:24:48 -06001224 if (android_image_get_kernel(buf, images->verify,
Simon Glassb6396402014-06-12 07:24:46 -06001225 os_data, os_len))
1226 return NULL;
Bo Lv4a465022023-02-28 05:51:47 +00001227#else
1228 if (!android_image_need_move(&img_addr, buf))
1229 buf = map_sysmem(img_addr, 0);
1230 else
1231 return NULL;
1232 if (android_image_get_kernel(buf, images->verify,
1233 os_data, os_len))
1234 return NULL;
1235
Bo Lva1bffde2023-08-16 21:04:03 +08001236 if (avb_s && strcmp(avb_s, "1") != 0) {
Bo Lv4a465022023-02-28 05:51:47 +00001237#ifdef CONFIG_AML_ANTIROLLBACK
1238 if (!check_antirollback((*tmp_img_hdr)->kernel_version)) {
1239 *os_len = 0;
1240 return NULL;
1241 }
1242#endif
1243 }
1244#endif
Simon Glassb6396402014-06-12 07:24:46 -06001245 break;
1246#endif
1247 default:
1248 printf("Wrong Image Format for %s command\n", cmdtp->name);
1249 bootstage_error(BOOTSTAGE_ID_FIT_KERNEL_INFO);
1250 return NULL;
1251 }
1252
1253 debug(" kernel data at 0x%08lx, len = 0x%08lx (%ld)\n",
1254 *os_data, *os_len, *os_len);
1255
1256 return buf;
1257}
Heinrich Schuchardtf6c6df72019-01-08 18:13:06 +01001258
1259/**
1260 * switch_to_non_secure_mode() - switch to non-secure mode
1261 *
1262 * This routine is overridden by architectures requiring this feature.
1263 */
1264void __weak switch_to_non_secure_mode(void)
1265{
1266}
1267
Simon Glassce1400f2014-06-12 07:24:53 -06001268#else /* USE_HOSTCC */
1269
Fabrice Fontaine93e07882019-05-03 22:37:05 +02001270#if defined(CONFIG_FIT_SIGNATURE)
Simon Glass8a9d0372020-03-18 11:44:02 -06001271static int bootm_host_load_image(const void *fit, int req_image_type,
1272 int cfg_noffset)
Simon Glassce1400f2014-06-12 07:24:53 -06001273{
1274 const char *fit_uname_config = NULL;
1275 ulong data, len;
Simon Glassd9d7c202022-09-06 20:26:50 -06001276 struct bootm_headers images;
Simon Glassce1400f2014-06-12 07:24:53 -06001277 int noffset;
Tom Rinic45568c2022-06-25 19:29:46 -04001278 ulong load_end, buf_size;
Simon Glassce1400f2014-06-12 07:24:53 -06001279 uint8_t image_type;
Daniel Golle0cd57f22022-08-27 04:14:42 +01001280 uint8_t image_comp;
Simon Glassce1400f2014-06-12 07:24:53 -06001281 void *load_buf;
1282 int ret;
1283
Simon Glass8a9d0372020-03-18 11:44:02 -06001284 fit_uname_config = fdt_get_name(fit, cfg_noffset, NULL);
Simon Glassce1400f2014-06-12 07:24:53 -06001285 memset(&images, '\0', sizeof(images));
1286 images.verify = 1;
1287 noffset = fit_image_load(&images, (ulong)fit,
1288 NULL, &fit_uname_config,
1289 IH_ARCH_DEFAULT, req_image_type, -1,
1290 FIT_LOAD_IGNORED, &data, &len);
1291 if (noffset < 0)
1292 return noffset;
1293 if (fit_image_get_type(fit, noffset, &image_type)) {
1294 puts("Can't get image type!\n");
1295 return -EINVAL;
1296 }
1297
Daniel Golle88de6c52022-08-27 04:17:28 +01001298 if (fit_image_get_comp(fit, noffset, &image_comp))
1299 image_comp = IH_COMP_NONE;
Simon Glassce1400f2014-06-12 07:24:53 -06001300
1301 /* Allow the image to expand by a factor of 4, should be safe */
Tom Rinic45568c2022-06-25 19:29:46 -04001302 buf_size = (1 << 20) + len * 4;
1303 load_buf = malloc(buf_size);
Daniel Golle0cd57f22022-08-27 04:14:42 +01001304 ret = image_decomp(image_comp, 0, data, image_type, load_buf,
Tom Rinic45568c2022-06-25 19:29:46 -04001305 (void *)data, len, buf_size, &load_end);
Simon Glassce1400f2014-06-12 07:24:53 -06001306 free(load_buf);
Simon Glass081cc192014-12-02 13:17:33 -07001307
Julius Werner20908542019-07-24 19:37:54 -07001308 if (ret) {
Daniel Golle0cd57f22022-08-27 04:14:42 +01001309 ret = handle_decomp_error(image_comp, load_end - 0, buf_size, ret);
Julius Werner20908542019-07-24 19:37:54 -07001310 if (ret != BOOTM_ERR_UNIMPLEMENTED)
1311 return ret;
1312 }
Simon Glassce1400f2014-06-12 07:24:53 -06001313
1314 return 0;
1315}
1316
1317int bootm_host_load_images(const void *fit, int cfg_noffset)
1318{
1319 static uint8_t image_types[] = {
1320 IH_TYPE_KERNEL,
1321 IH_TYPE_FLATDT,
1322 IH_TYPE_RAMDISK,
1323 };
1324 int err = 0;
1325 int i;
1326
1327 for (i = 0; i < ARRAY_SIZE(image_types); i++) {
1328 int ret;
1329
Simon Glass8a9d0372020-03-18 11:44:02 -06001330 ret = bootm_host_load_image(fit, image_types[i], cfg_noffset);
Simon Glassce1400f2014-06-12 07:24:53 -06001331 if (!err && ret && ret != -ENOENT)
1332 err = ret;
1333 }
1334
1335 /* Return the first error we found */
1336 return err;
1337}
Fabrice Fontaine93e07882019-05-03 22:37:05 +02001338#endif
Simon Glassea51a622014-06-12 07:24:51 -06001339
1340#endif /* ndef USE_HOSTCC */