summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShelley Chen <shchen@chromium.org>2015-01-08 09:13:44 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-01-23 21:32:12 +0000
commitf1f53b3732f235da15a50080db6e7bbd4666e390 (patch)
treeedddd76b155d86824fe33934a3d427914987b7ef
parentf242ad0f6fcfc9dc9195af06fe79301a9bd74113 (diff)
downloadvboot-f1f53b3732f235da15a50080db6e7bbd4666e390.tar.gz
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>
-rw-r--r--firmware/include/vboot_struct.h55
-rw-r--r--firmware/lib/include/vboot_common.h19
-rw-r--r--firmware/lib/vboot_common.c44
-rw-r--r--futility/cmd_show.c15
-rw-r--r--futility/cmd_vbutil_kernel.c92
-rw-r--r--futility/vb1_helper.c99
-rw-r--r--host/lib/host_common.c4
-rw-r--r--host/lib/include/host_common.h2
-rw-r--r--host/linktest/main.c2
-rw-r--r--tests/vboot_common2_tests.c2
-rw-r--r--tests/vboot_common_tests.c2
11 files changed, 318 insertions, 18 deletions
diff --git a/firmware/include/vboot_struct.h b/firmware/include/vboot_struct.h
index 923e63cd..9e845ef8 100644
--- a/firmware/include/vboot_struct.h
+++ b/firmware/include/vboot_struct.h
@@ -180,9 +180,9 @@ typedef struct VbFirmwarePreambleHeader {
/****************************************************************************/
#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 @@ typedef struct VbFirmwarePreambleHeader {
* 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 @@ typedef struct VbKernelPreambleHeader {
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 83064d2b..f792d1a2 100644
--- a/firmware/lib/include/vboot_common.h
+++ b/firmware/lib/include/vboot_common.h
@@ -149,6 +149,25 @@ int VerifyKernelPreamble(const VbKernelPreambleHeader *preamble,
/**
+ * 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 3811e1ef..2cb01f37 100644
--- a/firmware/lib/vboot_common.c
+++ b/firmware/lib/vboot_common.c
@@ -435,10 +435,54 @@ int VerifyKernelPreamble(const VbKernelPreambleHeader *preamble,
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 f2262698..7f0e488f 100644
--- a/futility/cmd_show.c
+++ b/futility/cmd_show.c
@@ -385,6 +385,8 @@ int futil_cb_show_kernel_preamble(struct futil_traverse_state_s *state)
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 @@ int futil_cb_show_kernel_preamble(struct futil_traverse_state_s *state)
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 786344fb..3b2643e4 100644
--- a/futility/cmd_vbutil_kernel.c
+++ b/futility/cmd_vbutil_kernel.c
@@ -43,6 +43,7 @@ enum {
OPT_MODE_PACK = 1000,
OPT_MODE_REPACK,
OPT_MODE_VERIFY,
+ OPT_MODE_GET_VMLINUZ,
OPT_ARCH,
OPT_OLDBLOB,
OPT_KLOADADDR,
@@ -57,12 +58,14 @@ enum {
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 @@ static const struct option long_opts[] = {
{"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 @@ static const char usage[] =
" 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 @@ static int do_vbutil_kernel(int argc, char *argv[])
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 @@ static int do_vbutil_kernel(int argc, char *argv[])
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 @@ static int do_vbutil_kernel(int argc, char *argv[])
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 @@ static int do_vbutil_kernel(int argc, char *argv[])
parse_error = 1;
}
break;
+ case OPT_VMLINUZ_OUT:
+ vmlinuz_out_file = optarg;
}
}
@@ -519,10 +534,79 @@ static int do_vbutil_kernel(int argc, char *argv[])
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 b3376726..dd219ef8 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 uint8_t *g_param_data;
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 @@ static int PickApartVmlinuz(uint8_t *kernel_buf, uint64_t kernel_size,
}
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 @@ static int PickApartVmlinuz(uint8_t *kernel_buf, uint64_t kernel_size,
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 @@ uint8_t *UnpackKPart(uint8_t *kpart_data, uint64_t kpart_size,
{
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 @@ uint8_t *UnpackKPart(uint8_t *kpart_data, uint64_t kpart_size,
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 @@ uint8_t *SignKernelBlob(uint8_t *kernel_blob, uint64_t kernel_size,
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 @@ int VerifyKernelBlob(uint8_t *kernel_blob,
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 @@ int VerifyKernelBlob(uint8_t *kernel_blob,
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 @@ uint8_t *CreateKernelBlob(uint8_t *vmlinuz_buf, uint64_t vmlinuz_size,
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 @@ uint8_t *CreateKernelBlob(uint8_t *vmlinuz_buf, uint64_t vmlinuz_size,
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 @@ uint8_t *CreateKernelBlob(uint8_t *vmlinuz_buf, uint64_t vmlinuz_size,
/* 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 9f6121de..b9c00cde 100644
--- a/host/lib/host_common.c
+++ b/host/lib/host_common.c
@@ -76,6 +76,8 @@ VbKernelPreambleHeader *CreateKernelPreamble(
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 @@ VbKernelPreambleHeader *CreateKernelPreamble(
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 40ce212a..b4693f84 100644
--- a/host/lib/include/host_common.h
+++ b/host/lib/include/host_common.h
@@ -50,6 +50,8 @@ VbKernelPreambleHeader *CreateKernelPreamble(
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 7ad89ee6..e24d5579 100644
--- a/host/linktest/main.c
+++ b/host/linktest/main.c
@@ -41,7 +41,7 @@ int main(void)
/* 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 220391cb..3a2b59f3 100644
--- a/tests/vboot_common2_tests.c
+++ b/tests/vboot_common2_tests.c
@@ -128,7 +128,7 @@ static void VerifyKernelPreambleTest(const VbPublicKey *public_key,
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 7cfea90e..8fd021a1 100644
--- a/tests/vboot_common_tests.c
+++ b/tests/vboot_common_tests.c
@@ -31,7 +31,7 @@ static void StructPackingTest(void)
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)");