1386a61e6SMatt Spinler #pragma once 2386a61e6SMatt Spinler 3386a61e6SMatt Spinler #include "section.hpp" 4386a61e6SMatt Spinler #include "stream.hpp" 5386a61e6SMatt Spinler 6386a61e6SMatt Spinler namespace openpower::pels 7386a61e6SMatt Spinler { 8386a61e6SMatt Spinler 9386a61e6SMatt Spinler /** 10386a61e6SMatt Spinler * @class ExtendedUserData 11386a61e6SMatt Spinler * 12386a61e6SMatt Spinler * This represents the Extended User Data section in a PEL. It is free form 13386a61e6SMatt Spinler * data that the creator knows the contents of. The component ID, version, and 14386a61e6SMatt Spinler * sub-type fields in the section header are used to identify the format. 15386a61e6SMatt Spinler * 16386a61e6SMatt Spinler * This section is used for one subsystem to add FFDC data to a PEL created 17386a61e6SMatt Spinler * by another subsystem. It is basically the same as a UserData section, 18386a61e6SMatt Spinler * except it has the creator ID of the section creator stored in the section. 19386a61e6SMatt Spinler * 20386a61e6SMatt Spinler * The Section base class handles the section header structure that every 21386a61e6SMatt Spinler * PEL section has at offset zero. 22386a61e6SMatt Spinler */ 23386a61e6SMatt Spinler class ExtendedUserData : public Section 24386a61e6SMatt Spinler { 25386a61e6SMatt Spinler public: 26386a61e6SMatt Spinler ExtendedUserData() = delete; 27362f469cSMatt Spinler ~ExtendedUserData() override = default; 28386a61e6SMatt Spinler ExtendedUserData(const ExtendedUserData&) = default; 29386a61e6SMatt Spinler ExtendedUserData& operator=(const ExtendedUserData&) = default; 30386a61e6SMatt Spinler ExtendedUserData(ExtendedUserData&&) = default; 31386a61e6SMatt Spinler ExtendedUserData& operator=(ExtendedUserData&&) = default; 32386a61e6SMatt Spinler 33386a61e6SMatt Spinler /** 34386a61e6SMatt Spinler * @brief Constructor 35386a61e6SMatt Spinler * 36386a61e6SMatt Spinler * Fills in this class's data fields from the stream. 37386a61e6SMatt Spinler * 38386a61e6SMatt Spinler * @param[in] pel - the PEL data stream 39386a61e6SMatt Spinler */ 40386a61e6SMatt Spinler explicit ExtendedUserData(Stream& pel); 41386a61e6SMatt Spinler 42386a61e6SMatt Spinler /** 43386a61e6SMatt Spinler * @brief Constructor 44386a61e6SMatt Spinler * 45386a61e6SMatt Spinler * Create a valid ExtendedUserData object with the passed in data. 46386a61e6SMatt Spinler * 47386a61e6SMatt Spinler * The component ID, subtype, and version are used to identify 48386a61e6SMatt Spinler * the data to know which parser to call. 49386a61e6SMatt Spinler * 50386a61e6SMatt Spinler * @param[in] componentID - Component ID of the creator 51386a61e6SMatt Spinler * @param[in] subType - The type of user data 52386a61e6SMatt Spinler * @param[in] version - The version of the data 53386a61e6SMatt Spinler */ 54386a61e6SMatt Spinler ExtendedUserData(uint16_t componentID, uint8_t subType, uint8_t version, 55386a61e6SMatt Spinler uint8_t creatorID, const std::vector<uint8_t>& data); 56386a61e6SMatt Spinler 57386a61e6SMatt Spinler /** 58386a61e6SMatt Spinler * @brief Flatten the section into the stream 59386a61e6SMatt Spinler * 60386a61e6SMatt Spinler * @param[in] stream - The stream to write to 61386a61e6SMatt Spinler */ 62386a61e6SMatt Spinler void flatten(Stream& stream) const override; 63386a61e6SMatt Spinler 64386a61e6SMatt Spinler /** 65386a61e6SMatt Spinler * @brief Returns the size of this section when flattened into a PEL 66386a61e6SMatt Spinler * 67386a61e6SMatt Spinler * @return size_t - the size of the section 68386a61e6SMatt Spinler */ flattenedSize()69386a61e6SMatt Spinler size_t flattenedSize() 70386a61e6SMatt Spinler { 71e2eb14aeSMatt Spinler return Section::headerSize() + sizeof(_creatorID) + 72386a61e6SMatt Spinler sizeof(_reserved1B) + sizeof(_reserved2B) + _data.size(); 73386a61e6SMatt Spinler } 74386a61e6SMatt Spinler 75386a61e6SMatt Spinler /** 76386a61e6SMatt Spinler * @brief Returns the section creator ID field. 77386a61e6SMatt Spinler * 78386a61e6SMatt Spinler * @return uint8_t - The creator ID 79386a61e6SMatt Spinler */ creatorID() const80d26fa3e7SPatrick Williams uint8_t creatorID() const 81386a61e6SMatt Spinler { 82386a61e6SMatt Spinler return _creatorID; 83386a61e6SMatt Spinler } 84386a61e6SMatt Spinler 85386a61e6SMatt Spinler /** 86386a61e6SMatt Spinler * @brief Returns the raw section data 87386a61e6SMatt Spinler * 88386a61e6SMatt Spinler * This doesn't include the creator ID. 89386a61e6SMatt Spinler * 90386a61e6SMatt Spinler * @return std::vector<uint8_t>& 91386a61e6SMatt Spinler */ data() const92386a61e6SMatt Spinler const std::vector<uint8_t>& data() const 93386a61e6SMatt Spinler { 94386a61e6SMatt Spinler return _data; 95386a61e6SMatt Spinler } 96386a61e6SMatt Spinler 97386a61e6SMatt Spinler /** 983160a544SSumit Kumar * @brief Returns the section data updated with new data 993160a544SSumit Kumar * 1003160a544SSumit Kumar * @param[in] subType - The type of user data 1013160a544SSumit Kumar * @param[in] componentID - Component ID of the creator 1023160a544SSumit Kumar * @param[in] newData - The new data 1033160a544SSumit Kumar * 1043160a544SSumit Kumar */ updateDataSection(const uint8_t subType,const uint16_t componentId,const std::vector<uint8_t> & newData)1053160a544SSumit Kumar void updateDataSection(const uint8_t subType, const uint16_t componentId, 1063160a544SSumit Kumar const std::vector<uint8_t>& newData) 1073160a544SSumit Kumar { 1083160a544SSumit Kumar if (newData.size() >= 4) 1093160a544SSumit Kumar { 11045796e82SMatt Spinler size_t origDataSize{}; 11145796e82SMatt Spinler 1123160a544SSumit Kumar // Update component Id & subtype in section header of ED 1133160a544SSumit Kumar _header.componentID = static_cast<uint16_t>(componentId); 1143160a544SSumit Kumar _header.subType = static_cast<uint8_t>(subType); 1153160a544SSumit Kumar 1163160a544SSumit Kumar if (newData.size() > _data.size()) 1173160a544SSumit Kumar { 1183160a544SSumit Kumar // Don't allow section to get bigger 1193160a544SSumit Kumar origDataSize = _data.size(); 1203160a544SSumit Kumar _data = newData; 1213160a544SSumit Kumar _data.resize(origDataSize); 1223160a544SSumit Kumar } 1233160a544SSumit Kumar else 1243160a544SSumit Kumar { 1253160a544SSumit Kumar // Use shrink to handle 4B alignment and update the header size 1263160a544SSumit Kumar auto status = 127e2eb14aeSMatt Spinler shrink(Section::headerSize() + 4 + newData.size()); 1283160a544SSumit Kumar if (status) 1293160a544SSumit Kumar { 1303160a544SSumit Kumar origDataSize = _data.size(); 1313160a544SSumit Kumar _data = newData; 1323160a544SSumit Kumar _data.resize(origDataSize); 1333160a544SSumit Kumar } 1343160a544SSumit Kumar } 1353160a544SSumit Kumar } 1363160a544SSumit Kumar } 1373160a544SSumit Kumar 1383160a544SSumit Kumar /** 139386a61e6SMatt Spinler * @brief Get the section contents in JSON 140386a61e6SMatt Spinler * 141386a61e6SMatt Spinler * @param[in] creatorID - Creator Subsystem ID - unused (see the .cpp) 142386a61e6SMatt Spinler * @param[in] plugins - Vector of strings of plugins found in filesystem 143386a61e6SMatt Spinler * 144386a61e6SMatt Spinler * @return The JSON as a string if a parser was found, 145386a61e6SMatt Spinler * otherwise std::nullopt. 146386a61e6SMatt Spinler */ 14725291157SPatrick Williams std::optional<std::string> getJSON( 14825291157SPatrick Williams uint8_t creatorID, 149386a61e6SMatt Spinler const std::vector<std::string>& plugins) const override; 150386a61e6SMatt Spinler 151386a61e6SMatt Spinler /** 152386a61e6SMatt Spinler * @brief Shrink the section 153386a61e6SMatt Spinler * 154386a61e6SMatt Spinler * The new size must be between the current size and the minimum 155386a61e6SMatt Spinler * size, which is 12 bytes. If it isn't a 4 byte aligned value 156386a61e6SMatt Spinler * the code will do the aligning before the resize takes place. 157386a61e6SMatt Spinler * 158386a61e6SMatt Spinler * @param[in] newSize - The new size in bytes 159386a61e6SMatt Spinler * 160386a61e6SMatt Spinler * @return bool - true if successful, false else. 161386a61e6SMatt Spinler */ 162386a61e6SMatt Spinler bool shrink(size_t newSize) override; 163386a61e6SMatt Spinler 164386a61e6SMatt Spinler private: 165386a61e6SMatt Spinler /** 166386a61e6SMatt Spinler * @brief Fills in the object from the stream data 167386a61e6SMatt Spinler * 168386a61e6SMatt Spinler * @param[in] stream - The stream to read from 169386a61e6SMatt Spinler */ 170386a61e6SMatt Spinler void unflatten(Stream& stream); 171386a61e6SMatt Spinler 172386a61e6SMatt Spinler /** 173386a61e6SMatt Spinler * @brief Validates the section contents 174386a61e6SMatt Spinler * 175386a61e6SMatt Spinler * Updates _valid (in Section) with the results. 176386a61e6SMatt Spinler */ 177*bf27da63SMatt Spinler void validate(); 178386a61e6SMatt Spinler 179386a61e6SMatt Spinler /** 180386a61e6SMatt Spinler * @brief The subsystem creator ID of the code that 181386a61e6SMatt Spinler * created this section. 182386a61e6SMatt Spinler */ 183386a61e6SMatt Spinler uint8_t _creatorID; 184386a61e6SMatt Spinler 185386a61e6SMatt Spinler /** 186386a61e6SMatt Spinler * @brief Reserved 187386a61e6SMatt Spinler */ 188386a61e6SMatt Spinler uint8_t _reserved1B; 189386a61e6SMatt Spinler 190386a61e6SMatt Spinler /** 191386a61e6SMatt Spinler * @brief Reserved 192386a61e6SMatt Spinler */ 193386a61e6SMatt Spinler uint16_t _reserved2B; 194386a61e6SMatt Spinler 195386a61e6SMatt Spinler /** 196386a61e6SMatt Spinler * @brief The section data 197386a61e6SMatt Spinler */ 198386a61e6SMatt Spinler std::vector<uint8_t> _data; 199386a61e6SMatt Spinler }; 200386a61e6SMatt Spinler 201386a61e6SMatt Spinler } // namespace openpower::pels 202