summaryrefslogtreecommitdiffstats
path: root/vpnor/pnor_partition.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'vpnor/pnor_partition.hpp')
-rw-r--r--vpnor/pnor_partition.hpp139
1 files changed, 139 insertions, 0 deletions
diff --git a/vpnor/pnor_partition.hpp b/vpnor/pnor_partition.hpp
new file mode 100644
index 0000000..eb63a39
--- /dev/null
+++ b/vpnor/pnor_partition.hpp
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier: Apache-2.0 */
+/* Copyright (C) 2018 IBM Corp. */
+#pragma once
+
+extern "C" {
+#include "mbox.h"
+};
+
+#include "mboxd_pnor_partition_table.h"
+#include "pnor_partition_table.hpp"
+#include <fcntl.h>
+#include <string>
+#include <unistd.h>
+#include <experimental/filesystem>
+
+namespace openpower
+{
+namespace virtual_pnor
+{
+
+namespace fs = std::experimental::filesystem;
+
+class Request
+{
+ public:
+ /** @brief Construct a flash access request
+ *
+ * @param[in] ctx - The mbox context used to process the request
+ * @param[in] offset - The absolute offset into the flash device as
+ * provided by the mbox message associated with the
+ * request
+ *
+ * The class does not take ownership of the ctx pointer. The lifetime of
+ * the ctx pointer must strictly exceed the lifetime of the class
+ * instance.
+ */
+ Request(struct mbox_context* ctx, size_t offset) :
+ ctx(ctx), partition(ctx->vpnor->table->partition(offset)),
+ base(partition.data.base << ctx->block_size_shift),
+ offset(offset - base)
+ {
+ }
+ Request(const Request&) = delete;
+ Request& operator=(const Request&) = delete;
+ Request(Request&&) = default;
+ Request& operator=(Request&&) = default;
+ ~Request() = default;
+
+ ssize_t read(void* dst, size_t len)
+ {
+ len = clamp(len);
+ constexpr auto flags = O_RDONLY;
+ fs::path path = getPartitionFilePath(flags);
+ return fulfil(path, flags, dst, len);
+ }
+
+ ssize_t write(void* dst, size_t len)
+ {
+ if (len != clamp(len))
+ {
+ std::stringstream err;
+ err << "Request size 0x" << std::hex << len << " from offset 0x"
+ << std::hex << offset << " exceeds the partition size 0x"
+ << std::hex << (partition.data.size << ctx->block_size_shift);
+ throw OutOfBoundsOffset(err.str());
+ }
+ constexpr auto flags = O_RDWR;
+ /* Ensure file is at least the size of the maximum access */
+ fs::path path = getPartitionFilePath(flags);
+ resize(path, len);
+ return fulfil(path, flags, dst, len);
+ }
+
+ private:
+ /** @brief Clamp the access length to the maximum supported by the ToC */
+ size_t clamp(size_t len);
+
+ /** @brief Ensure the backing file is sized appropriately for the access
+ *
+ * We need to ensure the file is big enough to satisfy the request so that
+ * mmap() will succeed for the required size.
+ *
+ * @return The valid access length
+ *
+ * Throws: std::system_error
+ */
+ void resize(const std::experimental::filesystem::path& path, size_t len);
+
+ /** @brief Returns the partition file path associated with the offset.
+ *
+ * The search strategy for the partition file depends on the value of the
+ * flags parameter.
+ *
+ * For the O_RDONLY case:
+ *
+ * 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.
+ *
+ * For the O_RDWR case:
+ *
+ * 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] flags - The flags that will be used to open the file. Must
+ * be one of O_RDONLY or O_RDWR.
+ *
+ * Post-condition: The file described by the returned path exists
+ *
+ * Throws: std::filesystem_error, std::bad_alloc
+ */
+ std::experimental::filesystem::path getPartitionFilePath(int flags);
+
+ /** @brief Fill dst with the content of the partition relative to offset.
+ *
+ * @param[in] offset - The pnor offset(bytes).
+ * @param[out] dst - The buffer to fill with partition data
+ * @param[in] len - The length of the destination buffer
+ */
+ size_t fulfil(const std::experimental::filesystem::path& path, int flags,
+ void* dst, size_t len);
+
+ struct mbox_context* ctx;
+ const pnor_partition& partition;
+ size_t base;
+ size_t offset;
+};
+
+} // namespace virtual_pnor
+} // namespace openpower
OpenPOWER on IntegriCloud