1 #pragma once 2 3 #include "additional_data.hpp" 4 #include "data_interface.hpp" 5 #include "private_header.hpp" 6 #include "registry.hpp" 7 #include "src.hpp" 8 #include "user_data.hpp" 9 #include "user_data_formats.hpp" 10 #include "user_header.hpp" 11 12 #include <memory> 13 #include <vector> 14 15 namespace openpower 16 { 17 namespace pels 18 { 19 20 /** 21 * @brief Contains information about an FFDC file. 22 */ 23 struct PelFFDCfile 24 { 25 UserDataFormat format; 26 uint8_t subType; 27 uint8_t version; 28 int fd; 29 }; 30 31 using PelFFDC = std::vector<PelFFDCfile>; 32 33 /** @class PEL 34 * 35 * @brief This class represents a specific event log format referred to as a 36 * Platform Event Log. 37 * 38 * Every field in a PEL are in structures call sections, of which there are 39 * several types. Some sections are required, and some are optional. In some 40 * cases there may be more than one instance of a section type. 41 * 42 * The only two required sections for every type of PEL are the Private Header 43 * section and User Header section, which must be in the first and second 44 * positions, respectively. 45 * 46 * Every section starts with an 8 byte section header, which has the section 47 * size and type, among other things. 48 * 49 * This class represents all sections with objects. 50 * 51 * The class can be constructed: 52 * - From a full formed flattened PEL. 53 * - From scratch based on an OpenBMC event and its corresponding PEL message 54 * registry entry. 55 * 56 * The data() method allows one to retrieve the PEL as a vector<uint8_t>. This 57 * is the format in which it is stored and transmitted. 58 */ 59 class PEL 60 { 61 public: 62 PEL() = delete; 63 ~PEL() = default; 64 PEL(const PEL&) = delete; 65 PEL& operator=(const PEL&) = delete; 66 PEL(PEL&&) = delete; 67 PEL& operator=(PEL&&) = delete; 68 69 /** 70 * @brief Constructor 71 * 72 * Build a PEL from raw data. 73 * 74 * Note: Neither this nor the following constructor can take a const vector& 75 * because the Stream class that is used to read from the vector cannot take 76 * a const. The alternative is to make a copy of the data, but as PELs can 77 * be up to 16KB that is undesireable. 78 * 79 * @param[in] data - The PEL data 80 */ 81 PEL(std::vector<uint8_t>& data); 82 83 /** 84 * @brief Constructor 85 * 86 * Build a PEL from the raw data. 87 * 88 * @param[in] data - the PEL data 89 * @param[in] obmcLogID - the corresponding OpenBMC event log ID 90 */ 91 PEL(std::vector<uint8_t>& data, uint32_t obmcLogID); 92 93 /** 94 * @brief Constructor 95 * 96 * Creates a PEL from an OpenBMC event log and its message 97 * registry entry. 98 * 99 * @param[in] entry - The message registry entry for this error 100 * @param[in] obmcLogID - ID of corresponding OpenBMC event log 101 * @param[in] timestamp - Timestamp from the event log 102 * @param[in] severity - Severity from the event log 103 * @param[in] additionalData - The AdditionalData contents 104 * @param[in] ffdcFiles - FFCD files that go into UserData sections 105 * @param[in] dataIface - The data interface object 106 */ 107 PEL(const openpower::pels::message::Entry& entry, uint32_t obmcLogID, 108 uint64_t timestamp, phosphor::logging::Entry::Level severity, 109 const AdditionalData& additionalData, const PelFFDC& ffdcFiles, 110 const DataInterfaceBase& dataIface); 111 112 /** 113 * @brief Convenience function to return the log ID field from the 114 * Private Header section. 115 * 116 * @return uint32_t - the ID 117 */ 118 uint32_t id() const 119 { 120 return _ph->id(); 121 } 122 123 /** 124 * @brief Convenience function to return the PLID field from the 125 * Private Header section. 126 * 127 * @return uint32_t - the PLID 128 */ 129 uint32_t plid() const 130 { 131 return _ph->plid(); 132 } 133 134 /** 135 * @brief Convenience function to return the OpenBMC event log ID field 136 * from the Private Header section. 137 * 138 * @return uint32_t - the OpenBMC event log ID 139 */ 140 uint32_t obmcLogID() const 141 { 142 return _ph->obmcLogID(); 143 } 144 145 /** 146 * @brief Convenience function to return the commit time field from 147 * the Private Header section. 148 * 149 * @return BCDTime - the timestamp 150 */ 151 BCDTime commitTime() const 152 { 153 return _ph->commitTimestamp(); 154 } 155 156 /** 157 * @brief Convenience function to return the create time field from 158 * the Private Header section. 159 * 160 * @return BCDTime - the timestamp 161 */ 162 BCDTime createTime() const 163 { 164 return _ph->createTimestamp(); 165 } 166 167 /** 168 * @brief Gives access to the Private Header section class 169 * 170 * @return const PrivateHeader& - the private header 171 */ 172 const PrivateHeader& privateHeader() const 173 { 174 return *_ph; 175 } 176 177 /** 178 * @brief Gives access to the User Header section class 179 * 180 * @return const UserHeader& - the user header 181 */ 182 const UserHeader& userHeader() const 183 { 184 return *_uh; 185 } 186 187 /** 188 * @brief Gives access to the primary SRC's section class 189 * 190 * This is technically an optional section, so the return 191 * value is an std::optional<SRC*>. 192 * 193 * @return std::optional<SRC*> - the SRC section object 194 */ 195 std::optional<SRC*> primarySRC() const; 196 197 /** 198 * @brief Returns the optional sections, which is everything but 199 * the Private and User Headers. 200 * 201 * @return const std::vector<std::unique_ptr<Section>>& 202 */ 203 const std::vector<std::unique_ptr<Section>>& optionalSections() const 204 { 205 return _optionalSections; 206 } 207 208 /** 209 * @brief Returns the PEL data. 210 * 211 * @return std::vector<uint8_t> - the raw PEL data 212 */ 213 std::vector<uint8_t> data() const; 214 215 /** 216 * @brief Returns the size of the PEL 217 * 218 * @return size_t The PEL size in bytes 219 */ 220 size_t size() const; 221 222 /** 223 * @brief Says if the PEL is valid (the sections are all valid) 224 * 225 * @return bool - if the PEL is valid 226 */ 227 bool valid() const; 228 229 /** 230 * @brief Sets the commit timestamp to the current time 231 */ 232 void setCommitTime(); 233 234 /** 235 * @brief Sets the error log ID field to a unique ID. 236 */ 237 void assignID(); 238 239 /** 240 * @brief Output a PEL in JSON. 241 * @param[in] registry - Registry object reference 242 * @param[in] plugins - Vector of strings of plugins found in filesystem 243 */ 244 void toJSON(message::Registry& registry, 245 const std::vector<std::string>& plugins) const; 246 247 /** 248 * @brief Sets the host transmission state in the User Header 249 * 250 * @param[in] state - The state value 251 */ 252 void setHostTransmissionState(TransmissionState state) 253 { 254 _uh->setHostTransmissionState(static_cast<uint8_t>(state)); 255 } 256 257 /** 258 * @brief Returns the host transmission state 259 * 260 * @return HostTransmissionState - The state 261 */ 262 TransmissionState hostTransmissionState() const 263 { 264 return static_cast<TransmissionState>(_uh->hostTransmissionState()); 265 } 266 267 /** 268 * @brief Sets the HMC transmission state in the User Header 269 * 270 * @param[in] state - The state value 271 */ 272 void setHMCTransmissionState(TransmissionState state) 273 { 274 _uh->setHMCTransmissionState(static_cast<uint8_t>(state)); 275 } 276 277 /** 278 * @brief Returns the HMC transmission state 279 * 280 * @return HMCTransmissionState - The state 281 */ 282 TransmissionState hmcTransmissionState() const 283 { 284 return static_cast<TransmissionState>(_uh->hmcTransmissionState()); 285 } 286 287 /** 288 * @brief Returns true if any callout is present in the primary SRC 289 * 290 * @return true if callout present, false otherwise 291 */ 292 bool isCalloutPresent() const; 293 294 private: 295 /** 296 * @brief Builds the section objects from a PEL data buffer 297 * 298 * Note: The data parameter cannot be const for the same reasons 299 * as listed in the constructor. 300 * 301 * @param[in] data - The PEL data 302 * @param[in] obmcLogID - The OpenBMC event log ID to use for that 303 * field in the Private Header. 304 */ 305 void populateFromRawData(std::vector<uint8_t>& data, uint32_t obmcLogID); 306 307 /** 308 * @brief Flattens the PEL objects into the buffer 309 * 310 * @param[out] pelBuffer - What the data will be written to 311 */ 312 void flatten(std::vector<uint8_t>& pelBuffer) const; 313 314 /** 315 * @brief Check that the PEL fields that need to be in agreement 316 * with each other are, and fix them up if necessary. 317 */ 318 void checkRulesAndFix(); 319 320 /** 321 * @brief Returns a map of the section IDs that appear more than once 322 * in the PEL. The data value for each entry will be set to 0. 323 * 324 * @return std::map<uint16_t, size_t> 325 */ 326 std::map<uint16_t, size_t> getPluralSections() const; 327 328 /** 329 * @brief Adds the UserData section to this PEL object, 330 * shrinking it if necessary 331 * 332 * @param[in] userData - The section to add 333 * 334 * @return bool - If the section was added or not. 335 */ 336 bool addUserDataSection(std::unique_ptr<UserData> userData); 337 338 /** 339 * @brief helper function for printing PELs. 340 * @param[in] Section& - section object reference 341 * @param[in] std::string - PEL string 342 * @param[in|out] pluralSections - Map used to track sections counts for 343 * when there is more than 1. 344 * @param[in] registry - Registry object reference 345 * @param[in] plugins - Vector of strings of plugins found in filesystem 346 * @param[in] creatorID - Creator Subsystem ID (only for UserData section) 347 */ 348 void printSectionInJSON(const Section& section, std::string& buf, 349 std::map<uint16_t, size_t>& pluralSections, 350 message::Registry& registry, 351 const std::vector<std::string>& plugins, 352 uint8_t creatorID = 0) const; 353 354 /** 355 * @brief Returns any callout JSON found in the FFDC files. 356 * 357 * Looks for an FFDC file that is JSON format and has the 358 * sub-type value set to 0xCA and returns its data as a JSON object. 359 * 360 * @param[in] ffdcFiles - FFCD files that go into UserData sections 361 * 362 * @return json - The callout JSON, or an empty object if not found 363 */ 364 nlohmann::json getCalloutJSON(const PelFFDC& ffdcFiles); 365 366 /** 367 * @brief The PEL Private Header section 368 */ 369 std::unique_ptr<PrivateHeader> _ph; 370 371 /** 372 * @brief The PEL User Header section 373 */ 374 std::unique_ptr<UserHeader> _uh; 375 376 /** 377 * @brief Holds all sections by the PH and UH. 378 */ 379 std::vector<std::unique_ptr<Section>> _optionalSections; 380 381 /** 382 * @brief The maximum size a PEL can be in bytes. 383 */ 384 static constexpr size_t _maxPELSize = 16384; 385 }; 386 387 namespace util 388 { 389 390 /** 391 * @brief Creates a UserData section object that contains JSON. 392 * 393 * @param[in] json - The JSON contents 394 * 395 * @return std::unique_ptr<UserData> - The UserData object 396 */ 397 std::unique_ptr<UserData> makeJSONUserDataSection(const nlohmann::json& json); 398 399 /** 400 * @brief Create a UserData section containing the AdditionalData 401 * contents as a JSON string. 402 * 403 * @param[in] ad - The AdditionalData contents 404 * 405 * @return std::unique_ptr<UserData> - The section 406 */ 407 std::unique_ptr<UserData> makeADUserDataSection(const AdditionalData& ad); 408 409 /** 410 * @brief Create a UserData section containing various useful pieces 411 * of system information as a JSON string. 412 * 413 * @param[in] ad - The AdditionalData contents 414 * @param[in] dataIface - The data interface object 415 * 416 * @return std::unique_ptr<UserData> - The section 417 */ 418 std::unique_ptr<UserData> 419 makeSysInfoUserDataSection(const AdditionalData& ad, 420 const DataInterfaceBase& dataIface); 421 422 /** 423 * @brief Reads data from an opened file descriptor. 424 * 425 * @param[in] fd - The FD to read from 426 * 427 * @return std::vector<uint8_t> - The data read 428 */ 429 std::vector<uint8_t> readFD(int fd); 430 431 /** 432 * @brief Create a UserData section that contains the data in the file 433 * pointed to by the file descriptor passed in. 434 * 435 * @param[in] componentID - The component ID of the PEL creator 436 * @param[in] file - The FFDC file information 437 */ 438 std::unique_ptr<UserData> makeFFDCuserDataSection(uint16_t componentID, 439 const PelFFDCfile& file); 440 } // namespace util 441 442 } // namespace pels 443 } // namespace openpower 444