Add parameter for POST code length

The -b/--bytes parameter allows specifying the length in bytes of each
POST code. It defaults to 1 for compatibility with existing systems.

Signed-off-by: Benjamin Fair <benjaminfair@google.com>
Change-Id: I1947c66c5cd4657984c3c5ffae8b11603c53939a
diff --git a/main.cpp b/main.cpp
index 2e79e2d..d070923 100644
--- a/main.cpp
+++ b/main.cpp
@@ -46,6 +46,7 @@
 };
 
 static const char* snoopFilename = "/dev/aspeed-lpc-snoop0";
+static size_t codeSize = 1; /* Size of each POST code in bytes */
 
 /*
  * 256 bytes is a nice amount.  It's improbable we'd need this many, but its
@@ -72,8 +73,24 @@
 {
     fprintf(stderr,
             "Usage: %s [-d <DEVICE>]\n"
+            "  -b, --bytes <SIZE>     set POST code length to <SIZE> bytes. "
+            "Default is %zu\n"
             "  -d, --device <DEVICE>  use <DEVICE> file. Default is '%s'\n\n",
-            name, snoopFilename);
+            name, codeSize, snoopFilename);
+}
+
+static uint64_t assembleBytes(std::array<uint8_t, BUFFER_SIZE> buf, int start,
+                              int size)
+{
+    uint64_t result = 0;
+
+    for (int i = start + size - 1; i >= start; i--)
+    {
+        result <<= 8;
+        result |= buf[i];
+    }
+
+    return result;
 }
 
 /*
@@ -106,14 +123,28 @@
     bool deferSignals = true;
 
     static const struct option long_options[] = {
-        {"device", required_argument, NULL, 'd'}, {0, 0, 0, 0}};
+        {"bytes", required_argument, NULL, 'b'},
+        {"device", required_argument, NULL, 'd'},
+        {0, 0, 0, 0}};
 
-    while ((opt = getopt_long(argc, argv, "d:", long_options, NULL)) != -1)
+    while ((opt = getopt_long(argc, argv, "b:d:", long_options, NULL)) != -1)
     {
         switch (opt)
         {
             case 0:
                 break;
+            case 'b':
+                codeSize = atoi(optarg);
+
+                if (codeSize < 1 || codeSize > 8)
+                {
+                    fprintf(stderr,
+                            "Invalid POST code size '%s'. Must be "
+                            "an integer from 1 to 8.\n",
+                            optarg);
+                    exit(EXIT_FAILURE);
+                }
+                break;
             case 'd':
                 snoopFilename = optarg;
                 break;
@@ -179,10 +210,20 @@
                 }
                 else
                 {
-                    /* Broadcast the bytes read. */
-                    for (int i = 0; i < readb; i++)
+                    if (readb % codeSize != 0)
                     {
-                        reporter.value(buffer[i]);
+                        fprintf(stderr,
+                                "Warning: read size %d not a multiple of "
+                                "POST code length %zu. Some codes may be "
+                                "corrupt or missing\n",
+                                readb, codeSize);
+                        readb -= (readb % codeSize);
+                    }
+
+                    /* Broadcast the values read. */
+                    for (int i = 0; i < readb; i += codeSize)
+                    {
+                        reporter.value(assembleBytes(buffer, i, codeSize));
                     }
                 }
             }