vboot: Add flag to vbutil_kernel for reconstruction of vmlinuz image

Adding functionality to allow for rebuilding of vmlinuz after it
has been processed into vblock and header stripped.  Basically appends
the 16-bit header of a vmlinuz image onto the end of the vblock.
BUG=chromium:438302
BRANCH=none
TEST=Successfully ran "make runalltests".
     Also, ran:
     1. Repack kernel block (so that 16-bit header is included):
        "vbutil_kernel --pack kern_0 ..."
     2. Verify kernel: "vbutil_kernel --verify kern_0 ... ".  This should
        be done before booting into kernel, but not necessary for it to work.
     3. Rebuild vmlinuz image:
        "vbutil_kernel --get-vmlinuz kern_0 --vmlinuz-out vm.out"
     4. Set up kexec with vmlinuz (this should complete with no errors):
        "kexec -l vm.out (other kernel cmd line args)"
     5. Boot into kernel:
        "kexec -e"

Change-Id: Iaa1582a1aedf70b43cdb3a56cde1fb248f1793d4
Signed-off-by: Shelley Chen <shchen@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/232750
Reviewed-by: Furquan Shaikh <furquan@chromium.org>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
diff --git a/firmware/include/vboot_struct.h b/firmware/include/vboot_struct.h
index 923e63c..9e845ef 100644
--- a/firmware/include/vboot_struct.h
+++ b/firmware/include/vboot_struct.h
@@ -180,9 +180,9 @@
 /****************************************************************************/
 
 #define KERNEL_PREAMBLE_HEADER_VERSION_MAJOR 2
-#define KERNEL_PREAMBLE_HEADER_VERSION_MINOR 0
+#define KERNEL_PREAMBLE_HEADER_VERSION_MINOR 1
 
-/* Preamble block for kernel
+/* Preamble block for kernel, version 2.0
  *
  * This should be followed by:
  *   1) The signature data for the kernel body, pointed to by
@@ -190,7 +190,7 @@
  *   2) The signature data for (VBFirmwarePreambleHeader + body signature
  *      data), pointed to by preamble_signature.sig_offset.
  */
