diff options
-rw-r--r-- | extensions/openpower-pels/openpower-pels.mk | 1 | ||||
-rw-r--r-- | extensions/openpower-pels/pce_identity.cpp | 33 | ||||
-rw-r--r-- | extensions/openpower-pels/pce_identity.hpp | 125 | ||||
-rw-r--r-- | test/openpower-pels/Makefile.include | 10 | ||||
-rw-r--r-- | test/openpower-pels/pce_identity_test.cpp | 42 |
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); +} |