bugfix: tools: fixup the region copied

Fixup the region copied in the blob handler so that the CRC is run
across the correct bytes.

Change-Id: Ie4bc8323b072e19f525110bbd68c46d3734ea3b8
Signed-off-by: Patrick Venture <venture@google.com>
diff --git a/test/crc_mock.hpp b/test/crc_mock.hpp
new file mode 100644
index 0000000..293ec24
--- /dev/null
+++ b/test/crc_mock.hpp
@@ -0,0 +1,23 @@
+#pragma once
+
+#include <cstdint>
+#include <vector>
+
+#include <gmock/gmock.h>
+
+class CrcInterface
+{
+  public:
+    virtual ~CrcInterface() = default;
+
+    virtual std::uint16_t
+        generateCrc(const std::vector<std::uint8_t>& data) const = 0;
+};
+
+class CrcMock : public CrcInterface
+{
+  public:
+    virtual ~CrcMock() = default;
+    MOCK_CONST_METHOD1(generateCrc,
+                       std::uint16_t(const std::vector<std::uint8_t>&));
+};
diff --git a/test/tools_blob_unittest.cpp b/test/tools_blob_unittest.cpp
index cbbb151..f3a01c1 100644
--- a/test/tools_blob_unittest.cpp
+++ b/test/tools_blob_unittest.cpp
@@ -1,19 +1,31 @@
 #include "blob_handler.hpp"
+#include "crc_mock.hpp"
 #include "ipmi_interface_mock.hpp"
 
 #include <gtest/gtest.h>
 
-std::uint16_t expectedCrc = 0;
+CrcInterface* crcIntf = nullptr;
 
 std::uint16_t generateCrc(const std::vector<std::uint8_t>& data)
 {
-    return expectedCrc;
+    return (crcIntf) ? crcIntf->generateCrc(data) : 0x00;
 }
 
 using ::testing::Eq;
 using ::testing::Return;
 
-TEST(BlobHandler, getCountIpmiHappy)
+class BlobHandlerTest : public ::testing::Test
+{
+  protected:
+    void SetUp() override
+    {
+        crcIntf = &crcMock;
+    }
+
+    CrcMock crcMock;
+};
+
+TEST_F(BlobHandlerTest, getCountIpmiHappy)
 {
     /* Verify returns the value specified by the IPMI response. */
     IpmiInterfaceMock ipmiMock;
@@ -25,11 +37,14 @@
     std::vector<std::uint8_t> resp = {0xcf, 0xc2, 0x00, 0x00, 0x00,
                                       0x01, 0x00, 0x00, 0x00};
 
+    std::vector<std::uint8_t> bytes = {0x01, 0x00, 0x00, 0x00};
+    EXPECT_CALL(crcMock, generateCrc(Eq(bytes))).WillOnce(Return(0x00));
+
     EXPECT_CALL(ipmiMock, sendPacket(Eq(request))).WillOnce(Return(resp));
     EXPECT_EQ(1, blob.getBlobCount());
 }
 
-TEST(BlobHandler, enumerateBlobIpmiHappy)
+TEST_F(BlobHandlerTest, enumerateBlobIpmiHappy)
 {
     /* Verify returns the name specified by the IPMI response. */
     IpmiInterfaceMock ipmiMock;
@@ -43,11 +58,16 @@
     std::vector<std::uint8_t> resp = {0xcf, 0xc2, 0x00, 0x00, 0x00,
                                       'a',  'b',  'c',  'd',  0x00};
 
+    std::vector<std::uint8_t> bytes = {'a', 'b', 'c', 'd', 0x00};
+    std::vector<std::uint8_t> reqCrc = {0x01, 0x00, 0x00, 0x00};
+    EXPECT_CALL(crcMock, generateCrc(Eq(reqCrc))).WillOnce(Return(0x00));
+    EXPECT_CALL(crcMock, generateCrc(Eq(bytes))).WillOnce(Return(0x00));
+
     EXPECT_CALL(ipmiMock, sendPacket(Eq(request))).WillOnce(Return(resp));
     EXPECT_STREQ("abcd", blob.enumerateBlob(1).c_str());
 }
 
-TEST(BlobHandler, enumerateBlobIpmiNoBytes)
+TEST_F(BlobHandlerTest, enumerateBlobIpmiNoBytes)
 {
     /* Simulate a case where the IPMI command returns no data. */
     IpmiInterfaceMock ipmiMock;
@@ -60,11 +80,14 @@
     /* return value. */
     std::vector<std::uint8_t> resp = {};
 
+    std::vector<std::uint8_t> reqCrc = {0x01, 0x00, 0x00, 0x00};
+    EXPECT_CALL(crcMock, generateCrc(Eq(reqCrc))).WillOnce(Return(0x00));
+
     EXPECT_CALL(ipmiMock, sendPacket(Eq(request))).WillOnce(Return(resp));
     EXPECT_STREQ("", blob.enumerateBlob(1).c_str());
 }
 
