Vboot wrapper API - crossystem and header files

Header file changes for wrapper API implementation

Crossystem support for reading recovery reason from VbSharedData, and
explicit support for version 1 VbSharedData structs.

BUG=chromium-os:16970
TEST=make && make runtests; run crossystem on Alex and make sure it still reports recovery_reason in recovery mode.

Change-Id: I15195b899583e425d3c9e8df09842d764528e2cb
Reviewed-on: http://gerrit.chromium.org/gerrit/3203
Reviewed-by: Tom Wai-Hong Tam <waihong@chromium.org>
Reviewed-by: Che-Liang Chiou <clchiou@chromium.org>
Tested-by: Randall Spangler <rspangler@chromium.org>
diff --git a/firmware/include/bmpblk_header.h b/firmware/include/bmpblk_header.h
index ea918ca..9007fe2 100644
--- a/firmware/include/bmpblk_header.h
+++ b/firmware/include/bmpblk_header.h
@@ -98,7 +98,10 @@
   uint32_t format;           /* File format of the image */
   uint32_t compression;      /* Compression method for the image file */
   uint32_t original_size;    /* Size of the original uncompressed image */
-  uint32_t compressed_size;  /* Size of the compressed image */
+  uint32_t compressed_size;  /* Size of the compressed image; if image is not
+                              * compressed, this will be the same as the
+                              * original size. */
+
   uint32_t reserved;
   /* NOTE: actual image content follows immediately */
 } __attribute__((packed)) ImageInfo;
diff --git a/firmware/include/load_kernel_fw.h b/firmware/include/load_kernel_fw.h
index 5815abf..6dd6c93 100644
--- a/firmware/include/load_kernel_fw.h
+++ b/firmware/include/load_kernel_fw.h
@@ -10,6 +10,7 @@
 #define VBOOT_REFERENCE_LOAD_KERNEL_FW_H_
 
 #include "sysincludes.h"
+#include "vboot_api.h"
 #include "vboot_nvstorage.h"
 
 /* Interface provided by verified boot library to BDS */
@@ -43,9 +44,12 @@
                                  * data size placed into the buffer. */
   void* gbb_data;               /* Pointer to GBB data */
   uint64_t gbb_size;            /* Size of GBB data in bytes */
+
+  VbExDiskHandle_t disk_handle; /* Disk handle for current device */
   uint64_t bytes_per_lba;       /* Bytes per lba sector on current device */
   uint64_t ending_lba;          /* Last addressable lba sector on current
                                  * device */
+
   void* kernel_buffer;          /* Destination buffer for kernel
                                  * (normally at 0x100000) */
   uint64_t kernel_buffer_size;  /* Size of kernel buffer in bytes */
diff --git a/firmware/include/vboot_nvstorage.h b/firmware/include/vboot_nvstorage.h
index 6018349..02f81a7 100644
--- a/firmware/include/vboot_nvstorage.h
+++ b/firmware/include/vboot_nvstorage.h
@@ -103,6 +103,8 @@
 #define VBNV_RECOVERY_RW_SHARED_DATA  0x46
 /* Test error from LoadKernel() */
 #define VBNV_RECOVERY_RW_TEST_LK      0x47
+/* No bootable disk found */
+#define VBNV_RECOVERY_RW_NO_DISK      0x48
 /* Unspecified/unknown error in rewritable firmware */
 #define VBNV_RECOVERY_RW_UNSPECIFIED  0x7F
 /* DM-verity error */
diff --git a/firmware/include/vboot_struct.h b/firmware/include/vboot_struct.h
index f8fd8c8..2dab742 100644
--- a/firmware/include/vboot_struct.h
+++ b/firmware/include/vboot_struct.h
@@ -149,6 +149,13 @@
 #define VBSD_KERNEL_KEY_VERIFIED        0x00000002
 /* LoadFirmware() was told the developer switch was on */
 #define VBSD_LF_DEV_SWITCH_ON           0x00000004
+/* Developer switch was enabled at boot time */
+#define VBSD_BOOT_DEV_SWITCH_ON         0x00000010
+/* Recovery switch was enabled at boot time */
+#define VBSD_BOOT_REC_SWITCH_ON         0x00000020
+/* Firmware write protect was enabled at boot time */
+#define VBSD_BOOT_FIRMWARE_WP_ENABLED   0x00000040
+
 
 /* Result codes for VbSharedDataHeader.check_fw_a_result (and b_result) */
 #define VBSD_LF_CHECK_NOT_DONE          0
@@ -306,10 +313,15 @@
   uint64_t kernel_supplemental_offset;
   uint64_t kernel_supplemental_size;
 
-  /* After read-only firmware which uses version 1 is released, any additional
+  /* Fields added in version 2.  Before accessing, make sure that
+   * struct_version >= 2*/
+  uint8_t recovery_reason;            /* Recovery reason for current boot */
+  uint8_t reserved2[7];               /* Reserved for padding */
+
+  /* After read-only firmware which uses version 2 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
-   * accessed is at least version 2.
+   * accessed is at least version 3.
    *
    * It's always ok for an older firmware to access a newer struct, since all
    * the fields it knows about are present.  Newer firmware needs to use
@@ -317,7 +329,13 @@
 
 } __attribute__((packed)) VbSharedDataHeader;
 
-#define VB_SHARED_DATA_VERSION 1      /* Version for struct_version */
+/* Size of VbSharedDataheader for each older version */
+// TODO: crossystem needs not to
+// fail if called on a v1 system where sizeof(VbSharedDataHeader) was smaller
+
+#define VB_SHARED_DATA_HEADER_SIZE_V1 1072
+
+#define VB_SHARED_DATA_VERSION 2      /* Version for struct_version */
 
 __pragma(pack(pop)) /* Support packing for MSVC. */
 
