1 /** 2 * Copyright © 2019 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 "private_header.hpp" 17 18 #include "json_utils.hpp" 19 #include "log_id.hpp" 20 #include "pel_types.hpp" 21 #include "pel_values.hpp" 22 23 #include <phosphor-logging/log.hpp> 24 25 namespace openpower 26 { 27 namespace pels 28 { 29 30 namespace pv = openpower::pels::pel_values; 31 using namespace phosphor::logging; 32 33 PrivateHeader::PrivateHeader(uint16_t componentID, uint32_t obmcLogID, 34 uint64_t timestamp) 35 { 36 _header.id = static_cast<uint16_t>(SectionID::privateHeader); 37 _header.size = PrivateHeader::flattenedSize(); 38 _header.version = privateHeaderVersion; 39 _header.subType = 0; 40 _header.componentID = componentID; 41 42 _createTimestamp = getBCDTime(timestamp); 43 44 auto now = std::chrono::system_clock::now(); 45 _commitTimestamp = getBCDTime(now); 46 47 _creatorID = static_cast<uint8_t>(CreatorID::openBMC); 48 49 // Add support for reminder and telemetry log types here if 50 // ever necessary. 51 _logType = 0; 52 53 _reservedByte = 0; 54 55 // the final section count will be updated later 56 _sectionCount = 1; 57 58 _obmcLogID = obmcLogID; 59 60 _id = generatePELID(); 61 62 _plid = _id; 63 64 // Leave _creatorVersion at 0 65 66 _valid = true; 67 } 68 69 PrivateHeader::PrivateHeader(Stream& pel) : 70 _creatorID(0), _logType(0), _reservedByte(0), _sectionCount(0), 71 _obmcLogID(0), _plid(0), _id(0) 72 { 73 try 74 { 75 unflatten(pel); 76 validate(); 77 } 78 catch (const std::exception& e) 79 { 80 log<level::ERR>("Cannot unflatten private header", 81 entry("ERROR=%s", e.what())); 82 _valid = false; 83 } 84 } 85 std::optional<std::string> PrivateHeader::getJSON() const 86 { 87 char tmpPhVal[50]; 88 sprintf(tmpPhVal, "%02X/%02X/%02X%02X %02X:%02X:%02X", 89 _createTimestamp.month, _createTimestamp.day, 90 _createTimestamp.yearMSB, _createTimestamp.yearLSB, 91 _createTimestamp.hour, _createTimestamp.minutes, 92 _createTimestamp.seconds); 93 std::string phCreateTStr(tmpPhVal); 94 sprintf(tmpPhVal, "%02X/%02X/%02X%02X %02X:%02X:%02X", 95 _commitTimestamp.month, _commitTimestamp.day, 96 _commitTimestamp.yearMSB, _commitTimestamp.yearLSB, 97 _commitTimestamp.hour, _commitTimestamp.minutes, 98 _commitTimestamp.seconds); 99 std::string phCommitTStr(tmpPhVal); 100 std::string creator = getNumberString("%c", _creatorID); 101 creator = pv::creatorIDs.count(creator) ? pv::creatorIDs.at(creator) 102 : "Unknown CreatorID"; 103 std::string phCreatorVersionStr = 104 std::string(reinterpret_cast<const char*>(_creatorVersion.version)); 105 106 std::string ph; 107 jsonInsert(ph, pv::sectionVer, getNumberString("%d", privateHeaderVersion), 108 1); 109 jsonInsert(ph, pv::subSection, getNumberString("%d", _header.subType), 1); 110 jsonInsert(ph, pv::createdBy, getNumberString("0x%X", _header.componentID), 111 1); 112 jsonInsert(ph, "Created at", phCreateTStr, 1); 113 jsonInsert(ph, "Committed at", phCommitTStr, 1); 114 jsonInsert(ph, "Creator Subsystem", creator, 1); 115 jsonInsert(ph, "CSSVER", phCreatorVersionStr, 1); 116 jsonInsert(ph, "Platform Log Id", getNumberString("0x%X", _plid), 1); 117 jsonInsert(ph, "Entry Id", getNumberString("0x%X", _id), 1); 118 jsonInsert(ph, "BMC Event Log Id", std::to_string(_obmcLogID), 1); 119 ph.erase(ph.size() - 2); 120 121 return ph; 122 } 123 void PrivateHeader::validate() 124 { 125 bool failed = false; 126 127 if (header().id != static_cast<uint16_t>(SectionID::privateHeader)) 128 { 129 log<level::ERR>("Invalid private header section ID", 130 entry("ID=0x%X", header().id)); 131 failed = true; 132 } 133 134 if (header().version != privateHeaderVersion) 135 { 136 log<level::ERR>("Invalid private header version", 137 entry("VERSION=0x%X", header().version)); 138 failed = true; 139 } 140 141 if (_sectionCount < minSectionCount) 142 { 143 log<level::ERR>("Invalid section count in private header", 144 entry("SECTION_COUNT=0x%X", _sectionCount)); 145 failed = true; 146 } 147 148 _valid = (failed) ? false : true; 149 } 150 151 void PrivateHeader::unflatten(Stream& stream) 152 { 153 stream >> _header >> _createTimestamp >> _commitTimestamp >> _creatorID >> 154 _logType >> _reservedByte >> _sectionCount >> _obmcLogID >> 155 _creatorVersion >> _plid >> _id; 156 } 157 158 void PrivateHeader::flatten(Stream& stream) const 159 { 160 stream << _header << _createTimestamp << _commitTimestamp << _creatorID 161 << _logType << _reservedByte << _sectionCount << _obmcLogID 162 << _creatorVersion << _plid << _id; 163 } 164 165 Stream& operator>>(Stream& s, CreatorVersion& cv) 166 { 167 for (size_t i = 0; i < sizeof(CreatorVersion); i++) 168 { 169 s >> cv.version[i]; 170 } 171 return s; 172 } 173 174 Stream& operator<<(Stream& s, const CreatorVersion& cv) 175 { 176 for (size_t i = 0; i < sizeof(CreatorVersion); i++) 177 { 178 s << cv.version[i]; 179 } 180 return s; 181 } 182 183 } // namespace pels 184 } // namespace openpower 185