blob: 6e9d2fa433eec9a2f036201742e268a765305cd2 [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 */
Andrew Jefferyf34db312018-03-09 15:27:03 +103037template <class T> checksum_t checksum(const T& data)
Deepak Kodihalli393821d2017-04-28 04:44:38 -050038{
39 static_assert(sizeof(decltype(data)) % sizeof(checksum_t) == 0,
40 "sizeof(data) is not aligned to sizeof(checksum_t) boundary");
41
42 auto begin = reinterpret_cast<const checksum_t*>(&data);
43 auto end = begin + (sizeof(decltype(data)) / sizeof(checksum_t));
44
45 return std::accumulate(begin, end, 0, std::bit_xor<checksum_t>());
46}
47
48} // namespace details
49
50namespace partition
51{
52
53/** @class Table
54 * @brief Generates virtual PNOR partition table.
55 *
56 * Generates virtual PNOR partition table upon construction. Reads
57 * the PNOR information generated by this tool :
58 * github.com/openbmc/openpower-pnor-code-mgmt/blob/master/generate-squashfs,
59 * which generates a minimalistic table-of-contents (toc) file and
60 * individual files to represent various partitions that are of interest -
61 * these help form the "virtual" PNOR, which is typically a subset of the full
62 * PNOR image.
63 * These files are stored in a well-known location on the PNOR.
64 * Based on this information, this class prepares the partition table whose
65 * structure is as outlined in pnor_partition.h.
66 *
67 * The virtual PNOR supports 4KB erase blocks - partitions must be aligned to
68 * this size.
69 */
70class Table
71{
Andrew Jefferyf34db312018-03-09 15:27:03 +103072 public:
73 /** @brief Constructor accepting the path of the directory
74 * that houses the PNOR partition files.
75 *
76 * @param[in] directory - path of the directory housing PNOR partitions
77 * @param[in] blockSize - PNOR block size, in bytes. See
78 * open-power/hostboot/blob/master/src/usr/pnor/ffs.h for
79 * the PNOR FFS structure.
80 * @param[in] pnorSize - PNOR size, in bytes
81 */
82 Table(fs::path&& directory, size_t blockSize, size_t pnorSize);
Deepak Kodihalli393821d2017-04-28 04:44:38 -050083
Andrew Jefferyf34db312018-03-09 15:27:03 +103084 /** @brief Constructor - creates partition table
85 *
86 * @param[in] blockSize - PNOR block size, in bytes
87 * @param[in] pnorSize - PNOR size, in bytes
88 */
89 Table(size_t blockSize, size_t pnorSize);
Deepak Kodihallid1d79302017-07-11 23:01:39 -050090
Andrew Jefferyf34db312018-03-09 15:27:03 +103091 Table(const Table&) = delete;
92 Table& operator=(const Table&) = delete;
93 Table(Table&&) = delete;
94 Table& operator=(Table&&) = delete;
95 ~Table() = default;
Deepak Kodihalli393821d2017-04-28 04:44:38 -050096
Andrew Jefferyf34db312018-03-09 15:27:03 +103097 /** @brief Return size of partition table
98 *
99 * @returns size_t - size of partition table in blocks
100 */
101 size_t size() const
102 {
103 return szBlocks;
104 }
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500105
Andrew Jefferyf34db312018-03-09 15:27:03 +1030106 /** @brief Return a partition table having byte-ordering
107 * that the host expects.
108 *
109 * The host needs the partion table in big-endian.
110 *
111 * @returns const reference to host partition table.
112 */
113 const pnor_partition_table& getHostTable() const
114 {
115 return *(reinterpret_cast<const pnor_partition_table*>(hostTbl.data()));
116 }
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500117
Andrew Jefferyf34db312018-03-09 15:27:03 +1030118 /** @brief Return a little-endian partition table
119 *
120 * @returns const reference to native partition table
121 */
122 const pnor_partition_table& getNativeTable() const
123 {
124 return *(reinterpret_cast<const pnor_partition_table*>(tbl.data()));
125 }
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500126
Andrew Jefferyf34db312018-03-09 15:27:03 +1030127 /** @brief Return partition corresponding to PNOR offset, the offset
128 * is within returned partition.
129 *
130 * @param[in] offset - PNOR offset in bytes
131 *
132 * @returns const reference to pnor_partition, if found, else an
133 * exception will be thrown.
134 */
135 const pnor_partition& partition(size_t offset) const;
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500136
Andrew Jefferyf34db312018-03-09 15:27:03 +1030137 /** @brief Return partition corresponding to input partition name.
138 *
139 * @param[in] name - PNOR partition name
140 *
141 * @returns const reference to pnor_partition, if found, else an
142 * exception will be thrown.
143 */
144 const pnor_partition& partition(const std::string& name) const;
Deepak Kodihalli8a899692017-07-11 23:17:19 -0500145
Andrew Jefferyf34db312018-03-09 15:27:03 +1030146 private:
Andrew Jeffery581a4f22018-02-21 15:29:38 +1030147 /** @brief Parse a ToC line (entry) into the corresponding FFS partition
148 * object.
149 *
150 * @param[in] dir - The parent directory of the FFS partition files
151 * described in the ToC.
152 * @param[in] line - The ToC line to parse
153 * @param[out] part - The partition object to populate with the information
154 * parsed from the provided ToC line
155 *
156 * @returns True on success, false on failure.
157 */
158 bool parseTocLine(fs::path& dir, const std::string& line,
159 pnor_partition& part);
160
Andrew Jefferyf34db312018-03-09 15:27:03 +1030161 /** @brief Prepares a vector of PNOR partition structures.
162 */
163 void preparePartitions();
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500164
Andrew Jefferyf34db312018-03-09 15:27:03 +1030165 /** @brief Prepares the PNOR header.
166 */
167 void prepareHeader();
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500168
Andrew Jefferyf34db312018-03-09 15:27:03 +1030169 /** @brief Allocate memory to hold the partion table. Determine the
170 * amount needed based on the partition files in the toc file.
171 *
172 * @param[in] tocFile - Table of contents file path.
173 */
174 void allocateMemory(const fs::path& tocFile);
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500175
Andrew Jefferyf34db312018-03-09 15:27:03 +1030176 /** @brief Populate fields related to sizes for the input
177 * pnor_partition structure.
178 *
179 * @param[in/out] part - pnor_partition structure
180 * @param[in] start - partition start address
181 * @param[in] end - partition end address
182 */
183 void writeSizes(pnor_partition& part, size_t start, size_t end);
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500184
Andrew Jefferyf34db312018-03-09 15:27:03 +1030185 /** @brief Populate userdata bits for the input
186 * pnor_partition structure.
187 *
188 * @param[in/out] part - pnor_partition structure
189 * @param[in] version - partition version check algorithm to be used
190 * (see pnor_partition_defs.h)
191 * @param[in] data - string having userdata fields in a
192 * comma-separated line.
193 */
194 void writeUserdata(pnor_partition& part, uint32_t version,
195 const std::string& data);
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500196
Andrew Jefferyf34db312018-03-09 15:27:03 +1030197 /** @brief Populate the name and id fields for the input
198 * pnor_partition structure.
199 *
200 * @param[in/out] part - pnor_partition structure
201 * @param[in] name - partition name
202 * @param[id] id - partition id
203 */
204 void writeNameAndId(pnor_partition& part, std::string&& name,
205 const std::string& id);
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500206
Andrew Jefferyf34db312018-03-09 15:27:03 +1030207 /** @brief Populate default/unused fields for the input
208 * pnor_partition structure.
209 *
210 * @param[in/out] part - pnor_partition structure
211 */
212 void writeDefaults(pnor_partition& part);
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500213
Andrew Jefferyf34db312018-03-09 15:27:03 +1030214 /** @brief Return a little-endian partition table
215 *
216 * @returns reference to native partition table
217 */
218 pnor_partition_table& getNativeTable()
219 {
220 return *(reinterpret_cast<pnor_partition_table*>(tbl.data()));
221 }
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500222
Andrew Jefferyf34db312018-03-09 15:27:03 +1030223 /** @brief Size of the PNOR partition table -
224 * sizeof(pnor_partition_table) +
225 * (no. of partitions * sizeof(pnor_partition)),
226 * measured in erase-blocks.
227 */
228 size_t szBlocks;
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500229
Andrew Jefferyf34db312018-03-09 15:27:03 +1030230 /** @brief Partition table */
231 PartitionTable tbl;
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500232
Andrew Jefferyf34db312018-03-09 15:27:03 +1030233 /** @brief Partition table with host byte ordering */
234 PartitionTable hostTbl;
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500235
Andrew Jefferyf34db312018-03-09 15:27:03 +1030236 /** @brief Directory housing generated PNOR partition files */
237 fs::path directory;
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500238
Andrew Jefferyf34db312018-03-09 15:27:03 +1030239 /** @brief Number of partitions */
240 size_t numParts;
Deepak Kodihallid1d79302017-07-11 23:01:39 -0500241
Andrew Jefferyf34db312018-03-09 15:27:03 +1030242 /** @brief PNOR block size, in bytes */
243 size_t blockSize;
Deepak Kodihallid1d79302017-07-11 23:01:39 -0500244
Andrew Jefferyf34db312018-03-09 15:27:03 +1030245 /** @brief PNOR size, in bytes */
246 size_t pnorSize;
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500247};
248
249} // namespace partition
250} // namespace virtual_pnor
251} // namespace openpower