diff options
-rw-r--r-- | firmware/lib/ec_sync.c | 22 | ||||
-rw-r--r-- | firmware/lib/ec_sync_all.c | 5 | ||||
-rw-r--r-- | firmware/lib/include/ec_sync.h | 12 | ||||
-rw-r--r-- | firmware/lib/include/load_kernel_fw.h | 8 | ||||
-rw-r--r-- | firmware/lib/include/vboot_kernel.h | 11 | ||||
-rw-r--r-- | firmware/lib/vboot_api_kernel.c | 372 | ||||
-rw-r--r-- | tests/vboot_api_devmode_tests.c | 4 | ||||
-rw-r--r-- | tests/vboot_api_kernel2_tests.c | 90 | ||||
-rw-r--r-- | tests/vboot_api_kernel4_tests.c | 10 | ||||
-rw-r--r-- | tests/vboot_api_kernel_tests.c | 12 | ||||
-rw-r--r-- | tests/vboot_kernel_tests.c | 30 | ||||
-rw-r--r-- | tests/verify_kernel.c | 4 | ||||
-rw-r--r-- | utility/load_kernel_test.c | 34 |
13 files changed, 309 insertions, 305 deletions
diff --git a/firmware/lib/ec_sync.c b/firmware/lib/ec_sync.c index d263c28f..77687a40 100644 --- a/firmware/lib/ec_sync.c +++ b/firmware/lib/ec_sync.c @@ -457,3 +457,25 @@ VbError_t ec_sync_phase2(struct vb2_context *ctx, VbCommonParams *cparams) return VBERROR_SUCCESS; } + +VbError_t ec_sync_phase3(struct vb2_context *ctx, VbCommonParams *cparams) +{ + VbSharedDataHeader *shared = + (VbSharedDataHeader *)cparams->shared_data_blob; + + /* EC verification (and possibly updating / jumping) is done */ + VbError_t rv = VbExEcVbootDone(!!shared->recovery_reason); + if (rv) + return rv; + + /* Check if we need to cut-off battery. This must be done after EC + * firmware updating and before kernel started. */ + if (vb2_nv_get(ctx, VB2_NV_BATTERY_CUTOFF_REQUEST)) { + VB2_DEBUG("Request to cut-off battery\n"); + vb2_nv_set(ctx, VB2_NV_BATTERY_CUTOFF_REQUEST, 0); + VbExEcBatteryCutOff(); + return VBERROR_SHUTDOWN_REQUESTED; + } + + return VBERROR_SUCCESS; +} diff --git a/firmware/lib/ec_sync_all.c b/firmware/lib/ec_sync_all.c index 2ad61035..a32d34dd 100644 --- a/firmware/lib/ec_sync_all.c +++ b/firmware/lib/ec_sync_all.c @@ -77,5 +77,10 @@ VbError_t ec_sync_all(struct vb2_context *ctx, struct VbCommonParams *cparams) return VBERROR_VGA_OPROM_MISMATCH; } + /* Do EC sync phase 3; this completes synd and handles battery cutoff */ + rv = ec_sync_phase3(ctx, cparams); + if (rv) + return rv; + return VBERROR_SUCCESS; } diff --git a/firmware/lib/include/ec_sync.h b/firmware/lib/include/ec_sync.h index dd133920..b629b2d5 100644 --- a/firmware/lib/include/ec_sync.h +++ b/firmware/lib/include/ec_sync.h @@ -60,6 +60,18 @@ int ec_will_update_slowly(struct vb2_context *ctx, VbError_t ec_sync_phase2(struct vb2_context *ctx, struct VbCommonParams *cparams); + +/** + * EC sync, phase 3 + * + * This completes EC sync and handles battery cutoff if needed. + * + * @param ctx Vboot2 context + * @param cparams Vboot common params + * @return VBERROR_SUCCESS or non-zero error code. + */ +VbError_t ec_sync_phase3(struct vb2_context *ctx, VbCommonParams *cparams); + /** * Sync all EC devices to expected versions. * diff --git a/firmware/lib/include/load_kernel_fw.h b/firmware/lib/include/load_kernel_fw.h index aeecb448..ca49b3c6 100644 --- a/firmware/lib/include/load_kernel_fw.h +++ b/firmware/lib/include/load_kernel_fw.h @@ -17,10 +17,6 @@ struct vb2_context; /* Interface provided by verified boot library to BDS */ /* Boot flags for LoadKernel().boot_flags */ -/* Developer switch is on */ -#define BOOT_FLAG_DEVELOPER (0x01ULL) -/* In recovery mode */ -#define BOOT_FLAG_RECOVERY (0x02ULL) /* GPT is external */ #define BOOT_FLAG_EXTERNAL_GPT (0x04ULL) @@ -28,10 +24,6 @@ struct RollbackSpaceFwmp; typedef struct LoadKernelParams { /* Inputs to LoadKernel() */ - /* Pointer to GBB data */ - void *gbb_data; - /* Size of GBB data in bytes */ - uint64_t gbb_size; /* Disk handle for current device */ VbExDiskHandle_t disk_handle; /* Bytes per lba sector on current device */ diff --git a/firmware/lib/include/vboot_kernel.h b/firmware/lib/include/vboot_kernel.h index 1c9dafcb..1c3221cb 100644 --- a/firmware/lib/include/vboot_kernel.h +++ b/firmware/lib/include/vboot_kernel.h @@ -29,13 +29,11 @@ void VbApiKernelFree(VbCommonParams *cparams); * * @param ctx Vboot context * @param cparams Vboot common params - * @param p Parameters for loading kernel * @param get_info_flags Flags to pass to VbExDiskGetInfo() * @return VBERROR_SUCCESS, VBERROR_NO_DISK_FOUND if no disks of the specified * type were found, or other non-zero VBERROR_ codes for other failures. */ uint32_t VbTryLoadKernel(struct vb2_context *ctx, VbCommonParams *cparams, - LoadKernelParams *p, uint32_t get_info_flags); /* Flags for VbUserConfirms() */ @@ -62,19 +60,16 @@ int VbUserConfirms(struct vb2_context *ctx, VbCommonParams *cparams, /** * Handle a normal boot. */ -VbError_t VbBootNormal(struct vb2_context *ctx, VbCommonParams *cparams, - LoadKernelParams *p); +VbError_t VbBootNormal(struct vb2_context *ctx, VbCommonParams *cparams); /** * Handle a developer-mode boot. */ -VbError_t VbBootDeveloper(struct vb2_context *ctx, VbCommonParams *cparams, - LoadKernelParams *p); +VbError_t VbBootDeveloper(struct vb2_context *ctx, VbCommonParams *cparams); /** * Handle a recovery-mode boot. */ -VbError_t VbBootRecovery(struct vb2_context *ctx, VbCommonParams *cparams, - LoadKernelParams *p); +VbError_t VbBootRecovery(struct vb2_context *ctx, VbCommonParams *cparams); #endif /* VBOOT_REFERENCE_VBOOT_KERNEL_H_ */ diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c index 7e48daae..5dad3b86 100644 --- a/firmware/lib/vboot_api_kernel.c +++ b/firmware/lib/vboot_api_kernel.c @@ -30,6 +30,9 @@ /* Global variables */ static VbNvContext vnc; static struct RollbackSpaceFwmp fwmp; +static LoadKernelParams lkp; +static struct vb2_context ctx; +static uint8_t *unaligned_workbuf; #ifdef CHROMEOS_ENVIRONMENT /* Global variable accessors for unit tests */ @@ -38,6 +41,12 @@ struct RollbackSpaceFwmp *VbApiKernelGetFwmp(void) { return &fwmp; } + +struct LoadKernelParams *VbApiKernelGetParams(void) +{ + return &lkp; +} + #endif /** @@ -122,7 +131,6 @@ static void VbTryLegacy(int allowed) * type were found, or other non-zero VBERROR_ codes for other failures. */ uint32_t VbTryLoadKernel(struct vb2_context *ctx, VbCommonParams *cparams, - LoadKernelParams *p, uint32_t get_info_flags) { VbError_t retval = VBERROR_UNKNOWN; @@ -133,7 +141,9 @@ uint32_t VbTryLoadKernel(struct vb2_context *ctx, VbCommonParams *cparams, VBDEBUG(("VbTryLoadKernel() start, get_info_flags=0x%x\n", (unsigned)get_info_flags)); - p->disk_handle = NULL; + lkp.fwmp = &fwmp; + lkp.nv_context = &vnc; + lkp.disk_handle = NULL; /* Find disks */ if (VBERROR_SUCCESS != VbExDiskGetInfo(&disk_info, &disk_count, @@ -168,14 +178,14 @@ uint32_t VbTryLoadKernel(struct vb2_context *ctx, VbCommonParams *cparams, disk_info[i].flags)); continue; } - p->disk_handle = disk_info[i].handle; - p->bytes_per_lba = disk_info[i].bytes_per_lba; - p->gpt_lba_count = disk_info[i].lba_count; - p->streaming_lba_count = disk_info[i].streaming_lba_count - ?: p->gpt_lba_count; - p->boot_flags |= disk_info[i].flags & VB_DISK_FLAG_EXTERNAL_GPT + lkp.disk_handle = disk_info[i].handle; + lkp.bytes_per_lba = disk_info[i].bytes_per_lba; + lkp.gpt_lba_count = disk_info[i].lba_count; + lkp.streaming_lba_count = disk_info[i].streaming_lba_count + ?: lkp.gpt_lba_count; + lkp.boot_flags |= disk_info[i].flags & VB_DISK_FLAG_EXTERNAL_GPT ? BOOT_FLAG_EXTERNAL_GPT : 0; - retval = LoadKernel(ctx, p, cparams); + retval = LoadKernel(ctx, &lkp, cparams); VBDEBUG(("VbTryLoadKernel() LoadKernel() = %d\n", retval)); /* @@ -192,10 +202,10 @@ uint32_t VbTryLoadKernel(struct vb2_context *ctx, VbCommonParams *cparams, /* If we didn't find any good kernels, don't return a disk handle. */ if (VBERROR_SUCCESS != retval) { VbSetRecoveryRequest(ctx, VBNV_RECOVERY_RW_NO_KERNEL); - p->disk_handle = NULL; + lkp.disk_handle = NULL; } - VbExDiskFreeInfo(disk_info, p->disk_handle); + VbExDiskFreeInfo(disk_info, lkp.disk_handle); /* * Pass through return code. Recovery reason (if any) has already been @@ -204,11 +214,9 @@ uint32_t VbTryLoadKernel(struct vb2_context *ctx, VbCommonParams *cparams, return retval; } -uint32_t VbTryUsb(struct vb2_context *ctx, VbCommonParams *cparams, - LoadKernelParams *p) +uint32_t VbTryUsb(struct vb2_context *ctx, VbCommonParams *cparams) { - uint32_t retval = VbTryLoadKernel(ctx, cparams, p, - VB_DISK_FLAG_REMOVABLE); + uint32_t retval = VbTryLoadKernel(ctx, cparams, VB_DISK_FLAG_REMOVABLE); if (VBERROR_SUCCESS == retval) { VBDEBUG(("VbBootDeveloper() - booting USB\n")); } else { @@ -295,13 +303,54 @@ int VbUserConfirms(struct vb2_context *ctx, VbCommonParams *cparams, return -1; } -VbError_t test_mockable -VbBootNormal(struct vb2_context *ctx, VbCommonParams *cparams, - LoadKernelParams *p) +VbError_t VbBootNormal(struct vb2_context *ctx, VbCommonParams *cparams) { + VbSharedDataHeader *shared = + (VbSharedDataHeader *)cparams->shared_data_blob; + /* Boot from fixed disk only */ - VBDEBUG(("Entering %s()\n", __func__)); - return VbTryLoadKernel(ctx, cparams, p, VB_DISK_FLAG_FIXED); + VB2_DEBUG("Entering %s()\n", __func__); + + VbError_t rv = VbTryLoadKernel(ctx, cparams, VB_DISK_FLAG_FIXED); + + VB2_DEBUG("Checking if TPM kernel version needs advancing\n"); + + if ((1 == shared->firmware_index) && (shared->flags & VBSD_FWB_TRIED)) { + /* + * Special cases for when we're trying a new firmware B. These + * are needed because firmware updates also usually change the + * kernel key, which means that the B firmware can only boot a + * new kernel, and the old firmware in A can only boot the + * previous kernel. + * + * Don't advance the TPM if we're trying a new firmware B, + * because we don't yet know if the new kernel will + * successfully boot. We still want to be able to fall back to + * the previous firmware+kernel if the new firmware+kernel + * fails. + * + * If we found only invalid kernels, reboot and try again. + * This allows us to fall back to the previous firmware+kernel + * instead of giving up and going to recovery mode right away. + * We'll still go to recovery mode if we run out of tries and + * the old firmware can't find a kernel it likes. + */ + if (rv == VBERROR_INVALID_KERNEL_FOUND) { + VB2_DEBUG("Trying FW B; only found invalid kernels.\n"); + VbSetRecoveryRequest(ctx, VBNV_RECOVERY_NOT_REQUESTED); + } + + return rv; + } + + if ((shared->kernel_version_tpm > shared->kernel_version_tpm_start) && + RollbackKernelWrite(shared->kernel_version_tpm)) { + VB2_DEBUG("Error writing kernel versions to TPM.\n"); + VbSetRecoveryRequest(ctx, VBNV_RECOVERY_RW_TPM_W_ERROR); + return VBERROR_TPM_WRITE_KERNEL; + } + + return rv; } static const char dev_disable_msg[] = @@ -309,8 +358,7 @@ static const char dev_disable_msg[] = "For more information, see http://dev.chromium.org/chromium-os/fwmp\n" "\n"; -VbError_t VbBootDeveloper(struct vb2_context *ctx, VbCommonParams *cparams, - LoadKernelParams *p) +VbError_t VbBootDeveloper(struct vb2_context *ctx, VbCommonParams *cparams) { GoogleBinaryBlockHeader *gbb = cparams->gbb; VbSharedDataHeader *shared = @@ -519,7 +567,7 @@ VbError_t VbBootDeveloper(struct vb2_context *ctx, VbCommonParams *cparams, VbDisplayScreen(ctx, cparams, VB_SCREEN_BLANK, 0); if (VBERROR_SUCCESS == - VbTryUsb(ctx, cparams, p)) { + VbTryUsb(ctx, cparams)) { VbAudioClose(audio); return VBERROR_SUCCESS; } else { @@ -547,7 +595,7 @@ VbError_t VbBootDeveloper(struct vb2_context *ctx, VbCommonParams *cparams, } if ((use_usb && !ctrl_d_pressed) && allow_usb) { - if (VBERROR_SUCCESS == VbTryUsb(ctx, cparams, p)) { + if (VBERROR_SUCCESS == VbTryUsb(ctx, cparams)) { VbAudioClose(audio); return VBERROR_SUCCESS; } @@ -556,7 +604,7 @@ VbError_t VbBootDeveloper(struct vb2_context *ctx, VbCommonParams *cparams, /* Timeout or Ctrl+D; attempt loading from fixed disk */ VBDEBUG(("VbBootDeveloper() - trying fixed disk\n")); VbAudioClose(audio); - return VbTryLoadKernel(ctx, cparams, p, VB_DISK_FLAG_FIXED); + return VbTryLoadKernel(ctx, cparams, VB_DISK_FLAG_FIXED); } /* Delay in recovery mode */ @@ -564,8 +612,7 @@ VbError_t VbBootDeveloper(struct vb2_context *ctx, VbCommonParams *cparams, #define REC_KEY_DELAY 20 /* Check keys every 20ms */ #define REC_MEDIA_INIT_DELAY 500 /* Check removable media every 500ms */ -VbError_t VbBootRecovery(struct vb2_context *ctx, VbCommonParams *cparams, - LoadKernelParams *p) +VbError_t VbBootRecovery(struct vb2_context *ctx, VbCommonParams *cparams) { VbSharedDataHeader *shared = (VbSharedDataHeader *)cparams->shared_data_blob; @@ -609,8 +656,7 @@ VbError_t VbBootRecovery(struct vb2_context *ctx, VbCommonParams *cparams, VBDEBUG(("VbBootRecovery() waiting for a recovery image\n")); while (1) { VBDEBUG(("VbBootRecovery() attempting to load kernel2\n")); - retval = VbTryLoadKernel(ctx, cparams, p, - VB_DISK_FLAG_REMOVABLE); + retval = VbTryLoadKernel(ctx, cparams, VB_DISK_FLAG_REMOVABLE); /* * Clear recovery requests from failed kernel loading, since @@ -724,60 +770,35 @@ void VbApiKernelFree(VbCommonParams *cparams) } } -VbError_t VbSelectAndLoadKernel(VbCommonParams *cparams, - VbSelectAndLoadKernelParams *kparams) +static VbError_t vb2_kernel_setup(VbCommonParams *cparams, + VbSelectAndLoadKernelParams *kparams) { VbSharedDataHeader *shared = (VbSharedDataHeader *)cparams->shared_data_blob; - VbError_t retval = VBERROR_SUCCESS; - LoadKernelParams p; - uint32_t tpm_status = 0; /* Start timer */ shared->timer_vb_select_and_load_kernel_enter = VbExGetTimer(); - VbNvLoad(); - - /* Fill in params for calls to LoadKernel() */ - memset(&p, 0, sizeof(p)); - p.gbb_data = cparams->gbb_data; - p.gbb_size = cparams->gbb_size; - p.fwmp = &fwmp; - p.nv_context = &vnc; - - /* - * This could be set to NULL, in which case the vboot header - * information about the load address and size will be used. - */ - p.kernel_buffer = kparams->kernel_buffer; - p.kernel_buffer_size = kparams->kernel_buffer_size; - - /* Set up boot flags */ - p.boot_flags = 0; - if (shared->flags & VBSD_BOOT_DEV_SWITCH_ON) - p.boot_flags |= BOOT_FLAG_DEVELOPER; - if (shared->recovery_reason) - p.boot_flags |= BOOT_FLAG_RECOVERY; - /* * Set up vboot context. * * TODO: Propagate this up to higher API levels, and use more of the * context fields (e.g. secdatak) and flags. */ - struct vb2_context ctx; memset(&ctx, 0, sizeof(ctx)); + + VbNvLoad(); memcpy(ctx.nvdata, vnc.raw, VB2_NVDATA_SIZE); - if (p.boot_flags & BOOT_FLAG_RECOVERY) + if (shared->recovery_reason) ctx.flags |= VB2_CONTEXT_RECOVERY_MODE; - if (p.boot_flags & BOOT_FLAG_DEVELOPER) + if (shared->flags & VBSD_BOOT_DEV_SWITCH_ON) ctx.flags |= VB2_CONTEXT_DEVELOPER_MODE; ctx.workbuf_size = VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE + VB2_WORKBUF_ALIGN; - uint8_t *unaligned_workbuf = ctx.workbuf = malloc(ctx.workbuf_size); + unaligned_workbuf = ctx.workbuf = malloc(ctx.workbuf_size); if (!unaligned_workbuf) { VB2_DEBUG("%s: Can't allocate work buffer\n", __func__); VbSetRecoveryRequest(&ctx, VB2_RECOVERY_RW_SHARED_DATA); @@ -802,6 +823,20 @@ VbError_t VbSelectAndLoadKernel(VbCommonParams *cparams, struct vb2_shared_data *sd = vb2_get_sd(&ctx); sd->recovery_reason = shared->recovery_reason; + /* + * If we're in recovery mode just to do memory retraining, all we + * need to do is reboot. + */ + if (shared->recovery_reason == VBNV_RECOVERY_TRAIN_AND_REBOOT) { + VB2_DEBUG("Reboot after retraining in recovery.\n"); + return VBERROR_REBOOT_REQUIRED; + } + + /* Fill in params for calls to LoadKernel() */ + memset(&lkp, 0, sizeof(lkp)); + lkp.kernel_buffer = kparams->kernel_buffer; + lkp.kernel_buffer_size = kparams->kernel_buffer_size; + /* Clear output params in case we fail */ kparams->disk_handle = NULL; kparams->partition_number = 0; @@ -810,161 +845,73 @@ VbError_t VbSelectAndLoadKernel(VbCommonParams *cparams, kparams->flags = 0; memset(kparams->partition_guid, 0, sizeof(kparams->partition_guid)); + /* Read GBB header, since we'll needs flags from it */ cparams->bmp = NULL; cparams->gbb = malloc(sizeof(*cparams->gbb)); - retval = VbGbbReadHeader_static(cparams, cparams->gbb); - if (VBERROR_SUCCESS != retval) - goto VbSelectAndLoadKernel_exit; - - /* Do EC software sync if necessary */ - retval = ec_sync_all(&ctx, cparams); - if (retval != VBERROR_SUCCESS) - goto VbSelectAndLoadKernel_exit; - - /* EC verification (and possibily updating / jumping) is done */ - retval = VbExEcVbootDone(!!shared->recovery_reason); - if (retval != VBERROR_SUCCESS) - goto VbSelectAndLoadKernel_exit; - - /* Check if we need to cut-off battery. This must be done after EC - * firmware updating and before kernel started. */ - if (vb2_nv_get(&ctx, VB2_NV_BATTERY_CUTOFF_REQUEST)) { - VBDEBUG(("Request to cut-off battery\n")); - vb2_nv_set(&ctx, VB2_NV_BATTERY_CUTOFF_REQUEST, 0); - VbExEcBatteryCutOff(); - retval = VBERROR_SHUTDOWN_REQUESTED; - goto VbSelectAndLoadKernel_exit; - } + uint32_t retval = VbGbbReadHeader_static(cparams, cparams->gbb); + if (retval) + return retval; /* Read kernel version from the TPM. Ignore errors in recovery mode. */ - tpm_status = RollbackKernelRead(&shared->kernel_version_tpm); - if (0 != tpm_status) { - VBDEBUG(("Unable to get kernel versions from TPM\n")); + if (RollbackKernelRead(&shared->kernel_version_tpm)) { + VB2_DEBUG("Unable to get kernel versions from TPM\n"); if (!shared->recovery_reason) { VbSetRecoveryRequest(&ctx, VBNV_RECOVERY_RW_TPM_R_ERROR); - retval = VBERROR_TPM_READ_KERNEL; - goto VbSelectAndLoadKernel_exit; + return VBERROR_TPM_READ_KERNEL; } } + shared->kernel_version_tpm_start = shared->kernel_version_tpm; /* Read FWMP. Ignore errors in recovery mode. */ if (cparams->gbb->flags & GBB_FLAG_DISABLE_FWMP) { memset(&fwmp, 0, sizeof(fwmp)); - tpm_status = 0; - } else { - tpm_status = RollbackFwmpRead(&fwmp); - } - if (0 != tpm_status) { - VBDEBUG(("Unable to get FWMP from TPM\n")); + } else if (RollbackFwmpRead(&fwmp)) { + VB2_DEBUG("Unable to get FWMP from TPM\n"); if (!shared->recovery_reason) { VbSetRecoveryRequest(&ctx, VBNV_RECOVERY_RW_TPM_R_ERROR); - retval = VBERROR_TPM_READ_FWMP; - goto VbSelectAndLoadKernel_exit; + return VBERROR_TPM_READ_FWMP; } } - /* Select boot path */ - if (shared->recovery_reason == VBNV_RECOVERY_TRAIN_AND_REBOOT) { - /* Reboot requested by user recovery code. */ - VBDEBUG(("Reboot requested by user (recovery_reason=%d).\n", - shared->recovery_reason)); - retval = VBERROR_REBOOT_REQUIRED; - } else if (shared->recovery_reason) { - /* Recovery boot */ - retval = VbBootRecovery(&ctx, cparams, &p); - VbExEcEnteringMode(0, VB_EC_RECOVERY); - VbDisplayScreen(&ctx, cparams, VB_SCREEN_BLANK, 0); - - } else if (p.boot_flags & BOOT_FLAG_DEVELOPER) { - /* Developer boot */ - retval = VbBootDeveloper(&ctx, cparams, &p); - VbExEcEnteringMode(0, VB_EC_DEVELOPER); - VbDisplayScreen(&ctx, cparams, VB_SCREEN_BLANK, 0); - - } else { - /* Normal boot */ - VbExEcEnteringMode(0, VB_EC_NORMAL); - retval = VbBootNormal(&ctx, cparams, &p); - - if ((1 == shared->firmware_index) && - (shared->flags & VBSD_FWB_TRIED)) { - /* - * Special cases for when we're trying a new firmware - * B. These are needed because firmware updates also - * usually change the kernel key, which means that the - * B firmware can only boot a new kernel, and the old - * firmware in A can only boot the previous kernel. - * - * Don't advance the TPM if we're trying a new firmware - * B, because we don't yet know if the new kernel will - * successfully boot. We still want to be able to fall - * back to the previous firmware+kernel if the new - * firmware+kernel fails. - * - * If we found only invalid kernels, reboot and try - * again. This allows us to fall back to the previous - * firmware+kernel instead of giving up and going to - * recovery mode right away. We'll still go to - * recovery mode if we run out of tries and the old - * firmware can't find a kernel it likes. - */ - if (VBERROR_INVALID_KERNEL_FOUND == retval) { - VBDEBUG(("Trying firmware B, " - "and only found invalid kernels.\n")); - VbSetRecoveryRequest(&ctx, - VBNV_RECOVERY_NOT_REQUESTED); - goto VbSelectAndLoadKernel_exit; - } - } else { - /* Not trying a new firmware B. */ - - /* See if we need to update the TPM. */ - VBDEBUG(("Checking if TPM kernel version needs " - "advancing\n")); - if (shared->kernel_version_tpm > - shared->kernel_version_tpm_start) { - tpm_status = RollbackKernelWrite( - shared->kernel_version_tpm); - if (0 != tpm_status) { - VBDEBUG(("Error writing kernel " - "versions to TPM.\n")); - VbSetRecoveryRequest(&ctx, - VBNV_RECOVERY_RW_TPM_W_ERROR); - retval = VBERROR_TPM_WRITE_KERNEL; - goto VbSelectAndLoadKernel_exit; - } - } - } - } + return VBERROR_SUCCESS; +} - if (VBERROR_SUCCESS != retval) - goto VbSelectAndLoadKernel_exit; +static VbError_t vb2_kernel_phase4(VbCommonParams *cparams, + VbSelectAndLoadKernelParams *kparams) +{ + VbSharedDataHeader *shared = + (VbSharedDataHeader *)cparams->shared_data_blob; /* Save disk parameters */ - kparams->disk_handle = p.disk_handle; - kparams->partition_number = p.partition_number; - kparams->bootloader_address = p.bootloader_address; - kparams->bootloader_size = p.bootloader_size; - kparams->flags = p.flags; - memcpy(kparams->partition_guid, p.partition_guid, + kparams->disk_handle = lkp.disk_handle; + kparams->partition_number = lkp.partition_number; + kparams->bootloader_address = lkp.bootloader_address; + kparams->bootloader_size = lkp.bootloader_size; + kparams->flags = lkp.flags; + kparams->kernel_buffer = lkp.kernel_buffer; + kparams->kernel_buffer_size = lkp.kernel_buffer_size; + memcpy(kparams->partition_guid, lkp.partition_guid, sizeof(kparams->partition_guid)); - /* Lock the kernel versions. Ignore errors in recovery mode. */ - tpm_status = RollbackKernelLock(shared->recovery_reason); - if (0 != tpm_status) { - VBDEBUG(("Error locking kernel versions.\n")); - if (!shared->recovery_reason) { - VbSetRecoveryRequest(&ctx, - VBNV_RECOVERY_RW_TPM_L_ERROR); - retval = VBERROR_TPM_LOCK_KERNEL; - goto VbSelectAndLoadKernel_exit; - } + /* Lock the kernel versions if not in recovery mode */ + if (!shared->recovery_reason && + RollbackKernelLock(shared->recovery_reason)) { + VB2_DEBUG("Error locking kernel versions.\n"); + VbSetRecoveryRequest(&ctx, VBNV_RECOVERY_RW_TPM_L_ERROR); + return VBERROR_TPM_LOCK_KERNEL; } - VbSelectAndLoadKernel_exit: + return VBERROR_SUCCESS; +} + +static void vb2_kernel_cleanup(VbCommonParams *cparams, + VbSelectAndLoadKernelParams *kparams) +{ + VbSharedDataHeader *shared = + (VbSharedDataHeader *)cparams->shared_data_blob; /* * Clean up vboot context. @@ -986,13 +933,54 @@ VbError_t VbSelectAndLoadKernel(VbCommonParams *cparams, /* Stop timer */ shared->timer_vb_select_and_load_kernel_exit = VbExGetTimer(); +} + +VbError_t VbSelectAndLoadKernel(VbCommonParams *cparams, + VbSelectAndLoadKernelParams *kparams) +{ + VbSharedDataHeader *shared = + (VbSharedDataHeader *)cparams->shared_data_blob; + + VbError_t retval = vb2_kernel_setup(cparams, kparams); + if (retval) + goto VbSelectAndLoadKernel_exit; + + /* + * Do EC software sync if necessary. This has UI, but it's just a + * single non-interactive WAIT screen. + */ + retval = ec_sync_all(&ctx, cparams); + if (retval) + goto VbSelectAndLoadKernel_exit; + + /* Select boot path */ + if (shared->recovery_reason) { + /* Recovery boot. This has UI. */ + retval = VbBootRecovery(&ctx, cparams); + VbExEcEnteringMode(0, VB_EC_RECOVERY); + VbDisplayScreen(&ctx, cparams, VB_SCREEN_BLANK, 0); + + } else if (shared->flags & VBSD_BOOT_DEV_SWITCH_ON) { + /* Developer boot. This has UI. */ + retval = VbBootDeveloper(&ctx, cparams); + VbExEcEnteringMode(0, VB_EC_DEVELOPER); + VbDisplayScreen(&ctx, cparams, VB_SCREEN_BLANK, 0); + + } else { + /* Normal boot */ + retval = VbBootNormal(&ctx, cparams); + VbExEcEnteringMode(0, VB_EC_NORMAL); + } + + VbSelectAndLoadKernel_exit: - kparams->kernel_buffer = p.kernel_buffer; - kparams->kernel_buffer_size = p.kernel_buffer_size; + if (VBERROR_SUCCESS == retval) + retval = vb2_kernel_phase4(cparams, kparams); - VBDEBUG(("VbSelectAndLoadKernel() returning %d\n", (int)retval)); + vb2_kernel_cleanup(cparams, kparams); /* Pass through return value from boot path */ + VB2_DEBUG("%s returning %d\n", __func__, (int)retval); return retval; } diff --git a/tests/vboot_api_devmode_tests.c b/tests/vboot_api_devmode_tests.c index 1d680969..271f3428 100644 --- a/tests/vboot_api_devmode_tests.c +++ b/tests/vboot_api_devmode_tests.c @@ -134,7 +134,6 @@ test_case_t test[] = { /* Mock data */ static VbCommonParams cparams; -static LoadKernelParams lkparams; static struct vb2_context ctx; static VbNvContext vnc; static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE]; @@ -159,7 +158,6 @@ static void ResetMocks(void) { cparams.gbb_data = &gbb; cparams.gbb = &gbb; - memset(&lkparams, 0, sizeof(lkparams)); memset(&ctx, 0, sizeof(ctx)); memset(&vnc, 0, sizeof(vnc)); @@ -317,7 +315,7 @@ static void VbBootDeveloperSoundTest(void) { kbd_fire_at = test[i].keypress_at_count; max_events = test[i].num_events; expected_event = test[i].notes; - (void) VbBootDeveloper(&ctx, &cparams, &lkparams); + (void) VbBootDeveloper(&ctx, &cparams); VBDEBUG(("INFO: matched %d total %d expected %d\n", matched_events, current_event, test[i].num_events)); TEST_TRUE(matched_events == test[i].num_events && diff --git a/tests/vboot_api_kernel2_tests.c b/tests/vboot_api_kernel2_tests.c index 284d4a1f..f6776e9e 100644 --- a/tests/vboot_api_kernel2_tests.c +++ b/tests/vboot_api_kernel2_tests.c @@ -184,7 +184,7 @@ int VbAudioLooping(VbAudioContext *audio) } uint32_t VbTryLoadKernel(struct vb2_context *ctx, VbCommonParams *cparams, - LoadKernelParams *p, uint32_t get_info_flags) + uint32_t get_info_flags) { return vbtlk_retval + get_info_flags; } @@ -273,7 +273,7 @@ static void VbBootTest(void) { ResetMocks(); VbExEcEnteringMode(0, VB_EC_NORMAL); - TEST_EQ(VbBootNormal(&ctx, &cparams, &lkp), 1002, "VbBootNormal()"); + TEST_EQ(VbBootNormal(&ctx, &cparams), 1002, "VbBootNormal()"); TEST_EQ(VbGetMode(), VB_EC_NORMAL, "vboot_mode normal"); } @@ -284,7 +284,7 @@ static void VbBootDevTest(void) /* Proceed after timeout */ ResetMocks(); VbExEcEnteringMode(0, VB_EC_DEVELOPER); - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, "Timeout"); + TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Timeout"); TEST_EQ(VbGetMode(), VB_EC_DEVELOPER, "vboot_mode developer"); TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING, " warning screen"); @@ -296,7 +296,7 @@ static void VbBootDevTest(void) ResetMocks(); gbb.flags |= GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY | GBB_FLAG_FORCE_DEV_BOOT_LEGACY; - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, "Timeout"); + TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Timeout"); TEST_EQ(vbexlegacy_called, 1, " try legacy"); /* Proceed to legacy after timeout if boot legacy and default boot @@ -305,14 +305,14 @@ static void VbBootDevTest(void) vb2_nv_set(&ctx, VB2_NV_DEV_DEFAULT_BOOT, VBNV_DEV_DEFAULT_BOOT_LEGACY); vb2_nv_set(&ctx, VB2_NV_DEV_BOOT_LEGACY, 1); - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, "Timeout"); + TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Timeout"); TEST_EQ(vbexlegacy_called, 1, " try legacy"); /* Proceed to legacy boot mode only if enabled */ ResetMocks(); vb2_nv_set(&ctx, VB2_NV_DEV_DEFAULT_BOOT, VBNV_DEV_DEFAULT_BOOT_LEGACY); - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, "Timeout"); + TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Timeout"); TEST_EQ(vbexlegacy_called, 0, " not legacy"); /* Proceed to usb after timeout if boot usb and default boot @@ -322,31 +322,31 @@ static void VbBootDevTest(void) VBNV_DEV_DEFAULT_BOOT_USB); vb2_nv_set(&ctx, VB2_NV_DEV_BOOT_USB, 1); vbtlk_retval = VBERROR_SUCCESS - VB_DISK_FLAG_REMOVABLE; - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 0, "Ctrl+U USB"); + TEST_EQ(VbBootDeveloper(&ctx, &cparams), 0, "Ctrl+U USB"); /* Proceed to usb boot mode only if enabled */ ResetMocks(); vb2_nv_set(&ctx, VB2_NV_DEV_DEFAULT_BOOT, VBNV_DEV_DEFAULT_BOOT_USB); - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, "Timeout"); + TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Timeout"); /* If no USB tries fixed disk */ ResetMocks(); vb2_nv_set(&ctx, VB2_NV_DEV_BOOT_USB, 1); vb2_nv_set(&ctx, VB2_NV_DEV_DEFAULT_BOOT, VBNV_DEV_DEFAULT_BOOT_USB); - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, "Ctrl+U enabled"); + TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Ctrl+U enabled"); TEST_EQ(vbexlegacy_called, 0, " not legacy"); /* Up arrow is uninteresting / passed to VbCheckDisplayKey() */ ResetMocks(); mock_keypress[0] = VB_KEY_UP; - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, "Up arrow"); + TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Up arrow"); /* Shutdown requested in loop */ ResetMocks(); shutdown_request_calls_left = 2; - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), + TEST_EQ(VbBootDeveloper(&ctx, &cparams), VBERROR_SHUTDOWN_REQUESTED, "Shutdown requested"); TEST_NEQ(audio_looping_calls_left, 0, " aborts audio"); @@ -354,7 +354,7 @@ static void VbBootDevTest(void) /* Space goes straight to recovery if no virtual dev switch */ ResetMocks(); mock_keypress[0] = ' '; - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), + TEST_EQ(VbBootDeveloper(&ctx, &cparams), VBERROR_LOAD_KERNEL_RECOVERY, "Space = recovery"); TEST_EQ(vb2_nv_get(&ctx, VB2_NV_RECOVERY_REQUEST), @@ -365,7 +365,7 @@ static void VbBootDevTest(void) shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_DEV_SWITCH_ON; mock_keypress[0] = ' '; mock_keypress[1] = '\r'; - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), VBERROR_REBOOT_REQUIRED, + TEST_EQ(VbBootDeveloper(&ctx, &cparams), VBERROR_REBOOT_REQUIRED, "Space = tonorm"); TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING, " warning screen"); @@ -382,7 +382,7 @@ static void VbBootDevTest(void) mock_keypress[0] = ' '; mock_keypress[1] = ' '; mock_keypress[2] = 0x1b; - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, "Space-space"); + TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Space-space"); TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING, " warning screen"); TEST_EQ(screens_displayed[1], VB_SCREEN_DEVELOPER_TO_NORM, @@ -395,7 +395,7 @@ static void VbBootDevTest(void) shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_DEV_SWITCH_ON; mock_keypress[0] = '\r'; mock_keypress[1] = '\r'; - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, "Enter ignored"); + TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Enter ignored"); /* Enter does if GBB flag set */ ResetMocks(); @@ -403,7 +403,7 @@ static void VbBootDevTest(void) gbb.flags |= GBB_FLAG_ENTER_TRIGGERS_TONORM; mock_keypress[0] = '\r'; mock_keypress[1] = '\r'; - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), VBERROR_REBOOT_REQUIRED, + TEST_EQ(VbBootDeveloper(&ctx, &cparams), VBERROR_REBOOT_REQUIRED, "Enter = tonorm"); /* Tonorm ignored if GBB forces dev switch on */ @@ -412,7 +412,7 @@ static void VbBootDevTest(void) gbb.flags |= GBB_FLAG_FORCE_DEV_SWITCH_ON; mock_keypress[0] = ' '; mock_keypress[1] = '\r'; - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, + TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Can't tonorm gbb-dev"); /* Shutdown requested at tonorm screen */ @@ -420,7 +420,7 @@ static void VbBootDevTest(void) shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_DEV_SWITCH_ON; mock_keypress[0] = ' '; shutdown_request_calls_left = 2; - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), + TEST_EQ(VbBootDeveloper(&ctx, &cparams), VBERROR_SHUTDOWN_REQUESTED, "Shutdown requested at tonorm"); TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING, @@ -431,7 +431,7 @@ static void VbBootDevTest(void) /* Ctrl+D dismisses warning */ ResetMocks(); mock_keypress[0] = 0x04; - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, "Ctrl+D"); + TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Ctrl+D"); TEST_EQ(vb2_nv_get(&ctx, VB2_NV_RECOVERY_REQUEST), 0, " recovery reason"); TEST_NEQ(audio_looping_calls_left, 0, " aborts audio"); @@ -441,67 +441,67 @@ static void VbBootDevTest(void) ResetMocks(); mock_keypress[0] = 0x04; gbb.flags |= GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY; - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, "Ctrl+D"); + TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Ctrl+D"); TEST_EQ(vbexlegacy_called, 0, " not legacy"); /* Ctrl+L tries legacy boot mode only if enabled */ ResetMocks(); mock_keypress[0] = 0x0c; - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, "Ctrl+L normal"); + TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Ctrl+L normal"); TEST_EQ(vbexlegacy_called, 0, " not legacy"); ResetMocks(); gbb.flags |= GBB_FLAG_FORCE_DEV_BOOT_LEGACY; mock_keypress[0] = 0x0c; - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, + TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Ctrl+L force legacy"); TEST_EQ(vbexlegacy_called, 1, " try legacy"); ResetMocks(); vb2_nv_set(&ctx, VB2_NV_DEV_BOOT_LEGACY, 1); mock_keypress[0] = 0x0c; - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, + TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Ctrl+L nv legacy"); TEST_EQ(vbexlegacy_called, 1, " try legacy"); ResetMocks(); VbApiKernelGetFwmp()->flags |= FWMP_DEV_ENABLE_LEGACY; mock_keypress[0] = 0x0c; - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, + TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Ctrl+L fwmp legacy"); TEST_EQ(vbexlegacy_called, 1, " fwmp legacy"); /* Ctrl+U boots USB only if enabled */ ResetMocks(); mock_keypress[0] = 0x15; - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, "Ctrl+U normal"); + TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Ctrl+U normal"); /* Ctrl+U enabled, with good USB boot */ ResetMocks(); vb2_nv_set(&ctx, VB2_NV_DEV_BOOT_USB, 1); mock_keypress[0] = 0x15; vbtlk_retval = VBERROR_SUCCESS - VB_DISK_FLAG_REMOVABLE; - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 0, "Ctrl+U USB"); + TEST_EQ(VbBootDeveloper(&ctx, &cparams), 0, "Ctrl+U USB"); /* Ctrl+U enabled via GBB */ ResetMocks(); gbb.flags |= GBB_FLAG_FORCE_DEV_BOOT_USB; mock_keypress[0] = 0x15; vbtlk_retval = VBERROR_SUCCESS - VB_DISK_FLAG_REMOVABLE; - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 0, "Ctrl+U force USB"); + TEST_EQ(VbBootDeveloper(&ctx, &cparams), 0, "Ctrl+U force USB"); /* Ctrl+U enabled via FWMP */ ResetMocks(); VbApiKernelGetFwmp()->flags |= FWMP_DEV_ENABLE_USB; mock_keypress[0] = 0x15; vbtlk_retval = VBERROR_SUCCESS - VB_DISK_FLAG_REMOVABLE; - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 0, "Ctrl+U force USB"); + TEST_EQ(VbBootDeveloper(&ctx, &cparams), 0, "Ctrl+U force USB"); /* If no USB, eventually times out and tries fixed disk */ ResetMocks(); vb2_nv_set(&ctx, VB2_NV_DEV_BOOT_USB, 1); mock_keypress[0] = 0x15; - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), 1002, "Ctrl+U enabled"); + TEST_EQ(VbBootDeveloper(&ctx, &cparams), 1002, "Ctrl+U enabled"); TEST_EQ(vbexlegacy_called, 0, " not legacy"); TEST_EQ(vb2_nv_get(&ctx, VB2_NV_RECOVERY_REQUEST), 0, " recovery reason"); @@ -512,7 +512,7 @@ static void VbBootDevTest(void) VbApiKernelGetFwmp()->flags |= FWMP_DEV_DISABLE_BOOT; mock_keypress[0] = '\x1b'; /* Just causes TONORM again */ mock_keypress[1] = '\r'; - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), VBERROR_REBOOT_REQUIRED, + TEST_EQ(VbBootDeveloper(&ctx, &cparams), VBERROR_REBOOT_REQUIRED, "FWMP dev disabled"); TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_TO_NORM, " tonorm screen"); @@ -528,7 +528,7 @@ static void VbBootDevTest(void) shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_DEV_SWITCH_ON; VbApiKernelGetFwmp()->flags |= FWMP_DEV_DISABLE_BOOT; shutdown_request_calls_left = 1; - TEST_EQ(VbBootDeveloper(&ctx, &cparams, &lkp), + TEST_EQ(VbBootDeveloper(&ctx, &cparams), VBERROR_SHUTDOWN_REQUESTED, "Shutdown requested when dev disabled"); TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_TO_NORM, @@ -545,7 +545,7 @@ static void VbBootRecTest(void) ResetMocks(); shutdown_request_calls_left = 10; VbExEcEnteringMode(0, VB_EC_RECOVERY); - TEST_EQ(VbBootRecovery(&ctx, &cparams, &lkp), + TEST_EQ(VbBootRecovery(&ctx, &cparams), VBERROR_SHUTDOWN_REQUESTED, "Shutdown requested"); TEST_EQ(VbGetMode(), VB_EC_RECOVERY, "vboot_mode recovery"); @@ -562,7 +562,7 @@ static void VbBootRecTest(void) mock_num_disks[1] = 1; mock_num_disks[2] = 1; vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE; - TEST_EQ(VbBootRecovery(&ctx, &cparams, &lkp), + TEST_EQ(VbBootRecovery(&ctx, &cparams), VBERROR_SHUTDOWN_REQUESTED, "Remove"); TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN, @@ -575,7 +575,7 @@ static void VbBootRecTest(void) mock_num_disks[1] = 1; shared->flags |= VBSD_BOOT_DEV_SWITCH_ON; vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE; - TEST_EQ(VbBootRecovery(&ctx, &cparams, &lkp), + TEST_EQ(VbBootRecovery(&ctx, &cparams), VBERROR_SHUTDOWN_REQUESTED, "No remove in dev"); TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT, @@ -588,7 +588,7 @@ static void VbBootRecTest(void) mock_num_disks[1] = 1; shared->flags |= VBSD_BOOT_REC_SWITCH_ON; vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE; - TEST_EQ(VbBootRecovery(&ctx, &cparams, &lkp), + TEST_EQ(VbBootRecovery(&ctx, &cparams), VBERROR_SHUTDOWN_REQUESTED, "No remove in rec"); TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT, @@ -600,7 +600,7 @@ static void VbBootRecTest(void) mock_num_disks[0] = 0; mock_num_disks[1] = 1; vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE; - TEST_EQ(VbBootRecovery(&ctx, &cparams, &lkp), + TEST_EQ(VbBootRecovery(&ctx, &cparams), VBERROR_SHUTDOWN_REQUESTED, "Remove"); TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN, @@ -612,7 +612,7 @@ static void VbBootRecTest(void) mock_num_disks[0] = -1; vbtlk_retval = VBERROR_NO_DISK_FOUND - VB_DISK_FLAG_REMOVABLE; shutdown_request_calls_left = 10; - TEST_EQ(VbBootRecovery(&ctx, &cparams, &lkp), + TEST_EQ(VbBootRecovery(&ctx, &cparams), VBERROR_SHUTDOWN_REQUESTED, "Bad disk count"); TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN, @@ -624,7 +624,7 @@ static void VbBootRecTest(void) shutdown_request_calls_left = 100; mock_keypress[0] = 0x04; trust_ec = 0; - TEST_EQ(VbBootRecovery(&ctx, &cparams, &lkp), + TEST_EQ(VbBootRecovery(&ctx, &cparams), VBERROR_SHUTDOWN_REQUESTED, "Ctrl+D ignored if EC not trusted"); TEST_EQ(virtdev_set, 0, " virtual dev mode off"); @@ -637,7 +637,7 @@ static void VbBootRecTest(void) trust_ec = 1; shutdown_request_calls_left = 100; mock_keypress[0] = 0x04; - TEST_EQ(VbBootRecovery(&ctx, &cparams, &lkp), + TEST_EQ(VbBootRecovery(&ctx, &cparams), VBERROR_SHUTDOWN_REQUESTED, "Ctrl+D ignored if already in dev mode"); TEST_EQ(virtdev_set, 0, " virtual dev mode off"); @@ -649,7 +649,7 @@ static void VbBootRecTest(void) trust_ec = 1; shutdown_request_calls_left = 100; mock_keypress[0] = 0x04; - TEST_EQ(VbBootRecovery(&ctx, &cparams, &lkp), + TEST_EQ(VbBootRecovery(&ctx, &cparams), VBERROR_SHUTDOWN_REQUESTED, "Ctrl+D ignored if recovery not manually triggered"); TEST_EQ(virtdev_set, 0, " virtual dev mode off"); @@ -661,7 +661,7 @@ static void VbBootRecTest(void) trust_ec = 1; shutdown_request_calls_left = 100; mock_keypress[0] = 0x04; - TEST_EQ(VbBootRecovery(&ctx, &cparams, &lkp), + TEST_EQ(VbBootRecovery(&ctx, &cparams), VBERROR_SHUTDOWN_REQUESTED, "Ctrl+D ignored if no virtual dev switch"); TEST_EQ(virtdev_set, 0, " virtual dev mode off"); @@ -677,7 +677,7 @@ static void VbBootRecTest(void) shutdown_request_calls_left = 100; mock_keypress[0] = 0x04; mock_switches[0] = VB_INIT_FLAG_REC_BUTTON_PRESSED; - TEST_EQ(VbBootRecovery(&ctx, &cparams, &lkp), + TEST_EQ(VbBootRecovery(&ctx, &cparams), VBERROR_SHUTDOWN_REQUESTED, "Ctrl+D ignored if phys rec button is still pressed"); TEST_NEQ(screens_displayed[1], VB_SCREEN_RECOVERY_TO_DEV, @@ -691,7 +691,7 @@ static void VbBootRecTest(void) trust_ec = 1; mock_keypress[0] = 0x04; mock_keypress[1] = ' '; - TEST_EQ(VbBootRecovery(&ctx, &cparams, &lkp), + TEST_EQ(VbBootRecovery(&ctx, &cparams), VBERROR_SHUTDOWN_REQUESTED, "Ctrl+D todev abort"); TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT, @@ -711,7 +711,7 @@ static void VbBootRecTest(void) mock_keypress[0] = 0x04; mock_keypress[1] = '\r'; mock_keyflags[1] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - TEST_EQ(VbBootRecovery(&ctx, &cparams, &lkp), VBERROR_REBOOT_REQUIRED, + TEST_EQ(VbBootRecovery(&ctx, &cparams), VBERROR_REBOOT_REQUIRED, "Ctrl+D todev confirm"); TEST_EQ(virtdev_set, 1, " virtual dev mode on"); @@ -725,7 +725,7 @@ static void VbBootRecTest(void) mock_keypress[1] = '\r'; mock_keyflags[1] = VB_KEY_FLAG_TRUSTED_KEYBOARD; virtdev_retval = VBERROR_SIMULATED; - TEST_EQ(VbBootRecovery(&ctx, &cparams, &lkp), + TEST_EQ(VbBootRecovery(&ctx, &cparams), VBERROR_TPM_SET_BOOT_MODE_STATE, "Ctrl+D todev failure"); diff --git a/tests/vboot_api_kernel4_tests.c b/tests/vboot_api_kernel4_tests.c index 0b1223d7..41e58c8e 100644 --- a/tests/vboot_api_kernel4_tests.c +++ b/tests/vboot_api_kernel4_tests.c @@ -111,8 +111,8 @@ uint32_t RollbackFwmpRead(struct RollbackSpaceFwmp *fwmp) return rfr_retval; } -VbError_t VbBootNormal(struct vb2_context *ctx, VbCommonParams *cparams, - LoadKernelParams *p) +uint32_t VbTryLoadKernel(struct vb2_context *ctx, VbCommonParams *cparams, + uint32_t get_info_flags) { shared->kernel_version_tpm = new_version; @@ -122,8 +122,7 @@ VbError_t VbBootNormal(struct vb2_context *ctx, VbCommonParams *cparams, return vbboot_retval; } -VbError_t VbBootDeveloper(struct vb2_context *ctx, VbCommonParams *cparams, - LoadKernelParams *p) +VbError_t VbBootDeveloper(struct vb2_context *ctx, VbCommonParams *cparams) { shared->kernel_version_tpm = new_version; @@ -133,8 +132,7 @@ VbError_t VbBootDeveloper(struct vb2_context *ctx, VbCommonParams *cparams, return vbboot_retval; } -VbError_t VbBootRecovery(struct vb2_context *ctx, VbCommonParams *cparams, - LoadKernelParams *p) +VbError_t VbBootRecovery(struct vb2_context *ctx, VbCommonParams *cparams) { shared->kernel_version_tpm = new_version; diff --git a/tests/vboot_api_kernel_tests.c b/tests/vboot_api_kernel_tests.c index 0a59160b..1d80dc4b 100644 --- a/tests/vboot_api_kernel_tests.c +++ b/tests/vboot_api_kernel_tests.c @@ -21,6 +21,8 @@ #include "vboot_api.h" #include "vboot_kernel.h" +struct LoadKernelParams *VbApiKernelGetParams(void); + #define MAX_TEST_DISKS 10 #define DEFAULT_COUNT -1 @@ -181,7 +183,6 @@ test_case_t test[] = { /****************************************************************************/ /* Mock data */ -static LoadKernelParams lkparams; static VbDiskInfo mock_disks[MAX_TEST_DISKS]; static test_case_t *t; static int load_kernel_calls; @@ -190,7 +191,6 @@ static const char *got_find_disk; static const char *got_load_disk; static uint32_t got_return_val; static uint32_t got_external_mismatch; -static VbNvContext vnc; static struct vb2_context ctx; /** @@ -198,10 +198,12 @@ static struct vb2_context ctx; */ static void ResetMocks(int i) { - memset(&lkparams, 0, sizeof(lkparams)); + memset(&ctx, 0, sizeof(ctx)); + + memset(VbApiKernelGetParams(), 0, sizeof(LoadKernelParams)); + memset(&mock_disks, 0, sizeof(mock_disks)); load_kernel_calls = 0; - memset(&vnc, 0, sizeof(vnc)); got_recovery_request_val = VBNV_RECOVERY_NOT_REQUESTED; got_find_disk = 0; @@ -313,7 +315,7 @@ static void VbTryLoadKernelTest(void) for (i = 0; i < num_tests; i++) { printf("Test case: %s ...\n", test[i].name); ResetMocks(i); - TEST_EQ(VbTryLoadKernel(&ctx, 0, &lkparams, test[i].want_flags), + TEST_EQ(VbTryLoadKernel(&ctx, 0, test[i].want_flags), t->expected_return_val, " return value"); TEST_EQ(got_recovery_request_val, t->expected_recovery_request_val, " recovery_request"); diff --git a/tests/vboot_kernel_tests.c b/tests/vboot_kernel_tests.c index 2a472d38..b1e1635e 100644 --- a/tests/vboot_kernel_tests.c +++ b/tests/vboot_kernel_tests.c @@ -158,8 +158,6 @@ static void ResetMocks(void) memset(&lkp, 0, sizeof(lkp)); lkp.nv_context = &vnc; - lkp.gbb_data = gbb; - lkp.gbb_size = sizeof(gbb_data); lkp.bytes_per_lba = 512; lkp.streaming_lba_count = 1024; lkp.gpt_lba_count = 1024; @@ -577,10 +575,6 @@ static void ReadWriteGptTest(void) static void TestLoadKernel(int expect_retval, char *test_name) { memcpy(ctx.nvdata, vnc.raw, VB2_NVDATA_SIZE); - if (lkp.boot_flags & BOOT_FLAG_RECOVERY) - ctx.flags |= VB2_CONTEXT_RECOVERY_MODE; - if (lkp.boot_flags & BOOT_FLAG_DEVELOPER) - ctx.flags |= VB2_CONTEXT_DEVELOPER_MODE; TEST_EQ(LoadKernel(&ctx, &lkp, &cparams), expect_retval, test_name); @@ -653,26 +647,26 @@ static void LoadKernelTest(void) /* In dev mode, fail if hash is bad too */ ResetMocks(); - lkp.boot_flags |= BOOT_FLAG_DEVELOPER; + ctx.flags |= VB2_CONTEXT_DEVELOPER_MODE; key_block_verify_fail = 2; TestLoadKernel(VBERROR_INVALID_KERNEL_FOUND, "Fail key block dev hash"); /* But just bad sig is ok */ ResetMocks(); - lkp.boot_flags |= BOOT_FLAG_DEVELOPER; + ctx.flags |= VB2_CONTEXT_DEVELOPER_MODE; key_block_verify_fail = 1; TestLoadKernel(0, "Succeed key block dev sig"); /* In dev mode and requiring signed kernel, fail if sig is bad */ ResetMocks(); - lkp.boot_flags |= BOOT_FLAG_DEVELOPER; + ctx.flags |= VB2_CONTEXT_DEVELOPER_MODE; VbNvSet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, 1); VbNvTeardown(&vnc); key_block_verify_fail = 1; TestLoadKernel(VBERROR_INVALID_KERNEL_FOUND, "Fail key block dev sig"); ResetMocks(); - lkp.boot_flags |= BOOT_FLAG_DEVELOPER; + ctx.flags |= VB2_CONTEXT_DEVELOPER_MODE; lkp.fwmp = &fwmp; fwmp.flags |= FWMP_DEV_ENABLE_OFFICIAL_ONLY; key_block_verify_fail = 1; @@ -693,14 +687,14 @@ static void LoadKernelTest(void) "Key block rec flag mismatch"); ResetMocks(); - lkp.boot_flags |= BOOT_FLAG_RECOVERY; + ctx.flags |= VB2_CONTEXT_RECOVERY_MODE; kbh.key_block_flags = KEY_BLOCK_FLAG_RECOVERY_1 | KEY_BLOCK_FLAG_DEVELOPER_1; TestLoadKernel(VBERROR_INVALID_KERNEL_FOUND, "Key block recdev flag mismatch"); ResetMocks(); - lkp.boot_flags |= BOOT_FLAG_RECOVERY | BOOT_FLAG_DEVELOPER; + ctx.flags |= VB2_CONTEXT_RECOVERY_MODE | VB2_CONTEXT_DEVELOPER_MODE; kbh.key_block_flags = KEY_BLOCK_FLAG_RECOVERY_1 | KEY_BLOCK_FLAG_DEVELOPER_0; TestLoadKernel(VBERROR_INVALID_KERNEL_FOUND, @@ -731,12 +725,12 @@ static void LoadKernelTest(void) ResetMocks(); kbh.data_key.key_version = 1; - lkp.boot_flags |= BOOT_FLAG_DEVELOPER; + ctx.flags |= VB2_CONTEXT_DEVELOPER_MODE; TestLoadKernel(0, "Key version ignored in dev mode"); ResetMocks(); kbh.data_key.key_version = 1; - lkp.boot_flags |= BOOT_FLAG_RECOVERY; + ctx.flags |= VB2_CONTEXT_RECOVERY_MODE; TestLoadKernel(0, "Key version ignored in rec mode"); ResetMocks(); @@ -753,17 +747,17 @@ static void LoadKernelTest(void) ResetMocks(); kph.kernel_version = 0; - lkp.boot_flags |= BOOT_FLAG_DEVELOPER; + ctx.flags |= VB2_CONTEXT_DEVELOPER_MODE; TestLoadKernel(0, "Kernel version ignored in dev mode"); ResetMocks(); kph.kernel_version = 0; - lkp.boot_flags |= BOOT_FLAG_RECOVERY; + ctx.flags |= VB2_CONTEXT_RECOVERY_MODE; TestLoadKernel(0, "Kernel version ignored in rec mode"); /* Check developer key hash - bad */ ResetMocks(); - lkp.boot_flags |= BOOT_FLAG_DEVELOPER; + ctx.flags |= VB2_CONTEXT_DEVELOPER_MODE; lkp.fwmp = &fwmp; fwmp.flags |= FWMP_DEV_USE_KEY_HASH; fwmp.dev_key_hash[0]++; @@ -772,7 +766,7 @@ static void LoadKernelTest(void) /* Check developer key hash - good */ ResetMocks(); - lkp.boot_flags |= BOOT_FLAG_DEVELOPER; + ctx.flags |= VB2_CONTEXT_DEVELOPER_MODE; lkp.fwmp = &fwmp; fwmp.flags |= FWMP_DEV_USE_KEY_HASH; TestLoadKernel(0, "Good key block dev fwmp hash"); diff --git a/tests/verify_kernel.c b/tests/verify_kernel.c index 9a7ee1e9..5c48781b 100644 --- a/tests/verify_kernel.c +++ b/tests/verify_kernel.c @@ -107,10 +107,6 @@ int main(int argc, char *argv[]) return 1; } - /* GBB and cparams only needed by LoadKernel() in recovery mode */ - params.gbb_data = NULL; - params.gbb_size = 0; - /* TODO(chromium:441893): support dev-mode flag and external gpt flag */ params.boot_flags = 0; diff --git a/utility/load_kernel_test.c b/utility/load_kernel_test.c index 4ca061ef..769c24c5 100644 --- a/utility/load_kernel_test.c +++ b/utility/load_kernel_test.c @@ -78,6 +78,9 @@ VbError_t VbExDiskWrite(VbExDiskHandle_t handle, uint64_t lba_start, } +#define BOOT_FLAG_DEVELOPER (1 << 0) +#define BOOT_FLAG_RECOVERY (1 << 1) + /* Main routine */ int main(int argc, char* argv[]) { @@ -93,7 +96,7 @@ int main(int argc, char* argv[]) { memset(&lkp, 0, sizeof(LoadKernelParams)); lkp.bytes_per_lba = LBA_BYTES; - lkp.boot_flags = BOOT_FLAG_RECOVERY; + int boot_flags = BOOT_FLAG_RECOVERY; memset(&vnc, 0, sizeof(VbNvContext)); VbNvSetup(&vnc); lkp.nv_context = &vnc; @@ -106,7 +109,7 @@ int main(int argc, char* argv[]) { switch (c) { case 'b': - lkp.boot_flags = strtoull(optarg, &e, 0); + boot_flags = strtoull(optarg, &e, 0); if (!*optarg || (e && *e)) { fprintf(stderr, "Invalid argument to -%c: \"%s\"\n", c, optarg); @@ -136,12 +139,12 @@ int main(int argc, char* argv[]) { argv[0]); fprintf(stderr, "\noptions:\n"); /* These cases are because uint64_t isn't necessarily the same as ULL. */ - fprintf(stderr, " -b NUM boot flag bits (default %" PRIu64 "):\n", - (uint64_t)BOOT_FLAG_RECOVERY); - fprintf(stderr, " %" PRIu64 " = developer mode on\n", - (uint64_t)BOOT_FLAG_DEVELOPER); - fprintf(stderr, " %" PRIu64 " = recovery mode on\n", - (uint64_t)BOOT_FLAG_RECOVERY); + fprintf(stderr, " -b NUM boot flag bits (default %d):\n", + BOOT_FLAG_RECOVERY); + fprintf(stderr, " %d = developer mode on\n", + BOOT_FLAG_DEVELOPER); + fprintf(stderr, " %d = recovery mode on\n", + BOOT_FLAG_RECOVERY); return 1; } @@ -163,11 +166,9 @@ int main(int argc, char* argv[]) { } /* Initialize the GBB */ - lkp.gbb_size = sizeof(GoogleBinaryBlockHeader) + key_size; - lkp.gbb_data = (void*)malloc(lkp.gbb_size); - gbb = (GoogleBinaryBlockHeader*)lkp.gbb_data; - cparams.gbb = gbb; - memset(gbb, 0, lkp.gbb_size); + cparams.gbb_size = sizeof(GoogleBinaryBlockHeader) + key_size; + cparams.gbb = gbb = (GoogleBinaryBlockHeader*)malloc(cparams.gbb_size); + memset(gbb, 0, cparams.gbb_size); memcpy(gbb->signature, GBB_SIGNATURE, GBB_SIGNATURE_SIZE); gbb->major_version = GBB_MAJOR_VER; gbb->minor_version = GBB_MINOR_VER; @@ -201,7 +202,8 @@ int main(int argc, char* argv[]) { /* Free the key blob, now that we're done with it */ free(key_blob); - printf("bootflags = %" PRIu64 "\n", lkp.boot_flags); + printf("bootflags = %d\n", boot_flags); + lkp.boot_flags = boot_flags; /* Get image size */ printf("Reading from image: %s\n", image_name); @@ -239,9 +241,9 @@ int main(int argc, char* argv[]) { return 1; } ctx.workbuf_size = VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE; - if (lkp.boot_flags & BOOT_FLAG_RECOVERY) + if (boot_flags & BOOT_FLAG_RECOVERY) ctx.flags |= VB2_CONTEXT_RECOVERY_MODE; - if (lkp.boot_flags & BOOT_FLAG_DEVELOPER) + if (boot_flags & BOOT_FLAG_DEVELOPER) ctx.flags |= VB2_CONTEXT_DEVELOPER_MODE; if (VB2_SUCCESS != vb2_init_context(&ctx)) { free(ctx.workbuf); |