-typedef struct VbKernelPreambleHeader {
+typedef struct VbKernelPreambleHeader2_0 {
 	/*
 	 * Size of this preamble, including keys, signatures, and padding, in
 	 * bytes
@@ -213,9 +213,56 @@
 	uint64_t bootloader_size;
 	/* Signature for the kernel body */
 	VbSignature body_signature;
+} __attribute__((packed)) VbKernelPreambleHeader2_0;
+
+#define EXPECTED_VBKERNELPREAMBLEHEADER2_0_SIZE 96
+
+/* Preamble block for kernel, version 2.1
+ *
+ * This should be followed by:
+ *   1) The signature data for the kernel body, pointed to by
+ *      body_signature.sig_offset.
+ *   2) The signature data for (VBFirmwarePreambleHeader + body signature
+ *      data), pointed to by preamble_signature.sig_offset.
+ *   3) The 16-bit vmlinuz header, which is used for reconstruction of
+ *      vmlinuz image.
+ */
+typedef struct VbKernelPreambleHeader {
+	/*
+	 * Size of this preamble, including keys, signatures, vmlinuz header,
+	 * and padding, in bytes
+	 */
+	uint64_t preamble_size;
+	/* Signature for this preamble (header + body signature) */
+	VbSignature preamble_signature;
+	/* Version of this header format */
+	uint32_t header_version_major;
+	/* Version of this header format */
+	uint32_t header_version_minor;
+
+	/* Kernel version */
+	uint64_t kernel_version;
+	/* Load address for kernel body */
+	uint64_t body_load_address;
+	/* Address of bootloader, after body is loaded at body_load_address */
+	uint64_t bootloader_address;
+	/* Size of bootloader in bytes */
+	uint64_t bootloader_size;
+	/* Signature for the kernel body */
+	VbSignature body_signature;
+	/*
+	 * Fields added in header version 2.1.  You must verify the header
+	 * version before reading these fields!
+	 */
+	/* Address of 16-bit header for vmlinuz reassembly.  Readers should
+	   return 0 for header version < 2.1 */
+	uint64_t vmlinuz_header_address;
+	/* Size of 16-bit header for vmlinuz in bytes.  Readers should return 0
+	   for header version < 2.1 */
+	uint64_t vmlinuz_header_size;
 } __attribute__((packed)) VbKernelPreambleHeader;
 
-#define EXPECTED_VBKERNELPREAMBLEHEADER_SIZE 96
+#define EXPECTED_VBKERNELPREAMBLEHEADER2_1_SIZE 112
 
 /****************************************************************************/
 
diff --git a/firmware/lib/include/vboot_common.h b/firmware/lib/include/vboot_common.h
index 83064d2..f792d1a 100644
--- a/firmware/lib/include/vboot_common.h
+++ b/firmware/lib/include/vboot_common.h
@@ -149,6 +149,25 @@
 
 
 /**
+ * Retrieve the 16-bit vmlinuz header address and size from the kernel preamble
+ * if there is one.  These are only available in Kernel Preamble Header version
+ * >= 2.1.  If given a header 2.0 or lower, will set address and size to 0 (this
+ * is not considered an error).
+ *
+ * Returns VBOOT_SUCCESS if successful.
+ */
+int VbGetKernelVmlinuzHeader(const VbKernelPreambleHeader *preamble,
+			     uint64_t *vmlinuz_header_address,
+			     uint64_t *vmlinuz_header_size);
+
+/**
+ * Verify that the Vmlinuz Header is contained inside of the kernel blob.
+ *
+ * Returns VBOOT_SUCCESS or VBOOT_PREAMBLE_INVALID on error
+ */
+int VerifyVmlinuzInsideKBlob(uint64_t kblob, uint64_t kblob_size,
+			     uint64_t header, uint64_t header_size);
+/**
  * Initialize a verified boot shared data structure.
  *
  * Returns 0 if success, non-zero if error.
diff --git a/firmware/lib/vboot_common.c b/firmware/lib/vboot_common.c
index 3811e1e..2cb01f3 100644
--- a/firmware/lib/vboot_common.c
+++ b/firmware/lib/vboot_common.c
@@ -435,10 +435,54 @@
 		return VBOOT_PREAMBLE_INVALID;
 	}
 
+	/*
+	 * If the preamble header version is at least 2.1, verify we have space
+	 * for the added fields from 2.1.
+	 */
+	if (preamble->header_version_minor >= 1) {
+		if(size < EXPECTED_VBKERNELPREAMBLEHEADER2_1_SIZE) {
+			VBDEBUG(("Not enough data for preamble header 2.1.\n"));
+			return VBOOT_PREAMBLE_INVALID;
+		}
+	}
+
 	/* Success */
 	return VBOOT_SUCCESS;
 }
 
