android: support loading android image separate
This patch support loading android image separate for the kernel/ramdisk/second images. It is disabled when android AVB is enabled, because AVB need verify the full android image. It brings some benefits, mainly for saving a lot of boot time: - allow skip load second content when kernel dtb is enabled; - allow skip fdt and ramdisk relocation during bootm boot flow; - allow loading fdt/ramdisk to "fdt_addr_r"/"ramdisk_addr_r"; - avoid android image too large when load to ram; Change-Id: Ia040b3031307a8a7c98b011ce038ec61fee6804a Signed-off-by: Joseph Chen <chenjh@rock-chips.com>
This commit is contained in:
parent
2280fbdd62
commit
644e344181
|
|
@ -623,6 +623,15 @@ config ANDROID_BOOT_IMAGE
|
|||
This enables support for booting images which use the Android
|
||||
image format header.
|
||||
|
||||
config ANDROID_BOOT_IMAGE_SEPARATE
|
||||
bool "Enable support for Android image separate loading"
|
||||
depends on ANDROID_BOOT_IMAGE
|
||||
default y
|
||||
help
|
||||
This enables support for android image separate loading. With this support,
|
||||
we can load ramdisk/fdt/kernel separate and skip ramdisk and fdt relocation
|
||||
safely. It saves a lot of boot time.
|
||||
|
||||
config SKIP_RELOCATE_UBOOT
|
||||
bool "Skip U-Boot relocation"
|
||||
help
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include <keymaster.h>
|
||||
#include <linux/libfdt_env.h>
|
||||
#include <optee_include/OpteeClientInterface.h>
|
||||
#include <sysmem.h>
|
||||
|
||||
#define ANDROID_PARTITION_BOOT "boot"
|
||||
#define ANDROID_PARTITION_MISC "misc"
|
||||
|
|
@ -331,6 +332,8 @@ int android_bootloader_boot_kernel(unsigned long kernel_address)
|
|||
printf("Booting kernel at %s with fdt at %s...\n\n\n",
|
||||
kernel_addr_r, fdt_addr);
|
||||
|
||||
sysmem_dump_check();
|
||||
|
||||
do_bootm(NULL, 0, 4, bootm_args);
|
||||
|
||||
return -1;
|
||||
|
|
@ -802,7 +805,16 @@ int android_fdt_overlay_apply(void *fdt_addr)
|
|||
|
||||
ret = android_get_dtbo(&fdt_dtbo, (void *)hdr, &index);
|
||||
if (!ret) {
|
||||
phys_size_t fdt_size;
|
||||
/* Must incease size before overlay */
|
||||
fdt_size = fdt_totalsize((void *)fdt_addr) +
|
||||
fdt_totalsize((void *)fdt_dtbo);
|
||||
if (sysmem_free((phys_addr_t)fdt_addr))
|
||||
goto out;
|
||||
if (!sysmem_alloc_base("fdt(dtbo)",
|
||||
(phys_addr_t)fdt_addr,
|
||||
fdt_size))
|
||||
goto out;
|
||||
fdt_increase_size(fdt_addr, fdt_totalsize((void *)fdt_dtbo));
|
||||
ret = fdt_overlay_apply(fdt_addr, (void *)fdt_dtbo);
|
||||
if (!ret) {
|
||||
|
|
@ -842,8 +854,8 @@ static int load_android_image(struct blk_desc *dev_desc,
|
|||
|
||||
ret = android_image_load(dev_desc, &boot_part, *load_address, -1UL);
|
||||
if (ret < 0) {
|
||||
printf("%s: %s part load fail, ret=%d\n",
|
||||
__func__, boot_part.name, ret);
|
||||
debug("%s: %s part load fail, ret=%d\n",
|
||||
__func__, boot_part.name, ret);
|
||||
return ret;
|
||||
}
|
||||
*load_address = ret;
|
||||
|
|
|
|||
|
|
@ -10,9 +10,17 @@
|
|||
#include <malloc.h>
|
||||
#include <mapmem.h>
|
||||
#include <errno.h>
|
||||
#include <boot_rkimg.h>
|
||||
#include <sysmem.h>
|
||||
#ifdef CONFIG_RKIMG_BOOTLOADER
|
||||
#include <asm/arch/resource_img.h>
|
||||
#endif
|
||||
#ifdef CONFIG_RK_AVB_LIBAVB_USER
|
||||
#include <android_avb/avb_slot_verify.h>
|
||||
#include <android_avb/avb_ops_user.h>
|
||||
#include <android_avb/rk_avb_ops_user.h>
|
||||
#endif
|
||||
#include <optee_include/OpteeClientInterface.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
|
|
@ -29,7 +37,7 @@ static ulong android_image_get_kernel_addr(const struct andr_img_hdr *hdr)
|
|||
* address as the default.
|
||||
*
|
||||
* Even though it doesn't really make a lot of sense, and it
|
||||
* might be valid on some platforms, we treat that adress as
|
||||
* might be valid on some platforms, we treat that address as
|
||||
* the default value for this field, and try to execute the
|
||||
* kernel in place in such a case.
|
||||
*
|
||||
|
|
@ -190,9 +198,25 @@ int android_image_get_ramdisk(const struct andr_img_hdr *hdr,
|
|||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* We load ramdisk at "ramdisk_addr_r" when CONFIG_ANDROID_BOOT_IMAGE_SEPARATE
|
||||
* CONFIG_USING_KERNEL_DTB is enabled.
|
||||
*/
|
||||
#ifdef CONFIG_ANDROID_BOOT_IMAGE_SEPARATE
|
||||
ulong ramdisk_addr_r;
|
||||
|
||||
ramdisk_addr_r = env_get_ulong("ramdisk_addr_r", 16, 0);
|
||||
if (!ramdisk_addr_r) {
|
||||
printf("No Found Ramdisk Load Address.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*rd_data = ramdisk_addr_r;
|
||||
#else
|
||||
*rd_data = (unsigned long)hdr;
|
||||
*rd_data += hdr->page_size;
|
||||
*rd_data += ALIGN(hdr->kernel_size, hdr->page_size);
|
||||
#endif
|
||||
*rd_len = hdr->ramdisk_size;
|
||||
|
||||
printf("RAM disk load addr 0x%08lx size %u KiB\n",
|
||||
|
|
@ -209,65 +233,123 @@ int android_image_get_fdt(const struct andr_img_hdr *hdr,
|
|||
return -1;
|
||||
}
|
||||
/*
|
||||
* If kernel dtb is enabled, it means we have read kernel dtb before do_bootm(),
|
||||
* that's: init_kernel_dtb() -> rockchip_read_dtb_file().
|
||||
* And maybe some operations(optional) are done:
|
||||
*
|
||||
* 1. apply fdt overlay;
|
||||
* 2. select fdt by adc or gpio;
|
||||
*
|
||||
* After that, we didn't update dtb at all untill run here, it's fine to
|
||||
* pass current fdt to kernel.
|
||||
*
|
||||
* This case has higher priority then the others(#elif, #else...).
|
||||
* We load fdt at "fdt_addr_r" when CONFIG_ANDROID_BOOT_IMAGE_SEPARATE or
|
||||
* or CONFIG_USING_KERNEL_DTB is enabled.
|
||||
*/
|
||||
#if defined(CONFIG_USING_KERNEL_DTB)
|
||||
*rd_data = (ulong)gd->fdt_blob;
|
||||
#if defined(CONFIG_ANDROID_BOOT_IMAGE_SEPARATE) || \
|
||||
defined(CONFIG_USING_KERNEL_DTB)
|
||||
ulong fdt_addr_r;
|
||||
|
||||
/*
|
||||
* If kernel dtb is disabled, it means kernel dtb is not read before do_bootm(),
|
||||
* we need to read it from boot.img/recovery.img now.
|
||||
*
|
||||
* For rockchip AOSP firmware(CONFIG_RKIMG_BOOTLOADER), we pack resource.img in
|
||||
* second position. we need read kernel dtb by rockchip_read_dtb_file() which
|
||||
* can do the above "some operations(optional)".
|
||||
*/
|
||||
#elif defined(CONFIG_RKIMG_BOOTLOADER)
|
||||
ulong fdt_addr = 0;
|
||||
int ret;
|
||||
|
||||
/* Get resource addr and fdt addr */
|
||||
fdt_addr = env_get_ulong("fdt_addr_r", 16, 0);
|
||||
if (!fdt_addr) {
|
||||
fdt_addr_r = env_get_ulong("fdt_addr_r", 16, 0);
|
||||
if (!fdt_addr_r) {
|
||||
printf("No Found FDT Load Address.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = rockchip_read_dtb_file((void *)fdt_addr);
|
||||
if (ret < 0) {
|
||||
printf("%s: failed to read dtb file, ret=%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
*rd_data = fdt_addr;
|
||||
|
||||
/*
|
||||
* If kernel dtb is disabled and it's not rockchip AOSP firmware, kernel dtb is
|
||||
* in second position, let't read it directly.
|
||||
*/
|
||||
*rd_data = fdt_addr_r;
|
||||
#else
|
||||
*rd_data = (unsigned long)hdr;
|
||||
*rd_data += hdr->page_size;
|
||||
*rd_data += ALIGN(hdr->kernel_size, hdr->page_size);
|
||||
*rd_data += ALIGN(hdr->ramdisk_size, hdr->page_size);
|
||||
#endif
|
||||
|
||||
printf("FDT load addr 0x%08x size %u KiB\n",
|
||||
hdr->second_addr, DIV_ROUND_UP(hdr->second_size, 1024));
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ANDROID_BOOT_IMAGE_SEPARATE
|
||||
static int android_image_load_separate(struct blk_desc *dev_desc,
|
||||
struct andr_img_hdr *hdr,
|
||||
const disk_partition_t *part,
|
||||
void *android_load_address)
|
||||
{
|
||||
ulong fdt_addr_r = env_get_ulong("fdt_addr_r", 16, 0);
|
||||
ulong blk_start, blk_cnt, size;
|
||||
int ret, blk_read = 0;
|
||||
|
||||
if (hdr->kernel_size) {
|
||||
size = hdr->kernel_size + hdr->page_size;
|
||||
blk_start = part->start;
|
||||
blk_cnt = DIV_ROUND_UP(size, dev_desc->blksz);
|
||||
if (!sysmem_alloc_base("kernel",
|
||||
(phys_addr_t)android_load_address,
|
||||
blk_cnt * dev_desc->blksz))
|
||||
return -ENXIO;
|
||||
|
||||
ret = blk_dread(dev_desc, blk_start,
|
||||
blk_cnt, android_load_address);
|
||||
if (ret < 0) {
|
||||
debug("%s: read kernel failed, ret=%d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
blk_read += ret;
|
||||
}
|
||||
|
||||
if (hdr->ramdisk_size) {
|
||||
ulong ramdisk_addr_r = env_get_ulong("ramdisk_addr_r", 16, 0);
|
||||
|
||||
size = hdr->page_size + ALIGN(hdr->kernel_size, hdr->page_size);
|
||||
blk_start = part->start + DIV_ROUND_UP(size, dev_desc->blksz);
|
||||
blk_cnt = DIV_ROUND_UP(hdr->ramdisk_size, dev_desc->blksz);
|
||||
if (!sysmem_alloc_base("ramdisk",
|
||||
ramdisk_addr_r,
|
||||
blk_cnt * dev_desc->blksz))
|
||||
return -ENXIO;
|
||||
|
||||
ret = blk_dread(dev_desc, blk_start,
|
||||
blk_cnt, (void *)ramdisk_addr_r);
|
||||
if (ret < 0) {
|
||||
debug("%s: read ramdisk failed, ret=%d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
blk_read += ret;
|
||||
}
|
||||
|
||||
if ((gd->fdt_blob != (void *)fdt_addr_r) && hdr->second_size) {
|
||||
#ifdef CONFIG_RKIMG_BOOTLOADER
|
||||
/* Rockchip AOSP, resource.img is in second position */
|
||||
ulong fdt_size;
|
||||
|
||||
fdt_size = rockchip_read_dtb_file((void *)fdt_addr_r);
|
||||
if (fdt_size < 0) {
|
||||
printf("%s: read fdt failed\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
blk_read += DIV_ROUND_UP(fdt_size, dev_desc->blksz);
|
||||
#else
|
||||
/* Standard AOSP, dtb is in second position */
|
||||
ulong blk_start, blk_cnt;
|
||||
|
||||
size = hdr->page_size +
|
||||
ALIGN(hdr->kernel_size, hdr->page_size) +
|
||||
ALIGN(hdr->ramdisk_size, hdr->page_size);
|
||||
blk_start = part->start + DIV_ROUND_UP(size, dev_desc->blksz);
|
||||
blk_cnt = DIV_ROUND_UP(hdr->second_size, dev_desc->blksz);
|
||||
if (!sysmem_alloc_base("fdt(AOSP)",
|
||||
fdt_addr_r,
|
||||
blk_cnt * dev_desc->blksz))
|
||||
return -ENXIO;
|
||||
|
||||
ret = blk_dread(dev_desc, blk_start, blk_cnt, (void *)fdt_addr_r);
|
||||
if (ret < 0) {
|
||||
debug("%s: read dtb failed, ret=%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
blk_read += blk_cnt;
|
||||
#endif /* CONFIG_RKIMG_BOOTLOADER */
|
||||
}
|
||||
|
||||
return blk_read;
|
||||
}
|
||||
#endif /* CONFIG_ANDROID_BOOT_IMAGE_SEPARATE */
|
||||
|
||||
long android_image_load(struct blk_desc *dev_desc,
|
||||
const disk_partition_t *part_info,
|
||||
unsigned long load_address,
|
||||
|
|
@ -279,6 +361,7 @@ long android_image_load(struct blk_desc *dev_desc,
|
|||
u32 kload_addr;
|
||||
u32 blkcnt;
|
||||
struct andr_img_hdr *hdr;
|
||||
__maybe_unused uint8_t vboot_flag = 0;
|
||||
|
||||
if (max_size < part_info->blksz)
|
||||
return -1;
|
||||
|
|
@ -333,8 +416,43 @@ long android_image_load(struct blk_desc *dev_desc,
|
|||
} else {
|
||||
debug("Loading Android Image (%lu blocks) to 0x%lx... ",
|
||||
blk_cnt, load_address);
|
||||
blk_read = blk_dread(dev_desc, part_info->start,
|
||||
blk_cnt, buf);
|
||||
|
||||
#if defined(CONFIG_ANDROID_AVB) && defined(CONFIG_OPTEE_CLIENT)
|
||||
if (trusty_read_vbootkey_enable_flag(&vboot_flag))
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ANDROID_BOOT_IMAGE_SEPARATE
|
||||
if (!vboot_flag) {
|
||||
char *fdt_high = env_get("fdt_high");
|
||||
char *ramdisk_high = env_get("initrd_high");
|
||||
|
||||
blk_read =
|
||||
android_image_load_separate(dev_desc, hdr,
|
||||
part_info, buf);
|
||||
if (blk_read > 0) {
|
||||
if (!fdt_high) {
|
||||
env_set_hex("fdt_high", -1UL);
|
||||
printf("Fdt ");
|
||||
}
|
||||
if (!ramdisk_high) {
|
||||
env_set_hex("initrd_high", -1UL);
|
||||
printf("Ramdisk ");
|
||||
}
|
||||
if (!fdt_high || !ramdisk_high)
|
||||
printf("skip relocation\n");
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (!sysmem_alloc_base("android",
|
||||
(phys_addr_t)buf,
|
||||
blk_cnt * part_info->blksz))
|
||||
return -ENXIO;
|
||||
|
||||
blk_read = blk_dread(dev_desc, part_info->start,
|
||||
blk_cnt, buf);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -354,10 +472,16 @@ long android_image_load(struct blk_desc *dev_desc,
|
|||
free(hdr);
|
||||
unmap_sysmem(buf);
|
||||
|
||||
#ifndef CONFIG_ANDROID_BOOT_IMAGE_SEPARATE
|
||||
debug("%lu blocks read: %s\n",
|
||||
blk_read, (blk_read == blk_cnt) ? "OK" : "ERROR");
|
||||
if (blk_read != blk_cnt)
|
||||
return -1;
|
||||
#else
|
||||
debug("%lu blocks read\n", blk_read);
|
||||
if (blk_read < 0)
|
||||
return blk_read;
|
||||
#endif
|
||||
|
||||
return load_address;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue