diff --git a/tools/rkcommon.c b/tools/rkcommon.c
index 6595e02c1c5b87e9e4c6b659bcd8c90365e5193a..1ea072b8d4da500c791f1e53578510086254391d 100644
--- a/tools/rkcommon.c
+++ b/tools/rkcommon.c
@@ -40,6 +40,14 @@ struct header0_info {
 	uint8_t reserved2[2];
 };
 
+/**
+ * struct header1_info
+ */
+struct header1_info {
+	uint32_t magic;
+	uint32_t first_insn;
+};
+
 /**
  * struct spl_info - spl info for each chip
  *
@@ -47,19 +55,22 @@ struct header0_info {
  * @spl_hdr:		Boot ROM requires a 4-bytes spl header
  * @spl_size:		Spl size(include extra 4-bytes spl header)
  * @spl_rc4:		RC4 encode the SPL binary (same key as header)
+ * @spl_aarch64:        Pad the header with an AArch64 'nop's to 8-bytes
  */
+
 struct spl_info {
 	const char *imagename;
 	const char *spl_hdr;
 	const uint32_t spl_size;
 	const bool spl_rc4;
+	const bool spl_aarch64;
 };
 
 static struct spl_info spl_infos[] = {
-	{ "rk3036", "RK30", 0x1000, false },
-	{ "rk3188", "RK31", 0x8000 - 0x800, true },
-	{ "rk3288", "RK32", 0x8000, false },
-	{ "rk3399", "RK33", 0x20000, false },
+	{ "rk3036", "RK30", 0x1000, false, false },
+	{ "rk3188", "RK31", 0x8000 - 0x800, true, false },
+	{ "rk3288", "RK32", 0x8000, false, false },
+	{ "rk3399", "RK33", 0x20000, false, true },
 };
 
 static unsigned char rc4_key[16] = {
@@ -106,6 +117,16 @@ const char *rkcommon_get_spl_hdr(struct image_tool_params *params)
 	return info->spl_hdr;
 }
 
+const bool rkcommon_get_spl_hdr_padto8(struct image_tool_params *params)
+{
+	struct spl_info *info = rkcommon_get_spl_info(params->imagename);
+
+	/*
+	 * info would not be NULL, because of we checked params before.
+	 */
+	return info->spl_aarch64;
+}
+
 int rkcommon_get_spl_size(struct image_tool_params *params)
 {
 	struct spl_info *info = rkcommon_get_spl_info(params->imagename);
@@ -126,16 +147,12 @@ bool rkcommon_need_rc4_spl(struct image_tool_params *params)
 	return info->spl_rc4;
 }
 
-int rkcommon_set_header(void *buf, uint file_size,
-			struct image_tool_params *params)
+static void rkcommon_set_header0(void *buf, uint file_size,
+				 struct image_tool_params *params)
 {
-	struct header0_info *hdr;
+	struct header0_info *hdr = buf;
 
-	if (file_size > rkcommon_get_spl_size(params))
-		return -ENOSPC;
-
-	memset(buf,  '\0', RK_INIT_OFFSET * RK_BLK_SIZE);
-	hdr = (struct header0_info *)buf;
+	memset(buf, '\0', RK_INIT_OFFSET * RK_BLK_SIZE);
 	hdr->signature = RK_SIGNATURE;
 	hdr->disable_rc4 = !rkcommon_need_rc4_spl(params);
 	hdr->init_offset = RK_INIT_OFFSET;
@@ -145,6 +162,31 @@ int rkcommon_set_header(void *buf, uint file_size,
 	hdr->init_boot_size = hdr->init_size + RK_MAX_BOOT_SIZE / RK_BLK_SIZE;
 
 	rc4_encode(buf, RK_BLK_SIZE, rc4_key);
+}
+
+int rkcommon_set_header(void *buf, uint file_size,
+			struct image_tool_params *params)
+{
+	struct header1_info *hdr = buf + RK_SPL_HDR_START;
+
+	if (file_size > rkcommon_get_spl_size(params))
+		return -ENOSPC;
+
+	rkcommon_set_header0(buf, file_size, params);
+
+	/* Set up the SPL name and add the AArch64 'nop' padding, if needed */
+	memcpy(&hdr->magic, rkcommon_get_spl_hdr(params), RK_SPL_HDR_SIZE);
+
+	/*
+	 * Pad the 4-byte header to 8-bytes using an AArch64 'nop'.
+	 * Note that AArch64 insns are always encoded as little-endian.
+	 */
+	if (rkcommon_get_spl_hdr_padto8(params))
+		hdr->first_insn = cpu_to_le32(0xd503201f);
+
+	if (rkcommon_need_rc4_spl(params))
+		rkcommon_rc4_encode_spl(buf, RK_SPL_HDR_START,
+					params->file_size - RK_SPL_HDR_START);
 
 	return 0;
 }
@@ -161,3 +203,34 @@ void rkcommon_rc4_encode_spl(void *buf, unsigned int offset, unsigned int size)
 		remaining -= step;
 	}
 }
