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, 506b3f345bSVijay Lobo const AdditionalData& additionalData, 51aadccc85SMatt Spinler const DataInterfaceBase& dataIface) 52fdb6a202SMatt Spinler { 53fdb6a202SMatt Spinler _header.id = static_cast<uint16_t>(SectionID::userHeader); 54fdb6a202SMatt Spinler _header.size = UserHeader::flattenedSize(); 55fdb6a202SMatt Spinler _header.version = userHeaderVersion; 56fdb6a202SMatt Spinler _header.subType = 0; 57fdb6a202SMatt Spinler _header.componentID = static_cast<uint16_t>(ComponentID::phosphorLogging); 58fdb6a202SMatt Spinler 59fdb6a202SMatt Spinler _eventSubsystem = entry.subsystem; 60fdb6a202SMatt Spinler 61fdb6a202SMatt Spinler _eventScope = entry.eventScope.value_or( 62fdb6a202SMatt Spinler static_cast<uint8_t>(EventScope::entirePlatform)); 63fdb6a202SMatt Spinler 643b8ed7f2SSumit Kumar { 653b8ed7f2SSumit Kumar bool mfgSevStatus = false; 663b8ed7f2SSumit Kumar bool mfgActionFlagStatus = false; 673b8ed7f2SSumit Kumar std::optional<uint8_t> sev = std::nullopt; 683b8ed7f2SSumit Kumar uint16_t val = 0; 693b8ed7f2SSumit Kumar 703b8ed7f2SSumit Kumar // Get the mfg severity & action flags 713b8ed7f2SSumit Kumar if (entry.mfgSeverity || entry.mfgActionFlags) 723b8ed7f2SSumit Kumar { 733b8ed7f2SSumit Kumar if (entry.mfgSeverity) 743b8ed7f2SSumit Kumar { 753b8ed7f2SSumit Kumar // Find the mf severity possibly dependent on the system type. 763b8ed7f2SSumit Kumar sev = getSeverity(entry.mfgSeverity.value(), dataIface); 773b8ed7f2SSumit Kumar } 783b8ed7f2SSumit Kumar 793b8ed7f2SSumit Kumar if (entry.mfgActionFlags) 803b8ed7f2SSumit Kumar { 813b8ed7f2SSumit Kumar // Find the mfg action flags 823b8ed7f2SSumit Kumar val = entry.mfgActionFlags.value(); 833b8ed7f2SSumit Kumar } 843b8ed7f2SSumit Kumar 853b8ed7f2SSumit Kumar if (sev || val) 863b8ed7f2SSumit Kumar { 873b8ed7f2SSumit Kumar bool mfgProp = dataIface.getQuiesceOnError(); 883b8ed7f2SSumit Kumar if (mfgProp) 893b8ed7f2SSumit Kumar { 903b8ed7f2SSumit Kumar if (sev) 913b8ed7f2SSumit Kumar { 923b8ed7f2SSumit Kumar _eventSeverity = *sev; 933b8ed7f2SSumit Kumar mfgSevStatus = true; 943b8ed7f2SSumit Kumar } 953b8ed7f2SSumit Kumar 963b8ed7f2SSumit Kumar if (val) 973b8ed7f2SSumit Kumar { 983b8ed7f2SSumit Kumar _actionFlags = val; 993b8ed7f2SSumit Kumar mfgActionFlagStatus = true; 1003b8ed7f2SSumit Kumar } 1013b8ed7f2SSumit Kumar } 1023b8ed7f2SSumit Kumar } 1033b8ed7f2SSumit Kumar } 1043b8ed7f2SSumit Kumar 1053b8ed7f2SSumit Kumar if (!mfgSevStatus) 1063b8ed7f2SSumit Kumar { 1073b8ed7f2SSumit Kumar // Get the severity from the registry if it's there, otherwise get 1083b8ed7f2SSumit Kumar // it from the OpenBMC event log severity value. 109aadccc85SMatt Spinler if (!entry.severity) 110aadccc85SMatt Spinler { 111aadccc85SMatt Spinler _eventSeverity = convertOBMCSeverityToPEL(severity); 112aadccc85SMatt Spinler } 113aadccc85SMatt Spinler else 114aadccc85SMatt Spinler { 115aadccc85SMatt Spinler // Find the severity possibly dependent on the system type. 1161ab6696fSMatt Spinler auto sev = getSeverity(entry.severity.value(), dataIface); 117aadccc85SMatt Spinler if (sev) 118aadccc85SMatt Spinler { 119aadccc85SMatt Spinler _eventSeverity = *sev; 120aadccc85SMatt Spinler } 121aadccc85SMatt Spinler else 122aadccc85SMatt Spinler { 1231ab6696fSMatt Spinler // Either someone screwed up the message registry 1241ab6696fSMatt Spinler // or getSystemNames failed. 1256ea4d5f7SMatt Spinler std::string types; 126aadccc85SMatt Spinler log<level::ERR>( 1271ab6696fSMatt Spinler "Failed finding the severity in the message registry", 1283b8ed7f2SSumit Kumar phosphor::logging::entry("ERROR=%s", 1293b8ed7f2SSumit Kumar entry.name.c_str())); 130aadccc85SMatt Spinler 131aadccc85SMatt Spinler // Have to choose something, just use informational. 132aadccc85SMatt Spinler _eventSeverity = 0; 133aadccc85SMatt Spinler } 134aadccc85SMatt Spinler } 1353b8ed7f2SSumit Kumar } 136fdb6a202SMatt Spinler 1376b3f345bSVijay Lobo // Convert Critical error (0x50) to Critical Error-System Termination 1386b3f345bSVijay Lobo // (0x51), if the AdditionalData is set to SYSTEM_TERM 1396b3f345bSVijay Lobo auto sevLevel = additionalData.getValue("SEVERITY_DETAIL"); 1406b3f345bSVijay Lobo if ((_eventSeverity & 0xF0) == 0x50) 1416b3f345bSVijay Lobo { 1426b3f345bSVijay Lobo if (sevLevel.value_or("") == "SYSTEM_TERM") 1436b3f345bSVijay Lobo { 1446b3f345bSVijay Lobo // Change to Critical Error, System Termination 1456b3f345bSVijay Lobo _eventSeverity = 0x51; 1466b3f345bSVijay Lobo } 1476b3f345bSVijay Lobo } 1486b3f345bSVijay Lobo 149f1e85e20SMatt Spinler if (entry.eventType) 150f1e85e20SMatt Spinler { 151f1e85e20SMatt Spinler _eventType = *entry.eventType; 152f1e85e20SMatt Spinler } 153f1e85e20SMatt Spinler else 154f1e85e20SMatt Spinler { 155f1e85e20SMatt Spinler // There are different default event types for info errors 156f1e85e20SMatt Spinler // vs non info ones. 157f1e85e20SMatt Spinler auto sevType = static_cast<SeverityType>(_eventSeverity & 0xF0); 1583b8ed7f2SSumit Kumar _eventType = 1593b8ed7f2SSumit Kumar (sevType == SeverityType::nonError) 160f1e85e20SMatt Spinler ? static_cast<uint8_t>(EventType::miscInformational) 161f1e85e20SMatt Spinler : static_cast<uint8_t>(EventType::notApplicable); 162f1e85e20SMatt Spinler } 163fdb6a202SMatt Spinler 164fdb6a202SMatt Spinler _reserved4Byte1 = 0; 165fdb6a202SMatt Spinler 166fdb6a202SMatt Spinler // No uses for problem domain or vector 167fdb6a202SMatt Spinler _problemDomain = 0; 168fdb6a202SMatt Spinler _problemVector = 0; 169fdb6a202SMatt Spinler 1701f93c590SMatt Spinler // These will be set in pel_rules::check() if they're still 1711f93c590SMatt Spinler // at the default value. 1723b8ed7f2SSumit Kumar if (!mfgActionFlagStatus) 1733b8ed7f2SSumit Kumar { 1741f93c590SMatt Spinler _actionFlags = entry.actionFlags.value_or(actionFlagsDefault); 1753b8ed7f2SSumit Kumar } 176fdb6a202SMatt Spinler 177eb111447SMatt Spinler _states = 0; 178fdb6a202SMatt Spinler 179fdb6a202SMatt Spinler _valid = true; 180fdb6a202SMatt Spinler } 1813b8ed7f2SSumit Kumar } 182fdb6a202SMatt Spinler 18303c1d915SMatt Spinler UserHeader::UserHeader(Stream& pel) 18403c1d915SMatt Spinler { 18503c1d915SMatt Spinler try 18603c1d915SMatt Spinler { 187cf5a8d0fSMatt Spinler unflatten(pel); 18803c1d915SMatt Spinler validate(); 18903c1d915SMatt Spinler } 19003c1d915SMatt Spinler catch (const std::exception& e) 19103c1d915SMatt Spinler { 19203c1d915SMatt Spinler log<level::ERR>("Cannot unflatten user header", 19303c1d915SMatt Spinler entry("ERROR=%s", e.what())); 19403c1d915SMatt Spinler _valid = false; 19503c1d915SMatt Spinler } 19603c1d915SMatt Spinler } 19703c1d915SMatt Spinler 19803c1d915SMatt Spinler void UserHeader::validate() 19903c1d915SMatt Spinler { 20003c1d915SMatt Spinler bool failed = false; 2011a94cc38SMatt Spinler if (header().id != static_cast<uint16_t>(SectionID::userHeader)) 20203c1d915SMatt Spinler { 20303c1d915SMatt Spinler log<level::ERR>("Invalid user header section ID", 20403c1d915SMatt Spinler entry("ID=0x%X", header().id)); 20503c1d915SMatt Spinler failed = true; 20603c1d915SMatt Spinler } 20703c1d915SMatt Spinler 20803c1d915SMatt Spinler if (header().version != userHeaderVersion) 20903c1d915SMatt Spinler { 21003c1d915SMatt Spinler log<level::ERR>("Invalid user header version", 21103c1d915SMatt Spinler entry("VERSION=0x%X", header().version)); 21203c1d915SMatt Spinler failed = true; 21303c1d915SMatt Spinler } 21403c1d915SMatt Spinler 21503c1d915SMatt Spinler _valid = (failed) ? false : true; 21603c1d915SMatt Spinler } 21703c1d915SMatt Spinler 218ad0e0476SAatir Manzur std::optional<std::string> UserHeader::getJSON() const 219ad0e0476SAatir Manzur { 220ad0e0476SAatir Manzur std::string severity; 221ad0e0476SAatir Manzur std::string subsystem; 222ad0e0476SAatir Manzur std::string eventScope; 223ad0e0476SAatir Manzur std::string eventType; 224600d15afSHarisuddin Mohamed Isa std::vector<std::string> actionFlags; 225c1489351SAatir severity = pv::getValue(_eventSeverity, pel_values::severityValues); 226c1489351SAatir subsystem = pv::getValue(_eventSubsystem, pel_values::subsystemValues); 227c1489351SAatir eventScope = pv::getValue(_eventScope, pel_values::eventScopeValues); 228c1489351SAatir eventType = pv::getValue(_eventType, pel_values::eventTypeValues); 229600d15afSHarisuddin Mohamed Isa actionFlags = 230600d15afSHarisuddin Mohamed Isa pv::getValuesBitwise(_actionFlags, pel_values::actionFlagsValues); 231455587e5SMatt Spinler 232455587e5SMatt Spinler std::string hostState{"Invalid"}; 233*2fb10211SVijay Lobo std::string hmcState{"Invalid"}; 234455587e5SMatt Spinler auto iter = pv::transmissionStates.find( 235455587e5SMatt Spinler static_cast<TransmissionState>(hostTransmissionState())); 236455587e5SMatt Spinler if (iter != pv::transmissionStates.end()) 237455587e5SMatt Spinler { 238455587e5SMatt Spinler hostState = iter->second; 239455587e5SMatt Spinler } 240*2fb10211SVijay Lobo auto iter1 = pv::transmissionStates.find( 241*2fb10211SVijay Lobo static_cast<TransmissionState>(hmcTransmissionState())); 242*2fb10211SVijay Lobo if (iter1 != pv::transmissionStates.end()) 243*2fb10211SVijay Lobo { 244*2fb10211SVijay Lobo hmcState = iter1->second; 245*2fb10211SVijay Lobo } 246455587e5SMatt Spinler 247600d15afSHarisuddin Mohamed Isa std::string uh; 248bebeb948SHarisuddin Mohamed Isa jsonInsert(uh, pv::sectionVer, getNumberString("%d", userHeaderVersion), 1); 249bebeb948SHarisuddin Mohamed Isa jsonInsert(uh, pv::subSection, getNumberString("%d", _header.subType), 1); 250bebeb948SHarisuddin Mohamed Isa jsonInsert(uh, "Log Committed by", 251bebeb948SHarisuddin Mohamed Isa getNumberString("0x%X", _header.componentID), 1); 252600d15afSHarisuddin Mohamed Isa jsonInsert(uh, "Subsystem", subsystem, 1); 253600d15afSHarisuddin Mohamed Isa jsonInsert(uh, "Event Scope", eventScope, 1); 254600d15afSHarisuddin Mohamed Isa jsonInsert(uh, "Event Severity", severity, 1); 255600d15afSHarisuddin Mohamed Isa jsonInsert(uh, "Event Type", eventType, 1); 256600d15afSHarisuddin Mohamed Isa jsonInsertArray(uh, "Action Flags", actionFlags, 1); 257455587e5SMatt Spinler jsonInsert(uh, "Host Transmission", hostState, 1); 258*2fb10211SVijay Lobo jsonInsert(uh, "HMC Transmission", hmcState, 1); 259600d15afSHarisuddin Mohamed Isa uh.erase(uh.size() - 2); 260ad0e0476SAatir Manzur return uh; 261ad0e0476SAatir Manzur } 262aadccc85SMatt Spinler 263aadccc85SMatt Spinler std::optional<uint8_t> UserHeader::getSeverity( 264aadccc85SMatt Spinler const std::vector<message::RegistrySeverity>& severities, 2651ab6696fSMatt Spinler const DataInterfaceBase& dataIface) const 266aadccc85SMatt Spinler { 267aadccc85SMatt Spinler const uint8_t* s = nullptr; 2681ab6696fSMatt Spinler std::vector<std::string> systemNames; 2691ab6696fSMatt Spinler 2701ab6696fSMatt Spinler // getSystemNames makes D-Bus calls, so only call it if we 2711ab6696fSMatt Spinler // know we'll need it because there is a system name in the sev list 2721ab6696fSMatt Spinler if (std::any_of(severities.begin(), severities.end(), 2731ab6696fSMatt Spinler [](const auto& sev) { return !sev.system.empty(); })) 2741ab6696fSMatt Spinler { 2751ab6696fSMatt Spinler try 2761ab6696fSMatt Spinler { 2771ab6696fSMatt Spinler systemNames = dataIface.getSystemNames(); 2781ab6696fSMatt Spinler } 2791ab6696fSMatt Spinler catch (const std::exception& e) 2801ab6696fSMatt Spinler { 2811ab6696fSMatt Spinler log<level::ERR>("Failed trying to look up system names on D-Bus", 2821ab6696fSMatt Spinler entry("ERROR=%s", e.what())); 2831ab6696fSMatt Spinler return std::nullopt; 2841ab6696fSMatt Spinler } 2851ab6696fSMatt Spinler } 286aadccc85SMatt Spinler 287aadccc85SMatt Spinler // Find the severity to use for this system type, or use the default 288aadccc85SMatt Spinler // entry (where no system type is specified). 289aadccc85SMatt Spinler for (const auto& sev : severities) 290aadccc85SMatt Spinler { 2916ea4d5f7SMatt Spinler if (std::find(systemNames.begin(), systemNames.end(), sev.system) != 2926ea4d5f7SMatt Spinler systemNames.end()) 293aadccc85SMatt Spinler { 294aadccc85SMatt Spinler s = &sev.severity; 295aadccc85SMatt Spinler break; 296aadccc85SMatt Spinler } 297aadccc85SMatt Spinler else if (sev.system.empty()) 298aadccc85SMatt Spinler { 299aadccc85SMatt Spinler s = &sev.severity; 300aadccc85SMatt Spinler } 301aadccc85SMatt Spinler } 302aadccc85SMatt Spinler 303aadccc85SMatt Spinler if (s) 304aadccc85SMatt Spinler { 305aadccc85SMatt Spinler return *s; 306aadccc85SMatt Spinler } 307aadccc85SMatt Spinler 308aadccc85SMatt Spinler return std::nullopt; 309aadccc85SMatt Spinler } 310aadccc85SMatt Spinler 31103c1d915SMatt Spinler } // namespace pels 31203c1d915SMatt Spinler } // namespace openpower 313