+int VbGetKernelVmlinuzHeader(const VbKernelPreambleHeader *preamble,
+			     uint64_t *vmlinuz_header_address,
+			     uint64_t *vmlinuz_header_size)
+{
+	*vmlinuz_header_address = 0;
+	*vmlinuz_header_size = 0;
+	if (preamble->header_version_minor > 0) {
+		/*
+		 * Set header and size only if the preamble header version is >
+		 * 2.1 as they don't exist in version 2.0 (Note that we don't
+		 * need to check header_version_major; if that's not 2 then
+		 * VerifyKernelPreamble() would have already failed.
+		 */
+		*vmlinuz_header_address = preamble->vmlinuz_header_address;
+		*vmlinuz_header_size = preamble->vmlinuz_header_size;
+	}
+	return VBOOT_SUCCESS;
+}
+
+int VerifyVmlinuzInsideKBlob(uint64_t kblob, uint64_t kblob_size,
+			     uint64_t header, uint64_t header_size)
+{
+	uint64_t end = header-kblob;
+	if (end > kblob_size)
+		return VBOOT_PREAMBLE_INVALID;
+	if (UINT64_MAX - end < header_size)
+		return VBOOT_PREAMBLE_INVALID;
+	if (end + header_size > kblob_size)
+		return VBOOT_PREAMBLE_INVALID;
+
+	return VBOOT_SUCCESS;
+}
+
 uint64_t VbSharedDataReserve(VbSharedDataHeader *header, uint64_t size)
 {
 	uint64_t offs = header->data_used;
diff --git a/futility/cmd_show.c b/futility/cmd_show.c
index f226269..7f0e488 100644
--- a/futility/cmd_show.c
+++ b/futility/cmd_show.c
@@ -385,6 +385,8 @@
 	uint64_t kernel_size = 0;
 	int good_sig = 0;
 	int retval = 0;
+	uint64_t vmlinuz_header_size = 0;
+	uint64_t vmlinuz_header_address = 0;
 
 	/* Check the hash... */
 	if (VBOOT_SUCCESS != KeyBlockVerify(key_block, len, NULL, 1)) {
@@ -435,6 +437,19 @@
 	printf("  Bootloader size:       0x%" PRIx64 "\n",
 	       preamble->bootloader_size);
 
+	if (VbGetKernelVmlinuzHeader(preamble,
+				     &vmlinuz_header_address,
+				     &vmlinuz_header_size)
+	    != VBOOT_SUCCESS) {
+		fprintf(stderr, "Unable to retrieve Vmlinuz Header!");
+		return 1;
+	}
+	if (vmlinuz_header_size) {
+		printf("  Vmlinuz_header address:    0x%" PRIx64 "\n",
+		       vmlinuz_header_address);
+		printf("  Vmlinuz header size:       0x%" PRIx64 "\n",
+		       vmlinuz_header_size);
+	}
 
 	/* Verify kernel body */
 	if (option.fv) {
diff --git a/futility/cmd_vbutil_kernel.c b/futility/cmd_vbutil_kernel.c
index 786344f..3b2643e 100644
--- a/futility/cmd_vbutil_kernel.c
+++ b/futility/cmd_vbutil_kernel.c
@@ -43,6 +43,7 @@
 	OPT_MODE_PACK = 1000,
 	OPT_MODE_REPACK,
 	OPT_MODE_VERIFY,
+	OPT_MODE_GET_VMLINUZ,
 	OPT_ARCH,
 	OPT_OLDBLOB,
 	OPT_KLOADADDR,
@@ -57,12 +58,14 @@
 	OPT_PAD,
 	OPT_VERBOSE,
 	OPT_MINVERSION,
+	OPT_VMLINUZ_OUT,
 };
 
 static const struct option long_opts[] = {
 	{"pack", 1, 0, OPT_MODE_PACK},
 	{"repack", 1, 0, OPT_MODE_REPACK},
 	{"verify", 1, 0, OPT_MODE_VERIFY},
+	{"get-vmlinuz", 1, 0, OPT_MODE_GET_VMLINUZ},
 	{"arch", 1, 0, OPT_ARCH},
 	{"oldblob", 1, 0, OPT_OLDBLOB},
 	{"kloadaddr", 1, 0, OPT_KLOADADDR},
@@ -78,6 +81,7 @@
 	{"pad", 1, 0, OPT_PAD},
 	{"verbose", 0, &opt_verbose, 1},
 	{"debug", 0, &debugging_enabled, 1},
+	{"vmlinuz-out", 1, 0, OPT_VMLINUZ_OUT},
 	{NULL, 0, 0, 0}
 };
 
@@ -129,14 +133,18 @@
 	"                                in .keyblock format\n"
 	"    --pad <number>            Verification padding size in bytes\n"
 	"    --minversion <number>     Minimum combined kernel key version\n"
-	"                              and kernel version\n"
+	"\nOR\n\n"
+	"Usage:  " MYNAME " %s --get-vmlinuz <file> [PARAMETERS]\n"
+	"\n"
+	"  Required parameters:\n"
+	"    --vmlinuz-out <file>      vmlinuz image output file\n"
 	"\n";
 
 
 /* Print help and return error */
 static void print_help(const char *progname)
 {
-	printf(usage, progname, progname, progname);
+	printf(usage, progname, progname, progname, progname);
 }
 
 
@@ -209,13 +217,14 @@
 	char *vmlinuz_file = NULL;
 	char *bootloader_file = NULL;
 	char *config_file = NULL;
+	char *vmlinuz_out_file = NULL;
 	enum arch_t arch = ARCH_X86;
 	uint64_t kernel_body_load_address = CROS_32BIT_ENTRY_ADDR;
 	int mode = 0;
 	int parse_error = 0;
 	uint64_t min_version = 0;
 	char *e;
-	int i;
+	int i = 0;
 	int rv;
 	VbKeyBlockHeader *keyblock = NULL;
 	VbKeyBlockHeader *t_keyblock = NULL;
@@ -229,11 +238,14 @@
 	uint64_t t_config_size;
 	uint8_t *t_bootloader_data;
 	uint64_t t_bootloader_size;
+	uint64_t vmlinuz_header_size = 0;
+	uint64_t vmlinuz_header_address = 0;
 	VbKernelPreambleHeader *preamble = NULL;
 	uint8_t *kblob_data = NULL;
 	uint64_t kblob_size = 0;
 	uint8_t *vblock_data = NULL;
 	uint64_t vblock_size = 0;
+	FILE *f;
 
 	while (((i = getopt_long(argc, argv, ":", long_opts, NULL)) != -1) &&
 	       !parse_error) {
@@ -251,6 +263,7 @@
 		case OPT_MODE_PACK:
 		case OPT_MODE_REPACK:
 		case OPT_MODE_VERIFY:
+		case OPT_MODE_GET_VMLINUZ:
 			if (mode && (mode != i)) {
 				fprintf(stderr,
 					"Only one mode can be specified\n");
@@ -343,6 +356,8 @@
 				parse_error = 1;
 			}
 			break;
+		case OPT_VMLINUZ_OUT:
+			vmlinuz_out_file = optarg;
 		}
 	}
 
@@ -519,10 +534,79 @@
 				      signpub_key, keyblock_file, min_version);
 
 		return rv;
