Hi Rob, > From: Sebastian Siewior <bige...@linutronix.de> > > 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" is currently ignored. 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. > > Cc: Wolfgang Denk <w...@denx.de> > Signed-off-by: Sebastian Andrzej Siewior <bige...@linutronix.de> > Signed-off-by: Rob Herring <r...@kernel.org> > --- > common/Makefile | 1 + > common/cmd_bootm.c | 23 +++++++++++++- > common/image-android.c | 84 > +++++++++++++++++++++++++++++++++++++++++++++++++ > common/image.c | 20 +++++++++--- include/android_image.h | > 69 ++++++++++++++++++++++++++++++++++++++++ include/image.h | > 13 ++++++++ 6 files changed, 204 insertions(+), 6 deletions(-) > create mode 100644 common/image-android.c > create mode 100644 include/android_image.h > > diff --git a/common/Makefile b/common/Makefile > index cecd81a..da208f3 100644 > --- a/common/Makefile > +++ b/common/Makefile > @@ -236,6 +236,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 9751edc..b6c8288 100644 > --- a/common/cmd_bootm.c > +++ b/common/cmd_bootm.c > @@ -223,6 +223,8 @@ static int bootm_find_os(cmd_tbl_t *cmdtp, int > flag, int argc, { > const void *os_hdr; > > + images.ep = ~0UL; > + > /* get kernel image header, start address and length */ > os_hdr = boot_get_kernel(cmdtp, flag, argc, argv, > &images, &images.os.image_start, > &images.os.image_len); @@ -274,6 +276,17 @@ 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; > + > + 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 (images.ep == ~0UL) { > 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..ec6fb3d > --- /dev/null > +++ b/common/image-android.c > @@ -0,0 +1,84 @@ > +/* > + * Copyright (c) 2011 Sebastian Andrzej Siewior > <bige...@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 andriod_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 afbf806..b6063f6 100644 > --- a/common/image.c > +++ b/common/image.c > @@ -676,10 +676,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; > @@ -949,7 +951,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) > && > + (!andriod_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..b123860 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 andriod_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__ */
Reviewed-by: Lukasz Majewski <l.majew...@samsung.com> -- Best regards, Lukasz Majewski Samsung R&D Institute Poland (SRPOL) | Linux Platform Group _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot