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 "user_header.hpp" 17 18 #include "json_utils.hpp" 19 #include "pel_types.hpp" 20 #include "pel_values.hpp" 21 #include "severity.hpp" 22 23 #include <iostream> 24 #include <phosphor-logging/log.hpp> 25 26 namespace openpower 27 { 28 namespace pels 29 { 30 31 namespace pv = openpower::pels::pel_values; 32 using namespace phosphor::logging; 33 34 void UserHeader::unflatten(Stream& stream) 35 { 36 stream >> _header >> _eventSubsystem >> _eventScope >> _eventSeverity >> 37 _eventType >> _reserved4Byte1 >> _problemDomain >> _problemVector >> 38 _actionFlags >> _states; 39 } 40 41 void UserHeader::flatten(Stream& stream) const 42 { 43 stream << _header << _eventSubsystem << _eventScope << _eventSeverity 44 << _eventType << _reserved4Byte1 << _problemDomain << _problemVector 45 << _actionFlags << _states; 46 } 47 48 UserHeader::UserHeader(const message::Entry& entry, 49 phosphor::logging::Entry::Level severity, 50 const DataInterfaceBase& dataIface) 51 { 52 _header.id = static_cast<uint16_t>(SectionID::userHeader); 53 _header.size = UserHeader::flattenedSize(); 54 _header.version = userHeaderVersion; 55 _header.subType = 0; 56 _header.componentID = static_cast<uint16_t>(ComponentID::phosphorLogging); 57 58 _eventSubsystem = entry.subsystem; 59 60 _eventScope = entry.eventScope.value_or( 61 static_cast<uint8_t>(EventScope::entirePlatform)); 62 63 // Get the severity from the registry if it's there, otherwise get it 64 // from the OpenBMC event log severity value. 65 if (!entry.severity) 66 { 67 _eventSeverity = convertOBMCSeverityToPEL(severity); 68 } 69 else 70 { 71 // Find the severity possibly dependent on the system type. 72 auto sev = 73 getSeverity(entry.severity.value(), dataIface.getSystemType()); 74 if (sev) 75 { 76 _eventSeverity = *sev; 77 } 78 else 79 { 80 // Someone screwed up the message registry. 81 log<level::ERR>( 82 "No severity entry found for this error and system type", 83 phosphor::logging::entry("ERROR=%s", entry.name.c_str()), 84 phosphor::logging::entry("SYSTEMTYPE=%s", 85 dataIface.getSystemType().c_str())); 86 87 // Have to choose something, just use informational. 88 _eventSeverity = 0; 89 } 90 } 91 92 // TODO: ibm-dev/dev/#1144 Handle manufacturing sev & action flags 93 94 if (entry.eventType) 95 { 96 _eventType = *entry.eventType; 97 } 98 else 99 { 100 // There are different default event types for info errors 101 // vs non info ones. 102 auto sevType = static_cast<SeverityType>(_eventSeverity & 0xF0); 103 104 _eventType = (sevType == SeverityType::nonError) 105 ? static_cast<uint8_t>(EventType::miscInformational) 106 : static_cast<uint8_t>(EventType::notApplicable); 107 } 108 109 _reserved4Byte1 = 0; 110 111 // No uses for problem domain or vector 112 _problemDomain = 0; 113 _problemVector = 0; 114 115 // These will be cleaned up later in pel_rules::check() 116 _actionFlags = entry.actionFlags.value_or(0); 117 118 _states = 0; 119 120 _valid = true; 121 } 122 123 UserHeader::UserHeader(Stream& pel) 124 { 125 try 126 { 127 unflatten(pel); 128 validate(); 129 } 130 catch (const std::exception& e) 131 { 132 log<level::ERR>("Cannot unflatten user header", 133 entry("ERROR=%s", e.what())); 134 _valid = false; 135 } 136 } 137 138 void UserHeader::validate() 139 { 140 bool failed = false; 141 if (header().id != static_cast<uint16_t>(SectionID::userHeader)) 142 { 143 log<level::ERR>("Invalid user header section ID", 144 entry("ID=0x%X", header().id)); 145 failed = true; 146 } 147 148 if (header().version != userHeaderVersion) 149 { 150 log<level::ERR>("Invalid user header version", 151 entry("VERSION=0x%X", header().version)); 152 failed = true; 153 } 154 155 _valid = (failed) ? false : true; 156 } 157 158 std::optional<std::string> UserHeader::getJSON() const 159 { 160 std::string severity; 161 std::string subsystem; 162 std::string eventScope; 163 std::string eventType; 164 std::vector<std::string> actionFlags; 165 severity = pv::getValue(_eventSeverity, pel_values::severityValues); 166 subsystem = pv::getValue(_eventSubsystem, pel_values::subsystemValues); 167 eventScope = pv::getValue(_eventScope, pel_values::eventScopeValues); 168 eventType = pv::getValue(_eventType, pel_values::eventTypeValues); 169 actionFlags = 170 pv::getValuesBitwise(_actionFlags, pel_values::actionFlagsValues); 171 172 std::string hostState{"Invalid"}; 173 auto iter = pv::transmissionStates.find( 174 static_cast<TransmissionState>(hostTransmissionState())); 175 if (iter != pv::transmissionStates.end()) 176 { 177 hostState = iter->second; 178 } 179 180 std::string uh; 181 jsonInsert(uh, pv::sectionVer, getNumberString("%d", userHeaderVersion), 1); 182 jsonInsert(uh, pv::subSection, getNumberString("%d", _header.subType), 1); 183 jsonInsert(uh, "Log Committed by", 184 getNumberString("0x%X", _header.componentID), 1); 185 jsonInsert(uh, "Subsystem", subsystem, 1); 186 jsonInsert(uh, "Event Scope", eventScope, 1); 187 jsonInsert(uh, "Event Severity", severity, 1); 188 jsonInsert(uh, "Event Type", eventType, 1); 189 jsonInsertArray(uh, "Action Flags", actionFlags, 1); 190 jsonInsert(uh, "Host Transmission", hostState, 1); 191 uh.erase(uh.size() - 2); 192 return uh; 193 } 194 195 std::optional<uint8_t> UserHeader::getSeverity( 196 const std::vector<message::RegistrySeverity>& severities, 197 const std::string& systemType) const 198 { 199 const uint8_t* s = nullptr; 200 201 // Find the severity to use for this system type, or use the default 202 // entry (where no system type is specified). 203 for (const auto& sev : severities) 204 { 205 if (sev.system == systemType) 206 { 207 s = &sev.severity; 208 break; 209 } 210 else if (sev.system.empty()) 211 { 212 s = &sev.severity; 213 } 214 } 215 216 if (s) 217 { 218 return *s; 219 } 220 221 return std::nullopt; 222 } 223 224 } // namespace pels 225 } // namespace openpower 226