+
+	case OPT_MODE_GET_VMLINUZ:
+
+		if (!vmlinuz_out_file) {
+			fprintf(stderr,
+				"USE: vbutil_kernel --get-vmlinuz <file> "
+				"--vmlinuz-out <file>\n");
+			print_help(argv[0]);
+			return 1;
+		}
+
+		kpart_data = ReadOldKPartFromFileOrDie(filename, &kpart_size);
+
+		kblob_data = UnpackKPart(kpart_data, kpart_size, opt_pad,
+					 &keyblock, &preamble, &kblob_size);
+
+		if (!kblob_data)
+			Fatal("Unable to unpack kernel partition\n");
+
+		f = fopen(vmlinuz_out_file, "wb");
+		if (!f) {
+			VbExError("Can't open output file %s\n",
+				  vmlinuz_out_file);
+			return 1;
+		}
+
+		/* Now stick 16-bit header followed by kernel block into
+		   output */
+		if (VbGetKernelVmlinuzHeader(preamble,
+					     &vmlinuz_header_address,
+					     &vmlinuz_header_size)
+		    != VBOOT_SUCCESS) {
+			Fatal("Unable to retrieve Vmlinuz Header!");
+		}
+		if (vmlinuz_header_size) {
+			// verify that the 16-bit header is included in the
+			// kblob (to make sure that it's included in the
+			// signature)
+			if (VerifyVmlinuzInsideKBlob(preamble->body_load_address,
+						     kblob_size,
+						     vmlinuz_header_address,
+						     vmlinuz_header_size)) {
+				VbExError("Vmlinuz header not signed!\n");
+				fclose(f);
+				unlink(vmlinuz_out_file);
+				return 1;
+			}
+
+			i = (1 != fwrite((void*)(uintptr_t)
+					 vmlinuz_header_address,
+					 vmlinuz_header_size,
+					 1,
+					 f));
+		}
+		i = i || (1 != fwrite(kblob_data,
+				      kblob_size,
+				      1,
+				      f));
+		if (i) {
+			VbExError("Can't write output file %s\n",
+				  vmlinuz_out_file);
+			fclose(f);
+			unlink(vmlinuz_out_file);
+			return 1;
+		}
+
+		fclose(f);
+		return 1;
 	}
 
 	fprintf(stderr,
-		"You must specify a mode: --pack, --repack or --verify\n");
+		"You must specify a mode: "
+		"--pack, --repack, --verify, or --get-vmlinuz\n");
 	print_help(argv[0]);
 	return 1;
 }
