summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorSebastian Siewior <bigeasy@linutronix.de>2014-05-05 15:08:09 -0500
committerLukasz Majewski <l.majewski@samsung.com>2014-05-08 10:38:29 +0200
commit9ace3fc81427f6a4036718c2daff9d6f8ee7b69a (patch)
treeb7565100e9f731cf375e33d6dd4b47ac5bde100a /common
parent8c6004568f7f0cb98c35fb86a193b502278f650f (diff)
downloadu-boot-imx-9ace3fc81427f6a4036718c2daff9d6f8ee7b69a.zip
u-boot-imx-9ace3fc81427f6a4036718c2daff9d6f8ee7b69a.tar.gz
u-boot-imx-9ace3fc81427f6a4036718c2daff9d6f8ee7b69a.tar.bz2
image: add support for Android's boot image format
This patch adds support for the Android boot-image format. The header file is from the Android project and got slightly alterted so the struct + its defines are not generic but have something like a namespace. The header file is from bootloader/legacy/include/boot/bootimg.h. The header parsing has been written from scratch and I looked at bootloader/legacy/usbloader/usbloader.c for some details. The image contains the physical address (load address) of the kernel and ramdisk. This address is considered only for the kernel image. The "second image" defined in the image header is currently not supported. I haven't found anything that is creating this. v3 (Rob Herring): This is based on http://patchwork.ozlabs.org/patch/126797/ with the following changes: - Rebased to current mainline - Moved android image handling to separate functions in common/image-android.c - s/u8/char/ in header to fix string function warnings - Use SPDX identifiers for licenses - Cleaned-up file source information: android_image.h is from file include/boot/bootimg.h in repository: https://android.googlesource.com/platform/bootable/bootloader/legacy The git commit hash is 4205b865141ff2e255fe1d3bd16de18e217ef06a usbloader.c would be from the same commit, but it does not appear to have been used for any actual code. v4: - s/andriod/android/ - Use a separate flag ep_found to track if the entry point has been set rather than using a magic value. Cc: Wolfgang Denk <wd@denx.de> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Rob Herring <robh@kernel.org> Reviewed-by: Tom Rini <trini@ti.com> Reviewed-by: Lukasz Majewski <l.majewski@samsung.com>
Diffstat (limited to 'common')
-rw-r--r--common/Makefile1
-rw-r--r--common/cmd_bootm.c23
-rw-r--r--common/image-android.c84
-rw-r--r--common/image.c20
4 files changed, 122 insertions, 6 deletions
diff --git a/common/Makefile b/common/Makefile
index 7c853ae..bfcb466 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -237,6 +237,7 @@ obj-y += console.o
obj-$(CONFIG_CROS_EC) += cros_ec.o
obj-y += dlmalloc.o
obj-y += image.o
+obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o
obj-$(CONFIG_OF_LIBFDT) += image-fdt.o
obj-$(CONFIG_FIT) += image-fit.o
obj-$(CONFIG_FIT_SIGNATURE) += image-sig.o
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index c243a5b..993b906 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -222,6 +222,7 @@ static int bootm_find_os(cmd_tbl_t *cmdtp, int flag, int argc,
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,
@@ -274,6 +275,18 @@ static int bootm_find_os(cmd_tbl_t *cmdtp, int flag, int argc,
}
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;
@@ -293,7 +306,7 @@ static int bootm_find_os(cmd_tbl_t *cmdtp, int flag, int argc,
return 1;
}
#endif
- } else {
+ } else if (!ep_found) {
puts("Could not find kernel entry point!\n");
return 1;
}
@@ -1002,6 +1015,14 @@ static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
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);
diff --git a/common/image-android.c b/common/image-android.c
new file mode 100644
index 0000000..6ded7e2
--- /dev/null
+++ b/common/image-android.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2011 Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <image.h>
+#include <android_image.h>
+
+static char andr_tmp_str[ANDR_BOOT_ARGS_SIZE + 1];
+
+int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify,
+ ulong *os_data, ulong *os_len)
+{
+ /*
+ * Not all Android tools use the id field for signing the image with
+ * sha1 (or anything) so we don't check it. It is not obvious that the
+ * string is null terminated so we take care of this.
+ */
+ strncpy(andr_tmp_str, hdr->name, ANDR_BOOT_NAME_SIZE);
+ andr_tmp_str[ANDR_BOOT_NAME_SIZE] = '\0';
+ if (strlen(andr_tmp_str))
+ printf("Android's image name: %s\n", andr_tmp_str);
+
+ printf("Kernel load addr 0x%08x size %u KiB\n",
+ hdr->kernel_addr, DIV_ROUND_UP(hdr->kernel_size, 1024));
+ strncpy(andr_tmp_str, hdr->cmdline, ANDR_BOOT_ARGS_SIZE);
+ andr_tmp_str[ANDR_BOOT_ARGS_SIZE] = '\0';
+ if (strlen(andr_tmp_str)) {
+ printf("Kernel command line: %s\n", andr_tmp_str);
+ setenv("bootargs", andr_tmp_str);
+ }
+ if (hdr->ramdisk_size)
+ printf("RAM disk load addr 0x%08x size %u KiB\n",
+ hdr->ramdisk_addr,
+ DIV_ROUND_UP(hdr->ramdisk_size, 1024));
+
+ if (os_data) {
+ *os_data = (ulong)hdr;
+ *os_data += hdr->page_size;
+ }
+ if (os_len)
+ *os_len = hdr->kernel_size;
+ return 0;
+}
+
+int android_image_check_header(const struct andr_img_hdr *hdr)
+{
+ return memcmp(ANDR_BOOT_MAGIC, hdr->magic, ANDR_BOOT_MAGIC_SIZE);
+}
+
+ulong android_image_get_end(const struct andr_img_hdr *hdr)
+{
+ u32 size = 0;
+ /*
+ * The header takes a full page, the remaining components are aligned
+ * on page boundary
+ */
+ size += hdr->page_size;
+ size += ALIGN(hdr->kernel_size, hdr->page_size);
+ size += ALIGN(hdr->ramdisk_size, hdr->page_size);
+ size += ALIGN(hdr->second_size, hdr->page_size);
+
+ return size;
+}
+
+ulong android_image_get_kload(const struct andr_img_hdr *hdr)
+{
+ return hdr->kernel_addr;
+}
+
+int android_image_get_ramdisk(const struct andr_img_hdr *hdr,
+ ulong *rd_data, ulong *rd_len)
+{
+ if (!hdr->ramdisk_size)
+ return -1;
+ *rd_data = (unsigned long)hdr;
+ *rd_data += hdr->page_size;
+ *rd_data += ALIGN(hdr->kernel_size, hdr->page_size);
+
+ *rd_len = hdr->ramdisk_size;
+ return 0;
+}
diff --git a/common/image.c b/common/image.c
index 9c6bec5..7ff27d7 100644
--- a/common/image.c
+++ b/common/image.c
@@ -659,10 +659,12 @@ int genimg_get_format(const void *img_addr)
if (image_check_magic(hdr))
format = IMAGE_FORMAT_LEGACY;
#if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT)
- else {
- if (fdt_check_header(img_addr) == 0)
- format = IMAGE_FORMAT_FIT;
- }
+ else if (fdt_check_header(img_addr) == 0)
+ format = IMAGE_FORMAT_FIT;
+#endif
+#ifdef CONFIG_ANDROID_BOOT_IMAGE
+ else if (android_image_check_header(img_addr) == 0)
+ format = IMAGE_FORMAT_ANDROID;
#endif
return format;
@@ -932,7 +934,15 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images,
(ulong)images->legacy_hdr_os);
image_multi_getimg(images->legacy_hdr_os, 1, &rd_data, &rd_len);
- } else {
+ }
+#ifdef CONFIG_ANDROID_BOOT_IMAGE
+ else if ((genimg_get_format(images) == IMAGE_FORMAT_ANDROID) &&
+ (!android_image_get_ramdisk((void *)images->os.start,
+ &rd_data, &rd_len))) {
+ /* empty */
+ }
+#endif
+ else {
/*
* no initrd image
*/