PEL: Create UserHeader from parameters

Add a constructor to the UserHeader section class so it can be built
from the message registry entry for that error along with the event log
severity.

This will be used when creating PELs from OpenBMC event logs.

Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: I7e432f59de7b3f0ba77c3e5887ed5ec3f442ed44
diff --git a/extensions/openpower-pels/pel_types.hpp b/extensions/openpower-pels/pel_types.hpp
index 3d9e457..9f801a3 100644
--- a/extensions/openpower-pels/pel_types.hpp
+++ b/extensions/openpower-pels/pel_types.hpp
@@ -66,5 +66,21 @@
     slic = 'S',
 };
 
+/**
+ * @brief Useful event scope values
+ */
+enum class EventScope
+{
+    entirePlatform = 0x03
+};
+
+/**
+ * @brief Useful event type values
+ */
+enum class EventType
+{
+    notApplicable = 0x00
+};
+
 } // namespace pels
 } // namespace openpower
diff --git a/extensions/openpower-pels/user_header.cpp b/extensions/openpower-pels/user_header.cpp
index e5e8abb..6dfbc09 100644
--- a/extensions/openpower-pels/user_header.cpp
+++ b/extensions/openpower-pels/user_header.cpp
@@ -1,6 +1,7 @@
 #include "user_header.hpp"
 
 #include "pel_types.hpp"
+#include "severity.hpp"
 
 #include <phosphor-logging/log.hpp>
 
@@ -25,6 +26,43 @@
            << _actionFlags << _reserved4Byte2;
 }
 
+UserHeader::UserHeader(const message::Entry& entry,
+                       phosphor::logging::Entry::Level severity)
+{
+    _header.id = static_cast<uint16_t>(SectionID::userHeader);
+    _header.size = UserHeader::flattenedSize();
+    _header.version = userHeaderVersion;
+    _header.subType = 0;
+    _header.componentID = static_cast<uint16_t>(ComponentID::phosphorLogging);
+
+    _eventSubsystem = entry.subsystem;
+
+    _eventScope = entry.eventScope.value_or(
+        static_cast<uint8_t>(EventScope::entirePlatform));
+
+    // Get the severity from the registry if it's there, otherwise get it
+    // from the OpenBMC event log severity value.
+    _eventSeverity =
+        entry.severity.value_or(convertOBMCSeverityToPEL(severity));
+
+    // TODO: ibm-dev/dev/#1144 Handle manufacturing sev & action flags
+
+    _eventType = entry.eventType.value_or(
+        static_cast<uint8_t>(EventType::notApplicable));
+
+    _reserved4Byte1 = 0;
+
+    // No uses for problem domain or vector
+    _problemDomain = 0;
+    _problemVector = 0;
+
+    _actionFlags = entry.actionFlags;
+
+    _reserved4Byte2 = 0;
+
+    _valid = true;
+}
+
 UserHeader::UserHeader(Stream& pel)
 {
     try
diff --git a/extensions/openpower-pels/user_header.hpp b/extensions/openpower-pels/user_header.hpp
index 5e64ff4..c1b6636 100644
--- a/extensions/openpower-pels/user_header.hpp
+++ b/extensions/openpower-pels/user_header.hpp
@@ -1,5 +1,7 @@
 #pragma once
 
+#include "elog_entry.hpp"
+#include "registry.hpp"
 #include "section.hpp"
 #include "stream.hpp"
 
@@ -35,6 +37,17 @@
     /**
      * @brief Constructor
      *
+     * Creates a valid UserHeader with the passed in data.
+     *
+     * @param[in] entry - The message registry entry for this error
+     * @param[in] severity - The OpenBMC event log severity for this error
+     */
+    UserHeader(const message::Entry& entry,
+               phosphor::logging::Entry::Level severity);
+
+    /**
+     * @brief Constructor
+     *
      * Fills in this class's data fields from the stream.
      *
      * @param[in] pel - the PEL data stream
diff --git a/test/openpower-pels/user_header_test.cpp b/test/openpower-pels/user_header_test.cpp
index 0f22132..d3eedfc 100644
--- a/test/openpower-pels/user_header_test.cpp
+++ b/test/openpower-pels/user_header_test.cpp
@@ -1,3 +1,5 @@
+#include "elog_entry.hpp"
+#include "extensions/openpower-pels/pel_types.hpp"
 #include "extensions/openpower-pels/private_header.hpp"
 #include "extensions/openpower-pels/user_header.hpp"
 #include "pel_utils.hpp"
@@ -91,3 +93,70 @@
 
     EXPECT_EQ(uh.valid(), false);
 }
+
+// Construct the User Header from the message registry
+TEST(UserHeaderTest, ConstructionTest)
+{
+    using namespace openpower::pels::message;
+    Entry regEntry;
+
+    regEntry.name = "test";
+    regEntry.subsystem = 5;
+    regEntry.severity = 0x40;
+    regEntry.actionFlags = 0xC000;
+    regEntry.eventType = 1;
+    regEntry.eventScope = 2;
+
+    UserHeader uh(regEntry, phosphor::logging::Entry::Level::Error);
+
+    ASSERT_TRUE(uh.valid());
+    EXPECT_EQ(uh.header().id, 0x5548);
+    EXPECT_EQ(uh.header().size, UserHeader::flattenedSize());
+    EXPECT_EQ(uh.header().version, 0x01);
+    EXPECT_EQ(uh.header().subType, 0x00);
+    EXPECT_EQ(uh.header().componentID,
+              static_cast<uint16_t>(ComponentID::phosphorLogging));
+
+    ASSERT_EQ(uh.subsystem(), 5);
+    ASSERT_EQ(uh.severity(), 0x40);
+    ASSERT_EQ(uh.eventType(), 1);
+    ASSERT_EQ(uh.scope(), 2);
+    ASSERT_EQ(uh.problemDomain(), 0);
+    ASSERT_EQ(uh.problemVector(), 0);
+    ASSERT_EQ(uh.actionFlags(), 0xC000);
+}
+
+// Test that the severity comes from the event log if not
+// in the message registry
+TEST(UserHeaderTest, UseEventLogSevTest)
+{
+    using namespace openpower::pels::message;
+    Entry regEntry;
+
+    regEntry.name = "test";
+    regEntry.subsystem = 5;
+    regEntry.actionFlags = 0xC000;
+    regEntry.eventType = 1;
+    regEntry.eventScope = 2;
+    // Leave off severity
+
+    UserHeader uh(regEntry, phosphor::logging::Entry::Level::Error);
+    ASSERT_EQ(uh.severity(), 0x40);
+}
+
+// Test that the optional event type & scope fields work
+TEST(UserHeaderTest, DefaultEventTypeScopeTest)
+{
+    using namespace openpower::pels::message;
+    Entry regEntry;
+
+    regEntry.name = "test";
+    regEntry.subsystem = 5;
+    regEntry.severity = 0x40;
+    regEntry.actionFlags = 0xC000;
+
+    UserHeader uh(regEntry, phosphor::logging::Entry::Level::Error);
+
+    ASSERT_EQ(uh.eventType(), 0);
+    ASSERT_EQ(uh.scope(), 0x03);
+}