1 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: Copyright 2020 IBM Corporation
3
4 #include "extended_user_data.hpp"
5
6 #include "pel_types.hpp"
7 #ifdef PELTOOL
8 #include "user_data_json.hpp"
9 #endif
10 #include <phosphor-logging/lg2.hpp>
11
12 #include <format>
13
14 namespace openpower::pels
15 {
16
unflatten(Stream & stream)17 void ExtendedUserData::unflatten(Stream& stream)
18 {
19 stream >> _header;
20
21 if (_header.size <= SectionHeader::flattenedSize() + 4)
22 {
23 throw std::out_of_range(
24 std::format("ExtendedUserData::unflatten: SectionHeader::size {} "
25 "too small",
26 _header.size));
27 }
28
29 size_t dataLength = _header.size - 4 - SectionHeader::flattenedSize();
30 _data.resize(dataLength);
31
32 stream >> _creatorID >> _reserved1B >> _reserved2B >> _data;
33 }
34
flatten(Stream & stream) const35 void ExtendedUserData::flatten(Stream& stream) const
36 {
37 stream << _header << _creatorID << _reserved1B << _reserved2B << _data;
38 }
39
ExtendedUserData(Stream & pel)40 ExtendedUserData::ExtendedUserData(Stream& pel)
41 {
42 try
43 {
44 unflatten(pel);
45 validate();
46 }
47 catch (const std::exception& e)
48 {
49 lg2::error("Cannot unflatten ExtendedUserData section: {EXCEPTION}",
50 "EXCEPTION", e);
51 _valid = false;
52 }
53 }
54
ExtendedUserData(uint16_t componentID,uint8_t subType,uint8_t version,uint8_t creatorID,const std::vector<uint8_t> & data)55 ExtendedUserData::ExtendedUserData(uint16_t componentID, uint8_t subType,
56 uint8_t version, uint8_t creatorID,
57 const std::vector<uint8_t>& data)
58 {
59 _header.id = static_cast<uint16_t>(SectionID::extUserData);
60 _header.version = version;
61 _header.subType = subType;
62 _header.componentID = componentID;
63
64 _creatorID = creatorID;
65 _reserved1B = 0;
66 _reserved2B = 0;
67 _data = data;
68 _header.size = flattenedSize();
69 _valid = true;
70 }
71
validate()72 void ExtendedUserData::validate()
73 {
74 if (header().id != static_cast<uint16_t>(SectionID::extUserData))
75 {
76 lg2::error("Invalid ExtendedUserData section ID: {HEADER_ID}",
77 "HEADER_ID", lg2::hex, header().id);
78 _valid = false;
79 }
80 else
81 {
82 _valid = true;
83 }
84 }
85
getJSON(uint8_t,const std::vector<std::string> & plugins) const86 std::optional<std::string> ExtendedUserData::getJSON(
87 uint8_t /*creatorID*/,
88 const std::vector<std::string>& plugins [[maybe_unused]]) const
89 {
90 // Use the creator ID value from the section.
91 #ifdef PELTOOL
92 return user_data::getJSON(_header.componentID, _header.subType,
93 _header.version, _data, _creatorID, plugins);
94 #endif
95 return std::nullopt;
96 }
97
shrink(size_t newSize)98 bool ExtendedUserData::shrink(size_t newSize)
99 {
100 // minimum size is 8B header + 4B of fields + 4B of data
101 if ((newSize < flattenedSize()) && (newSize >= (Section::headerSize() + 8)))
102 {
103 auto dataSize = newSize - Section::headerSize() - 4;
104
105 // Ensure it's 4B aligned
106 _data.resize((dataSize / 4) * 4);
107 _header.size = flattenedSize();
108 return true;
109 }
110
111 return false;
112 }
113
114 } // namespace openpower::pels
115