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 
181a94cc38SMatt Spinler #include "pel_types.hpp"
19*c1489351SAatir #include "pel_values.hpp"
20fdb6a202SMatt Spinler #include "severity.hpp"
211a94cc38SMatt Spinler 
22ad0e0476SAatir Manzur #include <iostream>
2303c1d915SMatt Spinler #include <phosphor-logging/log.hpp>
2403c1d915SMatt Spinler 
2503c1d915SMatt Spinler namespace openpower
2603c1d915SMatt Spinler {
2703c1d915SMatt Spinler namespace pels
2803c1d915SMatt Spinler {
2903c1d915SMatt Spinler 
30*c1489351SAatir namespace pv = openpower::pels::pel_values;
3103c1d915SMatt Spinler using namespace phosphor::logging;
3203c1d915SMatt Spinler 
33cf5a8d0fSMatt Spinler void UserHeader::unflatten(Stream& stream)
3403c1d915SMatt Spinler {
35cf5a8d0fSMatt Spinler     stream >> _header >> _eventSubsystem >> _eventScope >> _eventSeverity >>
36cf5a8d0fSMatt Spinler         _eventType >> _reserved4Byte1 >> _problemDomain >> _problemVector >>
37cf5a8d0fSMatt Spinler         _actionFlags >> _reserved4Byte2;
3803c1d915SMatt Spinler }
3903c1d915SMatt Spinler 
400688545bSMatt Spinler void UserHeader::flatten(Stream& stream) const
4103c1d915SMatt Spinler {
42cf5a8d0fSMatt Spinler     stream << _header << _eventSubsystem << _eventScope << _eventSeverity
43cf5a8d0fSMatt Spinler            << _eventType << _reserved4Byte1 << _problemDomain << _problemVector
44cf5a8d0fSMatt Spinler            << _actionFlags << _reserved4Byte2;
4503c1d915SMatt Spinler }
4603c1d915SMatt Spinler 
47fdb6a202SMatt Spinler UserHeader::UserHeader(const message::Entry& entry,
48fdb6a202SMatt Spinler                        phosphor::logging::Entry::Level severity)
49fdb6a202SMatt Spinler {
50fdb6a202SMatt Spinler     _header.id = static_cast<uint16_t>(SectionID::userHeader);
51fdb6a202SMatt Spinler     _header.size = UserHeader::flattenedSize();
52fdb6a202SMatt Spinler     _header.version = userHeaderVersion;
53fdb6a202SMatt Spinler     _header.subType = 0;
54fdb6a202SMatt Spinler     _header.componentID = static_cast<uint16_t>(ComponentID::phosphorLogging);
55fdb6a202SMatt Spinler 
56fdb6a202SMatt Spinler     _eventSubsystem = entry.subsystem;
57fdb6a202SMatt Spinler 
58fdb6a202SMatt Spinler     _eventScope = entry.eventScope.value_or(
59fdb6a202SMatt Spinler         static_cast<uint8_t>(EventScope::entirePlatform));
60fdb6a202SMatt Spinler 
61fdb6a202SMatt Spinler     // Get the severity from the registry if it's there, otherwise get it
62fdb6a202SMatt Spinler     // from the OpenBMC event log severity value.
63fdb6a202SMatt Spinler     _eventSeverity =
64fdb6a202SMatt Spinler         entry.severity.value_or(convertOBMCSeverityToPEL(severity));
65fdb6a202SMatt Spinler 
66fdb6a202SMatt Spinler     // TODO: ibm-dev/dev/#1144 Handle manufacturing sev & action flags
67fdb6a202SMatt Spinler 
68f1e85e20SMatt Spinler     if (entry.eventType)
69f1e85e20SMatt Spinler     {
70f1e85e20SMatt Spinler         _eventType = *entry.eventType;
71f1e85e20SMatt Spinler     }
72f1e85e20SMatt Spinler     else
73f1e85e20SMatt Spinler     {
74f1e85e20SMatt Spinler         // There are different default event types for info errors
75f1e85e20SMatt Spinler         // vs non info ones.
76f1e85e20SMatt Spinler         auto sevType = static_cast<SeverityType>(_eventSeverity & 0xF0);
77f1e85e20SMatt Spinler 
78f1e85e20SMatt Spinler         _eventType = (sevType == SeverityType::nonError)
79f1e85e20SMatt Spinler                          ? static_cast<uint8_t>(EventType::miscInformational)
80f1e85e20SMatt Spinler                          : static_cast<uint8_t>(EventType::notApplicable);
81f1e85e20SMatt Spinler     }
82fdb6a202SMatt Spinler 
83fdb6a202SMatt Spinler     _reserved4Byte1 = 0;
84fdb6a202SMatt Spinler 
85fdb6a202SMatt Spinler     // No uses for problem domain or vector
86fdb6a202SMatt Spinler     _problemDomain = 0;
87fdb6a202SMatt Spinler     _problemVector = 0;
88fdb6a202SMatt Spinler 
89f1e85e20SMatt Spinler     // These will be cleaned up later in pel_rules::check()
90e07f915bSMatt Spinler     _actionFlags = entry.actionFlags.value_or(0);
91fdb6a202SMatt Spinler 
92fdb6a202SMatt Spinler     _reserved4Byte2 = 0;
93fdb6a202SMatt Spinler 
94fdb6a202SMatt Spinler     _valid = true;
95fdb6a202SMatt Spinler }
96fdb6a202SMatt Spinler 
9703c1d915SMatt Spinler UserHeader::UserHeader(Stream& pel)
9803c1d915SMatt Spinler {
9903c1d915SMatt Spinler     try
10003c1d915SMatt Spinler     {
101cf5a8d0fSMatt Spinler         unflatten(pel);
10203c1d915SMatt Spinler         validate();
10303c1d915SMatt Spinler     }
10403c1d915SMatt Spinler     catch (const std::exception& e)
10503c1d915SMatt Spinler     {
10603c1d915SMatt Spinler         log<level::ERR>("Cannot unflatten user header",
10703c1d915SMatt Spinler                         entry("ERROR=%s", e.what()));
10803c1d915SMatt Spinler         _valid = false;
10903c1d915SMatt Spinler     }
11003c1d915SMatt Spinler }
11103c1d915SMatt Spinler 
11203c1d915SMatt Spinler void UserHeader::validate()
11303c1d915SMatt Spinler {
11403c1d915SMatt Spinler     bool failed = false;
1151a94cc38SMatt Spinler     if (header().id != static_cast<uint16_t>(SectionID::userHeader))
11603c1d915SMatt Spinler     {
11703c1d915SMatt Spinler         log<level::ERR>("Invalid user header section ID",
11803c1d915SMatt Spinler                         entry("ID=0x%X", header().id));
11903c1d915SMatt Spinler         failed = true;
12003c1d915SMatt Spinler     }
12103c1d915SMatt Spinler 
12203c1d915SMatt Spinler     if (header().version != userHeaderVersion)
12303c1d915SMatt Spinler     {
12403c1d915SMatt Spinler         log<level::ERR>("Invalid user header version",
12503c1d915SMatt Spinler                         entry("VERSION=0x%X", header().version));
12603c1d915SMatt Spinler         failed = true;
12703c1d915SMatt Spinler     }
12803c1d915SMatt Spinler 
12903c1d915SMatt Spinler     _valid = (failed) ? false : true;
13003c1d915SMatt Spinler }
13103c1d915SMatt Spinler 
132ad0e0476SAatir Manzur std::optional<std::string> UserHeader::getJSON() const
133ad0e0476SAatir Manzur {
134ad0e0476SAatir Manzur     std::string severity;
135ad0e0476SAatir Manzur     std::string subsystem;
136ad0e0476SAatir Manzur     std::string eventScope;
137ad0e0476SAatir Manzur     std::string eventType;
138*c1489351SAatir     severity = pv::getValue(_eventSeverity, pel_values::severityValues);
139*c1489351SAatir     subsystem = pv::getValue(_eventSubsystem, pel_values::subsystemValues);
140*c1489351SAatir     eventScope = pv::getValue(_eventScope, pel_values::eventScopeValues);
141*c1489351SAatir     eventType = pv::getValue(_eventType, pel_values::eventTypeValues);
142ad0e0476SAatir Manzur     char tmpUhVal[8];
143ad0e0476SAatir Manzur     sprintf(tmpUhVal, "%d", userHeaderVersion);
144ad0e0476SAatir Manzur     std::string uhVerStr(tmpUhVal);
145ad0e0476SAatir Manzur     sprintf(tmpUhVal, "0x%X", _header.componentID);
146ad0e0476SAatir Manzur     std::string uhCbStr(tmpUhVal);
147ad0e0476SAatir Manzur     sprintf(tmpUhVal, "%d", _header.subType);
148ad0e0476SAatir Manzur     std::string uhStStr(tmpUhVal);
149ad0e0476SAatir Manzur 
150ad0e0476SAatir Manzur     std::string uh = "{\"Section Version\": \"" + uhVerStr +
151ad0e0476SAatir Manzur                      "\"}, \n {\"Sub-section type\": \"" + uhStStr +
152ad0e0476SAatir Manzur                      "\"}, \n "
153ad0e0476SAatir Manzur                      "{\"Log Committed by\": \"" +
154ad0e0476SAatir Manzur                      uhCbStr + "\"}, \n {\"Subsystem\": \"" + subsystem +
155ad0e0476SAatir Manzur                      "\"},\n "
156ad0e0476SAatir Manzur                      "{\"Event Scope\": \"" +
157ad0e0476SAatir Manzur                      eventScope + "\"}, \n {\"Event Severity\":\"" + severity +
158ad0e0476SAatir Manzur                      "\"},\n {\"Event Type\": \"" + eventType + "\"}";
159ad0e0476SAatir Manzur     return uh;
160ad0e0476SAatir Manzur }
16103c1d915SMatt Spinler } // namespace pels
16203c1d915SMatt Spinler } // namespace openpower
163