blob: d3d7fa48025f4ebe35fcc96ceb561bc87321e099 [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:
147 /** @brief Prepares a vector of PNOR partition structures.
148 */
149 void preparePartitions();
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500150
Andrew Jefferyf34db312018-03-09 15:27:03 +1030151 /** @brief Prepares the PNOR header.
152 */
153 void prepareHeader();
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500154
Andrew Jefferyf34db312018-03-09 15:27:03 +1030155 /** @brief Allocate memory to hold the partion table. Determine the
156 * amount needed based on the partition files in the toc file.
157 *
158 * @param[in] tocFile - Table of contents file path.
159 */
160 void allocateMemory(const fs::path& tocFile);
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500161
Andrew Jefferyf34db312018-03-09 15:27:03 +1030162 /** @brief Populate fields related to sizes for the input
163 * pnor_partition structure.
164 *
165 * @param[in/out] part - pnor_partition structure
166 * @param[in] start - partition start address
167 * @param[in] end - partition end address
168 */
169 void writeSizes(pnor_partition& part, size_t start, size_t end);
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500170
Andrew Jefferyf34db312018-03-09 15:27:03 +1030171 /** @brief Populate userdata bits for the input
172 * pnor_partition structure.
173 *
174 * @param[in/out] part - pnor_partition structure
175 * @param[in] version - partition version check algorithm to be used
176 * (see pnor_partition_defs.h)
177 * @param[in] data - string having userdata fields in a
178 * comma-separated line.
179 */
180 void writeUserdata(pnor_partition& part, uint32_t version,
181 const std::string& data);
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500182
Andrew Jefferyf34db312018-03-09 15:27:03 +1030183 /** @brief Populate the name and id fields for the input
184 * pnor_partition structure.
185 *
186 * @param[in/out] part - pnor_partition structure
187 * @param[in] name - partition name
188 * @param[id] id - partition id
189 */
190 void writeNameAndId(pnor_partition& part, std::string&& name,
191 const std::string& id);
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500192
Andrew Jefferyf34db312018-03-09 15:27:03 +1030193 /** @brief Populate default/unused fields for the input
194 * pnor_partition structure.
195 *
196 * @param[in/out] part - pnor_partition structure
197 */
198 void writeDefaults(pnor_partition& part);
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500199
Andrew Jefferyf34db312018-03-09 15:27:03 +1030200 /** @brief Return a little-endian partition table
201 *
202 * @returns reference to native partition table
203 */
204 pnor_partition_table& getNativeTable()
205 {
206 return *(reinterpret_cast<pnor_partition_table*>(tbl.data()));
207 }
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500208
Andrew Jefferyf34db312018-03-09 15:27:03 +1030209 /** @brief Size of the PNOR partition table -
210 * sizeof(pnor_partition_table) +
211 * (no. of partitions * sizeof(pnor_partition)),
212 * measured in erase-blocks.
213 */
214 size_t szBlocks;
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500215
Andrew Jefferyf34db312018-03-09 15:27:03 +1030216 /** @brief Partition table */
217 PartitionTable tbl;
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500218
Andrew Jefferyf34db312018-03-09 15:27:03 +1030219 /** @brief Partition table with host byte ordering */
220 PartitionTable hostTbl;
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500221
Andrew Jefferyf34db312018-03-09 15:27:03 +1030222 /** @brief Directory housing generated PNOR partition files */
223 fs::path directory;
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500224
Andrew Jefferyf34db312018-03-09 15:27:03 +1030225 /** @brief Number of partitions */
226 size_t numParts;
Deepak Kodihallid1d79302017-07-11 23:01:39 -0500227
Andrew Jefferyf34db312018-03-09 15:27:03 +1030228 /** @brief PNOR block size, in bytes */
229 size_t blockSize;
Deepak Kodihallid1d79302017-07-11 23:01:39 -0500230
Andrew Jefferyf34db312018-03-09 15:27:03 +1030231 /** @brief PNOR size, in bytes */
232 size_t pnorSize;
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500233};
234
235} // namespace partition
236} // namespace virtual_pnor
237} // namespace openpower