summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Spinler <spinler@us.ibm.com>2019-10-09 12:48:25 -0500
committerMatt Spinler <spinler@us.ibm.com>2019-10-22 14:09:56 +0000
commit32f13c915fa4b27520ca0aea476804c37f5516b9 (patch)
tree87e6af31872b305f86d37f83670fa94524b95d99
parent6c9662c9a269a3fcf6e6ccee51b2ab76b1679fb0 (diff)
downloadphosphor-logging-32f13c915fa4b27520ca0aea476804c37f5516b9.tar.gz
phosphor-logging-32f13c915fa4b27520ca0aea476804c37f5516b9.zip
PEL: SRC callouts subsection object
This Callouts class represents the optional subsection of an SRC PEL section that contains FRU callouts. It is only present in the SRC when there are callouts, and it comes at the end of the section. It is basically just a container for the Callout objects that represent the actual callouts. Signed-off-by: Matt Spinler <spinler@us.ibm.com> Change-Id: I1d4d95b82f9b4943728d7939e3bf89e4a7bcbb75
-rw-r--r--extensions/openpower-pels/callouts.cpp36
-rw-r--r--extensions/openpower-pels/callouts.hpp96
-rw-r--r--extensions/openpower-pels/openpower-pels.mk1
-rw-r--r--test/openpower-pels/Makefile.include16
-rw-r--r--test/openpower-pels/pel_utils.cpp34
-rw-r--r--test/openpower-pels/pel_utils.hpp2
-rw-r--r--test/openpower-pels/src_callouts_test.cpp76
7 files changed, 261 insertions, 0 deletions
diff --git a/extensions/openpower-pels/callouts.cpp b/extensions/openpower-pels/callouts.cpp
new file mode 100644
index 0000000..8a519e2
--- /dev/null
+++ b/extensions/openpower-pels/callouts.cpp
@@ -0,0 +1,36 @@
+#include "callouts.hpp"
+
+namespace openpower
+{
+namespace pels
+{
+namespace src
+{
+
+Callouts::Callouts(Stream& pel)
+{
+ pel >> _subsectionID >> _subsectionFlags >> _subsectionWordLength;
+
+ size_t currentLength = sizeof(_subsectionID) + sizeof(_subsectionFlags) +
+ sizeof(_subsectionWordLength);
+
+ while ((_subsectionWordLength * 4) > currentLength)
+ {
+ _callouts.emplace_back(new Callout(pel));
+ currentLength += _callouts.back()->flattenedSize();
+ }
+}
+
+void Callouts::flatten(Stream& pel)
+{
+ pel << _subsectionID << _subsectionFlags << _subsectionWordLength;
+
+ for (auto& callout : _callouts)
+ {
+ callout->flatten(pel);
+ }
+}
+
+} // namespace src
+} // namespace pels
+} // namespace openpower
diff --git a/extensions/openpower-pels/callouts.hpp b/extensions/openpower-pels/callouts.hpp
new file mode 100644
index 0000000..430a5ae
--- /dev/null
+++ b/extensions/openpower-pels/callouts.hpp
@@ -0,0 +1,96 @@
+#pragma once
+
+#include "callout.hpp"
+#include "stream.hpp"
+
+namespace openpower
+{
+namespace pels
+{
+namespace src
+{
+
+/**
+ * @class Callouts
+ *
+ * This is an optional subsection of the SRC section in a PEL
+ * that holds callouts (represented as Callout objects).
+ * It is at the end of the SRC section, and there can only be one
+ * of these present in the SRC.
+ *
+ * If an SRC doesn't have any callouts, this object won't be created.
+ */
+class Callouts
+{
+ public:
+ Callouts() = default;
+ ~Callouts() = default;
+ Callouts(const Callouts&) = delete;
+ Callouts& operator=(const Callouts&) = delete;
+ Callouts(Callouts&&) = delete;
+ Callouts& operator=(Callouts&&) = delete;
+
+ /**
+ * @brief Constructor
+ *
+ * Fills in this class's data fields from the stream.
+ *
+ * @param[in] pel - the PEL data stream
+ */
+ explicit Callouts(Stream& pel);
+
+ /**
+ * @brief Flatten the object into the stream
+ *
+ * @param[in] stream - The stream to write to
+ */
+ void flatten(Stream& pel);
+
+ /**
+ * @brief Returns the size of this object when flattened into a PEL
+ *
+ * @return size_t - The size of the section
+ */
+ size_t flattenedSize()
+ {
+ return _subsectionWordLength * 4;
+ }
+
+ /**
+ * @brief Returns the contained callouts
+ *
+ * @return const std::vector<std::unique_ptr<Callout>>&
+ */
+ const std::vector<std::unique_ptr<Callout>>& callouts() const
+ {
+ return _callouts;
+ }
+
+ private:
+ /**
+ * @brief The ID of this subsection, which is 0xC0.
+ */
+ uint8_t _subsectionID;
+
+ /**
+ * @brief Subsection flags. Always 0.
+ */
+ uint8_t _subsectionFlags;
+
+ /**
+ * @brief Subsection length in 4B words.
+ *
+ * (Subsection is always a multiple of 4B)
+ */
+ uint16_t _subsectionWordLength;
+
+ /**
+ * @brief The contained callouts
+ */
+ std::vector<std::unique_ptr<Callout>> _callouts;
+};
+
+} // namespace src
+
+} // namespace pels
+} // namespace openpower
diff --git a/extensions/openpower-pels/openpower-pels.mk b/extensions/openpower-pels/openpower-pels.mk
index 9308159..a10a4a9 100644
--- a/extensions/openpower-pels/openpower-pels.mk
+++ b/extensions/openpower-pels/openpower-pels.mk
@@ -2,6 +2,7 @@ phosphor_log_manager_SOURCES += \
extensions/openpower-pels/ascii_string.cpp \
extensions/openpower-pels/bcd_time.cpp \
extensions/openpower-pels/callout.cpp \
+ extensions/openpower-pels/callouts.cpp \
extensions/openpower-pels/data_interface.cpp \
extensions/openpower-pels/entry_points.cpp \
extensions/openpower-pels/failing_mtms.cpp \
diff --git a/test/openpower-pels/Makefile.include b/test/openpower-pels/Makefile.include
index ccd5d26..3bc760f 100644
--- a/test/openpower-pels/Makefile.include
+++ b/test/openpower-pels/Makefile.include
@@ -21,6 +21,7 @@ check_PROGRAMS += \
section_header_test \
severity_test \
src_callout_test \
+ src_callouts_test \
stream_test \
user_data_test \
user_header_test
@@ -242,3 +243,18 @@ src_callout_test_LDADD = \
$(top_builddir)/extensions/openpower-pels/mtms.o \
$(top_builddir)/extensions/openpower-pels/pce_identity.o
src_callout_test_LDFLAGS = $(test_ldflags)
+
+src_callouts_test_SOURCES = \
+ %reldir%/src_callouts_test.cpp \
+ %reldir%/pel_utils.cpp
+src_callouts_test_CPPFLAGS = $(test_cppflags)
+src_callouts_test_CXXFLAGS = $(test_cxxflags)
+src_callouts_test_LDADD = \
+ $(test_ldadd) \
+ $(top_builddir)/extensions/openpower-pels/callout.o \
+ $(top_builddir)/extensions/openpower-pels/callouts.o \
+ $(top_builddir)/extensions/openpower-pels/fru_identity.o \
+ $(top_builddir)/extensions/openpower-pels/mru.o \
+ $(top_builddir)/extensions/openpower-pels/mtms.o \
+ $(top_builddir)/extensions/openpower-pels/pce_identity.o
+src_callouts_test_LDFLAGS = $(test_ldflags)
diff --git a/test/openpower-pels/pel_utils.cpp b/test/openpower-pels/pel_utils.cpp
index 3610dd7..f7c9150 100644
--- a/test/openpower-pels/pel_utils.cpp
+++ b/test/openpower-pels/pel_utils.cpp
@@ -113,6 +113,40 @@ std::vector<uint8_t> srcDataFactory(TestSRCType type)
case TestSRCType::mruStructure:
return srcMRUCallout;
+
+ case TestSRCType::calloutStructureA:
+ {
+ // Add just the FRU identity substructure to the base structure
+ std::vector<uint8_t> data{
+ 0xFF, 0x28, 'H', 4, // size, flags, priority, LC length
+ 'U', '4', '2', 0x00 // LC
+ };
+
+ data.insert(data.end(), srcFRUIdentityCallout.begin(),
+ srcFRUIdentityCallout.end());
+
+ // The final size
+ data[0] = data.size();
+ return data;
+ }
+ case TestSRCType::calloutStructureB:
+ {
+ // Add all 3 substructures to the base structure
+
+ std::vector<uint8_t> data{
+ 0xFF, 0x2F, 'L', 8, // size, flags, priority, LC length
+ 'U', '1', '2', '-', 'P', '1', 0x00, 0x00 // LC
+ };
+ data.insert(data.end(), srcFRUIdentityCallout.begin(),
+ srcFRUIdentityCallout.end());
+ data.insert(data.end(), srcPCEIdentityCallout.begin(),
+ srcPCEIdentityCallout.end());
+ data.insert(data.end(), srcMRUCallout.begin(), srcMRUCallout.end());
+
+ // The final size
+ data[0] = data.size();
+ return data;
+ }
}
return {};
}
diff --git a/test/openpower-pels/pel_utils.hpp b/test/openpower-pels/pel_utils.hpp
index 2d40033..7416c31 100644
--- a/test/openpower-pels/pel_utils.hpp
+++ b/test/openpower-pels/pel_utils.hpp
@@ -67,6 +67,8 @@ enum class TestSRCType
fruIdentityStructure,
pceIdentityStructure,
mruStructure,
+ calloutStructureA,
+ calloutStructureB
};
/**
diff --git a/test/openpower-pels/src_callouts_test.cpp b/test/openpower-pels/src_callouts_test.cpp
new file mode 100644
index 0000000..88dd721
--- /dev/null
+++ b/test/openpower-pels/src_callouts_test.cpp
@@ -0,0 +1,76 @@
+#include "extensions/openpower-pels/callouts.hpp"
+#include "pel_utils.hpp"
+
+#include <gtest/gtest.h>
+
+using namespace openpower::pels;
+using namespace openpower::pels::src;
+
+TEST(CalloutsTest, UnflattenFlattenTest)
+{
+ std::vector<uint8_t> data{0xC0, 0x00, 0x00,
+ 0x00}; // ID, flags, length in words
+
+ // Add 2 callouts
+ auto callout = srcDataFactory(TestSRCType::calloutStructureA);
+ data.insert(data.end(), callout.begin(), callout.end());
+
+ callout = srcDataFactory(TestSRCType::calloutStructureB);
+ data.insert(data.end(), callout.begin(), callout.end());
+
+ Stream stream{data};
+
+ // Set the actual word length value at offset 2
+ uint16_t wordLength = data.size() / 4;
+ stream.offset(2);
+ stream << wordLength;
+ stream.offset(0);
+
+ Callouts callouts{stream};
+
+ EXPECT_EQ(callouts.flattenedSize(), data.size());
+ EXPECT_EQ(callouts.callouts().size(), 2);
+
+ // spot check that each callout has the right substructures
+ EXPECT_TRUE(callouts.callouts().front()->fruIdentity());
+ EXPECT_FALSE(callouts.callouts().front()->pceIdentity());
+ EXPECT_FALSE(callouts.callouts().front()->mru());
+
+ EXPECT_TRUE(callouts.callouts().back()->fruIdentity());
+ EXPECT_TRUE(callouts.callouts().back()->pceIdentity());
+ EXPECT_TRUE(callouts.callouts().back()->mru());
+
+ // Flatten
+ std::vector<uint8_t> newData;
+ Stream newStream{newData};
+
+ callouts.flatten(newStream);
+ EXPECT_EQ(data, newData);
+}
+
+TEST(CalloutsTest, BadDataTest)
+{
+ // Start out with a valid 2 callout object, then truncate it.
+ std::vector<uint8_t> data{0xC0, 0x00, 0x00,
+ 0x00}; // ID, flags, length in words
+
+ // Add 2 callouts
+ auto callout = srcDataFactory(TestSRCType::calloutStructureA);
+ data.insert(data.end(), callout.begin(), callout.end());
+
+ callout = srcDataFactory(TestSRCType::calloutStructureB);
+ data.insert(data.end(), callout.begin(), callout.end());
+
+ Stream stream{data};
+
+ // Set the actual word length value at offset 2
+ uint16_t wordLength = data.size() / 4;
+ stream.offset(2);
+ stream << wordLength;
+ stream.offset(0);
+
+ // Shorten the data by an arbitrary amount so unflattening goes awry.
+ data.resize(data.size() - 37);
+
+ EXPECT_THROW(Callouts callouts{stream}, std::out_of_range);
+}
OpenPOWER on IntegriCloud