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 {
51     _header.id = static_cast<uint16_t>(SectionID::userHeader);
52     _header.size = UserHeader::flattenedSize();
53     _header.version = userHeaderVersion;
54     _header.subType = 0;
55     _header.componentID = static_cast<uint16_t>(ComponentID::phosphorLogging);
56 
57     _eventSubsystem = entry.subsystem;
58 
59     _eventScope = entry.eventScope.value_or(
60         static_cast<uint8_t>(EventScope::entirePlatform));
61 
62     // Get the severity from the registry if it's there, otherwise get it
63     // from the OpenBMC event log severity value.
64     _eventSeverity =
65         entry.severity.value_or(convertOBMCSeverityToPEL(severity));
66 
67     // TODO: ibm-dev/dev/#1144 Handle manufacturing sev & action flags
68 
69     if (entry.eventType)
70     {
71         _eventType = *entry.eventType;
72     }
73     else
74     {
75         // There are different default event types for info errors
76         // vs non info ones.
77         auto sevType = static_cast<SeverityType>(_eventSeverity & 0xF0);
78 
79         _eventType = (sevType == SeverityType::nonError)
80                          ? static_cast<uint8_t>(EventType::miscInformational)
81                          : static_cast<uint8_t>(EventType::notApplicable);
82     }
83 
84     _reserved4Byte1 = 0;
85 
86     // No uses for problem domain or vector
87     _problemDomain = 0;
88     _problemVector = 0;
89 
90     // These will be cleaned up later in pel_rules::check()
91     _actionFlags = entry.actionFlags.value_or(0);
92 
93     _states = 0;
94 
95     _valid = true;
96 }
97 
98 UserHeader::UserHeader(Stream& pel)
99 {
100     try
101     {
102         unflatten(pel);
103         validate();
104     }
105     catch (const std::exception& e)
106     {
107         log<level::ERR>("Cannot unflatten user header",
108                         entry("ERROR=%s", e.what()));
109         _valid = false;
110     }
111 }
112 
113 void UserHeader::validate()
114 {
115     bool failed = false;
116     if (header().id != static_cast<uint16_t>(SectionID::userHeader))
117     {
118         log<level::ERR>("Invalid user header section ID",
119                         entry("ID=0x%X", header().id));
120         failed = true;
121     }
122 
123     if (header().version != userHeaderVersion)
124     {
125         log<level::ERR>("Invalid user header version",
126                         entry("VERSION=0x%X", header().version));
127         failed = true;
128     }
129 
130     _valid = (failed) ? false : true;
131 }
132 
133 std::optional<std::string> UserHeader::getJSON() const
134 {
135     std::string severity;
136     std::string subsystem;
137     std::string eventScope;
138     std::string eventType;
139     std::vector<std::string> actionFlags;
140     severity = pv::getValue(_eventSeverity, pel_values::severityValues);
141     subsystem = pv::getValue(_eventSubsystem, pel_values::subsystemValues);
142     eventScope = pv::getValue(_eventScope, pel_values::eventScopeValues);
143     eventType = pv::getValue(_eventType, pel_values::eventTypeValues);
144     actionFlags =
145         pv::getValuesBitwise(_actionFlags, pel_values::actionFlagsValues);
146 
147     std::string hostState{"Invalid"};
148     auto iter = pv::transmissionStates.find(
149         static_cast<TransmissionState>(hostTransmissionState()));
150     if (iter != pv::transmissionStates.end())
151     {
152         hostState = iter->second;
153     }
154 
155     std::string uh;
156     jsonInsert(uh, pv::sectionVer, getNumberString("%d", userHeaderVersion), 1);
157     jsonInsert(uh, pv::subSection, getNumberString("%d", _header.subType), 1);
158     jsonInsert(uh, "Log Committed by",
159                getNumberString("0x%X", _header.componentID), 1);
160     jsonInsert(uh, "Subsystem", subsystem, 1);
161     jsonInsert(uh, "Event Scope", eventScope, 1);
162     jsonInsert(uh, "Event Severity", severity, 1);
163     jsonInsert(uh, "Event Type", eventType, 1);
164     jsonInsertArray(uh, "Action Flags", actionFlags, 1);
165     jsonInsert(uh, "Host Transmission", hostState, 1);
166     uh.erase(uh.size() - 2);
167     return uh;
168 }
169 } // namespace pels
170 } // namespace openpower
171