/** * Copyright © 2019 IBM Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "src.hpp" #include namespace openpower { namespace pels { using namespace phosphor::logging; void SRC::unflatten(Stream& stream) { stream >> _header >> _version >> _flags >> _reserved1B >> _wordCount >> _reserved2B >> _size; for (auto& word : _hexData) { stream >> word; } _asciiString = std::make_unique(stream); if (hasAdditionalSections()) { // The callouts section is currently the only extra subsection type _callouts = std::make_unique(stream); } } void SRC::flatten(Stream& stream) const { stream << _header << _version << _flags << _reserved1B << _wordCount << _reserved2B << _size; for (auto& word : _hexData) { stream << word; } _asciiString->flatten(stream); if (_callouts) { _callouts->flatten(stream); } } SRC::SRC(Stream& pel) { try { unflatten(pel); validate(); } catch (const std::exception& e) { log("Cannot unflatten SRC", entry("ERROR=%s", e.what())); _valid = false; } } SRC::SRC(const message::Entry& regEntry, const AdditionalData& additionalData) { _header.id = static_cast(SectionID::primarySRC); _header.version = srcSectionVersion; _header.subType = srcSectionSubtype; _header.componentID = regEntry.componentID; _version = srcVersion; _flags = 0; if (regEntry.src.powerFault.value_or(false)) { _flags |= powerFaultEvent; } _reserved1B = 0; _wordCount = numSRCHexDataWords + 1; _reserved2B = 0; // There are multiple fields encoded in the hex data words. std::for_each(_hexData.begin(), _hexData.end(), [](auto& word) { word = 0; }); setBMCFormat(); setBMCPosition(); // Partition dump status and partition boot type always 0 for BMC errors. // // TODO: Fill in other fields that aren't available yet. // Fill in the last 4 words from the AdditionalData property contents. setUserDefinedHexWords(regEntry, additionalData); _asciiString = std::make_unique(regEntry); // TODO: add callouts using the Callouts object _size = baseSRCSize; _size += _callouts ? _callouts->flattenedSize() : 0; _header.size = Section::flattenedSize() + _size; _valid = true; } void SRC::setUserDefinedHexWords(const message::Entry& regEntry, const AdditionalData& ad) { if (!regEntry.src.hexwordADFields) { return; } // Save the AdditionalData value corresponding to the // adName key in _hexData[wordNum]. for (const auto& [wordNum, adName] : *regEntry.src.hexwordADFields) { // Can only set words 6 - 9 if (!isUserDefinedWord(wordNum)) { log("SRC user data word out of range", entry("WORD_NUM=%d", wordNum), entry("ERROR_NAME=%s", regEntry.name.c_str())); continue; } auto value = ad.getValue(adName); if (value) { _hexData[getWordIndexFromWordNum(wordNum)] = std::strtoul(value.value().c_str(), nullptr, 0); } else { log("Source for user data SRC word not found", entry("ADDITIONALDATA_KEY=%s", adName.c_str()), entry("ERROR_NAME=%s", regEntry.name.c_str())); } } } void SRC::validate() { bool failed = false; if ((header().id != static_cast(SectionID::primarySRC)) && (header().id != static_cast(SectionID::secondarySRC))) { log("Invalid SRC section ID", entry("ID=0x%X", header().id)); failed = true; } // Check the version in the SRC, not in the header if (_version != srcVersion) { log("Invalid SRC version", entry("VERSION=0x%X", _version)); failed = true; } _valid = failed ? false : true; } } // namespace pels } // namespace openpower