#include <lmb.h>
#include <linux/ctype.h>
#include <asm/byteorder.h>
+#include <asm/io.h>
#include <linux/compiler.h>
#if defined(CONFIG_CMD_USB)
#include <linux/err.h>
#include <nand.h>
-#ifdef CONFIG_SILENT_CONSOLE
+#if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY)
static void fixup_silent_linux(void);
#endif
-static image_header_t *image_get_kernel(ulong img_addr, int verify);
-#if defined(CONFIG_FIT)
-static int fit_check_kernel(const void *fit, int os_noffset, int verify);
-#endif
-
-static void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
+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);
* - verified image architecture (PPC) and type (KERNEL or MULTI),
* - loaded (first part of) image to header load address,
* - disabled interrupts.
+ *
+ * @flag: Command flags (CMD_FLAG_...)
+ * @argc: Number of arguments. Note that the arguments are shifted down
+ * so that 0 is the first argument not processed by U-Boot, and
+ * argc is adjusted accordingly. This avoids confusion as to how
+ * many arguments are available for the OS.
+ * @images: Pointers to os/initrd/fdt
+ * @return 1 on error. On success the OS boots so this function does
+ * not return.
*/
typedef int boot_os_fn(int flag, int argc, char * const argv[],
- bootm_headers_t *images); /* pointers to os/initrd/fdt */
+ bootm_headers_t *images);
#ifdef CONFIG_BOOTM_LINUX
extern boot_os_fn do_bootm_linux;
#if defined(CONFIG_BOOTM_OSE)
static boot_os_fn do_bootm_ose;
#endif
+#if defined(CONFIG_BOOTM_PLAN9)
+static boot_os_fn do_bootm_plan9;
+#endif
#if defined(CONFIG_CMD_ELF)
static boot_os_fn do_bootm_vxworks;
static boot_os_fn do_bootm_qnxelf;
#if defined(CONFIG_BOOTM_OSE)
[IH_OS_OSE] = do_bootm_ose,
#endif
+#if defined(CONFIG_BOOTM_PLAN9)
+ [IH_OS_PLAN9] = do_bootm_plan9,
+#endif
#if defined(CONFIG_CMD_ELF)
[IH_OS_VXWORKS] = do_bootm_vxworks,
[IH_OS_QNX] = do_bootm_qnxelf,
static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
- void *os_hdr;
- int ret;
+ const void *os_hdr;
+ int ret;
memset((void *)&images, 0, sizeof(images));
images.verify = getenv_yesno("verify");
#if defined(CONFIG_FIT)
} else if (images.fit_uname_os) {
ret = fit_image_get_entry(images.fit_hdr_os,
- images.fit_noffset_os, &images.ep);
+ images.fit_noffset_os, &images.ep);
if (ret) {
puts("Can't get entry point property!\n");
return 1;
#if defined(CONFIG_OF_LIBFDT)
/* find flattened device tree */
- ret = boot_get_fdt(flag, argc, argv, &images,
+ ret = boot_get_fdt(flag, argc, argv, IH_ARCH_DEFAULT, &images,
&images.ft_addr, &images.ft_len);
if (ret) {
puts("Could not find a valid device tree\n");
ulong image_len = os.image_len;
__maybe_unused uint unc_len = CONFIG_SYS_BOOTM_LEN;
int no_overlap = 0;
+ void *load_buf, *image_buf;
#if defined(CONFIG_LZMA) || defined(CONFIG_LZO)
int ret;
#endif /* defined(CONFIG_LZMA) || defined(CONFIG_LZO) */
const char *type_name = genimg_get_type_name(os.type);
+ load_buf = map_sysmem(load, image_len);
+ image_buf = map_sysmem(image_start, image_len);
switch (comp) {
case IH_COMP_NONE:
if (load == blob_start || load == image_start) {
no_overlap = 1;
} else {
printf(" Loading %s ... ", type_name);
- memmove_wd((void *)load, (void *)image_start,
- image_len, CHUNKSZ);
+ memmove_wd(load_buf, image_buf, image_len, CHUNKSZ);
}
*load_end = load + image_len;
puts("OK\n");
#ifdef CONFIG_GZIP
case IH_COMP_GZIP:
printf(" Uncompressing %s ... ", type_name);
- if (gunzip((void *)load, unc_len,
- (uchar *)image_start, &image_len) != 0) {
+ if (gunzip(load_buf, unc_len, image_buf, &image_len) != 0) {
puts("GUNZIP: uncompress, out-of-mem or overwrite "
"error - must RESET board to recover\n");
if (boot_progress)
* use slower decompression algorithm which requires
* at most 2300 KB of memory.
*/
- int i = BZ2_bzBuffToBuffDecompress((char *)load,
- &unc_len, (char *)image_start, image_len,
- CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0);
+ int i = BZ2_bzBuffToBuffDecompress(load_buf, &unc_len,
+ image_buf, image_len,
+ CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0);
if (i != BZ_OK) {
printf("BUNZIP2: uncompress or overwrite error %d "
"- must RESET board to recover\n", i);
SizeT lzma_len = unc_len;
printf(" Uncompressing %s ... ", type_name);
- ret = lzmaBuffToBuffDecompress(
- (unsigned char *)load, &lzma_len,
- (unsigned char *)image_start, image_len);
+ ret = lzmaBuffToBuffDecompress(load_buf, &lzma_len,
+ image_buf, image_len);
unc_len = lzma_len;
if (ret != SZ_OK) {
printf("LZMA: uncompress or overwrite error %d "
case IH_COMP_LZO:
printf(" Uncompressing %s ... ", type_name);
- ret = lzop_decompress((const unsigned char *)image_start,
- image_len, (unsigned char *)load,
- &unc_len);
+ ret = lzop_decompress(image_buf, image_len, load_buf,
+ &unc_len);
if (ret != LZO_E_OK) {
printf("LZO: uncompress or overwrite error %d "
"- must RESET board to recover\n", ret);
return 0;
}
appl = (int (*)(int, char * const []))(ulong)ntohl(images.ep);
- (*appl)(argc-1, &argv[1]);
+ (*appl)(argc, argv);
return 0;
}
cmd_tbl_t *c;
boot_os_fn *boot_fn;
- c = find_cmd_tbl(argv[1], &cmd_bootm_sub[0], ARRAY_SIZE(cmd_bootm_sub));
+ c = find_cmd_tbl(argv[0], &cmd_bootm_sub[0], ARRAY_SIZE(cmd_bootm_sub));
+ argc--; argv++;
if (c) {
state = (long)c->cmd;
/* treat start special since it resets the state machine */
- if (state == BOOTM_STATE_START) {
- argc--;
- argv++;
+ if (state == BOOTM_STATE_START)
return bootm_start(cmdtp, flag, argc, argv);
- }
} else {
/* Unrecognized command */
return CMD_RET_USAGE;
#endif
/* determine if we have a sub command */
- if (argc > 1) {
+ argc--; argv++;
+ if (argc > 0) {
char *endp;
- simple_strtoul(argv[1], &endp, 16);
- /* endp pointing to NULL means that argv[1] was just a
+ simple_strtoul(argv[0], &endp, 16);
+ /* endp pointing to NULL means that argv[0] was just a
* valid number, pass it along to the normal bootm processing
*
* If endp is ':' or '#' assume a FIT identifier so pass
bootstage_mark(BOOTSTAGE_ID_CHECK_BOOT_OS);
-#ifdef CONFIG_SILENT_CONSOLE
+#if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY)
if (images.os.os == IH_OS_LINUX)
fixup_silent_linux();
#endif
return hdr;
}
-/**
- * fit_check_kernel - verify FIT format kernel subimage
- * @fit_hdr: pointer to the FIT image header
- * os_noffset: kernel subimage node offset within FIT image
- * @verify: data CRC verification flag
- *
- * fit_check_kernel() verifies integrity of the kernel subimage and from
- * specified FIT image.
- *
- * returns:
- * 1, on success
- * 0, on failure
- */
-#if defined(CONFIG_FIT)
-static int fit_check_kernel(const void *fit, int os_noffset, int verify)
-{
- fit_image_print(fit, os_noffset, " ");
-
- if (verify) {
- puts(" Verifying Hash Integrity ... ");
- if (!fit_image_check_hashes(fit, os_noffset)) {
- puts("Bad Data Hash\n");
- bootstage_error(BOOTSTAGE_ID_FIT_CHECK_HASH);
- return 0;
- }
- puts("OK\n");
- }
- bootstage_mark(BOOTSTAGE_ID_FIT_CHECK_ARCH);
-
- if (!fit_image_check_target_arch(fit, os_noffset)) {
- puts("Unsupported Architecture\n");
- bootstage_error(BOOTSTAGE_ID_FIT_CHECK_ARCH);
- return 0;
- }
-
- bootstage_mark(BOOTSTAGE_ID_FIT_CHECK_KERNEL);
- if (!fit_image_check_type(fit, os_noffset, IH_TYPE_KERNEL) &&
- !fit_image_check_type(fit, os_noffset, IH_TYPE_KERNEL_NOLOAD)) {
- puts("Not a kernel image\n");
- bootstage_error(BOOTSTAGE_ID_FIT_CHECK_KERNEL);
- return 0;
- }
-
- bootstage_mark(BOOTSTAGE_ID_FIT_CHECKED);
- return 1;
-}
-#endif /* CONFIG_FIT */
-
/**
* boot_get_kernel - find kernel image
* @os_data: pointer to a ulong variable, will hold os data start address
* pointer to image header if valid image was found, plus kernel start
* address and length, otherwise NULL
*/
-static void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
+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)
{
image_header_t *hdr;
ulong img_addr;
+ const void *buf;
#if defined(CONFIG_FIT)
- void *fit_hdr;
const char *fit_uname_config = NULL;
const char *fit_uname_kernel = NULL;
- const void *data;
- size_t len;
- int cfg_noffset;
int os_noffset;
#endif
/* find out kernel image address */
- if (argc < 2) {
+ if (argc < 1) {
img_addr = load_addr;
debug("* kernel: default image load address = 0x%08lx\n",
load_addr);
#if defined(CONFIG_FIT)
- } else if (fit_parse_conf(argv[1], load_addr, &img_addr,
+ } else if (fit_parse_conf(argv[0], load_addr, &img_addr,
&fit_uname_config)) {
debug("* kernel: config '%s' from image at 0x%08lx\n",
fit_uname_config, img_addr);
- } else if (fit_parse_subimage(argv[1], load_addr, &img_addr,
+ } else if (fit_parse_subimage(argv[0], load_addr, &img_addr,
&fit_uname_kernel)) {
debug("* kernel: subimage '%s' from image at 0x%08lx\n",
fit_uname_kernel, img_addr);
#endif
} else {
- img_addr = simple_strtoul(argv[1], NULL, 16);
+ img_addr = simple_strtoul(argv[0], NULL, 16);
debug("* kernel: cmdline image address = 0x%08lx\n", img_addr);
}
/* check image type, for FIT images get FIT kernel node */
*os_data = *os_len = 0;
- switch (genimg_get_format((void *)img_addr)) {
+ buf = map_sysmem(img_addr, 0);
+ switch (genimg_get_format(buf)) {
case IMAGE_FORMAT_LEGACY:
printf("## Booting kernel from Legacy Image at %08lx ...\n",
img_addr);
break;
#if defined(CONFIG_FIT)
case IMAGE_FORMAT_FIT:
- fit_hdr = (void *)img_addr;
- printf("## Booting kernel from FIT Image at %08lx ...\n",
- img_addr);
-
- if (!fit_check_format(fit_hdr)) {
- puts("Bad FIT kernel image format!\n");
- bootstage_error(BOOTSTAGE_ID_FIT_FORMAT);
- return NULL;
- }
- bootstage_mark(BOOTSTAGE_ID_FIT_FORMAT);
-
- if (!fit_uname_kernel) {
- /*
- * no kernel image node unit name, try to get config
- * node first. If config unit node name is NULL
- * fit_conf_get_node() will try to find default config
- * node
- */
- bootstage_mark(BOOTSTAGE_ID_FIT_NO_UNIT_NAME);
-#ifdef CONFIG_FIT_BEST_MATCH
- if (fit_uname_config)
- cfg_noffset =
- fit_conf_get_node(fit_hdr,
- fit_uname_config);
- else
- cfg_noffset =
- fit_conf_find_compat(fit_hdr,
- gd->fdt_blob);
-#else
- cfg_noffset = fit_conf_get_node(fit_hdr,
- fit_uname_config);
-#endif
- if (cfg_noffset < 0) {
- bootstage_error(BOOTSTAGE_ID_FIT_NO_UNIT_NAME);
- return NULL;
- }
- /* save configuration uname provided in the first
- * bootm argument
- */
- images->fit_uname_cfg = fdt_get_name(fit_hdr,
- cfg_noffset,
- NULL);
- printf(" Using '%s' configuration\n",
- images->fit_uname_cfg);
- bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG);
-
- os_noffset = fit_conf_get_kernel_node(fit_hdr,
- cfg_noffset);
- fit_uname_kernel = fit_get_name(fit_hdr, os_noffset,
- NULL);
- } else {
- /* get kernel component image node offset */
- bootstage_mark(BOOTSTAGE_ID_FIT_UNIT_NAME);
- os_noffset = fit_image_get_node(fit_hdr,
- fit_uname_kernel);
- }
- if (os_noffset < 0) {
- bootstage_error(BOOTSTAGE_ID_FIT_CONFIG);
+ os_noffset = fit_image_load(images, FIT_KERNEL_PROP,
+ img_addr,
+ &fit_uname_kernel, fit_uname_config,
+ IH_ARCH_DEFAULT, IH_TYPE_KERNEL,
+ BOOTSTAGE_ID_FIT_KERNEL_START,
+ FIT_LOAD_IGNORED, os_data, os_len);
+ if (os_noffset < 0)
return NULL;
- }
-
- printf(" Trying '%s' kernel subimage\n", fit_uname_kernel);
-
- bootstage_mark(BOOTSTAGE_ID_FIT_CHECK_SUBIMAGE);
- if (!fit_check_kernel(fit_hdr, os_noffset, images->verify))
- return NULL;
-
- /* get kernel image data address and length */
- if (fit_image_get_data(fit_hdr, os_noffset, &data, &len)) {
- puts("Could not find kernel subimage data!\n");
- bootstage_error(BOOTSTAGE_ID_FIT_KERNEL_INFO_ERR);
- return NULL;
- }
- bootstage_mark(BOOTSTAGE_ID_FIT_KERNEL_INFO);
- *os_len = len;
- *os_data = (ulong)data;
- images->fit_hdr_os = fit_hdr;
+ images->fit_hdr_os = map_sysmem(img_addr, 0);
images->fit_uname_os = fit_uname_kernel;
images->fit_noffset_os = os_noffset;
break;
debug(" kernel data at 0x%08lx, len = 0x%08lx (%ld)\n",
*os_data, *os_len, *os_len);
- return (void *)img_addr;
+ return buf;
}
#ifdef CONFIG_SYS_LONGHELP
"issued in the order below (it's ok to not issue all sub-commands):\n"
"\tstart [addr [arg ...]]\n"
"\tloados - load OS image\n"
-#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_SPARC)
+#if defined(CONFIG_SYS_BOOT_RAMDISK_HIGH)
"\tramdisk - relocate initrd, set env initrd_start/initrd_end\n"
#endif
#if defined(CONFIG_OF_LIBFDT)
fit_print_contents(hdr);
- if (!fit_all_image_check_hashes(hdr)) {
+ if (!fit_all_image_verify(hdr)) {
puts("Bad hash in FIT image!\n");
return 1;
}
/*******************************************************************/
/* helper routines */
/*******************************************************************/
-#ifdef CONFIG_SILENT_CONSOLE
+#if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY)
+
+#define CONSOLE_ARG "console="
+#define CONSOLE_ARG_LEN (sizeof(CONSOLE_ARG) - 1)
+
static void fixup_silent_linux(void)
{
- char buf[256], *start, *end;
+ char *buf;
+ const char *env_val;
char *cmdline = getenv("bootargs");
/* Only fix cmdline when requested */
return;
debug("before silent fix-up: %s\n", cmdline);
- if (cmdline) {
- start = strstr(cmdline, "console=");
+ if (cmdline && (cmdline[0] != '\0')) {
+ char *start = strstr(cmdline, CONSOLE_ARG);
+
+ /* Allocate space for maximum possible new command line */
+ buf = malloc(strlen(cmdline) + 1 + CONSOLE_ARG_LEN + 1);
+ if (!buf) {
+ debug("%s: out of memory\n", __func__);
+ return;
+ }
+
if (start) {
- end = strchr(start, ' ');
- strncpy(buf, cmdline, (start - cmdline + 8));
+ char *end = strchr(start, ' ');
+ int num_start_bytes = start - cmdline + CONSOLE_ARG_LEN;
+
+ strncpy(buf, cmdline, num_start_bytes);
if (end)
- strcpy(buf + (start - cmdline + 8), end);
+ strcpy(buf + num_start_bytes, end);
else
- buf[start - cmdline + 8] = '\0';
+ buf[num_start_bytes] = '\0';
} else {
- strcpy(buf, cmdline);
- strcat(buf, " console=");
+ sprintf(buf, "%s %s", cmdline, CONSOLE_ARG);
}
+ env_val = buf;
} else {
- strcpy(buf, "console=");
+ buf = NULL;
+ env_val = CONSOLE_ARG;
}
- setenv("bootargs", buf);
- debug("after silent fix-up: %s\n", buf);
+ setenv("bootargs", env_val);
+ debug("after silent fix-up: %s\n", env_val);
+ free(buf);
}
#endif /* CONFIG_SILENT_CONSOLE */
consdev = "scc3";
#endif
- if (argc > 2) {
+ if (argc > 0) {
ulong len;
int i;
- for (i = 2, len = 0; i < argc; i += 1)
+ for (i = 0, len = 0; i < argc; i += 1)
len += strlen(argv[i]) + 1;
cmdline = malloc(len);
- for (i = 2, len = 0; i < argc; i += 1) {
- if (i > 2)
+ for (i = 0, len = 0; i < argc; i += 1) {
+ if (i > 0)
cmdline[len++] = ' ';
strcpy(&cmdline[len], argv[i]);
len += strlen(argv[i]);
}
#endif /* CONFIG_BOOTM_OSE */
+#if defined(CONFIG_BOOTM_PLAN9)
+static int do_bootm_plan9(int flag, int argc, char * const argv[],
+ bootm_headers_t *images)
+{
+ void (*entry_point)(void);
+
+ if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
+ return 1;
+
+#if defined(CONFIG_FIT)
+ if (!images->legacy_hdr_valid) {
+ fit_unsupported_reset("Plan 9");
+ return 1;
+ }
+#endif
+
+ entry_point = (void (*)(void))images->ep;
+
+ printf("## Transferring control to Plan 9 (at address %08lx) ...\n",
+ (ulong)entry_point);
+
+ bootstage_mark(BOOTSTAGE_ID_RUN_OS);
+
+ /*
+ * Plan 9 Parameters:
+ * None
+ */
+ (*entry_point)();
+
+ return 1;
+}
+#endif /* CONFIG_BOOTM_PLAN9 */
+
#if defined(CONFIG_CMD_ELF)
static int do_bootm_vxworks(int flag, int argc, char * const argv[],
bootm_headers_t *images)
#if defined(CONFIG_OF_LIBFDT)
/* find flattened device tree */
- ret = boot_get_fdt(flag, argc, argv, images,
+ ret = boot_get_fdt(flag, argc, argv, IH_ARCH_DEFAULT, images,
&images->ft_addr, &images->ft_len);
if (ret) {
puts("Could not find a valid device tree\n");
return 0;
}
-static int do_bootz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+int do_bootz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
bootm_headers_t images;
usb_stop();
#endif
-#ifdef CONFIG_SILENT_CONSOLE
+#if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY)
fixup_silent_linux();
#endif
arch_preboot_os();