blob: 110513425e069ddba6fe3bfae8f54a403e629e86 [file] [log] [blame]
Deepak Kodihalli393821d2017-04-28 04:44:38 -05001#pragma once
2
3#include <vector>
4#include <memory>
5#include <numeric>
6#include <experimental/filesystem>
7#include "pnor_partition_defs.h"
8
9namespace openpower
10{
11namespace virtual_pnor
12{
13
14namespace fs = std::experimental::filesystem;
15
16using PartitionTable = std::vector<uint8_t>;
17using checksum_t = uint32_t;
18
19/** @brief Convert the input partition table to big endian.
20 *
21 * @param[in] src - reference to the pnor partition table
22 *
23 * @returns converted partition table
24 */
25PartitionTable endianFixup(const PartitionTable& src);
26
Andrew Jefferyd394a782018-02-21 16:16:14 +103027/** @brief Parse a ToC line (entry) into the corresponding FFS partition
28 * object.
29 *
30 * @param[in] line - The ToC line to parse
31 * @param[in] blockSize - The flash block size in bytes
32 * @param[out] part - The partition object to populate with the information
33 * parsed from the provided ToC line
34 *
35 * @returns True on success, false on failure.
36 */
37bool parseTocLine(const std::string& line, size_t blockSize,
38 pnor_partition& part);
39
Deepak Kodihalli393821d2017-04-28 04:44:38 -050040namespace details
41{
42
43/** @brief Compute XOR-based checksum, by XORing consecutive words
44 * in the input data. Input must be aligned to word boundary.
45 *
46 * @param[in] data - input data on which checksum is computed
47 *
48 * @returns computed checksum
49 */
Andrew Jefferyf34db312018-03-09 15:27:03 +103050template <class T> checksum_t checksum(const T& data)
Deepak Kodihalli393821d2017-04-28 04:44:38 -050051{
52 static_assert(sizeof(decltype(data)) % sizeof(checksum_t) == 0,
53 "sizeof(data) is not aligned to sizeof(checksum_t) boundary");
54
55 auto begin = reinterpret_cast<const checksum_t*>(&data);
56 auto end = begin + (sizeof(decltype(data)) / sizeof(checksum_t));
57
58 return std::accumulate(begin, end, 0, std::bit_xor<checksum_t>());
59}
60
61} // namespace details
62
63namespace partition
64{
65
66/** @class Table
67 * @brief Generates virtual PNOR partition table.
68 *
69 * Generates virtual PNOR partition table upon construction. Reads
70 * the PNOR information generated by this tool :
71 * github.com/openbmc/openpower-pnor-code-mgmt/blob/master/generate-squashfs,
72 * which generates a minimalistic table-of-contents (toc) file and
73 * individual files to represent various partitions that are of interest -
74 * these help form the "virtual" PNOR, which is typically a subset of the full
75 * PNOR image.
76 * These files are stored in a well-known location on the PNOR.
77 * Based on this information, this class prepares the partition table whose
78 * structure is as outlined in pnor_partition.h.
79 *
80 * The virtual PNOR supports 4KB erase blocks - partitions must be aligned to
81 * this size.
82 */
83class Table
84{
Andrew Jefferyf34db312018-03-09 15:27:03 +103085 public:
86 /** @brief Constructor accepting the path of the directory
87 * that houses the PNOR partition files.
88 *
89 * @param[in] directory - path of the directory housing PNOR partitions
90 * @param[in] blockSize - PNOR block size, in bytes. See
91 * open-power/hostboot/blob/master/src/usr/pnor/ffs.h for
92 * the PNOR FFS structure.
93 * @param[in] pnorSize - PNOR size, in bytes
94 */
95 Table(fs::path&& directory, size_t blockSize, size_t pnorSize);
Deepak Kodihalli393821d2017-04-28 04:44:38 -050096
Andrew Jefferyf34db312018-03-09 15:27:03 +103097 Table(const Table&) = delete;
98 Table& operator=(const Table&) = delete;
99 Table(Table&&) = delete;
100 Table& operator=(Table&&) = delete;
101 ~Table() = default;
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500102
Andrew Jefferyf34db312018-03-09 15:27:03 +1030103 /** @brief Return size of partition table
104 *
105 * @returns size_t - size of partition table in blocks
106 */
107 size_t size() const
108 {
109 return szBlocks;
110 }
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500111
Andrew Jefferyf34db312018-03-09 15:27:03 +1030112 /** @brief Return a partition table having byte-ordering
113 * that the host expects.
114 *
115 * The host needs the partion table in big-endian.
116 *
117 * @returns const reference to host partition table.
118 */
119 const pnor_partition_table& getHostTable() const
120 {
121 return *(reinterpret_cast<const pnor_partition_table*>(hostTbl.data()));
122 }
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500123
Andrew Jefferyf34db312018-03-09 15:27:03 +1030124 /** @brief Return a little-endian partition table
125 *
126 * @returns const reference to native partition table
127 */
128 const pnor_partition_table& getNativeTable() const
129 {
130 return *(reinterpret_cast<const pnor_partition_table*>(tbl.data()));
131 }
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500132
Andrew Jefferyf34db312018-03-09 15:27:03 +1030133 /** @brief Return partition corresponding to PNOR offset, the offset
134 * is within returned partition.
135 *
136 * @param[in] offset - PNOR offset in bytes
137 *
138 * @returns const reference to pnor_partition, if found, else an
139 * exception will be thrown.
140 */
141 const pnor_partition& partition(size_t offset) const;
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500142
Andrew Jefferyf34db312018-03-09 15:27:03 +1030143 /** @brief Return partition corresponding to input partition name.
144 *
145 * @param[in] name - PNOR partition name
146 *
147 * @returns const reference to pnor_partition, if found, else an
148 * exception will be thrown.
149 */
150 const pnor_partition& partition(const std::string& name) const;
Deepak Kodihalli8a899692017-07-11 23:17:19 -0500151
Andrew Jefferyf34db312018-03-09 15:27:03 +1030152 private:
153 /** @brief Prepares a vector of PNOR partition structures.
154 */
155 void preparePartitions();
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500156
Andrew Jefferyf34db312018-03-09 15:27:03 +1030157 /** @brief Prepares the PNOR header.
158 */
159 void prepareHeader();
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500160
Andrew Jefferyf34db312018-03-09 15:27:03 +1030161 /** @brief Allocate memory to hold the partion table. Determine the
162 * amount needed based on the partition files in the toc file.
163 *
164 * @param[in] tocFile - Table of contents file path.
165 */
166 void allocateMemory(const fs::path& tocFile);
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500167
Andrew Jefferyf34db312018-03-09 15:27:03 +1030168 /** @brief Return a little-endian partition table
169 *
170 * @returns reference to native partition table
171 */
172 pnor_partition_table& getNativeTable()
173 {
174 return *(reinterpret_cast<pnor_partition_table*>(tbl.data()));
175 }
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500176
Andrew Jefferyf34db312018-03-09 15:27:03 +1030177 /** @brief Size of the PNOR partition table -
178 * sizeof(pnor_partition_table) +
179 * (no. of partitions * sizeof(pnor_partition)),
180 * measured in erase-blocks.
181 */
182 size_t szBlocks;
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500183
Andrew Jefferyf34db312018-03-09 15:27:03 +1030184 /** @brief Partition table */
185 PartitionTable tbl;
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500186
Andrew Jefferyf34db312018-03-09 15:27:03 +1030187 /** @brief Partition table with host byte ordering */
188 PartitionTable hostTbl;
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500189
Andrew Jefferyf34db312018-03-09 15:27:03 +1030190 /** @brief Directory housing generated PNOR partition files */
191 fs::path directory;
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500192
Andrew Jefferyf34db312018-03-09 15:27:03 +1030193 /** @brief Number of partitions */
194 size_t numParts;
Deepak Kodihallid1d79302017-07-11 23:01:39 -0500195
Andrew Jefferyf34db312018-03-09 15:27:03 +1030196 /** @brief PNOR block size, in bytes */
197 size_t blockSize;
Deepak Kodihallid1d79302017-07-11 23:01:39 -0500198
Andrew Jefferyf34db312018-03-09 15:27:03 +1030199 /** @brief PNOR size, in bytes */
200 size_t pnorSize;
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500201};
202
203} // namespace partition
204} // namespace virtual_pnor
205} // namespace openpower