pnor : generate partition table
Implement a class that, upon construction, generates the virtual PNOR
partition table. The virtual PNOR is typically a subset of the full PNOR
image, by choosing partitions of interest.
The generation is based on upon information read from the
PNOR partition files and table of contents (toc) file.
Provide an interface to the virtual PNOR partition table.
Change-Id: I7a68e3833b8cf66e92eb6ca274f6a3c376ce0add
Signed-off-by: Deepak Kodihalli <dkodihal@in.ibm.com>
diff --git a/pnor_partition_table.hpp b/pnor_partition_table.hpp
new file mode 100644
index 0000000..b6c50f4
--- /dev/null
+++ b/pnor_partition_table.hpp
@@ -0,0 +1,214 @@
+#pragma once
+
+#include <vector>
+#include <memory>
+#include <numeric>
+#include <experimental/filesystem>
+#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);
+
+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] directory - path of the directory housing PNOR partitions
+ */
+ Table(fs::path&& directory);
+
+ Table();
+ Table(const Table&) = delete;
+ Table& operator=(const Table&) = delete;
+ Table(Table&&) = delete;
+ Table& operator=(Table&&) = delete;
+ ~Table() = default;
+
+ /** @brief Return size of partition table
+ *
+ * @returns size_t - size of partition table in blocks
+ */
+ size_t size() const
+ {
+ return szBlocks;
+ }
+
+ /** @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 a
+ * reference to a zeroed out pnor_partition structure.
+ */
+ const pnor_partition& partition(size_t offset) const;
+
+ private:
+ /** @brief Prepares a vector of PNOR partition structures.
+ */
+ void preparePartitions();
+
+ /** @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 Populate fields related to sizes for the input
+ * pnor_partition structure.
+ *
+ * @param[in/out] part - pnor_partition structure
+ * @param[in] start - partition start address
+ * @param[in] end - partition end address
+ */
+ void writeSizes(pnor_partition& part, size_t start, size_t end);
+
+ /** @brief Populate userdata bits for the input
+ * pnor_partition structure.
+ *
+ * @param[in/out] part - pnor_partition structure
+ * @param[in] data - string having userdata fields in a
+ * comma-separated line.
+ */
+ void writeUserdata(pnor_partition& part, const std::string& data);
+
+ /** @brief Populate the name and id fields for the input
+ * pnor_partition structure.
+ *
+ * @param[in/out] part - pnor_partition structure
+ * @param[in] name - partition name
+ * @param[id] id - partition id
+ */
+ void writeNameAndId(pnor_partition& part, std::string&& name,
+ const std::string& id);
+
+ /** @brief Populate default/unused fields for the input
+ * pnor_partition structure.
+ *
+ * @param[in/out] part - pnor_partition structure
+ */
+ void writeDefaults(pnor_partition& part);
+
+ /** @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)),
+ * measured in erase-blocks.
+ */
+ size_t szBlocks;
+
+ /** @brief Size of virtual PNOR image, measured in erase-blocks */
+ size_t imgBlocks;
+
+ /** @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;
+};
+
+} // namespace partition
+} // namespace virtual_pnor
+} // namespace openpower