diff options
author | Tom Rini <trini@ti.com> | 2014-08-14 06:42:36 -0400 |
---|---|---|
committer | Tom Rini <trini@ti.com> | 2014-08-30 07:46:41 -0400 |
commit | d2b2ffe3107dc2b43352b391129bc84340be0b35 (patch) | |
tree | e3c06b19d58c8b3b134fa6eb3b7dec4f4a7d98db | |
parent | 3f1b6bebe0cbe71ad6beab3c7a00ab2f2b082ca7 (diff) | |
download | u-boot-d2b2ffe3107dc2b43352b391129bc84340be0b35.tar.gz u-boot-d2b2ffe3107dc2b43352b391129bc84340be0b35.tar.xz u-boot-d2b2ffe3107dc2b43352b391129bc84340be0b35.zip |
cmd_bootm.c: Add 'booti' for ARM64 Linux kernel Images
The default format for arm64 Linux kernels is the "Image" format,
described in Documentation/arm64/booting.txt. This, along with an
optional gzip compression on top is all that is generated by default.
The Image format has a magic number within the header for verification,
a text_offset where the Image must be run from, an image_size that
includes the BSS and reserved fields.
This does not support automatic detection of a gzip compressed image.
Signed-off-by: Tom Rini <trini@ti.com>
-rw-r--r-- | README | 1 | ||||
-rw-r--r-- | common/cmd_bootm.c | 140 | ||||
-rw-r--r-- | include/bootm.h | 2 |
3 files changed, 142 insertions, 1 deletions
@@ -959,6 +959,7 @@ The following options need to be configured: CONFIG_CMD_BMP * BMP support CONFIG_CMD_BSP * Board specific commands CONFIG_CMD_BOOTD bootd + CONFIG_CMD_BOOTI * ARM64 Linux kernel Image support CONFIG_CMD_CACHE * icache, dcache CONFIG_CMD_CLK * clock command support CONFIG_CMD_CONSOLE coninfo diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 8b897c8d66..843ec6e0c2 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -627,3 +627,143 @@ U_BOOT_CMD( "boot Linux zImage image from memory", bootz_help_text ); #endif /* CONFIG_CMD_BOOTZ */ + +#ifdef CONFIG_CMD_BOOTI +/* See Documentation/arm64/booting.txt in the Linux kernel */ +struct Image_header { + uint32_t code0; /* Executable code */ + uint32_t code1; /* Executable code */ + uint64_t text_offset; /* Image load offset, LE */ + uint64_t image_size; /* Effective Image size, LE */ + uint64_t res1; /* reserved */ + uint64_t res2; /* reserved */ + uint64_t res3; /* reserved */ + uint64_t res4; /* reserved */ + uint32_t magic; /* Magic number */ + uint32_t res5; +}; + +#define LINUX_ARM64_IMAGE_MAGIC 0x644d5241 + +static int booti_setup(bootm_headers_t *images) +{ + struct Image_header *ih; + uint64_t dst; + + ih = (struct Image_header *)map_sysmem(images->ep, 0); + + if (ih->magic != le32_to_cpu(LINUX_ARM64_IMAGE_MAGIC)) { + puts("Bad Linux ARM64 Image magic!\n"); + return 1; + } + + if (ih->image_size == 0) { + puts("Image lacks image_size field, assuming 16MiB\n"); + ih->image_size = (16 << 20); + } + + /* + * If we are not at the correct run-time location, set the new + * correct location and then move the image there. + */ + dst = gd->bd->bi_dram[0].start + le32_to_cpu(ih->text_offset); + if (images->ep != dst) { + void *src; + + debug("Moving Image from 0x%lx to 0x%llx\n", images->ep, dst); + + src = (void *)images->ep; + images->ep = dst; + memmove((void *)dst, src, le32_to_cpu(ih->image_size)); + } + + return 0; +} + +/* + * Image booting support + */ +static int booti_start(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[], bootm_headers_t *images) +{ + int ret; + struct Image_header *ih; + + ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START, + images, 1); + + /* Setup Linux kernel Image entry point */ + if (!argc) { + images->ep = load_addr; + debug("* kernel: default image load address = 0x%08lx\n", + load_addr); + } else { + images->ep = simple_strtoul(argv[0], NULL, 16); + debug("* kernel: cmdline image address = 0x%08lx\n", + images->ep); + } + + ret = booti_setup(images); + if (ret != 0) + return 1; + + ih = (struct Image_header *)map_sysmem(images->ep, 0); + + lmb_reserve(&images->lmb, images->ep, le32_to_cpu(ih->image_size)); + + /* + * Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not + * have a header that provide this informaiton. + */ + if (bootm_find_ramdisk_fdt(flag, argc, argv)) + return 1; + + return 0; +} + +int do_booti(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int ret; + + /* Consume 'booti' */ + argc--; argv++; + + if (booti_start(cmdtp, flag, argc, argv, &images)) + return 1; + + /* + * We are doing the BOOTM_STATE_LOADOS state ourselves, so must + * disable interrupts ourselves + */ + bootm_disable_interrupts(); + + images.os.os = IH_OS_LINUX; + ret = do_bootm_states(cmdtp, flag, argc, argv, + BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO | + BOOTM_STATE_OS_GO, + &images, 1); + + return ret; +} + +#ifdef CONFIG_SYS_LONGHELP +static char booti_help_text[] = + "[addr [initrd[:size]] [fdt]]\n" + " - boot Linux Image stored in memory\n" + "\tThe argument 'initrd' is optional and specifies the address\n" + "\tof the initrd in memory. The optional argument ':size' allows\n" + "\tspecifying the size of RAW initrd.\n" +#if defined(CONFIG_OF_LIBFDT) + "\tSince booting a Linux kernelrequires a flat device-tree\n" + "\ta third argument is required which is the address of the\n" + "\tdevice-tree blob. To boot that kernel without an initrd image,\n" + "\tuse a '-' for the second argument.\n" +#endif + ""; +#endif + +U_BOOT_CMD( + booti, CONFIG_SYS_MAXARGS, 1, do_booti, + "boot arm64 Linux Image image from memory", booti_help_text +); +#endif /* CONFIG_CMD_BOOTI */ diff --git a/include/bootm.h b/include/bootm.h index 4a308d8115..694d6fc080 100644 --- a/include/bootm.h +++ b/include/bootm.h @@ -48,7 +48,7 @@ int boot_selected_os(int argc, char * const argv[], int state, ulong bootm_disable_interrupts(void); -/* This is a special function used by bootz */ +/* This is a special function used by booti/bootz */ int bootm_find_ramdisk_fdt(int flag, int argc, char * const argv[]); int do_bootm_states(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], |