From: Tom Rini Date: Thu, 14 Aug 2014 10:42:36 +0000 (-0400) Subject: cmd_bootm.c: Add 'booti' for ARM64 Linux kernel Images X-Git-Tag: v2014.10-rc2~26 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=d2b2ffe3107dc2b43352b391129bc84340be0b35;p=oweals%2Fu-boot.git 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 --- diff --git a/README b/README index 517b0b4499..0a0f528af1 100644 --- a/README +++ b/README @@ -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[],