summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/lib/bootm.c222
-rw-r--r--arch/blackfin/lib/blackfin_linux.c12
-rw-r--r--arch/nios2/lib/bootm.c11
-rw-r--r--arch/ppc/lib/ppclinux.c16
-rw-r--r--commands/Kconfig22
-rw-r--r--commands/bootm.c451
-rw-r--r--include/boot.h62
7 files changed, 633 insertions, 163 deletions
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 1de22bf81c..d8bb701c4a 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -11,6 +11,8 @@
#include <malloc.h>
#include <fcntl.h>
#include <errno.h>
+#include <sizes.h>
+#include <libbb.h>
#include <asm/byteorder.h>
#include <asm/setup.h>
@@ -18,33 +20,223 @@
#include <asm/armlinux.h>
#include <asm/system.h>
-static int do_bootm_linux(struct image_data *data)
+static int __do_bootm_linux(struct image_data *data, int swap)
{
- void (*theKernel)(int zero, int arch, void *params);
- image_header_t *os_header = &data->os->header;
+ unsigned long kernel;
+ unsigned long initrd_start = 0, initrd_size = 0;
+ struct memory_bank *bank;
+ unsigned long load_address;
+
+ if (data->os_res) {
+ load_address = data->os_res->start;
+ } else if (data->os_address != UIMAGE_INVALID_ADDRESS) {
+ load_address = data->os_address;
+ } else {
+ bank = list_first_entry(&memory_banks,
+ struct memory_bank, list);
+ load_address = bank->start + SZ_32K;
+ if (bootm_verbose(data))
+ printf("no os load address, defaulting to 0x%08lx\n",
+ load_address);
+ }
+
+ if (!data->os_res && data->os) {
+ data->os_res = uimage_load_to_sdram(data->os,
+ data->os_num, load_address);
+ if (!data->os_res)
+ return -ENOMEM;
+ }
+
+ if (!data->os_res) {
+ data->os_res = file_to_sdram(data->os_file, load_address);
+ if (!data->os_res)
+ return -ENOMEM;
+ }
+
+ kernel = data->os_res->start + data->os_entry;
+
+ if (data->initrd_file && data->initrd_address == UIMAGE_INVALID_ADDRESS) {
+ initrd_start = data->os_res->start + SZ_8M;
- theKernel = (void *)image_get_ep(os_header);
+ if (bootm_verbose(data)) {
+ printf("no initrd load address, defaulting to 0x%08lx\n",
+ initrd_start);
+ }
+ }
- debug("## Transferring control to Linux (at address 0x%p) ...\n",
- theKernel);
+ if (data->initrd) {
+ data->initrd_res = uimage_load_to_sdram(data->initrd,
+ data->initrd_num, initrd_start);
+ if (!data->initrd_res)
+ return -ENOMEM;
+ } else if (data->initrd_file) {
+ data->initrd_res = file_to_sdram(data->initrd_file, initrd_start);
+ if (!data->initrd_res)
+ return -ENOMEM;
+ }
- /* we assume that the kernel is in place */
- printf("\nStarting kernel %s...\n\n", data->initrd ? "with initrd " : "");
+ if (data->initrd_res) {
+ initrd_start = data->initrd_res->start;
+ initrd_size = data->initrd_res->size;
+ }
- start_linux((void *)theKernel, 0, data->initrd_address, data->initrd_size,
- data->oftree);
+ if (bootm_verbose(data)) {
+ printf("\nStarting kernel at 0x%08lx", kernel);
+ if (initrd_size)
+ printf(", initrd at 0x%08lx", initrd_start);
+ if (data->oftree)
+ printf(", oftree at 0x%p", data->oftree);
+ printf("...\n");
+ }
- return -1;
+ start_linux((void *)kernel, swap, initrd_start, initrd_size, data->oftree);
+
+ reset_cpu(0);
+
+ return -ERESTARTSYS;
+}
+
+static int do_bootm_linux(struct image_data *data)
+{
+ return __do_bootm_linux(data, 0);
}
-static struct image_handler handler = {
+static struct image_handler uimage_handler = {
+ .name = "ARM Linux uImage",
.bootm = do_bootm_linux,
- .image_type = IH_OS_LINUX,
+ .filetype = filetype_uimage,
+ .ih_os = IH_OS_LINUX,
};
-static int armlinux_register_image_handler(void)
+static struct image_handler rawimage_handler = {
+ .name = "ARM raw image",
+ .bootm = do_bootm_linux,
+ .filetype = filetype_unknown,
+};
+
+struct zimage_header {
+ u32 unused[9];
+ u32 magic;
+ u32 start;
+ u32 end;
+};
+
+#define ZIMAGE_MAGIC 0x016F2818
+
+static int do_bootz_linux(struct image_data *data)
+{
+ int fd, ret, swap = 0;
+ struct zimage_header __header, *header;
+ void *zimage;
+ u32 end;
+ unsigned long load_address = data->os_address;
+
+ if (load_address == UIMAGE_INVALID_ADDRESS) {
+ struct memory_bank *bank = list_first_entry(&memory_banks,
+ struct memory_bank, list);
+ data->os_address = bank->start + SZ_8M;
+ if (bootm_verbose(data))
+ printf("no os load address, defaulting to 0x%08lx\n",
+ load_address);
+ }
+
+ fd = open(data->os_file, O_RDONLY);
+ if (fd < 0) {
+ perror("open");
+ return 1;
+ }
+
+ header = &__header;
+ ret = read(fd, header, sizeof(*header));
+ if (ret < sizeof(*header)) {
+ printf("could not read %s\n", data->os_file);
+ goto err_out;
+ }
+
+ switch (header->magic) {
+ case swab32(ZIMAGE_MAGIC):
+ swap = 1;
+ /* fall through */
+ case ZIMAGE_MAGIC:
+ break;
+ default:
+ printf("invalid magic 0x%08x\n", header->magic);
+ ret = -EINVAL;
+ goto err_out;
+ }
+
+ end = header->end;
+
+ if (swap)
+ end = swab32(end);
+
+ data->os_res = request_sdram_region("zimage", load_address, end);
+ if (!data->os_res) {
+ ret = -ENOMEM;
+ goto err_out;
+ }
+
+ zimage = (void *)data->os_res->start;
+
+ memcpy(zimage, header, sizeof(*header));
+
+ ret = read_full(fd, zimage + sizeof(*header), end - sizeof(*header));
+ if (ret < 0)
+ goto err_out;
+ if (ret < end - sizeof(*header)) {
+ printf("premature end of image\n");
+ ret = -EIO;
+ goto err_out;
+ }
+
+ if (swap) {
+ void *ptr;
+ for (ptr = zimage; ptr < zimage + end; ptr += 4)
+ *(u32 *)ptr = swab32(*(u32 *)ptr);
+ }
+
+ return __do_bootm_linux(data, swap);
+
+err_out:
+ close(fd);
+
+ return ret;
+}
+
+static struct image_handler zimage_handler = {
+ .name = "ARM zImage",
+ .bootm = do_bootz_linux,
+ .filetype = filetype_arm_zimage,
+};
+
+static int do_bootm_barebox(struct image_data *data)
{
- return register_image_handler(&handler);
+ void (*barebox)(void);
+
+ barebox = read_file(data->os_file, NULL);
+ if (!barebox)
+ return -EINVAL;
+
+ shutdown_barebox();
+
+ barebox();
+
+ reset_cpu(0);
}
+static struct image_handler barebox_handler = {
+ .name = "ARM barebox",
+ .bootm = do_bootm_barebox,
+ .filetype = filetype_arm_barebox,
+};
+
+static int armlinux_register_image_handler(void)
+{
+ register_image_handler(&barebox_handler);
+ register_image_handler(&uimage_handler);
+ register_image_handler(&rawimage_handler);
+ register_image_handler(&zimage_handler);
+
+ return 0;
+}
late_initcall(armlinux_register_image_handler);
diff --git a/arch/blackfin/lib/blackfin_linux.c b/arch/blackfin/lib/blackfin_linux.c
index 9da9ec4e58..458d1b180b 100644
--- a/arch/blackfin/lib/blackfin_linux.c
+++ b/arch/blackfin/lib/blackfin_linux.c
@@ -34,6 +34,7 @@
#include <asm/byteorder.h>
#include <asm/cpu.h>
#include <asm/blackfin.h>
+#include <errno.h>
#include <init.h>
#include <boot.h>
@@ -44,10 +45,11 @@ static int do_bootm_linux(struct image_data *idata)
int (*appl)(char *cmdline);
const char *cmdline = getenv("bootargs");
char *cmdlinedest = (char *) CMD_LINE_ADDR;
- struct image_handle *os_handle = idata->os;
- image_header_t *os_header = &os_handle->header;
- appl = (int (*)(char *))image_get_ep(os_header);
+ if (!idata->os_res)
+ return -EINVAL;
+
+ appl = (void *)(idata->os_address + idata->os_entry);
printf("Starting Kernel at 0x%p\n", appl);
icache_disable();
@@ -63,8 +65,10 @@ static int do_bootm_linux(struct image_data *idata)
}
static struct image_handler handler = {
+ .name = "Blackfin Linux",
.bootm = do_bootm_linux,
- .image_type = IH_OS_LINUX,
+ .filetype = filetype_uimage,
+ .ih_os = IH_OS_LINUX,
};
static int bfinlinux_register_image_handler(void)
diff --git a/arch/nios2/lib/bootm.c b/arch/nios2/lib/bootm.c
index b5b344f499..1cd43c81af 100644
--- a/arch/nios2/lib/bootm.c
+++ b/arch/nios2/lib/bootm.c
@@ -31,17 +31,20 @@
#include <environment.h>
#include <init.h>
#include <boot.h>
+#include <errno.h>
#include <asm/cache.h>
#define NIOS_MAGIC 0x534f494e /* enable command line and initrd passing */
static int do_bootm_linux(struct image_data *idata)
{
- image_header_t *os_header = &idata->os->header;
void (*kernel)(int, int, int, const char *);
const char *commandline = getenv ("bootargs");
- kernel = (void (*)(int, int, int, const char *))ntohl(os_header->ih_ep);
+ if (!idata->os_res)
+ return -EINVAL;
+
+ kernel = (void *)(idata->os_address + idata->os_entry);
/* kernel parameters passing
* r4 : NIOS magic
@@ -63,8 +66,10 @@ static int do_bootm_linux(struct image_data *idata)
}
static struct image_handler handler = {
+ .name = "NIOS2 Linux",
.bootm = do_bootm_linux,
- .image_type = IH_OS_LINUX,
+ .filetype = filetype_uimage,
+ .ih_os = IH_OS_LINUX,
};
int nios2_register_image_handler(void)
diff --git a/arch/ppc/lib/ppclinux.c b/arch/ppc/lib/ppclinux.c
index f7d3950603..3c1b3fa006 100644
--- a/arch/ppc/lib/ppclinux.c
+++ b/arch/ppc/lib/ppclinux.c
@@ -11,18 +11,15 @@
#include <errno.h>
#include <fs.h>
-#ifdef CONFIG_OF_FLAT_TREE
-#include <ft_build.h>
-#endif
-extern bd_t *bd;
-
static int do_bootm_linux(struct image_data *data)
{
void (*kernel)(void *, void *, unsigned long,
unsigned long, unsigned long);
- struct image_header *os_header = &data->os->header;
- kernel = (void *)image_get_ep(os_header);
+ if (!data->os_res)
+ return -EINVAL;
+
+ kernel = (void *)(data->os_address + data->os_entry);
/*
* Linux Kernel Parameters (passing device tree):
@@ -41,8 +38,10 @@ static int do_bootm_linux(struct image_data *data)
}
static struct image_handler handler = {
+ .name = "PowerPC Linux",
.bootm = do_bootm_linux,
- .image_type = IH_OS_LINUX,
+ .filetype = filetype_uimage,
+ .ih_os = IH_OS_LINUX,
};
static int ppclinux_register_image_handler(void)
@@ -51,4 +50,3 @@ static int ppclinux_register_image_handler(void)
}
late_initcall(ppclinux_register_image_handler);
-
diff --git a/commands/Kconfig b/commands/Kconfig
index ebc9c7f2d0..3cf2d085f3 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -310,6 +310,28 @@ config CMD_BOOTM_SHOW_TYPE
depends on CMD_BOOTM
prompt "show image information"
+config CMD_BOOTM_VERBOSE
+ bool
+ prompt "bootm verbose support"
+ depends on CMD_BOOTM
+ help
+ support verbose bootm (-v switch)
+
+config CMD_BOOTM_INITRD
+ bool
+ prompt "bootm initrd support"
+ depends on CMD_BOOTM
+ help
+ support initrds in bootm
+
+config CMD_BOOTM_OFTREE_UIMAGE
+ bool
+ prompt "support passing oftree uImages"
+ depends on CMD_BOOTM
+ help
+ Support using oftree uImages. Without this only raw oftree
+ blobs can be used.
+
config CMD_IMINFO
bool
prompt "iminfo"
diff --git a/commands/bootm.c b/commands/bootm.c
index 265ad4637a..d9805866bd 100644
--- a/commands/bootm.c
+++ b/commands/bootm.c
@@ -39,202 +39,410 @@
#include <errno.h>
#include <boot.h>
#include <of.h>
+#include <libfdt.h>
#include <rtc.h>
#include <init.h>
+#include <of.h>
#include <magicvar.h>
#include <uncompress.h>
+#include <memory.h>
+#include <filetype.h>
#include <asm-generic/memory_layout.h>
-struct image_handle_data* image_handle_data_get_by_num(struct image_handle* handle, int num)
+static LIST_HEAD(handler_list);
+
+#ifdef CONFIG_CMD_BOOTM_INITRD
+static inline int bootm_initrd(struct image_data *data)
+{
+ return data->initrd ? 1 : 0;
+}
+#else
+static inline int bootm_initrd(struct image_data *data)
{
- if (!handle || num < 0 || num >= handle->nb_data_entries)
- return NULL;
+ return 0;
+}
+#endif
- return &handle->data_entries[num];
+int register_image_handler(struct image_handler *handler)
+{
+ list_add_tail(&handler->list, &handler_list);
+ return 0;
}
-int relocate_image(struct image_handle *handle, void *load_address)
+#define UIMAGE_SOME_ADDRESS (UIMAGE_INVALID_ADDRESS - 1)
+
+static int bootm_open_os_uimage(struct image_data *data)
{
- image_header_t *hdr = &handle->header;
- unsigned long len = image_get_size(hdr);
- struct image_handle_data *iha;
- void *data;
int ret;
- iha = image_handle_data_get_by_num(handle, 0);
- data = iha->data;
+ data->os = uimage_open(data->os_file);
+ if (!data->os)
+ return -EINVAL;
- switch (image_get_comp(hdr)) {
- case IH_COMP_NONE:
- if (load_address == data) {
- printf (" XIP ... ");
- } else {
- memmove(load_address, data, len);
- }
- break;
- default:
- printf (" Uncompressing ... ");
- ret = uncompress(data, len, NULL, NULL, load_address, NULL,
- uncompress_err_stdout);
- if (ret)
+ if (data->verify) {
+ ret = uimage_verify(data->os);
+ if (ret) {
+ printf("Checking data crc failed with %s\n",
+ strerror(-ret));
return ret;
- break;
+ }
+ }
+
+ uimage_print_contents(data->os);
+
+ if (data->os->header.ih_arch != IH_ARCH) {
+ printf("Unsupported Architecture 0x%x\n",
+ data->os->header.ih_arch);
+ return -EINVAL;
+ }
+
+ if (data->os_address == UIMAGE_SOME_ADDRESS)
+ data->os_address = data->os->header.ih_load;
+
+ if (data->os_address != UIMAGE_INVALID_ADDRESS) {
+ data->os_res = uimage_load_to_sdram(data->os, 0,
+ data->os_address);
+ if (!data->os_res)
+ return -ENOMEM;
}
return 0;
}
-EXPORT_SYMBOL(relocate_image);
-
-static LIST_HEAD(handler_list);
-int register_image_handler(struct image_handler *handler)
+static int bootm_open_initrd_uimage(struct image_data *data)
{
- list_add_tail(&handler->list, &handler_list);
+ int ret;
+
+ if (!data->initrd_file)
+ return 0;
+
+ if (strcmp(data->os_file, data->initrd_file)) {
+ data->initrd = uimage_open(data->initrd_file);
+ if (!data->initrd)
+ return -EINVAL;
+
+ if (data->verify) {
+ ret = uimage_verify(data->initrd);
+ if (ret) {
+ printf("Checking data crc failed with %s\n",
+ strerror(-ret));
+ }
+ }
+ uimage_print_contents(data->initrd);
+ } else {
+ data->initrd = data->os;
+ }
+
+ if (data->initrd_address == UIMAGE_SOME_ADDRESS)
+ data->initrd_address = data->initrd->header.ih_load;
+
+ if (data->initrd_address != UIMAGE_INVALID_ADDRESS) {
+ data->initrd_res = uimage_load_to_sdram(data->initrd,
+ data->initrd_num,
+ data->initrd_address);
+ if (!data->initrd_res)
+ return -ENOMEM;
+ }
+
return 0;
}
-/*
- * generate a image_handle from a multi_image
- * this image_handle can be freed by unmap_image
- */
-static struct image_handle *get_fake_image_handle(struct image_data *data, int num)
+#ifdef CONFIG_OFTREE
+static int bootm_open_oftree(struct image_data *data, char *oftree, int num)
{
- struct image_handle *handle;
- struct image_handle_data* iha;
- image_header_t *header;
+ enum filetype ft;
+ struct fdt_header *fdt;
+ int ret;
+ size_t size;
+
+ ft = file_name_detect_type(oftree);
+ if ((int)ft < 0)
+ return ft;
+
+ if (ft == filetype_uimage) {
+#ifdef CONFIG_CMD_BOOTM_OFTREE_UIMAGE
+ struct uimage_handle *of_handle;
+ int release = 0;
+
+ if (!strcmp(data->os_file, oftree)) {
+ of_handle = data->os;
+ } else if (!strcmp(data->initrd_file, oftree)) {
+ of_handle = data->initrd;
+ } else {
+ of_handle = uimage_open(oftree);
+ if (!of_handle)
+ return -ENODEV;
+ uimage_print_contents(of_handle);
+ release = 1;
+ }
+
+ fdt = uimage_load_to_buf(of_handle, num, &size);
+
+ if (release)
+ uimage_close(of_handle);
+#else
+ return -EINVAL;
+#endif
+ } else {
+ fdt = read_file(oftree, &size);
+ if (!fdt) {
+ perror("open");
+ return -ENODEV;
+ }
+ }
+
+ ft = file_detect_type(fdt);
+ if (ft != filetype_oftree) {
+ printf("%s is not a oftree but %s\n", oftree,
+ file_type_to_string(ft));
+ }
+
+ if (bootm_verbose(data))
+ printf("Loading oftree from '%s'\n", oftree);
+
+ fdt = xrealloc(fdt, size + 0x8000);
+ fdt_open_into(fdt, fdt, size + 0x8000);
+
+ if (!fdt) {
+ printf("unable to read %s\n", oftree);
+ return -ENODEV;
+ }
+
+ ret = of_fix_tree(fdt);
+ if (ret)
+ return ret;
- iha = image_handle_data_get_by_num(data->os, num);
+ if (bootm_verbose(data) > 1)
+ fdt_print(fdt, "/");
- handle = xzalloc(sizeof(struct image_handle));
- header = &handle->header;
- handle->data_entries = gen_image_handle_data(iha->data, iha->len);
- handle->nb_data_entries = 1;
- header->ih_size = cpu_to_uimage(iha->len);
- handle->data = handle->data_entries[0].data;
+ data->oftree = fdt;
- return handle;
+ return ret;
+}
+#endif
+
+static struct image_handler *bootm_find_handler(enum filetype filetype,
+ struct image_data *data)
+{
+ struct image_handler *handler;
+
+ list_for_each_entry(handler, &handler_list, list) {
+ if (filetype != filetype_uimage &&
+ handler->filetype == filetype)
+ return handler;
+ if (filetype == filetype_uimage &&
+ handler->ih_os == data->os->header.ih_os)
+ return handler;
+ }
+
+ return NULL;
+}
+
+static void bootm_image_name_and_no(char *name, int *no)
+{
+ char *at;
+
+ *no = 0;
+
+ at = strchr(name, '@');
+ if (!at)
+ return;
+
+ *at++ = 0;
+
+ *no = simple_strtoul(at, NULL, 10);
}
static int do_bootm(struct command *cmdtp, int argc, char *argv[])
{
- int opt;
- image_header_t *os_header;
- struct image_handle *os_handle = NULL;
+ int opt;
struct image_handler *handler;
struct image_data data;
- const char *initrdname = NULL;
int ret = 1;
+ enum filetype os_type, initrd_type = filetype_unknown;
+ char *oftree = NULL;
+ int fallback = 0;
memset(&data, 0, sizeof(struct image_data));
- data.verify = 1;
- data.initrd_address = ~0;
- while ((opt = getopt(argc, argv, "nr:L:")) > 0) {
+ data.initrd_address = UIMAGE_SOME_ADDRESS;
+ data.os_address = UIMAGE_SOME_ADDRESS;
+ data.verify = 0;
+ data.verbose = 0;
+
+ while ((opt = getopt(argc, argv, "cL:r:a:e:vo:f")) > 0) {
switch(opt) {
- case 'n':
- data.verify = 0;
+ case 'c':
+ data.verify = 1;
break;
+#ifdef CONFIG_CMD_BOOTM_INITRD
case 'L':
data.initrd_address = simple_strtoul(optarg, NULL, 0);
break;
case 'r':
- initrdname = optarg;
+ data.initrd_file = optarg;
+ break;
+#endif
+ case 'a':
+ data.os_address = simple_strtoul(optarg, NULL, 0);
+ break;
+ case 'e':
+ data.os_entry = simple_strtoul(optarg, NULL, 0);
+ break;
+ case 'v':
+ data.verbose++;
+ break;
+ case 'o':
+ oftree = optarg;
+ break;
+ case 'f':
+ fallback = 1;
break;
default:
break;
}
}
-#ifdef CONFIG_OFTREE
- data.oftree = of_get_fixed_tree();
-#endif
+ if (optind == argc)
+ return COMMAND_ERROR_USAGE;
+
+ data.os_file = argv[optind];
- if (optind == argc) {
- ret = COMMAND_ERROR_USAGE;
+ bootm_image_name_and_no(data.os_file, &data.os_num);
+
+ os_type = file_name_detect_type(data.os_file);
+ if ((int)os_type < 0) {
+ printf("could not open %s: %s\n", data.os_file,
+ strerror(-os_type));
goto err_out;
}
- os_handle = map_image(argv[optind], data.verify);
- if (!os_handle)
+ if (!fallback && os_type == filetype_unknown) {
+ printf("Unknown OS filetype (try -f)\n");
goto err_out;
- data.os = os_handle;
-
- os_header = &os_handle->header;
+ }
- if (image_get_arch(os_header) != IH_ARCH) {
- printf("Unsupported Architecture 0x%x\n",
- image_get_arch(os_header));
- goto err_out;
+ if (os_type == filetype_uimage) {
+ ret = bootm_open_os_uimage(&data);
+ if (ret) {
+ printf("loading initrd failed with %s\n",
+ strerror(-ret));
+ goto err_out;
+ }
}
- if (initrdname) {
- /* check for multi image @<num> */
- if (initrdname[0] == '@') {
- int num = simple_strtol(optarg + 1, NULL, 0);
+ if (bootm_initrd(&data)) {
+ bootm_image_name_and_no(data.initrd_file, &data.initrd_num);
- data.initrd = get_fake_image_handle(&data, num);
- } else {
- data.initrd = map_image(optarg, data.verify);
- }
- if (!data.initrd)
+ initrd_type = file_name_detect_type(data.initrd_file);
+ if ((int)initrd_type < 0) {
+ printf("could not open %s: %s\n", data.initrd_file,
+ strerror(-initrd_type));
goto err_out;
+ }
+ if (initrd_type == filetype_uimage) {
+ ret = bootm_open_initrd_uimage(&data);
+ if (ret) {
+ printf("loading initrd failed with %s\n",
+ strerror(-ret));
+ goto err_out;
+ }
+ }
}
- /*
- * We have reached the point of no return: we are going to
- * overwrite all exception vector code, so we cannot easily
- * recover from any failures any more...
- */
-
- puts ("OK\n");
-
- /*
- * FIXME: we do not check at all whether
- * - we will write the image to sdram
- * - we overwrite ourselves
- * - kernel and initrd overlap
- */
- ret = relocate_image(data.os, (void *)image_get_load(os_header));
- if (ret)
- goto err_out;
+ if (bootm_verbose(&data)) {
+ printf("\nLoading OS %s '%s'", file_type_to_string(os_type),
+ data.os_file);
+ if (os_type == filetype_uimage &&
+ data.os->header.ih_type == IH_TYPE_MULTI)
+ printf(", multifile image %d", data.os_num);
+ printf("\n");
+ if (data.os_res)
+ printf("OS image is at 0x%08x-0x%08x\n",
+ data.os_res->start,
+ data.os_res->start +
+ data.os_res->size - 1);
+ else
+ printf("OS image not yet relocated\n");
+
+ if (data.initrd_file) {
+ printf("Loading initrd %s '%s'",
+ file_type_to_string(initrd_type),
+ data.initrd_file);
+ if (initrd_type == filetype_uimage &&
+ data.initrd->header.ih_type == IH_TYPE_MULTI)
+ printf(", multifile image %d", data.initrd_num);
+ printf("\n");
+ if (data.initrd_res)
+ printf("initrd is at 0x%08x-0x%08x\n",
+ data.initrd_res->start,
+ data.initrd_res->start +
+ data.initrd_res->size - 1);
+ else
+ printf("initrd image not yet relocated\n");
+ }
+ }
- if (data.initrd) {
- if (data.initrd && data.initrd_address == ~0)
- data.initrd_address = uimage_to_cpu(data.initrd->header.ih_load);
+#ifdef CONFIG_OFTREE
+ if (oftree) {
+ int oftree_num;
- data.initrd_size = image_get_data_size(&data.initrd->header);
+ bootm_image_name_and_no(oftree, &oftree_num);
- ret = relocate_image(data.initrd, (void *)data.initrd_address);
+ ret = bootm_open_oftree(&data, oftree, oftree_num);
if (ret)
goto err_out;
}
-
- /* loop through the registered handlers */
- list_for_each_entry(handler, &handler_list, list) {
- if (image_get_os(os_header) == handler->image_type) {
- handler->bootm(&data);
- printf("handler returned!\n");
- goto err_out;
- }
+#endif
+ if (data.os_address == UIMAGE_SOME_ADDRESS)
+ data.os_address = UIMAGE_INVALID_ADDRESS;
+ if (data.initrd_address == UIMAGE_SOME_ADDRESS)
+ data.initrd_address = UIMAGE_INVALID_ADDRESS;
+
+ handler = bootm_find_handler(os_type, &data);
+ if (!handler) {
+ printf("no image handler found for image type %s\n",
+ file_type_to_string(os_type));
+ if (os_type == filetype_uimage)
+ printf("and os type: %d\n", data.os->header.ih_os);
+ goto err_out;
}
- printf("no image handler found for image type %d\n",
- image_get_os(os_header));
+ if (bootm_verbose(&data))
+ printf("Passing control to %s handler\n", handler->name);
+
+ ret = handler->bootm(&data);
+
+ printf("handler failed with %s\n", strerror(-ret));
err_out:
- if (os_handle)
- unmap_image(os_handle);
- if (data.initrd)
- unmap_image(data.initrd);
- return ret;
+ if (data.os_res)
+ release_sdram_region(data.os_res);
+ if (data.initrd_res)
+ release_sdram_region(data.initrd_res);
+ if (data.initrd && data.initrd != data.os)
+ uimage_close(data.initrd);
+ if (data.os)
+ uimage_close(data.os);
+ return 1;
}
BAREBOX_CMD_HELP_START(bootm)
BAREBOX_CMD_HELP_USAGE("bootm [OPTIONS] image\n")
BAREBOX_CMD_HELP_SHORT("Boot an application image.\n")
-BAREBOX_CMD_HELP_OPT ("-n", "Do not verify the image (speeds up boot process)\n")
+BAREBOX_CMD_HELP_OPT ("-c", "crc check uImage data\n")
+#ifdef CONFIG_CMD_BOOTM_INITRD
BAREBOX_CMD_HELP_OPT ("-r <initrd>","specify an initrd image\n")
-BAREBOX_CMD_HELP_OPT ("-L <load addr>","specify initrd load address")
+BAREBOX_CMD_HELP_OPT ("-L <load addr>","specify initrd load address\n")
+#endif
+BAREBOX_CMD_HELP_OPT ("-a <load addr>","specify os load address\n")
+BAREBOX_CMD_HELP_OPT ("-e <ofs>","entry point to the image relative to start (0)\n")
+#ifdef CONFIG_OFTREE
+BAREBOX_CMD_HELP_OPT ("-o <oftree>","specify oftree\n")
+#endif
+#ifdef CONFIG_CMD_BOOTM_VERBOSE
+BAREBOX_CMD_HELP_OPT ("-v","verbose\n")
+#endif
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(bootm)
@@ -245,13 +453,6 @@ BAREBOX_CMD_END
BAREBOX_MAGICVAR(bootargs, "Linux Kernel parameters");
-#ifdef CONFIG_BZLIB
-void bz_internal_error(int errcode)
-{
- printf ("BZIP2 internal error %d\n", errcode);
-}
-#endif /* CONFIG_BZLIB */
-
/**
* @file
* @brief Boot support for Linux
diff --git a/include/boot.h b/include/boot.h
index 297b944c71..a17bf25a4c 100644
--- a/include/boot.h
+++ b/include/boot.h
@@ -2,25 +2,73 @@
#define __BOOT_H
#include <image.h>
+#include <filetype.h>
+#include <of.h>
#include <linux/list.h>
struct image_data {
- struct image_handle *os;
- struct image_handle *initrd;
- void *oftree;
- int verify;
+ /* simplest case. barebox has already loaded the os here */
+ struct resource *os_res;
+
+ /* if os is an uImage this will be provided */
+ struct uimage_handle *os;
+ int os_num;
+
+ /* otherwise only the filename will be provided */
+ char *os_file;
+
+ /*
+ * The address the user wants to load the os image to.
+ * May be UIMAGE_INVALID_ADDRESS to indicate that the
+ * user has not specified any address. In this case the
+ * handler may choose a suitable address
+ */
+ unsigned long os_address;
+
+ /* entry point to the os. relative to the start of the image */
+ unsigned long os_entry;
+
+ /* if initrd is already loaded this resource will be !NULL */
+ struct resource *initrd_res;
+
+ /* if initrd is an uImage this will be provided */
+ struct uimage_handle *initrd;
+ int initrd_num;
+
+ /* otherwise only the filename will be provided */
+ char *initrd_file;
+
unsigned long initrd_address;
- unsigned long initrd_size;
+
+ struct fdt_header *oftree;
+
+ int verify;
+ int verbose;
};
struct image_handler {
+ const char *name;
+
struct list_head list;
- int image_type;
+ int ih_os;
+
+ enum filetype filetype;
int (*bootm)(struct image_data *data);
};
int register_image_handler(struct image_handler *handle);
-#endif /* __BOOT_H */
+#ifdef CONFIG_CMD_BOOTM_VERBOSE
+static inline int bootm_verbose(struct image_data *data)
+{
+ return data->verbose;
+}
+#else
+static inline int bootm_verbose(struct image_data *data)
+{
+ return 0;
+}
+#endif
+#endif /* __BOOT_H */