blob: b2b86bf9b19c7131adfb29028292df4a784013f4 [file] [log] [blame]
Matt Spinler711d51d2019-11-06 09:36:51 -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 */
Matt Spinlerf9bae182019-10-09 13:37:38 -050016#include "src.hpp"
17
18#include <phosphor-logging/log.hpp>
19
20namespace openpower
21{
22namespace pels
23{
24
25using namespace phosphor::logging;
26
27void SRC::unflatten(Stream& stream)
28{
29 stream >> _header >> _version >> _flags >> _reserved1B >> _wordCount >>
30 _reserved2B >> _size;
31
32 for (auto& word : _hexData)
33 {
34 stream >> word;
35 }
36
37 _asciiString = std::make_unique<src::AsciiString>(stream);
38
39 if (hasAdditionalSections())
40 {
41 // The callouts section is currently the only extra subsection type
42 _callouts = std::make_unique<src::Callouts>(stream);
43 }
44}
45
Matt Spinler06885452019-11-06 10:35:42 -060046void SRC::flatten(Stream& stream) const
Matt Spinlerf9bae182019-10-09 13:37:38 -050047{
48 stream << _header << _version << _flags << _reserved1B << _wordCount
49 << _reserved2B << _size;
50
51 for (auto& word : _hexData)
52 {
53 stream << word;
54 }
55
56 _asciiString->flatten(stream);
57
58 if (_callouts)
59 {
60 _callouts->flatten(stream);
61 }
62}
63
64SRC::SRC(Stream& pel)
65{
66 try
67 {
68 unflatten(pel);
69 validate();
70 }
71 catch (const std::exception& e)
72 {
73 log<level::ERR>("Cannot unflatten SRC", entry("ERROR=%s", e.what()));
74 _valid = false;
75 }
76}
77
Matt Spinlerbd716f02019-10-15 10:54:11 -050078SRC::SRC(const message::Entry& regEntry, const AdditionalData& additionalData)
79{
80 _header.id = static_cast<uint16_t>(SectionID::primarySRC);
81 _header.version = srcSectionVersion;
82 _header.subType = srcSectionSubtype;
83 _header.componentID = regEntry.componentID;
84
85 _version = srcVersion;
86
87 _flags = 0;
88 if (regEntry.src.powerFault.value_or(false))
89 {
90 _flags |= powerFaultEvent;
91 }
92
93 _reserved1B = 0;
94
95 _wordCount = numSRCHexDataWords + 1;
96
97 _reserved2B = 0;
98
99 // There are multiple fields encoded in the hex data words.
100 std::for_each(_hexData.begin(), _hexData.end(),
101 [](auto& word) { word = 0; });
102 setBMCFormat();
103 setBMCPosition();
104 // Partition dump status and partition boot type always 0 for BMC errors.
105 //
106 // TODO: Fill in other fields that aren't available yet.
107
108 // Fill in the last 4 words from the AdditionalData property contents.
109 setUserDefinedHexWords(regEntry, additionalData);
110
111 _asciiString = std::make_unique<src::AsciiString>(regEntry);
112
113 // TODO: add callouts using the Callouts object
114
115 _size = baseSRCSize;
116 _size += _callouts ? _callouts->flattenedSize() : 0;
117 _header.size = Section::flattenedSize() + _size;
118
119 _valid = true;
120}
121
122void SRC::setUserDefinedHexWords(const message::Entry& regEntry,
123 const AdditionalData& ad)
124{
125 if (!regEntry.src.hexwordADFields)
126 {
127 return;
128 }
129
130 // Save the AdditionalData value corresponding to the
131 // adName key in _hexData[wordNum].
132 for (const auto& [wordNum, adName] : *regEntry.src.hexwordADFields)
133 {
134 // Can only set words 6 - 9
135 if (!isUserDefinedWord(wordNum))
136 {
137 log<level::WARNING>("SRC user data word out of range",
138 entry("WORD_NUM=%d", wordNum),
139 entry("ERROR_NAME=%s", regEntry.name.c_str()));
140 continue;
141 }
142
143 auto value = ad.getValue(adName);
144 if (value)
145 {
146 _hexData[getWordIndexFromWordNum(wordNum)] =
147 std::strtoul(value.value().c_str(), nullptr, 0);
148 }
149 else
150 {
151 log<level::WARNING>("Source for user data SRC word not found",
152 entry("ADDITIONALDATA_KEY=%s", adName.c_str()),
153 entry("ERROR_NAME=%s", regEntry.name.c_str()));
154 }
155 }
156}
157
Matt Spinlerf9bae182019-10-09 13:37:38 -0500158void SRC::validate()
159{
160 bool failed = false;
161
162 if ((header().id != static_cast<uint16_t>(SectionID::primarySRC)) &&
163 (header().id != static_cast<uint16_t>(SectionID::secondarySRC)))
164 {
165 log<level::ERR>("Invalid SRC section ID",
166 entry("ID=0x%X", header().id));
167 failed = true;
168 }
169
170 // Check the version in the SRC, not in the header
Matt Spinlerbd716f02019-10-15 10:54:11 -0500171 if (_version != srcVersion)
Matt Spinlerf9bae182019-10-09 13:37:38 -0500172 {
Matt Spinlerbd716f02019-10-15 10:54:11 -0500173 log<level::ERR>("Invalid SRC version", entry("VERSION=0x%X", _version));
Matt Spinlerf9bae182019-10-09 13:37:38 -0500174 failed = true;
175 }
176
177 _valid = failed ? false : true;
178}
179
180} // namespace pels
181} // namespace openpower