summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--extensions/openpower-pels/openpower-pels.mk1
-rw-r--r--extensions/openpower-pels/pce_identity.cpp33
-rw-r--r--extensions/openpower-pels/pce_identity.hpp125
-rw-r--r--test/openpower-pels/Makefile.include10
-rw-r--r--test/openpower-pels/pce_identity_test.cpp42
5 files changed, 211 insertions, 0 deletions
diff --git a/extensions/openpower-pels/openpower-pels.mk b/extensions/openpower-pels/openpower-pels.mk
index 9a4f4fc..550530c 100644
--- a/extensions/openpower-pels/openpower-pels.mk
+++ b/extensions/openpower-pels/openpower-pels.mk
@@ -10,6 +10,7 @@ phosphor_log_manager_SOURCES += \
extensions/openpower-pels/manager.cpp \
extensions/openpower-pels/mtms.cpp \
extensions/openpower-pels/paths.cpp \
+ extensions/openpower-pels/pce_identity.cpp \
extensions/openpower-pels/pel.cpp \
extensions/openpower-pels/pel_values.cpp \
extensions/openpower-pels/private_header.cpp \
diff --git a/extensions/openpower-pels/pce_identity.cpp b/extensions/openpower-pels/pce_identity.cpp
new file mode 100644
index 0000000..12b21ae
--- /dev/null
+++ b/extensions/openpower-pels/pce_identity.cpp
@@ -0,0 +1,33 @@
+#include "pce_identity.hpp"
+
+namespace openpower
+{
+namespace pels
+{
+namespace src
+{
+
+PCEIdentity::PCEIdentity(Stream& pel)
+{
+ pel >> _type >> _size >> _flags >> _mtms;
+
+ // Whatever is left is the enclosure name.
+ if (_size < (4 + _mtms.flattenedSize()))
+ {
+ throw std::runtime_error("PCE identity structure size field too small");
+ }
+
+ size_t pceNameSize = _size - (4 + _mtms.flattenedSize());
+
+ _pceName.resize(pceNameSize);
+ pel >> _pceName;
+}
+
+void PCEIdentity::flatten(Stream& pel)
+{
+ pel << _type << _size << _flags << _mtms << _pceName;
+}
+
+} // namespace src
+} // namespace pels
+} // namespace openpower
diff --git a/extensions/openpower-pels/pce_identity.hpp b/extensions/openpower-pels/pce_identity.hpp
new file mode 100644
index 0000000..4503764
--- /dev/null
+++ b/extensions/openpower-pels/pce_identity.hpp
@@ -0,0 +1,125 @@
+#pragma once
+
+#include "mtms.hpp"
+#include "stream.hpp"
+
+namespace openpower
+{
+namespace pels
+{
+namespace src
+{
+
+/**
+ * @class PCEIdentity
+ *
+ * This represents the PCE (Power Controlling Enclosure) Identity
+ * substructure in the callout subsection of the SRC PEL section.
+ *
+ * It contains the name and machine type/model/SN of that enclosure.
+ *
+ * It is only used for errors in an I/O drawer where another enclosure
+ * may control its power. It is not used in BMC errors and so will
+ * never be created by the BMC, but only unflattened in errors it
+ * receives from the host.
+ */
+class PCEIdentity
+{
+ public:
+ PCEIdentity() = delete;
+ ~PCEIdentity() = default;
+ PCEIdentity(const PCEIdentity&) = default;
+ PCEIdentity& operator=(const PCEIdentity&) = default;
+ PCEIdentity(PCEIdentity&&) = default;
+ PCEIdentity& operator=(PCEIdentity&&) = default;
+
+ /**
+ * @brief Constructor
+ *
+ * Fills in this class's data fields from the stream.
+ *
+ * @param[in] pel - the PEL data stream
+ */
+ explicit PCEIdentity(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 structure when flattened into a PEL
+ *
+ * @return size_t - The size of the structure
+ */
+ size_t flattenedSize()
+ {
+ return _size;
+ }
+
+ /**
+ * @brief The type identifier value of this structure.
+ */
+ static const uint16_t substructureType = 0x5045; // "PE"
+
+ /**
+ * @brief Returns the enclosure name
+ *
+ * @return std::string - The enclosure name
+ */
+ std::string enclosureName() const
+ {
+ // _pceName is NULL terminated
+ std::string name{static_cast<const char*>(_pceName.data())};
+ return name;
+ }
+
+ /**
+ * @brief Returns the MTMS sub structure
+ *
+ * @return const MTMS& - The machine type/model/SN structure.
+ */
+ const MTMS& mtms() const
+ {
+ return _mtms;
+ }
+
+ private:
+ /**
+ * @brief The callout substructure type field. Will be 'PE'.
+ */
+ uint16_t _type;
+
+ /**
+ * @brief The size of this callout structure.
+ *
+ * Always a multiple of 4.
+ */
+ uint8_t _size;
+
+ /**
+ * @brief The flags byte of this substructure.
+ *
+ * Always 0 for this structure.
+ */
+ uint8_t _flags;
+
+ /**
+ * @brief The structure that holds the power controlling enclosure's
+ * machine type, model, and serial number.
+ */
+ MTMS _mtms;
+
+ /**
+ * @brief The name of the power controlling enclosure.
+ *
+ * Null terminated and padded with NULLs to a 4 byte boundary.
+ */
+ std::vector<char> _pceName;
+};
+
+} // namespace src
+} // namespace pels
+} // namespace openpower
diff --git a/test/openpower-pels/Makefile.include b/test/openpower-pels/Makefile.include
index f824030..74e33c6 100644
--- a/test/openpower-pels/Makefile.include
+++ b/test/openpower-pels/Makefile.include
@@ -9,6 +9,7 @@ check_PROGRAMS += \
generic_section_test \
log_id_test \
mtms_test \
+ pce_identity_test \
pel_test \
pel_values_test \
pel_manager_test \
@@ -208,3 +209,12 @@ fru_identity_test_LDADD = \
$(test_ldadd) \
$(top_builddir)/extensions/openpower-pels/fru_identity.o
fru_identity_test_LDFLAGS = $(test_ldflags)
+
+pce_identity_test_SOURCES = %reldir%/pce_identity_test.cpp
+pce_identity_test_CPPFLAGS = $(test_cppflags)
+pce_identity_test_CXXFLAGS = $(test_cxxflags)
+pce_identity_test_LDADD = \
+ $(test_ldadd) \
+ $(top_builddir)/extensions/openpower-pels/pce_identity.o \
+ $(top_builddir)/extensions/openpower-pels/mtms.o
+pce_identity_test_LDFLAGS = $(test_ldflags)
diff --git a/test/openpower-pels/pce_identity_test.cpp b/test/openpower-pels/pce_identity_test.cpp
new file mode 100644
index 0000000..8a3018c
--- /dev/null
+++ b/test/openpower-pels/pce_identity_test.cpp
@@ -0,0 +1,42 @@
+#include "extensions/openpower-pels/pce_identity.hpp"
+
+#include <gtest/gtest.h>
+
+using namespace openpower::pels;
+using namespace openpower::pels::src;
+
+TEST(PCEIdentityTest, TestConstructor)
+{
+ std::vector<uint8_t> data{
+ 'P', 'E', 0x24, 0x00, // type, size, flags
+ 'T', 'T', 'T', 'T', '-', 'M', 'M', 'M', // MTM
+ '1', '2', '3', '4', '5', '6', '7', // SN
+ '8', '9', 'A', 'B', 'C', 'P', 'C', 'E', // Name + null padded
+ 'N', 'A', 'M', 'E', '1', '2', 0x00, 0x00, 0x00};
+
+ Stream stream{data};
+
+ PCEIdentity pce{stream};
+
+ EXPECT_EQ(pce.flattenedSize(), data.size());
+ EXPECT_EQ(pce.enclosureName(), "PCENAME12");
+ EXPECT_EQ(pce.mtms().machineTypeAndModel(), "TTTT-MMM");
+ EXPECT_EQ(pce.mtms().machineSerialNumber(), "123456789ABC");
+
+ // Flatten it
+ std::vector<uint8_t> newData;
+ Stream newStream{newData};
+ pce.flatten(newStream);
+
+ EXPECT_EQ(data, newData);
+}
+
+TEST(PCEIdentityTest, TestBadData)
+{
+ std::vector<uint8_t> data{
+ 'P', 'E', 0x20, 0x00, 'T', 'T', 'T', 'T', '-',
+ };
+
+ Stream stream{data};
+ EXPECT_THROW(PCEIdentity pce{stream}, std::out_of_range);
+}
OpenPOWER on IntegriCloud