Print LoadKernel() debug data from VbSharedData

Change-Id: I60cf9c4dd07e83b1ed1a5bac8a3ce8c2a54df45b

R=reinauer@chromium.org
BUG=chrome-os-partner:2748
TEST=manually check output of 'crossystem vdat_lkdebug'

Review URL: http://codereview.chromium.org/6685097
This commit is contained in:
Randall Spangler
2011-03-21 11:04:50 -07:00
parent cabe6b3514
commit 7141571d55
3 changed files with 139 additions and 15 deletions

View File

@@ -203,6 +203,7 @@ typedef struct VbSharedDataKernelPart {
uint8_t gpt_index; /* Index of partition in GPT */
uint8_t check_result; /* Check result; see VBSD_LKP_CHECK_* */
uint8_t flags; /* Flags (see VBSD_LKP_FLAG_* */
uint8_t reserved0; /* Reserved for padding */
} VbSharedDataKernelPart;
/* Number of kernel partitions to track per call. Must be power of 2. */
@@ -234,6 +235,7 @@ typedef struct VbSharedDataKernelCall {
uint8_t test_error_num; /* Test error number, if non-zero */
uint8_t return_code; /* Return code from LoadKernel() */
uint8_t kernel_parts_found; /* Number of kernel partitions found */
uint8_t reserved0[7]; /* Reserved for padding */
VbSharedDataKernelPart parts[VBSD_MAX_KERNEL_PARTS]; /* Data on kernels */
} VbSharedDataKernelCall;
@@ -261,6 +263,7 @@ typedef struct VbSharedDataHeader {
uint64_t data_size; /* Size of shared data buffer in bytes */
uint64_t data_used; /* Amount of shared data used so far */
uint32_t flags; /* Flags */
uint32_t reserved0; /* Reserved for padding */
VbPublicKey kernel_subkey; /* Kernel subkey, from firmware */
uint64_t kernel_subkey_data_offset; /* Offset of kernel subkey data from
@@ -286,6 +289,7 @@ typedef struct VbSharedDataHeader {
uint8_t check_fw_b_result; /* Result of checking RW firmware B */
uint8_t firmware_index; /* Firmware index returned by
* LoadFirmware() or 0xFF if failure */
uint8_t reserved1; /* Reserved for padding */
uint32_t fw_version_tpm_start; /* Firmware TPM version at start of
* LoadFirmware() */
uint32_t fw_version_lowest; /* Firmware lowest version found */

View File

@@ -95,7 +95,8 @@ typedef struct {
/* Fields that GetVdatString() can get */
typedef enum VdatStringField {
VDAT_STRING_TIMERS = 0, /* Timer values */
VDAT_STRING_LOAD_FIRMWARE_DEBUG /* LoadFirmware() debug information */
VDAT_STRING_LOAD_FIRMWARE_DEBUG, /* LoadFirmware() debug information */
VDAT_STRING_LOAD_KERNEL_DEBUG /* LoadKernel() debug information */
} VdatStringField;
@@ -618,10 +619,123 @@ int VbGetCrosDebug(void) {
}
char* GetVdatLoadFirmwareDebug(char* dest, int size,
const VbSharedDataHeader* sh) {
snprintf(dest, size,
"Check A result=%d\n"
"Check B result=%d\n"
"Firmware index booted=0x%02x\n"
"TPM combined version at start=0x%08x\n"
"Lowest combined version from firmware=0x%08x\n",
sh->check_fw_a_result,
sh->check_fw_b_result,
sh->firmware_index,
sh->fw_version_tpm_start,
sh->fw_version_lowest);
return dest;
}
#define TRUNCATED "\n(truncated)\n"
char* GetVdatLoadKernelDebug(char* dest, int size,
const VbSharedDataHeader* sh) {
int used = 0;
int first_call_tracked = 0;
int call;
/* Make sure we have space for truncation warning */
if (size < strlen(TRUNCATED) + 1)
return NULL;
size -= strlen(TRUNCATED) + 1;
used += snprintf(
dest + used, size - used,
"Calls to LoadKernel()=%d\n",
sh->lk_call_count);
if (used > size)
goto LoadKernelDebugExit;
/* Report on the last calls */
if (sh->lk_call_count > VBSD_MAX_KERNEL_CALLS)
first_call_tracked = sh->lk_call_count - VBSD_MAX_KERNEL_CALLS;
for (call = first_call_tracked; call < sh->lk_call_count; call++) {
const VbSharedDataKernelCall* shc =
sh->lk_calls + (call & (VBSD_MAX_KERNEL_CALLS - 1));
int first_part_tracked = 0;
int part;
used += snprintf(
dest + used, size - used,
"Call %d:\n"
" Boot flags=0x%02x\n"
" Boot mode=%d\n"
" Test error=%d\n"
" Return code=%d\n"
" Debug flags=0x%02x\n"
" Drive sectors=%" PRIu64 "\n"
" Sector size=%d\n"
" Check result=%d\n"
" Kernel partitions found=%d\n",
call + 1,
shc->boot_flags,
shc->boot_mode,
shc->test_error_num,
shc->return_code,
shc->flags,
shc->sector_count,
shc->sector_size,
shc->check_result,
shc->kernel_parts_found);
if (used > size)
goto LoadKernelDebugExit;
/* If we found too many partitions, only prints ones where the
* structure has info. */
if (shc->kernel_parts_found > VBSD_MAX_KERNEL_PARTS)
first_part_tracked = shc->kernel_parts_found - VBSD_MAX_KERNEL_PARTS;
/* Report on the partitions checked */
for (part = first_part_tracked; part < shc->kernel_parts_found; part++) {
const VbSharedDataKernelPart* shp =
shc->parts + (part & (VBSD_MAX_KERNEL_PARTS - 1));
used += snprintf(
dest + used, size - used,
" Kernel %d:\n"
" GPT index=%d\n"
" Start sector=%" PRIu64 "\n"
" Sector count=%" PRIu64 "\n"
" Combined version=0x%08x\n"
" Check result=%d\n"
" Debug flags=0x%02x\n",
part + 1,
shp->gpt_index,
shp->sector_start,
shp->sector_count,
shp->combined_version,
shp->check_result,
shp->flags);
if (used > size)
goto LoadKernelDebugExit;
}
}
LoadKernelDebugExit:
/* Warn if data was truncated; we left space for this above. */
if (used > size)
strcat(dest, TRUNCATED);
return dest;
}
char* GetVdatString(char* dest, int size, VdatStringField field)
{
VbSharedDataHeader* sh;
AcpiBuffer* ab = VbGetBuffer(ACPI_VDAT_PATH);
char* value = dest;
if (!ab)
return NULL;
@@ -642,13 +756,11 @@ char* GetVdatString(char* dest, int size, VdatStringField field)
break;
case VDAT_STRING_LOAD_FIRMWARE_DEBUG:
snprintf(dest, size,
"check=%d,%d index=0x%02x tpmver=0x%x lowestver=0x%x",
sh->check_fw_a_result,
sh->check_fw_b_result,
sh->firmware_index,
sh->fw_version_tpm_start,
sh->fw_version_lowest);
value = GetVdatLoadFirmwareDebug(dest, size, sh);
break;
case VDAT_STRING_LOAD_KERNEL_DEBUG:
value = GetVdatLoadKernelDebug(dest, size, sh);
break;
default:
@@ -657,7 +769,7 @@ char* GetVdatString(char* dest, int size, VdatStringField field)
}
Free(ab);
return dest;
return value;
}
@@ -819,6 +931,8 @@ const char* VbGetSystemPropertyString(const char* name, char* dest, int size) {
return GetVdatString(dest, size, VDAT_STRING_TIMERS);
} else if (!strcasecmp(name, "vdat_lfdebug")) {
return GetVdatString(dest, size, VDAT_STRING_LOAD_FIRMWARE_DEBUG);
} else if (!strcasecmp(name, "vdat_lkdebug")) {
return GetVdatString(dest, size, VDAT_STRING_LOAD_KERNEL_DEBUG);
} else
return NULL;
}

