| Matt Spinler | 97f7abc | 2019-11-06 09:40:23 -0600 | [diff] [blame] | 1 | /** | 
 | 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 Spinler | d3335df | 2019-07-10 11:04:21 -0500 | [diff] [blame] | 16 | #include "pel_utils.hpp" | 
 | 17 |  | 
 | 18 | #include "extensions/openpower-pels/private_header.hpp" | 
| Matt Spinler | 03c1d91 | 2019-07-10 14:12:15 -0500 | [diff] [blame] | 19 | #include "extensions/openpower-pels/user_header.hpp" | 
| Matt Spinler | d3335df | 2019-07-10 11:04:21 -0500 | [diff] [blame] | 20 |  | 
 | 21 | #include <fstream> | 
 | 22 |  | 
 | 23 | #include <gtest/gtest.h> | 
 | 24 |  | 
 | 25 | namespace fs = std::filesystem; | 
 | 26 | using namespace openpower::pels; | 
 | 27 |  | 
| Matt Spinler | cb6b059 | 2019-07-16 15:58:51 -0500 | [diff] [blame] | 28 | std::filesystem::path CleanLogID::pelIDFile{}; | 
| Matt Spinler | 89fa082 | 2019-07-17 13:54:30 -0500 | [diff] [blame] | 29 | std::filesystem::path CleanPELFiles::pelIDFile{}; | 
 | 30 | std::filesystem::path CleanPELFiles::repoPath{}; | 
| Matt Spinler | 367144c | 2019-09-19 15:33:52 -0500 | [diff] [blame] | 31 | std::filesystem::path CleanPELFiles::registryPath{}; | 
| Matt Spinler | cb6b059 | 2019-07-16 15:58:51 -0500 | [diff] [blame] | 32 |  | 
| Matt Spinler | 42828bd | 2019-10-11 10:39:30 -0500 | [diff] [blame] | 33 | const std::vector<uint8_t> privateHeaderSection{ | 
 | 34 |     // section header | 
| Patrick Williams | ac1ba3f | 2023-05-10 07:50:16 -0500 | [diff] [blame] | 35 |     0x50, 0x48,                                     // ID 'PH' | 
 | 36 |     0x00, 0x30,                                     // Size | 
 | 37 |     0x01, 0x02,                                     // version, subtype | 
 | 38 |     0x03, 0x04,                                     // comp ID | 
| Matt Spinler | d3335df | 2019-07-10 11:04:21 -0500 | [diff] [blame] | 39 |  | 
| Matt Spinler | 42828bd | 2019-10-11 10:39:30 -0500 | [diff] [blame] | 40 |     0x20, 0x30, 0x05, 0x09, 0x11, 0x1E, 0x1,  0x63, // create timestamp | 
| Matt Spinler | d3335df | 2019-07-10 11:04:21 -0500 | [diff] [blame] | 41 |     0x20, 0x31, 0x06, 0x0F, 0x09, 0x22, 0x3A, 0x00, // commit timestamp | 
| Matt Spinler | 48c44db | 2020-08-25 12:47:13 -0500 | [diff] [blame] | 42 |     0x4F,                                           // creatorID 'O' | 
| Matt Spinler | d3335df | 2019-07-10 11:04:21 -0500 | [diff] [blame] | 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 Spinler | 454f656 | 2020-07-07 11:22:47 -0500 | [diff] [blame] | 49 |     0x80, 0x81, 0x82, 0x83};                        // PEL ID | 
| Matt Spinler | d3335df | 2019-07-10 11:04:21 -0500 | [diff] [blame] | 50 |  | 
| Matt Spinler | 42828bd | 2019-10-11 10:39:30 -0500 | [diff] [blame] | 51 | const std::vector<uint8_t> userHeaderSection{ | 
 | 52 |     // section header | 
| Patrick Williams | ac1ba3f | 2023-05-10 07:50:16 -0500 | [diff] [blame] | 53 |     0x55, 0x48,             // ID 'UH' | 
 | 54 |     0x00, 0x18,             // Size | 
 | 55 |     0x01, 0x0A,             // version, subtype | 
 | 56 |     0x0B, 0x0C,             // comp ID | 
| Matt Spinler | 03c1d91 | 2019-07-10 14:12:15 -0500 | [diff] [blame] | 57 |  | 
| Matt Spinler | 03c1d91 | 2019-07-10 14:12:15 -0500 | [diff] [blame] | 58 |     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 Spinler | d3335df | 2019-07-10 11:04:21 -0500 | [diff] [blame] | 64 | }; | 
 | 65 |  | 
| Matt Spinler | 42828bd | 2019-10-11 10:39:30 -0500 | [diff] [blame] | 66 | const std::vector<uint8_t> srcSectionNoCallouts{ | 
| Matt Spinler | f9bae18 | 2019-10-09 13:37:38 -0500 | [diff] [blame] | 67 |  | 
 | 68 |     // Header | 
| Matt Spinler | f1b46ff | 2020-01-22 14:10:04 -0600 | [diff] [blame] | 69 |     'P', 'S', 0x00, 0x50, 0x01, 0x01, 0x02, 0x02, | 
| Matt Spinler | f9bae18 | 2019-10-09 13:37:38 -0500 | [diff] [blame] | 70 |  | 
| Matt Spinler | f9bae18 | 2019-10-09 13:37:38 -0500 | [diff] [blame] | 71 |     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 Spinler | bd716f0 | 2019-10-15 10:54:11 -0500 | [diff] [blame] | 76 |     0x02, 0x02, 0x02, 0x55, 0x03, 0x03, 0x03, 0x10, 0x04, 0x04, 0x04, 0x04, | 
| Matt Spinler | f9bae18 | 2019-10-09 13:37:38 -0500 | [diff] [blame] | 77 |     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 Spinler | c63e2e8 | 2019-12-02 15:50:12 -0600 | [diff] [blame] | 84 | const std::vector<uint8_t> failingMTMSSection{ | 
| Matt Spinler | 213e5c1 | 2019-10-11 10:57:49 -0500 | [diff] [blame] | 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 |  | 
| Matt Spinler | c63e2e8 | 2019-12-02 15:50:12 -0600 | [diff] [blame] | 91 | const std::vector<uint8_t> UserDataSection{ | 
| Matt Spinler | 213e5c1 | 2019-10-11 10:57:49 -0500 | [diff] [blame] | 92 |     // Header | 
 | 93 |     0x55, 0x44, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, | 
 | 94 |  | 
 | 95 |     0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; | 
 | 96 |  | 
| Matt Spinler | c63e2e8 | 2019-12-02 15:50:12 -0600 | [diff] [blame] | 97 | const 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 Spinler | 42828bd | 2019-10-11 10:39:30 -0500 | [diff] [blame] | 121 | const 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 |  | 
 | 128 | const 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 |  | 
 | 135 | const 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 |  | 
| Matt Spinler | 386a61e | 2020-08-13 15:51:12 -0500 | [diff] [blame] | 148 | const std::vector<uint8_t> extendedUserDataSection{ | 
 | 149 |     // Header | 
 | 150 |     0x45, 0x44, 0x00, 0x18, 0x01, 0x02, 0x20, 0x00, | 
 | 151 |  | 
 | 152 |     // Creator ID 'O', and then data | 
 | 153 |     0x4F, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, | 
 | 154 |     0x05, 0x0A, 0x0B, 0x0C}; | 
 | 155 |  | 
| Matt Spinler | 42828bd | 2019-10-11 10:39:30 -0500 | [diff] [blame] | 156 | constexpr size_t sectionCountOffset = 27; | 
| Matt Spinler | 454f656 | 2020-07-07 11:22:47 -0500 | [diff] [blame] | 157 | constexpr size_t createTimestampPHOffset = 8; | 
 | 158 | constexpr size_t commitTimestampPHOffset = 16; | 
 | 159 | constexpr size_t creatorPHOffset = 24; | 
 | 160 | constexpr size_t obmcIDPHOffset = 28; | 
 | 161 | constexpr size_t plidPHOffset = 40; | 
 | 162 | constexpr size_t pelIDPHOffset = 44; | 
 | 163 | constexpr size_t sevUHOffset = 10; | 
 | 164 | constexpr size_t actionFlagsUHOffset = 18; | 
| Matt Spinler | 42828bd | 2019-10-11 10:39:30 -0500 | [diff] [blame] | 165 |  | 
 | 166 | std::vector<uint8_t> pelDataFactory(TestPELType type) | 
| Matt Spinler | d3335df | 2019-07-10 11:04:21 -0500 | [diff] [blame] | 167 | { | 
| Matt Spinler | 42828bd | 2019-10-11 10:39:30 -0500 | [diff] [blame] | 168 |     std::vector<uint8_t> data; | 
 | 169 |  | 
| Matt Spinler | d3335df | 2019-07-10 11:04:21 -0500 | [diff] [blame] | 170 |     switch (type) | 
 | 171 |     { | 
| Matt Spinler | 42828bd | 2019-10-11 10:39:30 -0500 | [diff] [blame] | 172 |         case TestPELType::pelSimple: | 
 | 173 |             data.insert(data.end(), privateHeaderSection.begin(), | 
 | 174 |                         privateHeaderSection.end()); | 
 | 175 |             data.insert(data.end(), userHeaderSection.begin(), | 
 | 176 |                         userHeaderSection.end()); | 
| Matt Spinler | 213e5c1 | 2019-10-11 10:57:49 -0500 | [diff] [blame] | 177 |             data.insert(data.end(), srcSectionNoCallouts.begin(), | 
 | 178 |                         srcSectionNoCallouts.end()); | 
 | 179 |             data.insert(data.end(), failingMTMSSection.begin(), | 
 | 180 |                         failingMTMSSection.end()); | 
 | 181 |             data.insert(data.end(), UserDataSection.begin(), | 
 | 182 |                         UserDataSection.end()); | 
| Matt Spinler | c63e2e8 | 2019-12-02 15:50:12 -0600 | [diff] [blame] | 183 |             data.insert(data.end(), ExtUserHeaderSection.begin(), | 
 | 184 |                         ExtUserHeaderSection.end()); | 
| Matt Spinler | 386a61e | 2020-08-13 15:51:12 -0500 | [diff] [blame] | 185 |             data.insert(data.end(), extendedUserDataSection.begin(), | 
 | 186 |                         extendedUserDataSection.end()); | 
 | 187 |             data.at(sectionCountOffset) = 7; | 
| Matt Spinler | d3335df | 2019-07-10 11:04:21 -0500 | [diff] [blame] | 188 |             break; | 
| Matt Spinler | 42828bd | 2019-10-11 10:39:30 -0500 | [diff] [blame] | 189 |         case TestPELType::privateHeaderSection: | 
 | 190 |             data.insert(data.end(), privateHeaderSection.begin(), | 
 | 191 |                         privateHeaderSection.end()); | 
| Matt Spinler | d3335df | 2019-07-10 11:04:21 -0500 | [diff] [blame] | 192 |             break; | 
| Matt Spinler | 42828bd | 2019-10-11 10:39:30 -0500 | [diff] [blame] | 193 |         case TestPELType::userHeaderSection: | 
 | 194 |             data.insert(data.end(), userHeaderSection.begin(), | 
 | 195 |                         userHeaderSection.end()); | 
| Matt Spinler | 03c1d91 | 2019-07-10 14:12:15 -0500 | [diff] [blame] | 196 |             break; | 
| Matt Spinler | 42828bd | 2019-10-11 10:39:30 -0500 | [diff] [blame] | 197 |         case TestPELType::primarySRCSection: | 
 | 198 |             data.insert(data.end(), srcSectionNoCallouts.begin(), | 
 | 199 |                         srcSectionNoCallouts.end()); | 
 | 200 |             break; | 
 | 201 |         case TestPELType::primarySRCSection2Callouts: | 
 | 202 |         { | 
 | 203 |             // Start with the no-callouts SRC, and add the callouts section | 
 | 204 |             // from above. | 
 | 205 |             auto src = srcSectionNoCallouts; | 
 | 206 |             auto callouts = | 
 | 207 |                 srcDataFactory(TestSRCType::calloutSection2Callouts); | 
 | 208 |  | 
 | 209 |             src.insert(src.end(), callouts.begin(), callouts.end()); | 
 | 210 |  | 
 | 211 |             // Set the flag that says there are callouts | 
 | 212 |             // One byte after the 8B header | 
 | 213 |             src[8 + 1] |= 0x01; | 
 | 214 |  | 
 | 215 |             // Set the new sizes | 
 | 216 |             uint16_t size = src.size(); | 
 | 217 |             Stream stream{src}; | 
 | 218 |  | 
 | 219 |             stream.offset(2); // In the header | 
 | 220 |             stream << size; | 
 | 221 |  | 
 | 222 |             // In the SRC - the size field doesn't include the header | 
 | 223 |             size -= 8; | 
 | 224 |             stream.offset(8 + 6); | 
 | 225 |             stream << size; | 
 | 226 |  | 
 | 227 |             data.insert(data.end(), src.begin(), src.end()); | 
 | 228 |             break; | 
 | 229 |         } | 
| Matt Spinler | 213e5c1 | 2019-10-11 10:57:49 -0500 | [diff] [blame] | 230 |         case TestPELType::failingMTMSSection: | 
 | 231 |             data.insert(data.end(), failingMTMSSection.begin(), | 
 | 232 |                         failingMTMSSection.end()); | 
| Patrick Williams | d26fa3e | 2021-04-21 15:22:23 -0500 | [diff] [blame] | 233 |             break; | 
| Matt Spinler | 386a61e | 2020-08-13 15:51:12 -0500 | [diff] [blame] | 234 |         case TestPELType::extendedUserDataSection: | 
 | 235 |             data.insert(data.end(), extendedUserDataSection.begin(), | 
 | 236 |                         extendedUserDataSection.end()); | 
| Patrick Williams | d26fa3e | 2021-04-21 15:22:23 -0500 | [diff] [blame] | 237 |             break; | 
| Matt Spinler | d3335df | 2019-07-10 11:04:21 -0500 | [diff] [blame] | 238 |     } | 
 | 239 |     return data; | 
 | 240 | } | 
 | 241 |  | 
| Matt Spinler | 454f656 | 2020-07-07 11:22:47 -0500 | [diff] [blame] | 242 | std::vector<uint8_t> pelFactory(uint32_t id, char creatorID, uint8_t severity, | 
 | 243 |                                 uint16_t actionFlags, size_t size) | 
 | 244 | { | 
 | 245 |     std::vector<uint8_t> data; | 
 | 246 |     size_t offset = 0; | 
 | 247 |  | 
 | 248 |     auto now = std::chrono::system_clock::now(); | 
 | 249 |     auto timestamp = getBCDTime(now); | 
 | 250 |  | 
 | 251 |     // Start with the default Private Header, and modify it | 
 | 252 |     data.insert(data.end(), privateHeaderSection.begin(), | 
 | 253 |                 privateHeaderSection.end()); | 
 | 254 |     data.at(creatorPHOffset) = creatorID; | 
 | 255 |  | 
 | 256 |     // Modify the multibyte fields in it | 
 | 257 |     Stream stream{data}; | 
 | 258 |     stream.offset(createTimestampPHOffset); | 
 | 259 |     stream << timestamp; | 
 | 260 |     stream.offset(commitTimestampPHOffset); | 
 | 261 |     stream << timestamp; | 
 | 262 |     stream.offset(plidPHOffset); | 
 | 263 |     stream << id; | 
 | 264 |     stream.offset(pelIDPHOffset); | 
 | 265 |     stream << id; | 
 | 266 |     stream.offset(obmcIDPHOffset); | 
 | 267 |     stream << id + 500; | 
 | 268 |  | 
 | 269 |     offset = data.size(); | 
 | 270 |  | 
 | 271 |     // User Header | 
 | 272 |     data.insert(data.end(), userHeaderSection.begin(), userHeaderSection.end()); | 
 | 273 |     data.at(offset + sevUHOffset) = severity; | 
 | 274 |     data.at(offset + actionFlagsUHOffset) = actionFlags >> 8; | 
 | 275 |     data.at(offset + actionFlagsUHOffset + 1) = actionFlags; | 
 | 276 |  | 
 | 277 |     // Use the default SRC, failing MTMS, and ext user Header sections | 
| Matt Spinler | 6c081cc | 2020-08-05 13:25:54 -0500 | [diff] [blame] | 278 |     auto src = pelDataFactory(TestPELType::primarySRCSection2Callouts); | 
 | 279 |  | 
 | 280 |     data.insert(data.end(), src.begin(), src.end()); | 
| Matt Spinler | 454f656 | 2020-07-07 11:22:47 -0500 | [diff] [blame] | 281 |     data.insert(data.end(), failingMTMSSection.begin(), | 
 | 282 |                 failingMTMSSection.end()); | 
 | 283 |     data.insert(data.end(), ExtUserHeaderSection.begin(), | 
 | 284 |                 ExtUserHeaderSection.end()); | 
 | 285 |  | 
 | 286 |     data.at(sectionCountOffset) = 5; | 
 | 287 |  | 
 | 288 |     // Require the size to be enough for all the above sections. | 
 | 289 |     assert(size >= data.size()); | 
 | 290 |     assert(size <= 16384); | 
 | 291 |  | 
 | 292 |     // Add a UserData section to get the size we need. | 
 | 293 |     auto udSection = UserDataSection; | 
 | 294 |     udSection.resize(size - data.size()); | 
 | 295 |  | 
 | 296 |     if (!udSection.empty()) | 
 | 297 |     { | 
 | 298 |         // At least has to be 8B for the header | 
 | 299 |         assert(udSection.size() >= 8); | 
 | 300 |  | 
 | 301 |         // UD sections must be 4B aligned | 
 | 302 |         assert(udSection.size() % 4 == 0); | 
 | 303 |  | 
 | 304 |         // Set the new size in the section heder | 
 | 305 |         Stream udStream{udSection}; | 
 | 306 |         udStream.offset(2); | 
 | 307 |         udStream << static_cast<uint16_t>(udSection.size()); | 
 | 308 |  | 
 | 309 |         data.insert(data.end(), udSection.begin(), udSection.end()); | 
 | 310 |         data[sectionCountOffset]++; | 
 | 311 |     } | 
 | 312 |  | 
 | 313 |     assert(size == data.size()); | 
 | 314 |     return data; | 
 | 315 | } | 
 | 316 |  | 
| Matt Spinler | 6c9662c | 2019-10-09 11:27:20 -0500 | [diff] [blame] | 317 | std::vector<uint8_t> srcDataFactory(TestSRCType type) | 
 | 318 | { | 
 | 319 |     switch (type) | 
 | 320 |     { | 
 | 321 |         case TestSRCType::fruIdentityStructure: | 
 | 322 |             return srcFRUIdentityCallout; | 
 | 323 |  | 
 | 324 |         case TestSRCType::pceIdentityStructure: | 
 | 325 |             return srcPCEIdentityCallout; | 
 | 326 |  | 
 | 327 |         case TestSRCType::mruStructure: | 
 | 328 |             return srcMRUCallout; | 
| Matt Spinler | 32f13c9 | 2019-10-09 12:48:25 -0500 | [diff] [blame] | 329 |  | 
 | 330 |         case TestSRCType::calloutStructureA: | 
 | 331 |         { | 
 | 332 |             // Add just the FRU identity substructure to the base structure | 
 | 333 |             std::vector<uint8_t> data{ | 
 | 334 |                 0xFF, 0x28, 'H', 4,   // size, flags, priority, LC length | 
 | 335 |                 'U',  '4',  '2', 0x00 // LC | 
 | 336 |             }; | 
 | 337 |  | 
 | 338 |             data.insert(data.end(), srcFRUIdentityCallout.begin(), | 
 | 339 |                         srcFRUIdentityCallout.end()); | 
 | 340 |  | 
 | 341 |             // The final size | 
 | 342 |             data[0] = data.size(); | 
 | 343 |             return data; | 
 | 344 |         } | 
 | 345 |         case TestSRCType::calloutStructureB: | 
 | 346 |         { | 
 | 347 |             // Add all 3 substructures to the base structure | 
 | 348 |  | 
 | 349 |             std::vector<uint8_t> data{ | 
 | 350 |                 0xFF, 0x2F, 'L', 8, // size, flags, priority, LC length | 
 | 351 |                 'U',  '1',  '2', '-', 'P', '1', 0x00, 0x00 // LC | 
 | 352 |             }; | 
 | 353 |             data.insert(data.end(), srcFRUIdentityCallout.begin(), | 
 | 354 |                         srcFRUIdentityCallout.end()); | 
 | 355 |             data.insert(data.end(), srcPCEIdentityCallout.begin(), | 
 | 356 |                         srcPCEIdentityCallout.end()); | 
 | 357 |             data.insert(data.end(), srcMRUCallout.begin(), srcMRUCallout.end()); | 
 | 358 |  | 
 | 359 |             // The final size | 
 | 360 |             data[0] = data.size(); | 
 | 361 |             return data; | 
 | 362 |         } | 
| Matt Spinler | f9bae18 | 2019-10-09 13:37:38 -0500 | [diff] [blame] | 363 |         case TestSRCType::calloutSection2Callouts: | 
 | 364 |         { | 
 | 365 |             std::vector<uint8_t> data{0xC0, 0x00, 0x00, | 
 | 366 |                                       0x00}; // ID, flags, length in words | 
 | 367 |  | 
 | 368 |             // Add 2 callouts | 
 | 369 |             auto callout = srcDataFactory(TestSRCType::calloutStructureA); | 
 | 370 |             data.insert(data.end(), callout.begin(), callout.end()); | 
 | 371 |  | 
 | 372 |             callout = srcDataFactory(TestSRCType::calloutStructureB); | 
 | 373 |             data.insert(data.end(), callout.begin(), callout.end()); | 
 | 374 |  | 
 | 375 |             // Set the actual word length value at offset 2 | 
 | 376 |             Stream stream{data}; | 
 | 377 |             uint16_t wordLength = data.size() / 4; | 
 | 378 |             stream.offset(2); | 
 | 379 |             stream << wordLength; | 
 | 380 |             stream.offset(0); | 
 | 381 |  | 
 | 382 |             return data; | 
 | 383 |         } | 
| Matt Spinler | 6c9662c | 2019-10-09 11:27:20 -0500 | [diff] [blame] | 384 |     } | 
 | 385 |     return {}; | 
 | 386 | } | 
 | 387 |  | 
| Matt Spinler | d3335df | 2019-07-10 11:04:21 -0500 | [diff] [blame] | 388 | std::unique_ptr<std::vector<uint8_t>> readPELFile(const fs::path& path) | 
 | 389 | { | 
 | 390 |     std::ifstream file{path}; | 
 | 391 |  | 
 | 392 |     auto pel = std::make_unique<std::vector<uint8_t>>( | 
 | 393 |         std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>()); | 
 | 394 |     return pel; | 
 | 395 | } |