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

Reply via email to