blob: 7d2d42dfe59233bb2c9aa1d6d1674b33419c5c12 [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
Mingyen Hung6e468002023-01-04 23:43:04 -0800343#if CONFIG_IS_ENABLED(CMD_BOOTCTOL_AVB)
344 ret = bootm_avb_bootctl();
345 if (ret) {
346 printf("bootm_avb_bootctl failed(%d)\n", ret);
347 return CMD_RET_FAILURE;
348 }
349#endif
Simon Glass2c0b61d2022-10-11 09:47:09 -0600350 states = BOOTM_STATE_START | BOOTM_STATE_FINDOS | BOOTM_STATE_PRE_LOAD |
351 BOOTM_STATE_FINDOTHER | BOOTM_STATE_LOADOS |
Paul Burton5c427e42013-09-06 11:23:55 +0100352 BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
Simon Glass2c0b61d2022-10-11 09:47:09 -0600353 BOOTM_STATE_OS_GO;
354 if (IS_ENABLED(CONFIG_SYS_BOOT_RAMDISK_HIGH))
355 states |= BOOTM_STATE_RAMDISK;
356 if (IS_ENABLED(CONFIG_PPC) || IS_ENABLED(CONFIG_MIPS))
357 states |= BOOTM_STATE_OS_CMDLINE;
358 ret = do_bootm_states(cmdtp, flag, argc, argv, states, &images, 1);
Simon Glassf06443f2022-10-11 09:47:08 -0600359
360 return ret ? CMD_RET_FAILURE : 0;
wdenk47d1a6e2002-11-03 00:01:44 +0000361}
362
Simon Glass09140112020-05-10 11:40:03 -0600363int bootm_maybe_autostart(struct cmd_tbl *cmdtp, const char *cmd)
Mike Frysinger67d668b2011-06-05 13:43:02 +0000364{
Simon Glass78398652021-10-21 21:08:52 -0600365 if (env_get_autostart()) {
Mike Frysinger67d668b2011-06-05 13:43:02 +0000366 char *local_args[2];
367 local_args[0] = (char *)cmd;
368 local_args[1] = NULL;
Simon Glassbb872dd2019-12-28 10:45:02 -0700369 printf("Automatic boot of image at addr 0x%08lX ...\n",
370 image_load_addr);
Mike Frysinger67d668b2011-06-05 13:43:02 +0000371 return do_bootm(cmdtp, 0, 1, local_args);
372 }
373
374 return 0;
375}
376
Kim Phillips088f1b12012-10-29 13:34:31 +0000377#ifdef CONFIG_SYS_LONGHELP
378static char bootm_help_text[] =
Marian Balakowicz1ee11802008-01-08 18:17:10 +0100379 "[addr [arg ...]]\n - boot application image stored in memory\n"
380 "\tpassing arguments 'arg ...'; when booting a Linux kernel,\n"
381 "\t'arg' can be the address of an initrd image\n"
Marian Balakowicz4a2ad5f2008-01-31 13:20:07 +0100382#if defined(CONFIG_OF_LIBFDT)
Matthew McClintock98a9c4d2006-06-28 10:41:37 -0500383 "\tWhen booting a Linux kernel which requires a flat device-tree\n"
Detlev Zundel5441f612007-10-19 16:47:26 +0200384 "\ta third argument is required which is the address of the\n"
Matthew McClintock98a9c4d2006-06-28 10:41:37 -0500385 "\tdevice-tree blob. To boot that kernel without an initrd image,\n"
386 "\tuse a '-' for the second argument. If you do not pass a third\n"
387 "\ta bd_info struct will be passed instead\n"
388#endif
Marian Balakowicz6986a382008-03-12 10:01:05 +0100389#if defined(CONFIG_FIT)
390 "\t\nFor the new multi component uImage format (FIT) addresses\n"
Vagrant Cascadianda1a3bd2016-10-23 20:45:18 -0700391 "\tmust be extended to include component or configuration unit name:\n"
Marian Balakowicz6986a382008-03-12 10:01:05 +0100392 "\taddr:<subimg_uname> - direct component image specification\n"
393 "\taddr#<conf_uname> - configuration specification\n"
394 "\tUse iminfo command to get the list of existing component\n"
395 "\timages and configurations.\n"
396#endif
Kumar Gala49c3a862008-10-21 17:25:45 -0500397 "\nSub-commands to do part of the bootm sequence. The sub-commands "
398 "must be\n"
399 "issued in the order below (it's ok to not issue all sub-commands):\n"
400 "\tstart [addr [arg ...]]\n"
Philippe Reynes7bebc112022-03-28 22:57:07 +0200401#if defined(CONFIG_CMD_BOOTM_PRE_LOAD)
402 "\tpreload [addr [arg ..]] - run only the preload stage\n"
403#endif
Kumar Gala49c3a862008-10-21 17:25:45 -0500404 "\tloados - load OS image\n"
Daniel Schwierzeck59af76d2013-02-26 04:54:19 +0000405#if defined(CONFIG_SYS_BOOT_RAMDISK_HIGH)
Kumar Gala49c3a862008-10-21 17:25:45 -0500406 "\tramdisk - relocate initrd, set env initrd_start/initrd_end\n"
407#endif
408#if defined(CONFIG_OF_LIBFDT)
409 "\tfdt - relocate flat device tree\n"
410#endif
Kumar Gala49c3a862008-10-21 17:25:45 -0500411 "\tcmdline - OS specific command line processing/setup\n"
Masahiro Yamadabb5a2cf2020-06-26 15:13:34 +0900412 "\tbdt - OS specific bd_info processing\n"
Kumar Gala49c3a862008-10-21 17:25:45 -0500413 "\tprep - OS specific prep before relocation or go\n"
Michal Simeke3046ba2015-01-15 09:53:13 +0100414#if defined(CONFIG_TRACE)
415 "\tfake - OS specific fake start without go\n"
416#endif
Kim Phillips088f1b12012-10-29 13:34:31 +0000417 "\tgo - start OS";
418#endif
419
420U_BOOT_CMD(
421 bootm, CONFIG_SYS_MAXARGS, 1, do_bootm,
422 "boot application image from memory", bootm_help_text
wdenk8bde7f72003-06-27 21:31:46 +0000423);
424
Marian Balakowicz1ee11802008-01-08 18:17:10 +0100425/*******************************************************************/
426/* bootd - boot default image */
427/*******************************************************************/
Jon Loeligerbaa26db2007-07-08 17:51:39 -0500428#if defined(CONFIG_CMD_BOOTD)
Simon Glass09140112020-05-10 11:40:03 -0600429int do_bootd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
wdenk47d1a6e2002-11-03 00:01:44 +0000430{
Simon Glass00caae62017-08-03 12:22:12 -0600431 return run_command(env_get("bootcmd"), flag);
wdenk47d1a6e2002-11-03 00:01:44 +0000432}
wdenk8bde7f72003-06-27 21:31:46 +0000433
wdenk0d498392003-07-01 21:06:45 +0000434U_BOOT_CMD(
Marian Balakowicz1ee11802008-01-08 18:17:10 +0100435 boot, 1, 1, do_bootd,
Peter Tyser2fb26042009-01-27 18:03:12 -0600436 "boot default, i.e., run 'bootcmd'",
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200437 ""
wdenk9d2b18a2003-06-28 23:11:04 +0000438);
439
440/* keep old command name "bootd" for backward compatibility */
wdenk0d498392003-07-01 21:06:45 +0000441U_BOOT_CMD(
Marian Balakowicz1ee11802008-01-08 18:17:10 +0100442 bootd, 1, 1, do_bootd,
Peter Tyser2fb26042009-01-27 18:03:12 -0600443 "boot default, i.e., run 'bootcmd'",
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200444 ""
wdenk8bde7f72003-06-27 21:31:46 +0000445);
446
wdenk47d1a6e2002-11-03 00:01:44 +0000447#endif
448
Marian Balakowicz1ee11802008-01-08 18:17:10 +0100449
450/*******************************************************************/
451/* iminfo - print header info for a requested image */
452/*******************************************************************/
Jon Loeligerbaa26db2007-07-08 17:51:39 -0500453#if defined(CONFIG_CMD_IMI)
Simon Glass09140112020-05-10 11:40:03 -0600454static int do_iminfo(struct cmd_tbl *cmdtp, int flag, int argc,
455 char *const argv[])
wdenk47d1a6e2002-11-03 00:01:44 +0000456{
457 int arg;
458 ulong addr;
Marian Balakowicz1ee11802008-01-08 18:17:10 +0100459 int rcode = 0;
wdenk47d1a6e2002-11-03 00:01:44 +0000460
461 if (argc < 2) {
Simon Glassbb872dd2019-12-28 10:45:02 -0700462 return image_info(image_load_addr);
wdenk47d1a6e2002-11-03 00:01:44 +0000463 }
464
Marian Balakowicz1ee11802008-01-08 18:17:10 +0100465 for (arg = 1; arg < argc; ++arg) {
Simon Glass7e5f4602021-07-24 09:03:29 -0600466 addr = hextoul(argv[arg], NULL);
Stephen Warren712fbcf2011-10-18 11:11:49 +0000467 if (image_info(addr) != 0)
Marian Balakowicz1ee11802008-01-08 18:17:10 +0100468 rcode = 1;
wdenk47d1a6e2002-11-03 00:01:44 +0000469 }
470 return rcode;
471}
472
Stephen Warren712fbcf2011-10-18 11:11:49 +0000473static int image_info(ulong addr)
wdenk47d1a6e2002-11-03 00:01:44 +0000474{
Philippe Reynesae0d12f2019-12-02 15:45:50 +0100475 void *hdr = (void *)map_sysmem(addr, 0);
wdenk47d1a6e2002-11-03 00:01:44 +0000476
Stephen Warren712fbcf2011-10-18 11:11:49 +0000477 printf("\n## Checking Image at %08lx ...\n", addr);
wdenk47d1a6e2002-11-03 00:01:44 +0000478
Stephen Warren712fbcf2011-10-18 11:11:49 +0000479 switch (genimg_get_format(hdr)) {
Tom Rinic76c93a2019-05-23 07:14:07 -0400480#if defined(CONFIG_LEGACY_IMAGE_FORMAT)
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100481 case IMAGE_FORMAT_LEGACY:
Stephen Warren712fbcf2011-10-18 11:11:49 +0000482 puts(" Legacy image found\n");
483 if (!image_check_magic(hdr)) {
484 puts(" Bad Magic Number\n");
Philippe Reynesae0d12f2019-12-02 15:45:50 +0100485 unmap_sysmem(hdr);
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100486 return 1;
487 }
488
Stephen Warren712fbcf2011-10-18 11:11:49 +0000489 if (!image_check_hcrc(hdr)) {
490 puts(" Bad Header Checksum\n");
Philippe Reynesae0d12f2019-12-02 15:45:50 +0100491 unmap_sysmem(hdr);
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100492 return 1;
493 }
494
Stephen Warren712fbcf2011-10-18 11:11:49 +0000495 image_print_contents(hdr);
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100496
Stephen Warren712fbcf2011-10-18 11:11:49 +0000497 puts(" Verifying Checksum ... ");
498 if (!image_check_dcrc(hdr)) {
499 puts(" Bad Data CRC\n");
Philippe Reynesae0d12f2019-12-02 15:45:50 +0100500 unmap_sysmem(hdr);
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100501 return 1;
502 }
Stephen Warren712fbcf2011-10-18 11:11:49 +0000503 puts("OK\n");
Philippe Reynesae0d12f2019-12-02 15:45:50 +0100504 unmap_sysmem(hdr);
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100505 return 0;
Heiko Schocher21d29f72014-05-28 11:33:33 +0200506#endif
Michael Trimarchi4f1318b2016-06-10 19:54:37 +0200507#if defined(CONFIG_ANDROID_BOOT_IMAGE)
508 case IMAGE_FORMAT_ANDROID:
509 puts(" Android image found\n");
510 android_print_contents(hdr);
Philippe Reynesae0d12f2019-12-02 15:45:50 +0100511 unmap_sysmem(hdr);
Michael Trimarchi4f1318b2016-06-10 19:54:37 +0200512 return 0;
513#endif
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100514#if defined(CONFIG_FIT)
515 case IMAGE_FORMAT_FIT:
Stephen Warren712fbcf2011-10-18 11:11:49 +0000516 puts(" FIT image found\n");
Marian Balakowicze32fea62008-03-11 12:35:20 +0100517
Simon Glassc5819702021-02-15 17:08:09 -0700518 if (fit_check_format(hdr, IMAGE_SIZE_INVAL)) {
Stephen Warren712fbcf2011-10-18 11:11:49 +0000519 puts("Bad FIT image format!\n");
Philippe Reynesae0d12f2019-12-02 15:45:50 +0100520 unmap_sysmem(hdr);
Marian Balakowicze32fea62008-03-11 12:35:20 +0100521 return 1;
522 }
523
Stephen Warren712fbcf2011-10-18 11:11:49 +0000524 fit_print_contents(hdr);
Bartlomiej Siekaa4f24342008-09-09 12:58:16 +0200525
Simon Glassb8da8362013-05-07 06:11:57 +0000526 if (!fit_all_image_verify(hdr)) {
Stephen Warren712fbcf2011-10-18 11:11:49 +0000527 puts("Bad hash in FIT image!\n");
Philippe Reynesae0d12f2019-12-02 15:45:50 +0100528 unmap_sysmem(hdr);
Bartlomiej Siekaa4f24342008-09-09 12:58:16 +0200529 return 1;
530 }
531
Philippe Reynesae0d12f2019-12-02 15:45:50 +0100532 unmap_sysmem(hdr);
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100533 return 0;
534#endif
535 default:
Stephen Warren712fbcf2011-10-18 11:11:49 +0000536 puts("Unknown image format!\n");
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100537 break;
wdenk47d1a6e2002-11-03 00:01:44 +0000538 }
539
Philippe Reynesae0d12f2019-12-02 15:45:50 +0100540 unmap_sysmem(hdr);
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100541 return 1;
wdenk47d1a6e2002-11-03 00:01:44 +0000542}
wdenk0d498392003-07-01 21:06:45 +0000543
544U_BOOT_CMD(
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200545 iminfo, CONFIG_SYS_MAXARGS, 1, do_iminfo,
Peter Tyser2fb26042009-01-27 18:03:12 -0600546 "print header information for application image",
wdenk8bde7f72003-06-27 21:31:46 +0000547 "addr [addr ...]\n"
548 " - print header information for application image starting at\n"
549 " address 'addr' in memory; this includes verification of the\n"
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200550 " image contents (magic number, header and payload checksums)"
wdenk8bde7f72003-06-27 21:31:46 +0000551);
Jon Loeliger90253172007-07-10 11:02:44 -0500552#endif
wdenk47d1a6e2002-11-03 00:01:44 +0000553
Marian Balakowicz1ee11802008-01-08 18:17:10 +0100554
555/*******************************************************************/
556/* imls - list all images found in flash */
557/*******************************************************************/
Jon Loeligerbaa26db2007-07-08 17:51:39 -0500558#if defined(CONFIG_CMD_IMLS)
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000559static int do_imls_nor(void)
wdenk27b207f2003-07-24 23:38:38 +0000560{
561 flash_info_t *info;
562 int i, j;
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100563 void *hdr;
wdenk27b207f2003-07-24 23:38:38 +0000564
Marian Balakowicz1ee11802008-01-08 18:17:10 +0100565 for (i = 0, info = &flash_info[0];
Patrick Delaunay98150e72022-01-04 14:23:58 +0100566 i < CFI_FLASH_BANKS; ++i, ++info) {
Marian Balakowicz1ee11802008-01-08 18:17:10 +0100567
wdenk27b207f2003-07-24 23:38:38 +0000568 if (info->flash_id == FLASH_UNKNOWN)
569 goto next_bank;
Marian Balakowicz1ee11802008-01-08 18:17:10 +0100570 for (j = 0; j < info->sector_count; ++j) {
wdenk27b207f2003-07-24 23:38:38 +0000571
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100572 hdr = (void *)info->start[j];
573 if (!hdr)
wdenk27b207f2003-07-24 23:38:38 +0000574 goto next_sector;
575
Stephen Warren712fbcf2011-10-18 11:11:49 +0000576 switch (genimg_get_format(hdr)) {
Tom Rinic76c93a2019-05-23 07:14:07 -0400577#if defined(CONFIG_LEGACY_IMAGE_FORMAT)
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100578 case IMAGE_FORMAT_LEGACY:
Stephen Warren712fbcf2011-10-18 11:11:49 +0000579 if (!image_check_hcrc(hdr))
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100580 goto next_sector;
581
Stephen Warren712fbcf2011-10-18 11:11:49 +0000582 printf("Legacy Image at %08lX:\n", (ulong)hdr);
583 image_print_contents(hdr);
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100584
Stephen Warren712fbcf2011-10-18 11:11:49 +0000585 puts(" Verifying Checksum ... ");
586 if (!image_check_dcrc(hdr)) {
587 puts("Bad Data CRC\n");
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100588 } else {
Stephen Warren712fbcf2011-10-18 11:11:49 +0000589 puts("OK\n");
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100590 }
591 break;
Heiko Schocher21d29f72014-05-28 11:33:33 +0200592#endif
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100593#if defined(CONFIG_FIT)
594 case IMAGE_FORMAT_FIT:
Simon Glassc5819702021-02-15 17:08:09 -0700595 if (fit_check_format(hdr, IMAGE_SIZE_INVAL))
Marian Balakowicze32fea62008-03-11 12:35:20 +0100596 goto next_sector;
597
Stephen Warren712fbcf2011-10-18 11:11:49 +0000598 printf("FIT Image at %08lX:\n", (ulong)hdr);
599 fit_print_contents(hdr);
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100600 break;
601#endif
602 default:
wdenk27b207f2003-07-24 23:38:38 +0000603 goto next_sector;
wdenk5bb226e2003-11-17 21:14:37 +0000604 }
Marian Balakowiczd5934ad2008-02-04 08:28:09 +0100605
wdenkbdccc4f2003-08-05 17:43:17 +0000606next_sector: ;
wdenk27b207f2003-07-24 23:38:38 +0000607 }
wdenkbdccc4f2003-08-05 17:43:17 +0000608next_bank: ;
wdenk27b207f2003-07-24 23:38:38 +0000609 }
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000610 return 0;
611}
612#endif
613
614#if defined(CONFIG_CMD_IMLS_NAND)
Scott Wood151c06e2016-05-30 13:57:54 -0500615static int nand_imls_legacyimage(struct mtd_info *mtd, int nand_dev,
616 loff_t off, size_t len)
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000617{
618 void *imgdata;
619 int ret;
620
621 imgdata = malloc(len);
622 if (!imgdata) {
623 printf("May be a Legacy Image at NAND device %d offset %08llX:\n",
624 nand_dev, off);
625 printf(" Low memory(cannot allocate memory for image)\n");
626 return -ENOMEM;
627 }
628
Grygorii Strashkodbe78812017-01-31 15:37:03 -0600629 ret = nand_read_skip_bad(mtd, off, &len, NULL, mtd->size, imgdata);
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000630 if (ret < 0 && ret != -EUCLEAN) {
631 free(imgdata);
632 return ret;
633 }
634
635 if (!image_check_hcrc(imgdata)) {
636 free(imgdata);
637 return 0;
638 }
639
640 printf("Legacy Image at NAND device %d offset %08llX:\n",
641 nand_dev, off);
642 image_print_contents(imgdata);
643
644 puts(" Verifying Checksum ... ");
645 if (!image_check_dcrc(imgdata))
646 puts("Bad Data CRC\n");
647 else
648 puts("OK\n");
649
650 free(imgdata);
651
652 return 0;
653}
654
Scott Wood151c06e2016-05-30 13:57:54 -0500655static int nand_imls_fitimage(struct mtd_info *mtd, int nand_dev, loff_t off,
656 size_t len)
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000657{
658 void *imgdata;
659 int ret;
660
661 imgdata = malloc(len);
662 if (!imgdata) {
663 printf("May be a FIT Image at NAND device %d offset %08llX:\n",
664 nand_dev, off);
665 printf(" Low memory(cannot allocate memory for image)\n");
666 return -ENOMEM;
667 }
668
Grygorii Strashkodbe78812017-01-31 15:37:03 -0600669 ret = nand_read_skip_bad(mtd, off, &len, NULL, mtd->size, imgdata);
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000670 if (ret < 0 && ret != -EUCLEAN) {
671 free(imgdata);
672 return ret;
673 }
674
Simon Glassc5819702021-02-15 17:08:09 -0700675 if (fit_check_format(imgdata, IMAGE_SIZE_INVAL)) {
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000676 free(imgdata);
677 return 0;
678 }
679
680 printf("FIT Image at NAND device %d offset %08llX:\n", nand_dev, off);
681
682 fit_print_contents(imgdata);
683 free(imgdata);
684
685 return 0;
686}
687
688static int do_imls_nand(void)
689{
Scott Wood151c06e2016-05-30 13:57:54 -0500690 struct mtd_info *mtd;
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000691 int nand_dev = nand_curr_device;
692 size_t len;
693 loff_t off;
694 u32 buffer[16];
695
696 if (nand_dev < 0 || nand_dev >= CONFIG_SYS_MAX_NAND_DEVICE) {
697 puts("\nNo NAND devices available\n");
698 return -ENODEV;
699 }
700
701 printf("\n");
702
703 for (nand_dev = 0; nand_dev < CONFIG_SYS_MAX_NAND_DEVICE; nand_dev++) {
Grygorii Strashkof370b512017-06-26 19:12:54 -0500704 mtd = get_nand_dev_by_index(nand_dev);
Scott Wood151c06e2016-05-30 13:57:54 -0500705 if (!mtd->name || !mtd->size)
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000706 continue;
707
Scott Wood151c06e2016-05-30 13:57:54 -0500708 for (off = 0; off < mtd->size; off += mtd->erasesize) {
Simon Glassf3543e62022-09-06 20:26:52 -0600709 const struct legacy_img_hdr *header;
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000710 int ret;
711
Scott Wood151c06e2016-05-30 13:57:54 -0500712 if (nand_block_isbad(mtd, off))
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000713 continue;
714
715 len = sizeof(buffer);
716
Scott Wood151c06e2016-05-30 13:57:54 -0500717 ret = nand_read(mtd, off, &len, (u8 *)buffer);
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000718 if (ret < 0 && ret != -EUCLEAN) {
719 printf("NAND read error %d at offset %08llX\n",
720 ret, off);
721 continue;
722 }
723
724 switch (genimg_get_format(buffer)) {
Tom Rinic76c93a2019-05-23 07:14:07 -0400725#if defined(CONFIG_LEGACY_IMAGE_FORMAT)
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000726 case IMAGE_FORMAT_LEGACY:
Simon Glassf3543e62022-09-06 20:26:52 -0600727 header = (const struct legacy_img_hdr *)buffer;
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000728
729 len = image_get_image_size(header);
Scott Wood151c06e2016-05-30 13:57:54 -0500730 nand_imls_legacyimage(mtd, nand_dev, off, len);
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000731 break;
Heiko Schocher21d29f72014-05-28 11:33:33 +0200732#endif
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000733#if defined(CONFIG_FIT)
734 case IMAGE_FORMAT_FIT:
735 len = fit_get_size(buffer);
Scott Wood151c06e2016-05-30 13:57:54 -0500736 nand_imls_fitimage(mtd, nand_dev, off, len);
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000737 break;
738#endif
739 }
740 }
741 }
742
743 return 0;
744}
745#endif
746
747#if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND)
Simon Glass09140112020-05-10 11:40:03 -0600748static int do_imls(struct cmd_tbl *cmdtp, int flag, int argc,
749 char *const argv[])
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000750{
751 int ret_nor = 0, ret_nand = 0;
752
753#if defined(CONFIG_CMD_IMLS)
754 ret_nor = do_imls_nor();
755#endif
756
757#if defined(CONFIG_CMD_IMLS_NAND)
758 ret_nand = do_imls_nand();
759#endif
760
761 if (ret_nor)
762 return ret_nor;
763
764 if (ret_nand)
765 return ret_nand;
wdenk27b207f2003-07-24 23:38:38 +0000766
767 return (0);
768}
769
770U_BOOT_CMD(
771 imls, 1, 1, do_imls,
Peter Tyser2fb26042009-01-27 18:03:12 -0600772 "list all images found in flash",
wdenk27b207f2003-07-24 23:38:38 +0000773 "\n"
Vipin Kumar8fdf1e02012-12-16 22:32:48 +0000774 " - Prints information about all images found at sector/block\n"
775 " boundaries in nor/nand flash."
wdenk27b207f2003-07-24 23:38:38 +0000776);
Jon Loeliger90253172007-07-10 11:02:44 -0500777#endif