/* Copyright (c) 2014 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. * * Routines for verifying a kernel or disk image */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "host_common.h" #include "util_misc.h" #include "vboot_common.h" #include "vboot_api.h" #include "vboot_kernel.h" static uint8_t *diskbuf; static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE]; static VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data; static VbNvContext nvc; static LoadKernelParams params; static VbCommonParams cparams; VbError_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start, uint64_t lba_count, void *buffer) { if (handle != (VbExDiskHandle_t)1) return VBERROR_UNKNOWN; if (lba_start >= params.streaming_lba_count) return VBERROR_UNKNOWN; if (lba_start + lba_count > params.streaming_lba_count) return VBERROR_UNKNOWN; memcpy(buffer, diskbuf + lba_start * 512, lba_count * 512); return VBERROR_SUCCESS; } VbError_t VbExDiskWrite(VbExDiskHandle_t handle, uint64_t lba_start, uint64_t lba_count, const void *buffer) { if (handle != (VbExDiskHandle_t)1) return VBERROR_UNKNOWN; if (lba_start >= params.streaming_lba_count) return VBERROR_UNKNOWN; if (lba_start + lba_count > params.streaming_lba_count) return VBERROR_UNKNOWN; memcpy(diskbuf + lba_start * 512, buffer, lba_count * 512); return VBERROR_SUCCESS; } static void print_help(const char *progname) { printf("\nUsage: %s <disk_image> <kernel.vbpubk>\n\n", progname); } int main(int argc, char *argv[]) { VbPublicKey *kernkey; uint64_t disk_bytes = 0; int rv; if (argc < 3) { print_help(argv[0]); return 1; } /* Load disk file */ /* TODO: is it better to mmap() in the long run? */ diskbuf = ReadFile(argv[1], &disk_bytes); if (!diskbuf) { fprintf(stderr, "Can't read disk file %s\n", argv[1]); return 1; } /* Read public key */ kernkey = PublicKeyRead(argv[2]); if (!kernkey) { fprintf(stderr, "Can't read key file %s\n", argv[2]); return 1; } /* Set up shared data blob */ VbSharedDataInit(shared, sizeof(shared_data)); VbSharedDataSetKernelKey(shared, kernkey); /* TODO: optional TPM current kernel version */ /* Set up params */ params.shared_data_blob = shared_data; params.shared_data_size = sizeof(shared_data); params.disk_handle = (VbExDiskHandle_t)1; params.bytes_per_lba = 512; params.streaming_lba_count = disk_bytes / 512; params.gpt_lba_count = params.streaming_lba_count; params.kernel_buffer_size = 16 * 1024 * 1024; params.kernel_buffer = malloc(params.kernel_buffer_size); if (!params.kernel_buffer) { fprintf(stderr, "Can't allocate kernel buffer\n"); 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; /* * LoadKernel() cares only about VBNV_DEV_BOOT_SIGNED_ONLY, and only in * dev mode. So just use defaults. */ VbNvSetup(&nvc); params.nv_context = &nvc; /* Try loading kernel */ rv = LoadKernel(¶ms, &cparams); if (rv != VBERROR_SUCCESS) { fprintf(stderr, "LoadKernel() failed with code %d\n", rv); return 1; } printf("Found a good kernel.\n"); printf("Partition number: %d\n", (int)params.partition_number); printf("Bootloader address: 0x%" PRIx64 "\n", params.bootloader_address); /* TODO: print other things (partition GUID, nv_context, shared_data) */ printf("Yaay!\n"); return 0; }