+
+void rkcommon_vrec_header(struct image_tool_params *params,
+			  struct image_type_params *tparams)
+{
+	/*
+	 * The SPL image looks as follows:
+	 *
+	 * 0x0    header0 (see rkcommon.c)
+	 * 0x800  spl_name ('RK30', ..., 'RK33')
+	 * 0x804  first instruction to be executed
+	 *        (image start for AArch32, 'nop' for AArch64))
+	 * 0x808  second instruction to be executed
+	 *        (image start for AArch64)
+	 *
+	 * For AArch64 (ARMv8) payloads, we receive an input file that
+	 * needs to start on an 8-byte boundary (natural alignment), so
+	 * we need to put a NOP at 0x804.
+	 *
+	 * Depending on this, the header is either 0x804 or 0x808 bytes
+	 * in length.
+	 */
+	if (rkcommon_get_spl_hdr_padto8(params))
+		tparams->header_size = RK_SPL_HDR_START + 8;
+	else
+		tparams->header_size = RK_SPL_HDR_START + 4;
+
+	/* Allocate, clear and install the header */
+	tparams->hdr = malloc(tparams->header_size);
+	memset(tparams->hdr, 0, tparams->header_size);
+	tparams->header_size = tparams->header_size;
+}
diff --git a/tools/rkcommon.h b/tools/rkcommon.h
index b4f6f327dc17f85be0933dc927336ca153b5de33..3d645168c2656ac39cbeb0580bdd479f5222f4f8 100644
--- a/tools/rkcommon.h
+++ b/tools/rkcommon.h
@@ -33,6 +33,19 @@ int rkcommon_check_params(struct image_tool_params *params);
  */
 const char *rkcommon_get_spl_hdr(struct image_tool_params *params);
 
+/**
+ * rkcommon_get_spl_hdr_padto8() - check if we need to pad to 8 bytes
+ *
+ * Rockchip's bootrom starts execution right after the SPL header (i.e.
+ * at offset 4), but we can not reasonably align the test section of
+ * an AArch64 SPL at 4 bytes (as this would break natural alignment
+ * and any embedded constants might cause an alignment exception, which
+ * is illegal in privileged modes).
+ *
+ * Padding is (for now) assumed to occur with a single AArch64 'nop'.
+ */
+const bool rkcommon_get_spl_hdr_padto8(struct image_tool_params *params);
+
 /**
  * rkcommon_get_spl_size() - get spl size for a Rockchip boot image
  *
@@ -77,4 +90,14 @@ bool rkcommon_need_rc4_spl(struct image_tool_params *params);
  */
 void rkcommon_rc4_encode_spl(void *buf, unsigned int offset, unsigned int size);
 
+/**
+ * rkcommon_vrec_header() - allocate memory for the header
+ *
+ * @params:     Pointer to the tool params structure
+ * @tparams:    Pointer tot the image type structure (for setting
+ *              the header and header_size)
+ */
+void rkcommon_vrec_header(struct image_tool_params *params,
+			  struct image_type_params *tparams);
+
 #endif
diff --git a/tools/rksd.c b/tools/rksd.c
index e55c52267fd8b189d139581d5003cf844c3d32bb..ac8a67d3bc80b1218f60400cb341b9e9ea315ef1 100644
--- a/tools/rksd.c
+++ b/tools/rksd.c
@@ -13,8 +13,6 @@
 #include "mkimage.h"
 #include "rkcommon.h"
 
