Add APIs to store/load BIOS tables

This commit implements C++ APIs to store a PLDM BIOS table into
persistent storage, and to load the same back into memory. This commit
also defines C structs representing the different BIOS tables.

Signed-off-by: Deepak Kodihalli <dkodihal@in.ibm.com>
Change-Id: I4a771a368c6931464f45ae4a8f467b579c7a5d74
diff --git a/libpldmresponder/Makefile.am b/libpldmresponder/Makefile.am
index 9113b3a..a285b8f 100644
--- a/libpldmresponder/Makefile.am
+++ b/libpldmresponder/Makefile.am
@@ -5,7 +5,8 @@
 	utils.cpp \
 	bios.cpp \
 	effecters.cpp \
-	pdr.cpp
+	pdr.cpp \
+	bios_table.cpp
 libpldmresponder_la_LIBADD = \
 	../libpldm/libpldm.la \
 	$(CODE_COVERAGE_LIBS)
diff --git a/libpldmresponder/bios_table.cpp b/libpldmresponder/bios_table.cpp
new file mode 100644
index 0000000..df2c8dd
--- /dev/null
+++ b/libpldmresponder/bios_table.cpp
@@ -0,0 +1,49 @@
+#include "bios_table.hpp"
+
+#include <fstream>
+
+namespace pldm
+{
+
+namespace responder
+{
+
+namespace bios
+{
+
+BIOSTable::BIOSTable(const char* filePath) : filePath(filePath)
+{
+}
+
+bool BIOSTable::isEmpty() const noexcept
+{
+    bool empty = false;
+    try
+    {
+        empty = fs::is_empty(filePath);
+    }
+    catch (fs::filesystem_error& e)
+    {
+        return true;
+    }
+    return empty;
+}
+
+void BIOSTable::store(const Table& table)
+{
+    std::ofstream stream(filePath.string(), std::ios::out | std::ios::binary);
+    stream.write(reinterpret_cast<const char*>(table.data()), table.size());
+}
+
+void BIOSTable::load(Response& response) const
+{
+    auto currSize = response.size();
+    auto fileSize = fs::file_size(filePath);
+    response.resize(currSize + fileSize);
+    std::ifstream stream(filePath.string(), std::ios::in | std::ios::binary);
+    stream.read(reinterpret_cast<char*>(response.data() + currSize), fileSize);
+}
+
+} // namespace bios
+} // namespace responder
+} // namespace pldm
diff --git a/libpldmresponder/bios_table.hpp b/libpldmresponder/bios_table.hpp
new file mode 100644
index 0000000..2b4077c
--- /dev/null
+++ b/libpldmresponder/bios_table.hpp
@@ -0,0 +1,76 @@
+#pragma once
+
+#include <stdint.h>
+
+#include <filesystem>
+#include <vector>
+
+#include "libpldm/bios.h"
+
+namespace pldm
+{
+
+namespace responder
+{
+
+namespace bios
+{
+
+using Table = std::vector<uint8_t>;
+using Response = std::vector<uint8_t>;
+namespace fs = std::filesystem;
+
+/** @class BIOSTable
+ *
+ *  @brief Provides APIs for storing and loading BIOS tables
+ *
+ *  Typical usage is as follows:
+ *  BIOSTable table(BIOS_STRING_TABLE_FILE_PATH);
+ *  if (table.isEmpty()) { // no persisted table
+ *    // construct BIOSTable 't'
+ *    // prepare Response 'r'
+ *    // send response to GetBIOSTable
+ *    table.store(t); // persisted
+ *  }
+ *  else { // persisted table exists
+ *    // create Response 'r' which has response fields (except
+ *    // the table itself) to a GetBIOSTable command
+ *    table.load(r); // actual table will be pushed back to the vector
+ *  }
+ */
+class BIOSTable
+{
+  public:
+    /** @brief Ctor - set file path to persist BIOS table
+     *
+     *  @param[in] filePath - file where BIOS table should be persisted
+     */
+    BIOSTable(const char* filePath);
+
+    /** @brief Checks if there's a persisted BIOS table
+     *
+     *  @return bool - true if table exists, false otherwise
+     */
+    bool isEmpty() const noexcept;
+
+    /** @brief Persist a BIOS table(string/attribute/attribute value)
+     *
+     *  @param[in] table - BIOS table
+     */
+    void store(const Table& table);
+
+    /** @brief Load BIOS table from persistent store to memory
+     *
+     *  @param[in,out] response - PLDM response message to GetBIOSTable
+     *  (excluding table), table will be pushed back to this.
+     */
+    void load(Response& response) const;
+
+  private:
+    // file storing PLDM BIOS table
+    fs::path filePath;
+};
+
+} // namespace bios
+} // namespace responder
+} // namespace pldm