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