blob: 843ec6e0c2696380d176740bbb5864b05e46624b [file] [log] [blame]
wdenk47d1a6e2002-11-03 00:01:44 +00001/*
Detlev Zundel77094472009-07-13 16:01:18 +02002 * (C) Copyright 2000-2009
wdenk47d1a6e2002-11-03 00:01:44 +00003 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
wdenk47d1a6e2002-11-03 00:01:44 +00006 */
7
8/*
9 * Boot support
10 */
11#include <common.h>
Simon Glass3b5866d2014-06-12 07:24:46 -060012#include <bootm.h>
wdenk47d1a6e2002-11-03 00:01:44 +000013#include <command.h>
wdenk0893c472003-05-20 14:25:27 +000014#include <environment.h>
Simon Glass3b5866d2014-06-12 07:24:46 -060015#include <image.h>
Kumar Gala6d7bfa82008-02-27 21:51:47 -060016#include <lmb.h>
Simon Glass3b5866d2014-06-12 07:24:46 -060017#include <malloc.h>
18#include <nand.h>
wdenk47d1a6e2002-11-03 00:01:44 +000019#include <asm/byteorder.h>
Anatolij Gustschin18e73d92011-11-19 13:12:18 +000020#include <linux/compiler.h>
Simon Glass3b5866d2014-06-12 07:24:46 -060021#include <linux/ctype.h>
22#include <linux/err.h>
23#include <u-boot/zlib.h>
Peter Korsgaardf7440cd2009-11-19 11:37:51 +010024
Marian Balakowicz2df645e2008-01-08 18:17:10 +010025DECLARE_GLOBAL_DATA_PTR;
wdenk9dfa8d12002-12-08 09:53:23 +000026
Jon Loeliger54324d02007-07-08 17:51:39 -050027#if defined(CONFIG_CMD_IMI)
Stephen Warren6904b6e2011-10-18 11:11:49 +000028static int image_info(unsigned long addr);
wdenk47d1a6e2002-11-03 00:01:44 +000029#endif
wdenk874ac262003-07-24 23:38:38 +000030
Jon Loeliger54324d02007-07-08 17:51:39 -050031#if defined(CONFIG_CMD_IMLS)
wdenk874ac262003-07-24 23:38:38 +000032#include <flash.h>
Stefan Roesefb9a7302010-08-31 10:00:10 +020033#include <mtd/cfi_flash.h>
Marian Balakowicz513b4a12005-10-11 19:09:42 +020034extern flash_info_t flash_info[]; /* info for FLASH chips */
Vipin Kumar3df41b12012-12-16 22:32:48 +000035#endif
36
37#if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND)
Stephen Warren6904b6e2011-10-18 11:11:49 +000038static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
wdenk874ac262003-07-24 23:38:38 +000039#endif
Kumar Galabf3954f2008-10-21 17:25:44 -050040
Simon Schwarz6519bbf2011-09-02 00:50:31 +000041bootm_headers_t images; /* pointers to os/initrd/fdt images */
Stefan Roese5d5ce292006-03-13 11:16:36 +010042
Kumar Gala18178bc2008-10-21 17:25:45 -050043/* we overload the cmd field with our state machine info instead of a
44 * function pointer */
Frans Meulenbroeks6b419fb2010-02-25 10:12:13 +010045static cmd_tbl_t cmd_bootm_sub[] = {
Kumar Gala18178bc2008-10-21 17:25:45 -050046 U_BOOT_CMD_MKENT(start, 0, 1, (void *)BOOTM_STATE_START, "", ""),
47 U_BOOT_CMD_MKENT(loados, 0, 1, (void *)BOOTM_STATE_LOADOS, "", ""),
John Rigbyeea8e692010-10-13 13:57:35 -060048#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
Kumar Gala18178bc2008-10-21 17:25:45 -050049 U_BOOT_CMD_MKENT(ramdisk, 0, 1, (void *)BOOTM_STATE_RAMDISK, "", ""),
50#endif
51#ifdef CONFIG_OF_LIBFDT
52 U_BOOT_CMD_MKENT(fdt, 0, 1, (void *)BOOTM_STATE_FDT, "", ""),
53#endif
Kumar Gala18178bc2008-10-21 17:25:45 -050054 U_BOOT_CMD_MKENT(cmdline, 0, 1, (void *)BOOTM_STATE_OS_CMDLINE, "", ""),
Peter Tyser694a3932009-11-18 19:08:59 -060055 U_BOOT_CMD_MKENT(bdt, 0, 1, (void *)BOOTM_STATE_OS_BD_T, "", ""),
Kumar Gala18178bc2008-10-21 17:25:45 -050056 U_BOOT_CMD_MKENT(prep, 0, 1, (void *)BOOTM_STATE_OS_PREP, "", ""),
Simon Glass00134882013-06-11 11:14:48 -070057 U_BOOT_CMD_MKENT(fake, 0, 1, (void *)BOOTM_STATE_OS_FAKE_GO, "", ""),
Kumar Gala18178bc2008-10-21 17:25:45 -050058 U_BOOT_CMD_MKENT(go, 0, 1, (void *)BOOTM_STATE_OS_GO, "", ""),
59};
60
Kim Phillipsdc00a682012-10-29 13:34:31 +000061static int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc,
Stephen Warren6904b6e2011-10-18 11:11:49 +000062 char * const argv[])
Kumar Gala18178bc2008-10-21 17:25:45 -050063{
64 int ret = 0;
Simon Glass81afc3d2011-10-07 13:53:40 +000065 long state;
Kumar Gala18178bc2008-10-21 17:25:45 -050066 cmd_tbl_t *c;
Kumar Gala18178bc2008-10-21 17:25:45 -050067
Simon Glass794a9212013-06-11 11:14:46 -070068 c = find_cmd_tbl(argv[0], &cmd_bootm_sub[0], ARRAY_SIZE(cmd_bootm_sub));
69 argc--; argv++;
Kumar Gala18178bc2008-10-21 17:25:45 -050070
71 if (c) {
Simon Glass81afc3d2011-10-07 13:53:40 +000072 state = (long)c->cmd;
Simon Glass794a9212013-06-11 11:14:46 -070073 if (state == BOOTM_STATE_START)
Simon Glass3081e2e2013-06-11 11:14:47 -070074 state |= BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER;
Wolfgang Denk3b683112010-07-17 01:06:04 +020075 } else {
76 /* Unrecognized command */
Simon Glassa06dfc72011-12-10 08:44:01 +000077 return CMD_RET_USAGE;
Kumar Gala18178bc2008-10-21 17:25:45 -050078 }
79
Simon Glass3081e2e2013-06-11 11:14:47 -070080 if (state != BOOTM_STATE_START && images.state >= state) {
Stephen Warren6904b6e2011-10-18 11:11:49 +000081 printf("Trying to execute a command out of order\n");
Simon Glassa06dfc72011-12-10 08:44:01 +000082 return CMD_RET_USAGE;
Kumar Gala18178bc2008-10-21 17:25:45 -050083 }
84
Simon Glass3081e2e2013-06-11 11:14:47 -070085 ret = do_bootm_states(cmdtp, flag, argc, argv, state, &images, 0);
Kumar Gala18178bc2008-10-21 17:25:45 -050086
87 return ret;
88}
89
Kumar Galabd70bbe2008-08-15 08:24:41 -050090/*******************************************************************/
91/* bootm - boot application image from image in memory */
92/*******************************************************************/
Kumar Galabf3954f2008-10-21 17:25:44 -050093
Stephen Warren6904b6e2011-10-18 11:11:49 +000094int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
Kumar Galabd70bbe2008-08-15 08:24:41 -050095{
Wolfgang Denkd0813e52010-10-28 20:00:11 +020096#ifdef CONFIG_NEEDS_MANUAL_RELOC
Peter Tyser9057cbf2009-09-21 11:20:36 -050097 static int relocated = 0;
Kumar Galabf3954f2008-10-21 17:25:44 -050098
Kumar Galabf3954f2008-10-21 17:25:44 -050099 if (!relocated) {
100 int i;
Daniel Schwierzecka2187092013-01-07 06:54:52 +0000101
Daniel Schwierzecka2187092013-01-07 06:54:52 +0000102 /* relocate names of sub-command table */
103 for (i = 0; i < ARRAY_SIZE(cmd_bootm_sub); i++)
104 cmd_bootm_sub[i].name += gd->reloc_off;
105
Kumar Galabf3954f2008-10-21 17:25:44 -0500106 relocated = 1;
107 }
Peter Tyser9057cbf2009-09-21 11:20:36 -0500108#endif
Kumar Galabd70bbe2008-08-15 08:24:41 -0500109
Kumar Gala18178bc2008-10-21 17:25:45 -0500110 /* determine if we have a sub command */
Simon Glass794a9212013-06-11 11:14:46 -0700111 argc--; argv++;
112 if (argc > 0) {
Kumar Gala18178bc2008-10-21 17:25:45 -0500113 char *endp;
114
Simon Glass794a9212013-06-11 11:14:46 -0700115 simple_strtoul(argv[0], &endp, 16);
116 /* endp pointing to NULL means that argv[0] was just a
Kumar Gala18178bc2008-10-21 17:25:45 -0500117 * valid number, pass it along to the normal bootm processing
118 *
119 * If endp is ':' or '#' assume a FIT identifier so pass
120 * along for normal processing.
121 *
122 * Right now we assume the first arg should never be '-'
123 */
124 if ((*endp != 0) && (*endp != ':') && (*endp != '#'))
125 return do_bootm_subcommand(cmdtp, flag, argc, argv);
126 }
127
Simon Glass3081e2e2013-06-11 11:14:47 -0700128 return do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START |
129 BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER |
Tom Rini1008dc22013-09-23 14:20:37 -0400130 BOOTM_STATE_LOADOS |
131#if defined(CONFIG_PPC) || defined(CONFIG_MIPS)
132 BOOTM_STATE_OS_CMDLINE |
133#endif
Paul Burton8a39e8d2013-09-06 11:23:55 +0100134 BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
135 BOOTM_STATE_OS_GO, &images, 1);
wdenk47d1a6e2002-11-03 00:01:44 +0000136}
137
Mike Frysinger194c2e82011-06-05 13:43:02 +0000138int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd)
139{
140 const char *ep = getenv("autostart");
141
142 if (ep && !strcmp(ep, "yes")) {
143 char *local_args[2];
144 local_args[0] = (char *)cmd;
145 local_args[1] = NULL;
146 printf("Automatic boot of image at addr 0x%08lX ...\n", load_addr);
147 return do_bootm(cmdtp, 0, 1, local_args);
148 }
149
150 return 0;
151}
152
Kim Phillipsdc00a682012-10-29 13:34:31 +0000153#ifdef CONFIG_SYS_LONGHELP
154static char bootm_help_text[] =
Marian Balakowicz2df645e2008-01-08 18:17:10 +0100155 "[addr [arg ...]]\n - boot application image stored in memory\n"
156 "\tpassing arguments 'arg ...'; when booting a Linux kernel,\n"
157 "\t'arg' can be the address of an initrd image\n"
Marian Balakowiczd2160852008-01-31 13:20:07 +0100158#if defined(CONFIG_OF_LIBFDT)
Matthew McClintock6fb7c812006-06-28 10:41:37 -0500159 "\tWhen booting a Linux kernel which requires a flat device-tree\n"
Detlev Zundele6099162007-10-19 16:47:26 +0200160 "\ta third argument is required which is the address of the\n"
Matthew McClintock6fb7c812006-06-28 10:41:37 -0500161 "\tdevice-tree blob. To boot that kernel without an initrd image,\n"
162 "\tuse a '-' for the second argument. If you do not pass a third\n"
163 "\ta bd_info struct will be passed instead\n"
164#endif
Marian Balakowicz9f8e4aa2008-03-12 10:01:05 +0100165#if defined(CONFIG_FIT)
166 "\t\nFor the new multi component uImage format (FIT) addresses\n"
167 "\tmust be extened to include component or configuration unit name:\n"
168 "\taddr:<subimg_uname> - direct component image specification\n"
169 "\taddr#<conf_uname> - configuration specification\n"
170 "\tUse iminfo command to get the list of existing component\n"
171 "\timages and configurations.\n"
172#endif
Kumar Gala18178bc2008-10-21 17:25:45 -0500173 "\nSub-commands to do part of the bootm sequence. The sub-commands "
174 "must be\n"
175 "issued in the order below (it's ok to not issue all sub-commands):\n"
176 "\tstart [addr [arg ...]]\n"
177 "\tloados - load OS image\n"
Daniel Schwierzeckf2f2ec92013-02-26 04:54:19 +0000178#if defined(CONFIG_SYS_BOOT_RAMDISK_HIGH)
Kumar Gala18178bc2008-10-21 17:25:45 -0500179 "\tramdisk - relocate initrd, set env initrd_start/initrd_end\n"
180#endif
181#if defined(CONFIG_OF_LIBFDT)
182 "\tfdt - relocate flat device tree\n"
183#endif
Kumar Gala18178bc2008-10-21 17:25:45 -0500184 "\tcmdline - OS specific command line processing/setup\n"
Peter Tyser694a3932009-11-18 19:08:59 -0600185 "\tbdt - OS specific bd_t processing\n"
Kumar Gala18178bc2008-10-21 17:25:45 -0500186 "\tprep - OS specific prep before relocation or go\n"
Kim Phillipsdc00a682012-10-29 13:34:31 +0000187 "\tgo - start OS";
188#endif
189
190U_BOOT_CMD(
191 bootm, CONFIG_SYS_MAXARGS, 1, do_bootm,
192 "boot application image from memory", bootm_help_text
wdenk57b2d802003-06-27 21:31:46 +0000193);
wdenk47d1a6e2002-11-03 00:01:44 +0000194
Marian Balakowicz2df645e2008-01-08 18:17:10 +0100195/*******************************************************************/
196/* bootd - boot default image */
197/*******************************************************************/
Jon Loeliger54324d02007-07-08 17:51:39 -0500198#if defined(CONFIG_CMD_BOOTD)
Stephen Warren6904b6e2011-10-18 11:11:49 +0000199int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
wdenk47d1a6e2002-11-03 00:01:44 +0000200{
Thomas Betker5ac00262014-06-05 20:07:56 +0200201 return run_command(getenv("bootcmd"), flag);
wdenk47d1a6e2002-11-03 00:01:44 +0000202}
wdenk47d1a6e2002-11-03 00:01:44 +0000203
wdenkf287a242003-07-01 21:06:45 +0000204U_BOOT_CMD(
Marian Balakowicz2df645e2008-01-08 18:17:10 +0100205 boot, 1, 1, do_bootd,
Peter Tyserdfb72b82009-01-27 18:03:12 -0600206 "boot default, i.e., run 'bootcmd'",
Wolfgang Denkc54781c2009-05-24 17:06:54 +0200207 ""
wdenk3086a972003-06-28 23:11:04 +0000208);
wdenk47d1a6e2002-11-03 00:01:44 +0000209
wdenk3086a972003-06-28 23:11:04 +0000210/* keep old command name "bootd" for backward compatibility */
wdenkf287a242003-07-01 21:06:45 +0000211U_BOOT_CMD(
Marian Balakowicz2df645e2008-01-08 18:17:10 +0100212 bootd, 1, 1, do_bootd,
Peter Tyserdfb72b82009-01-27 18:03:12 -0600213 "boot default, i.e., run 'bootcmd'",
Wolfgang Denkc54781c2009-05-24 17:06:54 +0200214 ""
wdenk57b2d802003-06-27 21:31:46 +0000215);
wdenk47d1a6e2002-11-03 00:01:44 +0000216
wdenk47d1a6e2002-11-03 00:01:44 +0000217#endif
wdenk47d1a6e2002-11-03 00:01:44 +0000218
wdenk47d1a6e2002-11-03 00:01:44 +0000219
Marian Balakowicz2df645e2008-01-08 18:17:10 +0100220/*******************************************************************/
221/* iminfo - print header info for a requested image */
222/*******************************************************************/
Jon Loeliger54324d02007-07-08 17:51:39 -0500223#if defined(CONFIG_CMD_IMI)
Kim Phillipsdc00a682012-10-29 13:34:31 +0000224static int do_iminfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
wdenk47d1a6e2002-11-03 00:01:44 +0000225{
226 int arg;
227 ulong addr;
Marian Balakowicz2df645e2008-01-08 18:17:10 +0100228 int rcode = 0;
wdenk47d1a6e2002-11-03 00:01:44 +0000229
wdenk47d1a6e2002-11-03 00:01:44 +0000230 if (argc < 2) {
Stephen Warren6904b6e2011-10-18 11:11:49 +0000231 return image_info(load_addr);
wdenk47d1a6e2002-11-03 00:01:44 +0000232 }
wdenk47d1a6e2002-11-03 00:01:44 +0000233
Marian Balakowicz2df645e2008-01-08 18:17:10 +0100234 for (arg = 1; arg < argc; ++arg) {
Stephen Warren6904b6e2011-10-18 11:11:49 +0000235 addr = simple_strtoul(argv[arg], NULL, 16);
236 if (image_info(addr) != 0)
Marian Balakowicz2df645e2008-01-08 18:17:10 +0100237 rcode = 1;
wdenk47d1a6e2002-11-03 00:01:44 +0000238 }
239 return rcode;
240}
wdenk47d1a6e2002-11-03 00:01:44 +0000241
Stephen Warren6904b6e2011-10-18 11:11:49 +0000242static int image_info(ulong addr)
wdenk47d1a6e2002-11-03 00:01:44 +0000243{
Marian Balakowiczdbdd16a2008-02-04 08:28:09 +0100244 void *hdr = (void *)addr;
wdenk47d1a6e2002-11-03 00:01:44 +0000245
Stephen Warren6904b6e2011-10-18 11:11:49 +0000246 printf("\n## Checking Image at %08lx ...\n", addr);
wdenk47d1a6e2002-11-03 00:01:44 +0000247
Stephen Warren6904b6e2011-10-18 11:11:49 +0000248 switch (genimg_get_format(hdr)) {
Heiko Schocher515eb122014-05-28 11:33:33 +0200249#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
Marian Balakowiczdbdd16a2008-02-04 08:28:09 +0100250 case IMAGE_FORMAT_LEGACY:
Stephen Warren6904b6e2011-10-18 11:11:49 +0000251 puts(" Legacy image found\n");
252 if (!image_check_magic(hdr)) {
253 puts(" Bad Magic Number\n");
Marian Balakowiczdbdd16a2008-02-04 08:28:09 +0100254 return 1;
255 }
wdenk47d1a6e2002-11-03 00:01:44 +0000256
Stephen Warren6904b6e2011-10-18 11:11:49 +0000257 if (!image_check_hcrc(hdr)) {
258 puts(" Bad Header Checksum\n");
Marian Balakowiczdbdd16a2008-02-04 08:28:09 +0100259 return 1;
wdenk47d1a6e2002-11-03 00:01:44 +0000260 }
261
Stephen Warren6904b6e2011-10-18 11:11:49 +0000262 image_print_contents(hdr);
wdenk47d1a6e2002-11-03 00:01:44 +0000263
Stephen Warren6904b6e2011-10-18 11:11:49 +0000264 puts(" Verifying Checksum ... ");
265 if (!image_check_dcrc(hdr)) {
266 puts(" Bad Data CRC\n");
Marian Balakowiczdbdd16a2008-02-04 08:28:09 +0100267 return 1;
wdenk47d1a6e2002-11-03 00:01:44 +0000268 }
Stephen Warren6904b6e2011-10-18 11:11:49 +0000269 puts("OK\n");
Marian Balakowiczdbdd16a2008-02-04 08:28:09 +0100270 return 0;
Heiko Schocher515eb122014-05-28 11:33:33 +0200271#endif
Marian Balakowiczdbdd16a2008-02-04 08:28:09 +0100272#if defined(CONFIG_FIT)
273 case IMAGE_FORMAT_FIT:
Stephen Warren6904b6e2011-10-18 11:11:49 +0000274 puts(" FIT image found\n");
wdenk47d1a6e2002-11-03 00:01:44 +0000275
Stephen Warren6904b6e2011-10-18 11:11:49 +0000276 if (!fit_check_format(hdr)) {
277 puts("Bad FIT image format!\n");
Marian Balakowiczcc1fd912008-03-11 12:35:20 +0100278 return 1;
wdenk47d1a6e2002-11-03 00:01:44 +0000279 }
280
Stephen Warren6904b6e2011-10-18 11:11:49 +0000281 fit_print_contents(hdr);
Bartlomiej Sieka03797f52008-09-09 12:58:16 +0200282
Simon Glass7428ad12013-05-07 06:11:57 +0000283 if (!fit_all_image_verify(hdr)) {
Stephen Warren6904b6e2011-10-18 11:11:49 +0000284 puts("Bad hash in FIT image!\n");
Bartlomiej Sieka03797f52008-09-09 12:58:16 +0200285 return 1;
286 }
287
Marian Balakowiczdbdd16a2008-02-04 08:28:09 +0100288 return 0;
wdenk47d1a6e2002-11-03 00:01:44 +0000289#endif
Marian Balakowiczdbdd16a2008-02-04 08:28:09 +0100290 default:
Stephen Warren6904b6e2011-10-18 11:11:49 +0000291 puts("Unknown image format!\n");
Marian Balakowiczdbdd16a2008-02-04 08:28:09 +0100292 break;
wdenk47d1a6e2002-11-03 00:01:44 +0000293 }
wdenk47d1a6e2002-11-03 00:01:44 +0000294
Marian Balakowiczdbdd16a2008-02-04 08:28:09 +0100295 return 1;
wdenk47d1a6e2002-11-03 00:01:44 +0000296}
wdenk47d1a6e2002-11-03 00:01:44 +0000297
wdenkf287a242003-07-01 21:06:45 +0000298U_BOOT_CMD(
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200299 iminfo, CONFIG_SYS_MAXARGS, 1, do_iminfo,
Peter Tyserdfb72b82009-01-27 18:03:12 -0600300 "print header information for application image",
wdenk57b2d802003-06-27 21:31:46 +0000301 "addr [addr ...]\n"
302 " - print header information for application image starting at\n"
303 " address 'addr' in memory; this includes verification of the\n"
Wolfgang Denkc54781c2009-05-24 17:06:54 +0200304 " image contents (magic number, header and payload checksums)"
wdenk57b2d802003-06-27 21:31:46 +0000305);
wdenk47d1a6e2002-11-03 00:01:44 +0000306#endif
307
308
Marian Balakowicz2df645e2008-01-08 18:17:10 +0100309/*******************************************************************/
310/* imls - list all images found in flash */
311/*******************************************************************/
Jon Loeliger54324d02007-07-08 17:51:39 -0500312#if defined(CONFIG_CMD_IMLS)
Vipin Kumar3df41b12012-12-16 22:32:48 +0000313static int do_imls_nor(void)
wdenk874ac262003-07-24 23:38:38 +0000314{
315 flash_info_t *info;
316 int i, j;
Marian Balakowiczdbdd16a2008-02-04 08:28:09 +0100317 void *hdr;
wdenk47d1a6e2002-11-03 00:01:44 +0000318
Marian Balakowicz2df645e2008-01-08 18:17:10 +0100319 for (i = 0, info = &flash_info[0];
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200320 i < CONFIG_SYS_MAX_FLASH_BANKS; ++i, ++info) {
wdenk47d1a6e2002-11-03 00:01:44 +0000321
wdenk874ac262003-07-24 23:38:38 +0000322 if (info->flash_id == FLASH_UNKNOWN)
323 goto next_bank;
Marian Balakowicz2df645e2008-01-08 18:17:10 +0100324 for (j = 0; j < info->sector_count; ++j) {
wdenk47d1a6e2002-11-03 00:01:44 +0000325
Marian Balakowiczdbdd16a2008-02-04 08:28:09 +0100326 hdr = (void *)info->start[j];
327 if (!hdr)
Marian Balakowicz41d71ed2008-01-08 18:14:09 +0100328 goto next_sector;
wdenk47d1a6e2002-11-03 00:01:44 +0000329
Stephen Warren6904b6e2011-10-18 11:11:49 +0000330 switch (genimg_get_format(hdr)) {
Heiko Schocher515eb122014-05-28 11:33:33 +0200331#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
Marian Balakowiczdbdd16a2008-02-04 08:28:09 +0100332 case IMAGE_FORMAT_LEGACY:
Stephen Warren6904b6e2011-10-18 11:11:49 +0000333 if (!image_check_hcrc(hdr))
Marian Balakowiczdbdd16a2008-02-04 08:28:09 +0100334 goto next_sector;
wdenk47d1a6e2002-11-03 00:01:44 +0000335
Stephen Warren6904b6e2011-10-18 11:11:49 +0000336 printf("Legacy Image at %08lX:\n", (ulong)hdr);
337 image_print_contents(hdr);
wdenk47d1a6e2002-11-03 00:01:44 +0000338
Stephen Warren6904b6e2011-10-18 11:11:49 +0000339 puts(" Verifying Checksum ... ");
340 if (!image_check_dcrc(hdr)) {
341 puts("Bad Data CRC\n");
Marian Balakowiczdbdd16a2008-02-04 08:28:09 +0100342 } else {
Stephen Warren6904b6e2011-10-18 11:11:49 +0000343 puts("OK\n");
Marian Balakowiczdbdd16a2008-02-04 08:28:09 +0100344 }
345 break;
Heiko Schocher515eb122014-05-28 11:33:33 +0200346#endif
Marian Balakowiczdbdd16a2008-02-04 08:28:09 +0100347#if defined(CONFIG_FIT)
348 case IMAGE_FORMAT_FIT:
Stephen Warren6904b6e2011-10-18 11:11:49 +0000349 if (!fit_check_format(hdr))
Marian Balakowiczcc1fd912008-03-11 12:35:20 +0100350 goto next_sector;
wdenk47d1a6e2002-11-03 00:01:44 +0000351
Stephen Warren6904b6e2011-10-18 11:11:49 +0000352 printf("FIT Image at %08lX:\n", (ulong)hdr);
353 fit_print_contents(hdr);
Marian Balakowiczdbdd16a2008-02-04 08:28:09 +0100354 break;
355#endif
356 default:
357 goto next_sector;
wdenk47d1a6e2002-11-03 00:01:44 +0000358 }
Marian Balakowiczdbdd16a2008-02-04 08:28:09 +0100359
wdenk0a658552003-08-05 17:43:17 +0000360next_sector: ;
wdenk47d1a6e2002-11-03 00:01:44 +0000361 }
wdenk0a658552003-08-05 17:43:17 +0000362next_bank: ;
wdenk47d1a6e2002-11-03 00:01:44 +0000363 }
Vipin Kumar3df41b12012-12-16 22:32:48 +0000364 return 0;
365}
366#endif
367
368#if defined(CONFIG_CMD_IMLS_NAND)
369static int nand_imls_legacyimage(nand_info_t *nand, int nand_dev, loff_t off,
370 size_t len)
371{
372 void *imgdata;
373 int ret;
374
375 imgdata = malloc(len);
376 if (!imgdata) {
377 printf("May be a Legacy Image at NAND device %d offset %08llX:\n",
378 nand_dev, off);
379 printf(" Low memory(cannot allocate memory for image)\n");
380 return -ENOMEM;
381 }
382
383 ret = nand_read_skip_bad(nand, off, &len,
384 imgdata);
385 if (ret < 0 && ret != -EUCLEAN) {
386 free(imgdata);
387 return ret;
388 }
389
390 if (!image_check_hcrc(imgdata)) {
391 free(imgdata);
392 return 0;
393 }
394
395 printf("Legacy Image at NAND device %d offset %08llX:\n",
396 nand_dev, off);
397 image_print_contents(imgdata);
398
399 puts(" Verifying Checksum ... ");
400 if (!image_check_dcrc(imgdata))
401 puts("Bad Data CRC\n");
402 else
403 puts("OK\n");
404
405 free(imgdata);
406
407 return 0;
408}
409
410static int nand_imls_fitimage(nand_info_t *nand, int nand_dev, loff_t off,
411 size_t len)
412{
413 void *imgdata;
414 int ret;
415
416 imgdata = malloc(len);
417 if (!imgdata) {
418 printf("May be a FIT Image at NAND device %d offset %08llX:\n",
419 nand_dev, off);
420 printf(" Low memory(cannot allocate memory for image)\n");
421 return -ENOMEM;
422 }
wdenk47d1a6e2002-11-03 00:01:44 +0000423
Vipin Kumar3df41b12012-12-16 22:32:48 +0000424 ret = nand_read_skip_bad(nand, off, &len,
425 imgdata);
426 if (ret < 0 && ret != -EUCLEAN) {
427 free(imgdata);
428 return ret;
429 }
430
431 if (!fit_check_format(imgdata)) {
432 free(imgdata);
433 return 0;
434 }
435
436 printf("FIT Image at NAND device %d offset %08llX:\n", nand_dev, off);
437
438 fit_print_contents(imgdata);
439 free(imgdata);
440
441 return 0;
442}
443
444static int do_imls_nand(void)
445{
446 nand_info_t *nand;
447 int nand_dev = nand_curr_device;
448 size_t len;
449 loff_t off;
450 u32 buffer[16];
451
452 if (nand_dev < 0 || nand_dev >= CONFIG_SYS_MAX_NAND_DEVICE) {
453 puts("\nNo NAND devices available\n");
454 return -ENODEV;
455 }
456
457 printf("\n");
458
459 for (nand_dev = 0; nand_dev < CONFIG_SYS_MAX_NAND_DEVICE; nand_dev++) {
460 nand = &nand_info[nand_dev];
461 if (!nand->name || !nand->size)
462 continue;
463
464 for (off = 0; off < nand->size; off += nand->erasesize) {
465 const image_header_t *header;
466 int ret;
467
468 if (nand_block_isbad(nand, off))
469 continue;
470
471 len = sizeof(buffer);
472
473 ret = nand_read(nand, off, &len, (u8 *)buffer);
474 if (ret < 0 && ret != -EUCLEAN) {
475 printf("NAND read error %d at offset %08llX\n",
476 ret, off);
477 continue;
478 }
479
480 switch (genimg_get_format(buffer)) {
Heiko Schocher515eb122014-05-28 11:33:33 +0200481#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
Vipin Kumar3df41b12012-12-16 22:32:48 +0000482 case IMAGE_FORMAT_LEGACY:
483 header = (const image_header_t *)buffer;
484
485 len = image_get_image_size(header);
486 nand_imls_legacyimage(nand, nand_dev, off, len);
487 break;
Heiko Schocher515eb122014-05-28 11:33:33 +0200488#endif
Vipin Kumar3df41b12012-12-16 22:32:48 +0000489#if defined(CONFIG_FIT)
490 case IMAGE_FORMAT_FIT:
491 len = fit_get_size(buffer);
492 nand_imls_fitimage(nand, nand_dev, off, len);
493 break;
494#endif
495 }
496 }
497 }
498
499 return 0;
500}
501#endif
502
503#if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND)
504static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
505{
506 int ret_nor = 0, ret_nand = 0;
507
508#if defined(CONFIG_CMD_IMLS)
509 ret_nor = do_imls_nor();
510#endif
511
512#if defined(CONFIG_CMD_IMLS_NAND)
513 ret_nand = do_imls_nand();
514#endif
515
516 if (ret_nor)
517 return ret_nor;
518
519 if (ret_nand)
520 return ret_nand;
521
wdenk874ac262003-07-24 23:38:38 +0000522 return (0);
523}
wdenk47d1a6e2002-11-03 00:01:44 +0000524
wdenk874ac262003-07-24 23:38:38 +0000525U_BOOT_CMD(
526 imls, 1, 1, do_imls,
Peter Tyserdfb72b82009-01-27 18:03:12 -0600527 "list all images found in flash",
wdenk874ac262003-07-24 23:38:38 +0000528 "\n"
Vipin Kumar3df41b12012-12-16 22:32:48 +0000529 " - Prints information about all images found at sector/block\n"
530 " boundaries in nor/nand flash."
wdenk874ac262003-07-24 23:38:38 +0000531);
wdenk47d1a6e2002-11-03 00:01:44 +0000532#endif
533
Marek Vasutcf41a9b2012-03-14 21:52:45 +0000534#ifdef CONFIG_CMD_BOOTZ
535
Simon Glass5f1afdd2013-07-04 13:26:10 -0700536int __weak bootz_setup(ulong image, ulong *start, ulong *end)
Marek Vasutcf41a9b2012-03-14 21:52:45 +0000537{
538 /* Please define bootz_setup() for your platform */
539
540 puts("Your platform's zImage format isn't supported yet!\n");
541 return -1;
542}
Marek Vasutcf41a9b2012-03-14 21:52:45 +0000543
544/*
545 * zImage booting support
546 */
547static int bootz_start(cmd_tbl_t *cmdtp, int flag, int argc,
548 char * const argv[], bootm_headers_t *images)
549{
550 int ret;
Simon Glass5f1afdd2013-07-04 13:26:10 -0700551 ulong zi_start, zi_end;
Marek Vasutcf41a9b2012-03-14 21:52:45 +0000552
Simon Glass3081e2e2013-06-11 11:14:47 -0700553 ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
554 images, 1);
Marek Vasutcf41a9b2012-03-14 21:52:45 +0000555
556 /* Setup Linux kernel zImage entry point */
Tom Rini6e5dac42013-07-09 15:32:34 -0400557 if (!argc) {
Marek Vasutcf41a9b2012-03-14 21:52:45 +0000558 images->ep = load_addr;
559 debug("* kernel: default image load address = 0x%08lx\n",
560 load_addr);
561 } else {
Tom Rini6e5dac42013-07-09 15:32:34 -0400562 images->ep = simple_strtoul(argv[0], NULL, 16);
Marek Vasutcf41a9b2012-03-14 21:52:45 +0000563 debug("* kernel: cmdline image address = 0x%08lx\n",
564 images->ep);
565 }
566
Simon Glass5f1afdd2013-07-04 13:26:10 -0700567 ret = bootz_setup(images->ep, &zi_start, &zi_end);
Marek Vasutcf41a9b2012-03-14 21:52:45 +0000568 if (ret != 0)
569 return 1;
570
571 lmb_reserve(&images->lmb, images->ep, zi_end - zi_start);
572
Tom Rini1ab61472013-07-09 15:33:25 -0400573 /*
574 * Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not
575 * have a header that provide this informaiton.
576 */
Simon Glass3b5866d2014-06-12 07:24:46 -0600577 if (bootm_find_ramdisk_fdt(flag, argc, argv))
Tom Rini6e5dac42013-07-09 15:32:34 -0400578 return 1;
579
Tom Rini6e5dac42013-07-09 15:32:34 -0400580 return 0;
Marek Vasutcf41a9b2012-03-14 21:52:45 +0000581}
582
Rob Herringc88e1bf2012-12-02 21:00:23 -0600583int do_bootz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
Marek Vasutcf41a9b2012-03-14 21:52:45 +0000584{
Simon Glass3081e2e2013-06-11 11:14:47 -0700585 int ret;
Marek Vasutcf41a9b2012-03-14 21:52:45 +0000586
Tom Rini6e5dac42013-07-09 15:32:34 -0400587 /* Consume 'bootz' */
588 argc--; argv++;
589
Marek Vasutcf41a9b2012-03-14 21:52:45 +0000590 if (bootz_start(cmdtp, flag, argc, argv, &images))
591 return 1;
592
Simon Glass917f6842013-07-04 13:26:08 -0700593 /*
594 * We are doing the BOOTM_STATE_LOADOS state ourselves, so must
595 * disable interrupts ourselves
596 */
597 bootm_disable_interrupts();
598
Simon Glass42bca362013-07-04 13:26:11 -0700599 images.os.os = IH_OS_LINUX;
Simon Glass3081e2e2013-06-11 11:14:47 -0700600 ret = do_bootm_states(cmdtp, flag, argc, argv,
Simon Glass42bca362013-07-04 13:26:11 -0700601 BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
602 BOOTM_STATE_OS_GO,
Simon Glass00134882013-06-11 11:14:48 -0700603 &images, 1);
Marek Vasutcf41a9b2012-03-14 21:52:45 +0000604
Simon Glass3081e2e2013-06-11 11:14:47 -0700605 return ret;
Marek Vasutcf41a9b2012-03-14 21:52:45 +0000606}
607
Kim Phillipsdc00a682012-10-29 13:34:31 +0000608#ifdef CONFIG_SYS_LONGHELP
609static char bootz_help_text[] =
Marek Vasut28850d02012-03-18 11:47:58 +0000610 "[addr [initrd[:size]] [fdt]]\n"
611 " - boot Linux zImage stored in memory\n"
Marek Vasutcf41a9b2012-03-14 21:52:45 +0000612 "\tThe argument 'initrd' is optional and specifies the address\n"
Marek Vasut28850d02012-03-18 11:47:58 +0000613 "\tof the initrd in memory. The optional argument ':size' allows\n"
614 "\tspecifying the size of RAW initrd.\n"
Marek Vasutcf41a9b2012-03-14 21:52:45 +0000615#if defined(CONFIG_OF_LIBFDT)
616 "\tWhen booting a Linux kernel which requires a flat device-tree\n"
617 "\ta third argument is required which is the address of the\n"
618 "\tdevice-tree blob. To boot that kernel without an initrd image,\n"
619 "\tuse a '-' for the second argument. If you do not pass a third\n"
620 "\ta bd_info struct will be passed instead\n"
621#endif
Kim Phillipsdc00a682012-10-29 13:34:31 +0000622 "";
623#endif
624
625U_BOOT_CMD(
626 bootz, CONFIG_SYS_MAXARGS, 1, do_bootz,
627 "boot Linux zImage image from memory", bootz_help_text
Marek Vasutcf41a9b2012-03-14 21:52:45 +0000628);
629#endif /* CONFIG_CMD_BOOTZ */
Tom Rini5ce62cd2014-08-14 06:42:36 -0400630
631#ifdef CONFIG_CMD_BOOTI
632/* See Documentation/arm64/booting.txt in the Linux kernel */
633struct Image_header {
634 uint32_t code0; /* Executable code */
635 uint32_t code1; /* Executable code */
636 uint64_t text_offset; /* Image load offset, LE */
637 uint64_t image_size; /* Effective Image size, LE */
638 uint64_t res1; /* reserved */
639 uint64_t res2; /* reserved */
640 uint64_t res3; /* reserved */
641 uint64_t res4; /* reserved */
642 uint32_t magic; /* Magic number */
643 uint32_t res5;
644};
645
646#define LINUX_ARM64_IMAGE_MAGIC 0x644d5241
647
648static int booti_setup(bootm_headers_t *images)
649{
650 struct Image_header *ih;
651 uint64_t dst;
652
653 ih = (struct Image_header *)map_sysmem(images->ep, 0);
654
655 if (ih->magic != le32_to_cpu(LINUX_ARM64_IMAGE_MAGIC)) {
656 puts("Bad Linux ARM64 Image magic!\n");
657 return 1;
658 }
659
660 if (ih->image_size == 0) {
661 puts("Image lacks image_size field, assuming 16MiB\n");
662 ih->image_size = (16 << 20);
663 }
664
665 /*
666 * If we are not at the correct run-time location, set the new
667 * correct location and then move the image there.
668 */
669 dst = gd->bd->bi_dram[0].start + le32_to_cpu(ih->text_offset);
670 if (images->ep != dst) {
671 void *src;
672
673 debug("Moving Image from 0x%lx to 0x%llx\n", images->ep, dst);
674
675 src = (void *)images->ep;
676 images->ep = dst;
677 memmove((void *)dst, src, le32_to_cpu(ih->image_size));
678 }
679
680 return 0;
681}
682
683/*
684 * Image booting support
685 */
686static int booti_start(cmd_tbl_t *cmdtp, int flag, int argc,
687 char * const argv[], bootm_headers_t *images)
688{
689 int ret;
690 struct Image_header *ih;
691
692 ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
693 images, 1);
694
695 /* Setup Linux kernel Image entry point */
696 if (!argc) {
697 images->ep = load_addr;
698 debug("* kernel: default image load address = 0x%08lx\n",
699 load_addr);
700 } else {
701 images->ep = simple_strtoul(argv[0], NULL, 16);
702 debug("* kernel: cmdline image address = 0x%08lx\n",
703 images->ep);
704 }
705
706 ret = booti_setup(images);
707 if (ret != 0)
708 return 1;
709
710 ih = (struct Image_header *)map_sysmem(images->ep, 0);
711
712 lmb_reserve(&images->lmb, images->ep, le32_to_cpu(ih->image_size));
713
714 /*
715 * Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not
716 * have a header that provide this informaiton.
717 */
718 if (bootm_find_ramdisk_fdt(flag, argc, argv))
719 return 1;
720
721 return 0;
722}
723
724int do_booti(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
725{
726 int ret;
727
728 /* Consume 'booti' */
729 argc--; argv++;
730
731 if (booti_start(cmdtp, flag, argc, argv, &images))
732 return 1;
733
734 /*
735 * We are doing the BOOTM_STATE_LOADOS state ourselves, so must
736 * disable interrupts ourselves
737 */
738 bootm_disable_interrupts();
739
740 images.os.os = IH_OS_LINUX;
741 ret = do_bootm_states(cmdtp, flag, argc, argv,
742 BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
743 BOOTM_STATE_OS_GO,
744 &images, 1);
745
746 return ret;
747}
748
749#ifdef CONFIG_SYS_LONGHELP
750static char booti_help_text[] =
751 "[addr [initrd[:size]] [fdt]]\n"
752 " - boot Linux Image stored in memory\n"
753 "\tThe argument 'initrd' is optional and specifies the address\n"
754 "\tof the initrd in memory. The optional argument ':size' allows\n"
755 "\tspecifying the size of RAW initrd.\n"
756#if defined(CONFIG_OF_LIBFDT)
757 "\tSince booting a Linux kernelrequires a flat device-tree\n"
758 "\ta third argument is required which is the address of the\n"
759 "\tdevice-tree blob. To boot that kernel without an initrd image,\n"
760 "\tuse a '-' for the second argument.\n"
761#endif
762 "";
763#endif
764
765U_BOOT_CMD(
766 booti, CONFIG_SYS_MAXARGS, 1, do_booti,
767 "boot arm64 Linux Image image from memory", booti_help_text
768);
769#endif /* CONFIG_CMD_BOOTI */