diff --git a/firmware/include/vboot_struct.h b/firmware/include/vboot_struct.h index 9e845ef8e7..09abf13885 100644 --- a/firmware/include/vboot_struct.h +++ b/firmware/include/vboot_struct.h @@ -180,7 +180,7 @@ typedef struct VbFirmwarePreambleHeader { /****************************************************************************/ #define KERNEL_PREAMBLE_HEADER_VERSION_MAJOR 2 -#define KERNEL_PREAMBLE_HEADER_VERSION_MINOR 1 +#define KERNEL_PREAMBLE_HEADER_VERSION_MINOR 2 /* Preamble block for kernel, version 2.0 * @@ -260,9 +260,17 @@ typedef struct VbKernelPreambleHeader { /* Size of 16-bit header for vmlinuz in bytes. Readers should return 0 for header version < 2.1 */ uint64_t vmlinuz_header_size; + /* + * Flags passed in by the signer. Readers should return 0 for header + * version < 2.2. Flags field is currently defined as: + * [31:2] - Reserved (for future use) + * [1:0] - Kernel image type (0b00 - CrOS, 0b01 - bootimg) + */ + uint32_t flags; } __attribute__((packed)) VbKernelPreambleHeader; #define EXPECTED_VBKERNELPREAMBLEHEADER2_1_SIZE 112 +#define EXPECTED_VBKERNELPREAMBLEHEADER2_2_SIZE 116 /****************************************************************************/ diff --git a/firmware/lib/include/vboot_common.h b/firmware/lib/include/vboot_common.h index f792d1a243..4d50ff62d0 100644 --- a/firmware/lib/include/vboot_common.h +++ b/firmware/lib/include/vboot_common.h @@ -41,6 +41,8 @@ enum { VBOOT_PREAMBLE_SIGNATURE, /* Shared data is invalid. */ VBOOT_SHARED_DATA_INVALID, + /* Kernel Preamble does not contain flags */ + VBOOT_KERNEL_PREAMBLE_NO_FLAGS, VBOOT_ERROR_MAX, }; extern const char *kVbootErrors[VBOOT_ERROR_MAX]; @@ -160,6 +162,15 @@ int VbGetKernelVmlinuzHeader(const VbKernelPreambleHeader *preamble, uint64_t *vmlinuz_header_address, uint64_t *vmlinuz_header_size); +/** + * Checks if the kernel preamble has flags field. This is available only if the + * Kernel Preamble Header version >=2.2. If give a header of 2.1 or lower, it + * will return VBOOT_KERNEL_PREAMBLE_NO_FLAGS. + * + * Returns VBOOT_SUCCESS if version is >=2.2. + */ +int VbKernelHasFlags(const VbKernelPreambleHeader *preamble); + /** * Verify that the Vmlinuz Header is contained inside of the kernel blob. * diff --git a/firmware/lib/vboot_common.c b/firmware/lib/vboot_common.c index 2cb01f37a1..226cdb7bd9 100644 --- a/firmware/lib/vboot_common.c +++ b/firmware/lib/vboot_common.c @@ -437,13 +437,20 @@ int VerifyKernelPreamble(const VbKernelPreambleHeader *preamble, /* * If the preamble header version is at least 2.1, verify we have space - * for the added fields from 2.1. + * for the added fields from >2.1. */ if (preamble->header_version_minor >= 1) { - if(size < EXPECTED_VBKERNELPREAMBLEHEADER2_1_SIZE) { + if((preamble->header_version_minor == 1) && + (size < EXPECTED_VBKERNELPREAMBLEHEADER2_1_SIZE)) { VBDEBUG(("Not enough data for preamble header 2.1.\n")); return VBOOT_PREAMBLE_INVALID; } + + if((preamble->header_version_minor == 2) && + (size < EXPECTED_VBKERNELPREAMBLEHEADER2_2_SIZE)) { + VBDEBUG(("Not enough data for preamble header 2.2.\n")); + return VBOOT_PREAMBLE_INVALID; + } } /* Success */ @@ -469,6 +476,14 @@ int VbGetKernelVmlinuzHeader(const VbKernelPreambleHeader *preamble, return VBOOT_SUCCESS; } +int VbKernelHasFlags(const VbKernelPreambleHeader *preamble) +{ + if (preamble->header_version_minor > 1) + return VBOOT_SUCCESS; + + return VBOOT_KERNEL_PREAMBLE_NO_FLAGS; +} + int VerifyVmlinuzInsideKBlob(uint64_t kblob, uint64_t kblob_size, uint64_t header, uint64_t header_size) { diff --git a/futility/cmd_show.c b/futility/cmd_show.c index dc7c814183..b6c2574ac0 100644 --- a/futility/cmd_show.c +++ b/futility/cmd_show.c @@ -419,6 +419,7 @@ int futil_cb_show_kernel_preamble(struct futil_traverse_state_s *state) int retval = 0; uint64_t vmlinuz_header_size = 0; uint64_t vmlinuz_header_address = 0; + uint32_t flags = 0; /* Check the hash... */ if (VBOOT_SUCCESS != KeyBlockVerify(key_block, len, NULL, 1)) { @@ -483,6 +484,10 @@ int futil_cb_show_kernel_preamble(struct futil_traverse_state_s *state) vmlinuz_header_size); } + if (VbKernelHasFlags(preamble) == VBOOT_SUCCESS) + flags = preamble->flags; + printf(" Flags: 0x%" PRIx32 "\n", flags); + /* Verify kernel body */ if (option.fv) { /* It's in a separate file, which we've already read in */ diff --git a/futility/cmd_sign.c b/futility/cmd_sign.c index a960abd6ab..2d247bcd37 100644 --- a/futility/cmd_sign.c +++ b/futility/cmd_sign.c @@ -219,7 +219,7 @@ int futil_cb_create_kernel_part(struct futil_traverse_state_s *state) vblock_data = SignKernelBlob(kblob_data, kblob_size, option.padding, option.version, option.kloadaddr, option.keyblock, option.signprivate, - &vblock_size); + option.flags, &vblock_size); if (!vblock_data) { fprintf(stderr, "Unable to sign kernel blob\n"); free(kblob_data); @@ -288,6 +288,12 @@ int futil_cb_resign_kernel_part(struct futil_traverse_state_s *state) if (!option.version_specified) option.version = preamble->kernel_version; + /* Preserve the flags if not specified */ + if (VbKernelHasFlags(preamble) == VBOOT_SUCCESS) { + if (option.flags_specified == 0) + option.flags = preamble->flags; + } + /* Replace the keyblock if asked */ if (option.keyblock) keyblock = option.keyblock; @@ -296,7 +302,7 @@ int futil_cb_resign_kernel_part(struct futil_traverse_state_s *state) vblock_data = SignKernelBlob(kblob_data, kblob_size, option.padding, option.version, option.kloadaddr, keyblock, option.signprivate, - &vblock_size); + option.flags, &vblock_size); if (!vblock_data) { fprintf(stderr, "Unable to sign kernel blob\n"); return 1; @@ -612,7 +618,8 @@ static const char usage_new_kpart[] = "\n" " --pad NUM The vblock padding size in bytes\n" " (default 0x%x)\n" " --vblockonly Emit just the vblock (requires a\n" - " distinct outfile)\n"; + " distinct outfile)\n" + " -f|--flags NUM The preamble flags value\n"; static const char usage_old_kpart[] = "\n" "-----------------------------------------------------------------\n" @@ -634,6 +641,7 @@ static const char usage_old_kpart[] = "\n" " [--outfile] OUTFILE Output kernel partition or vblock\n" " --vblockonly Emit just the vblock (requires a\n" " distinct OUTFILE)\n" + " -f|--flags NUM The preamble flags value\n" "\n"; static void print_help(const char *prog) diff --git a/futility/cmd_vbutil_kernel.c b/futility/cmd_vbutil_kernel.c index ae4fd3f9ce..3322e4b8c0 100644 --- a/futility/cmd_vbutil_kernel.c +++ b/futility/cmd_vbutil_kernel.c @@ -63,6 +63,7 @@ enum { OPT_VERBOSE, OPT_MINVERSION, OPT_VMLINUZ_OUT, + OPT_FLAGS, }; static const struct option long_opts[] = { @@ -86,6 +87,7 @@ static const struct option long_opts[] = { {"verbose", 0, &opt_verbose, 1}, {"debug", 0, &debugging_enabled, 1}, {"vmlinuz-out", 1, 0, OPT_VMLINUZ_OUT}, + {"flags", 1, 0, OPT_FLAGS}, {NULL, 0, 0, 0} }; @@ -109,6 +111,7 @@ static const char usage[] = " --kloadaddr
Assign kernel body load address\n" " --pad