blob: b98817727115b3d7af210aaa5b7719e25ec2ce9d [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
wdenk47d1a6e2002-11-03 00:01:44 +00002/*
Detlev Zundelca95c9d2009-07-13 16:01:18 +02003 * (C) Copyright 2000-2009
wdenk47d1a6e2002-11-03 00:01:44 +00004 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
wdenk47d1a6e2002-11-03 00:01:44 +00005 */
6
7/*
8 * Boot support
9 */
10#include <common.h>
Simon Glassb6396402014-06-12 07:24:46 -060011#include <bootm.h>
wdenk47d1a6e2002-11-03 00:01:44 +000012#include <command.h>
Simon Glass7b51b572019-08-01 09:46:52 -060013#include <env.h>
Simon Glass90268b82014-10-19 21:11:24 -060014#include <errno.h>
Simon Glassb6396402014-06-12 07:24:46 -060015#include <image.h>
Simon Glassb6396402014-06-12 07:24:46 -060016#include <malloc.h>
17#include <nand.h>
wdenk47d1a6e2002-11-03 00:01:44 +000018#include <asm/byteorder.h>
Simon Glass401d1c42020-10-30 21:38:53 -060019#include <asm/global_data.h>
Simon Glassb6396402014-06-12 07:24:46 -060020#include <linux/ctype.h>
21#include <linux/err.h>
22#include <u-boot/zlib.h>
Philippe Reynesae0d12f2019-12-02 15:45:50 +010023#include <mapmem.h>
Mingyen Hung6e468002023-01-04 23:43:04 -080024#include <amlogic/libavb/libavb.h>
25#include <amlogic/partition_table.h>
26#if CONFIG_IS_ENABLED(AML_ANTIROLLBACK) || CONFIG_IS_ENABLED(AML_AVB2_ANTIROLLBACK)
27#include <amlogic/anti-rollback.h>
28#endif
Zhongfu Luo04a29ff2023-07-31 15:53:00 +080029#include <amlogic/aml_efuse.h>
30#include <version.h>
31#include <amlogic/image_check.h>
32#include <asm/amlogic/arch/bl31_apis.h>
Mingyen Hung6e468002023-01-04 23:43:04 -080033#include <amlogic/aml_rollback.h>
Peter Korsgaard20dde482009-11-19 11:37:51 +010034
Marian Balakowicz1ee11802008-01-08 18:17:10 +010035DECLARE_GLOBAL_DATA_PTR;
36
Jon Loeligerbaa26db2007-07-08 17:51:39 -050037#if defined(CONFIG_CMD_IMI)
Stephen Warren712fbcf2011-10-18 11:11:49 +000038static int image_info(unsigned long addr);
wdenk47d1a6e2002-11-03 00:01:44 +000039#endif
wdenk27b207f2003-07-24 23:38:38 +000040
Jon Loeligerbaa26db2007-07-08 17:51:39 -050041#if defined(CONFIG_CMD_IMLS)
wdenk27b207f2003-07-24 23:38:38 +000042#include <flash.h>
Stefan Roeseca5def32010-08-31 10:00:10 +020043#include <mtd/cfi_flash.h>
Vipin Kumar8fdf1e02012-12-16 22:32:48 +000044#endif
45
46#if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND)
Simon Glass09140112020-05-10 11:40:03 -060047static int do_imls(struct cmd_tbl *cmdtp, int flag, int argc,
48 char *const argv[]);
wdenk27b207f2003-07-24 23:38:38 +000049#endif
50
Kumar Gala49c3a862008-10-21 17:25:45 -050051/* we overload the cmd field with our state machine info instead of a
52 * function pointer */
Simon Glass09140112020-05-10 11:40:03 -060053static struct cmd_tbl cmd_bootm_sub[] = {
Kumar Gala49c3a862008-10-21 17:25:45 -050054 U_BOOT_CMD_MKENT(start, 0, 1, (void *)BOOTM_STATE_START, "", ""),
55 U_BOOT_CMD_MKENT(loados, 0, 1, (void *)BOOTM_STATE_LOADOS, "", ""),
Philippe Reynes7bebc112022-03-28 22:57:07 +020056#ifdef CONFIG_CMD_BOOTM_PRE_LOAD
57 U_BOOT_CMD_MKENT(preload, 0, 1, (void *)BOOTM_STATE_PRE_LOAD, "", ""),
58#endif
John Rigbyfca43cc2010-10-13 13:57:35 -060059#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
Kumar Gala49c3a862008-10-21 17:25:45 -050060 U_BOOT_CMD_MKENT(ramdisk, 0, 1, (void *)BOOTM_STATE_RAMDISK, "", ""),
61#endif
62#ifdef CONFIG_OF_LIBFDT
63 U_BOOT_CMD_MKENT(fdt, 0, 1, (void *)BOOTM_STATE_FDT, "", ""),
64#endif
Kumar Gala49c3a862008-10-21 17:25:45 -050065 U_BOOT_CMD_MKENT(cmdline, 0, 1, (void *)BOOTM_STATE_OS_CMDLINE, "", ""),
Peter Tyser224c90d2009-11-18 19:08:59 -060066 U_BOOT_CMD_MKENT(bdt, 0, 1, (void *)BOOTM_STATE_OS_BD_T, "", ""),
Kumar Gala49c3a862008-10-21 17:25:45 -050067 U_BOOT_CMD_MKENT(prep, 0, 1, (void *)BOOTM_STATE_OS_PREP, "", ""),
Simon Glassd0ae31e2013-06-11 11:14:48 -070068 U_BOOT_CMD_MKENT(fake, 0, 1, (void *)BOOTM_STATE_OS_FAKE_GO, "", ""),
Kumar Gala49c3a862008-10-21 17:25:45 -050069 U_BOOT_CMD_MKENT(go, 0, 1, (void *)BOOTM_STATE_OS_GO, "", ""),
70};
71
Philippe Reynes7bebc112022-03-28 22:57:07 +020072#if defined(CONFIG_CMD_BOOTM_PRE_LOAD)
73static ulong bootm_get_addr(int argc, char *const argv[])
74{
75 ulong addr;
76
77 if (argc > 0)
78 addr = hextoul(argv[0], NULL);
79 else
80 addr = image_load_addr;
81
82 return addr;
83}
84#endif
85
Simon Glass09140112020-05-10 11:40:03 -060086static int do_bootm_subcommand(struct cmd_tbl *cmdtp, int flag, int argc,
87 char *const argv[])
Kumar Gala49c3a862008-10-21 17:25:45 -050088{
89 int ret = 0;
Simon Glass6d6f1232011-10-07 13:53:40 +000090 long state;
Simon Glass09140112020-05-10 11:40:03 -060091 struct cmd_tbl *c;
Kumar Gala49c3a862008-10-21 17:25:45 -050092
Simon Glass983c72f2013-06-11 11:14:46 -070093 c = find_cmd_tbl(argv[0], &cmd_bootm_sub[0], ARRAY_SIZE(cmd_bootm_sub));
94 argc--; argv++;
Kumar Gala49c3a862008-10-21 17:25:45 -050095
96 if (c) {
Simon Glass6d6f1232011-10-07 13:53:40 +000097 state = (long)c->cmd;
Simon Glass983c72f2013-06-11 11:14:46 -070098 if (state == BOOTM_STATE_START)
Philippe Reynes9d46e632022-03-28 22:57:00 +020099 state |= BOOTM_STATE_PRE_LOAD | BOOTM_STATE_FINDOS |
100 BOOTM_STATE_FINDOTHER;
Philippe Reynes7bebc112022-03-28 22:57:07 +0200101#if defined(CONFIG_CMD_BOOTM_PRE_LOAD)
102 if (state == BOOTM_STATE_PRE_LOAD)
103 state |= BOOTM_STATE_START;
104#endif
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200105 } else {
106 /* Unrecognized command */
Simon Glass4c12eeb2011-12-10 08:44:01 +0000107 return CMD_RET_USAGE;
Kumar Gala49c3a862008-10-21 17:25:45 -0500108 }
109
Heiko Schocherff6c0322015-02-24 07:04:38 +0100110 if (((state & BOOTM_STATE_START) != BOOTM_STATE_START) &&
111 images.state >= state) {
Stephen Warren712fbcf2011-10-18 11:11:49 +0000112 printf("Trying to execute a command out of order\n");
Simon Glass4c12eeb2011-12-10 08:44:01 +0000113 return CMD_RET_USAGE;
Kumar Gala49c3a862008-10-21 17:25:45 -0500114 }
115
Simon Glass35fc84f2013-06-11 11:14:47 -0700116 ret = do_bootm_states(cmdtp, flag, argc, argv, state, &images, 0);
Kumar Gala49c3a862008-10-21 17:25:45 -0500117
Philippe Reynes7bebc112022-03-28 22:57:07 +0200118#if defined(CONFIG_CMD_BOOTM_PRE_LOAD)
119 if (!ret && (state & BOOTM_STATE_PRE_LOAD))
120 env_set_hex("loadaddr_verified",
121 bootm_get_addr(argc, argv) + image_load_offset);
122#endif
123
Simon Glassf06443f2022-10-11 09:47:08 -0600124 return ret ? CMD_RET_FAILURE : 0;
Kumar Gala49c3a862008-10-21 17:25:45 -0500125}
126
Mingyen Hung6e468002023-01-04 23:43:04 -0800127#if CONFIG_IS_ENABLED(CMD_BOOTCTOL_AVB)
128#if CONFIG_IS_ENABLED(AML_ANTIROLLBACK) || CONFIG_IS_ENABLED(AML_AVB2_ANTIROLLBACK)
129static void bootm_avb_bootctl_anti_rollback(int rc, AvbSlotVerifyData *out_data)
130{
131 if (rc == AVB_SLOT_VERIFY_RESULT_OK && is_avb_arb_available() &&
132 !set_successful_boot() &&
133 out_data) {
134 u32 i = 0;
135 u32 version = 0;
136
137 for (i = 0; i < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; i++) {
138 u64 rb_idx = out_data->rollback_indexes[i];
139
140 if (get_avb_antirollback(i, &version) &&
141 version < (u32)rb_idx &&
142 !set_avb_antirollback(i, (u32)rb_idx)) {
143 printf("rollback(%d) = %u failed\n",
144 i, (u32)rb_idx);
145 }
146 }
147 }
148
149 if (is_avb_arb_available() &&
150 rc == AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX &&
151 has_boot_slot == 1) {
152 printf("ab mode\n");
153 update_rollback();
154 env_set("write_boot", "0");
155 run_command("saveenv", 0);
156 run_command("reset", 0);
157 }
158}
159#endif
160
161static int bootm_avb_bootctl(void)
162{
163 int rc = 0;
164 char *avb_s = NULL;
165 char *newbootargs = NULL;
166 AvbSlotVerifyData *out_data = NULL;
167
168 run_command("get_avb_mode;", 0);
169 avb_s = env_get("avb2");
170 printf("avb2: %s\n", avb_s);
171 if (strcmp(avb_s, "1") == 0) {
172 char *bootargs = NULL;
173 char *avb_cmdline = "\0";
174 const char *bootstate_o = "androidboot.verifiedbootstate=orange";
175 const char *bootstate_g = "androidboot.verifiedbootstate=green";
176 const char *bootstate = "\0";
177 u8 vbmeta_digest[AVB_SHA256_DIGEST_SIZE];
178 const int is_dev_unlocked = is_device_unlocked();
179
180 rc = avb_verify(&out_data);
181 if (is_dev_unlocked) {
182 printf("unlock state, ignore the avb check\n");
183 bootstate = bootstate_o;
184 /* return ok due to ignore error */
185 rc = AVB_SLOT_VERIFY_RESULT_OK;
186 } else {
187 printf("lock state, need avb check\n");
188 printf("avb verification: locked = %d, result = %d\n",
189 !is_dev_unlocked, rc);
190#if CONFIG_IS_ENABLED(AML_ANTIROLLBACK) || CONFIG_IS_ENABLED(AML_AVB2_ANTIROLLBACK)
191 bootm_avb_bootctl_anti_rollback(rc, out_data);
192#endif
193 if (rc != AVB_SLOT_VERIFY_RESULT_OK)
194 goto out;
195 else
196 bootstate = bootstate_g;
197 }
198
199 if (out_data) {
200 /* Trying to set boot params */
201 keymaster_boot_params boot_params;
202 AvbVBMetaImageHeader toplevel_vbmeta;
203
204 avb_vbmeta_image_header_to_host_byte_order
205 ((const AvbVBMetaImageHeader *)
206 out_data->vbmeta_images[0].vbmeta_data,
207 &toplevel_vbmeta);
208
209 boot_params.boot_patchlevel =
210 avb_get_boot_patchlevel_from_vbmeta(out_data);
211
212 create_csrs();
213
214 boot_params.device_locked = is_dev_unlocked ? 0 : 1;
215 if (is_dev_unlocked ||
216 (toplevel_vbmeta.flags &
217 AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) ||
218 (toplevel_vbmeta.flags &
219 AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED)) {
220 bootstate = bootstate_o;
221 boot_params.verified_boot_state = 2;
222 } else {
223 bootstate = bootstate_g;
224 boot_params.verified_boot_state = 0;
225 }
226
227 memcpy(boot_params.verified_boot_key, boot_key_hash,
228 sizeof(boot_params.verified_boot_key));
229
230 avb_slot_verify_data_calculate_vbmeta_digest(out_data,
231 AVB_DIGEST_TYPE_SHA256,
232 vbmeta_digest);
233 memcpy(boot_params.verified_boot_hash, vbmeta_digest,
234 sizeof(boot_params.verified_boot_hash));
235
236 if (set_boot_params(&boot_params) < 0)
237 printf("failed to set boot params.\n");
238 }
239
240 /* complete env string */
241 bootargs = env_get("bootconfig");
242 if (!bootargs)
243 bootargs = "\0";
244
245 if (out_data && out_data->cmdline)
246 avb_cmdline = out_data->cmdline;
247
248 newbootargs = malloc(strlen(bootargs) + strlen(avb_cmdline)
249 + strlen(bootstate) + 1 + 1 + 1); // spaces and EOL
250 if (!newbootargs) {
251 printf("failed to allocate buffer for bootarg\n");
252 goto out;
253 }
254 sprintf(newbootargs, "%s %s %s", bootargs,
255 avb_cmdline, bootstate);
256 env_set("bootconfig", newbootargs);
257 free(newbootargs);
258 }
259out:
260 if (out_data)
261 avb_slot_verify_data_free(out_data);
262 return rc;
263}
264#endif
265
Kumar Gala396f6352008-08-15 08:24:41 -0500266/*******************************************************************/
267/* bootm - boot application image from image in memory */
268/*******************************************************************/
Kumar Galabe083152008-10-21 17:25:44 -0500269
Simon Glass09140112020-05-10 11:40:03 -0600270int do_bootm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
Kumar Gala396f6352008-08-15 08:24:41 -0500271{
Simon Glass2c0b61d2022-10-11 09:47:09 -0600272 int states;
Simon Glassf06443f2022-10-11 09:47:08 -0600273 int ret;
Zhongfu Luodd243f42023-12-20 19:20:54 +0800274#if !defined(CONFIG_SKIP_KERNEL_DTB_SECBOOT_CHECK) && defined(CONFIG_IMAGE_CHECK)
275 char argv0_new[12] = {0};
276 char *argv_new = (char *)&argv0_new;
277#endif
Simon Glassf06443f2022-10-11 09:47:08 -0600278
Wolfgang Denk2e5167c2010-10-28 20:00:11 +0200279#ifdef CONFIG_NEEDS_MANUAL_RELOC
Peter Tyser521af042009-09-21 11:20:36 -0500280 static int relocated = 0;
Kumar Galabe083152008-10-21 17:25:44 -0500281
Kumar Galabe083152008-10-21 17:25:44 -0500282 if (!relocated) {
283 int i;
Daniel Schwierzeck58bd77d2013-01-07 06:54:52 +0000284
Daniel Schwierzeck58bd77d2013-01-07 06:54:52 +0000285 /* relocate names of sub-command table */
286 for (i = 0; i < ARRAY_SIZE(cmd_bootm_sub); i++)
287 cmd_bootm_sub[i].name += gd->reloc_off;
288
Kumar Galabe083152008-10-21 17:25:44 -0500289 relocated = 1;
290 }
Peter Tyser521af042009-09-21 11:20:36 -0500291#endif
Kumar Gala396f6352008-08-15 08:24:41 -0500292
Kumar Gala49c3a862008-10-21 17:25:45 -0500293 /* determine if we have a sub command */
Simon Glass983c72f2013-06-11 11:14:46 -0700294 argc--; argv++;
295 if (argc > 0) {
Kumar Gala49c3a862008-10-21 17:25:45 -0500296 char *endp;
297
Simon Glass7e5f4602021-07-24 09:03:29 -0600298 hextoul(argv[0], &endp);
Simon Glass983c72f2013-06-11 11:14:46 -0700299 /* endp pointing to NULL means that argv[0] was just a
Kumar Gala49c3a862008-10-21 17:25:45 -0500300 * valid number, pass it along to the normal bootm processing
301 *
302 * If endp is ':' or '#' assume a FIT identifier so pass
303 * along for normal processing.
304 *
305 * Right now we assume the first arg should never be '-'
306 */
307 if ((*endp != 0) && (*endp != ':') && (*endp != '#'))
308 return do_bootm_subcommand(cmdtp, flag, argc, argv);
309 }
310
Zhongfu Luo04a29ff2023-07-31 15:53:00 +0800311#if !defined(CONFIG_SKIP_KERNEL_DTB_SECBOOT_CHECK) && defined(CONFIG_IMAGE_CHECK)
312 unsigned int loadaddr = GXB_IMG_LOAD_ADDR; //default load address
313
314 if (argc > 0)
315 {
316 char *endp;
317 loadaddr = simple_strtoul(argv[0], &endp, 16);
318 //printf("aml log : addr = 0x%x\n",loadaddr);
319 }
320
321 if (IS_FEAT_BOOT_VERIFY()) {
322 int ret = 0;
323
Mingyen Hung6e468002023-01-04 23:43:04 -0800324 ret = secure_image_check((u8 *)(unsigned long)loadaddr,
325 GXB_IMG_SIZE, GXB_IMG_DEC_ALL);
Zhongfu Luo04a29ff2023-07-31 15:53:00 +0800326 if (ret) {
327 printf("\naml log : Sig Check %d\n", ret);
328 return ret;
329 }
330 /* Override load address argument to skip secure boot header.
331 * Only skip if secure boot so normal boot can use plain boot.img+
332 */
333 ulong img_addr, ncheckoffset;
Zhongfu Luo04a29ff2023-07-31 15:53:00 +0800334
335 img_addr = genimg_get_kernel_addr(argc < 1 ? NULL : argv[0]);
336 ncheckoffset = android_image_check_offset();
337 img_addr += ncheckoffset;
338 snprintf(argv0_new, sizeof(argv0_new), "%lx", img_addr);
339 argc = 1;
340 argv = (char **)&argv_new;
341 }
342#endif
Xindong Xu22e8daf2024-03-12 18:08:41 +0800343
344#ifdef CONFIG_AMLOGIC_MODIFY
345 char *fastboot_step = env_get("fastboot_step");
346
347 if (fastboot_step && (strcmp(fastboot_step, "2") == 0)) {
348 //come to here, means new burn bootloader.img is OK, reset env
349 printf("new burn bootloader.img is OK, write other bootloader\n");
350 char *gpt_mode = env_get("gpt_mode");
351 char *nocs_mode = env_get("nocs_mode");
352
353 if ((gpt_mode && !strcmp(gpt_mode, "true")) ||
354 (nocs_mode && !strcmp(nocs_mode, "true"))) {
355 printf("gpt or disable user bootloader mode\n");
356 run_command("copy_slot_bootable 2 1", 0);
357 } else {
358 printf("normal mode\n");
359 run_command("copy_slot_bootable 1 0", 0);
360 run_command("copy_slot_bootable 1 2", 0);
361 }
362
363 env_set("fastboot_step", "0");
364#if CONFIG_IS_ENABLED(AML_UPDATE_ENV)
365 run_command("update_env_part -p fastboot_step;", 0);
366#else
367 run_command("defenv_reserve;setenv fastboot_step 0;saveenv;", 0);
368#endif
369 }
370#endif
371
Mingyen Hung6e468002023-01-04 23:43:04 -0800372#if CONFIG_IS_ENABLED(CMD_BOOTCTOL_AVB)
373 ret = bootm_avb_bootctl();
374 if (ret) {
375 printf("bootm_avb_bootctl failed(%d)\n", ret);
376 return CMD_RET_FAILURE;
377 }
378#endif
Simon Glass2c0b61d2022-10-11 09:47:09 -0600379 states = BOOTM_STATE_START | BOOTM_STATE_FINDOS | BOOTM_STATE_PRE_LOAD |
380 BOOTM_STATE_FINDOTHER | BOOTM_STATE_LOADOS |
Paul Burton5c427e42013-09-06 11:23:55 +0100381 BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
Simon Glass2c0b61d2022-10-11 09:47:09 -0600382 BOOTM_STATE_OS_GO;
383 if (IS_ENABLED(CONFIG_SYS_BOOT_RAMDISK_HIGH))
384 states |= BOOTM_STATE_RAMDISK;
385 if (IS_ENABLED(CONFIG_PPC) || IS_ENABLED(CONFIG_MIPS))
386 states |= BOOTM_STATE_OS_CMDLINE;
387 ret = do_bootm_states(cmdtp, flag, argc, argv, states, &images, 1);
Simon Glassf06443f2022-10-11 09:47:08 -0600388
389 return ret ? CMD_RET_FAILURE : 0;
wdenk47d1a6e2002-11-03 00:01:44 +0000390}
391
Simon Glass09140112020-05-10 11:40:03 -0600392int bootm_maybe_autostart(struct cmd_tbl *cmdtp, const char *cmd)
Mike Frysinger67d668b2011-06-05 13:43:02 +0000393{
Simon Glass78398652021-10-21 21:08:52 -0600394 if (env_get_autostart()) {
Mike Frysinger67d668b2011-06-05 13:43:02 +0000395 char *local_args[2];
396 local_args[0] = (char *)cmd;
397 local_args[1] = NULL;
Simon Glassbb872dd2019-12-28 10:45:02 -0700398 printf("Automatic boot of image at addr 0x%08lX ...\n",
399 image_load_addr);
Mike Frysinger67d668b2011-06-05 13:43:02 +0000400 return do_bootm(cmdtp, 0, 1, local_args);
401 }
402
403 return 0;
404}
405
Kim Phillips088f1b12012-10-29 13:34:31 +0000406#ifdef CONFIG_SYS_LONGHELP
407static char bootm_help_text[] =
Marian Balakowicz1ee11802008-01-08 18:17:10 +0100408 "[addr [arg ...]]\n - boot application image stored in memory\n"
409 "\tpassing arguments 'arg ...'; when booting a Linux kernel,\n"
410 "\t'arg' can be the address of an initrd image\n"
Marian Balakowicz4a2ad5f2008-01-31 13:20:07 +0100411#if defined(CONFIG_OF_LIBFDT)
Matthew McClintock98a9c4d2006-06-28 10:41:37 -0500412 "\tWhen booting a Linux kernel which requires a flat device-tree\n"
Detlev Zundel5441f612007-10-19 16:47:26 +0200413 "\ta third argument is required which is the address of the\n"
Matthew McClintock98a9c4d2006-06-28 10:41:37 -0500414 "\tdevice-tree blob. To boot that kernel without an initrd image,\n"
415 "\tuse a '-' for the second argument. If you do not pass a third\n"
416 "\ta bd_info struct will be passed instead\n"
417#endif
Marian Balakowicz6986a382008-03-12 10:01:05 +0100418#if defined(CONFIG_FIT)
419 "\t\nFor the new multi component uImage format (FIT) addresses\n"
Vagrant Cascadianda1a3bd2016-10-23 20:45:18 -0700420 "\tmust be extended to include component or configuration unit name:\n"
Marian Balakowicz6986a382008-03-12 10:01:05 +0100421 "\taddr:<subimg_uname> - direct component image specification\n"
422 "\taddr#<conf_uname> - configuration specification\n"
423 "\tUse iminfo command to get the list of existing component\n"
424 "\timages and configurations.\n"
425#endif
Kumar Gala49c3a862008-10-21 17:25:45 -0500426 "\nSub-commands to do part of the bootm sequence. The sub-commands "
427 "must be\n"
428 "issued in the order below (it's ok to not issue all sub-commands):\n"
429 "\tstart [addr [arg ...]]\n"
Philippe Reynes7bebc112022-03-28 22:57:07 +0200430#if defined(CONFIG_CMD_BOOTM_PRE_LOAD)
431 "\tpreload [addr [arg ..]] - run only the preload stage\n"
432#endif
Kumar Gala49c3a862008-10-21 17:25:45 -0500433 "\tloados - load OS image\n"
Daniel Schwierzeck59af76d2013-02-26 04:54:19 +0000434#if defined(CONFIG_SYS_BOOT_RAMDISK_HIGH)
Kumar Gala49c3a862008-10-21 17:25:45 -0500435 "\tramdisk - relocate initrd, set env initrd_start/initrd_end\n"
436#endif
437#if defined(CONFIG_OF_LIBFDT)
438 "\tfdt - relocate flat device tree\n"
439#endif
Kumar Gala49c3a862008-10-21 17:25:45 -0500440 "\tcmdline - OS specific command line processing/setup\n"
Masahiro Yamadabb5a2cf2020-06-26 15:13:34 +0900441 "\tbdt - OS specific bd_info processing\n"
Kumar Gala49c3a862008-10-21 17:25:45 -0500442 "\tprep - OS specific prep before relocation or go\n"
Michal Simeke3046ba2015-01-15 09:53:13 +0100443#if defined(CONFIG_TRACE)
444 "\tfake - OS specific fake start without go\n"
445#endif
Kim Phillips088f1b12012-10-29 13:34:31 +0000446 "\tgo - start OS";
447#endif
448
449U_BOOT_CMD(
450 bootm, CONFIG_SYS_MAXARGS, 1, do_bootm,
451 "boot application image from memory", bootm_help_text
wdenk8bde7f72003-06-27 21:31:46 +0000452);
453
Marian Balakowicz1ee11802008-01-08 18:17:10 +0100454/*******************************************************************/
455/* bootd - boot default image */
456/*******************************************************************/
Jon Loeligerbaa26db2007-07-08 17:51:39 -0500457#if defined(CONFIG_CMD_BOOTD)
Simon Glass09140112020-05-10 11:40:03 -0600458int do_bootd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
wdenk47d1a6e2002-11-03 00:01:44 +0000459{
Simon Glass00caae62017-08-03 12:22:12 -0600460 return run_command(env_get("bootcmd"), flag);
wdenk47d1a6e2002-11-03 00:01:44 +0000461}
wdenk8bde7f72003-06-27 21:31:46 +0000462
wdenk0d498392003-07-01 21:06:45 +0000463U_BOOT_CMD(
Marian Balakowicz1ee11802008-01-08 18:17:10 +0100464 boot, 1, 1, do_bootd,
Peter Tyser2fb26042009-01-27 18:03:12 -0600465 "boot default, i.e., run 'bootcmd'",
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200466 ""
wdenk9d2b18a2003-06-28 23:11:04 +0000467);
468
469/* keep old command name "bootd" for backward compatibility */
wdenk0d498392003-07-01 21:06:45 +0000470U_BOOT_CMD(
Marian Balakowicz1ee11802008-01-08 18:17:10 +0100471 bootd, 1, 1, do_bootd,
Peter Tyser2fb26042009-01-27 18:03:12 -0600472 "boot default, i.e., run 'bootcmd'",
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200473 ""
wdenk8bde7f72003-06-27 21:31:46 +0000474);
475
wdenk47d1a6e2002-11-03 00:01:44 +0000476#endif
477
Marian Balakowicz1ee11802008-01-08 18:17:10 +0100478
479/*******************************************************************/
480/* iminfo - print header info for a requested image */
481/*******************************************************************/
Jon Loeligerbaa26db2007-07-08 17:51:39 -0500482#if defined(CONFIG_CMD_IMI)
Simon Glass09140112020-05-10 11:40:03 -0600483static int do_iminfo(struct cmd_tbl *cmdtp, int flag, int argc,
484 char *const argv[])
wdenk47d1a6e2002-11-03 00:01:44 +0000485{
486 int arg;
487 ulong addr;
Marian Balakowicz1ee11802008-01-08 18:17:10 +0100488 int rcode = 0;
wdenk47d1a6e2002-11-03 00:01:44 +0000489
490 if (argc < 2) {
Simon Glassbb872dd2019-12-28 10:45:02 -0700491 return image_info(image_load_addr);
wdenk47d1a6e2002-11-03 00:01:44 +0000492 }
493
Marian Balakowicz1ee11802008-01-08 18:17:10 +0100494 for (arg = 1; arg < argc; ++arg) {
Simon Glass7e5f4602021-07-24 09:03:29 -0600495 addr = hextoul(argv[arg], NULL);
Stephen Warren712fbcf2011-10-18 11:11:49 +0000496 if (image_info(addr) != 0)
Marian Balakowicz1ee11802008-01-08 18:17:10 +0100497 rcode = 1;
wdenk47d1a6e2002-11-03 00:01:44 +0000498 }
499 return rcode;
500}
501
Stephen Warren712fbcf2011-10-18 11:11:49 +0000502static int image_info(ulong addr)
wdenk47d1a6e2002-11-03 00:01:44 +0000503{
Philippe Reynesae0d12f2019-12-02 15:45:50 +0100504 void *hdr = (void *)map_sysmem(addr, 0);
wdenk47d1a6e2002-11-03 00:01:44 +0000505
Stephen Warren712fbcf2011-10-18 11:11:49 +0000506 printf("\n## Checking Image at %08lx ...\n", addr);
wdenk47d1a6e2002-11-03 00:01:44 +0000507
Stephen Warren712fbcf2011-10-18 11:11:49 +0000508 switch (genimg_get_format(hdr)) {
Tom Rinic76c93a2019-05-23 07:14:07 -0400509#if defined(CONFIG_LEGACY_IMAGE_FORMAT)
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100510 case IMAGE_FORMAT_LEGACY:
Stephen Warren712fbcf2011-10-18 11:11:49 +0000511 puts(" Legacy image found\n");
512 if (!image_check_magic(hdr)) {
513 puts(" Bad Magic Number\n");
Philippe Reynesae0d12f2019-12-02 15:45:50 +0100514 unmap_sysmem(hdr);
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100515 return 1;
516 }
517
Stephen Warren712fbcf2011-10-18 11:11:49 +0000518 if (!image_check_hcrc(hdr)) {
519 puts(" Bad Header Checksum\n");
Philippe Reynesae0d12f2019-12-02 15:45:50 +0100520 unmap_sysmem(hdr);
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100521 return 1;
522 }
523
Stephen Warren712fbcf2011-10-18 11:11:49 +0000524 image_print_contents(hdr);
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100525
Stephen Warren712fbcf2011-10-18 11:11:49 +0000526 puts(" Verifying Checksum ... ");
527 if (!image_check_dcrc(hdr)) {
528 puts(" Bad Data CRC\n");
Philippe Reynesae0d12f2019-12-02 15:45:50 +0100529 unmap_sysmem(hdr);
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100530 return 1;
531 }
Stephen Warren712fbcf2011-10-18 11:11:49 +0000532 puts("OK\n");
Philippe Reynesae0d12f2019-12-02 15:45:50 +0100533 unmap_sysmem(hdr);
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100534 return 0;
Heiko Schocher21d29f72014-05-28 11:33:33 +0200535#endif
Michael Trimarchi4f1318b2016-06-10 19:54:37 +0200536#if defined(CONFIG_ANDROID_BOOT_IMAGE)
537 case IMAGE_FORMAT_ANDROID:
538 puts(" Android image found\n");
539 android_print_contents(hdr);
Philippe Reynesae0d12f2019-12-02 15:45:50 +0100540 unmap_sysmem(hdr);
Michael Trimarchi4f1318b2016-06-10 19:54:37 +0200541 return 0;
542#endif
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100543#if defined(CONFIG_FIT)
544 case IMAGE_FORMAT_FIT:
Stephen Warren712fbcf2011-10-18 11:11:49 +0000545 puts(" FIT image found\n");
Marian Balakowicze32fea62008-03-11 12:35:20 +0100546
Simon Glassc5819702021-02-15 17:08:09 -0700547 if (fit_check_format(hdr, IMAGE_SIZE_INVAL)) {
Stephen Warren712fbcf2011-10-18 11:11:49 +0000548 puts("Bad FIT image format!\n");
Philippe Reynesae0d12f2019-12-02 15:45:50 +0100549 unmap_sysmem(hdr);
Marian Balakowicze32fea62008-03-11 12:35:20 +0100550 return 1;
551 }
552
Stephen Warren712fbcf2011-10-18 11:11:49 +0000553 fit_print_contents(hdr);
Bartlomiej Siekaa4f24342008-09-09 12:58:16 +0200554
Simon Glassb8da8362013-05-07 06:11:57 +0000555 if (!fit_all_image_verify(hdr)) {
Stephen Warren712fbcf2011-10-18 11:11:49 +0000556 puts("Bad hash in FIT image!\n");
Philippe Reynesae0d12f2019-12-02 15:45:50 +0100557 unmap_sysmem(hdr);
Bartlomiej Siekaa4f24342008-09-09 12:58:16 +0200558 return 1;
559 }
560
Philippe Reynesae0d12f2019-12-02 15:45:50 +0100561 unmap_sysmem(hdr);
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100562 return 0;
563#endif
564 default:
Stephen Warren712fbcf2011-10-18 11:11:49 +0000565 puts("Unknown image format!\n");
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100566 break;
wdenk47d1a6e2002-11-03 00:01:44 +0000567 }
568
Philippe Reynesae0d12f2019-12-02 15:45:50 +0100569 unmap_sysmem(hdr);
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100570 return 1;
wdenk47d1a6e2002-11-03 00:01:44 +0000571}
wdenk0d498392003-07-01 21:06:45 +0000572
573U_BOOT_CMD(
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200574 iminfo, CONFIG_SYS_MAXARGS, 1, do_iminfo,
Peter Tyser2fb26042009-01-27 18:03:12 -0600575 "print header information for application image",
wdenk8bde7f72003-06-27 21:31:46 +0000576 "addr [addr ...]\n"
577 " - print header information for application image starting at\n"
578 " address 'addr' in memory; this includes verification of the\n"
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200579 " image contents (magic number, header and payload checksums)"
wdenk8bde7f72003-06-27 21:31:46 +0000580);
Jon Loeliger90253172007-07-10 11:02:44 -0500581#endif
wdenk47d1a6e2002-11-03 00:01:44 +0000582
Marian Balakowicz1ee11802008-01-08 18:17:10 +0100583
584/*******************************************************************/
585/* imls - list all images found in flash */
586/*******************************************************************/
Jon Loeligerbaa26db2007-07-08 17:51:39 -0500587#if defined(CONFIG_CMD_IMLS)
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000588static int do_imls_nor(void)
wdenk27b207f2003-07-24 23:38:38 +0000589{
590 flash_info_t *info;
591 int i, j;
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100592 void *hdr;
wdenk27b207f2003-07-24 23:38:38 +0000593
Marian Balakowicz1ee11802008-01-08 18:17:10 +0100594 for (i = 0, info = &flash_info[0];
Patrick Delaunay98150e72022-01-04 14:23:58 +0100595 i < CFI_FLASH_BANKS; ++i, ++info) {
Marian Balakowicz1ee11802008-01-08 18:17:10 +0100596
wdenk27b207f2003-07-24 23:38:38 +0000597 if (info->flash_id == FLASH_UNKNOWN)
598 goto next_bank;
Marian Balakowicz1ee11802008-01-08 18:17:10 +0100599 for (j = 0; j < info->sector_count; ++j) {
wdenk27b207f2003-07-24 23:38:38 +0000600
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100601 hdr = (void *)info->start[j];
602 if (!hdr)
wdenk27b207f2003-07-24 23:38:38 +0000603 goto next_sector;
604
Stephen Warren712fbcf2011-10-18 11:11:49 +0000605 switch (genimg_get_format(hdr)) {
Tom Rinic76c93a2019-05-23 07:14:07 -0400606#if defined(CONFIG_LEGACY_IMAGE_FORMAT)
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100607 case IMAGE_FORMAT_LEGACY:
Stephen Warren712fbcf2011-10-18 11:11:49 +0000608 if (!image_check_hcrc(hdr))
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100609 goto next_sector;
610
Stephen Warren712fbcf2011-10-18 11:11:49 +0000611 printf("Legacy Image at %08lX:\n", (ulong)hdr);
612 image_print_contents(hdr);
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100613
Stephen Warren712fbcf2011-10-18 11:11:49 +0000614 puts(" Verifying Checksum ... ");
615 if (!image_check_dcrc(hdr)) {
616 puts("Bad Data CRC\n");
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100617 } else {
Stephen Warren712fbcf2011-10-18 11:11:49 +0000618 puts("OK\n");
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100619 }
620 break;
Heiko Schocher21d29f72014-05-28 11:33:33 +0200621#endif
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100622#if defined(CONFIG_FIT)
623 case IMAGE_FORMAT_FIT:
Simon Glassc5819702021-02-15 17:08:09 -0700624 if (fit_check_format(hdr, IMAGE_SIZE_INVAL))
Marian Balakowicze32fea62008-03-11 12:35:20 +0100625 goto next_sector;
626
Stephen Warren712fbcf2011-10-18 11:11:49 +0000627 printf("FIT Image at %08lX:\n", (ulong)hdr);
628 fit_print_contents(hdr);
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100629 break;
630#endif
631 default:
wdenk27b207f2003-07-24 23:38:38 +0000632 goto next_sector;
wdenk5bb226e2003-11-17 21:14:37 +0000633 }
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100634
wdenkbdccc4f2003-08-05 17:43:17 +0000635next_sector: ;
wdenk27b207f2003-07-24 23:38:38 +0000636 }
wdenkbdccc4f2003-08-05 17:43:17 +0000637next_bank: ;
wdenk27b207f2003-07-24 23:38:38 +0000638 }
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000639 return 0;
640}
641#endif
642
643#if defined(CONFIG_CMD_IMLS_NAND)
Scott Wood151c06e2016-05-30 13:57:54 -0500644static int nand_imls_legacyimage(struct mtd_info *mtd, int nand_dev,
645 loff_t off, size_t len)
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000646{
647 void *imgdata;
648 int ret;
649
650 imgdata = malloc(len);
651 if (!imgdata) {
652 printf("May be a Legacy Image at NAND device %d offset %08llX:\n",
653 nand_dev, off);
654 printf(" Low memory(cannot allocate memory for image)\n");
655 return -ENOMEM;
656 }
657
Grygorii Strashkodbe78812017-01-31 15:37:03 -0600658 ret = nand_read_skip_bad(mtd, off, &len, NULL, mtd->size, imgdata);
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000659 if (ret < 0 && ret != -EUCLEAN) {
660 free(imgdata);
661 return ret;
662 }
663
664 if (!image_check_hcrc(imgdata)) {
665 free(imgdata);
666 return 0;
667 }
668
669 printf("Legacy Image at NAND device %d offset %08llX:\n",
670 nand_dev, off);
671 image_print_contents(imgdata);
672
673 puts(" Verifying Checksum ... ");
674 if (!image_check_dcrc(imgdata))
675 puts("Bad Data CRC\n");
676 else
677 puts("OK\n");
678
679 free(imgdata);
680
681 return 0;
682}
683
Scott Wood151c06e2016-05-30 13:57:54 -0500684static int nand_imls_fitimage(struct mtd_info *mtd, int nand_dev, loff_t off,
685 size_t len)
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000686{
687 void *imgdata;
688 int ret;
689
690 imgdata = malloc(len);
691 if (!imgdata) {
692 printf("May be a FIT Image at NAND device %d offset %08llX:\n",
693 nand_dev, off);
694 printf(" Low memory(cannot allocate memory for image)\n");
695 return -ENOMEM;
696 }
697
Grygorii Strashkodbe78812017-01-31 15:37:03 -0600698 ret = nand_read_skip_bad(mtd, off, &len, NULL, mtd->size, imgdata);
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000699 if (ret < 0 && ret != -EUCLEAN) {
700 free(imgdata);
701 return ret;
702 }
703
Simon Glassc5819702021-02-15 17:08:09 -0700704 if (fit_check_format(imgdata, IMAGE_SIZE_INVAL)) {
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000705 free(imgdata);
706 return 0;
707 }
708
709 printf("FIT Image at NAND device %d offset %08llX:\n", nand_dev, off);
710
711 fit_print_contents(imgdata);
712 free(imgdata);
713
714 return 0;
715}
716
717static int do_imls_nand(void)
718{
Scott Wood151c06e2016-05-30 13:57:54 -0500719 struct mtd_info *mtd;
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000720 int nand_dev = nand_curr_device;
721 size_t len;
722 loff_t off;
723 u32 buffer[16];
724
725 if (nand_dev < 0 || nand_dev >= CONFIG_SYS_MAX_NAND_DEVICE) {
726 puts("\nNo NAND devices available\n");
727 return -ENODEV;
728 }
729
730 printf("\n");
731
732 for (nand_dev = 0; nand_dev < CONFIG_SYS_MAX_NAND_DEVICE; nand_dev++) {
Grygorii Strashkof370b512017-06-26 19:12:54 -0500733 mtd = get_nand_dev_by_index(nand_dev);
Scott Wood151c06e2016-05-30 13:57:54 -0500734 if (!mtd->name || !mtd->size)
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000735 continue;
736
Scott Wood151c06e2016-05-30 13:57:54 -0500737 for (off = 0; off < mtd->size; off += mtd->erasesize) {
Simon Glassf3543e62022-09-06 20:26:52 -0600738 const struct legacy_img_hdr *header;
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000739 int ret;
740
Scott Wood151c06e2016-05-30 13:57:54 -0500741 if (nand_block_isbad(mtd, off))
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000742 continue;
743
744 len = sizeof(buffer);
745
Scott Wood151c06e2016-05-30 13:57:54 -0500746 ret = nand_read(mtd, off, &len, (u8 *)buffer);
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000747 if (ret < 0 && ret != -EUCLEAN) {
748 printf("NAND read error %d at offset %08llX\n",
749 ret, off);
750 continue;
751 }
752
753 switch (genimg_get_format(buffer)) {
Tom Rinic76c93a2019-05-23 07:14:07 -0400754#if defined(CONFIG_LEGACY_IMAGE_FORMAT)
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000755 case IMAGE_FORMAT_LEGACY:
Simon Glassf3543e62022-09-06 20:26:52 -0600756 header = (const struct legacy_img_hdr *)buffer;
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000757
758 len = image_get_image_size(header);
Scott Wood151c06e2016-05-30 13:57:54 -0500759 nand_imls_legacyimage(mtd, nand_dev, off, len);
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000760 break;
Heiko Schocher21d29f72014-05-28 11:33:33 +0200761#endif
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000762#if defined(CONFIG_FIT)
763 case IMAGE_FORMAT_FIT:
764 len = fit_get_size(buffer);
Scott Wood151c06e2016-05-30 13:57:54 -0500765 nand_imls_fitimage(mtd, nand_dev, off, len);
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000766 break;
767#endif
768 }
769 }
770 }
771
772 return 0;
773}
774#endif
775
776#if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND)
Simon Glass09140112020-05-10 11:40:03 -0600777static int do_imls(struct cmd_tbl *cmdtp, int flag, int argc,
778 char *const argv[])
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000779{
780 int ret_nor = 0, ret_nand = 0;
781
782#if defined(CONFIG_CMD_IMLS)
783 ret_nor = do_imls_nor();
784#endif
785
786#if defined(CONFIG_CMD_IMLS_NAND)
787 ret_nand = do_imls_nand();
788#endif
789
790 if (ret_nor)
791 return ret_nor;
792
793 if (ret_nand)
794 return ret_nand;
wdenk27b207f2003-07-24 23:38:38 +0000795
796 return (0);
797}
798
799U_BOOT_CMD(
800 imls, 1, 1, do_imls,
Peter Tyser2fb26042009-01-27 18:03:12 -0600801 "list all images found in flash",
wdenk27b207f2003-07-24 23:38:38 +0000802 "\n"
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000803 " - Prints information about all images found at sector/block\n"
804 " boundaries in nor/nand flash."
wdenk27b207f2003-07-24 23:38:38 +0000805);
Jon Loeliger90253172007-07-10 11:02:44 -0500806#endif