-static char dummy_hdr[RK_IMAGE_HEADER_LEN];
-
 static int rksd_verify_header(unsigned char *buf,  int size,
 				 struct image_tool_params *params)
 {
@@ -38,13 +36,6 @@ static void rksd_set_header(void *buf,  struct stat *sbuf,  int ifd,
 		printf("Warning: SPL image is too large (size %#x) and will not boot\n",
 		       size);
 	}
-
-	memcpy(buf + RK_SPL_HDR_START, rkcommon_get_spl_hdr(params),
-	       RK_SPL_HDR_SIZE);
-
-	if (rkcommon_need_rc4_spl(params))
-		rkcommon_rc4_encode_spl(buf, RK_SPL_HDR_START,
-					params->file_size - RK_SPL_HDR_START);
 }
 
 static int rksd_extract_subimage(void *buf,  struct image_tool_params *params)
@@ -66,10 +57,12 @@ static int rksd_vrec_header(struct image_tool_params *params,
 {
 	int pad_size;
 
+	rkcommon_vrec_header(params, tparams);
+
 	pad_size = RK_SPL_HDR_START + rkcommon_get_spl_size(params);
 	debug("pad_size %x\n", pad_size);
 
-	return pad_size - params->file_size;
+	return pad_size - params->file_size - tparams->header_size;
 }
 
 /*
@@ -78,8 +71,8 @@ static int rksd_vrec_header(struct image_tool_params *params,
 U_BOOT_IMAGE_TYPE(
 	rksd,
 	"Rockchip SD Boot Image support",
-	RK_IMAGE_HEADER_LEN,
-	dummy_hdr,
+	0,
+	NULL,
 	rkcommon_check_params,
 	rksd_verify_header,
 	rksd_print_header,
diff --git a/tools/rkspi.c b/tools/rkspi.c
index 9fa43e8303468552153dd9b8234c838ac1a3d4c4..d2d3fdda424eadc545aac09253d65ae574268ec7 100644
--- a/tools/rkspi.c
+++ b/tools/rkspi.c
@@ -17,8 +17,6 @@ enum {
 	RKSPI_SECT_LEN		= RK_BLK_SIZE * 4,
 };
 
-static char dummy_hdr[RK_IMAGE_HEADER_LEN];
-
 static int rkspi_verify_header(unsigned char *buf, int size,
 			       struct image_tool_params *params)
 {
@@ -45,13 +43,6 @@ static void rkspi_set_header(void *buf, struct stat *sbuf, int ifd,
 		       size);
 	}
 
-	memcpy(buf + RK_SPL_HDR_START, rkcommon_get_spl_hdr(params),
-	       RK_SPL_HDR_SIZE);
-
-	if (rkcommon_need_rc4_spl(params))
-		rkcommon_rc4_encode_spl(buf, RK_SPL_HDR_START,
-					params->file_size - RK_SPL_HDR_START);
-
 	/*
 	 * Spread the image out so we only use the first 2KB of each 4KB
 	 * region. This is a feature of the SPI format required by the Rockchip
@@ -86,6 +77,8 @@ static int rkspi_vrec_header(struct image_tool_params *params,
 {
 	int pad_size;
 
+	rkcommon_vrec_header(params, tparams);
+
 	pad_size = (rkcommon_get_spl_size(params) + 0x7ff) / 0x800 * 0x800;
 	params->orig_file_size = pad_size;
 
@@ -94,7 +87,7 @@ static int rkspi_vrec_header(struct image_tool_params *params,
 	pad_size += RK_SPL_HDR_START;
 	debug("pad_size %x\n", pad_size);
 
-	return pad_size - params->file_size;
+	return pad_size - params->file_size - tparams->header_size;
 }
 
 /*
@@ -103,8 +96,8 @@ static int rkspi_vrec_header(struct image_tool_params *params,
 U_BOOT_IMAGE_TYPE(
 	rkspi,
 	"Rockchip SPI Boot Image support",
-	RK_IMAGE_HEADER_LEN,
-	dummy_hdr,
+	0,
+	NULL,
 	rkcommon_check_params,
 	rkspi_verify_header,
 	rkspi_print_header,