summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--include/android_image.h69
-rw-r--r--include/image.h13
6 files changed, 204 insertions, 6 deletions
diff --git a/common/Makefile b/common/Makefile
index 2d4e877..c52aede 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 6cd9242..e6b8b0f 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;
}
@@ -1012,6 +1025,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
*/
diff --git a/include/android_image.h b/include/android_image.h
new file mode 100644
index 0000000..094d60a
--- /dev/null
+++ b/include/android_image.h
@@ -0,0 +1,69 @@
+/*
+ * This is from the Android Project,
+ * Repository: https://android.googlesource.com/platform/bootable/bootloader/legacy
+ * File: include/boot/bootimg.h
+ * Commit: 4205b865141ff2e255fe1d3bd16de18e217ef06a
+ *
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef _ANDROID_IMAGE_H_
+#define _ANDROID_IMAGE_H_
+
+#define ANDR_BOOT_MAGIC "ANDROID!"
+#define ANDR_BOOT_MAGIC_SIZE 8
+#define ANDR_BOOT_NAME_SIZE 16
+#define ANDR_BOOT_ARGS_SIZE 512
+
+struct andr_img_hdr {
+ char magic[ANDR_BOOT_MAGIC_SIZE];
+
+ u32 kernel_size; /* size in bytes */
+ u32 kernel_addr; /* physical load addr */
+
+ u32 ramdisk_size; /* size in bytes */
+ u32 ramdisk_addr; /* physical load addr */
+
+ u32 second_size; /* size in bytes */
+ u32 second_addr; /* physical load addr */
+
+ u32 tags_addr; /* physical addr for kernel tags */
+ u32 page_size; /* flash page size we assume */
+ u32 unused[2]; /* future expansion: should be 0 */
+
+ char name[ANDR_BOOT_NAME_SIZE]; /* asciiz product name */
+
+ char cmdline[ANDR_BOOT_ARGS_SIZE];
+
+ u32 id[8]; /* timestamp / checksum / sha1 / etc */
+};
+
+/*
+ * +-----------------+
+ * | boot header | 1 page
+ * +-----------------+
+ * | kernel | n pages
+ * +-----------------+
+ * | ramdisk | m pages
+ * +-----------------+
+ * | second stage | o pages
+ * +-----------------+
+ *
+ * n = (kernel_size + page_size - 1) / page_size
+ * m = (ramdisk_size + page_size - 1) / page_size
+ * o = (second_size + page_size - 1) / page_size
+ *
+ * 0. all entities are page_size aligned in flash
+ * 1. kernel and ramdisk are required (size != 0)
+ * 2. second is optional (second_size == 0 -> no second)
+ * 3. load each element (kernel, ramdisk, second) at
+ * the specified physical address (kernel_addr, etc)
+ * 4. prepare tags at tag_addr. kernel_args[] is
+ * appended to the kernel commandline in the tags.
+ * 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
+ * 6. if second_size != 0: jump to second_addr
+ * else: jump to kernel_addr
+ */
+#endif
diff --git a/include/image.h b/include/image.h
index 6afd57b..5f85b96 100644
--- a/include/image.h
+++ b/include/image.h
@@ -403,6 +403,7 @@ enum fit_load_op {
#define IMAGE_FORMAT_INVALID 0x00
#define IMAGE_FORMAT_LEGACY 0x01 /* legacy image_header based format */
#define IMAGE_FORMAT_FIT 0x02 /* new, libfdt based format */
+#define IMAGE_FORMAT_ANDROID 0x03 /* Android boot image */
int genimg_get_format(const void *img_addr);
int genimg_has_config(bootm_headers_t *images);
@@ -996,4 +997,16 @@ static inline int fit_image_check_target_arch(const void *fdt, int node)
#endif /* CONFIG_FIT_VERBOSE */
#endif /* CONFIG_FIT */
+#if defined(CONFIG_ANDROID_BOOT_IMAGE)
+struct andr_img_hdr;
+int android_image_check_header(const struct andr_img_hdr *hdr);
+int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify,
+ ulong *os_data, ulong *os_len);
+int android_image_get_ramdisk(const struct andr_img_hdr *hdr,
+ ulong *rd_data, ulong *rd_len);
+ulong android_image_get_end(const struct andr_img_hdr *hdr);
+ulong android_image_get_kload(const struct andr_img_hdr *hdr);
+
+#endif /* CONFIG_ANDROID_BOOT_IMAGE */
+
#endif /* __IMAGE_H__ */