diff --git a/host/arch/x86/lib/crossystem_arch.c b/host/arch/x86/lib/crossystem_arch.c
index 8b320e4..25867e1 100644
--- a/host/arch/x86/lib/crossystem_arch.c
+++ b/host/arch/x86/lib/crossystem_arch.c
@@ -156,8 +156,7 @@
  *         deallocating the pointer, this will take care of both the structure
  *         and the buffer. Null in case of error.
  */
-static uint8_t* VbGetBuffer(const char* filename, int* buffer_size)
-{
+static uint8_t* VbGetBuffer(const char* filename, int* buffer_size) {
   FILE* f = NULL;
   char* file_buffer = NULL;
   uint8_t* output_buffer = NULL;
@@ -240,14 +239,24 @@
 
 
 VbSharedDataHeader* VbSharedDataRead(void) {
-
   VbSharedDataHeader* sh;
   int got_size = 0;
+  int expect_size;
 
   sh = (VbSharedDataHeader*)VbGetBuffer(ACPI_VDAT_PATH, &got_size);
   if (!sh)
     return NULL;
-  if (got_size < sizeof(VbSharedDataHeader)) {
+
+  /* Make sure the size is sufficient for the struct version we got.
+   * Check supported old versions first. */
+  if (1 == sh->struct_version)
+    expect_size = VB_SHARED_DATA_HEADER_SIZE_V1;
+  else {
+    /* There'd better be enough data for the current header size. */
+    expect_size = sizeof(VbSharedDataHeader);
+  }
+
+  if (got_size < expect_size) {
     Free(sh);
     return NULL;
   }
@@ -371,7 +380,18 @@
 
 /* Read the recovery reason.  Returns the reason code or -1 if error. */
 static int VbGetRecoveryReason(void) {
-  int value;
+  VbSharedDataHeader* sh;
+  int value = -1;
+
+  /* Try reading from VbSharedData first */
+  sh = VbSharedDataRead();
+  if (sh) {
+    if (sh->struct_version >= 2)
+      value = sh->recovery_reason;
+    Free(sh);
+    if (-1 != value)
+      return value;
+  }
 
   /* Try reading type from BINF.4 */
   value = ReadFileInt(ACPI_BINF_PATH ".4");
diff --git a/host/include/crossystem_arch.h b/host/include/crossystem_arch.h
index 6d33c65..fbef9b1 100644
--- a/host/include/crossystem_arch.h
+++ b/host/include/crossystem_arch.h
@@ -58,8 +58,8 @@
  * some data was not returned; callers must handle this; this is not considered
  * an error.
  *
- * Returns the data buffer, which must be freed by the caller, or NULL if
- * error. */
+ * Returns the data buffer, which must be freed by the caller using
+ * free(), or NULL if error. */
 VbSharedDataHeader* VbSharedDataRead(void);
 
 /* Read an architecture-specific system property integer.
diff --git a/host/include/host_common.h b/host/include/host_common.h
index d8a2b09..007c9d9 100644
--- a/host/include/host_common.h
+++ b/host/include/host_common.h
@@ -8,12 +8,17 @@
 #ifndef VBOOT_REFERENCE_HOST_COMMON_H_
 #define VBOOT_REFERENCE_HOST_COMMON_H_
 
+/* Host is allowed direct use of stdlib funcs such as malloc() and free(),
+ * since it's using the stub implementation from firmware/lib/stub. */
+#define _STUB_IMPLEMENTATION_
+
 #include "cryptolib.h"
 #include "host_key.h"
 #include "host_keyblock.h"
 #include "host_misc.h"
 #include "host_signature.h"
 #include "utility.h"
+#include "vboot_api.h"
 #include "vboot_struct.h"
 
 
diff --git a/host/lib/crossystem.c b/host/lib/crossystem.c
index 7ad5d80..54d0856 100644
--- a/host/lib/crossystem.c
+++ b/host/lib/crossystem.c
@@ -36,8 +36,9 @@
   VDAT_INT_FW_VERSION_TPM,           /* Current firmware version in TPM */
   VDAT_INT_KERNEL_VERSION_TPM,       /* Current kernel version in TPM */
   VDAT_INT_TRIED_FIRMWARE_B,         /* Tried firmware B due to fwb_tries */
-  VDAT_INT_KERNEL_KEY_VERIFIED       /* Kernel key verified using
+  VDAT_INT_KERNEL_KEY_VERIFIED,      /* Kernel key verified using
                                       * signature, not just hash */
+  VDAT_INT_RECOVERY_REASON           /* Recovery reason for current boot */
 } VdatIntField;
 
 
@@ -325,6 +326,11 @@
     case VDAT_INT_KERNEL_KEY_VERIFIED:
       value = (sh->flags & VBSD_KERNEL_KEY_VERIFIED ? 1 : 0);
       break;
+    case VDAT_INT_RECOVERY_REASON:
+      /* Field added in struct version 2 */
+      if (sh->struct_version >= 2)
+        value = sh->recovery_reason;
+      break;
   }
 
   Free(sh);
@@ -373,6 +379,8 @@
     value = GetVdatInt(VDAT_INT_KERNEL_VERSION_TPM);
   } else if (!strcasecmp(name,"tried_fwb")) {
     value = GetVdatInt(VDAT_INT_TRIED_FIRMWARE_B);
+  } else if (!strcasecmp(name,"recovery_reason")) {
+    value = GetVdatInt(VDAT_INT_RECOVERY_REASON);
   }
 
   return value;