blob: 23cb9f5f0ad3344f2d0668c2d0d796be4dde84e7 [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
27namespace details
28{
29
30/** @brief Compute XOR-based checksum, by XORing consecutive words
31 * in the input data. Input must be aligned to word boundary.
32 *
33 * @param[in] data - input data on which checksum is computed
34 *
35 * @returns computed checksum
36 */
37template <class T>
38checksum_t checksum(const T& data)
39{
40 static_assert(sizeof(decltype(data)) % sizeof(checksum_t) == 0,
41 "sizeof(data) is not aligned to sizeof(checksum_t) boundary");
42
43 auto begin = reinterpret_cast<const checksum_t*>(&data);
44 auto end = begin + (sizeof(decltype(data)) / sizeof(checksum_t));
45
46 return std::accumulate(begin, end, 0, std::bit_xor<checksum_t>());
47}
48
49} // namespace details
50
51namespace partition
52{
53
54/** @class Table
55 * @brief Generates virtual PNOR partition table.
56 *
57 * Generates virtual PNOR partition table upon construction. Reads
58 * the PNOR information generated by this tool :
59 * github.com/openbmc/openpower-pnor-code-mgmt/blob/master/generate-squashfs,
60 * which generates a minimalistic table-of-contents (toc) file and
61 * individual files to represent various partitions that are of interest -
62 * these help form the "virtual" PNOR, which is typically a subset of the full
63 * PNOR image.
64 * These files are stored in a well-known location on the PNOR.
65 * Based on this information, this class prepares the partition table whose
66 * structure is as outlined in pnor_partition.h.
67 *
68 * The virtual PNOR supports 4KB erase blocks - partitions must be aligned to
69 * this size.
70 */
71class Table
72{
73 public:
74 /** @brief Constructor accepting the path of the directory
75 * that houses the PNOR partition files.
76 *
77 * @param[in] directory - path of the directory housing PNOR partitions
Deepak Kodihallid1d79302017-07-11 23:01:39 -050078 * @param[in] blockSize - PNOR block size, in bytes. See
79 * open-power/hostboot/blob/master/src/usr/pnor/ffs.h for
80 * the PNOR FFS structure.
81 * @param[in] pnorSize - PNOR size, in bytes
Deepak Kodihalli393821d2017-04-28 04:44:38 -050082 */
Deepak Kodihallid1d79302017-07-11 23:01:39 -050083 Table(fs::path&& directory,
84 size_t blockSize,
85 size_t pnorSize);
Deepak Kodihalli393821d2017-04-28 04:44:38 -050086
Deepak Kodihallid1d79302017-07-11 23:01:39 -050087 /** @brief Constructor - creates partition table
88 *
89 * @param[in] blockSize - PNOR block size, in bytes
90 * @param[in] pnorSize - PNOR size, in bytes
91 */
92 Table(size_t blockSize,
93 size_t pnorSize);
94
Deepak Kodihalli393821d2017-04-28 04:44:38 -050095 Table(const Table&) = delete;
96 Table& operator=(const Table&) = delete;
97 Table(Table&&) = delete;
98 Table& operator=(Table&&) = delete;
99 ~Table() = default;
100
101 /** @brief Return size of partition table
102 *
103 * @returns size_t - size of partition table in blocks
104 */
105 size_t size() const
106 {
107 return szBlocks;
108 }
109
110 /** @brief Return a partition table having byte-ordering
111 * that the host expects.
112 *
113 * The host needs the partion table in big-endian.
114 *
115 * @returns const reference to host partition table.
116 */
117 const pnor_partition_table& getHostTable() const
118 {
119 return *(reinterpret_cast<
120 const pnor_partition_table*>(hostTbl.data()));
121 }
122
123 /** @brief Return a little-endian partition table
124 *
125 * @returns const reference to native partition table
126 */
127 const pnor_partition_table& getNativeTable() const
128 {
129 return *(reinterpret_cast<const pnor_partition_table*>(tbl.data()));
130 }
131
132 /** @brief Return partition corresponding to PNOR offset, the offset
133 * is within returned partition.
134 *
135 * @param[in] offset - PNOR offset in bytes
136 *
137 * @returns const reference to pnor_partition, if found, else a
138 * reference to a zeroed out pnor_partition structure.
139 */
140 const pnor_partition& partition(size_t offset) const;
141
Deepak Kodihalli8a899692017-07-11 23:17:19 -0500142 /** @brief Return partition corresponding to input partition name.
143 *
144 * @param[in] name - PNOR partition name
145 *
146 * @returns const reference to pnor_partition, if found, else an
147 * exception will be thrown.
148 */
149 const pnor_partition& partition(const std::string& name) const;
150
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500151 private:
152 /** @brief Prepares a vector of PNOR partition structures.
153 */
154 void preparePartitions();
155
156 /** @brief Prepares the PNOR header.
157 */
158 void prepareHeader();
159
160 /** @brief Allocate memory to hold the partion table. Determine the
161 * amount needed based on the partition files in the toc file.
162 *
163 * @param[in] tocFile - Table of contents file path.
164 */
165 void allocateMemory(const fs::path& tocFile);
166
167 /** @brief Populate fields related to sizes for the input
168 * pnor_partition structure.
169 *
170 * @param[in/out] part - pnor_partition structure
171 * @param[in] start - partition start address
172 * @param[in] end - partition end address
173 */
174 void writeSizes(pnor_partition& part, size_t start, size_t end);
175
176 /** @brief Populate userdata bits for the input
177 * pnor_partition structure.
178 *
179 * @param[in/out] part - pnor_partition structure
180 * @param[in] data - string having userdata fields in a
181 * comma-separated line.
182 */
183 void writeUserdata(pnor_partition& part, const std::string& data);
184
185 /** @brief Populate the name and id fields for the input
186 * pnor_partition structure.
187 *
188 * @param[in/out] part - pnor_partition structure
189 * @param[in] name - partition name
190 * @param[id] id - partition id
191 */
192 void writeNameAndId(pnor_partition& part, std::string&& name,
193 const std::string& id);
194
195 /** @brief Populate default/unused fields for the input
196 * pnor_partition structure.
197 *
198 * @param[in/out] part - pnor_partition structure
199 */
200 void writeDefaults(pnor_partition& part);
201
202 /** @brief Return a little-endian partition table
203 *
204 * @returns reference to native partition table
205 */
206 pnor_partition_table& getNativeTable()
207 {
208 return *(reinterpret_cast<pnor_partition_table*>(tbl.data()));
209 }
210
211 /** @brief Size of the PNOR partition table -
212 * sizeof(pnor_partition_table) +
213 * (no. of partitions * sizeof(pnor_partition)),
214 * measured in erase-blocks.
215 */
216 size_t szBlocks;
217
218 /** @brief Size of virtual PNOR image, measured in erase-blocks */
219 size_t imgBlocks;
220
221 /** @brief Partition table */
222 PartitionTable tbl;
223
224 /** @brief Partition table with host byte ordering */
225 PartitionTable hostTbl;
226
227 /** @brief Directory housing generated PNOR partition files */
228 fs::path directory;
229
230 /** @brief Number of partitions */
231 size_t numParts;
Deepak Kodihallid1d79302017-07-11 23:01:39 -0500232
233 /** @brief PNOR block size, in bytes */
234 size_t blockSize;
235
236 /** @brief PNOR size, in bytes */
237 size_t pnorSize;
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500238};
239
240} // namespace partition
241} // namespace virtual_pnor
242} // namespace openpower