Add function for VDAT processing.

This CL is a user space counterpart of
http://codereview.chromium.org/6690023, which provided the
ability to retrieve buffers through chromeos_acpi driver.

The buffer contents is communicated as a multi line string
with each buffer byte represented as a two symbol hex
number. `crosstool', on the other has to map the buffer
contents into a certain binary structure. This CL add
conversion of the multiline string into a binary buffer and
also adds a temp. routine to dump the buffer contents on the
screen when `crosstool' is invoked.

Change-Id: I8dd3eb935332f9bc8769c71de0db302365f12d70

BUG=chromium-os:13069, chromium-os:13091
TEST=manual

- Install the new image on a target with firmware providing
 the VDAT ACPI method.

- Run crosstool and watch for the last line:
vdat                   =  11 22 33 44 ff 1f 1c 40 ff 57 74 41 ff ff ff ff # Raw VDAT contents.
localhost tmp #

Review URL: http://codereview.chromium.org/6695012
diff --git a/host/lib/crossystem.c b/host/lib/crossystem.c
index 04dc975..9bea492 100644
--- a/host/lib/crossystem.c
+++ b/host/lib/crossystem.c
@@ -5,6 +5,10 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <ctype.h>
 
 #include "host_common.h"
 
@@ -68,6 +72,7 @@
 #define ACPI_FMAP_PATH ACPI_BASE_PATH "/FMAP"
 #define ACPI_GPIO_PATH ACPI_BASE_PATH "/GPIO"
 #define ACPI_VBNV_PATH ACPI_BASE_PATH "/VBNV"
+#define ACPI_VDAT_PATH ACPI_BASE_PATH "/VDAT"
 
 /* Base name for GPIO files */
 #define GPIO_BASE_PATH "/sys/class/gpio"
@@ -79,6 +84,12 @@
 /* Filename for kernel command line */
 #define KERNEL_CMDLINE_PATH "/proc/cmdline"
 
+/* A structure to contain buffer data retrieved from the ACPI. */
+typedef struct {
+  int buffer_size;
+  void* buffer;
+} AcpiBuffer;
+
 
 /* Copy up to dest_size-1 characters from src to dest, ensuring null
    termination (which strncpy() doesn't do).  Returns the destination
@@ -284,6 +295,102 @@
   return 0;
 }
 
+/*
+ * Get buffer data from ACPI.
+ *
+ * Buffer data is expected to be represented by a file which is a text dump of
+ * the buffer, representing each byte by two hex numbers, space and newline
+ * separated.
+ *
+ * Input - ACPI file name to get data from.
+ *
+ * Output: a pointer to AcpiBuffer structure containing the binary
+ *         representation of the data. The caller is responsible for
+ *         deallocating the pointer, this will take care of both the structure
+ *         and the buffer. Null in case of error.
+ */
+
+AcpiBuffer* VbGetBuffer(const char* filename)
+{
+  FILE* f = NULL;
+  char* file_buffer = NULL;
+  AcpiBuffer* acpi_buffer = NULL;
+  AcpiBuffer* return_value = NULL;
+
+  do {
+    struct stat fs;
+    unsigned char* output_ptr;
+    int rv, i, real_size;
+
+    rv = stat(filename, &fs);
+    if (rv || !S_ISREG(fs.st_mode))
+      break;
+
+    f = fopen(filename, "r");
+    if (!f)
+      break;
+
+    file_buffer = Malloc(fs.st_size + 1);
+    if (!file_buffer)
+      break;
+
+
+    real_size = fread(file_buffer, 1, fs.st_size, f);
+    if (!real_size)
+      break;
+
+    /* each byte in the output will replace two characters and a space in the
+     *  input, so the output size does not exceed input side/3 (a little less
+     *  if account for newline characters).
+     */
+    acpi_buffer = Malloc(sizeof(AcpiBuffer) + real_size/3);
+
+    if (!acpi_buffer)
+      break;
+
+    file_buffer[real_size] = '\0';
+
+    acpi_buffer->buffer = acpi_buffer + 1;
+    acpi_buffer->buffer_size = 0;
+    output_ptr = acpi_buffer->buffer;
+
+    /* process the file contents */
+    for (i = 0; i < real_size; i++) {
+      char* base, *end;
+
+      base = file_buffer + i;
+
+      if (!isxdigit(*base))
+        continue;
+
+      output_ptr[acpi_buffer->buffer_size++] = strtol(base, &end, 16) & 0xff;
+
+      if ((end - base) != 2)
+        /* Input file format error */
+        break;
+
+      i += 2; /* skip the second character and the following space */
+    }
+
+    if (i == real_size) {
+      /* all is well */
+      return_value = acpi_buffer;
+      acpi_buffer = NULL; /* prevent it from deallocating */
+    }
+  } while(0);
+
+  /* wrap up */
+  if (f)
+    fclose(f);
+
+  if (file_buffer)
+    Free(file_buffer);
+
+  if (acpi_buffer)
+    Free(acpi_buffer);
+
+  return return_value;
+}
 
 /* Read an integer property from VbNvStorage.
  *
@@ -565,6 +672,31 @@
   return value;
 }
 
+/* This function is just an example illustrating the use of VbGetBuffer(). It
+ * converts the binary contents of the buffer into a space delimetered hex
+ * string. It is expected to be replaced with a function which has knowledge
+ * of the buffer data structure.
+ */
+char* GetVdatBuffer(void)
+{
+  char* buffer, *src, *p;
+  int i;
+
+  AcpiBuffer* ab = VbGetBuffer(ACPI_VDAT_PATH);
+  if (!ab)
+    return NULL;
+
+  buffer = Malloc(ab->buffer_size * 3 + 2);
+  p = buffer;
+  src = ab->buffer;
+  for (i = 0; i < ab->buffer_size; i++) {
+    snprintf(p, 4, " %2.2x", *src++);
+    p += 3;
+  }
+  *p = '\0';
+  Free(ab);
+  return buffer;
+}
 
 /* Read a system property string into a destination buffer of the specified
  * size.
@@ -609,6 +741,8 @@
       default:
         return NULL;
     }
+  } else if (!strcasecmp(name, "vdat")) {
+    return GetVdatBuffer();
   } else
     return NULL;
 }
diff --git a/utility/crossystem_main.c b/utility/crossystem_main.c
index 90ad718..4d6cd48 100644
--- a/utility/crossystem_main.c
+++ b/utility/crossystem_main.c
@@ -49,6 +49,7 @@
   {"recovery_request", 0, 1, "Recovery mode request (writable)"},
   {"dbg_reset", 0, 1, "Debug reset mode request (writable)"},
   {"fwb_tries", 0, 1, "Try firmware B count (writable)"},
+  {"vdat", 1, 0, "Raw VDAT contents."},
 
   /* TODO: implement the following:
    *   nvram_cleared