blob: 07f996995a99dd86e67d5157751a4f65b9492698 [file] [log] [blame]
Matt Spinler386a61e2020-08-13 15:51:12 -05001#pragma once
2
3#include "section.hpp"
4#include "stream.hpp"
5
6namespace openpower::pels
7{
8
9/**
10 * @class ExtendedUserData
11 *
12 * This represents the Extended User Data section in a PEL. It is free form
13 * data that the creator knows the contents of. The component ID, version, and
14 * sub-type fields in the section header are used to identify the format.
15 *
16 * This section is used for one subsystem to add FFDC data to a PEL created
17 * by another subsystem. It is basically the same as a UserData section,
18 * except it has the creator ID of the section creator stored in the section.
19 *
20 * The Section base class handles the section header structure that every
21 * PEL section has at offset zero.
22 */
23class ExtendedUserData : public Section
24{
25 public:
26 ExtendedUserData() = delete;
27 ~ExtendedUserData() = default;
28 ExtendedUserData(const ExtendedUserData&) = default;
29 ExtendedUserData& operator=(const ExtendedUserData&) = default;
30 ExtendedUserData(ExtendedUserData&&) = default;
31 ExtendedUserData& operator=(ExtendedUserData&&) = default;
32
33 /**
34 * @brief Constructor
35 *
36 * Fills in this class's data fields from the stream.
37 *
38 * @param[in] pel - the PEL data stream
39 */
40 explicit ExtendedUserData(Stream& pel);
41
42 /**
43 * @brief Constructor
44 *
45 * Create a valid ExtendedUserData object with the passed in data.
46 *
47 * The component ID, subtype, and version are used to identify
48 * the data to know which parser to call.
49 *
50 * @param[in] componentID - Component ID of the creator
51 * @param[in] subType - The type of user data
52 * @param[in] version - The version of the data
53 */
54 ExtendedUserData(uint16_t componentID, uint8_t subType, uint8_t version,
55 uint8_t creatorID, const std::vector<uint8_t>& data);
56
57 /**
58 * @brief Flatten the section into the stream
59 *
60 * @param[in] stream - The stream to write to
61 */
62 void flatten(Stream& stream) const override;
63
64 /**
65 * @brief Returns the size of this section when flattened into a PEL
66 *
67 * @return size_t - the size of the section
68 */
69 size_t flattenedSize()
70 {
71 return Section::flattenedSize() + sizeof(_creatorID) +
72 sizeof(_reserved1B) + sizeof(_reserved2B) + _data.size();
73 }
74
75 /**
76 * @brief Returns the section creator ID field.
77 *
78 * @return uint8_t - The creator ID
79 */
Patrick Williamsd26fa3e2021-04-21 15:22:23 -050080 uint8_t creatorID() const
Matt Spinler386a61e2020-08-13 15:51:12 -050081 {
82 return _creatorID;
83 }
84
85 /**
86 * @brief Returns the raw section data
87 *
88 * This doesn't include the creator ID.
89 *
90 * @return std::vector<uint8_t>&
91 */
92 const std::vector<uint8_t>& data() const
93 {
94 return _data;
95 }
96
97 /**
Sumit Kumar3160a542021-04-26 08:07:04 -050098 * @brief Returns the section data updated with new data
99 *
100 * @param[in] subType - The type of user data
101 * @param[in] componentID - Component ID of the creator
102 * @param[in] newData - The new data
103 *
104 */
105 void updateDataSection(const uint8_t subType, const uint16_t componentId,
106 const std::vector<uint8_t>& newData)
107 {
Sumit Kumar3160a542021-04-26 08:07:04 -0500108 if (newData.size() >= 4)
109 {
Matt Spinler45796e82022-07-01 11:25:27 -0500110 size_t origDataSize{};
111
Sumit Kumar3160a542021-04-26 08:07:04 -0500112 // Update component Id & subtype in section header of ED
113 _header.componentID = static_cast<uint16_t>(componentId);
114 _header.subType = static_cast<uint8_t>(subType);
115
116 if (newData.size() > _data.size())
117 {
118 // Don't allow section to get bigger
119 origDataSize = _data.size();
120 _data = newData;
121 _data.resize(origDataSize);
122 }
123 else
124 {
125 // Use shrink to handle 4B alignment and update the header size
126 auto status =
127 shrink(Section::flattenedSize() + 4 + newData.size());
128 if (status)
129 {
130 origDataSize = _data.size();
131 _data = newData;
132 _data.resize(origDataSize);
133 }
134 }
135 }
136 }
137
138 /**
Matt Spinler386a61e2020-08-13 15:51:12 -0500139 * @brief Get the section contents in JSON
140 *
141 * @param[in] creatorID - Creator Subsystem ID - unused (see the .cpp)
142 * @param[in] plugins - Vector of strings of plugins found in filesystem
143 *
144 * @return The JSON as a string if a parser was found,
145 * otherwise std::nullopt.
146 */
147 std::optional<std::string>
148 getJSON(uint8_t creatorID,
149 const std::vector<std::string>& plugins) const override;
150
151 /**
152 * @brief Shrink the section
153 *
154 * The new size must be between the current size and the minimum
155 * size, which is 12 bytes. If it isn't a 4 byte aligned value
156 * the code will do the aligning before the resize takes place.
157 *
158 * @param[in] newSize - The new size in bytes
159 *
160 * @return bool - true if successful, false else.
161 */
162 bool shrink(size_t newSize) override;
163
164 private:
165 /**
166 * @brief Fills in the object from the stream data
167 *
168 * @param[in] stream - The stream to read from
169 */
170 void unflatten(Stream& stream);
171
172 /**
173 * @brief Validates the section contents
174 *
175 * Updates _valid (in Section) with the results.
176 */
177 void validate() override;
178
179 /**
180 * @brief The subsystem creator ID of the code that
181 * created this section.
182 */
183 uint8_t _creatorID;
184
185 /**
186 * @brief Reserved
187 */
188 uint8_t _reserved1B;
189
190 /**
191 * @brief Reserved
192 */
193 uint16_t _reserved2B;
194
195 /**
196 * @brief The section data
197 */
198 std::vector<uint8_t> _data;
199};
200
201} // namespace openpower::pels