-TEST(BlobHandler, getBlobListIpmiHappy)
+TEST_F(BlobHandlerTest, getBlobListIpmiHappy)
 {
     /* Verify returns the list built via the above two commands. */
     IpmiInterfaceMock ipmiMock;
@@ -77,6 +100,9 @@
     std::vector<std::uint8_t> resp1 = {0xcf, 0xc2, 0x00, 0x00, 0x00,
                                        0x01, 0x00, 0x00, 0x00};
 
+    std::vector<std::uint8_t> bytes1 = {0x01, 0x00, 0x00, 0x00};
+    EXPECT_CALL(crcMock, generateCrc(Eq(bytes1))).WillOnce(Return(0x00));
+
     EXPECT_CALL(ipmiMock, sendPacket(Eq(request1))).WillOnce(Return(resp1));
 
     std::vector<std::uint8_t> request2 = {
@@ -88,6 +114,11 @@
     std::vector<std::uint8_t> resp2 = {0xcf, 0xc2, 0x00, 0x00, 0x00,
                                        'a',  'b',  'c',  'd',  0x00};
 
+    std::vector<std::uint8_t> reqCrc = {0x00, 0x00, 0x00, 0x00};
+    std::vector<std::uint8_t> bytes2 = {'a', 'b', 'c', 'd', 0x00};
+    EXPECT_CALL(crcMock, generateCrc(Eq(reqCrc))).WillOnce(Return(0x00));
+    EXPECT_CALL(crcMock, generateCrc(Eq(bytes2))).WillOnce(Return(0x00));
+
     EXPECT_CALL(ipmiMock, sendPacket(Eq(request2))).WillOnce(Return(resp2));
 
     /* A std::string is not nul-terminated by default. */
@@ -96,7 +127,7 @@
     EXPECT_EQ(expectedList, blob.getBlobList());
 }
 
-TEST(BlobHandler, getStatWithMetadata)
+TEST_F(BlobHandlerTest, getStatWithMetadata)
 {
     /* Stat received metadata. */
     IpmiInterfaceMock ipmiMock;
@@ -110,6 +141,12 @@
     std::vector<std::uint8_t> resp = {0xcf, 0xc2, 0x00, 0x00, 0x00, 0xff, 0xff,
                                       0x00, 0x00, 0x00, 0x00, 0x02, 0x34, 0x45};
 
+    std::vector<std::uint8_t> reqCrc = {'a', 'b', 'c', 'd', 0x00};
+    std::vector<std::uint8_t> respCrc = {0xff, 0xff, 0x00, 0x00, 0x00,
+                                         0x00, 0x02, 0x34, 0x45};
+    EXPECT_CALL(crcMock, generateCrc(Eq(reqCrc))).WillOnce(Return(0x00));
+    EXPECT_CALL(crcMock, generateCrc(Eq(respCrc))).WillOnce(Return(0x00));
+
     EXPECT_CALL(ipmiMock, sendPacket(Eq(request))).WillOnce(Return(resp));
 
     auto meta = blob.getStat("abcd");
@@ -119,7 +156,7 @@
     EXPECT_EQ(metadata, meta.metadata);
 }
 
-TEST(BlobHandler, getStatNoMetadata)
+TEST_F(BlobHandlerTest, getStatNoMetadata)
 {
     /* Stat received no metadata. */
     IpmiInterfaceMock ipmiMock;
@@ -133,6 +170,13 @@
     std::vector<std::uint8_t> resp = {0xcf, 0xc2, 0x00, 0x00, 0x00, 0xff,
                                       0xff, 0x00, 0x00, 0x00, 0x00, 0x00};
 
+    std::vector<std::uint8_t> reqCrc = {'a', 'b', 'c', 'd', 0x00};
+    std::vector<std::uint8_t> respCrc = {0xff, 0xff, 0x00, 0x00,
+                                         0x00, 0x00, 0x00};
+
+    EXPECT_CALL(crcMock, generateCrc(Eq(reqCrc))).WillOnce(Return(0x00));
+    EXPECT_CALL(crcMock, generateCrc(Eq(respCrc))).WillOnce(Return(0x00));
+
     EXPECT_CALL(ipmiMock, sendPacket(Eq(request))).WillOnce(Return(resp));
 
     auto meta = blob.getStat("abcd");
@@ -142,7 +186,7 @@
     EXPECT_EQ(metadata, meta.metadata);
 }
 
-TEST(BlobHandler, openBlobSucceeds)
+TEST_F(BlobHandlerTest, openBlobSucceeds)
 {
     /* The open blob succeeds. */
     IpmiInterfaceMock ipmiMock;
@@ -156,6 +200,11 @@
 
     std::vector<std::uint8_t> resp = {0xcf, 0xc2, 0x00, 0x00, 0x00, 0xfe, 0xed};
 
+    std::vector<std::uint8_t> reqCrc = {0x02, 0x04, 'a', 'b', 'c', 'd', 0x00};
+    std::vector<std::uint8_t> respCrc = {0xfe, 0xed};
+    EXPECT_CALL(crcMock, generateCrc(Eq(reqCrc))).WillOnce(Return(0x00));
+    EXPECT_CALL(crcMock, generateCrc(Eq(respCrc))).WillOnce(Return(0x00));
+
     EXPECT_CALL(ipmiMock, sendPacket(Eq(request))).WillOnce(Return(resp));
 
     auto session =
diff --git a/tools/blob_handler.cpp b/tools/blob_handler.cpp
index a181559..43fc891 100644
--- a/tools/blob_handler.cpp
+++ b/tools/blob_handler.cpp
@@ -92,9 +92,14 @@
     auto ptr = reinterpret_cast<std::uint8_t*>(&crc);
     std::memcpy(ptr, &reply[ipmiPhosphorOen.size()], sizeof(crc));
 
+    for (const auto& byte : reply)
+    {
+        std::fprintf(stderr, "0x%02x ", byte);
+    }
+    std::fprintf(stderr, "\n");
+
     std::vector<std::uint8_t> bytes;
-    std::copy(&reply[headerSize], &reply[reply.size()],
-              std::back_inserter(bytes));
+    bytes.insert(bytes.begin(), reply.begin() + headerSize, reply.end());
 
     auto computed = generateCrc(bytes);
     if (crc != computed)