From ad6824ba4fc18c4eba4e98ba2b2e476dfcedbbae Mon Sep 17 00:00:00 2001 From: Randall Spangler Date: Wed, 16 Mar 2011 19:07:33 -0700 Subject: Added timing data to VbSharedData. Change-Id: I8d52765227fd3355431bebc77dfbe0106c889eca BUG=chrome-os-partner:2748 TEST=compiles; will be porting to H2C next Review URL: http://codereview.chromium.org/6672068 --- firmware/include/utility.h | 14 ++++++++++++++ firmware/include/vboot_struct.h | 12 +++++++++++- firmware/lib/vboot_firmware.c | 4 ++++ firmware/lib/vboot_kernel.c | 19 ++++++++++++------- firmware/stub/utility_stub.c | 13 ++++++++++++- 5 files changed, 53 insertions(+), 9 deletions(-) diff --git a/firmware/include/utility.h b/firmware/include/utility.h index 3c4a3bb5..4f88ab9c 100644 --- a/firmware/include/utility.h +++ b/firmware/include/utility.h @@ -96,4 +96,18 @@ int SafeMemcmp(const void* s1, const void* s2, size_t n); #define memset _do_not_use_standard_memset #endif +/* Read a high-resolution timer. */ +uint64_t VbGetTimer(void); + +/* Return the maximum frequency for the high-resolution timer, in Hz. + * + * Note that this call MUST be fast; the implementation must not + * attempt to actually measure the frequency. This function need only + * return an upper bound for the timer frequency, so that minimum + * delays can be established. For example, if the same BIOS can run + * on CPUs where the timer frequency varies between 1.2GHz and 1.8GHz, + * return 1800000000 (or even 2000000000). */ +uint64_t VbGetTimerMaxFreq(void); + + #endif /* VBOOT_REFERENCE_UTILITY_H_ */ diff --git a/firmware/include/vboot_struct.h b/firmware/include/vboot_struct.h index 1e988ee1..bb47403b 100644 --- a/firmware/include/vboot_struct.h +++ b/firmware/include/vboot_struct.h @@ -157,10 +157,20 @@ typedef struct VbSharedDataHeader { VbPublicKey kernel_subkey; /* Kernel subkey, from firmware */ uint64_t kernel_subkey_data_offset; /* Offset of kernel subkey data from * start of this struct */ - uint64_t kernel_subkey_data_size; /* Offset of kernel subkey data */ + uint64_t kernel_subkey_data_size; /* Size of kernel subkey data */ uint64_t flags; /* Flags */ + /* Timer values from VbGetTimer(). Unused values are set to 0. If a + * function is called mutiple times, these are the times from the + * most recent call. */ + uint64_t timer_load_firmware_start_enter; /* LoadFirmwareStart() - enter */ + uint64_t timer_load_firmware_start_exit; /* LoadFirmwareStart() - exit */ + uint64_t timer_load_firmware_enter; /* LoadFirmware() - enter */ + uint64_t timer_load_firmware_exit; /* LoadFirmware() - exit */ + uint64_t timer_load_kernel_enter; /* LoadKernel() - enter */ + uint64_t timer_load_kernel_exit; /* LoadKernel() - exit */ + /* After read-only firmware which uses version 1 is released, any additional * fields must be added below, and the struct version must be increased. * Before reading/writing those fields, make sure that the struct being diff --git a/firmware/lib/vboot_firmware.c b/firmware/lib/vboot_firmware.c index 6265acc7..9172e5c8 100644 --- a/firmware/lib/vboot_firmware.c +++ b/firmware/lib/vboot_firmware.c @@ -36,6 +36,7 @@ void UpdateFirmwareBodyHash(LoadFirmwareParams* params, int LoadFirmwareSetup(void) { /* TODO: handle test errors (requires passing in VbNvContext) */ + /* TODO: record timer values (requires passing in VbSharedData) */ /* TODO: start initializing the TPM */ return LOAD_FIRMWARE_SUCCESS; } @@ -76,6 +77,7 @@ int LoadFirmware(LoadFirmwareParams* params) { recovery = VBNV_RECOVERY_RO_SHARED_DATA; goto LoadFirmwareExit; } + shared->timer_load_firmware_enter = VbGetTimer(); /* Handle test errors */ VbNvGet(vnc, VBNV_TEST_ERROR_FUNC, &test_err); @@ -352,6 +354,8 @@ LoadFirmwareExit: recovery : VBNV_RECOVERY_NOT_REQUESTED); VbNvTeardown(vnc); + shared->timer_load_firmware_exit = VbGetTimer(); + /* Note that we don't reduce params->shared_data_size to shared->data_used, * since we want to leave space for LoadKernel() to add to the shared data * buffer. */ diff --git a/firmware/lib/vboot_kernel.c b/firmware/lib/vboot_kernel.c index 83fb3fed..e50fd0f6 100644 --- a/firmware/lib/vboot_kernel.c +++ b/firmware/lib/vboot_kernel.c @@ -141,6 +141,7 @@ int LoadKernel(LoadKernelParams* params) { int retval = LOAD_KERNEL_RECOVERY; int recovery = VBNV_RECOVERY_RO_UNSPECIFIED; + uint64_t timer_enter = VbGetTimer(); /* Setup NV storage */ VbNvSetup(vnc); @@ -155,6 +156,11 @@ int LoadKernel(LoadKernelParams* params) { goto LoadKernelExit; } + /* Clear output params in case we fail */ + params->partition_number = 0; + params->bootloader_address = 0; + params->bootloader_size = 0; + /* Handle test errors */ VbNvGet(vnc, VBNV_TEST_ERROR_FUNC, &test_err); if (VBNV_TEST_ERROR_LOAD_KERNEL == test_err) { @@ -206,11 +212,6 @@ int LoadKernel(LoadKernelParams* params) { dev_switch = 0; /* Always do a fully verified boot */ } - /* Clear output params in case we fail */ - params->partition_number = 0; - params->bootloader_address = 0; - params->bootloader_size = 0; - if (kBootRecovery == boot_mode) { /* Initialize the shared data structure, since LoadFirmware() didn't do it * for us. */ @@ -556,9 +557,13 @@ LoadKernelExit: recovery : VBNV_RECOVERY_NOT_REQUESTED); VbNvTeardown(vnc); - /* Store how much shared data we used, if any */ - if (shared) + if (shared) { + /* Save timer values */ + shared->timer_load_kernel_enter = timer_enter; + shared->timer_load_kernel_exit = VbGetTimer(); + /* Store how much shared data we used, if any */ params->shared_data_size = shared->data_used; + } return retval; } diff --git a/firmware/stub/utility_stub.c b/firmware/stub/utility_stub.c index 61417856..2d56f72b 100644 --- a/firmware/stub/utility_stub.c +++ b/firmware/stub/utility_stub.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. +/* Copyright (c) 2011 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. * @@ -13,6 +13,7 @@ #include #include #include +#include void error(const char *format, ...) { va_list ap; @@ -51,3 +52,13 @@ int Memcmp(const void* src1, const void* src2, size_t n) { void* Memcpy(void* dest, const void* src, uint64_t n) { return memcpy(dest, src, (size_t)n); } + +uint64_t VbGetTimer(void) { + struct timeval tv; + gettimeofday(&tv, NULL); + return (uint64_t)tv.tv_sec * 1000000 + (uint64_t)tv.tv_usec; +} + +uint64_t VbGetTimerMaxFreq(void) { + return UINT64_C(1000000); +} -- cgit v1.2.1