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 <fmt/format.h> 23 24 #include <phosphor-logging/log.hpp> 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 fmt::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 fmt::format("Cannot unflatten ExtendedUserData: {}", e.what()) 65 .c_str()); 66 _valid = false; 67 } 68 } 69 70 ExtendedUserData::ExtendedUserData(uint16_t componentID, uint8_t subType, 71 uint8_t version, uint8_t creatorID, 72 const std::vector<uint8_t>& data) 73 { 74 _header.id = static_cast<uint16_t>(SectionID::extUserData); 75 _header.version = version; 76 _header.subType = subType; 77 _header.componentID = componentID; 78 79 _creatorID = creatorID; 80 _reserved1B = 0; 81 _reserved2B = 0; 82 _data = data; 83 _header.size = flattenedSize(); 84 _valid = true; 85 } 86 87 void ExtendedUserData::validate() 88 { 89 if (header().id != static_cast<uint16_t>(SectionID::extUserData)) 90 { 91 log<level::ERR>( 92 fmt::format("Invalid ExtendedUserData section ID {}", header().id) 93 .c_str()); 94 _valid = false; 95 } 96 else 97 { 98 _valid = true; 99 } 100 } 101 102 std::optional<std::string> 103 ExtendedUserData::getJSON(uint8_t creatorID, 104 const std::vector<std::string>& plugins) const 105 { 106 // Use the creator ID value from the section. 107 #ifdef PELTOOL 108 return user_data::getJSON(_header.componentID, _header.subType, 109 _header.version, _data, _creatorID, plugins); 110 #endif 111 return std::nullopt; 112 } 113 114 bool ExtendedUserData::shrink(size_t newSize) 115 { 116 // minimum size is 8B header + 4B of fields + 4B of data 117 if ((newSize < flattenedSize()) && 118 (newSize >= (Section::flattenedSize() + 8))) 119 { 120 auto dataSize = newSize - Section::flattenedSize() - 4; 121 122 // Ensure it's 4B aligned 123 _data.resize((dataSize / 4) * 4); 124 _header.size = flattenedSize(); 125 return true; 126 } 127 128 return false; 129 } 130 131 } // namespace openpower::pels 132