diff --git a/futility/vb1_helper.c b/futility/vb1_helper.c
index b337672..dd219ef 100644
--- a/futility/vb1_helper.c
+++ b/futility/vb1_helper.c
@@ -20,7 +20,8 @@
 /* Here are globals containing all the bits & pieces I'm working on.
  *
  * kernel vblock    = keyblock + kernel preamble + padding to 64K (or whatever)
- * kernel blob      = 32-bit kernel + config file + params + bootloader stub
+ * kernel blob      = 32-bit kernel + config file + params + bootloader stub +
+ *                    vmlinuz_header
  * kernel partition = kernel vblock + kernel blob
  *
  * The VbKernelPreambleHeader.preamble_size includes the padding.
@@ -41,8 +42,11 @@
 static uint64_t g_param_size;
 static uint8_t *g_bootloader_data;
 static uint64_t g_bootloader_size;
+static uint8_t *g_vmlinuz_header_data;
+static uint64_t g_vmlinuz_header_size;
 
 static uint64_t g_ondisk_bootloader_addr;
+static uint64_t g_ondisk_vmlinuz_header_addr;
 
 
 /*
@@ -163,6 +167,9 @@
 		}
 		kernel32_size = kernel_size - kernel32_start;
 
+		Debug(" kernel16_start=0x%" PRIx64 "\n", 0);
+		Debug(" kernel16_size=0x%" PRIx64 "\n", kernel32_start);
+
 		/* Copy the original zeropage data from kernel_buf into
 		 * g_param_data, then tweak a few fields for our purposes */
 		params = (struct linux_kernel_params *)(g_param_data);
@@ -206,14 +213,34 @@
 	return 0;
 }
 
