summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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