summaryrefslogtreecommitdiffstats
path: root/vpnor/pnor_partition_table.hpp
diff options
context:
space:
mode:
authorAndrew Jeffery <andrew@aj.id.au>2018-03-26 11:56:16 +1030
committerAndrew Jeffery <andrew@aj.id.au>2018-04-04 17:27:31 +0930
commit53c21aaa803e148c9c79cb3f5e0252d911506b10 (patch)
tree2c8e7482711617bc12a58022dd5839234a17f6a7 /vpnor/pnor_partition_table.hpp
parent8b9102389718f639434253be3fa99f8f6d38d9a6 (diff)
downloadphosphor-mboxd-53c21aaa803e148c9c79cb3f5e0252d911506b10.tar.gz
phosphor-mboxd-53c21aaa803e148c9c79cb3f5e0252d911506b10.zip
vpnor: Isolate relevant code in vpnor directory
This is prepatory work for introducing more vpnor-specific behaviours to window handling. We will be introducing more objects to link, in order to hook some of the window command handlers. This change takes the opportunity to revert back to the upstream names for some of the original C files. Change-Id: I6b67ae466a2695054035e65ba752881be9c32d1a Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Diffstat (limited to 'vpnor/pnor_partition_table.hpp')
-rw-r--r--vpnor/pnor_partition_table.hpp345
1 files changed, 345 insertions, 0 deletions
diff --git a/vpnor/pnor_partition_table.hpp b/vpnor/pnor_partition_table.hpp
new file mode 100644
index 0000000..10dccdd
--- /dev/null
+++ b/vpnor/pnor_partition_table.hpp
@@ -0,0 +1,345 @@
+/* SPDX-License-Identifier: Apache-2.0 */
+/* Copyright (C) 2018 IBM Corp. */
+#pragma once
+
+#include <vector>
+#include <memory>
+#include <numeric>
+#include <experimental/filesystem>
+#include "common.h"
+#include "mbox.h"
+#include "pnor_partition_defs.h"
+
+namespace openpower
+{
+namespace virtual_pnor
+{
+
+namespace fs = std::experimental::filesystem;
+
+using PartitionTable = std::vector<uint8_t>;
+using checksum_t = uint32_t;
+
+/** @brief Convert the input partition table to big endian.
+ *
+ * @param[in] src - reference to the pnor partition table
+ *
+ * @returns converted partition table
+ */
+PartitionTable endianFixup(const PartitionTable& src);
+
+/** @brief Parse a ToC line (entry) into the corresponding FFS partition
+ * object.
+ *
+ * @param[in] line - The ToC line to parse
+ * @param[in] blockSize - The flash block size in bytes
+ * @param[out] part - The partition object to populate with the information
+ * parsed from the provided ToC line
+ *
+ * Throws: MalformedTocEntry, InvalidTocEntry
+ */
+void parseTocLine(const std::string& line, size_t blockSize,
+ pnor_partition& part);
+
+namespace details
+{
+
+/** @brief Compute XOR-based checksum, by XORing consecutive words
+ * in the input data. Input must be aligned to word boundary.
+ *
+ * @param[in] data - input data on which checksum is computed
+ *
+ * @returns computed checksum
+ */
+template <class T> checksum_t checksum(const T& data)
+{
+ static_assert(sizeof(decltype(data)) % sizeof(checksum_t) == 0,
+ "sizeof(data) is not aligned to sizeof(checksum_t) boundary");
+
+ auto begin = reinterpret_cast<const checksum_t*>(&data);
+ auto end = begin + (sizeof(decltype(data)) / sizeof(checksum_t));
+
+ return std::accumulate(begin, end, 0, std::bit_xor<checksum_t>());
+}
+
+} // namespace details
+
+namespace partition
+{
+
+/** @class Table
+ * @brief Generates virtual PNOR partition table.
+ *
+ * Generates virtual PNOR partition table upon construction. Reads
+ * the PNOR information generated by this tool :
+ * github.com/openbmc/openpower-pnor-code-mgmt/blob/master/generate-squashfs,
+ * which generates a minimalistic table-of-contents (toc) file and
+ * individual files to represent various partitions that are of interest -
+ * these help form the "virtual" PNOR, which is typically a subset of the full
+ * PNOR image.
+ * These files are stored in a well-known location on the PNOR.
+ * Based on this information, this class prepares the partition table whose
+ * structure is as outlined in pnor_partition.h.
+ *
+ * The virtual PNOR supports 4KB erase blocks - partitions must be aligned to
+ * this size.
+ */
+class Table
+{
+ public:
+ /** @brief Constructor accepting the path of the directory
+ * that houses the PNOR partition files.
+ *
+ * @param[in] ctx - Acquire sizes and paths relevant to the table
+ *
+ * Throws MalformedTocEntry, InvalidTocEntry
+ */
+ Table(const struct mbox_context* ctx);
+
+ Table(const Table&) = delete;
+ Table& operator=(const Table&) = delete;
+ Table(Table&&) = delete;
+ Table& operator=(Table&&) = delete;
+ ~Table() = default;
+
+ /** @brief Return the exact size of partition table in bytes
+ *
+ * @returns size_t - size of partition table in bytes
+ */
+ size_t size() const
+ {
+ return szBytes;
+ }
+
+ /** @brief Return aligned size of partition table in bytes
+ *
+ * The value returned will be greater-than or equal to size(), and
+ * aligned to blockSize.
+ *
+ * @returns size_t - capacity of partition table in bytes
+ */
+ size_t capacity() const
+ {
+ return align_up(szBytes, blockSize);
+ }
+
+ /** @brief Return the size of partition table in blocks
+ *
+ * @returns size_t - size of partition table in blocks
+ */
+ size_t blocks() const
+ {
+ return capacity() / blockSize;
+ }
+
+ /** @brief Return a partition table having byte-ordering
+ * that the host expects.
+ *
+ * The host needs the partion table in big-endian.
+ *
+ * @returns const reference to host partition table.
+ */
+ const pnor_partition_table& getHostTable() const
+ {
+ return *(reinterpret_cast<const pnor_partition_table*>(hostTbl.data()));
+ }
+
+ /** @brief Return a little-endian partition table
+ *
+ * @returns const reference to native partition table
+ */
+ const pnor_partition_table& getNativeTable() const
+ {
+ return *(reinterpret_cast<const pnor_partition_table*>(tbl.data()));
+ }
+
+ /** @brief Return partition corresponding to PNOR offset, the offset
+ * is within returned partition.
+ *
+ * @param[in] offset - PNOR offset in bytes
+ *
+ * @returns const reference to pnor_partition, if found, else an
+ * exception will be thrown.
+ *
+ * Throws: UnmappedOffset
+ */
+ const pnor_partition& partition(size_t offset) const;
+
+ /** @brief Return partition corresponding to input partition name.
+ *
+ * @param[in] name - PNOR partition name
+ *
+ * @returns const reference to pnor_partition, if found, else an
+ * exception will be thrown.
+ *
+ * Throws: UnknownPartition
+ */
+ const pnor_partition& partition(const std::string& name) const;
+
+ private:
+ /** @brief Prepares a vector of PNOR partition structures.
+ *
+ * @param[in] ctx - An mbox context providing partition locations
+ *
+ * Throws: MalformedTocEntry, InvalidTocEntry
+ */
+ void preparePartitions(const struct mbox_context* ctx);
+
+ /** @brief Prepares the PNOR header.
+ */
+ void prepareHeader();
+
+ /** @brief Allocate memory to hold the partion table. Determine the
+ * amount needed based on the partition files in the toc file.
+ *
+ * @param[in] tocFile - Table of contents file path.
+ */
+ void allocateMemory(const fs::path& tocFile);
+
+ /** @brief Return a little-endian partition table
+ *
+ * @returns reference to native partition table
+ */
+ pnor_partition_table& getNativeTable()
+ {
+ return *(reinterpret_cast<pnor_partition_table*>(tbl.data()));
+ }
+
+ /** @brief Size of the PNOR partition table -
+ * sizeof(pnor_partition_table) +
+ * (no. of partitions * sizeof(pnor_partition)),
+ */
+ size_t szBytes;
+
+ /** @brief Partition table */
+ PartitionTable tbl;
+
+ /** @brief Partition table with host byte ordering */
+ PartitionTable hostTbl;
+
+ /** @brief Directory housing generated PNOR partition files */
+ fs::path directory;
+
+ /** @brief Number of partitions */
+ size_t numParts;
+
+ /** @brief PNOR block size, in bytes */
+ size_t blockSize;
+
+ /** @brief PNOR size, in bytes */
+ size_t pnorSize;
+};
+} // namespace partition
+
+/** @brief An exception type storing a reason string.
+ *
+ * This looks a lot like how std::runtime_error might be implemented however
+ * we want to avoid extending it, as exceptions extending ReasonedError have
+ * an expectation of being handled (can be predicted and are inside the scope
+ * of the program).
+ *
+ * From std::runtime_error documentation[1]:
+ *
+ * > Defines a type of object to be thrown as exception. It reports errors
+ * > that are due to events beyond the scope of the program and can not be
+ * > easily predicted.
+ *
+ * [1] http://en.cppreference.com/w/cpp/error/runtime_error
+ *
+ * We need to keep the inheritance hierarchy separate: This avoids the
+ * introduction of code that overzealously catches std::runtime_error to
+ * handle exceptions that would otherwise derive ReasonedError, and in the
+ * process swallows genuine runtime failures.
+ */
+class ReasonedError : public std::exception
+{
+ public:
+ ReasonedError(const std::string&& what) : _what(what)
+ {
+ }
+ const char* what() const noexcept
+ {
+ return _what.c_str();
+ };
+
+ private:
+ const std::string _what;
+};
+
+/** @brief Base exception type for errors related to ToC entry parsing.
+ *
+ * Callers of parseTocEntry() may not be concerned with the specifics and
+ * rather just want to extract and log what().
+ */
+class TocEntryError : public ReasonedError
+{
+ public:
+ TocEntryError(const std::string&& reason) : ReasonedError(std::move(reason))
+ {
+ }
+};
+
+/** @brief The exception thrown on finding a syntax error in the ToC entry
+ *
+ * If the syntax is wrong, or expected values are missing, the ToC entry is
+ * malformed
+ */
+class MalformedTocEntry : public TocEntryError
+{
+ public:
+ MalformedTocEntry(const std::string&& reason) :
+ TocEntryError(std::move(reason))
+ {
+ }
+};
+
+/** @brief The exception thrown on finding a semantic error in the ToC entry
+ *
+ * If the syntax of the ToC entry is correct but the semantics are broken,
+ * then we have an invalid ToC entry.
+ */
+class InvalidTocEntry : public TocEntryError
+{
+ public:
+ InvalidTocEntry(const std::string&& reason) :
+ TocEntryError(std::move(reason))
+ {
+ }
+};
+
+class UnmappedOffset : public std::exception
+{
+ public:
+ UnmappedOffset(size_t base, size_t next) : base(base), next(next)
+ {
+ }
+
+ const size_t base;
+ const size_t next;
+};
+
+class OutOfBoundsOffset : public ReasonedError
+{
+ public:
+ OutOfBoundsOffset(const std::string&& reason) :
+ ReasonedError(std::move(reason))
+ {
+ }
+};
+
+class UnknownPartition : public ReasonedError
+{
+ public:
+ UnknownPartition(const std::string&& reason) :
+ ReasonedError(std::move(reason))
+ {
+ }
+};
+
+} // namespace virtual_pnor
+} // namespace openpower
+
+struct vpnor_partition_table
+{
+ openpower::virtual_pnor::partition::Table* table;
+};
OpenPOWER on IntegriCloud