1711d51d8SMatt Spinler /** 2711d51d8SMatt Spinler * Copyright © 2019 IBM Corporation 3711d51d8SMatt Spinler * 4711d51d8SMatt Spinler * Licensed under the Apache License, Version 2.0 (the "License"); 5711d51d8SMatt Spinler * you may not use this file except in compliance with the License. 6711d51d8SMatt Spinler * You may obtain a copy of the License at 7711d51d8SMatt Spinler * 8711d51d8SMatt Spinler * http://www.apache.org/licenses/LICENSE-2.0 9711d51d8SMatt Spinler * 10711d51d8SMatt Spinler * Unless required by applicable law or agreed to in writing, software 11711d51d8SMatt Spinler * distributed under the License is distributed on an "AS IS" BASIS, 12711d51d8SMatt Spinler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13711d51d8SMatt Spinler * See the License for the specific language governing permissions and 14711d51d8SMatt Spinler * limitations under the License. 15711d51d8SMatt Spinler */ 1603c1d915SMatt Spinler #include "user_header.hpp" 1703c1d915SMatt Spinler 18600d15afSHarisuddin Mohamed Isa #include "json_utils.hpp" 191a94cc38SMatt Spinler #include "pel_types.hpp" 20c1489351SAatir #include "pel_values.hpp" 21fdb6a202SMatt Spinler #include "severity.hpp" 221a94cc38SMatt Spinler 23ad0e0476SAatir Manzur #include <iostream> 2403c1d915SMatt Spinler #include <phosphor-logging/log.hpp> 2503c1d915SMatt Spinler 2603c1d915SMatt Spinler namespace openpower 2703c1d915SMatt Spinler { 2803c1d915SMatt Spinler namespace pels 2903c1d915SMatt Spinler { 3003c1d915SMatt Spinler 31c1489351SAatir namespace pv = openpower::pels::pel_values; 3203c1d915SMatt Spinler using namespace phosphor::logging; 3303c1d915SMatt Spinler 34cf5a8d0fSMatt Spinler void UserHeader::unflatten(Stream& stream) 3503c1d915SMatt Spinler { 36cf5a8d0fSMatt Spinler stream >> _header >> _eventSubsystem >> _eventScope >> _eventSeverity >> 37cf5a8d0fSMatt Spinler _eventType >> _reserved4Byte1 >> _problemDomain >> _problemVector >> 38eb111447SMatt Spinler _actionFlags >> _states; 3903c1d915SMatt Spinler } 4003c1d915SMatt Spinler 410688545bSMatt Spinler void UserHeader::flatten(Stream& stream) const 4203c1d915SMatt Spinler { 43cf5a8d0fSMatt Spinler stream << _header << _eventSubsystem << _eventScope << _eventSeverity 44cf5a8d0fSMatt Spinler << _eventType << _reserved4Byte1 << _problemDomain << _problemVector 45eb111447SMatt Spinler << _actionFlags << _states; 4603c1d915SMatt Spinler } 4703c1d915SMatt Spinler 48fdb6a202SMatt Spinler UserHeader::UserHeader(const message::Entry& entry, 49aadccc85SMatt Spinler phosphor::logging::Entry::Level severity, 50aadccc85SMatt Spinler const DataInterfaceBase& dataIface) 51fdb6a202SMatt Spinler { 52fdb6a202SMatt Spinler _header.id = static_cast<uint16_t>(SectionID::userHeader); 53fdb6a202SMatt Spinler _header.size = UserHeader::flattenedSize(); 54fdb6a202SMatt Spinler _header.version = userHeaderVersion; 55fdb6a202SMatt Spinler _header.subType = 0; 56fdb6a202SMatt Spinler _header.componentID = static_cast<uint16_t>(ComponentID::phosphorLogging); 57fdb6a202SMatt Spinler 58fdb6a202SMatt Spinler _eventSubsystem = entry.subsystem; 59fdb6a202SMatt Spinler 60fdb6a202SMatt Spinler _eventScope = entry.eventScope.value_or( 61fdb6a202SMatt Spinler static_cast<uint8_t>(EventScope::entirePlatform)); 62fdb6a202SMatt Spinler 63fdb6a202SMatt Spinler // Get the severity from the registry if it's there, otherwise get it 64fdb6a202SMatt Spinler // from the OpenBMC event log severity value. 65aadccc85SMatt Spinler if (!entry.severity) 66aadccc85SMatt Spinler { 67aadccc85SMatt Spinler _eventSeverity = convertOBMCSeverityToPEL(severity); 68aadccc85SMatt Spinler } 69aadccc85SMatt Spinler else 70aadccc85SMatt Spinler { 71aadccc85SMatt Spinler // Find the severity possibly dependent on the system type. 72aadccc85SMatt Spinler auto sev = 73*6ea4d5f7SMatt Spinler getSeverity(entry.severity.value(), dataIface.getSystemNames()); 74aadccc85SMatt Spinler if (sev) 75aadccc85SMatt Spinler { 76aadccc85SMatt Spinler _eventSeverity = *sev; 77aadccc85SMatt Spinler } 78aadccc85SMatt Spinler else 79aadccc85SMatt Spinler { 80aadccc85SMatt Spinler // Someone screwed up the message registry. 81*6ea4d5f7SMatt Spinler std::string types; 82*6ea4d5f7SMatt Spinler const auto& compatibles = dataIface.getSystemNames(); 83*6ea4d5f7SMatt Spinler std::for_each(compatibles.begin(), compatibles.end(), 84*6ea4d5f7SMatt Spinler [&types](const auto& t) { types += t + '|'; }); 85*6ea4d5f7SMatt Spinler 86aadccc85SMatt Spinler log<level::ERR>( 87*6ea4d5f7SMatt Spinler "No severity entry found for this error and system name", 88aadccc85SMatt Spinler phosphor::logging::entry("ERROR=%s", entry.name.c_str()), 89*6ea4d5f7SMatt Spinler phosphor::logging::entry("SYSTEMNAMES=%s", types.c_str())); 90aadccc85SMatt Spinler 91aadccc85SMatt Spinler // Have to choose something, just use informational. 92aadccc85SMatt Spinler _eventSeverity = 0; 93aadccc85SMatt Spinler } 94aadccc85SMatt Spinler } 95fdb6a202SMatt Spinler 96fdb6a202SMatt Spinler // TODO: ibm-dev/dev/#1144 Handle manufacturing sev & action flags 97fdb6a202SMatt Spinler 98f1e85e20SMatt Spinler if (entry.eventType) 99f1e85e20SMatt Spinler { 100f1e85e20SMatt Spinler _eventType = *entry.eventType; 101f1e85e20SMatt Spinler } 102f1e85e20SMatt Spinler else 103f1e85e20SMatt Spinler { 104f1e85e20SMatt Spinler // There are different default event types for info errors 105f1e85e20SMatt Spinler // vs non info ones. 106f1e85e20SMatt Spinler auto sevType = static_cast<SeverityType>(_eventSeverity & 0xF0); 107f1e85e20SMatt Spinler 108f1e85e20SMatt Spinler _eventType = (sevType == SeverityType::nonError) 109f1e85e20SMatt Spinler ? static_cast<uint8_t>(EventType::miscInformational) 110f1e85e20SMatt Spinler : static_cast<uint8_t>(EventType::notApplicable); 111f1e85e20SMatt Spinler } 112fdb6a202SMatt Spinler 113fdb6a202SMatt Spinler _reserved4Byte1 = 0; 114fdb6a202SMatt Spinler 115fdb6a202SMatt Spinler // No uses for problem domain or vector 116fdb6a202SMatt Spinler _problemDomain = 0; 117fdb6a202SMatt Spinler _problemVector = 0; 118fdb6a202SMatt Spinler 119f1e85e20SMatt Spinler // These will be cleaned up later in pel_rules::check() 120e07f915bSMatt Spinler _actionFlags = entry.actionFlags.value_or(0); 121fdb6a202SMatt Spinler 122eb111447SMatt Spinler _states = 0; 123fdb6a202SMatt Spinler 124fdb6a202SMatt Spinler _valid = true; 125fdb6a202SMatt Spinler } 126fdb6a202SMatt Spinler 12703c1d915SMatt Spinler UserHeader::UserHeader(Stream& pel) 12803c1d915SMatt Spinler { 12903c1d915SMatt Spinler try 13003c1d915SMatt Spinler { 131cf5a8d0fSMatt Spinler unflatten(pel); 13203c1d915SMatt Spinler validate(); 13303c1d915SMatt Spinler } 13403c1d915SMatt Spinler catch (const std::exception& e) 13503c1d915SMatt Spinler { 13603c1d915SMatt Spinler log<level::ERR>("Cannot unflatten user header", 13703c1d915SMatt Spinler entry("ERROR=%s", e.what())); 13803c1d915SMatt Spinler _valid = false; 13903c1d915SMatt Spinler } 14003c1d915SMatt Spinler } 14103c1d915SMatt Spinler 14203c1d915SMatt Spinler void UserHeader::validate() 14303c1d915SMatt Spinler { 14403c1d915SMatt Spinler bool failed = false; 1451a94cc38SMatt Spinler if (header().id != static_cast<uint16_t>(SectionID::userHeader)) 14603c1d915SMatt Spinler { 14703c1d915SMatt Spinler log<level::ERR>("Invalid user header section ID", 14803c1d915SMatt Spinler entry("ID=0x%X", header().id)); 14903c1d915SMatt Spinler failed = true; 15003c1d915SMatt Spinler } 15103c1d915SMatt Spinler 15203c1d915SMatt Spinler if (header().version != userHeaderVersion) 15303c1d915SMatt Spinler { 15403c1d915SMatt Spinler log<level::ERR>("Invalid user header version", 15503c1d915SMatt Spinler entry("VERSION=0x%X", header().version)); 15603c1d915SMatt Spinler failed = true; 15703c1d915SMatt Spinler } 15803c1d915SMatt Spinler 15903c1d915SMatt Spinler _valid = (failed) ? false : true; 16003c1d915SMatt Spinler } 16103c1d915SMatt Spinler 162ad0e0476SAatir Manzur std::optional<std::string> UserHeader::getJSON() const 163ad0e0476SAatir Manzur { 164ad0e0476SAatir Manzur std::string severity; 165ad0e0476SAatir Manzur std::string subsystem; 166ad0e0476SAatir Manzur std::string eventScope; 167ad0e0476SAatir Manzur std::string eventType; 168600d15afSHarisuddin Mohamed Isa std::vector<std::string> actionFlags; 169c1489351SAatir severity = pv::getValue(_eventSeverity, pel_values::severityValues); 170c1489351SAatir subsystem = pv::getValue(_eventSubsystem, pel_values::subsystemValues); 171c1489351SAatir eventScope = pv::getValue(_eventScope, pel_values::eventScopeValues); 172c1489351SAatir eventType = pv::getValue(_eventType, pel_values::eventTypeValues); 173600d15afSHarisuddin Mohamed Isa actionFlags = 174600d15afSHarisuddin Mohamed Isa pv::getValuesBitwise(_actionFlags, pel_values::actionFlagsValues); 175455587e5SMatt Spinler 176455587e5SMatt Spinler std::string hostState{"Invalid"}; 177455587e5SMatt Spinler auto iter = pv::transmissionStates.find( 178455587e5SMatt Spinler static_cast<TransmissionState>(hostTransmissionState())); 179455587e5SMatt Spinler if (iter != pv::transmissionStates.end()) 180455587e5SMatt Spinler { 181455587e5SMatt Spinler hostState = iter->second; 182455587e5SMatt Spinler } 183455587e5SMatt Spinler 184600d15afSHarisuddin Mohamed Isa std::string uh; 185bebeb948SHarisuddin Mohamed Isa jsonInsert(uh, pv::sectionVer, getNumberString("%d", userHeaderVersion), 1); 186bebeb948SHarisuddin Mohamed Isa jsonInsert(uh, pv::subSection, getNumberString("%d", _header.subType), 1); 187bebeb948SHarisuddin Mohamed Isa jsonInsert(uh, "Log Committed by", 188bebeb948SHarisuddin Mohamed Isa getNumberString("0x%X", _header.componentID), 1); 189600d15afSHarisuddin Mohamed Isa jsonInsert(uh, "Subsystem", subsystem, 1); 190600d15afSHarisuddin Mohamed Isa jsonInsert(uh, "Event Scope", eventScope, 1); 191600d15afSHarisuddin Mohamed Isa jsonInsert(uh, "Event Severity", severity, 1); 192600d15afSHarisuddin Mohamed Isa jsonInsert(uh, "Event Type", eventType, 1); 193600d15afSHarisuddin Mohamed Isa jsonInsertArray(uh, "Action Flags", actionFlags, 1); 194455587e5SMatt Spinler jsonInsert(uh, "Host Transmission", hostState, 1); 195600d15afSHarisuddin Mohamed Isa uh.erase(uh.size() - 2); 196ad0e0476SAatir Manzur return uh; 197ad0e0476SAatir Manzur } 198aadccc85SMatt Spinler 199aadccc85SMatt Spinler std::optional<uint8_t> UserHeader::getSeverity( 200aadccc85SMatt Spinler const std::vector<message::RegistrySeverity>& severities, 201*6ea4d5f7SMatt Spinler const std::vector<std::string>& systemNames) const 202aadccc85SMatt Spinler { 203aadccc85SMatt Spinler const uint8_t* s = nullptr; 204aadccc85SMatt Spinler 205aadccc85SMatt Spinler // Find the severity to use for this system type, or use the default 206aadccc85SMatt Spinler // entry (where no system type is specified). 207aadccc85SMatt Spinler for (const auto& sev : severities) 208aadccc85SMatt Spinler { 209*6ea4d5f7SMatt Spinler if (std::find(systemNames.begin(), systemNames.end(), sev.system) != 210*6ea4d5f7SMatt Spinler systemNames.end()) 211aadccc85SMatt Spinler { 212aadccc85SMatt Spinler s = &sev.severity; 213aadccc85SMatt Spinler break; 214aadccc85SMatt Spinler } 215aadccc85SMatt Spinler else if (sev.system.empty()) 216aadccc85SMatt Spinler { 217aadccc85SMatt Spinler s = &sev.severity; 218aadccc85SMatt Spinler } 219aadccc85SMatt Spinler } 220aadccc85SMatt Spinler 221aadccc85SMatt Spinler if (s) 222aadccc85SMatt Spinler { 223aadccc85SMatt Spinler return *s; 224aadccc85SMatt Spinler } 225aadccc85SMatt Spinler 226aadccc85SMatt Spinler return std::nullopt; 227aadccc85SMatt Spinler } 228aadccc85SMatt Spinler 22903c1d915SMatt Spinler } // namespace pels 23003c1d915SMatt Spinler } // namespace openpower 231