PEL: Add SRC PEL section class
This section consists of:
- An 8B header
- 8 4B words of hex data
- Some data is predefined based on the SRC format, some is free format.
- A 32B ASCII character string (The AsciiString class)
- An optional section for FRU callouts (The Callouts class)
Usually, the term SRC (System Reference Code) refers to the contents of
the ASCII string and the hex data words, which can then be looked up in
service documentation to find the meaning of the event log. This PEL
section wraps this pure SRC with additional data like callouts.
This commit only adds support for unflattening the section from an
existing PEL, and flattening it again. Future commits will add support
for creating an SRC from message registry data.
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: I3dd97c6aca59cc6d6d6fadef84465164090d5658
diff --git a/test/openpower-pels/Makefile.include b/test/openpower-pels/Makefile.include
index 3bc760f..d110cc1 100644
--- a/test/openpower-pels/Makefile.include
+++ b/test/openpower-pels/Makefile.include
@@ -20,6 +20,7 @@
repository_test \
section_header_test \
severity_test \
+ src_test \
src_callout_test \
src_callouts_test \
stream_test \
@@ -27,17 +28,24 @@
user_header_test
pel_objects = \
+ $(top_builddir)/extensions/openpower-pels/ascii_string.o \
$(top_builddir)/extensions/openpower-pels/bcd_time.o \
+ $(top_builddir)/extensions/openpower-pels/callout.o \
+ $(top_builddir)/extensions/openpower-pels/callouts.o \
$(top_builddir)/extensions/openpower-pels/failing_mtms.o \
+ $(top_builddir)/extensions/openpower-pels/fru_identity.o \
$(top_builddir)/extensions/openpower-pels/generic.o \
$(top_builddir)/extensions/openpower-pels/log_id.o \
$(top_builddir)/extensions/openpower-pels/mtms.o \
+ $(top_builddir)/extensions/openpower-pels/mru.o \
+ $(top_builddir)/extensions/openpower-pels/pce_identity.o \
$(top_builddir)/extensions/openpower-pels/pel.o \
$(top_builddir)/extensions/openpower-pels/pel_values.o \
$(top_builddir)/extensions/openpower-pels/private_header.o \
$(top_builddir)/extensions/openpower-pels/registry.o \
$(top_builddir)/extensions/openpower-pels/section_factory.o \
$(top_builddir)/extensions/openpower-pels/severity.o \
+ $(top_builddir)/extensions/openpower-pels/src.o \
$(top_builddir)/extensions/openpower-pels/user_data.o \
$(top_builddir)/extensions/openpower-pels/user_header.o
@@ -258,3 +266,20 @@
$(top_builddir)/extensions/openpower-pels/mtms.o \
$(top_builddir)/extensions/openpower-pels/pce_identity.o
src_callouts_test_LDFLAGS = $(test_ldflags)
+
+src_test_SOURCES = \
+ %reldir%/src_test.cpp \
+ %reldir%/pel_utils.cpp
+src_test_CPPFLAGS = $(test_cppflags)
+src_test_CXXFLAGS = $(test_cxxflags)
+src_test_LDADD = \
+ $(test_ldadd) \
+ $(top_builddir)/extensions/openpower-pels/ascii_string.o \
+ $(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 \
+ $(top_builddir)/extensions/openpower-pels/src.o
+src_test_LDFLAGS = $(test_ldflags)
diff --git a/test/openpower-pels/pel_utils.cpp b/test/openpower-pels/pel_utils.cpp
index f7c9150..109c1ce 100644
--- a/test/openpower-pels/pel_utils.cpp
+++ b/test/openpower-pels/pel_utils.cpp
@@ -78,6 +78,25 @@
0x04, 0x04, 0x04, 0x04, // MRU ID 3
};
+std::vector<uint8_t> srcSectionNoCallouts{
+
+ // Header
+ 'P', 'S', 0x00, 0x80, 0x01, 0x01, 0x02, 0x02,
+
+ // SRC
+ 0x02, 0x00, 0x00, // version, flags, reserved
+ 0x09, 0x00, 0x00, // hex word count, reserved2B
+ 0x00, 0x48, // SRC structure size
+
+ // Hex words 2 - 9
+ 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04,
+ 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07,
+ 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09,
+ // ASCII string
+ 'B', 'D', '8', 'D', '5', '6', '7', '8', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' '};
+
std::unique_ptr<std::vector<uint8_t>> pelDataFactory(TestPelType type)
{
std::unique_ptr<std::vector<uint8_t>> data;
@@ -147,6 +166,59 @@
data[0] = data.size();
return data;
}
+ case TestSRCType::calloutSection2Callouts:
+ {
+ 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());
+
+ // Set the actual word length value at offset 2
+ Stream stream{data};
+ uint16_t wordLength = data.size() / 4;
+ stream.offset(2);
+ stream << wordLength;
+ stream.offset(0);
+
+ return data;
+ }
+ case TestSRCType::primarySRCNoCallouts:
+ {
+ return srcSectionNoCallouts;
+ }
+ case TestSRCType::primarySRC2Callouts:
+ {
+ // Start with the no-callouts SRC, and add the callouts section
+ // from above.
+ auto src = srcSectionNoCallouts;
+ auto callouts =
+ srcDataFactory(TestSRCType::calloutSection2Callouts);
+
+ src.insert(src.end(), callouts.begin(), callouts.end());
+
+ // Set the flag that says there are callouts
+ // One byte after the 8B header
+ src[8 + 1] |= 0x01;
+
+ // Set the new sizes
+ uint16_t size = src.size();
+ Stream stream{src};
+
+ stream.offset(2); // In the header
+ stream << size;
+
+ // In the SRC - the size field doesn't include the header
+ size -= 8;
+ stream.offset(8 + 6);
+ stream << size;
+
+ return src;
+ }
}
return {};
}
diff --git a/test/openpower-pels/pel_utils.hpp b/test/openpower-pels/pel_utils.hpp
index 7416c31..6d70dfa 100644
--- a/test/openpower-pels/pel_utils.hpp
+++ b/test/openpower-pels/pel_utils.hpp
@@ -68,7 +68,10 @@
pceIdentityStructure,
mruStructure,
calloutStructureA,
- calloutStructureB
+ calloutStructureB,
+ calloutSection2Callouts,
+ primarySRCNoCallouts,
+ primarySRC2Callouts
};
/**
diff --git a/test/openpower-pels/src_test.cpp b/test/openpower-pels/src_test.cpp
new file mode 100644
index 0000000..7af3306
--- /dev/null
+++ b/test/openpower-pels/src_test.cpp
@@ -0,0 +1,82 @@
+#include "extensions/openpower-pels/src.hpp"
+#include "pel_utils.hpp"
+
+#include <gtest/gtest.h>
+
+using namespace openpower::pels;
+
+TEST(SRCTest, UnflattenFlattenTestNoCallouts)
+{
+ auto data = srcDataFactory(TestSRCType::primarySRCNoCallouts);
+
+ Stream stream{data};
+ SRC src{stream};
+
+ EXPECT_TRUE(src.valid());
+
+ EXPECT_EQ(src.header().id, 0x5053);
+ EXPECT_EQ(src.header().size, 0x80);
+ EXPECT_EQ(src.header().version, 0x01);
+ EXPECT_EQ(src.header().subType, 0x01);
+ EXPECT_EQ(src.header().componentID, 0x0202);
+
+ EXPECT_EQ(src.version(), 0x02);
+ EXPECT_EQ(src.flags(), 0x00);
+ EXPECT_EQ(src.hexWordCount(), 9);
+ EXPECT_EQ(src.size(), 0x48);
+
+ const auto& hexwords = src.hexwordData();
+ EXPECT_EQ(0x02020202, hexwords[0]);
+ EXPECT_EQ(0x03030303, hexwords[1]);
+ EXPECT_EQ(0x04040404, hexwords[2]);
+ EXPECT_EQ(0x05050505, hexwords[3]);
+ EXPECT_EQ(0x06060606, hexwords[4]);
+ EXPECT_EQ(0x07070707, hexwords[5]);
+ EXPECT_EQ(0x08080808, hexwords[6]);
+ EXPECT_EQ(0x09090909, hexwords[7]);
+
+ EXPECT_EQ(src.asciiString(), "BD8D5678 ");
+ EXPECT_FALSE(src.callouts());
+
+ // Flatten
+ std::vector<uint8_t> newData;
+ Stream newStream{newData};
+
+ src.flatten(newStream);
+ EXPECT_EQ(data, newData);
+}
+
+TEST(SRCTest, UnflattenFlattenTest2Callouts)
+{
+ auto data = srcDataFactory(TestSRCType::primarySRC2Callouts);
+
+ Stream stream{data};
+ SRC src{stream};
+
+ EXPECT_TRUE(src.valid());
+
+ // Spot check the SRC fields, but they're the same as above
+ EXPECT_EQ(src.asciiString(), "BD8D5678 ");
+
+ // There should be 2 callouts
+ const auto& calloutsSection = src.callouts();
+ ASSERT_TRUE(calloutsSection);
+ const auto& callouts = calloutsSection->callouts();
+ EXPECT_EQ(callouts.size(), 2);
+
+ // spot check that each callout has the right substructures
+ EXPECT_TRUE(callouts.front()->fruIdentity());
+ EXPECT_FALSE(callouts.front()->pceIdentity());
+ EXPECT_FALSE(callouts.front()->mru());
+
+ EXPECT_TRUE(callouts.back()->fruIdentity());
+ EXPECT_TRUE(callouts.back()->pceIdentity());
+ EXPECT_TRUE(callouts.back()->mru());
+
+ // Flatten
+ std::vector<uint8_t> newData;
+ Stream newStream{newData};
+
+ src.flatten(newStream);
+ EXPECT_EQ(data, newData);
+}