android: support boot images packed with rockchip android hdr

For some legacy reasons, rockchip use mkbootimg tool to pack android
images with special pack parameters(SDK version lower than 8.1) to
assign kernel/ramdisk/seconds address and page size.

Android hdr on RK3399 SDK-7.1:
   kernel size:      1299808
   kernel address:   60408000
   ramdisk size:     1e6b80
   ramdisk addrress: 62000000
   second size:      41c00
   second address:   60f00000
   tags address:     60088000
   page size:        4000
   header_version:   0
   os_version:       e041114 (ver: 1.7.2, level: 2017.4)
   name:
   cmdline:          buildvariant=userdebug

The kernel/ramdisk/seconds address base is not from 0x10000000 and
page size is not 0x800!

This patch makes bootflow to compatible with above legacy packing.

Change-Id: I663a0d1386694658c97586706ff21ed887d6a2e7
Signed-off-by: Joseph Chen <chenjh@rock-chips.com>
This commit is contained in:
Joseph Chen 2018-10-22 20:20:21 +08:00 committed by Kever Yang
parent ab70714e5a
commit ee465021fe
3 changed files with 61 additions and 24 deletions

View File

@ -48,7 +48,7 @@ static int do_boot_android(cmd_tbl_t *cmdtp, int flag, int argc,
*/
load_address &= ~0x7ffff;
#endif
load_address -= 0x800; /* default page size for boot header */
dev_desc = blk_get_dev(argv[1], simple_strtoul(argv[2], NULL, 16));
if (!dev_desc) {
printf("Could not get %s %s\n", argv[1], argv[2]);

View File

@ -424,7 +424,7 @@ static void slot_set_unbootable(AvbABSlotData* slot)
}
static AvbSlotVerifyResult android_slot_verify(char *boot_partname,
unsigned long load_address,
unsigned long *android_load_address,
char *slot_suffix)
{
const char *requested_partitions[1] = {NULL};
@ -437,6 +437,8 @@ static AvbSlotVerifyResult android_slot_verify(char *boot_partname,
size_t slot_index_to_boot = 0;
char verify_state[38] = {0};
char can_boot = 1;
unsigned long load_address = *android_load_address;
struct andr_img_hdr *hdr;
requested_partitions[0] = boot_partname;
ops = avb_ops_user_new();
@ -539,6 +541,11 @@ static AvbSlotVerifyResult android_slot_verify(char *boot_partname,
strcat(newbootargs, slot_data[0]->cmdline);
env_set("bootargs", newbootargs);
/* Reserve page_size */
hdr = (void *)slot_data[0]->loaded_partitions->data;
load_address -= hdr->page_size;
*android_load_address = load_address;
memcpy((uint8_t *)load_address,
slot_data[0]->loaded_partitions->data,
slot_data[0]->loaded_partitions->data_size);
@ -878,7 +885,7 @@ int android_bootloader_boot_flow(struct blk_desc *dev_desc,
}
#ifdef CONFIG_ANDROID_AVB
if (android_slot_verify(boot_partname, load_address, slot_suffix))
if (android_slot_verify(boot_partname, &load_address, slot_suffix))
return -1;
#else
/*

View File

@ -38,7 +38,25 @@ static ulong android_image_get_kernel_addr(const struct andr_img_hdr *hdr)
if (hdr->kernel_addr == ANDROID_IMAGE_DEFAULT_KERNEL_ADDR)
return (ulong)hdr + hdr->page_size;
#ifdef CONFIG_ARCH_ROCKCHIP
/*
* If kernel is compressed, kernel_addr is set as decompressed address
* after compressed being loaded to ram, so let's use it.
*/
if (android_kernel_comp_type != IH_COMP_NONE &&
android_kernel_comp_type != IH_COMP_ZIMAGE)
return hdr->kernel_addr;
/*
* Compatble with rockchip legacy packing with kernel/ramdisk/second
* address base from 0x60000000(SDK versiont < 8.1), these are invalid
* address, so we calc it by real size.
*/
return (ulong)hdr + hdr->page_size;
#else
return hdr->kernel_addr;
#endif
}
void android_image_set_comp(struct andr_img_hdr *hdr, u32 comp)
@ -172,14 +190,14 @@ int android_image_get_ramdisk(const struct andr_img_hdr *hdr,
return -1;
}
printf("RAM disk load addr 0x%08x size %u KiB\n",
hdr->ramdisk_addr, DIV_ROUND_UP(hdr->ramdisk_size, 1024));
*rd_data = (unsigned long)hdr;
*rd_data += hdr->page_size;
*rd_data += ALIGN(hdr->kernel_size, hdr->page_size);
*rd_len = hdr->ramdisk_size;
printf("RAM disk load addr 0x%08lx size %u KiB\n",
*rd_data, DIV_ROUND_UP(hdr->ramdisk_size, 1024));
return 0;
}
@ -253,37 +271,48 @@ long android_image_load(struct blk_desc *dev_desc,
long blk_read = 0;
u32 comp;
u32 kload_addr;
u32 blkcnt;
struct andr_img_hdr *hdr;
if (max_size < part_info->blksz)
return -1;
/*
* Read the Android boot.img header and a few parts of
* the head of kernel image.
*/
blkcnt = DIV_ROUND_UP(sizeof(*hdr), 512);
hdr = memalign(ARCH_DMA_MINALIGN, blkcnt * 512);
if (!hdr) {
printf("%s: no memory\n", __func__);
return -1;
}
if (blk_dread(dev_desc, part_info->start, blkcnt, hdr) != blkcnt)
blk_read = -1;
if (!blk_read && android_image_check_header(hdr) != 0) {
printf("** Invalid Android Image header **\n");
blk_read = -1;
}
/* page_size for image header */
load_address -= hdr->page_size;
/* We don't know the size of the Android image before reading the header
* so we don't limit the size of the mapped memory.
*/
buf = map_sysmem(load_address, 0 /* size */);
/* Read the Android boot.img header and a few parts of
* the head of kernel image.
*/
if (blk_dread(dev_desc, part_info->start, 8, buf) != 8)
blk_read = -1;
if (!blk_read && android_image_check_header(buf) != 0) {
printf("** Invalid Android Image header **\n");
blk_read = -1;
}
if (!blk_read) {
blk_cnt = (android_image_get_end(buf) - (ulong)buf +
blk_cnt = (android_image_get_end(hdr) - (ulong)hdr +
part_info->blksz - 1) / part_info->blksz;
comp = android_image_parse_kernel_comp(buf);
comp = android_image_parse_kernel_comp(hdr);
/*
* We should load a compressed kernel Image
* to high memory
*/
if (comp != IH_COMP_NONE) {
load_address += android_image_get_ksize(buf) * 3;
load_address += android_image_get_ksize(hdr) * 3;
load_address = env_get_ulong("kernel_addr_c", 16, load_address);
unmap_sysmem(buf);
buf = map_sysmem(load_address, 0 /* size */);
@ -291,7 +320,7 @@ long android_image_load(struct blk_desc *dev_desc,
if (blk_cnt * part_info->blksz > max_size) {
debug("Android Image too big (%lu bytes, max %lu)\n",
android_image_get_end(buf) - (ulong)buf,
android_image_get_end(hdr) - (ulong)hdr,
max_size);
blk_read = -1;
} else {
@ -315,6 +344,7 @@ long android_image_load(struct blk_desc *dev_desc,
}
free(hdr);
unmap_sysmem(buf);
debug("%lu blocks read: %s\n",