View File

@@ -11,6 +11,9 @@
#include "crossystem.h"
/* Max length of a string parameter */
#define MAX_STRING 8192
/* Flags for Param */
#define IS_STRING 0x01 /* String (not present = integer) */
#define CAN_WRITE 0x02 /* Writable (not present = read-only */
@@ -52,7 +55,6 @@ const Param sys_param_list[] = {
{"ecfw_act", IS_STRING, "Active EC firmware"},
{"kernkey_vfy", IS_STRING, "Type of verification done on kernel key block"},
{"vdat_timers", IS_STRING, "Timer values from VbSharedData"},
{"vdat_lfdebug", IS_STRING, "LoadFirmware() debug data VbSharedData"},
/* Writable integers */
{"nvram_cleared", CAN_WRITE, "Have NV settings been lost? Write 0 to clear"},
{"kern_nv", CAN_WRITE, "Non-volatile field for kernel use", "0x%08x"},
@@ -61,7 +63,11 @@ const Param sys_param_list[] = {
{"fwb_tries", CAN_WRITE, "Try firmware B count (writable)"},
{"vbtest_errfunc", CAN_WRITE, "Verified boot test error function (writable)"},
{"vbtest_errno", CAN_WRITE, "Verified boot test error number (writable)"},
/* Fields not shown in a print-all list */
{"vdat_lfdebug", IS_STRING|NO_PRINT_ALL,
"LoadFirmware() debug data (not in print-all)"},
{"vdat_lkdebug", IS_STRING|NO_PRINT_ALL,
"LoadKernel() debug data (not in print-all)"},
/* Terminate with null name */
{NULL, 0, NULL}
};
@@ -125,7 +131,7 @@ int SetParam(const Param* p, const char* value) {
* Returns 0 if success (match), non-zero if error (mismatch). */
int CheckParam(const Param* p, char* expect) {
if (p->flags & IS_STRING) {
char buf[256];
char buf[MAX_STRING];
const char* v = VbGetSystemPropertyString(p->name, buf, sizeof(buf));
if (!v || 0 != strcmp(v, expect))
return 1;
@@ -147,7 +153,7 @@ int CheckParam(const Param* p, char* expect) {
* Returns 0 if success, non-zero if error. */
int PrintParam(const Param* p) {
if (p->flags & IS_STRING) {
char buf[256];
char buf[MAX_STRING];
const char* v = VbGetSystemPropertyString(p->name, buf, sizeof(buf));
if (!v)
return 1;
@@ -168,7 +174,7 @@ int PrintParam(const Param* p) {
int PrintAllParams(void) {
const Param* p;
int retval = 0;
char buf[256];
char buf[MAX_STRING];
const char* value;
for (p = sys_param_list; p->name; p++) {