blob: 5fdab549e85c5230356767c9de79ca44191ad95a [file] [log] [blame]
Matt Spinler97f7abc2019-11-06 09:40:23 -06001/**
2 * Copyright © 2019 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Matt Spinlerd3335df2019-07-10 11:04:21 -050016#include "pel_utils.hpp"
17
18#include "extensions/openpower-pels/private_header.hpp"
Matt Spinler03c1d912019-07-10 14:12:15 -050019#include "extensions/openpower-pels/user_header.hpp"
Matt Spinlerd3335df2019-07-10 11:04:21 -050020
21#include <fstream>
22
23#include <gtest/gtest.h>
24
25namespace fs = std::filesystem;
26using namespace openpower::pels;
27
Matt Spinlercb6b0592019-07-16 15:58:51 -050028std::filesystem::path CleanLogID::pelIDFile{};
Matt Spinler89fa0822019-07-17 13:54:30 -050029std::filesystem::path CleanPELFiles::pelIDFile{};
30std::filesystem::path CleanPELFiles::repoPath{};
Matt Spinler367144c2019-09-19 15:33:52 -050031std::filesystem::path CleanPELFiles::registryPath{};
Matt Spinlercb6b0592019-07-16 15:58:51 -050032
Matt Spinler42828bd2019-10-11 10:39:30 -050033const std::vector<uint8_t> privateHeaderSection{
34 // section header
Matt Spinlerd3335df2019-07-10 11:04:21 -050035 0x50, 0x48, // ID 'PH'
36 0x00, 0x30, // Size
37 0x01, 0x02, // version, subtype
38 0x03, 0x04, // comp ID
39
Matt Spinler42828bd2019-10-11 10:39:30 -050040 0x20, 0x30, 0x05, 0x09, 0x11, 0x1E, 0x1, 0x63, // create timestamp
Matt Spinlerd3335df2019-07-10 11:04:21 -050041 0x20, 0x31, 0x06, 0x0F, 0x09, 0x22, 0x3A, 0x00, // commit timestamp
42 0xAA, // creatorID
43 0x00, // logtype
44 0x00, // reserved
45 0x02, // section count
46 0x90, 0x91, 0x92, 0x93, // OpenBMC log ID
47 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0, // creator version
48 0x50, 0x51, 0x52, 0x53, // plid
Matt Spinler42828bd2019-10-11 10:39:30 -050049 0x80, 0x81, 0x82, 0x83};
Matt Spinlerd3335df2019-07-10 11:04:21 -050050
Matt Spinler42828bd2019-10-11 10:39:30 -050051const std::vector<uint8_t> userHeaderSection{
52 // section header
Matt Spinler03c1d912019-07-10 14:12:15 -050053 0x55, 0x48, // ID 'UH'
54 0x00, 0x18, // Size
55 0x01, 0x0A, // version, subtype
56 0x0B, 0x0C, // comp ID
57
Matt Spinler03c1d912019-07-10 14:12:15 -050058 0x10, 0x04, // subsystem, scope
59 0x20, 0x00, // severity, type
60 0x00, 0x00, 0x00, 0x00, // reserved
61 0x03, 0x04, // problem domain, vector
62 0x80, 0xC0, // action flags
63 0x00, 0x00, 0x00, 0x00 // reserved
Matt Spinlerd3335df2019-07-10 11:04:21 -050064};
65
Matt Spinler42828bd2019-10-11 10:39:30 -050066const std::vector<uint8_t> srcSectionNoCallouts{
Matt Spinlerf9bae182019-10-09 13:37:38 -050067
68 // Header
69 'P', 'S', 0x00, 0x80, 0x01, 0x01, 0x02, 0x02,
70
Matt Spinlerf9bae182019-10-09 13:37:38 -050071 0x02, 0x00, 0x00, // version, flags, reserved
72 0x09, 0x00, 0x00, // hex word count, reserved2B
73 0x00, 0x48, // SRC structure size
74
75 // Hex words 2 - 9
Matt Spinlerbd716f02019-10-15 10:54:11 -050076 0x02, 0x02, 0x02, 0x55, 0x03, 0x03, 0x03, 0x10, 0x04, 0x04, 0x04, 0x04,
Matt Spinlerf9bae182019-10-09 13:37:38 -050077 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07,
78 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09,
79 // ASCII string
80 'B', 'D', '8', 'D', '5', '6', '7', '8', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
81 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
82 ' ', ' '};
83
Matt Spinler213e5c12019-10-11 10:57:49 -050084std::vector<uint8_t> failingMTMSSection{
85 // Header
86 0x4D, 0x54, 0x00, 0x1C, 0x01, 0x00, 0x20, 0x00,
87
88 'T', 'T', 'T', 'T', '-', 'M', 'M', 'M', '1', '2',
89 '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C'};
90
91std::vector<uint8_t> UserDataSection{
92 // Header
93 0x55, 0x44, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00,
94
95 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
96
Matt Spinler42828bd2019-10-11 10:39:30 -050097const std::vector<uint8_t> srcFRUIdentityCallout{
98 'I', 'D', 0x1C, 0x1D, // type, size, flags
99 '1', '2', '3', '4', // PN
100 '5', '6', '7', 0x00, 'A', 'A', 'A', 'A', // CCIN
101 '1', '2', '3', '4', '5', '6', '7', '8', // SN
102 '9', 'A', 'B', 'C'};
103
104const std::vector<uint8_t> srcPCEIdentityCallout{
105 'P', 'E', 0x24, 0x00, // type, size, flags
106 'T', 'T', 'T', 'T', '-', 'M', 'M', 'M', // MTM
107 '1', '2', '3', '4', '5', '6', '7', // SN
108 '8', '9', 'A', 'B', 'C', 'P', 'C', 'E', // Name + null padded
109 'N', 'A', 'M', 'E', '1', '2', 0x00, 0x00, 0x00};
110
111const std::vector<uint8_t> srcMRUCallout{
112 'M', 'R', 0x28, 0x04, // ID, size, flags
113 0x00, 0x00, 0x00, 0x00, // Reserved
114 0x00, 0x00, 0x00, 'H', // priority 0
115 0x01, 0x01, 0x01, 0x01, // MRU ID 0
116 0x00, 0x00, 0x00, 'M', // priority 1
117 0x02, 0x02, 0x02, 0x02, // MRU ID 1
118 0x00, 0x00, 0x00, 'L', // priority 2
119 0x03, 0x03, 0x03, 0x03, // MRU ID 2
120 0x00, 0x00, 0x00, 'H', // priority 3
121 0x04, 0x04, 0x04, 0x04, // MRU ID 3
122};
123
124constexpr size_t sectionCountOffset = 27;
125
126std::vector<uint8_t> pelDataFactory(TestPELType type)
Matt Spinlerd3335df2019-07-10 11:04:21 -0500127{
Matt Spinler42828bd2019-10-11 10:39:30 -0500128 std::vector<uint8_t> data;
129
Matt Spinlerd3335df2019-07-10 11:04:21 -0500130 switch (type)
131 {
Matt Spinler42828bd2019-10-11 10:39:30 -0500132 case TestPELType::pelSimple:
133 data.insert(data.end(), privateHeaderSection.begin(),
134 privateHeaderSection.end());
135 data.insert(data.end(), userHeaderSection.begin(),
136 userHeaderSection.end());
Matt Spinler213e5c12019-10-11 10:57:49 -0500137 data.insert(data.end(), srcSectionNoCallouts.begin(),
138 srcSectionNoCallouts.end());
139 data.insert(data.end(), failingMTMSSection.begin(),
140 failingMTMSSection.end());
141 data.insert(data.end(), UserDataSection.begin(),
142 UserDataSection.end());
143 data.at(sectionCountOffset) = 5;
Matt Spinlerd3335df2019-07-10 11:04:21 -0500144 break;
Matt Spinler42828bd2019-10-11 10:39:30 -0500145 case TestPELType::privateHeaderSection:
146 data.insert(data.end(), privateHeaderSection.begin(),
147 privateHeaderSection.end());
Matt Spinlerd3335df2019-07-10 11:04:21 -0500148 break;
Matt Spinler42828bd2019-10-11 10:39:30 -0500149 case TestPELType::userHeaderSection:
150 data.insert(data.end(), userHeaderSection.begin(),
151 userHeaderSection.end());
Matt Spinler03c1d912019-07-10 14:12:15 -0500152 break;
Matt Spinler42828bd2019-10-11 10:39:30 -0500153 case TestPELType::primarySRCSection:
154 data.insert(data.end(), srcSectionNoCallouts.begin(),
155 srcSectionNoCallouts.end());
156 break;
157 case TestPELType::primarySRCSection2Callouts:
158 {
159 // Start with the no-callouts SRC, and add the callouts section
160 // from above.
161 auto src = srcSectionNoCallouts;
162 auto callouts =
163 srcDataFactory(TestSRCType::calloutSection2Callouts);
164
165 src.insert(src.end(), callouts.begin(), callouts.end());
166
167 // Set the flag that says there are callouts
168 // One byte after the 8B header
169 src[8 + 1] |= 0x01;
170
171 // Set the new sizes
172 uint16_t size = src.size();
173 Stream stream{src};
174
175 stream.offset(2); // In the header
176 stream << size;
177
178 // In the SRC - the size field doesn't include the header
179 size -= 8;
180 stream.offset(8 + 6);
181 stream << size;
182
183 data.insert(data.end(), src.begin(), src.end());
184 break;
185 }
Matt Spinler213e5c12019-10-11 10:57:49 -0500186 case TestPELType::failingMTMSSection:
187 data.insert(data.end(), failingMTMSSection.begin(),
188 failingMTMSSection.end());
Matt Spinlerd3335df2019-07-10 11:04:21 -0500189 }
190 return data;
191}
192
Matt Spinler6c9662c2019-10-09 11:27:20 -0500193std::vector<uint8_t> srcDataFactory(TestSRCType type)
194{
195 switch (type)
196 {
197 case TestSRCType::fruIdentityStructure:
198 return srcFRUIdentityCallout;
199
200 case TestSRCType::pceIdentityStructure:
201 return srcPCEIdentityCallout;
202
203 case TestSRCType::mruStructure:
204 return srcMRUCallout;
Matt Spinler32f13c92019-10-09 12:48:25 -0500205
206 case TestSRCType::calloutStructureA:
207 {
208 // Add just the FRU identity substructure to the base structure
209 std::vector<uint8_t> data{
210 0xFF, 0x28, 'H', 4, // size, flags, priority, LC length
211 'U', '4', '2', 0x00 // LC
212 };
213
214 data.insert(data.end(), srcFRUIdentityCallout.begin(),
215 srcFRUIdentityCallout.end());
216
217 // The final size
218 data[0] = data.size();
219 return data;
220 }
221 case TestSRCType::calloutStructureB:
222 {
223 // Add all 3 substructures to the base structure
224
225 std::vector<uint8_t> data{
226 0xFF, 0x2F, 'L', 8, // size, flags, priority, LC length
227 'U', '1', '2', '-', 'P', '1', 0x00, 0x00 // LC
228 };
229 data.insert(data.end(), srcFRUIdentityCallout.begin(),
230 srcFRUIdentityCallout.end());
231 data.insert(data.end(), srcPCEIdentityCallout.begin(),
232 srcPCEIdentityCallout.end());
233 data.insert(data.end(), srcMRUCallout.begin(), srcMRUCallout.end());
234
235 // The final size
236 data[0] = data.size();
237 return data;
238 }
Matt Spinlerf9bae182019-10-09 13:37:38 -0500239 case TestSRCType::calloutSection2Callouts:
240 {
241 std::vector<uint8_t> data{0xC0, 0x00, 0x00,
242 0x00}; // ID, flags, length in words
243
244 // Add 2 callouts
245 auto callout = srcDataFactory(TestSRCType::calloutStructureA);
246 data.insert(data.end(), callout.begin(), callout.end());
247
248 callout = srcDataFactory(TestSRCType::calloutStructureB);
249 data.insert(data.end(), callout.begin(), callout.end());
250
251 // Set the actual word length value at offset 2
252 Stream stream{data};
253 uint16_t wordLength = data.size() / 4;
254 stream.offset(2);
255 stream << wordLength;
256 stream.offset(0);
257
258 return data;
259 }
Matt Spinler6c9662c2019-10-09 11:27:20 -0500260 }
261 return {};
262}
263
Matt Spinlerd3335df2019-07-10 11:04:21 -0500264std::unique_ptr<std::vector<uint8_t>> readPELFile(const fs::path& path)
265{
266 std::ifstream file{path};
267
268 auto pel = std::make_unique<std::vector<uint8_t>>(
269 std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());
270 return pel;
271}