pci: implement sending firmware image over p2a

Implement sending firmware image over p2a via the aspeed-p2a-ctrl
driver.

Test configuration:
# Image is static, uses the PCI bridge, and requires the ASPEED
# PCI-to-AHB hardware implementation.
EXTRA_OECONF_append_quanta-q71l = " --enable-static-layout"
EXTRA_OECONF_append_quanta-q71l = " --enable-pci-bridge"
EXTRA_OECONF_append_quanta-q71l = " --enable-aspeed-p2a"
EXTRA_OECONF_append_quanta-q71l = " MAPPED_ADDRESS=0x47FF0000"

Tested: Verified via md5sum the image-bmc file sent from the host via
this tool matches the hash of /run/initramfs/bmc-image.  This code can
be used to send any file down, but was only tested with a "static"
layout build.

Signed-off-by: Patrick Venture <venture@google.com>
Change-Id: I430bc7444f06f4f93a63e3bf2646bd195eaa2e52
diff --git a/tools/io.cpp b/tools/io.cpp
index cc9e7d1..420dd94 100644
--- a/tools/io.cpp
+++ b/tools/io.cpp
@@ -16,15 +16,10 @@
 bool DevMemDevice::read(const std::size_t offset, const std::size_t length,
                         void* const destination)
 {
-    if (!opened)
+    devMemFd = sys->open(devMemPath.c_str(), O_RDONLY);
+    if (devMemFd < 0)
     {
-        devMemFd = sys->open(devMemPath.c_str(), O_RDWR);
-        if (devMemFd < 0)
-        {
-            return false;
-        }
-
-        opened = true;
+        return false;
     }
 
     /* Map based on aligned addresses - behind the scenes. */
@@ -37,7 +32,10 @@
                              alignedOffset);
     if (devMemMapped == MAP_FAILED)
     {
-        return false; /* but leave the file open. */
+        std::fprintf(stderr, "Failed to mmap at offset: 0x%lx, length: %lu\n",
+                     offset, length);
+        sys->close(devMemFd);
+        return false;
     }
 
     void* alignedSource =
@@ -48,6 +46,7 @@
 
     /* Close the map between reads for now. */
     sys->munmap(devMemMapped, length);
+    sys->close(devMemFd);
 
     return true;
 }
@@ -55,15 +54,11 @@
 bool DevMemDevice::write(const std::size_t offset, const std::size_t length,
                          const void* const source)
 {
-    if (!opened)
+    devMemFd = sys->open(devMemPath.c_str(), O_RDWR);
+    if (devMemFd < 0)
     {
-        devMemFd = sys->open(devMemPath.c_str(), O_RDWR);
-        if (devMemFd < 0)
-        {
-            return false;
-        }
-
-        opened = true;
+        std::fprintf(stderr, "Failed to open /dev/mem for writing\n");
+        return false;
     }
 
     /* Map based on aligned addresses - behind the scenes. */
@@ -77,7 +72,10 @@
 
     if (devMemMapped == MAP_FAILED)
     {
-        return false; /* but leave the file open. */
+        std::fprintf(stderr, "Failed to mmap at offset: 0x%lx, length: %lu\n",
+                     offset, length);
+        sys->close(devMemFd);
+        return false;
     }
 
     void* alignedDestination =
@@ -88,6 +86,7 @@
 
     /* Close the map between writes for now. */
     sys->munmap(devMemMapped, length);
+    sys->close(devMemFd);
 
     return true;
 }