Implement write flash function for vpnor

Opens the partition file from the vpnor,
Memory map to it and then copy the given data
from the reserved memory area to the vpnor.

Change-Id: I29f44482155d890622221695deee255b222e9a49
Signed-off-by: Ratan Gupta <ratagupt@in.ibm.com>
diff --git a/mboxd_flash.c b/mboxd_flash.c
index 240c660..4b6c1f7 100644
--- a/mboxd_flash.c
+++ b/mboxd_flash.c
@@ -230,43 +230,3 @@
 
 	return 0;
 }
-
-/*
- * write_flash() - Write the flash from a provided buffer
- * @context:	The mbox context pointer
- * @offset:	The flash offset to write to (bytes)
- * @buf:	The buffer to write from (must be of atleast size)
- * @size:	The number of bytes to write
- *
- * Return:	0 on success otherwise negative error code
- */
-int write_flash(struct mbox_context *context, uint32_t offset, void *buf,
-		uint32_t count)
-{
-	uint32_t buf_offset = 0;
-	int rc;
-
-	MSG_DBG("Write flash @ 0x%.8x for 0x%.8x from %p\n", offset, count, buf);
-
-	if (lseek(context->fds[MTD_FD].fd, offset, SEEK_SET) != offset) {
-		MSG_ERR("Couldn't seek flash at pos: %u %s\n", offset,
-			strerror(errno));
-		return -MBOX_R_SYSTEM_ERROR;
-	}
-
-	while (count) {
-		rc = write(context->fds[MTD_FD].fd, buf + buf_offset, count);
-		if (rc < 0) {
-			MSG_ERR("Couldn't write to flash, write lost: %s\n",
-				strerror(errno));
-			return -MBOX_R_WRITE_ERROR;
-		}
-		/* Mark *NOT* erased where we just wrote */
-		set_flash_bytemap(context, offset + buf_offset, rc,
-				  FLASH_DIRTY);
-		count -= rc;
-		buf_offset += rc;
-	}
-
-	return 0;
-}
diff --git a/mboxd_flash_physical.c b/mboxd_flash_physical.c
index 92c70e7..16f2363 100644
--- a/mboxd_flash_physical.c
+++ b/mboxd_flash_physical.c
@@ -69,3 +69,43 @@
 
 	return size ? -MBOX_R_SYSTEM_ERROR : 0;
 }
+
+/*
+ * write_flash() - Write the flash from a provided buffer
+ * @context:	The mbox context pointer
+ * @offset:	The flash offset to write to (bytes)
+ * @buf:	The buffer to write from (must be of atleast size)
+ * @size:	The number of bytes to write
+ *
+ * Return:	0 on success otherwise negative error code
+ */
+int write_flash(struct mbox_context *context, uint32_t offset, void *buf,
+		uint32_t count)
+{
+	uint32_t buf_offset = 0;
+	int rc;
+
+	MSG_DBG("Write flash @ 0x%.8x for 0x%.8x from %p\n", offset, count, buf);
+
+	if (lseek(context->fds[MTD_FD].fd, offset, SEEK_SET) != offset) {
+		MSG_ERR("Couldn't seek flash at pos: %u %s\n", offset,
+			strerror(errno));
+		return -MBOX_R_SYSTEM_ERROR;
+	}
+
+	while (count) {
+		rc = write(context->fds[MTD_FD].fd, buf + buf_offset, count);
+		if (rc < 0) {
+			MSG_ERR("Couldn't write to flash, write lost: %s\n",
+				strerror(errno));
+			return -MBOX_R_WRITE_ERROR;
+		}
+		/* Mark *NOT* erased where we just wrote */
+		set_flash_bytemap(context, offset + buf_offset, rc,
+				  FLASH_DIRTY);
+		count -= rc;
+		buf_offset += rc;
+	}
+
+	return 0;
+}
diff --git a/mboxd_flash_virtual.cpp b/mboxd_flash_virtual.cpp
index c7154d6..3c83f02 100644
--- a/mboxd_flash_virtual.cpp
+++ b/mboxd_flash_virtual.cpp
@@ -119,3 +119,65 @@
     }
     return rc;
 }
+
+/*
+ * write_flash() - Write to the virtual pnor from a provided buffer
+ * @context: The mbox context pointer
+ * @offset:  The flash offset to write to (bytes)
+ * @buf:     The buffer to write from (must be of atleast size)
+ * @size:    The number of bytes to write
+ *
+ * Return:  0 on success otherwise negative error code
+ */
+
+int write_flash(struct mbox_context* context, uint32_t offset, void* buf,
+                uint32_t count)
+{
+    using namespace phosphor::logging;
+    using namespace sdbusplus::xyz::openbmc_project::Common::Error;
+    using namespace std::string_literals;
+
+    int rc = 0;
+    MSG_DBG("Write flash @ 0x%.8x for 0x%.8x from %p\n", offset, count, buf);
+    try
+    {
+        openpower::virtual_pnor::RWRequest rwRequest;
+        auto partitionInfo = rwRequest.getPartitionInfo(context, offset);
+
+
+        auto mapped_mem = mmap(NULL, partitionInfo->data.actual,
+                               PROT_READ | PROT_WRITE,
+                               MAP_SHARED, rwRequest.fd(), 0);
+        if (mapped_mem == MAP_FAILED)
+        {
+            MSG_ERR("Failed to map partition=%s:Error=%s\n",
+                    partitionInfo->data.name, strerror(errno));
+
+            elog<InternalFailure>();
+        }
+        //copy to the mapped memory.
+
+        uint32_t baseOffset = partitionInfo->data.base << context->block_size_shift;
+
+        // if the asked offset + no of bytes to write is greater
+        // then size of the partition file then throw error.
+        if ((offset + count) > (baseOffset + partitionInfo->data.actual))
+        {
+            MSG_ERR("Offset is beyond the partition file length[0x%.8x]\n",
+                     partitionInfo->data.actual);
+            munmap(mapped_mem, partitionInfo->data.actual);
+            elog<InternalFailure>();
+        }
+
+        auto diffOffset = offset - baseOffset;
+        memcpy((char*)mapped_mem + diffOffset , buf, count);
+        munmap(mapped_mem, partitionInfo->data.actual);
+
+        set_flash_bytemap(context, offset, count, FLASH_DIRTY);
+    }
+    catch (InternalFailure & e)
+    {
+        rc = -1;
+    }
+    return rc;
+}