blob: 4560b2f1a96341ba216dd56666fc389207484071 [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
Matt Spinlerf1b46ff2020-01-22 14:10:04 -060069 'P', 'S', 0x00, 0x50, 0x01, 0x01, 0x02, 0x02,
Matt Spinlerf9bae182019-10-09 13:37:38 -050070
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 Spinlerc63e2e82019-12-02 15:50:12 -060084const std::vector<uint8_t> failingMTMSSection{
Matt Spinler213e5c12019-10-11 10:57:49 -050085 // 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
Matt Spinlerc63e2e82019-12-02 15:50:12 -060091const std::vector<uint8_t> UserDataSection{
Matt Spinler213e5c12019-10-11 10:57:49 -050092 // Header
93 0x55, 0x44, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00,
94
95 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
96
Matt Spinlerc63e2e82019-12-02 15:50:12 -060097const std::vector<uint8_t> ExtUserHeaderSection{
98 // Header
99 'E', 'H', 0x00, 0x60, 0x01, 0x00, 0x03, 0x04,
100
101 // MTMS
102 'T', 'T', 'T', 'T', '-', 'M', 'M', 'M', '1', '2', '3', '4', '5', '6', '7',
103 '8', '9', 'A', 'B', 'C',
104
105 // Server FW version
106 'S', 'E', 'R', 'V', 'E', 'R', '_', 'V', 'E', 'R', 'S', 'I', 'O', 'N', '\0',
107 '\0',
108
109 // Subsystem FW Version
110 'B', 'M', 'C', '_', 'V', 'E', 'R', 'S', 'I', 'O', 'N', '\0', '\0', '\0',
111 '\0', '\0',
112
113 0x00, 0x00, 0x00, 0x00, // Reserved
114 0x20, 0x25, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, // Ref time
115 0x00, 0x00, 0x00, // Reserved
116
117 // SymptomID length and symptom ID
118 20, 'B', 'D', '8', 'D', '4', '2', '0', '0', '_', '1', '2', '3', '4', '5',
119 '6', '7', '8', '\0', '\0', '\0'};
120
Matt Spinler42828bd2019-10-11 10:39:30 -0500121const std::vector<uint8_t> srcFRUIdentityCallout{
122 'I', 'D', 0x1C, 0x1D, // type, size, flags
123 '1', '2', '3', '4', // PN
124 '5', '6', '7', 0x00, 'A', 'A', 'A', 'A', // CCIN
125 '1', '2', '3', '4', '5', '6', '7', '8', // SN
126 '9', 'A', 'B', 'C'};
127
128const std::vector<uint8_t> srcPCEIdentityCallout{
129 'P', 'E', 0x24, 0x00, // type, size, flags
130 'T', 'T', 'T', 'T', '-', 'M', 'M', 'M', // MTM
131 '1', '2', '3', '4', '5', '6', '7', // SN
132 '8', '9', 'A', 'B', 'C', 'P', 'C', 'E', // Name + null padded
133 'N', 'A', 'M', 'E', '1', '2', 0x00, 0x00, 0x00};
134
135const std::vector<uint8_t> srcMRUCallout{
136 'M', 'R', 0x28, 0x04, // ID, size, flags
137 0x00, 0x00, 0x00, 0x00, // Reserved
138 0x00, 0x00, 0x00, 'H', // priority 0
139 0x01, 0x01, 0x01, 0x01, // MRU ID 0
140 0x00, 0x00, 0x00, 'M', // priority 1
141 0x02, 0x02, 0x02, 0x02, // MRU ID 1
142 0x00, 0x00, 0x00, 'L', // priority 2
143 0x03, 0x03, 0x03, 0x03, // MRU ID 2
144 0x00, 0x00, 0x00, 'H', // priority 3
145 0x04, 0x04, 0x04, 0x04, // MRU ID 3
146};
147
148constexpr size_t sectionCountOffset = 27;
149
150std::vector<uint8_t> pelDataFactory(TestPELType type)
Matt Spinlerd3335df2019-07-10 11:04:21 -0500151{
Matt Spinler42828bd2019-10-11 10:39:30 -0500152 std::vector<uint8_t> data;
153
Matt Spinlerd3335df2019-07-10 11:04:21 -0500154 switch (type)
155 {
Matt Spinler42828bd2019-10-11 10:39:30 -0500156 case TestPELType::pelSimple:
157 data.insert(data.end(), privateHeaderSection.begin(),
158 privateHeaderSection.end());
159 data.insert(data.end(), userHeaderSection.begin(),
160 userHeaderSection.end());
Matt Spinler213e5c12019-10-11 10:57:49 -0500161 data.insert(data.end(), srcSectionNoCallouts.begin(),
162 srcSectionNoCallouts.end());
163 data.insert(data.end(), failingMTMSSection.begin(),
164 failingMTMSSection.end());
165 data.insert(data.end(), UserDataSection.begin(),
166 UserDataSection.end());
Matt Spinlerc63e2e82019-12-02 15:50:12 -0600167 data.insert(data.end(), ExtUserHeaderSection.begin(),
168 ExtUserHeaderSection.end());
169 data.at(sectionCountOffset) = 6;
Matt Spinlerd3335df2019-07-10 11:04:21 -0500170 break;
Matt Spinler42828bd2019-10-11 10:39:30 -0500171 case TestPELType::privateHeaderSection:
172 data.insert(data.end(), privateHeaderSection.begin(),
173 privateHeaderSection.end());
Matt Spinlerd3335df2019-07-10 11:04:21 -0500174 break;
Matt Spinler42828bd2019-10-11 10:39:30 -0500175 case TestPELType::userHeaderSection:
176 data.insert(data.end(), userHeaderSection.begin(),
177 userHeaderSection.end());
Matt Spinler03c1d912019-07-10 14:12:15 -0500178 break;
Matt Spinler42828bd2019-10-11 10:39:30 -0500179 case TestPELType::primarySRCSection:
180 data.insert(data.end(), srcSectionNoCallouts.begin(),
181 srcSectionNoCallouts.end());
182 break;
183 case TestPELType::primarySRCSection2Callouts:
184 {
185 // Start with the no-callouts SRC, and add the callouts section
186 // from above.
187 auto src = srcSectionNoCallouts;
188 auto callouts =
189 srcDataFactory(TestSRCType::calloutSection2Callouts);
190
191 src.insert(src.end(), callouts.begin(), callouts.end());
192
193 // Set the flag that says there are callouts
194 // One byte after the 8B header
195 src[8 + 1] |= 0x01;
196
197 // Set the new sizes
198 uint16_t size = src.size();
199 Stream stream{src};
200
201 stream.offset(2); // In the header
202 stream << size;
203
204 // In the SRC - the size field doesn't include the header
205 size -= 8;
206 stream.offset(8 + 6);
207 stream << size;
208
209 data.insert(data.end(), src.begin(), src.end());
210 break;
211 }
Matt Spinler213e5c12019-10-11 10:57:49 -0500212 case TestPELType::failingMTMSSection:
213 data.insert(data.end(), failingMTMSSection.begin(),
214 failingMTMSSection.end());
Matt Spinlerd3335df2019-07-10 11:04:21 -0500215 }
216 return data;
217}
218
Matt Spinler6c9662c2019-10-09 11:27:20 -0500219std::vector<uint8_t> srcDataFactory(TestSRCType type)
220{
221 switch (type)
222 {
223 case TestSRCType::fruIdentityStructure:
224 return srcFRUIdentityCallout;
225
226 case TestSRCType::pceIdentityStructure:
227 return srcPCEIdentityCallout;
228
229 case TestSRCType::mruStructure:
230 return srcMRUCallout;
Matt Spinler32f13c92019-10-09 12:48:25 -0500231
232 case TestSRCType::calloutStructureA:
233 {
234 // Add just the FRU identity substructure to the base structure
235 std::vector<uint8_t> data{
236 0xFF, 0x28, 'H', 4, // size, flags, priority, LC length
237 'U', '4', '2', 0x00 // LC
238 };
239
240 data.insert(data.end(), srcFRUIdentityCallout.begin(),
241 srcFRUIdentityCallout.end());
242
243 // The final size
244 data[0] = data.size();
245 return data;
246 }
247 case TestSRCType::calloutStructureB:
248 {
249 // Add all 3 substructures to the base structure
250
251 std::vector<uint8_t> data{
252 0xFF, 0x2F, 'L', 8, // size, flags, priority, LC length
253 'U', '1', '2', '-', 'P', '1', 0x00, 0x00 // LC
254 };
255 data.insert(data.end(), srcFRUIdentityCallout.begin(),
256 srcFRUIdentityCallout.end());
257 data.insert(data.end(), srcPCEIdentityCallout.begin(),
258 srcPCEIdentityCallout.end());
259 data.insert(data.end(), srcMRUCallout.begin(), srcMRUCallout.end());
260
261 // The final size
262 data[0] = data.size();
263 return data;
264 }
Matt Spinlerf9bae182019-10-09 13:37:38 -0500265 case TestSRCType::calloutSection2Callouts:
266 {
267 std::vector<uint8_t> data{0xC0, 0x00, 0x00,
268 0x00}; // ID, flags, length in words
269
270 // Add 2 callouts
271 auto callout = srcDataFactory(TestSRCType::calloutStructureA);
272 data.insert(data.end(), callout.begin(), callout.end());
273
274 callout = srcDataFactory(TestSRCType::calloutStructureB);
275 data.insert(data.end(), callout.begin(), callout.end());
276
277 // Set the actual word length value at offset 2
278 Stream stream{data};
279 uint16_t wordLength = data.size() / 4;
280 stream.offset(2);
281 stream << wordLength;
282 stream.offset(0);
283
284 return data;
285 }
Matt Spinler6c9662c2019-10-09 11:27:20 -0500286 }
287 return {};
288}
289
Matt Spinlerd3335df2019-07-10 11:04:21 -0500290std::unique_ptr<std::vector<uint8_t>> readPELFile(const fs::path& path)
291{
292 std::ifstream file{path};
293
294 auto pel = std::make_unique<std::vector<uint8_t>>(
295 std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());
296 return pel;
297}