PEL: Create error log for 'bad PEL'

Create an event log (and a PEL) for the case when the host rejects a PEL
because it is malformed.  This requires a new message registry entry for
the error.

Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: Ibd52921b5d6020f98b457b9ee0b3bb4f0b95e707
diff --git a/extensions/openpower-pels/manager.cpp b/extensions/openpower-pels/manager.cpp
index a00da37..40501a5 100644
--- a/extensions/openpower-pels/manager.cpp
+++ b/extensions/openpower-pels/manager.cpp
@@ -16,6 +16,7 @@
 #include "manager.hpp"
 
 #include "additional_data.hpp"
+#include "json_utils.hpp"
 #include "pel.hpp"
 
 #include <unistd.h>
@@ -250,16 +251,20 @@
         throw common_error::InvalidArgument();
     }
 
-    if (_hostNotifier)
+    if (reason == RejectionReason::BadPEL)
     {
-        if (reason == RejectionReason::BadPEL)
+        AdditionalData data;
+        data.add("BAD_ID", getNumberString("0x%08X", pelID));
+        _eventLogger.log("org.open_power.Logging.Error.SentBadPELToHost",
+                         Entry::Level::Informational, data);
+        if (_hostNotifier)
         {
             _hostNotifier->setBadPEL(pelID);
         }
-        else if (reason == RejectionReason::HostFull)
-        {
-            _hostNotifier->setHostFull(pelID);
-        }
+    }
+    else if ((reason == RejectionReason::HostFull) && _hostNotifier)
+    {
+        _hostNotifier->setHostFull(pelID);
     }
 }
 
diff --git a/extensions/openpower-pels/registry/message_registry.json b/extensions/openpower-pels/registry/message_registry.json
index 7e278e3..6b4ab45 100644
--- a/extensions/openpower-pels/registry/message_registry.json
+++ b/extensions/openpower-pels/registry/message_registry.json
@@ -132,6 +132,34 @@
                 "Description": "The server's CA certificate has not been provided",
                 "Message": "The server's CA certificate has not been provided"
             }
+        },
+
+        {
+            "Name": "org.open_power.Logging.Error.SentBadPELToHost",
+            "Subsystem": "bmc_firmware",
+            "Severity": "non_error",
+
+            "SRC":
+            {
+                "ReasonCode": "0x2001",
+                "Words6To9":
+                {
+                    "6":
+                    {
+                        "Description": "The bad PEL ID",
+                        "AdditionalDataPropSource": "BAD_ID"
+                    }
+                }
+            },
+
+            "Documentation":
+            {
+                "Description": "The BMC sent the host a malformed PEL",
+                "Message": "The BMC sent the host a malformed PEL",
+                "Notes": [
+                    "The host firmware rejected that PEL."
+                ]
+            }
         }
     ]
 }
diff --git a/test/openpower-pels/pel_manager_test.cpp b/test/openpower-pels/pel_manager_test.cpp
index 28802f4..5305468 100644
--- a/test/openpower-pels/pel_manager_test.cpp
+++ b/test/openpower-pels/pel_manager_test.cpp
@@ -26,6 +26,22 @@
 using namespace openpower::pels;
 namespace fs = std::filesystem;
 
+class TestLogger
+{
+  public:
+    void log(const std::string& name, phosphor::logging::Entry::Level level,
+             const EventLogger::ADMap& additionalData)
+    {
+        errName = name;
+        errLevel = level;
+        ad = additionalData;
+    }
+
+    std::string errName;
+    phosphor::logging::Entry::Level errLevel;
+    EventLogger::ADMap ad;
+};
+
 class ManagerTest : public CleanPELFiles
 {
   public:
@@ -43,6 +59,7 @@
     sdbusplus::bus::bus bus = sdbusplus::bus::new_default();
     phosphor::logging::internal::Manager logManager;
     sd_event* sdEvent;
+    TestLogger logger;
 };
 
 fs::path makeTempDir()
@@ -67,11 +84,6 @@
     return std::nullopt;
 }
 
-void eventLoggerStub(const std::string&, phosphor::logging::Entry::Level,
-                     const EventLogger::ADMap&)
-{
-}
-
 // Test that using the RAWPEL=<file> with the Manager::create() call gets
 // a PEL saved in the repository.
 TEST_F(ManagerTest, TestCreateWithPEL)
@@ -79,8 +91,10 @@
     std::unique_ptr<DataInterfaceBase> dataIface =
         std::make_unique<DataInterface>(bus);
 
-    openpower::pels::Manager manager{logManager, std::move(dataIface),
-                                     eventLoggerStub};
+    openpower::pels::Manager manager{
+        logManager, std::move(dataIface),
+        std::bind(std::mem_fn(&TestLogger::log), &logger, std::placeholders::_1,
+                  std::placeholders::_2, std::placeholders::_3)};
 
     // Create a PEL, write it to a file, and pass that filename into
     // the create function.
@@ -150,8 +164,10 @@
     std::unique_ptr<DataInterfaceBase> dataIface =
         std::make_unique<DataInterface>(logManager.getBus());
 
-    openpower::pels::Manager manager{logManager, std::move(dataIface),
-                                     eventLoggerStub};
+    openpower::pels::Manager manager{
+        logManager, std::move(dataIface),
+        std::bind(std::mem_fn(&TestLogger::log), &logger, std::placeholders::_1,
+                  std::placeholders::_2, std::placeholders::_3)};
 
     std::vector<std::string> additionalData;
     std::vector<std::string> associations;
@@ -195,7 +211,10 @@
     std::unique_ptr<DataInterfaceBase> dataIface =
         std::make_unique<DataInterface>(bus);
 
-    Manager manager{logManager, std::move(dataIface), eventLoggerStub};
+    Manager manager{logManager, std::move(dataIface),
+                    std::bind(std::mem_fn(&TestLogger::log), &logger,
+                              std::placeholders::_1, std::placeholders::_2,
+                              std::placeholders::_3)};
 
     // Create a PEL, write it to a file, and pass that filename into
     // the create function so there's one in the repo.
@@ -248,6 +267,10 @@
 
     fclose(fp);
 
+    // Run the event loop to close the FD
+    sdeventplus::Event e{sdEvent};
+    e.run(std::chrono::milliseconds(1));
+
     EXPECT_THROW(
         manager.getPEL(id + 1),
         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
@@ -261,6 +284,13 @@
 
     // hostReject
     manager.hostReject(id, Manager::RejectionReason::BadPEL);
+
+    // Run the event loop to log the bad PEL event
+    e.run(std::chrono::milliseconds(1));
+
+    EXPECT_EQ(logger.errName, "org.open_power.Logging.Error.SentBadPELToHost");
+    EXPECT_EQ(id, std::stoi(logger.ad["BAD_ID"], nullptr, 16));
+
     manager.hostReject(id, Manager::RejectionReason::HostFull);
 
     EXPECT_THROW(