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