blob: a333b5f0db22ed41509541bf3004d3e77d1f36ab [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 *
Andrew Jeffery581a4f22018-02-21 15:29:38 +1030150 * @param[in] line - The ToC line to parse
151 * @param[out] part - The partition object to populate with the information
152 * parsed from the provided ToC line
153 *
154 * @returns True on success, false on failure.
155 */
Andrew Jefferyfaaa71c2018-02-21 16:29:48 +1030156 bool parseTocLine(const std::string& line, pnor_partition& part);
Andrew Jeffery581a4f22018-02-21 15:29:38 +1030157
Andrew Jefferyf34db312018-03-09 15:27:03 +1030158 /** @brief Prepares a vector of PNOR partition structures.
159 */
160 void preparePartitions();
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500161
Andrew Jefferyf34db312018-03-09 15:27:03 +1030162 /** @brief Prepares the PNOR header.
163 */
164 void prepareHeader();
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500165
Andrew Jefferyf34db312018-03-09 15:27:03 +1030166 /** @brief Allocate memory to hold the partion table. Determine the
167 * amount needed based on the partition files in the toc file.
168 *
169 * @param[in] tocFile - Table of contents file path.
170 */
171 void allocateMemory(const fs::path& tocFile);
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500172
Andrew Jefferyf34db312018-03-09 15:27:03 +1030173 /** @brief Populate fields related to sizes for the input
174 * pnor_partition structure.
175 *
176 * @param[in/out] part - pnor_partition structure
177 * @param[in] start - partition start address
178 * @param[in] end - partition end address
179 */
180 void writeSizes(pnor_partition& part, size_t start, size_t end);
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500181
Andrew Jefferyf34db312018-03-09 15:27:03 +1030182 /** @brief Return a little-endian partition table
183 *
184 * @returns reference to native partition table
185 */
186 pnor_partition_table& getNativeTable()
187 {
188 return *(reinterpret_cast<pnor_partition_table*>(tbl.data()));
189 }
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500190
Andrew Jefferyf34db312018-03-09 15:27:03 +1030191 /** @brief Size of the PNOR partition table -
192 * sizeof(pnor_partition_table) +
193 * (no. of partitions * sizeof(pnor_partition)),
194 * measured in erase-blocks.
195 */
196 size_t szBlocks;
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500197
Andrew Jefferyf34db312018-03-09 15:27:03 +1030198 /** @brief Partition table */
199 PartitionTable tbl;
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500200
Andrew Jefferyf34db312018-03-09 15:27:03 +1030201 /** @brief Partition table with host byte ordering */
202 PartitionTable hostTbl;
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500203
Andrew Jefferyf34db312018-03-09 15:27:03 +1030204 /** @brief Directory housing generated PNOR partition files */
205 fs::path directory;
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500206
Andrew Jefferyf34db312018-03-09 15:27:03 +1030207 /** @brief Number of partitions */
208 size_t numParts;
Deepak Kodihallid1d79302017-07-11 23:01:39 -0500209
Andrew Jefferyf34db312018-03-09 15:27:03 +1030210 /** @brief PNOR block size, in bytes */
211 size_t blockSize;
Deepak Kodihallid1d79302017-07-11 23:01:39 -0500212
Andrew Jefferyf34db312018-03-09 15:27:03 +1030213 /** @brief PNOR size, in bytes */
214 size_t pnorSize;
Deepak Kodihalli393821d2017-04-28 04:44:38 -0500215};
216
217} // namespace partition
218} // namespace virtual_pnor
219} // namespace openpower