common: android: add boot_img_hdr_v3 and vendor boot support
Android Header v3 and vendor boot partition are introduced
from Android-11(R).
Header populate:
Header v3 is no longer compatible with v0/1/2 header, we
add populate_andr_img_hdr() to merge boot and vendor_boot
partition header into struct andr_img_hdr in order to
compatible with v0/1/2 header.
resource.img:
The second_addr and second_size fields are removed in v3,
so we require resource partition to restore resource.img.
A/B system:
If not A/B system, the boot.img header version is 3 and
recovery header is version 2.
AVB load image:
- If allow verification error: the image is loaded by
ops->get_preloaded_partition() which auto populates
boot_img_hdr_v3.
- If not allow verification error: the image is full loaded
by ops->read_from_partition() which doesn't populate
boot_img_hdr_v3, we need to fix it.
Signed-off-by: Joseph Chen <chenjh@rock-chips.com>
Change-Id: I2afce53c43d782fc57baa01acf9c05518b580840
This commit is contained in:
parent
5a4b526e82
commit
745aeb1a7d
|
|
@ -273,27 +273,6 @@ static int read_logo_bmps(struct blk_desc *dev_desc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int read_dtb_from_android_v2(int rsce_base, int dtb_offset, int dtb_size)
|
||||
{
|
||||
if (!dtb_size)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* boot_img_hdr_v2 feature.
|
||||
*
|
||||
* If dtb position is present, replace the old with new one if
|
||||
* we don't need to verify DTB hash from resource.img file entry.
|
||||
*/
|
||||
#ifndef CONFIG_ROCKCHIP_DTB_VERIFY
|
||||
if (replace_resource_entry(DTB_FILE, rsce_base, dtb_offset, dtb_size))
|
||||
printf("Failed to load dtb from v2 dtb position\n");
|
||||
else
|
||||
#endif
|
||||
env_update("bootargs", "androidboot.dtb_idx=0");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int resource_create_ram_list(struct blk_desc *dev_desc, void *rsce_hdr)
|
||||
{
|
||||
struct resource_img_hdr *hdr = rsce_hdr;
|
||||
|
|
@ -385,81 +364,105 @@ err:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int read_dtb_from_android(struct blk_desc *dev_desc,
|
||||
struct andr_img_hdr *hdr,
|
||||
ulong rsce_base)
|
||||
{
|
||||
ulong dtb_offset = 0;
|
||||
ulong dtb_size = 0;
|
||||
|
||||
if (!hdr || hdr->header_version <= 1) {
|
||||
return 0;
|
||||
} else if (hdr->header_version == 2) {
|
||||
dtb_offset += hdr->page_size;
|
||||
dtb_offset += ALIGN(hdr->kernel_size, hdr->page_size);
|
||||
dtb_offset += ALIGN(hdr->ramdisk_size, hdr->page_size);
|
||||
dtb_offset += ALIGN(hdr->recovery_dtbo_size, hdr->page_size) +
|
||||
ALIGN(hdr->second_size, hdr->page_size);
|
||||
dtb_size = hdr->dtb_size;
|
||||
} else if (hdr->header_version == 3) {
|
||||
dtb_offset += ALIGN(VENDOR_BOOT_HDR_SIZE,
|
||||
hdr->vendor_page_size) +
|
||||
ALIGN(hdr->vendor_ramdisk_size,
|
||||
hdr->vendor_page_size);
|
||||
dtb_size = hdr->dtb_size;
|
||||
}
|
||||
|
||||
if (!dtb_size)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* boot_img_hdr_v2,3 feature.
|
||||
*
|
||||
* If dtb position is present, replace the old with new one if
|
||||
* we don't need to verify DTB hash from resource.img file entry.
|
||||
*/
|
||||
dtb_offset = DIV_ROUND_UP(dtb_offset, dev_desc->blksz);
|
||||
#ifndef CONFIG_ROCKCHIP_DTB_VERIFY
|
||||
if (replace_resource_entry(DTB_FILE, rsce_base, dtb_offset, dtb_size))
|
||||
printf("Failed to load dtb from v2 dtb position\n");
|
||||
else
|
||||
#endif
|
||||
env_update("bootargs", "androidboot.dtb_idx=0");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_resource_base_sector(struct blk_desc *dev_desc,
|
||||
disk_partition_t *from_part,
|
||||
int *dtb_off, int *dtb_size)
|
||||
struct andr_img_hdr **ret_hdr)
|
||||
{
|
||||
disk_partition_t part;
|
||||
int rsce_base;
|
||||
int rsce_base = 0;
|
||||
#ifdef CONFIG_ANDROID_BOOT_IMAGE
|
||||
struct andr_img_hdr *hdr;
|
||||
int blknum;
|
||||
u32 os_ver = 0, os_lvl;
|
||||
|
||||
/*
|
||||
* Anyway, we must read android hdr firstly from boot partition to get
|
||||
* the 'os_version' for android_bcb_msg_sector_offset(), in order to
|
||||
* confirm BCB message offset of misc partition.
|
||||
* confirm BCB message offset of *MISC* partition.
|
||||
*/
|
||||
if (part_get_info_by_name(dev_desc, PART_BOOT, &part) < 0)
|
||||
goto resource_part;
|
||||
|
||||
blknum = DIV_ROUND_UP(sizeof(*hdr), dev_desc->blksz);
|
||||
hdr = memalign(ARCH_DMA_MINALIGN, dev_desc->blksz * blknum);
|
||||
if (!hdr)
|
||||
return -ENOMEM;
|
||||
|
||||
if (blk_dread(dev_desc, part.start, blknum, hdr) != blknum) {
|
||||
printf("Failed to read %s hdr\n", part.name);
|
||||
free(hdr);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (!android_image_check_header(hdr)) {
|
||||
u32 os_ver, os_lvl;
|
||||
|
||||
hdr = populate_andr_img_hdr(dev_desc, &part);
|
||||
if (hdr) {
|
||||
os_ver = hdr->os_version >> 11;
|
||||
os_lvl = hdr->os_version & ((1U << 11) - 1);
|
||||
if (os_ver) {
|
||||
if (os_ver)
|
||||
gd->bd->bi_andr_version = hdr->os_version;
|
||||
printf("Android %u.%u, Build %u.%u\n",
|
||||
(os_ver >> 14) & 0x7F, (os_ver >> 7) & 0x7F,
|
||||
(os_lvl >> 4) + 2000, os_lvl & 0x0F);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_ANDROID_AB
|
||||
/* Get boot mode from misc and read if recovery mode */
|
||||
if (rockchip_get_boot_mode() == BOOT_MODE_RECOVERY) {
|
||||
if (hdr)
|
||||
free(hdr);
|
||||
|
||||
if (part_get_info_by_name(dev_desc, PART_RECOVERY, &part) < 0)
|
||||
goto resource_part;
|
||||
|
||||
if (blk_dread(dev_desc, part.start, blknum, hdr) != blknum) {
|
||||
printf("Failed to read %s hdr\n", part.name);
|
||||
free(hdr);
|
||||
return -EIO;
|
||||
}
|
||||
hdr = populate_andr_img_hdr(dev_desc, &part);
|
||||
if (!hdr)
|
||||
goto resource_part;
|
||||
}
|
||||
#endif
|
||||
/* get ! */
|
||||
if (!android_image_check_header(hdr)) {
|
||||
rsce_base = part.start * dev_desc->blksz;
|
||||
rsce_base += hdr->page_size;
|
||||
rsce_base += ALIGN(hdr->kernel_size, hdr->page_size);
|
||||
rsce_base += ALIGN(hdr->ramdisk_size, hdr->page_size);
|
||||
|
||||
if (hdr->header_version >= 2) {
|
||||
*dtb_size = hdr->dtb_size;
|
||||
*dtb_off =
|
||||
rsce_base +
|
||||
ALIGN(hdr->recovery_dtbo_size, hdr->page_size) +
|
||||
ALIGN(hdr->second_size, hdr->page_size);
|
||||
/* If Android v012, getting resource from second position ! */
|
||||
if (hdr) {
|
||||
if (os_ver)
|
||||
printf("Android %u.%u, Build %u.%u, v%d\n",
|
||||
(os_ver >> 14) & 0x7F, (os_ver >> 7) & 0x7F,
|
||||
(os_lvl >> 4) + 2000, os_lvl & 0x0F,
|
||||
hdr->header_version);
|
||||
*ret_hdr = hdr;
|
||||
if (hdr->header_version < 3) {
|
||||
rsce_base = part.start * dev_desc->blksz;
|
||||
rsce_base += hdr->page_size;
|
||||
rsce_base += ALIGN(hdr->kernel_size, hdr->page_size);
|
||||
rsce_base += ALIGN(hdr->ramdisk_size, hdr->page_size);
|
||||
rsce_base = DIV_ROUND_UP(rsce_base, dev_desc->blksz);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
rsce_base = DIV_ROUND_UP(rsce_base, dev_desc->blksz);
|
||||
*dtb_off = DIV_ROUND_UP(*dtb_off, dev_desc->blksz) - rsce_base;
|
||||
*from_part = part;
|
||||
free(hdr);
|
||||
goto finish;
|
||||
}
|
||||
resource_part:
|
||||
#endif
|
||||
|
|
@ -467,10 +470,9 @@ resource_part:
|
|||
if (part_get_info_by_name(dev_desc, PART_RESOURCE, &part) < 0) {
|
||||
printf("No resource partition\n");
|
||||
return -ENODEV;
|
||||
} else {
|
||||
rsce_base = part.start;
|
||||
}
|
||||
|
||||
*from_part = part;
|
||||
rsce_base = part.start;
|
||||
#ifdef CONFIG_ANDROID_BOOT_IMAGE
|
||||
finish:
|
||||
#endif
|
||||
|
|
@ -490,11 +492,9 @@ finish:
|
|||
*/
|
||||
static int init_resource_list(void)
|
||||
{
|
||||
struct andr_img_hdr *hdr = NULL;
|
||||
struct blk_desc *dev_desc;
|
||||
disk_partition_t part;
|
||||
int rsce_base;
|
||||
int dtb_offset;
|
||||
int dtb_size = 0;
|
||||
|
||||
dev_desc = rockchip_get_bootdev();
|
||||
if (!dev_desc) {
|
||||
|
|
@ -502,17 +502,14 @@ static int init_resource_list(void)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
rsce_base = get_resource_base_sector(dev_desc, &part,
|
||||
&dtb_offset, &dtb_size);
|
||||
rsce_base = get_resource_base_sector(dev_desc, &hdr);
|
||||
if (rsce_base > 0) {
|
||||
if (resource_create_list(dev_desc, rsce_base))
|
||||
printf("Failed to create resource list\n");
|
||||
}
|
||||
|
||||
/* override the old one if dtb_size != 0 */
|
||||
read_dtb_from_android_v2(rsce_base, dtb_offset, dtb_size);
|
||||
|
||||
return 0;
|
||||
/* override the resource dtb with android dtb if need */
|
||||
return read_dtb_from_android(dev_desc, hdr, rsce_base);
|
||||
}
|
||||
|
||||
static struct resource_file *get_file_info(const char *name)
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ static int do_android_print_hdr(cmd_tbl_t *cmdtp, int flag,
|
|||
struct andr_img_hdr *hdr;
|
||||
disk_partition_t part_info;
|
||||
const char *part_name;
|
||||
int blkcnt, ret;
|
||||
|
||||
if (argc != 2)
|
||||
return CMD_RET_USAGE;
|
||||
|
|
@ -31,31 +30,18 @@ static int do_android_print_hdr(cmd_tbl_t *cmdtp, int flag,
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = part_get_info_by_name(dev_desc, part_name, &part_info);
|
||||
if (ret < 0) {
|
||||
printf("Failed to get \"%s\" part, ret=%d\n", part_name, ret);
|
||||
if (part_get_info_by_name(dev_desc, part_name, &part_info) < 0) {
|
||||
printf("Failed to get \"%s\" part\n", part_name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
blkcnt = DIV_ROUND_UP(sizeof(*hdr), dev_desc->blksz);
|
||||
hdr = memalign(ARCH_DMA_MINALIGN, dev_desc->blksz * blkcnt);
|
||||
hdr = populate_andr_img_hdr(dev_desc, &part_info);
|
||||
if (!hdr) {
|
||||
printf("%s: out of memory!\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = blk_dread(dev_desc, part_info.start, blkcnt, hdr);
|
||||
if (ret != blkcnt) {
|
||||
printf("Failed to read %s sector, ret=%d\n", part_info.name, ret);
|
||||
free(hdr);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (!android_image_check_header(hdr)) {
|
||||
printf("Not an android image\n");
|
||||
return -EINVAL;
|
||||
} else {
|
||||
printf("Partition \"%s\"\n", part_info.name);
|
||||
android_print_contents(hdr);
|
||||
} else {
|
||||
printf("Not an android image\n");
|
||||
}
|
||||
|
||||
free(hdr);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#define ANDROID_PARTITION_BOOT "boot"
|
||||
#define ANDROID_PARTITION_VENDOR_BOOT "vendor_boot"
|
||||
#define ANDROID_PARTITION_MISC "misc"
|
||||
#define ANDROID_PARTITION_OEM "oem"
|
||||
#define ANDROID_PARTITION_RECOVERY "recovery"
|
||||
|
|
@ -790,8 +791,41 @@ 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;
|
||||
|
||||
/*
|
||||
* populate boot_img_hdr_v3
|
||||
*
|
||||
* If allow verification error: the image is loaded by
|
||||
* ops->get_preloaded_partition() which auto populates
|
||||
* boot_img_hdr_v3.
|
||||
*
|
||||
* If not allow verification error: the image is full loaded
|
||||
* by ops->read_from_partition() which doesn't populate
|
||||
* boot_img_hdr_v3, we need to fix it here.
|
||||
*/
|
||||
if (hdr->header_version >= 3 &&
|
||||
!(flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR)) {
|
||||
struct andr_img_hdr *v3hdr;
|
||||
struct blk_desc *dev_desc;
|
||||
disk_partition_t part;
|
||||
|
||||
dev_desc = rockchip_get_bootdev();
|
||||
if (!dev_desc)
|
||||
return -1;
|
||||
|
||||
if (part_get_info_by_name(dev_desc,
|
||||
boot_partname, &part) < 0)
|
||||
return -1;
|
||||
|
||||
v3hdr = populate_andr_img_hdr(dev_desc, &part);
|
||||
if (v3hdr) {
|
||||
memcpy(hdr, v3hdr, sizeof(*v3hdr));
|
||||
free(v3hdr);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reserve page_size */
|
||||
load_address -= hdr->page_size;
|
||||
if (android_image_memcpy_separate(hdr, &load_address)) {
|
||||
printf("Failed to separate copy android image\n");
|
||||
|
|
@ -948,7 +982,6 @@ int android_fdt_overlay_apply(void *fdt_addr)
|
|||
disk_partition_t part_info;
|
||||
char *part_dtbo;
|
||||
char buf[32] = {0};
|
||||
u32 blk_cnt;
|
||||
ulong fdt_dtbo = -1;
|
||||
int index = -1;
|
||||
int ret;
|
||||
|
|
@ -970,32 +1003,25 @@ int android_fdt_overlay_apply(void *fdt_addr)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
blk_cnt = DIV_ROUND_UP(sizeof(*hdr), part_info.blksz);
|
||||
hdr = memalign(ARCH_DMA_MINALIGN, part_info.blksz * blk_cnt);
|
||||
if (!hdr) {
|
||||
printf("%s: out of memory!\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = blk_dread(dev_desc, part_info.start, blk_cnt, hdr);
|
||||
if (ret != blk_cnt) {
|
||||
printf("%s: failed to read %s hdr!\n", __func__, part_boot);
|
||||
goto out;
|
||||
}
|
||||
|
||||
hdr = populate_andr_img_hdr(dev_desc, &part_info);
|
||||
if (!hdr)
|
||||
return -EINVAL;
|
||||
#ifdef DEBUG
|
||||
android_print_contents(hdr);
|
||||
#endif
|
||||
|
||||
if (android_image_check_header(hdr))
|
||||
return -EINVAL;
|
||||
|
||||
/* Check header version */
|
||||
if (!hdr->header_version) {
|
||||
printf("Android header version 0\n");
|
||||
ret = -EINVAL;
|
||||
/*
|
||||
* recovery_dtbo fields
|
||||
*
|
||||
* boot_img_hdr_v0: unsupported
|
||||
* boot_img_hdr_v1,2: supported
|
||||
* boot_img_hdr_v3 + boot.img: supported
|
||||
* boot_img_hdr_v3 + recovery.img: unsupported
|
||||
*/
|
||||
if ((hdr->header_version == 0) ||
|
||||
(hdr->header_version == 3 && !strcmp(part_boot, PART_RECOVERY)) ||
|
||||
(hdr->header_version > 3))
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = android_get_dtbo(&fdt_dtbo, (void *)hdr, &index, part_dtbo);
|
||||
if (!ret) {
|
||||
|
|
|
|||
|
|
@ -30,9 +30,10 @@ DECLARE_GLOBAL_DATA_PTR;
|
|||
#define ANDROID_IMAGE_DEFAULT_KERNEL_ADDR 0x10008000
|
||||
#define ANDROID_ARG_FDT_FILENAME "rk-kernel.dtb"
|
||||
#define ANDROID_Q_VER 10
|
||||
#define ANDROID_PARTITION_VENDOR_BOOT "vendor_boot"
|
||||
|
||||
/* Defined by rockchip legacy mkboot tool(SDK version < 8.1) */
|
||||
#define ANDROID_ROCKCHIP_LEGACY_PAGE_SIZE 0x4000
|
||||
#define BLK_CNT(_num_bytes, _block_size) \
|
||||
((_num_bytes + _block_size - 1) / _block_size)
|
||||
|
||||
static char andr_tmp_str[ANDR_BOOT_ARGS_SIZE + 1];
|
||||
static u32 android_kernel_comp_type = IH_COMP_NONE;
|
||||
|
|
@ -131,7 +132,8 @@ int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify,
|
|||
ulong *os_data, ulong *os_len)
|
||||
{
|
||||
u32 kernel_addr = android_image_get_kernel_addr(hdr);
|
||||
|
||||
const char *cmdline = hdr->header_version < 3 ?
|
||||
hdr->cmdline : hdr->total_cmdline;
|
||||
/*
|
||||
* 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
|
||||
|
|
@ -146,9 +148,9 @@ int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify,
|
|||
kernel_addr, DIV_ROUND_UP(hdr->kernel_size, 1024));
|
||||
|
||||
int len = 0;
|
||||
if (*hdr->cmdline) {
|
||||
debug("Kernel command line: %s\n", hdr->cmdline);
|
||||
len += strlen(hdr->cmdline);
|
||||
if (cmdline) {
|
||||
debug("Kernel command line: %s\n", cmdline);
|
||||
len += strlen(cmdline);
|
||||
}
|
||||
|
||||
char *bootargs = env_get("bootargs");
|
||||
|
|
@ -166,8 +168,8 @@ int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify,
|
|||
strcpy(newbootargs, bootargs);
|
||||
strcat(newbootargs, " ");
|
||||
}
|
||||
if (*hdr->cmdline)
|
||||
strcat(newbootargs, hdr->cmdline);
|
||||
if (cmdline)
|
||||
strcat(newbootargs, cmdline);
|
||||
|
||||
env_set("bootargs", newbootargs);
|
||||
|
||||
|
|
@ -193,16 +195,22 @@ ulong android_image_get_end(const struct andr_img_hdr *hdr)
|
|||
* on page boundary
|
||||
*/
|
||||
end = (ulong)hdr;
|
||||
end += hdr->page_size;
|
||||
end += ALIGN(hdr->kernel_size, hdr->page_size);
|
||||
end += ALIGN(hdr->ramdisk_size, hdr->page_size);
|
||||
end += ALIGN(hdr->second_size, hdr->page_size);
|
||||
|
||||
if (hdr->header_version >= 2) {
|
||||
end += ALIGN(hdr->recovery_dtbo_size, hdr->page_size);
|
||||
end += ALIGN(hdr->dtb_size, hdr->page_size);
|
||||
} else if (hdr->header_version >= 1) {
|
||||
end += ALIGN(hdr->recovery_dtbo_size, hdr->page_size);
|
||||
if (hdr->header_version < 3) {
|
||||
end += hdr->page_size;
|
||||
end += ALIGN(hdr->kernel_size, hdr->page_size);
|
||||
end += ALIGN(hdr->ramdisk_size, hdr->page_size);
|
||||
end += ALIGN(hdr->second_size, hdr->page_size);
|
||||
if (hdr->header_version == 1) {
|
||||
end += ALIGN(hdr->recovery_dtbo_size, hdr->page_size);
|
||||
} else if (hdr->header_version == 2) {
|
||||
end += ALIGN(hdr->recovery_dtbo_size, hdr->page_size);
|
||||
end += ALIGN(hdr->dtb_size, hdr->page_size);
|
||||
}
|
||||
} else {
|
||||
/* boot_img_hdr_v3 */
|
||||
end += hdr->page_size;
|
||||
end += ALIGN(hdr->kernel_size, hdr->page_size);
|
||||
end += ALIGN(hdr->ramdisk_size, hdr->page_size);
|
||||
}
|
||||
|
||||
return end;
|
||||
|
|
@ -293,6 +301,7 @@ typedef enum {
|
|||
IMG_RECOVERY_DTBO,
|
||||
IMG_RK_DTB, /* within resource.img in second position */
|
||||
IMG_DTB,
|
||||
IMG_VENDOR_RAMDISK,
|
||||
IMG_MAX,
|
||||
} img_t;
|
||||
|
||||
|
|
@ -301,11 +310,14 @@ static int image_load(img_t img, struct andr_img_hdr *hdr,
|
|||
struct udevice *crypto)
|
||||
{
|
||||
struct blk_desc *desc = rockchip_get_bootdev();
|
||||
disk_partition_t part_vendor_boot;
|
||||
__maybe_unused u32 sizesz;
|
||||
ulong pgsz = hdr->page_size;
|
||||
ulong blksz = desc->blksz;
|
||||
ulong blkcnt, blkoff;
|
||||
ulong orgdst = 0;
|
||||
ulong offset = 0;
|
||||
ulong extra = 0;
|
||||
ulong datasz;
|
||||
void *ramdst;
|
||||
int ret = 0;
|
||||
|
|
@ -321,15 +333,62 @@ static int image_load(img_t img, struct andr_img_hdr *hdr,
|
|||
(phys_addr_t)ramdst, blkcnt * blksz))
|
||||
return -ENOMEM;
|
||||
break;
|
||||
case IMG_VENDOR_RAMDISK:
|
||||
if (part_get_info_by_name(desc,
|
||||
ANDROID_PARTITION_VENDOR_BOOT,
|
||||
&part_vendor_boot) < 0) {
|
||||
printf("No vendor boot partition\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
/* Always load vendor boot from storage: avb full load boot/recovery */
|
||||
blkstart = part_vendor_boot.start;
|
||||
ram_base = 0;
|
||||
|
||||
pgsz = hdr->vendor_page_size;
|
||||
offset = ALIGN(VENDOR_BOOT_HDR_SIZE, pgsz);
|
||||
blkcnt = DIV_ROUND_UP(hdr->vendor_ramdisk_size, blksz);
|
||||
ramdst = (void *)env_get_ulong("ramdisk_addr_r", 16, 0);
|
||||
datasz = hdr->vendor_ramdisk_size;
|
||||
sizesz = sizeof(hdr->vendor_ramdisk_size);
|
||||
/*
|
||||
* Add extra memory for generic ramdisk space.
|
||||
*
|
||||
* In case of unaligned vendor ramdisk size, reserve
|
||||
* 1 more blksz.
|
||||
*/
|
||||
if (hdr->header_version == 3)
|
||||
extra = ALIGN(hdr->ramdisk_size, blksz) + blksz;
|
||||
if (datasz && !sysmem_alloc_base(MEM_RAMDISK,
|
||||
(phys_addr_t)ramdst, blkcnt * blksz + extra))
|
||||
return -ENOMEM;
|
||||
break;
|
||||
case IMG_RAMDISK:
|
||||
offset = pgsz + ALIGN(hdr->kernel_size, pgsz);
|
||||
blkcnt = DIV_ROUND_UP(hdr->ramdisk_size, blksz);
|
||||
ramdst = (void *)env_get_ulong("ramdisk_addr_r", 16, 0);
|
||||
/*
|
||||
* ramdisk_addr_r:
|
||||
* |----------------|---------|
|
||||
* | vendor-ramdisk | ramdisk |
|
||||
* |----------------|---------|
|
||||
*/
|
||||
if (hdr->header_version >= 3) {
|
||||
ramdst += hdr->vendor_ramdisk_size;
|
||||
if (!IS_ALIGNED((ulong)ramdst, blksz)) {
|
||||
orgdst = (ulong)ramdst;
|
||||
ramdst = (void *)ALIGN(orgdst, blksz);
|
||||
}
|
||||
}
|
||||
datasz = hdr->ramdisk_size;
|
||||
sizesz = sizeof(hdr->ramdisk_size);
|
||||
if (datasz && !sysmem_alloc_base(MEM_RAMDISK,
|
||||
/*
|
||||
* skip v3: sysmem has been alloced by vendor ramdisk.
|
||||
*/
|
||||
if (hdr->header_version < 3) {
|
||||
if (datasz && !sysmem_alloc_base(MEM_RAMDISK,
|
||||
(phys_addr_t)ramdst, blkcnt * blksz))
|
||||
return -ENOMEM;
|
||||
return -ENOMEM;
|
||||
}
|
||||
break;
|
||||
case IMG_SECOND:
|
||||
offset = pgsz +
|
||||
|
|
@ -393,6 +452,9 @@ static int image_load(img_t img, struct andr_img_hdr *hdr,
|
|||
}
|
||||
}
|
||||
|
||||
if (orgdst)
|
||||
memmove((char *)orgdst, ramdst, datasz);
|
||||
|
||||
crypto_calc:
|
||||
/* sha1 */
|
||||
#ifdef CONFIG_DM_CRYPTO
|
||||
|
|
@ -410,6 +472,9 @@ crypto_calc:
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* @ram_base: !NULL means require memcpy for an exist full android image.
|
||||
*/
|
||||
static int android_image_separate(struct andr_img_hdr *hdr,
|
||||
const disk_partition_t *part,
|
||||
void *load_address,
|
||||
|
|
@ -508,6 +573,48 @@ static int android_image_separate(struct andr_img_hdr *hdr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int android_image_separate_v3(struct andr_img_hdr *hdr,
|
||||
const disk_partition_t *part,
|
||||
void *load_address, void *ram_base)
|
||||
{
|
||||
ulong bstart;
|
||||
|
||||
if (android_image_check_header(hdr)) {
|
||||
printf("Bad android image header\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* set for image_load(IMG_KERNEL, ...) */
|
||||
env_set_hex("android_addr_r", (ulong)load_address);
|
||||
bstart = part ? part->start : 0;
|
||||
|
||||
/*
|
||||
* 1. Load images to their individual target ram position
|
||||
* in order to disable fdt/ramdisk relocation.
|
||||
*/
|
||||
if (image_load(IMG_RK_DTB, hdr, bstart, ram_base, NULL))
|
||||
return -1;
|
||||
if (image_load(IMG_KERNEL, hdr, bstart, ram_base, NULL))
|
||||
return -1;
|
||||
if (image_load(IMG_VENDOR_RAMDISK, hdr, bstart, ram_base, NULL))
|
||||
return -1;
|
||||
if (image_load(IMG_RAMDISK, hdr, bstart, ram_base, NULL))
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Copy the populated hdr to load address after image_load(IMG_KERNEL)
|
||||
*
|
||||
* The image_load(IMG_KERNEL) only reads boot_img_hdr_v3 while
|
||||
* vendor_boot_img_hdr_v3 is not included, so fix it here.
|
||||
*/
|
||||
memcpy((char *)load_address, hdr, hdr->page_size);
|
||||
|
||||
/* 2. Disable fdt/ramdisk relocation, it saves boot time */
|
||||
env_set("bootm-no-reloc", "y");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ulong android_image_get_comp_addr(struct andr_img_hdr *hdr, int comp)
|
||||
{
|
||||
ulong kernel_addr_c;
|
||||
|
|
@ -605,7 +712,10 @@ static int android_image_load_separate(struct andr_img_hdr *hdr,
|
|||
const disk_partition_t *part,
|
||||
void *load_addr)
|
||||
{
|
||||
return android_image_separate(hdr, part, load_addr, NULL);
|
||||
if (hdr->header_version < 3)
|
||||
return android_image_separate(hdr, part, load_addr, NULL);
|
||||
else
|
||||
return android_image_separate_v3(hdr, part, load_addr, NULL);
|
||||
}
|
||||
|
||||
int android_image_memcpy_separate(struct andr_img_hdr *hdr, ulong *load_addr)
|
||||
|
|
@ -617,8 +727,13 @@ int android_image_memcpy_separate(struct andr_img_hdr *hdr, ulong *load_addr)
|
|||
if (comp_addr == (ulong)hdr)
|
||||
return 0;
|
||||
|
||||
if (android_image_separate(hdr, NULL, (void *)comp_addr, hdr))
|
||||
return -1;
|
||||
if (hdr->header_version < 3) {
|
||||
if (android_image_separate(hdr, NULL, (void *)comp_addr, hdr))
|
||||
return -1;
|
||||
} else {
|
||||
if (android_image_separate_v3(hdr, NULL, (void *)comp_addr, hdr))
|
||||
return -1;
|
||||
}
|
||||
|
||||
*load_addr = comp_addr;
|
||||
android_image_set_decomp((void *)comp_addr, comp);
|
||||
|
|
@ -631,54 +746,45 @@ long android_image_load(struct blk_desc *dev_desc,
|
|||
unsigned long load_address,
|
||||
unsigned long max_size) {
|
||||
struct andr_img_hdr *hdr;
|
||||
u32 blksz = dev_desc->blksz;
|
||||
u32 pszcnt, hdrcnt, kercnt;
|
||||
int comp, ret;
|
||||
int blk_off;
|
||||
|
||||
if (max_size < part_info->blksz)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* read Android image header and leave enough space for page_size align
|
||||
* and kernel image header(1 block maybe enough).
|
||||
*
|
||||
* ANDROID_ROCKCHIP_LEGACY_PAGE_SIZE is defined by rockchip legacy
|
||||
* mkboot tool(SDK version < 8.1) and larger than Google defined.
|
||||
*
|
||||
* To compatible this, we malloc enough buffer but only read android
|
||||
* header and kernel image(1 block) from storage(ignore page size).
|
||||
*/
|
||||
kercnt = 1;
|
||||
hdrcnt = DIV_ROUND_UP(sizeof(*hdr), blksz);
|
||||
pszcnt = DIV_ROUND_UP(ANDROID_ROCKCHIP_LEGACY_PAGE_SIZE, blksz);
|
||||
|
||||
hdr = memalign(ARCH_DMA_MINALIGN, (hdrcnt + pszcnt + kercnt) * blksz);
|
||||
hdr = populate_andr_img_hdr(dev_desc, (disk_partition_t *)part_info);
|
||||
if (!hdr) {
|
||||
printf("No memory\n");
|
||||
printf("No valid android hdr\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (blk_dread(dev_desc, part_info->start, hdrcnt, hdr) != hdrcnt) {
|
||||
printf("Failed to read image header\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (android_image_check_header(hdr) != 0) {
|
||||
printf("** Invalid Android Image header **\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update and skip pszcnt(hdr is included) according to hdr->page_size,
|
||||
* reading kernel image for compress validation.
|
||||
* create the layout:
|
||||
*
|
||||
* |<- page_size ->|1-blk |
|
||||
* |-----|---------|------|-----|
|
||||
* | hdr | ... | kernel |
|
||||
* |-----|----- ---|------------|
|
||||
*
|
||||
* Alloc page_size and 1 more blk for reading kernel image to
|
||||
* get it's compression type, then fill the android hdr what
|
||||
* we have populated before.
|
||||
*
|
||||
* Why? see: android_image_get_kernel_addr().
|
||||
*/
|
||||
pszcnt = DIV_ROUND_UP(hdr->page_size, blksz);
|
||||
if (blk_dread(dev_desc, part_info->start + pszcnt, kercnt,
|
||||
(void *)((ulong)hdr + hdr->page_size)) != kercnt) {
|
||||
printf("Failed to read kernel header\n");
|
||||
goto fail;
|
||||
blk_off = BLK_CNT(hdr->page_size, dev_desc->blksz);
|
||||
hdr = (struct andr_img_hdr *)
|
||||
realloc(hdr, (blk_off + 1) * dev_desc->blksz);
|
||||
if (!hdr)
|
||||
return -1;
|
||||
|
||||
if (blk_dread(dev_desc, part_info->start + blk_off, 1,
|
||||
(char *)hdr + hdr->page_size) != 1) {
|
||||
free(hdr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Make kernel start address at load_address */
|
||||
load_address -= hdr->page_size;
|
||||
|
||||
/* Let's load kernel now ! */
|
||||
|
|
@ -700,6 +806,260 @@ fail:
|
|||
return -1;
|
||||
}
|
||||
|
||||
static struct andr_img_hdr *
|
||||
extract_boot_image_v012_header(struct blk_desc *dev_desc,
|
||||
const disk_partition_t *boot_img)
|
||||
{
|
||||
struct andr_img_hdr *hdr;
|
||||
long blk_cnt, blks_read;
|
||||
|
||||
blk_cnt = BLK_CNT(sizeof(struct andr_img_hdr), dev_desc->blksz);
|
||||
hdr = (struct andr_img_hdr *)malloc(blk_cnt * dev_desc->blksz);
|
||||
|
||||
if (!blk_cnt || !hdr)
|
||||
return NULL;
|
||||
|
||||
blks_read = blk_dread(dev_desc, boot_img->start, blk_cnt, hdr);
|
||||
if (blks_read != blk_cnt) {
|
||||
debug("boot img header blk cnt is %ld and blks read is %ld\n",
|
||||
blk_cnt, blks_read);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (android_image_check_header((void *)hdr)) {
|
||||
printf("boot header magic is invalid.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (hdr->page_size < sizeof(*hdr)) {
|
||||
printf("android hdr is over size\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return hdr;
|
||||
}
|
||||
|
||||
static struct boot_img_hdr_v3 *
|
||||
extract_boot_image_v3_header(struct blk_desc *dev_desc,
|
||||
const disk_partition_t *boot_img)
|
||||
{
|
||||
struct boot_img_hdr_v3 *boot_hdr;
|
||||
long blk_cnt, blks_read;
|
||||
|
||||
blk_cnt = BLK_CNT(sizeof(struct boot_img_hdr_v3), dev_desc->blksz);
|
||||
boot_hdr = (struct boot_img_hdr_v3 *)malloc(blk_cnt * dev_desc->blksz);
|
||||
|
||||
if (!blk_cnt || !boot_hdr)
|
||||
return NULL;
|
||||
|
||||
blks_read = blk_dread(dev_desc, boot_img->start, blk_cnt, boot_hdr);
|
||||
if (blks_read != blk_cnt) {
|
||||
debug("boot img header blk cnt is %ld and blks read is %ld\n",
|
||||
blk_cnt, blks_read);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (android_image_check_header((void *)boot_hdr)) {
|
||||
printf("boot header magic is invalid.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (boot_hdr->header_version != 3) {
|
||||
printf("boot header is not v3.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return boot_hdr;
|
||||
}
|
||||
|
||||
static struct vendor_boot_img_hdr_v3 *
|
||||
extract_vendor_boot_image_v3_header(struct blk_desc *dev_desc,
|
||||
const disk_partition_t *part_vendor_boot)
|
||||
{
|
||||
struct vendor_boot_img_hdr_v3 *vboot_hdr;
|
||||
long blk_cnt, blks_read;
|
||||
|
||||
blk_cnt = BLK_CNT(sizeof(struct vendor_boot_img_hdr_v3),
|
||||
part_vendor_boot->blksz);
|
||||
vboot_hdr = (struct vendor_boot_img_hdr_v3 *)
|
||||
malloc(blk_cnt * part_vendor_boot->blksz);
|
||||
|
||||
if (!blk_cnt || !vboot_hdr)
|
||||
return NULL;
|
||||
|
||||
blks_read = blk_dread(dev_desc, part_vendor_boot->start,
|
||||
blk_cnt, vboot_hdr);
|
||||
if (blks_read != blk_cnt) {
|
||||
debug("vboot img header blk cnt is %ld and blks read is %ld\n",
|
||||
blk_cnt, blks_read);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strncmp(VENDOR_BOOT_MAGIC, (void *)vboot_hdr->magic,
|
||||
VENDOR_BOOT_MAGIC_SIZE)) {
|
||||
printf("vendor boot header is invalid.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (vboot_hdr->header_version != 3) {
|
||||
printf("vendor boot header is not v3.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return vboot_hdr;
|
||||
}
|
||||
|
||||
static int populate_boot_info(const struct boot_img_hdr_v3 *boot_hdr,
|
||||
const struct vendor_boot_img_hdr_v3 *vendor_hdr,
|
||||
struct andr_img_hdr *hdr)
|
||||
{
|
||||
memset(hdr->magic, 0, ANDR_BOOT_MAGIC_SIZE);
|
||||
memcpy(hdr->magic, boot_hdr->magic, ANDR_BOOT_MAGIC_SIZE);
|
||||
|
||||
hdr->kernel_size = boot_hdr->kernel_size;
|
||||
/* don't use vendor_hdr->kernel_addr, we prefer "hdr + hdr->page_size" */
|
||||
hdr->kernel_addr = ANDROID_IMAGE_DEFAULT_KERNEL_ADDR;
|
||||
/* generic ramdisk: immediately following the vendor ramdisk */
|
||||
hdr->ramdisk_size = boot_hdr->ramdisk_size +
|
||||
vendor_hdr->vendor_ramdisk_size;
|
||||
/* actually, useless */
|
||||
hdr->ramdisk_addr = vendor_hdr->ramdisk_addr +
|
||||
vendor_hdr->vendor_ramdisk_size;
|
||||
/* removed in v3 */
|
||||
hdr->second_size = 0;
|
||||
hdr->second_addr = 0;
|
||||
|
||||
hdr->tags_addr = vendor_hdr->tags_addr;
|
||||
|
||||
/* fixed in v3 */
|
||||
hdr->page_size = 4096;
|
||||
hdr->header_version = boot_hdr->header_version;
|
||||
hdr->os_version = boot_hdr->os_version;
|
||||
|
||||
memset(hdr->name, 0, ANDR_BOOT_NAME_SIZE);
|
||||
strncpy(hdr->name, (const char *)vendor_hdr->name, ANDR_BOOT_NAME_SIZE);
|
||||
|
||||
/* removed in v3 */
|
||||
memset(hdr->cmdline, 0, ANDR_BOOT_ARGS_SIZE);
|
||||
memset(hdr->id, 0, 32);
|
||||
memset(hdr->extra_cmdline, 0, ANDR_BOOT_EXTRA_ARGS_SIZE);
|
||||
hdr->recovery_dtbo_size = 0;
|
||||
hdr->recovery_dtbo_offset = 0;
|
||||
|
||||
hdr->header_size = boot_hdr->header_size;
|
||||
hdr->dtb_size = vendor_hdr->dtb_size;
|
||||
hdr->dtb_addr = vendor_hdr->dtb_addr;
|
||||
|
||||
/* boot_img_hdr_v3 fields */
|
||||
hdr->vendor_ramdisk_size = vendor_hdr->vendor_ramdisk_size;
|
||||
hdr->vendor_page_size = vendor_hdr->page_size;
|
||||
hdr->vendor_header_version = vendor_hdr->header_version;
|
||||
hdr->vendor_header_size = vendor_hdr->header_size;
|
||||
|
||||
hdr->total_cmdline = calloc(1, TOTAL_BOOT_ARGS_SIZE);
|
||||
if (!hdr->total_cmdline)
|
||||
return -ENOMEM;
|
||||
strncpy(hdr->total_cmdline, (const char *)boot_hdr->cmdline,
|
||||
sizeof(boot_hdr->cmdline));
|
||||
strncat(hdr->total_cmdline, " ", 1);
|
||||
strncat(hdr->total_cmdline, (const char *)vendor_hdr->cmdline,
|
||||
sizeof(vendor_hdr->cmdline));
|
||||
|
||||
if (hdr->page_size < sizeof(*hdr)) {
|
||||
printf("android hdr is over size\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The possible cases of boot.img + recovery.img:
|
||||
*
|
||||
* [N]: 0, 1, 2
|
||||
* [M]: 0, 1, 2, 3
|
||||
*
|
||||
* |--------------------|---------------------|
|
||||
* | boot.img | recovery.img |
|
||||
* |--------------------|---------------------|
|
||||
* | boot_img_hdr_v[N] | boot_img_hdr_v[N] | <= if A/B is not required
|
||||
* |--------------------|---------------------|
|
||||
* | boot_img_hdr_v3 | boot_img_hdr_v2 | <= if A/B is not required
|
||||
* |------------------------------------------|
|
||||
* | boot_img_hdr_v[M], no recovery.img | <= if A/B is required
|
||||
* |------------------------------------------|
|
||||
*/
|
||||
struct andr_img_hdr *populate_andr_img_hdr(struct blk_desc *dev_desc,
|
||||
disk_partition_t *part_boot)
|
||||
{
|
||||
disk_partition_t part_vendor_boot;
|
||||
struct vendor_boot_img_hdr_v3 *vboot_hdr;
|
||||
struct boot_img_hdr_v3 *boot_hdr;
|
||||
struct andr_img_hdr *andr_hdr;
|
||||
int header_version;
|
||||
|
||||
if (!dev_desc || !part_boot)
|
||||
return NULL;
|
||||
|
||||
andr_hdr = (struct andr_img_hdr *)malloc(1 * dev_desc->blksz);
|
||||
if (!andr_hdr)
|
||||
return NULL;
|
||||
|
||||
if (blk_dread(dev_desc, part_boot->start, 1, andr_hdr) != 1) {
|
||||
free(andr_hdr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (android_image_check_header(andr_hdr)) {
|
||||
free(andr_hdr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
header_version = andr_hdr->header_version;
|
||||
free(andr_hdr);
|
||||
|
||||
if (header_version < 3) {
|
||||
return extract_boot_image_v012_header(dev_desc, part_boot);
|
||||
} else {
|
||||
if (part_get_info_by_name(dev_desc,
|
||||
ANDROID_PARTITION_VENDOR_BOOT,
|
||||
&part_vendor_boot) < 0) {
|
||||
printf("No vendor boot partition\n");
|
||||
return NULL;
|
||||
}
|
||||
boot_hdr = extract_boot_image_v3_header(dev_desc, part_boot);
|
||||
vboot_hdr = extract_vendor_boot_image_v3_header(dev_desc,
|
||||
&part_vendor_boot);
|
||||
if (!boot_hdr || !vboot_hdr)
|
||||
goto image_load_exit;
|
||||
|
||||
andr_hdr = (struct andr_img_hdr *)
|
||||
malloc(sizeof(struct andr_img_hdr));
|
||||
if (!andr_hdr) {
|
||||
printf("No memory for andr hdr\n");
|
||||
goto image_load_exit;
|
||||
}
|
||||
|
||||
if (populate_boot_info(boot_hdr, vboot_hdr, andr_hdr)) {
|
||||
printf("populate boot info failed\n");
|
||||
goto image_load_exit;
|
||||
}
|
||||
|
||||
free(boot_hdr);
|
||||
free(vboot_hdr);
|
||||
|
||||
return andr_hdr;
|
||||
|
||||
image_load_exit:
|
||||
free(boot_hdr);
|
||||
free(vboot_hdr);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_SPL_BUILD)
|
||||
/**
|
||||
* android_print_contents - prints out the contents of the Android format image
|
||||
|
|
@ -723,7 +1083,7 @@ void android_print_contents(const struct andr_img_hdr *hdr)
|
|||
printf("%skernel size: %x\n", p, hdr->kernel_size);
|
||||
printf("%skernel address: %x\n", p, hdr->kernel_addr);
|
||||
printf("%sramdisk size: %x\n", p, hdr->ramdisk_size);
|
||||
printf("%sramdisk addrress: %x\n", p, hdr->ramdisk_addr);
|
||||
printf("%sramdisk address: %x\n", p, hdr->ramdisk_addr);
|
||||
printf("%ssecond size: %x\n", p, hdr->second_size);
|
||||
printf("%ssecond address: %x\n", p, hdr->second_addr);
|
||||
printf("%stags address: %x\n", p, hdr->tags_addr);
|
||||
|
|
@ -738,15 +1098,23 @@ void android_print_contents(const struct andr_img_hdr *hdr)
|
|||
printf("%sname: %s\n", p, hdr->name);
|
||||
printf("%scmdline: %s\n", p, hdr->cmdline);
|
||||
|
||||
if (header_version >= 1) {
|
||||
if (header_version == 1 || header_version == 2) {
|
||||
printf("%srecovery dtbo size: %x\n", p, hdr->recovery_dtbo_size);
|
||||
printf("%srecovery dtbo offset: %llx\n", p, hdr->recovery_dtbo_offset);
|
||||
printf("%sheader size: %x\n", p, hdr->header_size);
|
||||
}
|
||||
|
||||
if (header_version >= 2) {
|
||||
if (header_version == 2 || header_version == 3) {
|
||||
printf("%sdtb size: %x\n", p, hdr->dtb_size);
|
||||
printf("%sdtb addr: %llx\n", p, hdr->dtb_addr);
|
||||
}
|
||||
|
||||
if (header_version == 3) {
|
||||
printf("%scmdline: %s\n", p, hdr->total_cmdline);
|
||||
printf("%svendor ramdisk size: %x\n", p, hdr->vendor_ramdisk_size);
|
||||
printf("%svendor page size: %x\n", p, hdr->vendor_page_size);
|
||||
printf("%svendor header version: %d\n", p, hdr->vendor_header_version);
|
||||
printf("%svendor header size: %x\n", p, hdr->vendor_header_size);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -12,10 +12,19 @@
|
|||
#define _ANDROID_IMAGE_H_
|
||||
|
||||
#define ANDR_BOOT_MAGIC "ANDROID!"
|
||||
#define VENDOR_BOOT_MAGIC "VNDRBOOT"
|
||||
#define ANDR_BOOT_MAGIC_SIZE 8
|
||||
#define VENDOR_BOOT_MAGIC_SIZE 8
|
||||
#define ANDR_BOOT_NAME_SIZE 16
|
||||
#define VENDOR_BOOT_NAME_SIZE 16
|
||||
#define ANDR_BOOT_ARGS_SIZE 512
|
||||
#define ANDR_BOOT_EXTRA_ARGS_SIZE 1024
|
||||
#define VENDOR_BOOT_ARGS_SIZE 2048
|
||||
#define ANDR_BOOT_IMG_PAGE_SIZE 4096
|
||||
#define ANDR_BOOT_IMG_HDR_SIZE (ANDR_BOOT_IMG_PAGE_SIZE)
|
||||
#define TOTAL_BOOT_ARGS_SIZE (ANDR_BOOT_ARGS_SIZE + ANDR_BOOT_EXTRA_ARGS_SIZE + \
|
||||
VENDOR_BOOT_ARGS_SIZE + 1)
|
||||
#define VENDOR_BOOT_HDR_SIZE 2112
|
||||
|
||||
/*
|
||||
* It is expected that callers would explicitly specify which version of the
|
||||
|
|
@ -60,14 +69,78 @@ struct andr_img_hdr {
|
|||
* binary compatibility with older versions of mkbootimg. */
|
||||
char extra_cmdline[ANDR_BOOT_EXTRA_ARGS_SIZE];
|
||||
|
||||
/* Fields in boot_img_hdr_v1 and newer. */
|
||||
/* Fields in boot_img_hdr_v1(Android-9) and newer. */
|
||||
u32 recovery_dtbo_size; /* size in bytes for recovery DTBO/ACPIO image */
|
||||
u64 recovery_dtbo_offset; /* offset to recovery dtbo/acpio in boot image */
|
||||
u32 header_size;
|
||||
|
||||
/* Fields in boot_img_hdr_v2 and newer. */
|
||||
/* Fields in boot_img_hdr_v2(Android-10) and newer. */
|
||||
u32 dtb_size; /* size in bytes for DTB image */
|
||||
u64 dtb_addr; /* physical load address for DTB image */
|
||||
|
||||
/*
|
||||
* [Rockchip compatibility]
|
||||
*
|
||||
* boot_img_hdr_v3(Android-11) is not compatible with boot_img_hdr_v012,
|
||||
* we have to partly merge fields from boot_img_hdr_v3 and vendor_boot_img_hdr_v3
|
||||
* into this structure to compatible with boot_img_hdr_v012.
|
||||
*/
|
||||
u32 vendor_ramdisk_size; /* size in bytes */
|
||||
u32 vendor_page_size;
|
||||
u32 vendor_header_version;
|
||||
u32 vendor_header_size;
|
||||
/*
|
||||
* Don't define 'char total_cmdline[TOTAL_BOOT_ARGS_SIZE]' to avoid
|
||||
* this structrue is over size than page_size.
|
||||
*/
|
||||
char *total_cmdline;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct boot_img_hdr_v3 {
|
||||
/* Must be ANDR_BOOT_MAGIC. */
|
||||
uint8_t magic[ANDR_BOOT_MAGIC_SIZE];
|
||||
|
||||
uint32_t kernel_size; /* size in bytes */
|
||||
uint32_t ramdisk_size; /* size in bytes */
|
||||
|
||||
/* Operating system version and security patch level.
|
||||
* For version "A.B.C" and patch level "Y-M-D":
|
||||
* (7 bits for each of A, B, C; 7 bits for (Y-2000), 4 bits for M)
|
||||
* os_version = A[31:25] B[24:18] C[17:11] (Y-2000)[10:4] M[3:0] */
|
||||
uint32_t os_version;
|
||||
|
||||
uint32_t header_size;
|
||||
|
||||
uint32_t reserved[4];
|
||||
|
||||
uint32_t header_version;
|
||||
|
||||
uint8_t cmdline[ANDR_BOOT_ARGS_SIZE + ANDR_BOOT_EXTRA_ARGS_SIZE];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct vendor_boot_img_hdr_v3 {
|
||||
/* Must be VENDOR_BOOT_MAGIC. */
|
||||
uint8_t magic[VENDOR_BOOT_MAGIC_SIZE];
|
||||
|
||||
/* Version of the vendor boot image header. */
|
||||
uint32_t header_version;
|
||||
|
||||
uint32_t page_size; /* flash page size we assume */
|
||||
|
||||
uint32_t kernel_addr; /* physical load addr */
|
||||
uint32_t ramdisk_addr; /* physical load addr */
|
||||
|
||||
uint32_t vendor_ramdisk_size; /* size in bytes */
|
||||
|
||||
uint8_t cmdline[VENDOR_BOOT_ARGS_SIZE];
|
||||
|
||||
uint32_t tags_addr; /* physical addr for kernel tags (if required) */
|
||||
uint8_t name[VENDOR_BOOT_NAME_SIZE]; /* asciiz product name */
|
||||
|
||||
uint32_t header_size;
|
||||
|
||||
uint32_t dtb_size; /* size in bytes for DTB image */
|
||||
uint64_t dtb_addr; /* physical load address for DTB image */
|
||||
} __attribute__((packed));
|
||||
|
||||
/* When a boot header is of version 0, the structure of boot image is as
|
||||
|
|
@ -139,4 +212,50 @@ struct andr_img_hdr {
|
|||
* else: jump to kernel_addr
|
||||
*/
|
||||
|
||||
/* When the boot image header has a version of 3, the structure of the boot
|
||||
* image is as follows:
|
||||
*
|
||||
* +---------------------+
|
||||
* | boot header | 4096 bytes
|
||||
* +---------------------+
|
||||
* | kernel | m pages
|
||||
* +---------------------+
|
||||
* | ramdisk | n pages
|
||||
* +---------------------+
|
||||
*
|
||||
* m = (kernel_size + 4096 - 1) / 4096
|
||||
* n = (ramdisk_size + 4096 - 1) / 4096
|
||||
*
|
||||
* Note that in version 3 of the boot image header, page size is fixed at 4096 bytes.
|
||||
*
|
||||
* The structure of the vendor boot image (introduced with version 3 and
|
||||
* required to be present when a v3 boot image is used) is as follows:
|
||||
*
|
||||
* +---------------------+
|
||||
* | vendor boot header | o pages
|
||||
* +---------------------+
|
||||
* | vendor ramdisk | p pages
|
||||
* +---------------------+
|
||||
* | dtb | q pages
|
||||
* +---------------------+
|
||||
*
|
||||
* o = (2112 + page_size - 1) / page_size
|
||||
* p = (vendor_ramdisk_size + page_size - 1) / page_size
|
||||
* q = (dtb_size + page_size - 1) / page_size
|
||||
*
|
||||
* 0. all entities in the boot image are 4096-byte aligned in flash, all
|
||||
* entities in the vendor boot image are page_size (determined by the vendor
|
||||
* and specified in the vendor boot image header) aligned in flash
|
||||
* 1. kernel, ramdisk, vendor ramdisk, and DTB are required (size != 0)
|
||||
* 2. load the kernel and DTB at the specified physical address (kernel_addr,
|
||||
* dtb_addr)
|
||||
* 3. load the vendor ramdisk at ramdisk_addr
|
||||
* 4. load the generic ramdisk immediately following the vendor ramdisk in
|
||||
* memory
|
||||
* 5. set up registers for kernel entry as required by your architecture
|
||||
* 6. if the platform has a second stage bootloader jump to it (must be
|
||||
* contained outside boot and vendor boot partitions), otherwise
|
||||
* jump to kernel_addr
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ struct rockchip_image {
|
|||
#define PART_RESOURCE "resource"
|
||||
#define PART_KERNEL "kernel"
|
||||
#define PART_BOOT "boot"
|
||||
#define PART_VENDOR_BOOT "vendor_boot"
|
||||
#define PART_RECOVERY "recovery"
|
||||
#define PART_DTBO "dtbo"
|
||||
#define PART_LOGO "logo"
|
||||
|
|
|
|||
|
|
@ -1365,6 +1365,9 @@ void android_image_set_decomp(struct andr_img_hdr *hdr, int comp);
|
|||
int android_image_parse_comp(struct andr_img_hdr *hdr, ulong *load_addr);
|
||||
int android_image_memcpy_separate(struct andr_img_hdr *hdr, ulong *load_address);
|
||||
|
||||
struct andr_img_hdr *populate_andr_img_hdr(struct blk_desc *dev_desc,
|
||||
disk_partition_t *part_boot);
|
||||
|
||||
/** android_image_load - Load an Android Image from storage.
|
||||
*
|
||||
* Load an Android Image based on the header size in the storage.
|
||||
|
|
|
|||
Loading…
Reference in New Issue