summaryrefslogtreecommitdiffstats
path: root/pnor_partition.cpp
diff options
context:
space:
mode:
authorRatan Gupta <ratagupt@in.ibm.com>2017-06-06 14:31:37 +0530
committerRatan Gupta <ratagupt@in.ibm.com>2017-06-29 22:08:30 +0530
commitc0ef98774c3e0f3e365c745f0b82ec0b8739ca47 (patch)
tree126e7eff3d56d711ea12d52b70792b831dd53921 /pnor_partition.cpp
parentb0327581344ffba6cb53fca87d386cbf567986e9 (diff)
downloadphosphor-mboxd-c0ef98774c3e0f3e365c745f0b82ec0b8739ca47.tar.gz
phosphor-mboxd-c0ef98774c3e0f3e365c745f0b82ec0b8739ca47.zip
Read/write window property defines FFS partition file location.
The BMC loads the PNOR partitions in a read-only volume. So after that there are following two cases: Read: Tries to open the file in read only mode from the partition(READONLY/READWRITE/PRESERVED), Partition Table tells the partition type depends on the offset. if file is not there in the mapped partition then tries to open the file from the read only partition. Write: Tries to open the file in write mode from the partition(READWRITE/PRESERVED), if file is not there in the mapped partition then mailbox daemon will copy the requested partition to the read-write volume to make changes to it. Change-Id: Ic0ef882380b56536ac55feae3ec563de95fdd4a6 Signed-off-by: Ratan Gupta <ratagupt@in.ibm.com>
Diffstat (limited to 'pnor_partition.cpp')
-rw-r--r--pnor_partition.cpp187
1 files changed, 187 insertions, 0 deletions
diff --git a/pnor_partition.cpp b/pnor_partition.cpp
new file mode 100644
index 0000000..3f4fd02
--- /dev/null
+++ b/pnor_partition.cpp
@@ -0,0 +1,187 @@
+#include "pnor_partition.hpp"
+#include "config.h"
+#include "mboxd_flash.h"
+#include "mboxd_pnor_partition_table.h"
+#include "xyz/openbmc_project/Common/error.hpp"
+#include <phosphor-logging/log.hpp>
+#include <phosphor-logging/elog-errors.hpp>
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#include "common.h"
+
+#include <string>
+#include <exception>
+#include <stdexcept>
+#include <iostream>
+
+namespace openpower
+{
+namespace virtual_pnor
+{
+
+using namespace phosphor::logging;
+using namespace sdbusplus::xyz::openbmc_project::Common::Error;
+using namespace std::string_literals;
+
+ReturnCode Request::open(const std::string& path,
+ int mode)
+{
+ if (mode == O_RDWR &&
+ partition->data.user.data[1] & PARTITION_READONLY)
+ {
+ MSG_ERR("Can't open the RO partition for write");
+ return ReturnCode::PARTITION_READ_ONLY;
+ }
+
+ fs::path partitionFilePath = path;
+
+ if (!fs::exists(partitionFilePath))
+ {
+ return ReturnCode::FILE_NOT_FOUND;
+ }
+
+ auto descriptor = ::open(partitionFilePath.c_str(), mode);
+ if (descriptor < 0)
+ {
+ return ReturnCode::FILE_OPEN_FAILURE;
+ }
+
+ fd.set(descriptor);
+ descriptor = -1;
+
+ return ReturnCode::SUCCESS;
+}
+
+std::string Request::getPartitionFilePath(struct mbox_context* context,
+ uint32_t offset)
+{
+ partition = vpnor_get_partition(context, offset);
+ if (!partition)
+ {
+ MSG_ERR("Couldn't get the partition info for offset[0x%.8x]",offset);
+ elog<InternalFailure>();
+ }
+
+ fs::path partitionFilePath;
+
+ switch (partition->data.user.data[1] &
+ (PARTITION_PRESERVED | PARTITION_READONLY))
+ {
+ case PARTITION_PRESERVED:
+ partitionFilePath = context->paths.prsv_loc;
+ break;
+
+ case PARTITION_READONLY:
+ partitionFilePath = context->paths.ro_loc;
+ break;
+
+ default:
+ partitionFilePath = context->paths.rw_loc;
+ }
+ partitionFilePath /= partition->data.name;
+ return partitionFilePath.string();
+}
+
+const pnor_partition* RORequest::getPartitionInfo(struct mbox_context* context,
+ uint32_t offset)
+{
+ std::string path = getPartitionFilePath(context, offset);
+
+ ReturnCode rc = Request::open(path, O_RDONLY);
+ if (rc == ReturnCode::SUCCESS)
+ {
+ return partition;
+ }
+ // not interested in any other error except FILE_NOT_FOUND
+ if (rc != ReturnCode::FILE_NOT_FOUND)
+ {
+ elog<InternalFailure>();
+ }
+
+ // if the offset lies in read only partition then throw error.
+ if (partition->data.user.data[1] & PARTITION_READONLY)
+ {
+ MSG_ERR("Can't open the partition file");
+ elog<InternalFailure>();
+ }
+
+ MSG_DBG("Couldn't open the file[%s]", path.c_str());
+ // we don't get the file in the respective partition(RW/PSRV)
+ // try to open it from RO location.
+
+ fs::path partitionFilePath = context->paths.ro_loc;
+ partitionFilePath /= partition->data.name;
+
+ rc = Request::open(path, O_RDONLY);
+ if (rc != ReturnCode::SUCCESS)
+ {
+ elog<InternalFailure>();
+ }
+
+ return partition;
+
+}
+
+const pnor_partition* RWRequest::getPartitionInfo(struct mbox_context* context,
+ uint32_t offset)
+{
+ std::string path = getPartitionFilePath(context, offset);
+
+ ReturnCode rc = Request::open(path, O_RDWR);
+ if (rc == ReturnCode::SUCCESS)
+ {
+ return partition;
+ }
+ // not interested in any other error except FILE_NOT_FOUND
+ if (rc != ReturnCode::FILE_NOT_FOUND)
+ {
+ elog<InternalFailure>();
+ }
+
+ // if the file is not available in the respective(RW/PSRV) partition
+ // then copy the file from RO to the respective(RW/PSRV) partition
+ // and open it for writing.
+
+ fs::path fromPath = context->paths.ro_loc;
+ fromPath /= partition->data.name;
+ if (!fs::exists(fromPath))
+ {
+ MSG_ERR("Couldn't find the file[%s]",fromPath.c_str());
+ elog<InternalFailure>();
+ }
+ //copy the file from ro to respective partition
+ fs::path toPath = context->paths.rw_loc;
+
+ if (partition->data.user.data[1] & PARTITION_PRESERVED)
+ {
+ toPath = context->paths.prsv_loc;
+ }
+
+ toPath /= partition->data.name;
+
+ MSG_DBG("Didn't find the file in the desired partition so copying[%s]\n",
+ toPath.c_str());
+
+ if (fs::copy_file(fromPath, toPath))
+ {
+ MSG_DBG("File copied from[%s] to [%s]\n",
+ fromPath.c_str(), toPath.c_str());
+ }
+
+ rc = Request::open(toPath.c_str(), O_RDWR);
+
+ if (rc != ReturnCode::SUCCESS)
+ {
+ elog<InternalFailure>();
+ }
+
+ return partition;
+}
+
+}// namespace virtual_pnor
+}// namespace openpower
OpenPOWER on IntegriCloud