blob: 02abc34aa851958ccff13e1624a2c6180ac863db [file] [log] [blame]
Brad Bishope45d8c72022-05-25 15:12:53 -04001#include "fru_utils.hpp"
Patrick Venturea62466c2021-02-08 14:55:18 -08002
Andrew Jefferyf8ae2ba2022-03-25 15:13:55 +10303#include <algorithm>
Patrick Venturea62466c2021-02-08 14:55:18 -08004#include <array>
Andrew Jefferyf8ae2ba2022-03-25 15:13:55 +10305#include <iterator>
Patrick Venturea62466c2021-02-08 14:55:18 -08006
7#include "gtest/gtest.h"
8
9extern "C"
10{
11// Include for I2C_SMBUS_BLOCK_MAX
12#include <linux/i2c.h>
13}
14
Zev Weiss309c0b12022-02-25 01:44:12 +000015static constexpr size_t blockSize = I2C_SMBUS_BLOCK_MAX;
16
Patrick Venturea62466c2021-02-08 14:55:18 -080017TEST(ValidateHeaderTest, InvalidFruVersionReturnsFalse)
18{
19 // Validates the FruVersion is checked for the only legal value.
Ed Tanous07d467b2021-02-23 14:48:37 -080020 constexpr std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> fruHeader = {
Patrick Venturea62466c2021-02-08 14:55:18 -080021 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
22
Ed Tanous07d467b2021-02-23 14:48:37 -080023 EXPECT_FALSE(validateHeader(fruHeader));
Patrick Venturea62466c2021-02-08 14:55:18 -080024}
Vijay Khemka1694ef62021-02-12 23:14:49 +000025
Vijay Khemka7a682a32021-04-12 22:15:00 +000026TEST(ValidateHeaderTest, InvalidReservedReturnsFalse)
27{
28 // Validates the reserved bit(7:4) of first bytes.
Ed Tanous07d467b2021-02-23 14:48:37 -080029 constexpr std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> fruHeader = {
Vijay Khemka7a682a32021-04-12 22:15:00 +000030 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
31
Ed Tanous07d467b2021-02-23 14:48:37 -080032 EXPECT_FALSE(validateHeader(fruHeader));
Vijay Khemka7a682a32021-04-12 22:15:00 +000033}
34
35TEST(ValidateHeaderTest, InvalidPaddingReturnsFalse)
36{
37 // Validates the padding byte (7th byte).
Ed Tanous07d467b2021-02-23 14:48:37 -080038 constexpr std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> fruHeader = {
Vijay Khemka7a682a32021-04-12 22:15:00 +000039 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00};
40
Ed Tanous07d467b2021-02-23 14:48:37 -080041 EXPECT_FALSE(validateHeader(fruHeader));
Vijay Khemka7a682a32021-04-12 22:15:00 +000042}
43
44TEST(ValidateHeaderTest, InvalidChecksumReturnsFalse)
45{
46 // Validates the checksum, check for incorrect value.
Ed Tanous07d467b2021-02-23 14:48:37 -080047 constexpr std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> fruHeader = {
Vijay Khemka7a682a32021-04-12 22:15:00 +000048 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x00, 0x00};
49
Ed Tanous07d467b2021-02-23 14:48:37 -080050 EXPECT_FALSE(validateHeader(fruHeader));
Vijay Khemka7a682a32021-04-12 22:15:00 +000051}
52
53TEST(ValidateHeaderTest, ValidChecksumReturnsTrue)
54{
55 // Validates the checksum, check for correct value.
Ed Tanous07d467b2021-02-23 14:48:37 -080056 constexpr std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> fruHeader = {
Vijay Khemka7a682a32021-04-12 22:15:00 +000057 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x00, 0xf5};
58
Ed Tanous07d467b2021-02-23 14:48:37 -080059 EXPECT_TRUE(validateHeader(fruHeader));
Vijay Khemka7a682a32021-04-12 22:15:00 +000060}
61
Vijay Khemka1694ef62021-02-12 23:14:49 +000062TEST(VerifyOffsetTest, EmptyFruDataReturnsFalse)
63{
64 // Validates the FruData size is checked for non empty.
Ed Tanous07d467b2021-02-23 14:48:37 -080065 std::vector<uint8_t> fruData = {};
Vijay Khemka1694ef62021-02-12 23:14:49 +000066
Ed Tanous07d467b2021-02-23 14:48:37 -080067 EXPECT_FALSE(verifyOffset(fruData, fruAreas::fruAreaChassis, 0));
Vijay Khemka1694ef62021-02-12 23:14:49 +000068}
69
70TEST(VerifyOffsetTest, AreaOutOfRangeReturnsFalse)
71{
72 // Validates the FruArea value, check if it is within range.
Ed Tanous07d467b2021-02-23 14:48:37 -080073 const std::vector<uint8_t> fruData = {0x01, 0x00, 0x00, 0x00, 0x00,
74 0x00, 0x00, 0x00, 0x00};
Vijay Khemka1694ef62021-02-12 23:14:49 +000075
76 unsigned int areaOutOfRange = 8;
77 EXPECT_FALSE(
Ed Tanous07d467b2021-02-23 14:48:37 -080078 verifyOffset(fruData, static_cast<fruAreas>(areaOutOfRange), 0));
Vijay Khemka1694ef62021-02-12 23:14:49 +000079}
80
81TEST(VerifyOffsetTest, OverlapNextAreaReturnsFalse)
82{
83 // Validates the Overlap of offsets with overlapped values.
Ed Tanous07d467b2021-02-23 14:48:37 -080084 const std::vector<uint8_t> fruData = {0x01, 0x00, 0x01, 0x02, 0x03,
85 0x04, 0x00, 0x00, 0x00};
Vijay Khemka1694ef62021-02-12 23:14:49 +000086
Ed Tanous07d467b2021-02-23 14:48:37 -080087 EXPECT_FALSE(verifyOffset(fruData, fruAreas::fruAreaChassis, 2));
Vijay Khemka1694ef62021-02-12 23:14:49 +000088}
89
90TEST(VerifyOffsetTest, OverlapPrevAreaReturnsFalse)
91{
92 // Validates the Overlap of offsets with overlapped values.
Ed Tanous07d467b2021-02-23 14:48:37 -080093 const std::vector<uint8_t> fruData = {0x01, 0x00, 0x01, 0x03, 0x02,
94 0x07, 0x00, 0x00, 0x00};
Vijay Khemka1694ef62021-02-12 23:14:49 +000095
Ed Tanous07d467b2021-02-23 14:48:37 -080096 EXPECT_FALSE(verifyOffset(fruData, fruAreas::fruAreaProduct, 2));
Vijay Khemka1694ef62021-02-12 23:14:49 +000097}
98
99TEST(VerifyOffsetTest, ValidInputDataNoOverlapReturnsTrue)
100{
101 // Validates all inputs with expected value and no overlap.
Ed Tanous07d467b2021-02-23 14:48:37 -0800102 const std::vector<uint8_t> fruData = {0x01, 0x00, 0x01, 0x02, 0x03,
103 0x04, 0x00, 0x00, 0x00};
Vijay Khemka1694ef62021-02-12 23:14:49 +0000104
Ed Tanous07d467b2021-02-23 14:48:37 -0800105 EXPECT_TRUE(verifyOffset(fruData, fruAreas::fruAreaChassis, 1));
Vijay Khemka1694ef62021-02-12 23:14:49 +0000106}
Andrew Jeffery8dacf6a2021-08-02 22:17:18 +0930107
108TEST(VerifyChecksumTest, EmptyInput)
109{
110 std::vector<uint8_t> data = {};
111
112 EXPECT_EQ(calculateChecksum(data), 0);
113}
114
115TEST(VerifyChecksumTest, SingleOneInput)
116{
117 std::vector<uint8_t> data(1, 1);
118
119 EXPECT_EQ(calculateChecksum(data), 255);
120}
121
122TEST(VerifyChecksumTest, AllOneInput)
123{
124 std::vector<uint8_t> data(256, 1);
125
126 EXPECT_EQ(calculateChecksum(data), 0);
127}
128
129TEST(VerifyChecksumTest, WrapBoundaryLow)
130{
Ed Tanousfbce8e22021-09-02 15:29:12 -0700131 std::vector<uint8_t> data = {255, 0};
Andrew Jeffery8dacf6a2021-08-02 22:17:18 +0930132
133 EXPECT_EQ(calculateChecksum(data), 1);
134}
135
136TEST(VerifyChecksumTest, WrapBoundaryExact)
137{
Ed Tanousfbce8e22021-09-02 15:29:12 -0700138 std::vector<uint8_t> data = {255, 1};
Andrew Jeffery8dacf6a2021-08-02 22:17:18 +0930139
140 EXPECT_EQ(calculateChecksum(data), 0);
141}
142
143TEST(VerifyChecksumTest, WrapBoundaryHigh)
144{
Ed Tanousfbce8e22021-09-02 15:29:12 -0700145 std::vector<uint8_t> data = {255, 2};
Andrew Jeffery8dacf6a2021-08-02 22:17:18 +0930146
147 EXPECT_EQ(calculateChecksum(data), 255);
148}
Oskar Senftbd4075f2021-10-05 23:42:43 -0400149
Zev Weiss309c0b12022-02-25 01:44:12 +0000150int64_t getDataTempl(const std::vector<uint8_t>& data, off_t offset,
Zev Weiss1525e852022-03-22 22:27:43 +0000151 size_t length, uint8_t* outBuf)
Oskar Senftbd4075f2021-10-05 23:42:43 -0400152{
Zev Weiss1525e852022-03-22 22:27:43 +0000153 if (offset >= static_cast<off_t>(data.size()))
Oskar Senftbd4075f2021-10-05 23:42:43 -0400154 {
155 return 0;
156 }
157
158 uint16_t idx;
Andrew Jefferyf8ae2ba2022-03-25 15:13:55 +1030159 for (idx = offset; idx < data.size() && idx < offset + length;
Oskar Senftbd4075f2021-10-05 23:42:43 -0400160 ++idx, ++outBuf)
161 {
162 *outBuf = data[idx];
163 }
164
165 return idx - offset;
166}
167
Zev Weiss309c0b12022-02-25 01:44:12 +0000168TEST(FRUReaderTest, ReadData)
169{
170 std::vector<uint8_t> data = {};
171 for (size_t i = 0; i < blockSize * 2; i++)
172 {
173 data.push_back(i);
174 }
175 std::array<uint8_t, blockSize * 2> rdbuf;
176 auto getData = [&data](auto o, auto l, auto* b) {
177 return getDataTempl(data, o, l, b);
178 };
179 FRUReader reader(getData);
180
181 EXPECT_EQ(reader.read(0, data.size(), rdbuf.data()),
182 static_cast<ssize_t>(data.size()));
183 EXPECT_TRUE(std::equal(rdbuf.begin(), rdbuf.end(), data.begin()));
184 for (size_t i = 0; i < blockSize * 2; i++)
185 {
186 EXPECT_EQ(reader.read(i, 1, rdbuf.data()), 1);
187 EXPECT_EQ(rdbuf[i], i);
188 }
189 EXPECT_EQ(reader.read(blockSize - 1, 2, rdbuf.data()), 2);
190 EXPECT_EQ(rdbuf[0], blockSize - 1);
191 EXPECT_EQ(rdbuf[1], blockSize);
192}
193
194TEST(FRUReaderTest, StartPastUnknownEOF)
195{
196 const std::vector<uint8_t> data = {};
197 auto getData = [&data](auto o, auto l, auto* b) {
198 return getDataTempl(data, o, l, b);
199 };
200 FRUReader reader(getData);
201
202 EXPECT_EQ(reader.read(1, 1, nullptr), 0);
203}
204
205TEST(FRUReaderTest, StartPastKnownEOF)
206{
207 std::vector<uint8_t> data = {};
208 data.resize(blockSize / 2);
209 std::array<uint8_t, blockSize> blockData;
210 auto getData = [&data](auto o, auto l, auto* b) {
211 return getDataTempl(data, o, l, b);
212 };
213 FRUReader reader(getData);
214
215 EXPECT_EQ(reader.read(0, blockSize, blockData.data()),
216 static_cast<ssize_t>(data.size()));
217 EXPECT_EQ(reader.read(data.size(), 1, nullptr), 0);
218 EXPECT_EQ(reader.read(data.size() + 1, 1, nullptr), 0);
219 EXPECT_EQ(reader.read(blockSize, 1, nullptr), 0);
220 EXPECT_EQ(reader.read(blockSize + 1, 1, nullptr), 0);
221}
222
223TEST(FRUReaderTest, DecreasingEOF)
224{
225 const std::vector<uint8_t> data = {};
226 auto getData = [&data](auto o, auto l, auto* b) {
227 return getDataTempl(data, o, l, b);
228 };
229 FRUReader reader(getData);
230
231 EXPECT_EQ(reader.read(blockSize * 2, 1, nullptr), 0);
232 EXPECT_EQ(reader.read(blockSize + (blockSize / 2), 1, nullptr), 0);
233 EXPECT_EQ(reader.read(blockSize, 1, nullptr), 0);
234 EXPECT_EQ(reader.read(blockSize / 2, 1, nullptr), 0);
235 EXPECT_EQ(reader.read(0, 1, nullptr), 0);
236}
237
238TEST(FRUReaderTest, CacheHit)
239{
240 std::vector<uint8_t> data = {'X'};
241 std::array<uint8_t, blockSize> read1, read2;
242 auto getData = [&data](auto o, auto l, auto* b) {
243 return getDataTempl(data, o, l, b);
244 };
245 FRUReader reader(getData);
246
247 // cache hit should return the same data for the second read even if we
248 // change it behind the FRUReader's back after the first
249 EXPECT_EQ(reader.read(0, blockSize, read1.data()), 1);
250 data[0] = 'Y';
251 EXPECT_EQ(reader.read(0, blockSize, read2.data()), 1);
252 EXPECT_EQ(read1[0], read2[0]);
253}
254
255TEST(FRUReaderTest, ReadPastKnownEnd)
256{
257 const std::vector<uint8_t> data = {'X', 'Y'};
258 std::array<uint8_t, blockSize> rdbuf;
259 auto getData = [&data](auto o, auto l, auto* b) {
260 return getDataTempl(data, o, l, b);
261 };
262 FRUReader reader(getData);
263
264 EXPECT_EQ(reader.read(0, data.size(), rdbuf.data()),
265 static_cast<ssize_t>(data.size()));
266 EXPECT_EQ(rdbuf[0], 'X');
267 EXPECT_EQ(rdbuf[1], 'Y');
268 EXPECT_EQ(reader.read(1, data.size(), rdbuf.data()),
269 static_cast<ssize_t>(data.size() - 1));
270 EXPECT_EQ(rdbuf[0], 'Y');
271}
272
273TEST(FRUReaderTest, MultiBlockRead)
274{
275 std::vector<uint8_t> data = {};
276 data.resize(blockSize, 'X');
277 data.resize(2 * blockSize, 'Y');
278 std::array<uint8_t, 2 * blockSize> rdbuf;
279 auto getData = [&data](auto o, auto l, auto* b) {
280 return getDataTempl(data, o, l, b);
281 };
282 FRUReader reader(getData);
283
284 EXPECT_EQ(reader.read(0, 2 * blockSize, rdbuf.data()),
285 static_cast<ssize_t>(2 * blockSize));
286 EXPECT_TRUE(std::equal(rdbuf.begin(), rdbuf.end(), data.begin()));
287}
288
289TEST(FRUReaderTest, ShrinkingEEPROM)
290{
291 std::vector<uint8_t> data = {};
292 data.resize(3 * blockSize, 'X');
293 std::array<uint8_t, blockSize> rdbuf;
294 auto getData = [&data](auto o, auto l, auto* b) {
295 return getDataTempl(data, o, l, b);
296 };
297 FRUReader reader(getData);
298
299 EXPECT_EQ(reader.read(data.size() - 1, 2, rdbuf.data()), 1);
300 data.resize(blockSize);
301 EXPECT_EQ(reader.read(data.size() - 1, 2, rdbuf.data()), 1);
302}
303
Oskar Senftbd4075f2021-10-05 23:42:43 -0400304TEST(FindFRUHeaderTest, InvalidHeader)
305{
306 const std::vector<uint8_t> data = {255, 16};
Zev Weiss1525e852022-03-22 22:27:43 +0000307 off_t offset = 0;
Oskar Senftbd4075f2021-10-05 23:42:43 -0400308 std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> blockData;
Zev Weiss309c0b12022-02-25 01:44:12 +0000309 auto getData = [&data](auto o, auto l, auto* b) {
310 return getDataTempl(data, o, l, b);
Andrew Jefferyf8ae2ba2022-03-25 15:13:55 +1030311 };
Zev Weiss309c0b12022-02-25 01:44:12 +0000312 FRUReader reader(getData);
Oskar Senftbd4075f2021-10-05 23:42:43 -0400313
Zev Weiss309c0b12022-02-25 01:44:12 +0000314 EXPECT_FALSE(findFRUHeader(reader, "error", blockData, offset));
Oskar Senftbd4075f2021-10-05 23:42:43 -0400315}
316
317TEST(FindFRUHeaderTest, NoData)
318{
319 const std::vector<uint8_t> data = {};
Zev Weiss1525e852022-03-22 22:27:43 +0000320 off_t offset = 0;
Oskar Senftbd4075f2021-10-05 23:42:43 -0400321 std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> blockData;
Zev Weiss309c0b12022-02-25 01:44:12 +0000322 auto getData = [&data](auto o, auto l, auto* b) {
323 return getDataTempl(data, o, l, b);
Andrew Jefferyf8ae2ba2022-03-25 15:13:55 +1030324 };
Zev Weiss309c0b12022-02-25 01:44:12 +0000325 FRUReader reader(getData);
Oskar Senftbd4075f2021-10-05 23:42:43 -0400326
Zev Weiss309c0b12022-02-25 01:44:12 +0000327 EXPECT_FALSE(findFRUHeader(reader, "error", blockData, offset));
Oskar Senftbd4075f2021-10-05 23:42:43 -0400328}
329
330TEST(FindFRUHeaderTest, ValidHeader)
331{
Andrew Jefferyf8ae2ba2022-03-25 15:13:55 +1030332 const std::vector<uint8_t> data = {0x01, 0x00, 0x01, 0x02,
333 0x03, 0x04, 0x00, 0xf5};
Zev Weiss1525e852022-03-22 22:27:43 +0000334 off_t offset = 0;
Oskar Senftbd4075f2021-10-05 23:42:43 -0400335 std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> blockData;
Zev Weiss309c0b12022-02-25 01:44:12 +0000336 auto getData = [&data](auto o, auto l, auto* b) {
337 return getDataTempl(data, o, l, b);
Andrew Jefferyf8ae2ba2022-03-25 15:13:55 +1030338 };
Zev Weiss309c0b12022-02-25 01:44:12 +0000339 FRUReader reader(getData);
Oskar Senftbd4075f2021-10-05 23:42:43 -0400340
Zev Weiss309c0b12022-02-25 01:44:12 +0000341 EXPECT_TRUE(findFRUHeader(reader, "error", blockData, offset));
Oskar Senftbd4075f2021-10-05 23:42:43 -0400342 EXPECT_EQ(0, offset);
343}
344
345TEST(FindFRUHeaderTest, TyanInvalidHeader)
346{
347 std::vector<uint8_t> data = {'$', 'T', 'Y', 'A', 'N', '$', 0, 0};
348 data.resize(0x6000 + I2C_SMBUS_BLOCK_MAX);
Zev Weiss1525e852022-03-22 22:27:43 +0000349 off_t offset = 0;
Oskar Senftbd4075f2021-10-05 23:42:43 -0400350 std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> blockData;
Zev Weiss309c0b12022-02-25 01:44:12 +0000351 auto getData = [&data](auto o, auto l, auto* b) {
352 return getDataTempl(data, o, l, b);
Andrew Jefferyf8ae2ba2022-03-25 15:13:55 +1030353 };
Zev Weiss309c0b12022-02-25 01:44:12 +0000354 FRUReader reader(getData);
Oskar Senftbd4075f2021-10-05 23:42:43 -0400355
Zev Weiss309c0b12022-02-25 01:44:12 +0000356 EXPECT_FALSE(findFRUHeader(reader, "error", blockData, offset));
Oskar Senftbd4075f2021-10-05 23:42:43 -0400357}
358
359TEST(FindFRUHeaderTest, TyanNoData)
360{
361 const std::vector<uint8_t> data = {'$', 'T', 'Y', 'A', 'N', '$', 0, 0};
Zev Weiss1525e852022-03-22 22:27:43 +0000362 off_t offset = 0;
Oskar Senftbd4075f2021-10-05 23:42:43 -0400363 std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> blockData;
Zev Weiss309c0b12022-02-25 01:44:12 +0000364 auto getData = [&data](auto o, auto l, auto* b) {
365 return getDataTempl(data, o, l, b);
Andrew Jefferyf8ae2ba2022-03-25 15:13:55 +1030366 };
Zev Weiss309c0b12022-02-25 01:44:12 +0000367 FRUReader reader(getData);
Oskar Senftbd4075f2021-10-05 23:42:43 -0400368
Zev Weiss309c0b12022-02-25 01:44:12 +0000369 EXPECT_FALSE(findFRUHeader(reader, "error", blockData, offset));
Oskar Senftbd4075f2021-10-05 23:42:43 -0400370}
371
372TEST(FindFRUHeaderTest, TyanValidHeader)
373{
374 std::vector<uint8_t> data = {'$', 'T', 'Y', 'A', 'N', '$', 0, 0};
375 data.resize(0x6000);
376 constexpr std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> fruHeader = {
377 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x00, 0xf5};
378 copy(fruHeader.begin(), fruHeader.end(), back_inserter(data));
379
Zev Weiss1525e852022-03-22 22:27:43 +0000380 off_t offset = 0;
Oskar Senftbd4075f2021-10-05 23:42:43 -0400381 std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> blockData;
Zev Weiss309c0b12022-02-25 01:44:12 +0000382 auto getData = [&data](auto o, auto l, auto* b) {
383 return getDataTempl(data, o, l, b);
Andrew Jefferyf8ae2ba2022-03-25 15:13:55 +1030384 };
Zev Weiss309c0b12022-02-25 01:44:12 +0000385 FRUReader reader(getData);
Oskar Senftbd4075f2021-10-05 23:42:43 -0400386
Zev Weiss309c0b12022-02-25 01:44:12 +0000387 EXPECT_TRUE(findFRUHeader(reader, "error", blockData, offset));
Oskar Senftbd4075f2021-10-05 23:42:43 -0400388 EXPECT_EQ(0x6000, offset);
389}