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 */ 243 void toJSON(message::Registry& registry) const; 244 245 /** 246 * @brief Sets the host transmission state in the User Header 247 * 248 * @param[in] state - The state value 249 */ 250 void setHostTransmissionState(TransmissionState state) 251 { 252 _uh->setHostTransmissionState(static_cast<uint8_t>(state)); 253 } 254 255 /** 256 * @brief Returns the host transmission state 257 * 258 * @return HostTransmissionState - The state 259 */ 260 TransmissionState hostTransmissionState() const 261 { 262 return static_cast<TransmissionState>(_uh->hostTransmissionState()); 263 } 264 265 /** 266 * @brief Sets the HMC transmission state in the User Header 267 * 268 * @param[in] state - The state value 269 */ 270 void setHMCTransmissionState(TransmissionState state) 271 { 272 _uh->setHMCTransmissionState(static_cast<uint8_t>(state)); 273 } 274 275 /** 276 * @brief Returns the HMC transmission state 277 * 278 * @return HMCTransmissionState - The state 279 */ 280 TransmissionState hmcTransmissionState() const 281 { 282 return static_cast<TransmissionState>(_uh->hmcTransmissionState()); 283 } 284 285 private: 286 /** 287 * @brief Builds the section objects from a PEL data buffer 288 * 289 * Note: The data parameter cannot be const for the same reasons 290 * as listed in the constructor. 291 * 292 * @param[in] data - The PEL data 293 * @param[in] obmcLogID - The OpenBMC event log ID to use for that 294 * field in the Private Header. 295 */ 296 void populateFromRawData(std::vector<uint8_t>& data, uint32_t obmcLogID); 297 298 /** 299 * @brief Flattens the PEL objects into the buffer 300 * 301 * @param[out] pelBuffer - What the data will be written to 302 */ 303 void flatten(std::vector<uint8_t>& pelBuffer) const; 304 305 /** 306 * @brief Check that the PEL fields that need to be in agreement 307 * with each other are, and fix them up if necessary. 308 */ 309 void checkRulesAndFix(); 310 311 /** 312 * @brief Returns a map of the section IDs that appear more than once 313 * in the PEL. The data value for each entry will be set to 0. 314 * 315 * @return std::map<uint16_t, size_t> 316 */ 317 std::map<uint16_t, size_t> getPluralSections() const; 318 319 /** 320 * @brief The PEL Private Header section 321 */ 322 std::unique_ptr<PrivateHeader> _ph; 323 324 /** 325 * @brief The PEL User Header section 326 */ 327 std::unique_ptr<UserHeader> _uh; 328 329 /** 330 * @brief Holds all sections by the PH and UH. 331 */ 332 std::vector<std::unique_ptr<Section>> _optionalSections; 333 334 /** 335 * @brief helper function for printing PELs. 336 * @param[in] Section& - section object reference 337 * @param[in] std::string - PEL string 338 * @param[in|out] pluralSections - Map used to track sections counts for 339 * when there is more than 1. 340 * @param[in] registry - Registry object reference 341 */ 342 void printSectionInJSON(const Section& section, std::string& buf, 343 std::map<uint16_t, size_t>& pluralSections, 344 message::Registry& registry) const; 345 346 /** 347 * @brief The maximum size a PEL can be in bytes. 348 */ 349 static constexpr size_t _maxPELSize = 16384; 350 }; 351 352 namespace util 353 { 354 355 /** 356 * @brief Create a UserData section containing the AdditionalData 357 * contents as a JSON string. 358 * 359 * @param[in] ad - The AdditionalData contents 360 * 361 * @return std::unique_ptr<UserData> - The section 362 */ 363 std::unique_ptr<UserData> makeADUserDataSection(const AdditionalData& ad); 364 365 /** 366 * @brief Create a UserData section containing various useful pieces 367 * of system information as a JSON string. 368 * 369 * @param[in] ad - The AdditionalData contents 370 * @param[in] dataIface - The data interface object 371 * 372 * @return std::unique_ptr<UserData> - The section 373 */ 374 std::unique_ptr<UserData> 375 makeSysInfoUserDataSection(const AdditionalData& ad, 376 const DataInterfaceBase& dataIface); 377 378 /** 379 * @brief Create a UserData section that contains the data in the file 380 * pointed to by the file descriptor passed in. 381 * 382 * @param[in] componentID - The component ID of the PEL creator 383 * @param[in] file - The FFDC file information 384 */ 385 std::unique_ptr<UserData> makeFFDCuserDataSection(uint16_t componentID, 386 const PelFFDCfile& file); 387 } // namespace util 388 389 } // namespace pels 390 } // namespace openpower 391