#include <mmc.h>
#define ANDROID_IMAGE_DEFAULT_KERNEL_ADDR 0x10008000
+#define COMMANDLINE_LENGTH 2048
static char andr_tmp_str[ANDR_BOOT_ARGS_SIZE + 1];
return hdr->kernel_addr;
}
-/**
- * android_image_get_kernel() - processes kernel part of Android boot images
- * @hdr: Pointer to image header, which is at the start
- * of the image.
- * @verify: Checksum verification flag. Currently unimplemented.
- * @os_data: Pointer to a ulong variable, will hold os data start
- * address.
- * @os_len: Pointer to a ulong variable, will hold os data length.
- *
- * This function returns the os image's start address and length. Also,
- * it appends the kernel command line to the bootargs env variable.
- *
- * Return: Zero, os start address and length on success,
- * otherwise on failure.
- */
-int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify,
- ulong *os_data, ulong *os_len)
+static void append_kernel_cmdline(char *commandline)
{
- extern boot_metric metrics;
- u32 kernel_addr = android_image_get_kernel_addr(hdr);
- const struct image_header *ihdr = (const struct image_header *)
- ((uintptr_t)hdr + hdr->page_size);
-
- /*
- * 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",
- kernel_addr, DIV_ROUND_UP(hdr->kernel_size, 1024));
-
char newbootargs[512] = {0};
- char commandline[2048] = {0};
- int offset;
- char *bootargs = env_get("bootargs");
-
- if (bootargs) {
- if (strlen(bootargs) + 1 > sizeof(commandline)) {
- printf("bootargs is too long!\n");
- return -1;
- }
- else
- strncpy(commandline, bootargs, sizeof(commandline) - 1);
- } else {
- offset = fdt_path_offset(gd->fdt_blob, "/chosen");
- if (offset > 0) {
- bootargs = (char *)fdt_getprop(gd->fdt_blob, offset,
- "bootargs", NULL);
- if (bootargs)
- sprintf(commandline, "%s ", bootargs);
- }
-
- if (*hdr->cmdline) {
- if (strlen(hdr->cmdline) + 1 >
- sizeof(commandline) - strlen(commandline)) {
- printf("cmdline in bootimg is too long!\n");
- return -1;
- }
- else
- strncat(commandline, hdr->cmdline, sizeof(commandline) - strlen(commandline));
- }
- }
+ extern boot_metric metrics;
/* Add 'bootargs_ram_capacity' to hold the parameters based on different ram capacity */
char *bootargs_ram_capacity = env_get("bootargs_ram_capacity");
if (bootargs_ram_capacity) {
- strncat(commandline, " ", sizeof(commandline) - strlen(commandline));
+ strncat(commandline, " ", COMMANDLINE_LENGTH - strlen(commandline));
strncat(commandline, bootargs_ram_capacity,
- sizeof(commandline) - strlen(commandline));
+ COMMANDLINE_LENGTH - strlen(commandline));
}
#ifdef CONFIG_SERIAL_TAG
" androidboot.serialno=%08x%08x",
serialnr.high,
serialnr.low);
- strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline));
+ strncat(commandline, newbootargs, COMMANDLINE_LENGTH - strlen(commandline));
if (serialnr.high + serialnr.low != 0) {
char bd_addr[16]={0};
" androidboot.btmacaddr=%c%c:%c%c:%c%c:%c%c:%c%c:%c%c",
bd_addr[0],bd_addr[1],bd_addr[2],bd_addr[3],bd_addr[4],bd_addr[5],
bd_addr[6],bd_addr[7],bd_addr[8],bd_addr[9],bd_addr[10],bd_addr[11]);
- strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline));
+ strncat(commandline, newbootargs, COMMANDLINE_LENGTH - strlen(commandline));
}
#endif
sprintf(newbootargs,
" androidboot.soc_type=%s",
soc_type);
- strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline));
+ strncat(commandline, newbootargs, COMMANDLINE_LENGTH - strlen(commandline));
}
sprintf(newbootargs,
" androidboot.boot_device_root=mmcblk%d", mmc_map_to_kernel_blk(mmc_get_env_dev()));
- strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline));
+ strncat(commandline, newbootargs, COMMANDLINE_LENGTH - strlen(commandline));
/* boot metric variables */
metrics.ble_1 = get_timer(0);
" androidboot.boottime=1BLL:%d,1BLE:%d,KL:%d,KD:%d,AVB:%d,ODT:%d,SW:%d",
metrics.bll_1, metrics.ble_1, metrics.kl, metrics.kd, metrics.avb,
metrics.odt, metrics.sw);
- strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline));
+ strncat(commandline, newbootargs, COMMANDLINE_LENGTH - strlen(commandline));
#if defined(CONFIG_ARCH_MX6) || defined(CONFIG_ARCH_MX7) || \
defined(CONFIG_ARCH_MX7ULP) || defined(CONFIG_ARCH_IMX8M)
#else
sprintf(newbootargs," androidboot.bootreason=reboot");
#endif
- strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline));
+ strncat(commandline, newbootargs, COMMANDLINE_LENGTH - strlen(commandline));
#ifdef CONFIG_AVB_SUPPORT
/* secondary cmdline added by avb */
char *bootargs_sec = env_get("bootargs_sec");
if (bootargs_sec) {
- strncat(commandline, " ", sizeof(commandline) - strlen(commandline));
- strncat(commandline, bootargs_sec, sizeof(commandline) - strlen(commandline));
+ strncat(commandline, " ", COMMANDLINE_LENGTH - strlen(commandline));
+ strncat(commandline, bootargs_sec, COMMANDLINE_LENGTH - strlen(commandline));
}
#endif
#ifdef CONFIG_SYSTEM_RAMDISK_SUPPORT
*/
char *bootargs_3rd = env_get("bootargs_3rd");
if (bootargs_3rd) {
- strncat(commandline, " ", sizeof(commandline) - strlen(commandline));
- strncat(commandline, bootargs_3rd, sizeof(commandline) - strlen(commandline));
+ strncat(commandline, " ", COMMANDLINE_LENGTH - strlen(commandline));
+ strncat(commandline, bootargs_3rd, COMMANDLINE_LENGTH - strlen(commandline));
}
#endif
*/
#if defined(CONFIG_ANDROID_SUPPORT) || defined(CONFIG_ANDROID_AUTO_SUPPORT)
sprintf(newbootargs," androidboot.dtbo_idx=0");
- strncat(commandline, newbootargs, sizeof(commandline) - strlen(commandline));
+ strncat(commandline, newbootargs, COMMANDLINE_LENGTH - strlen(commandline));
#endif
char *keystore = env_get("keystore");
if ((keystore == NULL) || strncmp(keystore, "trusty", sizeof("trusty"))) {
char *bootargs_trusty = "androidboot.keystore=software";
- strncat(commandline, " ", sizeof(commandline) - strlen(commandline));
- strncat(commandline, bootargs_trusty, sizeof(commandline) - strlen(commandline));
+ strncat(commandline, " ", COMMANDLINE_LENGTH - strlen(commandline));
+ strncat(commandline, bootargs_trusty, COMMANDLINE_LENGTH - strlen(commandline));
} else {
char *bootargs_trusty = "androidboot.keystore=trusty";
- strncat(commandline, " ", sizeof(commandline) - strlen(commandline));
- strncat(commandline, bootargs_trusty, sizeof(commandline) - strlen(commandline));
+ strncat(commandline, " ", COMMANDLINE_LENGTH - strlen(commandline));
+ strncat(commandline, bootargs_trusty, COMMANDLINE_LENGTH - strlen(commandline));
}
#ifdef CONFIG_APPEND_BOOTARGS
char *append_bootargs = env_get("append_bootargs");
if (append_bootargs) {
if (strlen(append_bootargs) + 2 >
- (sizeof(commandline) - strlen(commandline))) {
+ (COMMANDLINE_LENGTH - strlen(commandline))) {
printf("The 'append_bootargs' is too long to be appended to bootargs\n");
} else {
- strncat(commandline, " ", sizeof(commandline) - strlen(commandline));
- strncat(commandline, append_bootargs, sizeof(commandline) - strlen(commandline));
+ strncat(commandline, " ", COMMANDLINE_LENGTH - strlen(commandline));
+ strncat(commandline, append_bootargs, COMMANDLINE_LENGTH - strlen(commandline));
}
}
#endif
+}
+
+/**
+ * android_image_get_kernel() - processes kernel part of Android boot images
+ * @hdr: Pointer to image header, which is at the start
+ * of the image.
+ * @verify: Checksum verification flag. Currently unimplemented.
+ * @os_data: Pointer to a ulong variable, will hold os data start
+ * address.
+ * @os_len: Pointer to a ulong variable, will hold os data length.
+ *
+ * This function returns the os image's start address and length. Also,
+ * it appends the kernel command line to the bootargs env variable.
+ *
+ * Return: Zero, os start address and length on success,
+ * otherwise on failure.
+ */
+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 struct image_header *ihdr = (const struct image_header *)
+ ((uintptr_t)hdr + hdr->page_size);
+
+ /*
+ * 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",
+ kernel_addr, DIV_ROUND_UP(hdr->kernel_size, 1024));
+
+ char commandline[COMMANDLINE_LENGTH] = {0};
+ int offset;
+ char *bootargs = env_get("bootargs");
+
+ if (bootargs) {
+ if (strlen(bootargs) + 1 > sizeof(commandline)) {
+ printf("bootargs is too long!\n");
+ return -1;
+ }
+ else
+ strncpy(commandline, bootargs, sizeof(commandline) - 1);
+ } else {
+ offset = fdt_path_offset(gd->fdt_blob, "/chosen");
+ if (offset > 0) {
+ bootargs = (char *)fdt_getprop(gd->fdt_blob, offset,
+ "bootargs", NULL);
+ if (bootargs)
+ sprintf(commandline, "%s ", bootargs);
+ }
+
+ if (*hdr->cmdline) {
+ if (strlen(hdr->cmdline) + 1 >
+ COMMANDLINE_LENGTH - strlen(commandline)) {
+ printf("cmdline in bootimg is too long!\n");
+ return -1;
+ }
+ else
+ strncat(commandline, hdr->cmdline, COMMANDLINE_LENGTH - strlen(commandline));
+ }
+ }
+
+ append_kernel_cmdline(commandline);
debug("Kernel command line: %s\n", commandline);
env_set("bootargs", commandline);
else
*os_len = hdr->kernel_size;
}
+
+ return 0;
+}
+
+/**
+ * android_image_get_kernel() - processes kernel part of Android boot images
+ * @hdr: Pointer to boot image header, which is at the start
+ * of the image.
+ * @vendor_hdr: Pointer to vendor_boot image header, which is at the start
+ * of the image.
+ * This function appends the kernel command line to the bootargs env variable.
+ *
+ * Return: Zero on success, otherwise on failure.
+ */
+int android_image_get_kernel_v3(const struct boot_img_hdr_v3 *hdr,
+ const struct vendor_boot_img_hdr_v3 *vendor_hdr)
+{
+ u32 kernel_addr = vendor_hdr->kernel_addr;
+
+ /*
+ * 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, (char *)(vendor_hdr->name), ANDR_VENDOR_BOOT_NAME_SIZE);
+ andr_tmp_str[ANDR_VENDOR_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",
+ kernel_addr, DIV_ROUND_UP(hdr->kernel_size, 1024));
+
+ char commandline[COMMANDLINE_LENGTH] = {0};
+ int offset;
+ char *bootargs = env_get("bootargs");
+
+ if (bootargs) {
+ if (strlen(bootargs) + 1 > sizeof(commandline)) {
+ printf("bootargs is too long!\n");
+ return -1;
+ }
+ else
+ strncpy(commandline, bootargs, sizeof(commandline) - 1);
+ } else {
+ offset = fdt_path_offset(gd->fdt_blob, "/chosen");
+ if (offset > 0) {
+ bootargs = (char *)fdt_getprop(gd->fdt_blob, offset,
+ "bootargs", NULL);
+ if (bootargs)
+ sprintf(commandline, "%s ", bootargs);
+ }
+
+ if (*vendor_hdr->cmdline) {
+ if (strlen((char *)vendor_hdr->cmdline) + 1 >
+ COMMANDLINE_LENGTH - strlen(commandline)) {
+ printf("cmdline in bootimg is too long!\n");
+ return -1;
+ }
+ else
+ strncat(commandline, (char *)(vendor_hdr->cmdline), COMMANDLINE_LENGTH - strlen(commandline));
+ }
+
+ if (*hdr->cmdline) {
+ if (strlen((char *)hdr->cmdline) + 1 >
+ COMMANDLINE_LENGTH - strlen(commandline)) {
+ printf("cmdline in bootimg is too long!\n");
+ return -1;
+ }
+ else
+ strncat(commandline, (char *)hdr->cmdline, COMMANDLINE_LENGTH - strlen(commandline));
+ }
+ }
+
+ append_kernel_cmdline(commandline);
+
+ debug("Kernel command line: %s\n", commandline);
+ env_set("bootargs", commandline);
+
return 0;
}
return memcmp(ANDR_BOOT_MAGIC, hdr->magic, ANDR_BOOT_MAGIC_SIZE);
}
+int android_image_check_header_v3(const struct boot_img_hdr_v3 *hdr,
+ const struct vendor_boot_img_hdr_v3 *vendor_hdr)
+{
+ return memcmp(ANDR_BOOT_MAGIC, hdr->magic, ANDR_BOOT_MAGIC_SIZE) ||
+ memcmp(ANDR_VENDOR_BOOT_MAGIC, vendor_hdr->magic, ANDR_VENDOR_BOOT_MAGIC_SIZE);
+}
+
ulong android_image_get_end(const struct andr_img_hdr *hdr)
{
ulong end;
#include <asm/arch/sys_proto.h>
#include <asm/setup.h>
#include <env.h>
+#include <lz4.h>
#include "../lib/avb/fsl/utils.h"
#ifdef CONFIG_AVB_SUPPORT
#if defined(CONFIG_AVB_SUPPORT) && defined(CONFIG_MMC)
/* we can use avb to verify Trusty if we want */
+#ifdef CONFIG_VENDOR_BOOT_SUPPORT
+const char *requested_partitions_boot[] = {"boot", "vendor_boot", FDT_PART_NAME, NULL};
+#else
const char *requested_partitions_boot[] = {"boot", FDT_PART_NAME, NULL};
+#endif
const char *requested_partitions_recovery[] = {"recovery", FDT_PART_NAME, NULL};
static bool is_load_fdt_from_part(void)
int do_boota(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {
ulong addr = 0;
+ /* 'hdr' should point to boot.img */
+#ifdef CONFIG_VENDOR_BOOT_SUPPORT
+ struct boot_img_hdr_v3 *hdr = NULL;
+ struct vendor_boot_img_hdr_v3 *vendor_hdr = NULL;
+#else
struct andr_img_hdr *hdr = NULL;
- ulong image_size;
+#endif
u32 avb_metric;
bool check_image_arm64 = false;
bool is_recovery_mode = false;
AvbABFlowResult avb_result;
AvbSlotVerifyData *avb_out_data = NULL;
AvbPartitionData *avb_loadpart = NULL;
+#ifdef CONFIG_VENDOR_BOOT_SUPPORT
+ AvbPartitionData *avb_vendorboot = NULL;
+#endif
/* get bootmode, default to boot "boot" */
if (argc > 1) {
avb_metric = get_timer(0);
/* we don't need to verify fdt partition if we don't have it. */
if (!is_load_fdt_from_part()) {
+#ifdef CONFIG_VENDOR_BOOT_SUPPORT
+ requested_partitions_boot[2] = NULL;
+#else
requested_partitions_boot[1] = NULL;
+#endif
requested_partitions_recovery[1] = NULL;
}
#ifndef CONFIG_SYSTEM_RAMDISK_SUPPORT
}
#endif
- /* if in lock state, do avb verify */
+ /* do avb verify */
#ifndef CONFIG_DUAL_BOOTLOADER
/* For imx6 on Android, we don't have a/b slot and we want to verify
* boot/recovery with AVB. For imx8 and Android Things we don't have
#ifdef CONFIG_SYSTEM_RAMDISK_SUPPORT
if (find_partition_data_by_name("boot", avb_out_data, &avb_loadpart))
goto fail;
+#ifdef CONFIG_VENDOR_BOOT_SUPPORT
+ if (find_partition_data_by_name("vendor_boot", avb_out_data, &avb_vendorboot))
+ goto fail;
+#endif
#else
if (!is_recovery_mode) {
if (find_partition_data_by_name("boot", avb_out_data, &avb_loadpart))
}
#endif
assert(avb_loadpart != NULL);
+#ifdef CONFIG_VENDOR_BOOT_SUPPORT
+ assert(avb_vendorboot != NULL);
+#endif
/* we should use avb_part_data->data as boot image */
/* boot image is already read by avb */
+#ifdef CONFIG_VENDOR_BOOT_SUPPORT
+ hdr = (struct boot_img_hdr_v3 *)avb_loadpart->data;
+ vendor_hdr = (struct vendor_boot_img_hdr_v3 *)avb_vendorboot->data;
+ if (android_image_check_header_v3(hdr, vendor_hdr)) {
+#else
hdr = (struct andr_img_hdr *)avb_loadpart->data;
if (android_image_check_header(hdr)) {
+#endif
printf("boota: bad boot image magic\n");
goto fail;
}
fastboot_setup_system_boot_args(avb_out_data->ab_suffix, true);
}
#endif /* CONFIG_SYSTEM_RAMDISK_SUPPORT */
- image_size = avb_loadpart->data_size;
-#if defined (CONFIG_ARCH_IMX8) || defined (CONFIG_ARCH_IMX8M)
+
/* If we are using uncompressed kernel image, copy it directly to
- * hdr->kernel_addr, if we are using compressed lz4 kernel image,
+ * physical dram address. If we are using compressed lz4 kernel image,
* we need to decompress the kernel image first. */
+#ifdef CONFIG_VENDOR_BOOT_SUPPORT
+ if (image_arm64((void *)((ulong)hdr + 4096))) {
+ memcpy((void *)(long)vendor_hdr->kernel_addr,
+ (void *)((ulong)hdr + 4096), hdr->kernel_size);
+ } else if (IS_ENABLED(CONFIG_LZ4)) {
+ size_t lz4_len = MAX_KERNEL_LEN;
+ if (ulz4fn((void *)((ulong)hdr + 4096),
+ hdr->kernel_size, (void *)(ulong)vendor_hdr->kernel_addr, &lz4_len) != 0) {
+ printf("Decompress kernel fail!\n");
+ goto fail;
+ }
+ } else {
+ printf("Wrong kernel image! Please check if you need to enable 'CONFIG_LZ4'\n");
+ goto fail;
+ }
+#else /* CONFIG_VENDOR_BOOT_SUPPORT */
+#if defined (CONFIG_ARCH_IMX8) || defined (CONFIG_ARCH_IMX8M)
if (image_arm64((void *)((ulong)hdr + hdr->page_size))) {
memcpy((void *)(long)hdr->kernel_addr,
(void *)((ulong)hdr + hdr->page_size), hdr->kernel_size);
- } else {
-#ifdef CONFIG_LZ4
+ } else if (IS_ENABLED(CONFIG_LZ4)) {
size_t lz4_len = MAX_KERNEL_LEN;
if (ulz4fn((void *)((ulong)hdr + hdr->page_size),
hdr->kernel_size, (void *)(ulong)hdr->kernel_addr, &lz4_len) != 0) {
printf("Decompress kernel fail!\n");
goto fail;
}
-#else /* CONFIG_LZ4 */
- printf("please enable CONFIG_LZ4 if we're using compressed lz4 kernel image!\n");
+ } else {
+ printf("Wrong kernel image! Please check if you need to enable 'CONFIG_LZ4'\n");
goto fail;
-#endif /* CONFIG_LZ4 */
}
#else /* CONFIG_ARCH_IMX8 || CONFIG_ARCH_IMX8M */
/* copy kernel image and boot header to hdr->kernel_addr - hdr->page_size */
memcpy((void *)(ulong)(hdr->kernel_addr - hdr->page_size), (void *)hdr,
hdr->page_size + ALIGN(hdr->kernel_size, hdr->page_size));
#endif /* CONFIG_ARCH_IMX8 || CONFIG_ARCH_IMX8M */
+#endif /* CONFIG_VENDOR_BOOT_SUPPORT */
} else {
/* Fall into fastboot mode if get unacceptable error from avb
* or verify fail in lock state.
goto fail;
}
- flush_cache((ulong)image_load_addr, image_size);
+#ifdef CONFIG_VENDOR_BOOT_SUPPORT
+ check_image_arm64 = image_arm64((void *)(ulong)vendor_hdr->kernel_addr);
+#else
check_image_arm64 = image_arm64((void *)(ulong)hdr->kernel_addr);
+#endif
+
+#ifdef CONFIG_VENDOR_BOOT_SUPPORT
+ /* Need to concatenate vendor_boot ramdisk and boot ramdisk, check
+ * "include/android_image.h" for boot/vendor_boot image overlay.
+ */
+ memcpy((void *)(ulong)vendor_hdr->ramdisk_addr,
+ (void *)(ulong)vendor_hdr + ALIGN(sizeof(struct vendor_boot_img_hdr_v3), vendor_hdr->page_size),
+ vendor_hdr->vendor_ramdisk_size);
+ memcpy((void *)(ulong)vendor_hdr->ramdisk_addr + vendor_hdr->vendor_ramdisk_size,
+ (void *)(ulong)hdr + 4096 + ALIGN(hdr->kernel_size, 4096), hdr->ramdisk_size);
+#else /* CONFIG_VENDOR_BOOT_SUPPORT */
#if !defined(CONFIG_SYSTEM_RAMDISK_SUPPORT) || !defined(CONFIG_ANDROID_AUTO_SUPPORT)
memcpy((void *)(ulong)hdr->ramdisk_addr, (void *)(ulong)hdr + hdr->page_size
+ ALIGN(hdr->kernel_size, hdr->page_size), hdr->ramdisk_size);
memcpy((void *)(ulong)hdr->ramdisk_addr, (void *)(ulong)hdr + hdr->page_size
+ ALIGN(hdr->kernel_size, hdr->page_size), hdr->ramdisk_size);
#endif
+#endif /* CONFIG_VENDOR_BOOT_SUPPORT */
-#ifdef CONFIG_OF_LIBFDT
/* load the dtb file */
+#ifdef CONFIG_OF_LIBFDT
u32 fdt_addr = 0;
u32 fdt_size = 0;
struct dt_table_header *dt_img = NULL;
- if (is_load_fdt_from_part()) {
- fdt_addr = (ulong)((ulong)(hdr->kernel_addr) + MAX_KERNEL_LEN);
+#ifdef CONFIG_VENDOR_BOOT_SUPPORT
+ fdt_addr = (ulong)((ulong)(vendor_hdr->kernel_addr) + MAX_KERNEL_LEN);
+#else
+ fdt_addr = (ulong)((ulong)(hdr->kernel_addr) + MAX_KERNEL_LEN);
+#endif
#ifdef CONFIG_ANDROID_THINGS_SUPPORT
- if (find_partition_data_by_name("oem_bootloader",
- avb_out_data, &avb_loadpart)) {
- goto fail;
- } else
- dt_img = (struct dt_table_header *)avb_loadpart->data;
+ if (find_partition_data_by_name("oem_bootloader",
+ avb_out_data, &avb_loadpart)) {
+ goto fail;
+ } else
+ dt_img = (struct dt_table_header *)avb_loadpart->data;
#elif defined(CONFIG_SYSTEM_RAMDISK_SUPPORT) /* It means boot.img(recovery) do not include dtb, it need load dtb from partition */
- if (find_partition_data_by_name("dtbo",
- avb_out_data, &avb_loadpart)) {
- goto fail;
- } else
- dt_img = (struct dt_table_header *)avb_loadpart->data;
+ if (find_partition_data_by_name("dtbo",
+ avb_out_data, &avb_loadpart)) {
+ goto fail;
+ } else
+ dt_img = (struct dt_table_header *)avb_loadpart->data;
#else /* recovery.img include dts while boot.img use dtbo */
- if (is_recovery_mode) {
- if (hdr->header_version != 1) {
- printf("boota: boot image header version error!\n");
- goto fail;
- }
-
- dt_img = (struct dt_table_header *)((void *)(ulong)hdr +
- hdr->page_size +
- ALIGN(hdr->kernel_size, hdr->page_size) +
- ALIGN(hdr->ramdisk_size, hdr->page_size) +
- ALIGN(hdr->second_size, hdr->page_size));
- } else if (find_partition_data_by_name("dtbo",
- avb_out_data, &avb_loadpart)) {
- goto fail;
- } else
- dt_img = (struct dt_table_header *)avb_loadpart->data;
-#endif
-
- if (be32_to_cpu(dt_img->magic) != DT_TABLE_MAGIC) {
- printf("boota: bad dt table magic %08x\n",
- be32_to_cpu(dt_img->magic));
- goto fail;
- } else if (!be32_to_cpu(dt_img->dt_entry_count)) {
- printf("boota: no dt entries\n");
+ if (is_recovery_mode) {
+ if (hdr->header_version != 1) {
+ printf("boota: boot image header version error!\n");
goto fail;
}
- struct dt_table_entry *dt_entry;
- dt_entry = (struct dt_table_entry *)((ulong)dt_img +
- be32_to_cpu(dt_img->dt_entries_offset));
- fdt_size = be32_to_cpu(dt_entry->dt_size);
- memcpy((void *)fdt_addr, (void *)((ulong)dt_img +
- be32_to_cpu(dt_entry->dt_offset)), fdt_size);
- } else {
- fdt_addr = (ulong)(hdr->second_addr);
- fdt_size = (ulong)(hdr->second_size);
- if (fdt_size && fdt_addr) {
- memcpy((void *)(ulong)fdt_addr,
- (void *)(ulong)hdr + hdr->page_size
- + ALIGN(hdr->kernel_size, hdr->page_size)
- + ALIGN(hdr->ramdisk_size, hdr->page_size),
- fdt_size);
- }
+ dt_img = (struct dt_table_header *)((void *)(ulong)hdr +
+ hdr->page_size +
+ ALIGN(hdr->kernel_size, hdr->page_size) +
+ ALIGN(hdr->ramdisk_size, hdr->page_size) +
+ ALIGN(hdr->second_size, hdr->page_size));
+ } else if (find_partition_data_by_name("dtbo",
+ avb_out_data, &avb_loadpart)) {
+ goto fail;
+ } else
+ dt_img = (struct dt_table_header *)avb_loadpart->data;
+#endif
+
+ if (be32_to_cpu(dt_img->magic) != DT_TABLE_MAGIC) {
+ printf("boota: bad dt table magic %08x\n",
+ be32_to_cpu(dt_img->magic));
+ goto fail;
+ } else if (!be32_to_cpu(dt_img->dt_entry_count)) {
+ printf("boota: no dt entries\n");
+ goto fail;
}
+
+ struct dt_table_entry *dt_entry;
+ dt_entry = (struct dt_table_entry *)((ulong)dt_img +
+ be32_to_cpu(dt_img->dt_entries_offset));
+ fdt_size = be32_to_cpu(dt_entry->dt_size);
+ memcpy((void *)fdt_addr, (void *)((ulong)dt_img +
+ be32_to_cpu(dt_entry->dt_offset)), fdt_size);
#endif /*CONFIG_OF_LIBFDT*/
+#ifdef CONFIG_VENDOR_BOOT_SUPPORT
+ android_image_get_kernel_v3(hdr, vendor_hdr);
+ addr = vendor_hdr->kernel_addr;
+#else
if (check_image_arm64) {
android_image_get_kernel(hdr, 0, NULL, NULL);
addr = hdr->kernel_addr;
} else {
addr = (ulong)(hdr->kernel_addr - hdr->page_size);
}
+#endif
+
+#ifdef CONFIG_VENDOR_BOOT_SUPPORT
+ printf("kernel @ %08x (%d)\n", vendor_hdr->kernel_addr, hdr->kernel_size);
+ printf("ramdisk @ %08x (%d)\n", vendor_hdr->ramdisk_addr,
+ vendor_hdr->vendor_ramdisk_size + hdr->ramdisk_size);
+#else
printf("kernel @ %08x (%d)\n", hdr->kernel_addr, hdr->kernel_size);
printf("ramdisk @ %08x (%d)\n", hdr->ramdisk_addr, hdr->ramdisk_size);
+#endif
#ifdef CONFIG_OF_LIBFDT
if (fdt_size)
printf("fdt @ %08x (%d)\n", fdt_addr, fdt_size);
boot_args[0] = "bootm";
sprintf(boot_addr_start, "0x%lx", addr);
+#ifdef CONFIG_VENDOR_BOOT_SUPPORT
+ sprintf(ramdisk_addr, "0x%x:0x%x", vendor_hdr->ramdisk_addr,
+ vendor_hdr->vendor_ramdisk_size + hdr->ramdisk_size);
+#else
sprintf(ramdisk_addr, "0x%x:0x%x", hdr->ramdisk_addr, hdr->ramdisk_size);
+#endif
sprintf(fdt_addr_start, "0x%x", fdt_addr);
/* when CONFIG_SYSTEM_RAMDISK_SUPPORT is enabled and it's for Android Auto, if it's not recovery mode
#define ANDR_BOOT_ARGS_SIZE 512
#define ANDR_BOOT_EXTRA_ARGS_SIZE 1024
+#define ANDR_VENDOR_BOOT_MAGIC "VNDRBOOT"
+#define ANDR_VENDOR_BOOT_MAGIC_SIZE 8
+#define ANDR_VENDOR_BOOT_ARGS_SIZE 2048
+#define ANDR_VENDOR_BOOT_NAME_SIZE 16
+
/* The bootloader expects the structure of andr_img_hdr with header
* version 0 to be as follows: */
/* Boot metric variables (in millisecond) */
u64 dtb_addr; /* physical load address for DTB image */
} __attribute__((packed));
+struct boot_img_hdr_v3 {
+ // Must be 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;
+
+#if __cplusplus
+ void SetOsVersion(unsigned major, unsigned minor, unsigned patch) {
+ os_version &= ((1 << 11) - 1);
+ os_version |= (((major & 0x7f) << 25) | ((minor & 0x7f) << 18) | ((patch & 0x7f) << 11));
+ }
+
+ void SetOsPatchLevel(unsigned year, unsigned month) {
+ os_version &= ~((1 << 11) - 1);
+ os_version |= (((year - 2000) & 0x7f) << 4) | ((month & 0xf) << 0);
+ }
+#endif
+
+ uint32_t header_size;
+
+ uint32_t reserved[4];
+
+ // Version of the boot image header.
+ 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 ANDR_VENDOR_BOOT_MAGIC.
+ uint8_t magic[ANDR_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[ANDR_VENDOR_BOOT_ARGS_SIZE];
+
+ uint32_t tags_addr; /* physical addr for kernel tags (if required) */
+ uint8_t name[ANDR_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
* follows:
*
* 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
+ */
struct header_image {
uint32_t code0; /* Executable code */
uint32_t code1; /* Executable code */
#if !defined(USE_HOSTCC)
#if defined(CONFIG_ANDROID_BOOT_IMAGE)
struct andr_img_hdr;
+struct boot_img_hdr_v3;
+struct vendor_boot_img_hdr_v3;
int android_image_check_header(const struct andr_img_hdr *hdr);
+int android_image_check_header_v3(const struct boot_img_hdr_v3 *hdr, const struct vendor_boot_img_hdr_v3 *vendor_hdr);
int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify,
ulong *os_data, ulong *os_len);
+int android_image_get_kernel_v3(const struct boot_img_hdr_v3 *hdr, const struct vendor_boot_img_hdr_v3 *vendor_hdr);
int android_image_get_ramdisk(const struct andr_img_hdr *hdr,
ulong *rd_data, ulong *rd_len);
int android_image_get_second(const struct andr_img_hdr *hdr,
bool "Support unlock permission protection in trusty"
depends on IMX_TRUSTY_OS
+config VENDOR_BOOT_SUPPORT
+ bool "Support vendor boot load"
+
endmenu
menu "Hashing Support"