aboot: add support for booting 64bit kernel
Dynamically check weather a given bootimage contains
a 64bit kernel and add support for booting into the 64bit
kernel via secure-monitor(EL3) api.
Change-Id: Ifcc63181258df561d8acdd7ce2374a75113f357a
diff --git a/app/aboot/aboot.c b/app/aboot/aboot.c
index f82a2b3..589ffd2 100755
--- a/app/aboot/aboot.c
+++ b/app/aboot/aboot.c
@@ -102,6 +102,8 @@
#define UBI_MAGIC "UBI#"
#define UBI_MAGIC_SIZE 0x04
+#define IS_ARM64(ptr) (ptr->magic_64 == KERNEL64_HDR_MAGIC) ? true : false
+
#if UFS_SUPPORT
static const char *emmc_cmdline = " androidboot.bootdevice=msm_sdcc.1";
static const char *ufs_cmdline = " androidboot.bootdevice=msm_ufs.1";
@@ -181,11 +183,14 @@
extern int fastboot_trigger(void);
#endif
-static void update_ker_tags_rdisk_addr(struct boot_img_hdr *hdr)
+static void update_ker_tags_rdisk_addr(struct boot_img_hdr *hdr, bool is_arm64)
{
/* overwrite the destination of specified for the project */
#ifdef ABOOT_IGNORE_BOOT_HEADER_ADDRS
- hdr->kernel_addr = ABOOT_FORCE_KERNEL_ADDR;
+ if (is_arm64)
+ hdr->kernel_addr = ABOOT_FORCE_KERNEL64_ADDR;
+ else
+ hdr->kernel_addr = ABOOT_FORCE_KERNEL_ADDR;
hdr->ramdisk_addr = ABOOT_FORCE_RAMDISK_ADDR;
hdr->tags_addr = ABOOT_FORCE_TAGS_ADDR;
#endif
@@ -579,6 +584,7 @@
void (*entry)(unsigned, unsigned, unsigned*) = (entry_func_ptr*)(PA((addr_t)kernel));
uint32_t tags_phys = PA((addr_t)tags);
+ struct kernel64_hdr *kptr = (struct kernel64_hdr*)kernel;
ramdisk = PA(ramdisk);
@@ -623,7 +629,13 @@
arch_disable_mmu();
#endif
bs_set_timestamp(BS_KERNEL_ENTRY);
- entry(0, machtype, (unsigned*)tags_phys);
+
+ if (IS_ARM64(kptr))
+ /* Jump to a 64bit kernel */
+ scm_elexec_call((paddr_t)kernel, tags_phys);
+ else
+ /* Jump to a 32bit kernel */
+ entry(0, machtype, (unsigned*)tags_phys);
}
/* Function to check if the memory address range falls within the aboot
@@ -648,9 +660,9 @@
#define ROUND_TO_PAGE(x,y) (((x) + (y)) & (~(y)))
-BUF_DMA_ALIGN(buf, 4096); //Equal to max-supported pagesize
+BUF_DMA_ALIGN(buf, BOOT_IMG_MAX_PAGE_SIZE); //Equal to max-supported pagesize
#if DEVICE_TREE
-BUF_DMA_ALIGN(dt_buf, 4096);
+BUF_DMA_ALIGN(dt_buf, BOOT_IMG_MAX_PAGE_SIZE);
#endif
static void verify_signed_bootimg(uint32_t bootimg_addr, uint32_t bootimg_size)
@@ -763,6 +775,9 @@
uint32_t dt_actual;
uint32_t dt_hdr_size;
#endif
+ BUF_DMA_ALIGN(kbuf, BOOT_IMG_MAX_PAGE_SIZE);
+ struct kernel64_hdr *kptr = (void*) kbuf;
+
if (check_format_bit())
boot_into_recovery = 1;
@@ -815,12 +830,21 @@
page_mask = page_size - 1;
}
+ /* Read the next page to get kernel Image header
+ * which lives in the second page for arm64 targets.
+ */
+
+ if (mmc_read(ptn + page_size, (unsigned int *) kbuf, page_size)) {
+ dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
+ return -1;
+ }
+
/*
* Update the kernel/ramdisk/tags address if the boot image header
* has default values, these default values come from mkbootimg when
* the boot image is flashed using fastboot flash:raw
*/
- update_ker_tags_rdisk_addr(hdr);
+ update_ker_tags_rdisk_addr(hdr, IS_ARM64(kptr));
/* Get virtual addresses since the hdr saves physical addresses. */
hdr->kernel_addr = VA((addr_t)(hdr->kernel_addr));
@@ -1141,7 +1165,7 @@
* has default values, these default values come from mkbootimg when
* the boot image is flashed using fastboot flash:raw
*/
- update_ker_tags_rdisk_addr(hdr);
+ update_ker_tags_rdisk_addr(hdr, false);
/* Get virtual addresses since the hdr saves physical addresses. */
hdr->kernel_addr = VA((addr_t)(hdr->kernel_addr));
@@ -1327,7 +1351,7 @@
return 0;
}
-BUF_DMA_ALIGN(info_buf, 4096);
+BUF_DMA_ALIGN(info_buf, BOOT_IMG_MAX_PAGE_SIZE);
void write_device_info_mmc(device_info *dev)
{
struct device_info *info = (void*) info_buf;
@@ -1565,6 +1589,7 @@
unsigned kernel_actual;
unsigned ramdisk_actual;
struct boot_img_hdr *hdr;
+ struct kernel64_hdr *kptr;
char *ptr = ((char*) data);
int ret = 0;
uint8_t dtb_copied = 0;
@@ -1592,7 +1617,8 @@
* has default values, these default values come from mkbootimg when
* the boot image is flashed using fastboot flash:raw
*/
- update_ker_tags_rdisk_addr(hdr);
+ kptr = (struct kernel64_hdr*)((char*) data + page_size);
+ update_ker_tags_rdisk_addr(hdr, IS_ARM64(kptr));
/* Get virtual addresses since the hdr saves physical addresses. */
hdr->kernel_addr = VA(hdr->kernel_addr);
diff --git a/app/aboot/bootimg.h b/app/aboot/bootimg.h
index f9966a1..8320470 100644
--- a/app/aboot/bootimg.h
+++ b/app/aboot/bootimg.h
@@ -2,6 +2,8 @@
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -33,8 +35,9 @@
#define BOOT_MAGIC "ANDROID!"
#define BOOT_MAGIC_SIZE 8
-#define BOOT_NAME_SIZE 16
-#define BOOT_ARGS_SIZE 512
+#define BOOT_NAME_SIZE 16
+#define BOOT_ARGS_SIZE 512
+#define BOOT_IMG_MAX_PAGE_SIZE 4096
struct boot_img_hdr
{
@@ -97,4 +100,21 @@
unsigned *bootimg_size);
void bootimg_set_cmdline(boot_img_hdr *hdr, const char *cmdline);
+
+#define KERNEL64_HDR_MAGIC 0x644D5241 /* ARM64 */
+
+struct kernel64_hdr
+{
+ uint32_t insn;
+ uint32_t res1;
+ uint64_t text_offset;
+ uint64_t res2;
+ uint64_t res3;
+ uint64_t res4;
+ uint64_t res5;
+ uint64_t res6;
+ uint32_t magic_64;
+ uint32_t res7;
+};
+
#endif