diff options
author | Hsin-Te Yuan <yuanhsinte@google.com> | 2022-07-12 10:52:13 +0800 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2022-07-29 09:47:12 +0000 |
commit | 18cb85b52d689b4cfbd49c6384ae2088b78af1e0 (patch) | |
tree | 2c7e7aca1e50a81e05aa7c302db29554f0a82c70 /firmware | |
parent | 81b8d3faabad2f16bfd08efa6920bdaaeb637ce8 (diff) | |
download | vboot-18cb85b52d689b4cfbd49c6384ae2088b78af1e0.tar.gz |
2load_kernel.c: Expose load kernel as vb2_api
Move VbTryLoadKernel() and VbTryLoadMiniOsKernel() to depthcharge.
In addition, expose LoadKernel() and LoadMiniOsKernel() as
vb2api_load_kernel() and vb2api_load_minos_kernel(), respectively.
Since we remove VbTryLoadKernel() in vb2api_normal_boot(), rename
vb2api_normal_boot() to check_kernel_version() and call it in
vb2api_kernel_finalize().
Also, rename VbSelectAndLoadKernelParams, VbDiskInfo, and
VbExDiskHandle_t as vb2_kernel_params, vb2_disk_info, and
vb2ex_disk_handle_t, respectively.
BUG=b:172339016
BRANCH=none
TEST=make runtests
TEST=FW_NAME=tomato emerge-cherry depthcharge
Cq-Depend: chromium:3758201
Signed-off-by: Hsin-Te Yuan <yuanhsinte@google.com>
Change-Id: Iaf182ca81797fee24c6104dac9d4770ff75c7fb2
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/3755923
Reviewed-by: Yu-Ping Wu <yupingso@chromium.org>
Reviewed-by: Julius Werner <jwerner@chromium.org>
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/2lib/2kernel.c | 102 | ||||
-rw-r--r-- | firmware/2lib/2load_kernel.c (renamed from firmware/lib/vboot_kernel.c) | 40 | ||||
-rw-r--r-- | firmware/2lib/2recovery_reasons.c | 2 | ||||
-rw-r--r-- | firmware/2lib/2secdata_kernel.c | 1 | ||||
-rw-r--r-- | firmware/2lib/include/2api.h | 150 | ||||
-rw-r--r-- | firmware/2lib/include/2constants.h | 8 | ||||
-rw-r--r-- | firmware/2lib/include/2recovery_reasons.h | 2 | ||||
-rw-r--r-- | firmware/2lib/include/2return_codes.h | 8 | ||||
-rw-r--r-- | firmware/include/gpt_misc.h | 9 | ||||
-rw-r--r-- | firmware/include/vboot_api.h | 164 | ||||
-rw-r--r-- | firmware/lib/gpt_misc.c | 4 | ||||
-rw-r--r-- | firmware/lib/include/load_kernel_fw.h | 41 | ||||
-rw-r--r-- | firmware/lib/include/vboot_struct.h | 21 | ||||
-rw-r--r-- | firmware/lib/vboot_api_kernel.c | 123 | ||||
-rw-r--r-- | firmware/stub/vboot_api_stub_disk.c | 10 | ||||
-rw-r--r-- | firmware/stub/vboot_api_stub_stream.c | 4 |
16 files changed, 252 insertions, 437 deletions
diff --git a/firmware/2lib/2kernel.c b/firmware/2lib/2kernel.c index 41764ef1..ff89e142 100644 --- a/firmware/2lib/2kernel.c +++ b/firmware/2lib/2kernel.c @@ -5,64 +5,12 @@ * Kernel selection, loading, verification, and booting. */ +#include "2api.h" #include "2common.h" #include "2misc.h" #include "2nvstorage.h" #include "2rsa.h" #include "2secdata.h" -#include "vboot_api.h" - -vb2_error_t vb2api_normal_boot(struct vb2_context *ctx, - VbSelectAndLoadKernelParams *kparams) -{ - struct vb2_shared_data *sd = vb2_get_sd(ctx); - uint32_t max_rollforward = vb2_nv_get(ctx, - VB2_NV_KERNEL_MAX_ROLLFORWARD); - - /* Boot from fixed disk only */ - VB2_DEBUG("Entering\n"); - - vb2_error_t rv = VbTryLoadKernel(ctx, VB_DISK_FLAG_FIXED, kparams); - - VB2_DEBUG("Checking if TPM kernel version needs advancing\n"); - - /* - * Special case for when we're trying a slot with new firmware. - * Firmware updates also usually change the kernel key, which means - * that the new firmware can only boot a new kernel, and the old - * firmware in the previous slot can only boot the previous kernel. - * - * Don't roll-forward the kernel version, because we don't yet know if - * the new kernel will successfully boot. - */ - if (vb2_nv_get(ctx, VB2_NV_FW_RESULT) == VB2_FW_RESULT_TRYING) { - VB2_DEBUG("Trying new FW; skip kernel version roll-forward.\n"); - return rv; - } - - /* - * Limit kernel version rollforward if needed. Can't limit kernel - * version to less than the version currently in the TPM. That is, - * we're limiting rollforward, not allowing rollback. - */ - if (max_rollforward < sd->kernel_version_secdata) - max_rollforward = sd->kernel_version_secdata; - - if (sd->kernel_version > max_rollforward) { - VB2_DEBUG("Limiting TPM kernel version roll-forward " - "to %#x < %#x\n", - max_rollforward, sd->kernel_version); - - sd->kernel_version = max_rollforward; - } - - if (sd->kernel_version > sd->kernel_version_secdata) { - vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_VERSIONS, - sd->kernel_version); - } - - return rv; -} int vb2api_is_developer_signed(struct vb2_context *ctx) { @@ -263,6 +211,51 @@ vb2_error_t vb2api_kernel_phase2(struct vb2_context *ctx) return VB2_SUCCESS; } +static void update_kernel_version(struct vb2_context *ctx) +{ + struct vb2_shared_data *sd = vb2_get_sd(ctx); + uint32_t max_rollforward = + vb2_nv_get(ctx, VB2_NV_KERNEL_MAX_ROLLFORWARD); + + VB2_DEBUG("Checking if TPM kernel version needs advancing\n"); + + /* + * Special case for when we're trying a slot with new firmware. + * Firmware updates also usually change the kernel key, which means + * that the new firmware can only boot a new kernel, and the old + * firmware in the previous slot can only boot the previous kernel. + * + * Don't roll-forward the kernel version, because we don't yet know if + * the new kernel will successfully boot. + */ + if (vb2_nv_get(ctx, VB2_NV_FW_RESULT) == VB2_FW_RESULT_TRYING) { + VB2_DEBUG("Trying new FW; " + "skip kernel version roll-forward.\n"); + return; + } + + /* + * Limit kernel version rollforward if needed. Can't limit kernel + * version to less than the version currently in the TPM. That is, + * we're limiting rollforward, not allowing rollback. + */ + if (max_rollforward < sd->kernel_version_secdata) + max_rollforward = sd->kernel_version_secdata; + + if (sd->kernel_version > max_rollforward) { + VB2_DEBUG("Limiting TPM kernel version roll-forward " + "to %#x < %#x\n", + max_rollforward, sd->kernel_version); + + sd->kernel_version = max_rollforward; + } + + if (sd->kernel_version > sd->kernel_version_secdata) { + vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_VERSIONS, + sd->kernel_version); + } +} + vb2_error_t vb2api_kernel_finalize(struct vb2_context *ctx) { vb2_gbb_flags_t gbb_flags = vb2api_gbb_get_flags(ctx); @@ -279,5 +272,8 @@ vb2_error_t vb2api_kernel_finalize(struct vb2_context *ctx) return VB2_ERROR_ESCAPE_NO_BOOT; } + if (ctx->boot_mode == VB2_BOOT_MODE_NORMAL) + update_kernel_version(ctx); + return VB2_SUCCESS; } diff --git a/firmware/lib/vboot_kernel.c b/firmware/2lib/2load_kernel.c index 44bcf295..65e40536 100644 --- a/firmware/lib/vboot_kernel.c +++ b/firmware/2lib/2load_kernel.c @@ -16,7 +16,6 @@ #include "cgptlib.h" #include "cgptlib_internal.h" #include "gpt_misc.h" -#include "load_kernel_fw.h" #include "vboot_api.h" enum vb2_load_partition_flags { @@ -348,7 +347,7 @@ static vb2_error_t vb2_verify_kernel_vblock( * @return VB2_SUCCESS, or non-zero error code. */ static vb2_error_t vb2_load_partition( - struct vb2_context *ctx, VbSelectAndLoadKernelParams *params, + struct vb2_context *ctx, struct vb2_kernel_params *params, VbExStream_t stream, uint32_t lpflags) { uint32_t read_ms = 0, start_ts; @@ -462,8 +461,8 @@ static vb2_error_t vb2_load_partition( } static vb2_error_t try_minios_kernel(struct vb2_context *ctx, - VbSelectAndLoadKernelParams *params, - VbDiskInfo *disk_info, + struct vb2_kernel_params *params, + struct vb2_disk_info *disk_info, uint64_t sector) { VbExStream_t stream; uint64_t sectors_left = disk_info->lba_count - sector; @@ -471,7 +470,7 @@ static vb2_error_t try_minios_kernel(struct vb2_context *ctx, vb2_error_t rv = VB2_ERROR_LK_NO_KERNEL_FOUND; /* Re-open stream at correct offset to pass to vb2_load_partition. */ - if (VbExStreamOpen(params->disk_handle, sector, sectors_left, + if (VbExStreamOpen(disk_info->handle, sector, sectors_left, &stream)) { VB2_DEBUG("Unable to open disk handle.\n"); return rv; @@ -488,8 +487,8 @@ static vb2_error_t try_minios_kernel(struct vb2_context *ctx, } static vb2_error_t try_minios_sectors(struct vb2_context *ctx, - VbSelectAndLoadKernelParams *params, - VbDiskInfo *disk_info, + struct vb2_kernel_params *params, + struct vb2_disk_info *disk_info, uint64_t start, uint64_t count) { const uint32_t buf_size = count * disk_info->bytes_per_lba; @@ -504,7 +503,7 @@ static vb2_error_t try_minios_sectors(struct vb2_context *ctx, return rv; } - if (VbExStreamOpen(params->disk_handle, start, count, &stream)) { + if (VbExStreamOpen(disk_info->handle, start, count, &stream)) { VB2_DEBUG("Unable to open disk handle.\n"); free(buf); return rv; @@ -534,8 +533,8 @@ static vb2_error_t try_minios_sectors(struct vb2_context *ctx, } static vb2_error_t try_minios_sector_region(struct vb2_context *ctx, - VbSelectAndLoadKernelParams *params, - VbDiskInfo *disk_info, + struct vb2_kernel_params *params, + struct vb2_disk_info *disk_info, int end_region) { const uint64_t disk_count_half = (disk_info->lba_count + 1) / 2; @@ -577,14 +576,15 @@ static vb2_error_t try_minios_sector_region(struct vb2_context *ctx, * the start and end of disks are considered, and the kernel must start exactly * at the first byte of the sector. */ -vb2_error_t LoadMiniOsKernel(struct vb2_context *ctx, - VbSelectAndLoadKernelParams *params, - VbDiskInfo *disk_info, uint32_t minios_flags) +vb2_error_t vb2api_load_minios_kernel(struct vb2_context *ctx, + struct vb2_kernel_params *params, + struct vb2_disk_info *disk_info, + uint32_t minios_flags) { vb2_error_t rv; int end_region_first = vb2_nv_get(ctx, VB2_NV_MINIOS_PRIORITY); - if (minios_flags & VB_MINIOS_FLAG_NON_ACTIVE) + if (minios_flags & VB2_MINIOS_FLAG_NON_ACTIVE) rv = VB2_ERROR_UNKNOWN; /* Ignore active partition */ else rv = try_minios_sector_region(ctx, params, disk_info, @@ -594,12 +594,15 @@ vb2_error_t LoadMiniOsKernel(struct vb2_context *ctx, rv = try_minios_sector_region(ctx, params, disk_info, !end_region_first); + if (rv == VB2_SUCCESS) + params->disk_handle = disk_info->handle; + return rv; } -vb2_error_t LoadKernel(struct vb2_context *ctx, - VbSelectAndLoadKernelParams *params, - VbDiskInfo *disk_info) +vb2_error_t vb2api_load_kernel(struct vb2_context *ctx, + struct vb2_kernel_params *params, + struct vb2_disk_info *disk_info) { struct vb2_shared_data *sd = vb2_get_sd(ctx); int found_partitions = 0; @@ -615,7 +618,7 @@ vb2_error_t LoadKernel(struct vb2_context *ctx, gpt.streaming_drive_sectors = disk_info->streaming_lba_count ?: disk_info->lba_count; gpt.gpt_drive_sectors = disk_info->lba_count; - gpt.flags = disk_info->flags & VB_DISK_FLAG_EXTERNAL_GPT + gpt.flags = disk_info->flags & VB2_DISK_FLAG_EXTERNAL_GPT ? GPT_FLAG_EXTERNAL : 0; if (AllocAndReadGptData(disk_info->handle, &gpt)) { VB2_DEBUG("Unable to read GPT data\n"); @@ -748,6 +751,7 @@ vb2_error_t LoadKernel(struct vb2_context *ctx, /* Success! */ rv = VB2_SUCCESS; + params->disk_handle = disk_info->handle; } else if (found_partitions > 0) { rv = VB2_ERROR_LK_INVALID_KERNEL_FOUND; } else { diff --git a/firmware/2lib/2recovery_reasons.c b/firmware/2lib/2recovery_reasons.c index 8c43dcef..73fd8121 100644 --- a/firmware/2lib/2recovery_reasons.c +++ b/firmware/2lib/2recovery_reasons.c @@ -113,7 +113,7 @@ const char *vb2_get_recovery_reason_string(uint8_t code) /* 0x46 */ case VB2_RECOVERY_RW_SHARED_DATA: return "Shared data error in rewritable firmware"; /* 0x47 */ case VB2_RECOVERY_DEPRECATED_RW_TEST_LK: - return "Test error from LoadKernel()"; + return "Test error from vb2api_load_kernel()"; /* 0x48 */ case VB2_RECOVERY_DEPRECATED_RW_NO_DISK: return "No bootable storage device in system"; /* 0x49 */ case VB2_RECOVERY_TPM_E_FAIL: diff --git a/firmware/2lib/2secdata_kernel.c b/firmware/2lib/2secdata_kernel.c index 9973cd46..754552c0 100644 --- a/firmware/2lib/2secdata_kernel.c +++ b/firmware/2lib/2secdata_kernel.c @@ -180,6 +180,7 @@ vb2_error_t vb2_secdata_kernel_init(struct vb2_context *ctx) return VB2_SUCCESS; } +test_mockable uint32_t vb2_secdata_kernel_get(struct vb2_context *ctx, enum vb2_secdata_kernel_param param) { diff --git a/firmware/2lib/include/2api.h b/firmware/2lib/include/2api.h index 904b7105..23af95d8 100644 --- a/firmware/2lib/include/2api.h +++ b/firmware/2lib/include/2api.h @@ -29,7 +29,6 @@ #include "2return_codes.h" #include "2rsa.h" #include "2secdata_struct.h" -#include "vboot_api.h" #define _VB2_TRY_IMPL(expr, ctx, recovery_reason, ...) do { \ vb2_error_t _vb2_try_rv = (expr); \ @@ -779,24 +778,155 @@ vb2_error_t vb2api_kernel_phase1(struct vb2_context *ctx); vb2_error_t vb2api_kernel_phase2(struct vb2_context *ctx); /** - * Handle a normal boot. + * Finalize for kernel verification stage. * - * @param ctx Vboot context. - * @param kparams Params specific to loading the kernel + * Handle NO_BOOT flag. Also, check and roll forward kernel version. + * + * @param ctx Vboot context * @return VB2_SUCCESS, or error code on error. */ -vb2_error_t vb2api_normal_boot(struct vb2_context *ctx, - VbSelectAndLoadKernelParams *kparams); +vb2_error_t vb2api_kernel_finalize(struct vb2_context *ctx); + +struct vb2_kernel_params { + /* Inputs to vb2api_load_kernel(). */ + /* Destination buffer for kernel (normally at 0x100000 on x86). */ + void *kernel_buffer; + /* Size of kernel buffer in bytes. */ + uint32_t kernel_buffer_size; + + /* + * Outputs from vb2api_load_kernel(); valid only if it returns success. + */ + /* Handle of disk containing loaded kernel. */ + vb2ex_disk_handle_t disk_handle; + /* Partition number on disk to boot (1...M). */ + uint32_t partition_number; + /* Address of bootloader image in RAM. */ + uint64_t bootloader_address; + /* Size of bootloader image in bytes. */ + uint32_t bootloader_size; + /* UniquePartitionGuid for boot partition. */ + uint8_t partition_guid[16]; + /* Flags set by signer. */ + uint32_t flags; +}; + +/*****************************************************************************/ +/* Disk access */ + +/* Flags for vb2_disk_info */ + +/* + * Disk selection in the lower 16 bits (where the disk lives), and disk + * attributes in the higher 16 bits (extra information about the disk + * needed to access it correctly). + */ +#define VB2_DISK_FLAG_SELECT_MASK 0xffff +#define VB2_DISK_FLAG_ATTRIBUTE_MASK (0xffff << 16) + +/* Disk is removable. Example removable disks: SD cards, USB keys. */ +#define VB2_DISK_FLAG_REMOVABLE (1 << 0) +/* + * Disk is fixed. If this flag is present, disk is internal to the system and + * not removable. Example fixed disks: internal SATA SSD, eMMC. + */ +#define VB2_DISK_FLAG_FIXED (1 << 1) +/* + * Note that VB2_DISK_FLAG_REMOVABLE and VB2_DISK_FLAG_FIXED are + * mutually-exclusive for a single disk. VbExDiskGetInfo() may specify both + * flags to request disks of both types in a single call. + * + * At some point we could specify additional flags, but we don't currently + * have a way to make use of these: + * + * USB Device is known to be attached to USB. Note that the SD + * card reader inside x86 systems is attached to USB so this + * isn't super useful. + * SD Device is known to be a SD card. Note that external card + * readers might not return this information, so also of + * questionable use. + * READ_ONLY Device is known to be read-only. Could be used by recovery + * when processing read-only recovery image. + */ + +/* + * Disks are used in two ways: + * - As a random-access device to read and write the GPT + * - As a streaming device to read the kernel + * These are implemented differently on raw NAND vs eMMC/SATA/USB + * - On eMMC/SATA/USB, both of these refer to the same underlying + * storage, so they have the same size and LBA size. In this case, + * the GPT should not point to the same address as itself. + * - On raw NAND, the GPT is held on a portion of the SPI flash. + * Random access GPT operations refer to the SPI and streaming + * operations refer to NAND. The GPT may therefore point into + * the same offsets as itself. + * These types are distinguished by the following flag and vb2_disk_info + * has separate fields to describe the random-access ("GPT") and + * streaming aspects of the disk. If a disk is random-access (i.e. + * not raw NAND) then these fields are equal. + */ +#define VB2_DISK_FLAG_EXTERNAL_GPT (1 << 16) + +/* Information on a single disk. */ +struct vb2_disk_info { + /* Disk handle. */ + vb2ex_disk_handle_t handle; + /* Size of a random-access LBA sector in bytes. */ + uint64_t bytes_per_lba; + /* Number of random-access LBA sectors on the device. + * If streaming_lba_count is 0, this stands in for the size of the + * randomly accessed portion as well as the streaming portion. + * Otherwise, this is only the randomly-accessed portion. */ + uint64_t lba_count; + /* Number of streaming sectors on the device. */ + uint64_t streaming_lba_count; + /* Flags (see VB2_DISK_FLAG_* constants). */ + uint32_t flags; + /* + * Optional name string, for use in debugging. May be empty or null if + * not available. + */ + const char *name; +}; /** - * Finalize for kernel verification stage. + * Attempt to load kernel from the specified device. On success, the output + * fields of params will be filled. The caller should set the input fields of + * params. * - * Handle NO_BOOT flag. * * @param ctx Vboot context - * @return VB2_SUCCESS, or error code on error. + * @param params Params specific to loading the kernel + * @param disk_info Disk from which to read kernel + * + * @return VB2_SUCCESS, or non-zero error code. */ -vb2_error_t vb2api_kernel_finalize(struct vb2_context *ctx); +vb2_error_t vb2api_load_kernel(struct vb2_context *ctx, + struct vb2_kernel_params *params, + struct vb2_disk_info *disk_info); + +/* miniOS flags */ + +/* Boot from non-active miniOS partition only. */ +#define VB2_MINIOS_FLAG_NON_ACTIVE (1 << 0) + +/** + * Attempt to load miniOS kernel from the specified device. On success, the + * output fields of params will be filled. The caller should set the input + * fields of params. + * + * @param ctx Vboot context + * @param params Params specific to loading the kernel + * @param disk_info Disk from which to read kernel + * @param minios_flags Flags for miniOS + * + * @return VB2_SUCCESS, or non-zero error code. + */ +vb2_error_t vb2api_load_minios_kernel(struct vb2_context *ctx, + struct vb2_kernel_params *params, + struct vb2_disk_info *disk_info, + uint32_t minios_flags); /** * Load the verified boot block (vblock) for a kernel. diff --git a/firmware/2lib/include/2constants.h b/firmware/2lib/include/2constants.h index 96dc9995..c1e6bb91 100644 --- a/firmware/2lib/include/2constants.h +++ b/firmware/2lib/include/2constants.h @@ -80,6 +80,14 @@ #ifndef __ASSEMBLER__ #include <stdint.h> typedef uint32_t vb2_gbb_flags_t; +/* + * We use disk handles rather than indices. Using indices causes problems if + * a disk is removed/inserted in the middle of processing. + * + * TODO(b/181739551): move this to 2api.h when the VbExDisk* functions are + * removed from vboot_api.h. + */ +typedef void *vb2ex_disk_handle_t; #endif /* Size of legacy VbSharedDataHeader struct. Defined here to avoid including diff --git a/firmware/2lib/include/2recovery_reasons.h b/firmware/2lib/include/2recovery_reasons.h index 30dbd2e3..918e3327 100644 --- a/firmware/2lib/include/2recovery_reasons.h +++ b/firmware/2lib/include/2recovery_reasons.h @@ -205,7 +205,7 @@ enum vb2_nv_recovery { /* Shared data error in rewritable firmware */ VB2_RECOVERY_RW_SHARED_DATA = 0x46, - /* Test error from LoadKernel() (deprecated) */ + /* Test error from vb2api_load_kernel() (deprecated) */ VB2_RECOVERY_DEPRECATED_RW_TEST_LK = 0x47, /* No bootable disk found (deprecated, see 0x5a) */ diff --git a/firmware/2lib/include/2return_codes.h b/firmware/2lib/include/2return_codes.h index ccb50aa4..a7b79307 100644 --- a/firmware/2lib/include/2return_codes.h +++ b/firmware/2lib/include/2return_codes.h @@ -767,19 +767,19 @@ enum vb2_return_code { VB2_ERROR_DEPRECATED_EX_DIAG_TEST_INIT_FAILED, /********************************************************************** - * LoadKernel errors + * Kernel loading errors * * Should be ordered by specificity -- lower number means more specific. */ VB2_ERROR_LK = 0x100b0000, - /* Only an invalid kernel was found in LoadKernel() */ + /* Only an invalid kernel was found in vb2api_load_kernel() */ VB2_ERROR_LK_INVALID_KERNEL_FOUND = 0x100b1000, - /* No kernel partitions were found in LoadKernel() */ + /* No kernel partitions were found in vb2api_load_kernel() */ VB2_ERROR_LK_NO_KERNEL_FOUND = 0x100b2000, - /* No working block devices were found in VbTryLoadKernel() */ + /* No working block devices were found */ VB2_ERROR_LK_NO_DISK_FOUND = 0x100b3000, /********************************************************************** diff --git a/firmware/include/gpt_misc.h b/firmware/include/gpt_misc.h index aa46094f..e01e0dcf 100644 --- a/firmware/include/gpt_misc.h +++ b/firmware/include/gpt_misc.h @@ -76,9 +76,8 @@ enum { * depthcharge does not have logic to properly setup stored_on_device and * gpt_drive_sectors, but it does do a memset(gpt, 0, sizeof(GptData)). And so, * GPT_STORED_ON_DEVICE should be 0 to make stored_on_device compatible with - * present behavior. At the same time, in vboot_kernel:LoadKernel(), and - * cgpt_common:GptLoad(), we need to have simple shims to set gpt_drive_sectors - * to drive_sectors. + * present behavior. At the same time, in vb2api_load_kernel() and GptLoad(), + * we need to have simple shims to set gpt_drive_sectors to drive_sectors. * * TODO(namnguyen): Remove those shims when the firmware can set these fields. */ @@ -157,12 +156,12 @@ GptEntry *GptFindNthEntry(GptData *gpt, const Guid *guid, unsigned int n); * * Returns 0 if successful, 1 if error. */ -int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata); +int AllocAndReadGptData(vb2ex_disk_handle_t disk_handle, GptData *gptdata); /** * Write any changes for the GPT data back to the drive, then free the buffers. */ -int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData *gptdata); +int WriteAndFreeGptData(vb2ex_disk_handle_t disk_handle, GptData *gptdata); /** * Return 1 if the entry is unused, 0 if it is used. diff --git a/firmware/include/vboot_api.h b/firmware/include/vboot_api.h index 4dba0a06..4059accb 100644 --- a/firmware/include/vboot_api.h +++ b/firmware/include/vboot_api.h @@ -24,6 +24,7 @@ #include <stdint.h> #include <stdlib.h> +#include "../2lib/include/2constants.h" #include "../2lib/include/2return_codes.h" #include "gpt.h" @@ -32,165 +33,18 @@ extern "C" { #endif /* __cplusplus */ struct vb2_context; +struct vb2_disk_info; typedef struct VbSharedDataHeader VbSharedDataHeader; - -/*****************************************************************************/ -/* Main entry points from firmware into vboot_reference */ - -/* - * We use disk handles rather than indices. Using indices causes problems if - * a disk is removed/inserted in the middle of processing. - */ -typedef void *VbExDiskHandle_t; - -typedef struct VbSelectAndLoadKernelParams { - /* Inputs to VbTryLoadKernel() */ - /* Destination buffer for kernel (normally at 0x100000 on x86) */ - void *kernel_buffer; - /* Size of kernel buffer in bytes */ - uint32_t kernel_buffer_size; - - /* - * Outputs from VbTryLoadKernel(); valid only if it returns success. - */ - /* Handle of disk containing loaded kernel */ - VbExDiskHandle_t disk_handle; - /* Partition number on disk to boot (1...M) */ - uint32_t partition_number; - /* Address of bootloader image in RAM */ - uint64_t bootloader_address; - /* Size of bootloader image in bytes */ - uint32_t bootloader_size; - /* UniquePartitionGuid for boot partition */ - uint8_t partition_guid[16]; - /* Flags set by signer */ - uint32_t flags; -} VbSelectAndLoadKernelParams; - -/** - * Attempt loading a kernel from the specified type(s) of disks. - * - * If successful, sets kparams.disk_handle to the disk for the kernel and - * returns VB2_SUCCESS. - * - * @param ctx Vboot context - * @param disk_flags Flags to pass to VbExDiskGetInfo() - * @param kparams Params specific to loading the kernel - * @return VB2_SUCCESS or the most specific VB2_ERROR_LK error. - */ -vb2_error_t VbTryLoadKernel(struct vb2_context *ctx, uint32_t disk_flags, - VbSelectAndLoadKernelParams *kparams); - -/* miniOS flags */ - -/* Boot from non-active miniOS partition only */ -#define VB_MINIOS_FLAG_NON_ACTIVE (1 << 0) - -/** - * Attempt loading a miniOS kernel from internal disk. - * - * Scans sectors at the start and end of the disk, and looks for miniOS kernels - * starting at the beginning of the sector. Attempts loading any miniOS - * kernels found. - * - * If successful, sets lkp.disk_handle to the disk for the kernel and returns - * VB2_SUCCESS. - * - * @param ctx Vboot context - * @param minios_flags Flags for miniOS - * @param kparams Params specific to loading the kernel - * @return VB2_SUCCESS or the most specific VB2_ERROR_LK error. - */ -vb2_error_t VbTryLoadMiniOsKernel(struct vb2_context *ctx, - uint32_t minios_flags, - VbSelectAndLoadKernelParams *kparams); - /*****************************************************************************/ /* Disk access (previously in boot_device.h) */ -/* Flags for VbDisk APIs */ - -/* - * Disk selection in the lower 16 bits (where the disk lives), and disk - * attributes in the higher 16 bits (extra information about the disk - * needed to access it correctly). - */ -#define VB_DISK_FLAG_SELECT_MASK 0xffff -#define VB_DISK_FLAG_ATTRIBUTE_MASK (0xffff << 16) - -/* Disk is removable. Example removable disks: SD cards, USB keys. */ -#define VB_DISK_FLAG_REMOVABLE (1 << 0) -/* - * Disk is fixed. If this flag is present, disk is internal to the system and - * not removable. Example fixed disks: internal SATA SSD, eMMC. - */ -#define VB_DISK_FLAG_FIXED (1 << 1) -/* - * Note that VB_DISK_FLAG_REMOVABLE and VB_DISK_FLAG_FIXED are - * mutually-exclusive for a single disk. VbExDiskGetInfo() may specify both - * flags to request disks of both types in a single call. - * - * At some point we could specify additional flags, but we don't currently - * have a way to make use of these: - * - * USB Device is known to be attached to USB. Note that the SD - * card reader inside x86 systems is attached to USB so this - * isn't super useful. - * SD Device is known to be a SD card. Note that external card - * readers might not return this information, so also of - * questionable use. - * READ_ONLY Device is known to be read-only. Could be used by recovery - * when processing read-only recovery image. - */ - -/* - * Disks are used in two ways: - * - As a random-access device to read and write the GPT - * - As a streaming device to read the kernel - * These are implemented differently on raw NAND vs eMMC/SATA/USB - * - On eMMC/SATA/USB, both of these refer to the same underlying - * storage, so they have the same size and LBA size. In this case, - * the GPT should not point to the same address as itself. - * - On raw NAND, the GPT is held on a portion of the SPI flash. - * Random access GPT operations refer to the SPI and streaming - * operations refer to NAND. The GPT may therefore point into - * the same offsets as itself. - * These types are distinguished by the following flag and VbDiskInfo - * has separate fields to describe the random-access ("GPT") and - * streaming aspects of the disk. If a disk is random-access (i.e. - * not raw NAND) then these fields are equal. - */ -#define VB_DISK_FLAG_EXTERNAL_GPT (1 << 16) - -/* Information on a single disk */ -typedef struct VbDiskInfo { - /* Disk handle */ - VbExDiskHandle_t handle; - /* Size of a random-access LBA sector in bytes */ - uint64_t bytes_per_lba; - /* Number of random-access LBA sectors on the device. - * If streaming_lba_count is 0, this stands in for the size of the - * randomly accessed portion as well as the streaming portion. - * Otherwise, this is only the randomly-accessed portion. */ - uint64_t lba_count; - /* Number of streaming sectors on the device */ - uint64_t streaming_lba_count; - /* Flags (see VB_DISK_FLAG_* constants) */ - uint32_t flags; - /* - * Optional name string, for use in debugging. May be empty or null if - * not available. - */ - const char *name; -} VbDiskInfo; - /** * Store information into [info] for all disks (storage devices) attached to * the system which match all of the disk_flags. * * On output, count indicates how many disks are present, and [infos_ptr] - * points to a [count]-sized array of VbDiskInfo structs with the information + * points to a [count]-sized array of vb2_disk_info structs with the information * on those disks; this pointer must be freed by calling VbExDiskFreeInfo(). * If count=0, infos_ptr may point to NULL. If [infos_ptr] points to NULL * because count=0 or error, it is not necessary to call VbExDiskFreeInfo(). @@ -201,7 +55,7 @@ typedef struct VbDiskInfo { * The firmware must not alter or free the list pointed to by [infos_ptr] until * VbExDiskFreeInfo() is called. */ -vb2_error_t VbExDiskGetInfo(VbDiskInfo **infos_ptr, uint32_t *count, +vb2_error_t VbExDiskGetInfo(struct vb2_disk_info **infos_ptr, uint32_t *count, uint32_t disk_flags); /** @@ -210,8 +64,8 @@ vb2_error_t VbExDiskGetInfo(VbDiskInfo **infos_ptr, uint32_t *count, * that handle remains valid after this call; all other handles from the info * list need not remain valid after this call. */ -vb2_error_t VbExDiskFreeInfo(VbDiskInfo *infos, - VbExDiskHandle_t preserve_handle); +vb2_error_t VbExDiskFreeInfo(struct vb2_disk_info *infos, + vb2ex_disk_handle_t preserve_handle); /** * Read lba_count LBA sectors, starting at sector lba_start, from the disk, @@ -224,7 +78,7 @@ vb2_error_t VbExDiskFreeInfo(VbDiskInfo *infos, * which as been removed), the function must return error but must not * crash. */ -vb2_error_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start, +vb2_error_t VbExDiskRead(vb2ex_disk_handle_t handle, uint64_t lba_start, uint64_t lba_count, void *buffer); /** @@ -238,7 +92,7 @@ vb2_error_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start, * which as been removed), the function must return error but must not * crash. */ -vb2_error_t VbExDiskWrite(VbExDiskHandle_t handle, uint64_t lba_start, +vb2_error_t VbExDiskWrite(vb2ex_disk_handle_t handle, uint64_t lba_start, uint64_t lba_count, const void *buffer); /* Streaming read interface */ @@ -258,7 +112,7 @@ typedef void *VbExStream_t; * device. It is not used to access the GPT. The size of the content addressed * is within streaming_lba_count. */ -vb2_error_t VbExStreamOpen(VbExDiskHandle_t handle, uint64_t lba_start, +vb2_error_t VbExStreamOpen(vb2ex_disk_handle_t handle, uint64_t lba_start, uint64_t lba_count, VbExStream_t *stream_ptr); /** diff --git a/firmware/lib/gpt_misc.c b/firmware/lib/gpt_misc.c index 641ef37b..b42d4660 100644 --- a/firmware/lib/gpt_misc.c +++ b/firmware/lib/gpt_misc.c @@ -19,7 +19,7 @@ * * Returns 0 if successful, 1 if error. */ -int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata) +int AllocAndReadGptData(vb2ex_disk_handle_t disk_handle, GptData *gptdata) { int primary_valid = 0, secondary_valid = 0; @@ -126,7 +126,7 @@ int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata) * * Returns 0 if successful, 1 if error. */ -int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData *gptdata) +int WriteAndFreeGptData(vb2ex_disk_handle_t disk_handle, GptData *gptdata) { int skip_primary = 0; GptHeader *header; diff --git a/firmware/lib/include/load_kernel_fw.h b/firmware/lib/include/load_kernel_fw.h deleted file mode 100644 index 76d25560..00000000 --- a/firmware/lib/include/load_kernel_fw.h +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * High-level firmware API for loading and verifying kernel. - * (Firmware Portion) - */ - -#ifndef VBOOT_REFERENCE_LOAD_KERNEL_FW_H_ -#define VBOOT_REFERENCE_LOAD_KERNEL_FW_H_ - -#include "vboot_api.h" - -/** - * Attempt to load kernel from the specified device. - * - * @param ctx Vboot context - * @param params Params specific to loading the kernel - * @param disk_info Disk from which to read kernel - * - * Returns VB2_SUCCESS if successful. If unsuccessful, returns an error code. - */ -vb2_error_t LoadKernel(struct vb2_context *ctx, - VbSelectAndLoadKernelParams *params, - VbDiskInfo *disk_info); - -/** - * Attempt to load miniOS kernel from the specified device. - * - * @param ctx Vboot context - * @param params Params specific to loading the kernel - * @param disk_info Disk from which to read kernel - * @param minios_flags Flags for miniOS - * - * Returns VB2_SUCCESS if successful. If unsuccessful, returns an error code. - */ -vb2_error_t LoadMiniOsKernel(struct vb2_context *ctx, - VbSelectAndLoadKernelParams *params, - VbDiskInfo *disk_info, uint32_t minios_flags); - -#endif /* VBOOT_REFERENCE_LOAD_KERNEL_FW_H_ */ diff --git a/firmware/lib/include/vboot_struct.h b/firmware/lib/include/vboot_struct.h index edcb2b45..ea4a9ee9 100644 --- a/firmware/lib/include/vboot_struct.h +++ b/firmware/lib/include/vboot_struct.h @@ -35,9 +35,9 @@ extern "C" { Deprecated as part of chromium:1010389. */ #define VBSD_FWB_TRIED 0x00000001 /* - * LoadKernel() verified the good kernel keyblock using the kernel subkey from - * the firmware. If this flag is not present, it just used the hash of the - * kernel keyblock. + * vb2api_load_kernel() verified the good kernel keyblock using the kernel + * subkey from the firmware. If this flag is not present, it just used the + * hash of the kernel keyblock. */ #define VBSD_KERNEL_KEY_VERIFIED 0x00000002 /* Developer switch was enabled at boot time */ @@ -111,21 +111,8 @@ typedef struct VbSharedDataHeader { /* Firmware lowest version found */ uint32_t fw_version_lowest; - /* Debugging information from LoadKernel() */ - /* Number of times LoadKernel() called */ - uint32_t lk_call_count; /* Reserved for padding */ - uint8_t reserved3[896]; - - /* - * Offset and size of supplemental kernel data. Reserve space for - * these fields now, so that future LoadKernel() versions can store - * information there without needing to shift down whatever data the - * original LoadFirmware() might have put immediately following its - * VbSharedDataHeader. - */ - uint64_t kernel_supplemental_offset; - uint64_t kernel_supplemental_size; + uint8_t reserved3[916]; /* * Fields added in version 2. Before accessing, make sure that diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c deleted file mode 100644 index 0fdc2d33..00000000 --- a/firmware/lib/vboot_api_kernel.c +++ /dev/null @@ -1,123 +0,0 @@ -/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * High-level firmware wrapper API - entry points for kernel selection - */ - -#include "2api.h" -#include "2common.h" -#include "2misc.h" -#include "2nvstorage.h" -#include "2rsa.h" -#include "2secdata.h" -#include "2sysincludes.h" -#include "load_kernel_fw.h" -#include "vboot_api.h" -#include "vboot_struct.h" - -static int is_valid_disk(VbDiskInfo *info, uint32_t disk_flags) -{ - return info->bytes_per_lba >= 512 && - (info->bytes_per_lba & (info->bytes_per_lba - 1)) == 0 && - info->lba_count >= 16 && - (info->flags & disk_flags & VB_DISK_FLAG_SELECT_MASK) && - ((info->flags & VB_DISK_FLAG_SELECT_MASK) & - ((info->flags & VB_DISK_FLAG_SELECT_MASK) - 1)) == 0; -} - -static vb2_error_t VbTryLoadKernelImpl(struct vb2_context *ctx, - uint32_t disk_flags, int minios, - uint32_t minios_flags, - VbSelectAndLoadKernelParams *kparams) -{ - vb2_error_t rv = VB2_ERROR_LK_NO_DISK_FOUND; - VbDiskInfo* disk_info = NULL; - uint32_t disk_count = 0; - uint32_t i; - vb2_error_t new_rv; - - VB2_ASSERT(kparams); - kparams->disk_handle = NULL; - - /* Find disks */ - if (VB2_SUCCESS != VbExDiskGetInfo(&disk_info, &disk_count, disk_flags)) - disk_count = 0; - - /* Loop over disks */ - for (i = 0; i < disk_count; i++) { - VB2_DEBUG("trying disk %d\n", (int)i); - - if (!is_valid_disk(&disk_info[i], disk_flags)) { - VB2_DEBUG(" skipping: bytes_per_lba=%" PRIu64 - " lba_count=%" PRIu64 " flags=%#x\n", - disk_info[i].bytes_per_lba, - disk_info[i].lba_count, - disk_info[i].flags); - continue; - } - kparams->disk_handle = disk_info[i].handle; - - if (minios) { - new_rv = LoadMiniOsKernel(ctx, kparams, - &disk_info[i], minios_flags); - VB2_DEBUG("LoadMiniOsKernel() = %#x\n", new_rv); - } else { - new_rv = LoadKernel(ctx, kparams, &disk_info[i]); - VB2_DEBUG("LoadKernel() = %#x\n", new_rv); - } - - /* Stop now if we found a kernel. */ - if (VB2_SUCCESS == new_rv) { - VbExDiskFreeInfo(disk_info, disk_info[i].handle); - return VB2_SUCCESS; - } - - /* Don't update error if we already have a more specific one. */ - if (VB2_ERROR_LK_INVALID_KERNEL_FOUND != rv) - rv = new_rv; - } - - /* If we drop out of the loop, we didn't find any usable kernel. */ - if (!(ctx->flags & VB2_CONTEXT_RECOVERY_MODE) && - !(ctx->flags & VB2_CONTEXT_DEVELOPER_MODE)) { - switch (rv) { - case VB2_ERROR_LK_INVALID_KERNEL_FOUND: - vb2api_fail(ctx, VB2_RECOVERY_RW_INVALID_OS, rv); - break; - case VB2_ERROR_LK_NO_KERNEL_FOUND: - vb2api_fail(ctx, VB2_RECOVERY_RW_NO_KERNEL, rv); - break; - case VB2_ERROR_LK_NO_DISK_FOUND: - vb2api_fail(ctx, VB2_RECOVERY_RW_NO_DISK, rv); - break; - default: - vb2api_fail(ctx, VB2_RECOVERY_LK_UNSPECIFIED, rv); - break; - } - } - - /* If we didn't find any good kernels, don't return a disk handle. */ - VbExDiskFreeInfo(disk_info, NULL); - - return rv; -} - -test_mockable -vb2_error_t VbTryLoadKernel(struct vb2_context *ctx, uint32_t disk_flags, - VbSelectAndLoadKernelParams *kparams) -{ - ctx->flags &= ~VB2_CONTEXT_DISABLE_TPM; - return VbTryLoadKernelImpl(ctx, disk_flags, 0, 0, kparams); -} - -test_mockable -vb2_error_t VbTryLoadMiniOsKernel(struct vb2_context *ctx, - uint32_t minios_flags, - VbSelectAndLoadKernelParams *kparams) -{ - VB2_TRY(VbTryLoadKernelImpl(ctx, VB_DISK_FLAG_FIXED, 1, minios_flags, - kparams)); - ctx->flags |= VB2_CONTEXT_DISABLE_TPM; - return VB2_SUCCESS; -} diff --git a/firmware/stub/vboot_api_stub_disk.c b/firmware/stub/vboot_api_stub_disk.c index 3244dc65..dd24c21d 100644 --- a/firmware/stub/vboot_api_stub_disk.c +++ b/firmware/stub/vboot_api_stub_disk.c @@ -17,7 +17,7 @@ __attribute__((weak)) -vb2_error_t VbExDiskGetInfo(VbDiskInfo** infos_ptr, uint32_t* count, +vb2_error_t VbExDiskGetInfo(struct vb2_disk_info **infos_ptr, uint32_t *count, uint32_t disk_flags) { *infos_ptr = NULL; @@ -27,15 +27,15 @@ vb2_error_t VbExDiskGetInfo(VbDiskInfo** infos_ptr, uint32_t* count, __attribute__((weak)) -vb2_error_t VbExDiskFreeInfo(VbDiskInfo* infos_ptr, - VbExDiskHandle_t preserve_handle) +vb2_error_t VbExDiskFreeInfo(struct vb2_disk_info *infos_ptr, + vb2ex_disk_handle_t preserve_handle) { return VB2_SUCCESS; } __attribute__((weak)) -vb2_error_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start, +vb2_error_t VbExDiskRead(vb2ex_disk_handle_t handle, uint64_t lba_start, uint64_t lba_count, void* buffer) { return VB2_SUCCESS; @@ -43,7 +43,7 @@ vb2_error_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start, __attribute__((weak)) -vb2_error_t VbExDiskWrite(VbExDiskHandle_t handle, uint64_t lba_start, +vb2_error_t VbExDiskWrite(vb2ex_disk_handle_t handle, uint64_t lba_start, uint64_t lba_count, const void* buffer) { return VB2_SUCCESS; diff --git a/firmware/stub/vboot_api_stub_stream.c b/firmware/stub/vboot_api_stub_stream.c index 68e7ec7d..1a6a65cd 100644 --- a/firmware/stub/vboot_api_stub_stream.c +++ b/firmware/stub/vboot_api_stub_stream.c @@ -16,7 +16,7 @@ /* Internal struct to simulate a stream for sector-based disks */ struct disk_stream { /* Disk handle */ - VbExDiskHandle_t handle; + vb2ex_disk_handle_t handle; /* Next sector to read */ uint64_t sector; @@ -26,7 +26,7 @@ struct disk_stream { }; __attribute__((weak)) -vb2_error_t VbExStreamOpen(VbExDiskHandle_t handle, uint64_t lba_start, +vb2_error_t VbExStreamOpen(vb2ex_disk_handle_t handle, uint64_t lba_start, uint64_t lba_count, VbExStream_t *stream) { struct disk_stream *s; |