summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
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 7c853ae442..bfcb4664b7 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 c243a5bd78..993b906c70 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 0000000000..6ded7e2c97
--- /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 9c6bec5b76..7ff27d75c3 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
*/