blob: 7b381e8d92f7dfb8d34211a10d631adbed68d476 [file] [log] [blame]
Matt Spinlerc63e2e82019-12-02 15:50:12 -06001/**
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 "extended_user_header.hpp"
17
Harisuddin Mohamed Isa160c51c2020-02-13 23:42:20 +080018#include "json_utils.hpp"
Matt Spinlerc63e2e82019-12-02 15:50:12 -060019#include "pel_types.hpp"
Harisuddin Mohamed Isabebeb942020-03-12 17:12:24 +080020#include "pel_values.hpp"
Matt Spinlerc63e2e82019-12-02 15:50:12 -060021
22#include <phosphor-logging/log.hpp>
23
24namespace openpower
25{
26namespace pels
27{
28
Harisuddin Mohamed Isabebeb942020-03-12 17:12:24 +080029namespace pv = openpower::pels::pel_values;
Matt Spinlerc63e2e82019-12-02 15:50:12 -060030using namespace phosphor::logging;
31const size_t defaultSymptomIDWord = 3;
32const size_t symptomIDMaxSize = 80;
33
34ExtendedUserHeader::ExtendedUserHeader(Stream& pel)
35{
36 try
37 {
38 unflatten(pel);
39 validate();
40 }
41 catch (const std::exception& e)
42 {
43 log<level::ERR>("Cannot unflatten extended user header",
44 entry("ERROR=%s", e.what()));
45 _valid = false;
46 }
47}
48
49ExtendedUserHeader::ExtendedUserHeader(const DataInterfaceBase& dataIface,
50 const message::Entry& regEntry,
51 const SRC& src) :
52 _mtms(dataIface.getMachineTypeModel(), dataIface.getMachineSerialNumber())
53{
54 _header.id = static_cast<uint16_t>(SectionID::extendedUserHeader);
55 _header.version = extendedUserHeaderVersion;
56 _header.subType = 0;
57 _header.componentID = static_cast<uint16_t>(ComponentID::phosphorLogging);
58
59 memset(_serverFWVersion.data(), 0, _serverFWVersion.size());
60 auto version = dataIface.getServerFWVersion();
61
62 // The last byte must always be the NULL terminator
63 for (size_t i = 0; i < version.size() && i < firmwareVersionSize - 1; i++)
64 {
65 _serverFWVersion[i] = version[i];
66 }
67
68 memset(_subsystemFWVersion.data(), 0, _subsystemFWVersion.size());
69 version = dataIface.getBMCFWVersion();
70
71 // The last byte must always be the NULL terminator
72 for (size_t i = 0; i < version.size() && i < firmwareVersionSize - 1; i++)
73 {
74 _subsystemFWVersion[i] = version[i];
75 }
76
77 createSymptomID(regEntry, src);
78
79 _header.size = flattenedSize();
80 _valid = true;
81}
82
83void ExtendedUserHeader::flatten(Stream& pel) const
84{
85 pel << _header << _mtms;
86 pel.write(_serverFWVersion.data(), _serverFWVersion.size());
87 pel.write(_subsystemFWVersion.data(), _subsystemFWVersion.size());
88 pel << _reserved4B << _refTime << _reserved1B1 << _reserved1B2
89 << _reserved1B3 << _symptomIDSize << _symptomID;
90}
91
92void ExtendedUserHeader::unflatten(Stream& pel)
93{
94 pel >> _header >> _mtms;
95 pel.read(_serverFWVersion.data(), _serverFWVersion.size());
96 pel.read(_subsystemFWVersion.data(), _subsystemFWVersion.size());
97 pel >> _reserved4B >> _refTime >> _reserved1B1 >> _reserved1B2 >>
98 _reserved1B3 >> _symptomIDSize;
99
100 _symptomID.resize(_symptomIDSize);
101 pel >> _symptomID;
102}
103
104void ExtendedUserHeader::validate()
105{
106 bool failed = false;
107
108 if (header().id != static_cast<uint16_t>(SectionID::extendedUserHeader))
109 {
110 log<level::ERR>("Invalid failing Extended User Header section ID",
111 entry("ID=0x%X", header().id));
112 failed = true;
113 }
114
115 if (header().version != extendedUserHeaderVersion)
116 {
117 log<level::ERR>("Invalid Extended User Header version",
118 entry("VERSION=0x%X", header().version));
119 failed = true;
120 }
121
122 _valid = (failed) ? false : true;
123}
124
125void ExtendedUserHeader::createSymptomID(const message::Entry& regEntry,
126 const SRC& src)
127{
128 // Contains the first 8 characters of the ASCII string plus additional
129 // words from the SRC, separated by underscores. The message registry
130 // says which words to use, though that's optional and if not present
131 // then use a default word.
132 std::vector<size_t> idWords;
133
134 if (regEntry.src.symptomID)
135 {
136 idWords = regEntry.src.symptomID.value();
137 }
138 else
139 {
140 idWords.push_back(defaultSymptomIDWord);
141 }
142
143 auto symptomID = src.asciiString().substr(0, 8);
144
145 const auto& hexWords = src.hexwordData();
146
147 for (auto wordNum : idWords)
148 {
149 symptomID.push_back('_');
150
151 // Get the hexword array index for this SRC word
152 auto index = src.getWordIndexFromWordNum(wordNum);
153
154 // Convert to ASCII
155 char word[20];
156 sprintf(word, "%08X", hexWords[index]);
157 symptomID += word;
158 }
159
160 std::copy(symptomID.begin(), symptomID.end(),
161 std::back_inserter(_symptomID));
162
163 // Max total size is 80, including the upcoming NULL
164 if (_symptomID.size() > (symptomIDMaxSize - 1))
165 {
166 _symptomID.resize(symptomIDMaxSize - 1);
167 }
168
169 // NULL terminated
170 _symptomID.push_back(0);
171
172 // PAD with NULLs to a 4 byte boundary
173 while ((_symptomID.size() % 4) != 0)
174 {
175 _symptomID.push_back(0);
176 }
177
178 _symptomIDSize = _symptomID.size();
179}
180
Harisuddin Mohamed Isa160c51c2020-02-13 23:42:20 +0800181std::optional<std::string> ExtendedUserHeader::getJSON() const
182{
183 std::string json;
Harisuddin Mohamed Isabebeb942020-03-12 17:12:24 +0800184 jsonInsert(json, pv::sectionVer, getNumberString("%d", _header.version), 1);
185 jsonInsert(json, pv::subSection, getNumberString("%d", _header.subType), 1);
186 jsonInsert(json, pv::createdBy,
187 getNumberString("0x%X", _header.componentID), 1);
Harisuddin Mohamed Isa160c51c2020-02-13 23:42:20 +0800188 jsonInsert(json, "Reporting Machine Type", machineTypeModel(), 1);
189 jsonInsert(json, "Reporting Serial Number", trimEnd(machineSerialNumber()),
190 1);
191 jsonInsert(json, "FW Released Ver", serverFWVersion(), 1);
192 jsonInsert(json, "FW SubSys Version", subsystemFWVersion(), 1);
193 jsonInsert(json, "Common Ref Time",
194 getNumberString("%02X", _refTime.month) + '/' +
195 getNumberString("%02X", _refTime.day) + '/' +
196 getNumberString("%02X", _refTime.yearMSB) +
197 getNumberString("%02X", _refTime.yearLSB) + ' ' +
198 getNumberString("%02X", _refTime.hour) + ':' +
199 getNumberString("%02X", _refTime.minutes) + ':' +
200 getNumberString("%02X", _refTime.seconds),
201 1);
202 jsonInsert(json, "Symptom Id Len", getNumberString("%d", _symptomIDSize),
203 1);
204 jsonInsert(json, "Symptom Id", symptomID(), 1);
205 json.erase(json.size() - 2);
206 return json;
207}
208
Matt Spinlerc63e2e82019-12-02 15:50:12 -0600209} // namespace pels
210} // namespace openpower