-/* Split a kernel blob into separate g_kernel, g_param, g_config, and
- * g_bootloader parts. */
+/* Split a kernel blob into separate g_kernel, g_param, g_config,
+ * g_bootloader, and g_vmlinuz_header parts. */
 static void UnpackKernelBlob(uint8_t *kernel_blob_data)
 {
 	uint64_t now;
+	uint64_t vmlinuz_header_size = 0;
+	uint64_t vmlinuz_header_address = 0;
 
 	/* We have to work backwards from the end, because the preamble
-	   only describes the bootloader stub. */
+	   only describes the bootloader and vmlinuz stubs. */
+
+	/* Vmlinuz Header is at the end */
+	if (VbGetKernelVmlinuzHeader(g_preamble,
+				     &vmlinuz_header_address,
+				     &vmlinuz_header_size)
+	    != VBOOT_SUCCESS) {
+		fprintf(stderr, "Unable to retrieve Vmlinuz Header!");
+		return;
+	}
+	if (vmlinuz_header_size) {
+		now = vmlinuz_header_address - g_preamble->body_load_address;
+		g_vmlinuz_header_size = vmlinuz_header_size;
+		g_vmlinuz_header_data = kernel_blob_data + now;
+
+		Debug("vmlinuz_header_size     = 0x%" PRIx64 "\n",
+		      g_vmlinuz_header_size);
+		Debug("vmlinuz_header_ofs      = 0x%" PRIx64 "\n", now);
+	}
 
 	/* Where does the bootloader stub begin? */
 	now = g_preamble->bootloader_address - g_preamble->body_load_address;
@@ -273,6 +300,8 @@
 {
 	VbKeyBlockHeader *keyblock;
 	VbKernelPreambleHeader *preamble;
+	uint64_t vmlinuz_header_size = 0;
+	uint64_t vmlinuz_header_address = 0;
 	uint64_t now = 0;
 
 	/* Sanity-check the keyblock */
@@ -319,6 +348,21 @@
 	g_preamble = preamble;
 	g_ondisk_bootloader_addr = g_preamble->bootloader_address;
 
+	if (VbGetKernelVmlinuzHeader(preamble,
+				     &vmlinuz_header_address,
+				     &vmlinuz_header_size)
+	    != VBOOT_SUCCESS) {
+		fprintf(stderr, "Unable to retrieve Vmlinuz Header!");
+		return NULL;
+	}
+	if (vmlinuz_header_size) {
+		Debug(" vmlinuz_header_address = 0x%" PRIx64 "\n",
+		      vmlinuz_header_address);
+		Debug(" vmlinuz_header_size = 0x%" PRIx64 "\n",
+		      vmlinuz_header_size);
+		g_ondisk_vmlinuz_header_addr = vmlinuz_header_address;
+	}
+
 	Debug("kernel blob is at offset 0x%" PRIx64 "\n", now);
 	g_kernel_blob_data = kpart_data + now;
 	g_kernel_blob_size = preamble->body_signature.data_size;
@@ -367,7 +411,10 @@
 					kernel_body_load_address,
 					g_ondisk_bootloader_addr,
 					g_bootloader_size,
-					body_sig, min_size,
+					body_sig,
+					g_ondisk_vmlinuz_header_addr,
+					g_vmlinuz_header_size,
+					min_size,
 					signpriv_key);
 	if (!preamble) {
 		fprintf(stderr, "Error creating preamble.\n");
@@ -440,6 +487,8 @@
 	VbPublicKey *data_key;
 	RSAPublicKey *rsa;
 	int rv = -1;
+	uint64_t vmlinuz_header_size = 0;
+	uint64_t vmlinuz_header_address = 0;
 
 	if (0 != KeyBlockVerify(g_keyblock, g_keyblock->key_block_size,
 				signpub_key, (0 == signpub_key))) {
@@ -526,6 +575,20 @@
 	printf("  Bootloader size:     0x%" PRIx64 "\n",
 	       g_preamble->bootloader_size);
 
+	if (VbGetKernelVmlinuzHeader(g_preamble,
+				     &vmlinuz_header_address,
+				     &vmlinuz_header_size)
+	    != VBOOT_SUCCESS) {
+		fprintf(stderr, "Unable to retrieve Vmlinuz Header!");
+		goto done;
+	}
+	if (vmlinuz_header_size) {
+		printf("  Vmlinuz header address: 0x%" PRIx64 "\n",
+		       vmlinuz_header_address);
+		printf("  Vmlinuz header size:    0x%" PRIx64 "\n",
+		       vmlinuz_header_size);
+	}
+
 	if (g_preamble->kernel_version < (min_version & 0xFFFF)) {
 		fprintf(stderr,
 			"Kernel version %" PRIu64 " is lower than minimum %"
@@ -567,8 +630,13 @@
 	g_config_size = CROS_CONFIG_SIZE;
 	g_param_size = CROS_PARAMS_SIZE;
 	g_bootloader_size = roundup(bootloader_size, CROS_ALIGN);
-	g_kernel_blob_size = roundup(g_kernel_size, CROS_ALIGN) +
-		g_config_size + g_param_size + g_bootloader_size;
+	g_vmlinuz_header_size = vmlinuz_size-g_kernel_size;
+	g_kernel_blob_size =
+		roundup(g_kernel_size, CROS_ALIGN) +
+		g_config_size                      +
+		g_param_size                       +
+		g_bootloader_size                  +
+		g_vmlinuz_header_size;
 	Debug("g_kernel_blob_size  0x%" PRIx64 "\n", g_kernel_blob_size);
 
 	/* Allocate space for the blob. */
@@ -597,6 +665,18 @@
 	g_ondisk_bootloader_addr = kernel_body_load_address + now;
 	Debug("g_ondisk_bootloader_addr   0x%" PRIx64 "\n",
 	      g_ondisk_bootloader_addr);
+	now += g_bootloader_size;
+
+	if (g_vmlinuz_header_size) {
+		g_vmlinuz_header_data = g_kernel_blob_data + now;
+		Debug("g_vmlinuz_header_size 0x%" PRIx64 " ofs 0x%" PRIx64 "\n",
+		      g_vmlinuz_header_size, now);
+		g_ondisk_vmlinuz_header_addr = kernel_body_load_address + now;
+		Debug("g_ondisk_vmlinuz_header_addr   0x%" PRIx64 "\n",
+		      g_ondisk_vmlinuz_header_addr);
+	}
+
+	Debug("end of kern_blob at kern_blob+0x%" PRIx64 "\n", now);
 
 	/* Copy the kernel and params bits into the correct places */
 	if (0 != PickApartVmlinuz(vmlinuz_buf, vmlinuz_size,
@@ -611,6 +691,11 @@
 	/* Copy the other bits too */
 	Memcpy(g_config_data, config_data, config_size);
 	Memcpy(g_bootloader_data, bootloader_data, bootloader_size);
+	if (g_vmlinuz_header_size) {
+		Memcpy(g_vmlinuz_header_data,
+		       vmlinuz_buf,
+		       g_vmlinuz_header_size);
+	}
 
 	if (blob_size_ptr)
 		*blob_size_ptr = g_kernel_blob_size;
diff --git a/host/lib/host_common.c b/host/lib/host_common.c
index 9f6121d..b9c00cd 100644
--- a/host/lib/host_common.c
+++ b/host/lib/host_common.c
@@ -76,6 +76,8 @@
 	uint64_t bootloader_address,
 	uint64_t bootloader_size,
 	const VbSignature *body_signature,
+	uint64_t vmlinuz_header_address,
+	uint64_t vmlinuz_header_size,
 	uint64_t desired_size,
 	const VbPrivateKey *signing_key)
 {
@@ -107,6 +109,8 @@
 	h->body_load_address = body_load_address;
 	h->bootloader_address = bootloader_address;
 	h->bootloader_size = bootloader_size;
+	h->vmlinuz_header_address = vmlinuz_header_address;
+	h->vmlinuz_header_size = vmlinuz_header_size;
 
 	/* Copy body signature */
 	SignatureInit(&h->body_signature, body_sig_dest,
diff --git a/host/lib/include/host_common.h b/host/lib/include/host_common.h
index 40ce212..b4693f8 100644
--- a/host/lib/include/host_common.h
+++ b/host/lib/include/host_common.h
@@ -50,6 +50,8 @@
 	uint64_t bootloader_address,
 	uint64_t bootloader_size,
 	const VbSignature *body_signature,
+	uint64_t vmlinuz_header_address,
+	uint64_t vmlinuz_header_size,
 	uint64_t desired_size,
 	const VbPrivateKey *signing_key);
 
diff --git a/host/linktest/main.c b/host/linktest/main.c
index 7ad89ee..e24d557 100644
--- a/host/linktest/main.c
+++ b/host/linktest/main.c
@@ -41,7 +41,7 @@
 
   /* host_common.h */
   CreateFirmwarePreamble(0, 0, 0, 0, 0);
-  CreateKernelPreamble(0, 0, 0, 0, 0, 0, 0);
+  CreateKernelPreamble(0, 0, 0, 0, 0, 0, 0, 0, 0);
 
   /* file_keys.h */
   BufferFromFile(0, 0);
diff --git a/tests/vboot_common2_tests.c b/tests/vboot_common2_tests.c
index 220391c..3a2b59f 100644
--- a/tests/vboot_common2_tests.c
+++ b/tests/vboot_common2_tests.c
@@ -128,7 +128,7 @@
 
 	rsa = PublicKeyToRSA(public_key);
 	hdr = CreateKernelPreamble(0x1234, 0x100000, 0x300000, 0x4000, body_sig,
-				   0, private_key);
+				   0, 0, 0, private_key);
 	TEST_NEQ(hdr && rsa, 0, "VerifyKernelPreamble() prerequisites");
 	if (!hdr)
 		return;
diff --git a/tests/vboot_common_tests.c b/tests/vboot_common_tests.c
index 7cfea90..8fd021a 100644
--- a/tests/vboot_common_tests.c
+++ b/tests/vboot_common_tests.c
@@ -31,7 +31,7 @@
 	TEST_EQ(EXPECTED_VBFIRMWAREPREAMBLEHEADER2_1_SIZE,
 		sizeof(VbFirmwarePreambleHeader),
 		"sizeof(VbFirmwarePreambleHeader)");
-	TEST_EQ(EXPECTED_VBKERNELPREAMBLEHEADER_SIZE,
+	TEST_EQ(EXPECTED_VBKERNELPREAMBLEHEADER2_1_SIZE,
 		sizeof(VbKernelPreambleHeader),
 		"sizeof(VbKernelPreambleHeader)");