1 /** 2 * Copyright © 2020 IBM Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #include "extended_user_data.hpp" 17 18 #include "pel_types.hpp" 19 #ifdef PELTOOL 20 #include "user_data_json.hpp" 21 #endif 22 #include <phosphor-logging/log.hpp> 23 24 #include <format> 25 26 namespace openpower::pels 27 { 28 29 using namespace phosphor::logging; 30 31 void ExtendedUserData::unflatten(Stream& stream) 32 { 33 stream >> _header; 34 35 if (_header.size <= SectionHeader::flattenedSize() + 4) 36 { 37 throw std::out_of_range( 38 std::format("ExtendedUserData::unflatten: SectionHeader::size {} " 39 "too small", 40 _header.size)); 41 } 42 43 size_t dataLength = _header.size - 4 - SectionHeader::flattenedSize(); 44 _data.resize(dataLength); 45 46 stream >> _creatorID >> _reserved1B >> _reserved2B >> _data; 47 } 48 49 void ExtendedUserData::flatten(Stream& stream) const 50 { 51 stream << _header << _creatorID << _reserved1B << _reserved2B << _data; 52 } 53 54 ExtendedUserData::ExtendedUserData(Stream& pel) 55 { 56 try 57 { 58 unflatten(pel); 59 validate(); 60 } 61 catch (const std::exception& e) 62 { 63 log<level::ERR>( 64 std::format("Cannot unflatten ExtendedUserData section: {}", 65 e.what()) 66 .c_str()); 67 _valid = false; 68 } 69 } 70 71 ExtendedUserData::ExtendedUserData(uint16_t componentID, uint8_t subType, 72 uint8_t version, uint8_t creatorID, 73 const std::vector<uint8_t>& data) 74 { 75 _header.id = static_cast<uint16_t>(SectionID::extUserData); 76 _header.version = version; 77 _header.subType = subType; 78 _header.componentID = componentID; 79 80 _creatorID = creatorID; 81 _reserved1B = 0; 82 _reserved2B = 0; 83 _data = data; 84 _header.size = flattenedSize(); 85 _valid = true; 86 } 87 88 void ExtendedUserData::validate() 89 { 90 if (header().id != static_cast<uint16_t>(SectionID::extUserData)) 91 { 92 log<level::ERR>( 93 std::format("Invalid ExtendedUserData section ID: {0:#x}", 94 header().id) 95 .c_str()); 96 _valid = false; 97 } 98 else 99 { 100 _valid = true; 101 } 102 } 103 104 std::optional<std::string> 105 ExtendedUserData::getJSON(uint8_t /*creatorID*/, 106 const std::vector<std::string>& plugins 107 [[maybe_unused]]) const 108 { 109 // Use the creator ID value from the section. 110 #ifdef PELTOOL 111 return user_data::getJSON(_header.componentID, _header.subType, 112 _header.version, _data, _creatorID, plugins); 113 #endif 114 return std::nullopt; 115 } 116 117 bool ExtendedUserData::shrink(size_t newSize) 118 { 119 // minimum size is 8B header + 4B of fields + 4B of data 120 if ((newSize < flattenedSize()) && 121 (newSize >= (Section::flattenedSize() + 8))) 122 { 123 auto dataSize = newSize - Section::flattenedSize() - 4; 124 125 // Ensure it's 4B aligned 126 _data.resize((dataSize / 4) * 4); 127 _header.size = flattenedSize(); 128 return true; 129 } 130 131 return false; 132 } 133 134 } // namespace openpower::pels 135