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 "pel_types.hpp"
19 #include "pel_values.hpp"
20 #include "severity.hpp"
21 
22 #include <iostream>
23 #include <phosphor-logging/log.hpp>
24 
25 namespace openpower
26 {
27 namespace pels
28 {
29 
30 namespace pv = openpower::pels::pel_values;
31 using namespace phosphor::logging;
32 
33 void UserHeader::unflatten(Stream& stream)
34 {
35     stream >> _header >> _eventSubsystem >> _eventScope >> _eventSeverity >>
36         _eventType >> _reserved4Byte1 >> _problemDomain >> _problemVector >>
37         _actionFlags >> _reserved4Byte2;
38 }
39 
40 void UserHeader::flatten(Stream& stream) const
41 {
42     stream << _header << _eventSubsystem << _eventScope << _eventSeverity
43            << _eventType << _reserved4Byte1 << _problemDomain << _problemVector
44            << _actionFlags << _reserved4Byte2;
45 }
46 
47 UserHeader::UserHeader(const message::Entry& entry,
48                        phosphor::logging::Entry::Level severity)
49 {
50     _header.id = static_cast<uint16_t>(SectionID::userHeader);
51     _header.size = UserHeader::flattenedSize();
52     _header.version = userHeaderVersion;
53     _header.subType = 0;
54     _header.componentID = static_cast<uint16_t>(ComponentID::phosphorLogging);
55 
56     _eventSubsystem = entry.subsystem;
57 
58     _eventScope = entry.eventScope.value_or(
59         static_cast<uint8_t>(EventScope::entirePlatform));
60 
61     // Get the severity from the registry if it's there, otherwise get it
62     // from the OpenBMC event log severity value.
63     _eventSeverity =
64         entry.severity.value_or(convertOBMCSeverityToPEL(severity));
65 
66     // TODO: ibm-dev/dev/#1144 Handle manufacturing sev & action flags
67 
68     if (entry.eventType)
69     {
70         _eventType = *entry.eventType;
71     }
72     else
73     {
74         // There are different default event types for info errors
75         // vs non info ones.
76         auto sevType = static_cast<SeverityType>(_eventSeverity & 0xF0);
77 
78         _eventType = (sevType == SeverityType::nonError)
79                          ? static_cast<uint8_t>(EventType::miscInformational)
80                          : static_cast<uint8_t>(EventType::notApplicable);
81     }
82 
83     _reserved4Byte1 = 0;
84 
85     // No uses for problem domain or vector
86     _problemDomain = 0;
87     _problemVector = 0;
88 
89     // These will be cleaned up later in pel_rules::check()
90     _actionFlags = entry.actionFlags.value_or(0);
91 
92     _reserved4Byte2 = 0;
93 
94     _valid = true;
95 }
96 
97 UserHeader::UserHeader(Stream& pel)
98 {
99     try
100     {
101         unflatten(pel);
102         validate();
103     }
104     catch (const std::exception& e)
105     {
106         log<level::ERR>("Cannot unflatten user header",
107                         entry("ERROR=%s", e.what()));
108         _valid = false;
109     }
110 }
111 
112 void UserHeader::validate()
113 {
114     bool failed = false;
115     if (header().id != static_cast<uint16_t>(SectionID::userHeader))
116     {
117         log<level::ERR>("Invalid user header section ID",
118                         entry("ID=0x%X", header().id));
119         failed = true;
120     }
121 
122     if (header().version != userHeaderVersion)
123     {
124         log<level::ERR>("Invalid user header version",
125                         entry("VERSION=0x%X", header().version));
126         failed = true;
127     }
128 
129     _valid = (failed) ? false : true;
130 }
131 
132 std::optional<std::string> UserHeader::getJSON() const
133 {
134     std::string severity;
135     std::string subsystem;
136     std::string eventScope;
137     std::string eventType;
138     severity = pv::getValue(_eventSeverity, pel_values::severityValues);
139     subsystem = pv::getValue(_eventSubsystem, pel_values::subsystemValues);
140     eventScope = pv::getValue(_eventScope, pel_values::eventScopeValues);
141     eventType = pv::getValue(_eventType, pel_values::eventTypeValues);
142     char tmpUhVal[8];
143     sprintf(tmpUhVal, "%d", userHeaderVersion);
144     std::string uhVerStr(tmpUhVal);
145     sprintf(tmpUhVal, "0x%X", _header.componentID);
146     std::string uhCbStr(tmpUhVal);
147     sprintf(tmpUhVal, "%d", _header.subType);
148     std::string uhStStr(tmpUhVal);
149 
150     std::string uh = "{\"Section Version\": \"" + uhVerStr +
151                      "\"}, \n {\"Sub-section type\": \"" + uhStStr +
152                      "\"}, \n "
153                      "{\"Log Committed by\": \"" +
154                      uhCbStr + "\"}, \n {\"Subsystem\": \"" + subsystem +
155                      "\"},\n "
156                      "{\"Event Scope\": \"" +
157                      eventScope + "\"}, \n {\"Event Severity\":\"" + severity +
158                      "\"},\n {\"Event Type\": \"" + eventType + "\"}";
159     return uh;
160 }
161 } // namespace pels
162 } // namespace openpower
163