summaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--Makefile.am43
-rw-r--r--configure.ac5
-rw-r--r--mboxd.c5
-rw-r--r--mboxd_pnor_partition_table.h2
-rw-r--r--pnor_partition.cpp187
-rw-r--r--pnor_partition.hpp162
-rw-r--r--pnor_partition_table.cpp2
-rw-r--r--test/create_read_window_vpnor.cpp2
8 files changed, 397 insertions, 11 deletions
diff --git a/Makefile.am b/Makefile.am
index 5614256..4f49644 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -16,7 +16,8 @@ mboxd_CFLAGS = $(LIBSYSTEMD_CFLAGS)
if VIRTUAL_PNOR_ENABLED
mboxd_SOURCES += pnor_partition_table.cpp \
mboxd_pnor_partition_table.cpp \
- mboxd_flash_virtual.cpp
+ mboxd_flash_virtual.cpp \
+ pnor_partition.cpp
mboxd_LDFLAGS += -lstdc++fs \
$(SDBUSPLUS_LIBS) \
@@ -39,13 +40,35 @@ AM_CXXFLAGS = $(CODE_COVERAGE_CXXFLAGS)
test_sanity_SOURCES = test/sanity.c
-test_copy_flash_SOURCES = test/copy_flash.c mboxd_flash.c mboxd_flash_physical.c common.c mtd.c test/tmpf.c
+test_copy_flash_SOURCES = \
+ test/copy_flash.c \
+ mboxd_flash.c \
+ mboxd_flash_physical.c \
+ common.c mtd.c \
+ test/tmpf.c
-test_erase_flash_SOURCES = test/erase_flash.c mboxd_flash.c common.c test/tmpf.c
+test_erase_flash_SOURCES = \
+ test/erase_flash.c \
+ mboxd_flash.c \
+ mboxd_flash_physical.c \
+ common.c \
+ test/tmpf.c
-test_write_flash_SOURCES = test/write_flash.c mboxd_flash.c common.c test/tmpf.c
+test_write_flash_SOURCES = \
+ test/write_flash.c \
+ mboxd_flash.c \
+ mboxd_flash_physical.c \
+ common.c \
+ test/tmpf.c
+
+TEST_MBOX_SRCS = \
+ mboxd_msg.c \
+ mboxd_windows.c \
+ mboxd_lpc.c \
+ mboxd_flash.c \
+ common.c \
+ mboxd_flash_physical.c
-TEST_MBOX_SRCS = mboxd_msg.c mboxd_windows.c mboxd_lpc.c mboxd_flash.c common.c mboxd_flash_physical.c
TEST_MOCK_SRCS = test/tmpf.c test/mbox.c test/system.c
test_get_mbox_info_v2_SOURCES = test/get_mbox_info_v2.c \
@@ -133,9 +156,13 @@ test_create_read_window_vpnor_SOURCES = \
mboxd_flash.c \
mboxd_pnor_partition_table.cpp \
mboxd_flash_virtual.cpp \
+ pnor_partition.cpp \
test/create_read_window_vpnor.cpp
test_create_read_window_vpnor_LDFLAGS = $(OESDK_TESTCASE_FLAGS)
-test_create_read_window_vpnor_LDADD = -lstdc++fs
+test_create_read_window_vpnor_LDADD = -lstdc++fs \
+ $(SDBUSPLUS_LIBS) \
+ $(PHOSPHOR_LOGGING_LIBS) \
+ $(PHOSPHOR_DBUS_INTERFACES_LIBS)
check_PROGRAMS = test/sanity \
test/copy_flash \
@@ -166,7 +193,9 @@ check_PROGRAMS = test/sanity \
test/get_mbox_info_v2_timeout
if VIRTUAL_PNOR_ENABLED
-check_PROGRAMS += test/create_pnor_partition_table test/create_read_window_vpnor
+check_PROGRAMS += \
+ test/create_pnor_partition_table \
+ test/create_read_window_vpnor
endif
TESTS = $(check_PROGRAMS)
diff --git a/configure.ac b/configure.ac
index 2f51e2b..94047da 100644
--- a/configure.ac
+++ b/configure.ac
@@ -76,8 +76,9 @@ AC_SUBST([LIBSYSTEMD_CFLAGS])
AC_SUBST([LIBSYSTEMD_LIBS])
AC_DEFINE(PARTITION_TOC_FILE, "pnor.toc", [The basename of the PNOR Table of contents file.])
-AC_DEFINE(PARTITION_FILES_LOC, "/var/lib/phosphor-software-manager/pnor/ro", [The path to the directory containing PNOR partition files.])
-
+AC_DEFINE(PARTITION_FILES_RO_LOC, "/var/lib/phosphor-software-manager/pnor/ro", [The path to the directory containing PNOR read only partition files.])
+AC_DEFINE(PARTITION_FILES_RW_LOC, "/var/lib/phosphor-software-manager/pnor/rw", [The path to the directory containing PNOR read write partition files.])
+AC_DEFINE(PARTITION_FILES_PRSV_LOC, "/var/lib/phosphor-software-manager/pnor/prsv", [The path to the directory containing PNOR preserve partition files.])
# Create configured output
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
diff --git a/mboxd.c b/mboxd.c
index fcc3688..e1f3251 100644
--- a/mboxd.c
+++ b/mboxd.c
@@ -314,7 +314,10 @@ int main(int argc, char **argv)
#ifdef VIRTUAL_PNOR_ENABLED
vpnor_create_partition_table(context);
- strcpy(context->paths.ro_loc, PARTITION_FILES_LOC);
+
+ strcpy(context->paths.ro_loc, PARTITION_FILES_RO_LOC);
+ strcpy(context->paths.rw_loc, PARTITION_FILES_RW_LOC);
+ strcpy(context->paths.prsv_loc, PARTITION_FILES_PRSV_LOC);
#endif
rc = init_signals(context, &set);
diff --git a/mboxd_pnor_partition_table.h b/mboxd_pnor_partition_table.h
index f494830..e6c899b 100644
--- a/mboxd_pnor_partition_table.h
+++ b/mboxd_pnor_partition_table.h
@@ -11,6 +11,8 @@ struct vpnor_partition_table;
struct vpnor_partition_paths
{
char ro_loc[PATH_MAX];
+ char rw_loc[PATH_MAX];
+ char prsv_loc[PATH_MAX];
};
#ifdef __cplusplus
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
diff --git a/pnor_partition.hpp b/pnor_partition.hpp
new file mode 100644
index 0000000..004dca6
--- /dev/null
+++ b/pnor_partition.hpp
@@ -0,0 +1,162 @@
+#pragma once
+
+#include "mboxd_pnor_partition_table.h"
+#include <fcntl.h>
+#include <string>
+#include <unistd.h>
+#include <experimental/filesystem>
+
+namespace openpower
+{
+namespace file
+{
+
+class Descriptor
+{
+ private:
+ /** default value */
+ int fd = -1;
+
+ public:
+ Descriptor() = default;
+ Descriptor(const Descriptor&) = delete;
+ Descriptor& operator=(const Descriptor&) = delete;
+ Descriptor(Descriptor&&) = delete;
+ Descriptor& operator=(Descriptor &&) = delete;
+
+ Descriptor(int fd) : fd(fd) {}
+
+ ~Descriptor()
+ {
+ if (fd >= 0)
+ {
+ close(fd);
+ }
+ }
+
+ int operator()() const
+ {
+ return fd;
+ }
+
+ void set(int descriptor)
+ {
+ fd = descriptor;
+ }
+};
+
+}// namespace file
+
+namespace virtual_pnor
+{
+
+namespace fs = std::experimental::filesystem;
+
+enum class ReturnCode : uint8_t
+{
+ FILE_NOT_FOUND = 0,
+ PARTITION_NOT_FOUND = 1,
+ PARTITION_READ_ONLY = 2,
+ FILE_OPEN_FAILURE = 3,
+ SUCCESS = 4,
+};
+
+class Request
+{
+ public:
+
+ Request() = default;
+ Request(const Request&) = delete;
+ Request& operator=(const Request&) = delete;
+ Request(Request&&) = default;
+ Request& operator=(Request&&) = default;
+ ~Request() = default;
+
+ openpower::file::Descriptor fd;
+
+ protected:
+ /** @brief opens the partition file
+ *
+ * @param[in] filePath - Absolute file path.
+ * @param[in] mode - File open mode.
+ */
+ ReturnCode open(const std::string& filePath, int mode);
+
+ /** @brief returns the partition file path associated with the offset.
+ *
+ * @param[in] context - The mbox context pointer.
+ * @param[in] offset - The pnor offset(bytes).
+ */
+
+ std::string getPartitionFilePath(struct mbox_context* context,
+ uint32_t offset);
+
+ const pnor_partition* partition = nullptr;
+};
+
+/** @class RORequest
+ * @brief Represent the read request of the partition.
+ * Stores the partition meta data.
+ */
+class RORequest : public Request
+{
+ public:
+ RORequest() = default;
+ RORequest(const RORequest&) = delete;
+ RORequest& operator=(const RORequest&) = delete;
+ RORequest(RORequest&&) = default;
+ RORequest& operator=(RORequest&&) = default;
+ ~RORequest(){};
+
+ /** @brief opens the partition file associated with the offset
+ * in read only mode and gets the partition details.
+ *
+ * 1. Depending on the partition type,tries to open the file
+ * from the associated partition(RW/PRSV/RO).
+ * 1a. if file not found in the corresponding
+ * partition(RW/PRSV/RO) then tries to read the file from
+ * the read only partition.
+ * 1b. if the file not found in the read only partition then
+ * throw exception.
+ *
+ * @param[in] context - The mbox context pointer.
+ * @param[in] offset - The pnor offset(bytes).
+ */
+ const pnor_partition* getPartitionInfo(struct mbox_context* context,
+ uint32_t offset);
+};
+
+/** @class RWRequest
+ * @brief Represent the write request of the partition.
+ * Stores the partition meta data.
+ */
+class RWRequest : public Request
+{
+ public:
+
+ RWRequest() = default;
+ RWRequest(const RWRequest&) = delete;
+ RWRequest& operator=(const RWRequest&) = delete;
+ RWRequest(RWRequest&&) = default;
+ RWRequest& operator=(RWRequest&&) = default;
+ ~RWRequest() {};
+
+ /** @brief opens the partition file associated with the offset
+ * in write mode and gets the parttition details.
+ *
+ * 1. Depending on the partition type tries to open the file
+ * from the associated partition.
+ * 1a. if file not found in the corresponding partition(RW/PRSV)
+ * then copy the file from the read only partition to the (RW/PRSV)
+ * partition depending on the partition type.
+ * 1b. if the file not found in the read only partition then throw exception.
+ *
+ * @param[in] context - The mbox context pointer.
+ * @param[in] offset - The pnor offset(bytes).
+ */
+ const pnor_partition* getPartitionInfo(struct mbox_context* context,
+ uint32_t offset);
+};
+
+}// namespace virtual_pnor
+}// namespace openpower
diff --git a/pnor_partition_table.cpp b/pnor_partition_table.cpp
index 17f5011..d20b44c 100644
--- a/pnor_partition_table.cpp
+++ b/pnor_partition_table.cpp
@@ -23,7 +23,7 @@ constexpr size_t size = 4096;
} // namespace block
Table::Table():
- Table(fs::path(PARTITION_FILES_LOC))
+ Table(fs::path(PARTITION_FILES_RO_LOC))
{
}
diff --git a/test/create_read_window_vpnor.cpp b/test/create_read_window_vpnor.cpp
index 855d88d..8121498 100644
--- a/test/create_read_window_vpnor.cpp
+++ b/test/create_read_window_vpnor.cpp
@@ -66,6 +66,8 @@ int main()
struct mbox_context *ctx = mbox_create_test_context(N_WINDOWS, WINDOW_SIZE);
strcpy(ctx->paths.ro_loc,tmpdir);
+ strcpy(ctx->paths.rw_loc,tmpdir);
+ strcpy(ctx->paths.prsv_loc,tmpdir);
vpnor_create_partition_table_from_path(ctx, tmpdir);
OpenPOWER on IntegriCloud