* (C) Copyright 2000-2009
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
+ * SPDX-License-Identifier: GPL-2.0+
*/
#include <asm/io.h>
#include <linux/compiler.h>
-#if defined(CONFIG_CMD_USB)
-#include <usb.h>
+#if defined(CONFIG_BOOTM_VXWORKS) && \
+ (defined(CONFIG_PPC) || defined(CONFIG_ARM))
+#include <vxworks.h>
#endif
-#ifdef CONFIG_SYS_HUSH_PARSER
-#include <hush.h>
+#if defined(CONFIG_CMD_USB)
+#include <usb.h>
#endif
#if defined(CONFIG_OF_LIBFDT)
static void fixup_silent_linux(void);
#endif
+static int do_bootm_standalone(int flag, int argc, char * const argv[],
+ bootm_headers_t *images);
+
static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
char * const argv[], bootm_headers_t *images,
ulong *os_data, ulong *os_len);
#if defined(CONFIG_BOOTM_PLAN9)
static boot_os_fn do_bootm_plan9;
#endif
-#if defined(CONFIG_CMD_ELF)
+#if defined(CONFIG_BOOTM_VXWORKS) && \
+ (defined(CONFIG_PPC) || defined(CONFIG_ARM))
static boot_os_fn do_bootm_vxworks;
+#endif
+#if defined(CONFIG_CMD_ELF)
static boot_os_fn do_bootm_qnxelf;
int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
int do_bootelf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
#endif
static boot_os_fn *boot_os[] = {
+ [IH_OS_U_BOOT] = do_bootm_standalone,
#ifdef CONFIG_BOOTM_LINUX
[IH_OS_LINUX] = do_bootm_linux,
#endif
#if defined(CONFIG_BOOTM_PLAN9)
[IH_OS_PLAN9] = do_bootm_plan9,
#endif
-#if defined(CONFIG_CMD_ELF)
+#if defined(CONFIG_BOOTM_VXWORKS) && \
+ (defined(CONFIG_PPC) || defined(CONFIG_ARM))
[IH_OS_VXWORKS] = do_bootm_vxworks,
+#endif
+#if defined(CONFIG_CMD_ELF)
[IH_OS_QNX] = do_bootm_qnxelf,
#endif
#ifdef CONFIG_INTEGRITY
char * const argv[])
{
const void *os_hdr;
+ bool ep_found = false;
/* get kernel image header, start address and length */
os_hdr = boot_get_kernel(cmdtp, flag, argc, argv,
/* get image parameters */
switch (genimg_get_format(os_hdr)) {
+#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
case IMAGE_FORMAT_LEGACY:
images.os.type = image_get_type(os_hdr);
images.os.comp = image_get_comp(os_hdr);
images.os.end = image_get_image_end(os_hdr);
images.os.load = image_get_load(os_hdr);
break;
+#endif
#if defined(CONFIG_FIT)
case IMAGE_FORMAT_FIT:
if (fit_image_get_type(images.fit_hdr_os,
}
break;
#endif
+#ifdef CONFIG_ANDROID_BOOT_IMAGE
+ case IMAGE_FORMAT_ANDROID:
+ images.os.type = IH_TYPE_KERNEL;
+ images.os.comp = IH_COMP_NONE;
+ images.os.os = IH_OS_LINUX;
+ images.ep = images.os.load;
+ ep_found = true;
+
+ images.os.end = android_image_get_end(os_hdr);
+ images.os.load = android_image_get_kload(os_hdr);
+ break;
+#endif
default:
puts("ERROR: unknown image format type!\n");
return 1;
return 1;
}
#endif
- } else {
+ } else if (!ep_found) {
puts("Could not find kernel entry point!\n");
return 1;
}
if (((images.os.type == IH_TYPE_KERNEL) ||
(images.os.type == IH_TYPE_KERNEL_NOLOAD) ||
(images.os.type == IH_TYPE_MULTI)) &&
- (images.os.os == IH_OS_LINUX)) {
+ (images.os.os == IH_OS_LINUX ||
+ images.os.os == IH_OS_VXWORKS)) {
if (bootm_find_ramdisk(flag, argc, argv))
return 1;
const char *type_name = genimg_get_type_name(os.type);
- load_buf = map_sysmem(load, image_len);
+ load_buf = map_sysmem(load, unc_len);
image_buf = map_sysmem(image_start, image_len);
switch (comp) {
case IH_COMP_NONE:
- if (load == blob_start || load == image_start) {
+ if (load == image_start) {
printf(" XIP %s ... ", type_name);
no_overlap = 1;
} else {
}
#endif /* CONFIG_LZMA */
#ifdef CONFIG_LZO
- case IH_COMP_LZO:
+ case IH_COMP_LZO: {
+ size_t size = unc_len;
+
printf(" Uncompressing %s ... ", type_name);
- ret = lzop_decompress(image_buf, image_len, load_buf,
- &unc_len);
+ ret = lzop_decompress(image_buf, image_len, load_buf, &size);
if (ret != LZO_E_OK) {
printf("LZO: uncompress or overwrite error %d "
"- must RESET board to recover\n", ret);
return BOOTM_ERR_RESET;
}
- *load_end = load + unc_len;
+ *load_end = load + size;
break;
+ }
#endif /* CONFIG_LZO */
default:
printf("Unimplemented compression type %d\n", comp);
return 0;
}
-static int bootm_start_standalone(int argc, char * const argv[])
+static int do_bootm_standalone(int flag, int argc, char * const argv[],
+ bootm_headers_t *images)
{
char *s;
int (*appl)(int, char * const []);
/* Don't start if "autostart" is set to "no" */
if (((s = getenv("autostart")) != NULL) && (strcmp(s, "no") == 0)) {
- setenv_hex("filesize", images.os.image_len);
+ setenv_hex("filesize", images->os.image_len);
return 0;
}
- appl = (int (*)(int, char * const []))(ulong)ntohl(images.ep);
- (*appl)(argc, argv);
+ appl = (int (*)(int, char * const []))images->ep;
+ appl(argc, argv);
return 0;
}
static int boot_selected_os(int argc, char * const argv[], int state,
bootm_headers_t *images, boot_os_fn *boot_fn)
{
- if (images->os.type == IH_TYPE_STANDALONE) {
- /* This may return when 'autostart' is 'no' */
- bootm_start_standalone(argc, argv);
- return 0;
- }
-#ifdef CONFIG_SILENT_CONSOLE
- if (images->os.os == IH_OS_LINUX)
- fixup_silent_linux();
-#endif
arch_preboot_os();
boot_fn(state, argc, argv, images);
- if (state == BOOTM_STATE_OS_FAKE_GO) /* We expect to return */
+
+ /* Stand-alone may return when 'autostart' is 'no' */
+ if (images->os.type == IH_TYPE_STANDALONE ||
+ state == BOOTM_STATE_OS_FAKE_GO) /* We expect to return */
return 0;
bootstage_error(BOOTSTAGE_ID_BOOT_OS_RETURNED);
#ifdef DEBUG
#ifdef CONFIG_NETCONSOLE
/* Stop the ethernet stack if NetConsole could have left it up */
eth_halt();
+ eth_unregister(eth_get_dev());
#endif
#if defined(CONFIG_CMD_USB)
goto err;
else if (ret == BOOTM_ERR_OVERLAP)
ret = 0;
+#if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY)
+ if (images->os.os == IH_OS_LINUX)
+ fixup_silent_linux();
+#endif
}
/* Relocate the ramdisk */
return do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START |
BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER |
- BOOTM_STATE_LOADOS | BOOTM_STATE_OS_PREP |
- BOOTM_STATE_OS_FAKE_GO | BOOTM_STATE_OS_GO, &images, 1);
+ BOOTM_STATE_LOADOS |
+#if defined(CONFIG_PPC) || defined(CONFIG_MIPS)
+ BOOTM_STATE_OS_CMDLINE |
+#endif
+ BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
+ BOOTM_STATE_OS_GO, &images, 1);
}
int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd)
return 0;
}
+#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
/**
* image_get_kernel - verify legacy format kernel image
* @img_addr: in RAM address of the legacy format image to be verified
}
return hdr;
}
+#endif
/**
* boot_get_kernel - find kernel image
char * const argv[], bootm_headers_t *images, ulong *os_data,
ulong *os_len)
{
+#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
image_header_t *hdr;
+#endif
ulong img_addr;
const void *buf;
#if defined(CONFIG_FIT)
*os_data = *os_len = 0;
buf = map_sysmem(img_addr, 0);
switch (genimg_get_format(buf)) {
+#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
case IMAGE_FORMAT_LEGACY:
printf("## Booting kernel from Legacy Image at %08lx ...\n",
img_addr);
images->legacy_hdr_valid = 1;
bootstage_mark(BOOTSTAGE_ID_DECOMP_IMAGE);
break;
+#endif
#if defined(CONFIG_FIT)
case IMAGE_FORMAT_FIT:
os_noffset = fit_image_load(images, FIT_KERNEL_PROP,
images->fit_noffset_os = os_noffset;
break;
#endif
+#ifdef CONFIG_ANDROID_BOOT_IMAGE
+ case IMAGE_FORMAT_ANDROID:
+ printf("## Booting Android Image at 0x%08lx ...\n", img_addr);
+ if (android_image_get_kernel((void *)img_addr, images->verify,
+ os_data, os_len))
+ return NULL;
+ break;
+#endif
default:
printf("Wrong Image Format for %s command\n", cmdtp->name);
bootstage_error(BOOTSTAGE_ID_FIT_KERNEL_INFO);
#if defined(CONFIG_CMD_BOOTD)
int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
- int rcode = 0;
-
- if (run_command(getenv("bootcmd"), flag) < 0)
- rcode = 1;
- return rcode;
+ return run_command(getenv("bootcmd"), flag);
}
U_BOOT_CMD(
printf("\n## Checking Image at %08lx ...\n", addr);
switch (genimg_get_format(hdr)) {
+#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
case IMAGE_FORMAT_LEGACY:
puts(" Legacy image found\n");
if (!image_check_magic(hdr)) {
}
puts("OK\n");
return 0;
+#endif
#if defined(CONFIG_FIT)
case IMAGE_FORMAT_FIT:
puts(" FIT image found\n");
goto next_sector;
switch (genimg_get_format(hdr)) {
+#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
case IMAGE_FORMAT_LEGACY:
if (!image_check_hcrc(hdr))
goto next_sector;
puts("OK\n");
}
break;
+#endif
#if defined(CONFIG_FIT)
case IMAGE_FORMAT_FIT:
if (!fit_check_format(hdr))
}
switch (genimg_get_format(buffer)) {
+#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
case IMAGE_FORMAT_LEGACY:
header = (const image_header_t *)buffer;
len = image_get_image_size(header);
nand_imls_legacyimage(nand, nand_dev, off, len);
break;
+#endif
#if defined(CONFIG_FIT)
case IMAGE_FORMAT_FIT:
len = fit_get_size(buffer);
char *buf;
const char *env_val;
char *cmdline = getenv("bootargs");
+ int want_silent;
- /* Only fix cmdline when requested */
- if (!(gd->flags & GD_FLG_SILENT))
+ /*
+ * Only fix cmdline when requested. The environment variable can be:
+ *
+ * no - we never fixup
+ * yes - we always fixup
+ * unset - we rely on the console silent flag
+ */
+ want_silent = getenv_yesno("silent_linux");
+ if (want_silent == 0)
+ return;
+ else if (want_silent == -1 && !(gd->flags & GD_FLG_SILENT))
return;
debug("before silent fix-up: %s\n", cmdline);
char *consdev;
char *cmdline;
- if (flag & BOOTM_STATE_OS_PREP)
+ if (flag != BOOTM_STATE_OS_GO)
return 0;
- if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
- return 1;
#if defined(CONFIG_FIT)
if (!images->legacy_hdr_valid) {
/*
* NetBSD Stage-2 Loader Parameters:
- * r3: ptr to board info data
- * r4: image address
- * r5: console device
- * r6: boot args string
+ * arg[0]: pointer to board info data
+ * arg[1]: image load address
+ * arg[2]: char pointer to the console device to use
+ * arg[3]: char pointer to the boot arguments
*/
(*loader)(gd->bd, os_hdr, consdev, cmdline);
{
image_header_t *hdr = &images->legacy_hdr_os_copy;
- if (flag & BOOTM_STATE_OS_PREP)
+ if (flag != BOOTM_STATE_OS_GO)
return 0;
- if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
- return 1;
#if defined(CONFIG_FIT)
if (!images->legacy_hdr_valid) {
{
void (*entry_point)(bd_t *);
- if (flag & BOOTM_STATE_OS_PREP)
+ if (flag != BOOTM_STATE_OS_GO)
return 0;
- if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
- return 1;
#if defined(CONFIG_FIT)
if (!images->legacy_hdr_valid) {
{
void (*entry_point)(void);
- if (flag & BOOTM_STATE_OS_PREP)
+ if (flag != BOOTM_STATE_OS_GO)
return 0;
- if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
- return 1;
#if defined(CONFIG_FIT)
if (!images->legacy_hdr_valid) {
void (*entry_point)(void);
char *s;
- if (flag & BOOTM_STATE_OS_PREP)
+ if (flag != BOOTM_STATE_OS_GO)
return 0;
- if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
- return 1;
#if defined(CONFIG_FIT)
if (!images->legacy_hdr_valid) {
}
#endif /* CONFIG_BOOTM_PLAN9 */
-#if defined(CONFIG_CMD_ELF)
+#if defined(CONFIG_BOOTM_VXWORKS) && \
+ (defined(CONFIG_PPC) || defined(CONFIG_ARM))
+
+void do_bootvx_fdt(bootm_headers_t *images)
+{
+#if defined(CONFIG_OF_LIBFDT)
+ int ret;
+ char *bootline;
+ ulong of_size = images->ft_len;
+ char **of_flat_tree = &images->ft_addr;
+ struct lmb *lmb = &images->lmb;
+
+ if (*of_flat_tree) {
+ boot_fdt_add_mem_rsv_regions(lmb, *of_flat_tree);
+
+ ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size);
+ if (ret)
+ return;
+
+ ret = fdt_add_subnode(*of_flat_tree, 0, "chosen");
+ if ((ret >= 0 || ret == -FDT_ERR_EXISTS)) {
+ bootline = getenv("bootargs");
+ if (bootline) {
+ ret = fdt_find_and_setprop(*of_flat_tree,
+ "/chosen", "bootargs",
+ bootline,
+ strlen(bootline) + 1, 1);
+ if (ret < 0) {
+ printf("## ERROR: %s : %s\n", __func__,
+ fdt_strerror(ret));
+ return;
+ }
+ }
+ } else {
+ printf("## ERROR: %s : %s\n", __func__,
+ fdt_strerror(ret));
+ return;
+ }
+ }
+#endif
+
+ boot_prep_vxworks(images);
+
+ bootstage_mark(BOOTSTAGE_ID_RUN_OS);
+
+#if defined(CONFIG_OF_LIBFDT)
+ printf("## Starting vxWorks at 0x%08lx, device tree at 0x%08lx ...\n",
+ (ulong)images->ep, (ulong)*of_flat_tree);
+#else
+ printf("## Starting vxWorks at 0x%08lx\n", (ulong)images->ep);
+#endif
+
+ boot_jump_vxworks(images);
+
+ puts("## vxWorks terminated\n");
+}
+
static int do_bootm_vxworks(int flag, int argc, char * const argv[],
bootm_headers_t *images)
{
- char str[80];
-
- if (flag & BOOTM_STATE_OS_PREP)
+ if (flag != BOOTM_STATE_OS_GO)
return 0;
- if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
- return 1;
#if defined(CONFIG_FIT)
if (!images->legacy_hdr_valid) {
}
#endif
- sprintf(str, "%lx", images->ep); /* write entry-point into string */
- setenv("loadaddr", str);
- do_bootvx(NULL, 0, 0, NULL);
+ do_bootvx_fdt(images);
return 1;
}
+#endif
+#if defined(CONFIG_CMD_ELF)
static int do_bootm_qnxelf(int flag, int argc, char * const argv[],
bootm_headers_t *images)
{
char *local_args[2];
char str[16];
- if (flag & BOOTM_STATE_OS_PREP)
+ if (flag != BOOTM_STATE_OS_GO)
return 0;
- if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
- return 1;
#if defined(CONFIG_FIT)
if (!images->legacy_hdr_valid) {
{
void (*entry_point)(void);
- if (flag & BOOTM_STATE_OS_PREP)
+ if (flag != BOOTM_STATE_OS_GO)
return 0;
- if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
- return 1;
#if defined(CONFIG_FIT)
if (!images->legacy_hdr_valid) {