tools: Add PpcMemDevice as an HostIoInterface

PPC platforms may require a different mempath and different I/O
operations to access the file system.

Change-Id: I46b8825c685b362009dc62fdbaa59c65239831d1
Signed-off-by: Brandon Kim <brandonkim@google.com>
diff --git a/tools/io.cpp b/tools/io.cpp
index 21e7d40..991507b 100644
--- a/tools/io.cpp
+++ b/tools/io.cpp
@@ -91,4 +91,61 @@
     return true;
 }
 
+PpcMemDevice::~PpcMemDevice()
+{
+    // Attempt to close in case reads or writes didn't close themselves
+    if (ppcMemFd >= 0)
+    {
+        sys->close(ppcMemFd);
+    }
+}
+
+bool PpcMemDevice::read(const std::size_t offset, const std::size_t length,
+                        void* const destination)
+{
+    ppcMemFd = sys->open(ppcMemPath.c_str(), O_RDWR);
+    if (ppcMemFd < 0)
+    {
+        std::fprintf(stderr, "Failed to open PPC LPC access path: %s",
+                     ppcMemPath.c_str());
+        return false;
+    }
+
+    int ret = sys->pread(ppcMemFd, destination, length, offset);
+    if (ret < 0)
+    {
+        std::fprintf(stderr, "IO read failed at offset: 0x%zx, length: %zu\n",
+                     offset, length);
+        sys->close(ppcMemFd);
+        return false;
+    }
+
+    sys->close(ppcMemFd);
+    return true;
+}
+
+bool PpcMemDevice::write(const std::size_t offset, const std::size_t length,
+                         const void* const source)
+{
+    ppcMemFd = sys->open(ppcMemPath.c_str(), O_RDWR);
+    if (ppcMemFd < 0)
+    {
+        std::fprintf(stderr, "Failed to open PPC LPC access path: %s",
+                     ppcMemPath.c_str());
+        return false;
+    }
+
+    ssize_t ret = sys->pwrite(ppcMemFd, source, length, offset);
+    if (ret < 0)
+    {
+        std::fprintf(stderr, "IO write failed at offset: 0x%zx, length: %zu\n",
+                     offset, length);
+        sys->close(ppcMemFd);
+        return false;
+    }
+
+    sys->close(ppcMemFd);
+    return true;
+}
+
 } // namespace host_tool
diff --git a/tools/io.hpp b/tools/io.hpp
index 44cd2cb..6cc982c 100644
--- a/tools/io.hpp
+++ b/tools/io.hpp
@@ -68,4 +68,34 @@
     const internal::Sys* sys;
 };
 
+class PpcMemDevice : public HostIoInterface
+{
+  public:
+    explicit PpcMemDevice(const std::string ppcMemPath,
+                          const internal::Sys* sys = &internal::sys_impl) :
+        ppcMemPath(ppcMemPath),
+        sys(sys)
+    {
+    }
+
+    ~PpcMemDevice() override;
+
+    /* Don't allow copying or assignment, only moving. */
+    PpcMemDevice(const PpcMemDevice&) = delete;
+    PpcMemDevice& operator=(const PpcMemDevice&) = delete;
+    PpcMemDevice(PpcMemDevice&&) = default;
+    PpcMemDevice& operator=(PpcMemDevice&&) = default;
+
+    bool read(const std::size_t offset, const std::size_t length,
+              void* const destination) override;
+
+    bool write(const std::size_t offset, const std::size_t length,
+               const void* const source) override;
+
+  private:
+    int ppcMemFd = -1;
+    const std::string ppcMemPath;
+    const internal::Sys* sys;
+};
+
 } // namespace host_tool