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
235bc26533SArya K Padman #include <phosphor-logging/lg2.hpp>
2403c1d915SMatt Spinler
251aa90d49SJayanth Othayoth #include <format>
262544b419SPatrick Williams #include <iostream>
272544b419SPatrick Williams
2803c1d915SMatt Spinler namespace openpower
2903c1d915SMatt Spinler {
3003c1d915SMatt Spinler namespace pels
3103c1d915SMatt Spinler {
3203c1d915SMatt Spinler
33c1489351SAatir namespace pv = openpower::pels::pel_values;
3403c1d915SMatt Spinler
unflatten(Stream & stream)35cf5a8d0fSMatt Spinler void UserHeader::unflatten(Stream& stream)
3603c1d915SMatt Spinler {
37cf5a8d0fSMatt Spinler stream >> _header >> _eventSubsystem >> _eventScope >> _eventSeverity >>
38cf5a8d0fSMatt Spinler _eventType >> _reserved4Byte1 >> _problemDomain >> _problemVector >>
39eb111447SMatt Spinler _actionFlags >> _states;
4003c1d915SMatt Spinler }
4103c1d915SMatt Spinler
flatten(Stream & stream) const420688545bSMatt Spinler void UserHeader::flatten(Stream& stream) const
4303c1d915SMatt Spinler {
44cf5a8d0fSMatt Spinler stream << _header << _eventSubsystem << _eventScope << _eventSeverity
45cf5a8d0fSMatt Spinler << _eventType << _reserved4Byte1 << _problemDomain << _problemVector
46eb111447SMatt Spinler << _actionFlags << _states;
4703c1d915SMatt Spinler }
4803c1d915SMatt Spinler
UserHeader(const message::Entry & entry,phosphor::logging::Entry::Level severity,const AdditionalData & additionalData,const DataInterfaceBase & dataIface)49fdb6a202SMatt Spinler UserHeader::UserHeader(const message::Entry& entry,
50aadccc85SMatt Spinler phosphor::logging::Entry::Level severity,
516b3f345bSVijay Lobo const AdditionalData& additionalData,
52aadccc85SMatt Spinler const DataInterfaceBase& dataIface)
53fdb6a202SMatt Spinler {
54fdb6a202SMatt Spinler _header.id = static_cast<uint16_t>(SectionID::userHeader);
55fdb6a202SMatt Spinler _header.size = UserHeader::flattenedSize();
56fdb6a202SMatt Spinler _header.version = userHeaderVersion;
57fdb6a202SMatt Spinler _header.subType = 0;
58fdb6a202SMatt Spinler _header.componentID = static_cast<uint16_t>(ComponentID::phosphorLogging);
59fdb6a202SMatt Spinler
6023970b0dSMatt Spinler std::optional<uint8_t> subsys;
61fdb6a202SMatt Spinler
6250bfa69aSSumit Kumar // Check for additional data - PEL_SUBSYSTEM
6350bfa69aSSumit Kumar auto ss = additionalData.getValue("PEL_SUBSYSTEM");
6450bfa69aSSumit Kumar if (ss)
6550bfa69aSSumit Kumar {
6650bfa69aSSumit Kumar auto eventSubsystem = std::stoul(*ss, NULL, 16);
67*075c7923SPatrick Williams std::string subsystemString =
68*075c7923SPatrick Williams pv::getValue(eventSubsystem, pel_values::subsystemValues);
6923970b0dSMatt Spinler if (subsystemString == "invalid")
7050bfa69aSSumit Kumar {
715bc26533SArya K Padman lg2::warning(
725bc26533SArya K Padman "UH: Invalid SubSystem value in PEL_SUBSYSTEM: {PEL_SUBSYSTEM}",
735bc26533SArya K Padman "PEL_SUBSYSTEM", lg2::hex, eventSubsystem);
7450bfa69aSSumit Kumar }
7550bfa69aSSumit Kumar else
7650bfa69aSSumit Kumar {
7723970b0dSMatt Spinler subsys = eventSubsystem;
7850bfa69aSSumit Kumar }
7950bfa69aSSumit Kumar }
8023970b0dSMatt Spinler else
8123970b0dSMatt Spinler {
8223970b0dSMatt Spinler subsys = entry.subsystem;
8323970b0dSMatt Spinler }
8423970b0dSMatt Spinler
8523970b0dSMatt Spinler if (subsys)
8623970b0dSMatt Spinler {
8723970b0dSMatt Spinler _eventSubsystem = *subsys;
8823970b0dSMatt Spinler }
8923970b0dSMatt Spinler else
9023970b0dSMatt Spinler {
9123970b0dSMatt Spinler // Gotta use something, how about 'others'.
925bc26533SArya K Padman lg2::warning(
9323970b0dSMatt Spinler "No PEL subystem value supplied for error, using 'others'");
9423970b0dSMatt Spinler _eventSubsystem = 0x70;
9523970b0dSMatt Spinler }
9650bfa69aSSumit Kumar
97fdb6a202SMatt Spinler _eventScope = entry.eventScope.value_or(
98fdb6a202SMatt Spinler static_cast<uint8_t>(EventScope::entirePlatform));
99fdb6a202SMatt Spinler
1003b8ed7f2SSumit Kumar {
1013b8ed7f2SSumit Kumar bool mfgSevStatus = false;
1023b8ed7f2SSumit Kumar bool mfgActionFlagStatus = false;
1033b8ed7f2SSumit Kumar
1043b8ed7f2SSumit Kumar // Get the mfg severity & action flags
1053b8ed7f2SSumit Kumar if (entry.mfgSeverity || entry.mfgActionFlags)
1063b8ed7f2SSumit Kumar {
107be952d2eSMatt Spinler std::optional<uint8_t> sev = std::nullopt;
108be952d2eSMatt Spinler uint16_t val = 0;
109be952d2eSMatt Spinler
1103b8ed7f2SSumit Kumar if (entry.mfgSeverity)
1113b8ed7f2SSumit Kumar {
1123b8ed7f2SSumit Kumar // Find the mf severity possibly dependent on the system type.
1133b8ed7f2SSumit Kumar sev = getSeverity(entry.mfgSeverity.value(), dataIface);
1143b8ed7f2SSumit Kumar }
1153b8ed7f2SSumit Kumar
1163b8ed7f2SSumit Kumar if (entry.mfgActionFlags)
1173b8ed7f2SSumit Kumar {
1183b8ed7f2SSumit Kumar // Find the mfg action flags
1193b8ed7f2SSumit Kumar val = entry.mfgActionFlags.value();
1203b8ed7f2SSumit Kumar }
1213b8ed7f2SSumit Kumar
1223b8ed7f2SSumit Kumar if (sev || val)
1233b8ed7f2SSumit Kumar {
1243b8ed7f2SSumit Kumar bool mfgProp = dataIface.getQuiesceOnError();
1253b8ed7f2SSumit Kumar if (mfgProp)
1263b8ed7f2SSumit Kumar {
1273b8ed7f2SSumit Kumar if (sev)
1283b8ed7f2SSumit Kumar {
1293b8ed7f2SSumit Kumar _eventSeverity = *sev;
1303b8ed7f2SSumit Kumar mfgSevStatus = true;
1313b8ed7f2SSumit Kumar }
1323b8ed7f2SSumit Kumar
1333b8ed7f2SSumit Kumar if (val)
1343b8ed7f2SSumit Kumar {
1353b8ed7f2SSumit Kumar _actionFlags = val;
1363b8ed7f2SSumit Kumar mfgActionFlagStatus = true;
1373b8ed7f2SSumit Kumar }
1383b8ed7f2SSumit Kumar }
1393b8ed7f2SSumit Kumar }
1403b8ed7f2SSumit Kumar }
1413b8ed7f2SSumit Kumar
1423b8ed7f2SSumit Kumar if (!mfgSevStatus)
1433b8ed7f2SSumit Kumar {
1443b8ed7f2SSumit Kumar // Get the severity from the registry if it's there, otherwise get
1453b8ed7f2SSumit Kumar // it from the OpenBMC event log severity value.
146aadccc85SMatt Spinler if (!entry.severity)
147aadccc85SMatt Spinler {
148aadccc85SMatt Spinler _eventSeverity = convertOBMCSeverityToPEL(severity);
149aadccc85SMatt Spinler }
150aadccc85SMatt Spinler else
151aadccc85SMatt Spinler {
152aadccc85SMatt Spinler // Find the severity possibly dependent on the system type.
1531ab6696fSMatt Spinler auto sev = getSeverity(entry.severity.value(), dataIface);
154aadccc85SMatt Spinler if (sev)
155aadccc85SMatt Spinler {
156aadccc85SMatt Spinler _eventSeverity = *sev;
157aadccc85SMatt Spinler }
158aadccc85SMatt Spinler else
159aadccc85SMatt Spinler {
1601ab6696fSMatt Spinler // Either someone screwed up the message registry
1611ab6696fSMatt Spinler // or getSystemNames failed.
1625bc26533SArya K Padman lg2::error(
1635bc26533SArya K Padman "Failed finding the severity in the message registry ERROR={ERROR}",
1645bc26533SArya K Padman "ERROR", entry.name);
165aadccc85SMatt Spinler
166aadccc85SMatt Spinler // Have to choose something, just use informational.
167aadccc85SMatt Spinler _eventSeverity = 0;
168aadccc85SMatt Spinler }
169aadccc85SMatt Spinler }
1703b8ed7f2SSumit Kumar }
171fdb6a202SMatt Spinler
1726b3f345bSVijay Lobo // Convert Critical error (0x50) to Critical Error-System Termination
1736b3f345bSVijay Lobo // (0x51), if the AdditionalData is set to SYSTEM_TERM
1746b3f345bSVijay Lobo auto sevLevel = additionalData.getValue("SEVERITY_DETAIL");
1756b3f345bSVijay Lobo if ((_eventSeverity & 0xF0) == 0x50)
1766b3f345bSVijay Lobo {
1776b3f345bSVijay Lobo if (sevLevel.value_or("") == "SYSTEM_TERM")
1786b3f345bSVijay Lobo {
1796b3f345bSVijay Lobo // Change to Critical Error, System Termination
1806b3f345bSVijay Lobo _eventSeverity = 0x51;
1816b3f345bSVijay Lobo }
1826b3f345bSVijay Lobo }
1836b3f345bSVijay Lobo
184f1e85e20SMatt Spinler if (entry.eventType)
185f1e85e20SMatt Spinler {
186f1e85e20SMatt Spinler _eventType = *entry.eventType;
187f1e85e20SMatt Spinler }
188f1e85e20SMatt Spinler else
189f1e85e20SMatt Spinler {
190f1e85e20SMatt Spinler // There are different default event types for info errors
191f1e85e20SMatt Spinler // vs non info ones.
192f1e85e20SMatt Spinler auto sevType = static_cast<SeverityType>(_eventSeverity & 0xF0);
1933b8ed7f2SSumit Kumar _eventType =
1943b8ed7f2SSumit Kumar (sevType == SeverityType::nonError)
195f1e85e20SMatt Spinler ? static_cast<uint8_t>(EventType::miscInformational)
196f1e85e20SMatt Spinler : static_cast<uint8_t>(EventType::notApplicable);
197f1e85e20SMatt Spinler }
198fdb6a202SMatt Spinler
199fdb6a202SMatt Spinler _reserved4Byte1 = 0;
200fdb6a202SMatt Spinler
201fdb6a202SMatt Spinler // No uses for problem domain or vector
202fdb6a202SMatt Spinler _problemDomain = 0;
203fdb6a202SMatt Spinler _problemVector = 0;
204fdb6a202SMatt Spinler
2051f93c590SMatt Spinler // These will be set in pel_rules::check() if they're still
2061f93c590SMatt Spinler // at the default value.
2073b8ed7f2SSumit Kumar if (!mfgActionFlagStatus)
2083b8ed7f2SSumit Kumar {
2091f93c590SMatt Spinler _actionFlags = entry.actionFlags.value_or(actionFlagsDefault);
2103b8ed7f2SSumit Kumar }
211fdb6a202SMatt Spinler
212eb111447SMatt Spinler _states = 0;
213fdb6a202SMatt Spinler
214fdb6a202SMatt Spinler _valid = true;
215fdb6a202SMatt Spinler }
2163b8ed7f2SSumit Kumar }
217fdb6a202SMatt Spinler
UserHeader(Stream & pel)21803c1d915SMatt Spinler UserHeader::UserHeader(Stream& pel)
21903c1d915SMatt Spinler {
22003c1d915SMatt Spinler try
22103c1d915SMatt Spinler {
222cf5a8d0fSMatt Spinler unflatten(pel);
22303c1d915SMatt Spinler validate();
22403c1d915SMatt Spinler }
22503c1d915SMatt Spinler catch (const std::exception& e)
22603c1d915SMatt Spinler {
2275bc26533SArya K Padman lg2::error("Cannot unflatten user header: {EXCEPTION}", "EXCEPTION", e);
22803c1d915SMatt Spinler _valid = false;
22903c1d915SMatt Spinler }
23003c1d915SMatt Spinler }
23103c1d915SMatt Spinler
validate()23203c1d915SMatt Spinler void UserHeader::validate()
23303c1d915SMatt Spinler {
23403c1d915SMatt Spinler bool failed = false;
2351a94cc38SMatt Spinler if (header().id != static_cast<uint16_t>(SectionID::userHeader))
23603c1d915SMatt Spinler {
2375bc26533SArya K Padman lg2::error("Invalid user header section ID: {HEADER_ID}", "HEADER_ID",
2385bc26533SArya K Padman lg2::hex, header().id);
23903c1d915SMatt Spinler failed = true;
24003c1d915SMatt Spinler }
24103c1d915SMatt Spinler
24203c1d915SMatt Spinler if (header().version != userHeaderVersion)
24303c1d915SMatt Spinler {
2445bc26533SArya K Padman lg2::error("Invalid user header version: {HEADER_VERSION}",
2455bc26533SArya K Padman "HEADER_VERSION", lg2::hex, header().version);
24603c1d915SMatt Spinler failed = true;
24703c1d915SMatt Spinler }
24803c1d915SMatt Spinler
24903c1d915SMatt Spinler _valid = (failed) ? false : true;
25003c1d915SMatt Spinler }
25103c1d915SMatt Spinler
getJSON(uint8_t creatorID) const252b832aa5eSMatt Spinler std::optional<std::string> UserHeader::getJSON(uint8_t creatorID) const
253ad0e0476SAatir Manzur {
254ad0e0476SAatir Manzur std::string severity;
255ad0e0476SAatir Manzur std::string subsystem;
256ad0e0476SAatir Manzur std::string eventScope;
257ad0e0476SAatir Manzur std::string eventType;
258600d15afSHarisuddin Mohamed Isa std::vector<std::string> actionFlags;
259c1489351SAatir severity = pv::getValue(_eventSeverity, pel_values::severityValues);
260c1489351SAatir subsystem = pv::getValue(_eventSubsystem, pel_values::subsystemValues);
261c1489351SAatir eventScope = pv::getValue(_eventScope, pel_values::eventScopeValues);
262c1489351SAatir eventType = pv::getValue(_eventType, pel_values::eventTypeValues);
263*075c7923SPatrick Williams actionFlags =
264*075c7923SPatrick Williams pv::getValuesBitwise(_actionFlags, pel_values::actionFlagsValues);
265455587e5SMatt Spinler
266455587e5SMatt Spinler std::string hostState{"Invalid"};
2672fb10211SVijay Lobo std::string hmcState{"Invalid"};
268455587e5SMatt Spinler auto iter = pv::transmissionStates.find(
269455587e5SMatt Spinler static_cast<TransmissionState>(hostTransmissionState()));
270455587e5SMatt Spinler if (iter != pv::transmissionStates.end())
271455587e5SMatt Spinler {
272455587e5SMatt Spinler hostState = iter->second;
273455587e5SMatt Spinler }
2742fb10211SVijay Lobo auto iter1 = pv::transmissionStates.find(
2752fb10211SVijay Lobo static_cast<TransmissionState>(hmcTransmissionState()));
2762fb10211SVijay Lobo if (iter1 != pv::transmissionStates.end())
2772fb10211SVijay Lobo {
2782fb10211SVijay Lobo hmcState = iter1->second;
2792fb10211SVijay Lobo }
280455587e5SMatt Spinler
281600d15afSHarisuddin Mohamed Isa std::string uh;
282bebeb948SHarisuddin Mohamed Isa jsonInsert(uh, pv::sectionVer, getNumberString("%d", userHeaderVersion), 1);
283bebeb948SHarisuddin Mohamed Isa jsonInsert(uh, pv::subSection, getNumberString("%d", _header.subType), 1);
284bebeb948SHarisuddin Mohamed Isa jsonInsert(uh, "Log Committed by",
285b832aa5eSMatt Spinler getComponentName(_header.componentID, creatorID), 1);
286600d15afSHarisuddin Mohamed Isa jsonInsert(uh, "Subsystem", subsystem, 1);
287600d15afSHarisuddin Mohamed Isa jsonInsert(uh, "Event Scope", eventScope, 1);
288600d15afSHarisuddin Mohamed Isa jsonInsert(uh, "Event Severity", severity, 1);
289600d15afSHarisuddin Mohamed Isa jsonInsert(uh, "Event Type", eventType, 1);
290600d15afSHarisuddin Mohamed Isa jsonInsertArray(uh, "Action Flags", actionFlags, 1);
291455587e5SMatt Spinler jsonInsert(uh, "Host Transmission", hostState, 1);
2922fb10211SVijay Lobo jsonInsert(uh, "HMC Transmission", hmcState, 1);
293600d15afSHarisuddin Mohamed Isa uh.erase(uh.size() - 2);
294ad0e0476SAatir Manzur return uh;
295ad0e0476SAatir Manzur }
296aadccc85SMatt Spinler
getSeverity(const std::vector<message::RegistrySeverity> & severities,const DataInterfaceBase & dataIface) const297aadccc85SMatt Spinler std::optional<uint8_t> UserHeader::getSeverity(
298aadccc85SMatt Spinler const std::vector<message::RegistrySeverity>& severities,
2991ab6696fSMatt Spinler const DataInterfaceBase& dataIface) const
300aadccc85SMatt Spinler {
301aadccc85SMatt Spinler const uint8_t* s = nullptr;
3021ab6696fSMatt Spinler std::vector<std::string> systemNames;
3031ab6696fSMatt Spinler
3041ab6696fSMatt Spinler // getSystemNames makes D-Bus calls, so only call it if we
3051ab6696fSMatt Spinler // know we'll need it because there is a system name in the sev list
3061ab6696fSMatt Spinler if (std::any_of(severities.begin(), severities.end(),
3071ab6696fSMatt Spinler [](const auto& sev) { return !sev.system.empty(); }))
3081ab6696fSMatt Spinler {
3091ab6696fSMatt Spinler try
3101ab6696fSMatt Spinler {
3111ab6696fSMatt Spinler systemNames = dataIface.getSystemNames();
3121ab6696fSMatt Spinler }
3131ab6696fSMatt Spinler catch (const std::exception& e)
3141ab6696fSMatt Spinler {
3155bc26533SArya K Padman lg2::error(
3165bc26533SArya K Padman "Failed trying to look up system names on D-Bus ERROR={ERROR}",
3175bc26533SArya K Padman "ERROR", e);
3181ab6696fSMatt Spinler return std::nullopt;
3191ab6696fSMatt Spinler }
3201ab6696fSMatt Spinler }
321aadccc85SMatt Spinler
322aadccc85SMatt Spinler // Find the severity to use for this system type, or use the default
323aadccc85SMatt Spinler // entry (where no system type is specified).
324aadccc85SMatt Spinler for (const auto& sev : severities)
325aadccc85SMatt Spinler {
3266ea4d5f7SMatt Spinler if (std::find(systemNames.begin(), systemNames.end(), sev.system) !=
3276ea4d5f7SMatt Spinler systemNames.end())
328aadccc85SMatt Spinler {
329aadccc85SMatt Spinler s = &sev.severity;
330aadccc85SMatt Spinler break;
331aadccc85SMatt Spinler }
332aadccc85SMatt Spinler else if (sev.system.empty())
333aadccc85SMatt Spinler {
334aadccc85SMatt Spinler s = &sev.severity;
335aadccc85SMatt Spinler }
336aadccc85SMatt Spinler }
337aadccc85SMatt Spinler
338aadccc85SMatt Spinler if (s)
339aadccc85SMatt Spinler {
340aadccc85SMatt Spinler return *s;
341aadccc85SMatt Spinler }
342aadccc85SMatt Spinler
343aadccc85SMatt Spinler return std::nullopt;
344aadccc85SMatt Spinler }
345aadccc85SMatt Spinler
34603c1d915SMatt Spinler } // namespace pels
34703c1d915SMatt Spinler } // namespace openpower
348