PEL: Add PELs from ESELs

When the OpenPower host firmware subsystem hostboot creates PELs, those
PELs get added to OpenBMC event logs in the ESEL entry of the
AdditionalData property.  (Eventually hostboot will update their code to
use PLDM to send down PELs.)

This commit looks for that ESEL keyword on incoming event logs, extracts
the PEL data, and adds it to the PEL repository with all of the other
PELs.

It extracts the PEL data by converting the string value to a vector of
uint8_ts starting after the IPMI data fields contained in that string.

Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: I2b7f2915dceb9c306466b8181cae05a3ddd65057
diff --git a/extensions/openpower-pels/manager.cpp b/extensions/openpower-pels/manager.cpp
index 05ccb42..4eb6772 100644
--- a/extensions/openpower-pels/manager.cpp
+++ b/extensions/openpower-pels/manager.cpp
@@ -39,7 +39,8 @@
 namespace additional_data
 {
 constexpr auto rawPEL = "RAWPEL";
-}
+constexpr auto esel = "ESEL";
+} // namespace additional_data
 
 void Manager::create(const std::string& message, uint32_t obmcLogID,
                      uint64_t timestamp, Entry::Level severity,
@@ -48,7 +49,8 @@
 {
     AdditionalData ad{additionalData};
 
-    // If a PEL was passed in, use that.  Otherwise, create one.
+    // If a PEL was passed in via a filename or in an ESEL,
+    // use that.  Otherwise, create one.
     auto rawPelPath = ad.getValue(additional_data::rawPEL);
     if (rawPelPath)
     {
@@ -56,8 +58,16 @@
     }
     else
     {
-        createPEL(message, obmcLogID, timestamp, severity, additionalData,
-                  associations);
+        auto esel = ad.getValue(additional_data::esel);
+        if (esel)
+        {
+            addESELPEL(*esel, obmcLogID);
+        }
+        else
+        {
+            createPEL(message, obmcLogID, timestamp, severity, additionalData,
+                      associations);
+        }
     }
 }
 
@@ -80,48 +90,7 @@
 
         file.close();
 
-        auto pel = std::make_unique<openpower::pels::PEL>(data, obmcLogID);
-        if (pel->valid())
-        {
-            // PELs created by others still need these fields set by us.
-            pel->assignID();
-            pel->setCommitTime();
-
-            try
-            {
-                _repo.add(pel);
-            }
-            catch (std::exception& e)
-            {
-                // Probably a full or r/o filesystem, not much we can do.
-                log<level::ERR>("Unable to add PEL to Repository",
-                                entry("PEL_ID=0x%X", pel->id()));
-            }
-        }
-        else
-        {
-            log<level::ERR>("Invalid PEL received from the host",
-                            entry("PELFILE=%s", rawPelPath.c_str()),
-                            entry("OBMCLOGID=%d", obmcLogID));
-
-            AdditionalData ad;
-            ad.add("PLID", getNumberString("0x%08X", pel->plid()));
-            ad.add("OBMC_LOG_ID", std::to_string(obmcLogID));
-            ad.add("RAW_PEL_FILENAME", rawPelPath);
-            ad.add("PEL_SIZE", std::to_string(data.size()));
-
-            std::string asciiString;
-            auto src = pel->primarySRC();
-            if (src)
-            {
-                asciiString = (*src)->asciiString();
-            }
-
-            ad.add("SRC", asciiString);
-
-            _eventLogger.log("org.open_power.Logging.Error.BadHostPEL",
-                             Entry::Level::Error, ad);
-        }
+        addPEL(data, obmcLogID);
     }
     else
     {
@@ -131,6 +100,105 @@
     }
 }
 
+void Manager::addPEL(std::vector<uint8_t>& pelData, uint32_t obmcLogID)
+{
+
+    auto pel = std::make_unique<openpower::pels::PEL>(pelData, obmcLogID);
+    if (pel->valid())
+    {
+        // PELs created by others still need these fields set by us.
+        pel->assignID();
+        pel->setCommitTime();
+
+        try
+        {
+            _repo.add(pel);
+        }
+        catch (std::exception& e)
+        {
+            // Probably a full or r/o filesystem, not much we can do.
+            log<level::ERR>("Unable to add PEL to Repository",
+                            entry("PEL_ID=0x%X", pel->id()));
+        }
+    }
+    else
+    {
+        log<level::ERR>("Invalid PEL received from the host",
+                        entry("OBMCLOGID=%d", obmcLogID));
+
+        AdditionalData ad;
+        ad.add("PLID", getNumberString("0x%08X", pel->plid()));
+        ad.add("OBMC_LOG_ID", std::to_string(obmcLogID));
+        ad.add("PEL_SIZE", std::to_string(pelData.size()));
+
+        std::string asciiString;
+        auto src = pel->primarySRC();
+        if (src)
+        {
+            asciiString = (*src)->asciiString();
+        }
+
+        ad.add("SRC", asciiString);
+
+        _eventLogger.log("org.open_power.Logging.Error.BadHostPEL",
+                         Entry::Level::Error, ad);
+    }
+}
+
+void Manager::addESELPEL(const std::string& esel, uint32_t obmcLogID)
+{
+    std::vector<uint8_t> data;
+
+    try
+    {
+        data = std::move(eselToRawData(esel));
+    }
+    catch (std::exception& e)
+    {
+        // Try to add it below anyway, so it follows the usual bad data path.
+        log<level::ERR>("Problems converting ESEL string to a byte vector");
+    }
+
+    addPEL(data, obmcLogID);
+}
+
+std::vector<uint8_t> Manager::eselToRawData(const std::string& esel)
+{
+    std::vector<uint8_t> data;
+    std::string byteString;
+
+    // As the eSEL string looks like: "50 48 00 ab ..." there are 3
+    // characters per raw byte, and since the actual PEL data starts
+    // at the 16th byte, the code will grab the PEL data starting at
+    // offset 48 in the string.
+    static constexpr size_t pelStart = 16 * 3;
+
+    if (esel.size() <= pelStart)
+    {
+        log<level::ERR>("ESEL data too short",
+                        entry("ESEL_SIZE=%d", esel.size()));
+
+        throw std::length_error("ESEL data too short");
+    }
+
+    for (size_t i = pelStart; i < esel.size(); i += 3)
+    {
+        if (i + 1 < esel.size())
+        {
+            byteString = esel.substr(i, 2);
+            data.push_back(std::stoi(byteString, nullptr, 16));
+        }
+        else
+        {
+            log<level::ERR>("ESEL data too short",
+                            entry("ESEL_SIZE=%d", esel.size()));
+            throw std::length_error("ESEL data too short");
+        }
+    }
+
+    return data;
+}
+
 void Manager::erase(uint32_t obmcLogID)
 {
     Repository::LogID id{Repository::LogID::Obmc(obmcLogID)};
@@ -165,8 +233,7 @@
         if (src)
         {
             using namespace std::literals::string_literals;
-            char id[11];
-            sprintf(id, "0x%08X", pel->id());
+            auto id = getNumberString("0x%08X", pel->id());
             msg = "Created PEL "s + id + " with SRC "s + (*src)->asciiString();
             while (msg.back() == ' ')
             {
diff --git a/extensions/openpower-pels/manager.hpp b/extensions/openpower-pels/manager.hpp
index bec67ca..86030d4 100644
--- a/extensions/openpower-pels/manager.hpp
+++ b/extensions/openpower-pels/manager.hpp
@@ -161,6 +161,20 @@
      */
     void hostReject(uint32_t pelID, RejectionReason reason) override;
 
+    /**
+     * @brief Converts the ESEL field in an OpenBMC event log to a
+     *        vector of uint8_ts that just contains the PEL data.
+     *
+     * That data string looks like: "50 48 00 ab ..."
+     *
+     * Throws an exception on any failures.
+     *
+     * @param[in] esel - The ESEL string
+     *
+     * @return std::vector<uint8_t> - The contained PEL data
+     */
+    static std::vector<uint8_t> eselToRawData(const std::string& esel);
+
   private:
     /**
      * @brief Adds a received raw PEL to the PEL repository
@@ -208,6 +222,23 @@
     void closeFD(int fd, sdeventplus::source::EventBase& source);
 
     /**
+     * @brief Adds a PEL to the repository given its data
+     *
+     * @param[in] pelData - The PEL to add as a vector of uint8_ts
+     * @param[in] obmcLogID - the OpenBMC event log ID
+     */
+    void addPEL(std::vector<uint8_t>& pelData, uint32_t obmcLogID);
+
+    /**
+     * @brief Adds the PEL stored in the ESEL field of the AdditionalData
+     *        property of an OpenBMC event log to the repository.
+     *
+     * @param[in] esel - The ESEL AdditionalData contents
+     * @param[in] obmcLogID - The OpenBMC event log ID
+     */
+    void addESELPEL(const std::string& esel, uint32_t obmcLogID);
+
+    /**
      * @brief Reference to phosphor-logging's Manager class
      */
     phosphor::logging::internal::Manager& _logManager;
diff --git a/test/openpower-pels/pel_manager_test.cpp b/test/openpower-pels/pel_manager_test.cpp
index 1e0e1a9..b020d9d 100644
--- a/test/openpower-pels/pel_manager_test.cpp
+++ b/test/openpower-pels/pel_manager_test.cpp
@@ -344,3 +344,171 @@
 
     fs::remove_all(pelFilename.parent_path());
 }
+
+// An ESEL from the wild
+const std::string esel{
+    "00 00 df 00 00 00 00 20 00 04 12 01 6f aa 00 00 "
+    "50 48 00 30 01 00 33 00 00 00 00 07 5c 69 cc 0d 00 00 00 07 5c d5 50 db "
+    "42 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00 90 00 00 4e 90 00 00 4e "
+    "55 48 00 18 01 00 09 00 8a 03 40 00 00 00 00 00 ff ff 00 00 00 00 00 00 "
+    "50 53 00 50 01 01 00 00 02 00 00 09 33 2d 00 48 00 00 00 e0 00 00 10 00 "
+    "00 00 00 00 00 20 00 00 00 0c 00 02 00 00 00 fa 00 00 0c e4 00 00 00 12 "
+    "42 43 38 41 33 33 32 44 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 "
+    "20 20 20 20 20 20 20 20 55 44 00 1c 01 06 01 00 02 54 41 4b 00 00 00 06 "
+    "00 00 00 55 00 01 f9 20 00 00 00 00 55 44 00 24 01 06 01 00 01 54 41 4b "
+    "00 00 00 05 00 00 00 00 00 00 00 00 00 00 00 00 23 01 00 02 00 05 00 00 "
+    "55 44 00 0c 01 0b 01 00 0f 01 00 00 55 44 00 10 01 04 01 00 0f 9f de 6a "
+    "00 01 00 00 55 44 00 7c 00 0c 01 00 00 13 0c 02 00 fa 0c e4 16 00 01 2c "
+    "0c 1c 16 00 00 fa 0a f0 14 00 00 fa 0b b8 14 00 00 be 09 60 12 00 01 2c "
+    "0d 7a 12 00 00 fa 0c 4e 10 00 00 fa 0c e4 10 00 00 be 0a 8c 16 00 01 2c "
+    "0c 1c 16 00 01 09 09 f6 16 00 00 fa 09 f6 14 00 00 fa 0b b8 14 00 00 fa "
+    "0a f0 14 00 00 be 08 ca 12 00 01 2c 0c e4 12 00 00 fa 0b 54 10 00 00 fa "
+    "0c 2d 10 00 00 be 08 ca 55 44 00 58 01 03 01 00 00 00 00 00 00 05 31 64 "
+    "00 00 00 00 00 05 0d d4 00 00 00 00 40 5f 06 e0 00 00 00 00 40 5d d2 00 "
+    "00 00 00 00 40 57 d3 d0 00 00 00 00 40 58 f6 a0 00 00 00 00 40 54 c9 34 "
+    "00 00 00 00 40 55 9a 10 00 00 00 00 40 4c 0a 80 00 00 00 00 00 00 27 14 "
+    "55 44 01 84 01 01 01 00 48 6f 73 74 62 6f 6f 74 20 42 75 69 6c 64 20 49 "
+    "44 3a 20 68 6f 73 74 62 6f 6f 74 2d 66 65 63 37 34 64 66 2d 70 30 61 38 "
+    "37 64 63 34 2f 68 62 69 63 6f 72 65 2e 62 69 6e 00 49 42 4d 2d 77 69 74 "
+    "68 65 72 73 70 6f 6f 6e 2d 4f 50 39 2d 76 32 2e 34 2d 39 2e 32 33 34 0a "
+    "09 6f 70 2d 62 75 69 6c 64 2d 38 32 66 34 63 66 30 0a 09 62 75 69 6c 64 "
+    "72 6f 6f 74 2d 32 30 31 39 2e 30 35 2e 32 2d 31 30 2d 67 38 39 35 39 31 "
+    "31 34 0a 09 73 6b 69 62 6f 6f 74 2d 76 36 2e 35 2d 31 38 2d 67 34 37 30 "
+    "66 66 62 35 66 32 39 64 37 0a 09 68 6f 73 74 62 6f 6f 74 2d 66 65 63 37 "
+    "34 64 66 2d 70 30 61 38 37 64 63 34 0a 09 6f 63 63 2d 65 34 35 39 37 61 "
+    "62 0a 09 6c 69 6e 75 78 2d 35 2e 32 2e 31 37 2d 6f 70 65 6e 70 6f 77 65 "
+    "72 31 2d 70 64 64 63 63 30 33 33 0a 09 70 65 74 69 74 62 6f 6f 74 2d 76 "
+    "31 2e 31 30 2e 34 0a 09 6d 61 63 68 69 6e 65 2d 78 6d 6c 2d 63 36 32 32 "
+    "63 62 35 2d 70 37 65 63 61 62 33 64 0a 09 68 6f 73 74 62 6f 6f 74 2d 62 "
+    "69 6e 61 72 69 65 73 2d 36 36 65 39 61 36 30 0a 09 63 61 70 70 2d 75 63 "
+    "6f 64 65 2d 70 39 2d 64 64 32 2d 76 34 0a 09 73 62 65 2d 36 30 33 33 30 "
+    "65 30 0a 09 68 63 6f 64 65 2d 68 77 30 39 32 31 31 39 61 2e 6f 70 6d 73 "
+    "74 0a 00 00 55 44 00 70 01 04 01 00 0f 9f de 6a 00 05 00 00 07 5f 1d f4 "
+    "30 32 43 59 34 37 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "
+    "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "
+    "0b ac 54 02 59 41 31 39 33 34 36 39 37 30 35 38 00 00 00 00 00 00 05 22 "
+    "a1 58 01 8a 00 58 40 20 17 18 4d 2c 00 00 00 fc 01 a1 00 00 55 44 00 14 "
+    "01 08 01 00 00 00 00 01 00 00 00 5a 00 00 00 05 55 44 03 fc 01 15 31 00 "
+    "01 28 00 42 46 41 50 49 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 f4 "
+    "00 00 00 00 00 00 03 f4 00 00 00 0b 00 00 00 00 00 00 00 3d 2c 9b c2 84 "
+    "00 00 01 e4 00 48 43 4f fb ed 70 b1 00 00 02 01 00 00 00 00 00 00 00 09 "
+    "00 00 00 00 00 11 bd 20 00 00 00 00 00 01 f8 80 00 00 00 00 00 00 00 01 "
+    "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 16 00 00 00 00 00 00 01 2c "
+    "00 00 00 00 00 00 07 d0 00 00 00 00 00 00 0c 1c 00 00 00 64 00 00 00 3d "
+    "2c 9b d1 11 00 00 01 e4 00 48 43 4f fb ed 70 b1 00 00 02 01 00 00 00 00 "
+    "00 00 00 0a 00 00 00 00 00 13 b5 a0 00 00 00 00 00 01 f8 80 00 00 00 00 "
+    "00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 00 "
+    "00 00 00 be 00 00 00 00 00 00 07 d0 00 00 00 00 00 00 0a 8c 00 00 00 64 "
+    "00 00 00 3d 2c 9b df 98 00 00 01 e4 00 48 43 4f fb ed 70 b1 00 00 02 01 "
+    "00 00 00 00 00 00 00 0b 00 00 00 00 00 15 ae 20 00 00 00 00 00 01 f8 80 "
+    "00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 "
+    "00 00 00 00 00 00 00 fa 00 00 00 00 00 00 07 d0 00 00 00 00 00 00 0c e4 "
+    "00 00 00 64 00 00 00 3d 2c 9b ea b7 00 00 01 e4 00 48 43 4f fb ed 70 b1 "
+    "00 00 02 01 00 00 00 00 00 00 00 0c 00 00 00 00 00 17 a6 a0 00 00 00 00 "
+    "00 01 f8 80 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 "
+    "00 00 00 12 00 00 00 00 00 00 00 fa 00 00 00 00 00 00 07 d0 00 00 00 00 "
+    "00 00 0c 4e 00 00 00 64 00 00 00 3d 2c 9b f6 27 00 00 01 e4 00 48 43 4f "
+    "fb ed 70 b1 00 00 02 01 00 00 00 00 00 00 00 0d 00 00 00 00 00 19 9f 20 "
+    "00 00 00 00 00 01 f8 80 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 "
+    "00 00 00 00 00 00 00 12 00 00 00 00 00 00 01 2c 00 00 00 00 00 00 07 d0 "
+    "00 00 00 00 00 00 0d 7a 00 00 00 64 00 00 00 3d 2c 9c 05 75 00 00 01 e4 "
+    "00 48 43 4f fb ed 70 b1 00 00 02 01 00 00 00 00 00 00 00 0e 00 00 00 00 "
+    "00 1b 97 a0 00 00 00 00 00 01 f8 80 00 00 00 00 00 00 00 01 00 00 00 00 "
+    "00 00 00 00 00 00 00 00 00 00 00 14 00 00 00 00 00 00 00 be 00 00 00 00 "
+    "00 00 07 d0 00 00 00 00 00 00 09 60 00 00 00 64 00 00 00 3d 2c 9c 11 29 "
+    "00 00 01 e4 00 48 43 4f fb ed 70 b1 00 00 02 01 00 00 00 00 00 00 00 0f "
+    "00 00 00 00 00 1d 90 20 00 00 00 00 00 01 f8 80 00 00 00 00 00 00 00 01 "
+    "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 14 00 00 00 00 00 00 00 fa "
+    "00 00 00 00 00 00 07 d0 00 00 00 00 00 00 0b b8 00 00 00 64 00 00 00 3d "
+    "2c 9c 1c 45 00 00 01 e4 00 48 43 4f fb ed 70 b1 00 00 02 01 00 00 00 00 "
+    "00 00 00 10 00 00 00 00 00 1f 88 a0 00 00 00 00 00 01 f8 80 00 00 00 00 "
+    "00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 16 00 00 00 00 "
+    "00 00 00 fa 00 00 00 00 00 00 07 d0 00 00 00 00 00 00 0a f0 00 00 00 64 "
+    "00 00 00 3d 2c 9c 2b 14 00 00 01 e4 00 48 43 4f fb ed 70 b1 00 00 02 01 "
+    "00 00 00 00 00 00 00 11 00 00 00 00 00 21 81 20 00 00 00 00 00 01 f8 80 "
+    "00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 16 "
+    "00 00 00 00 00 00 01 2c 00 00 00 00 00 00 07 d0 00 00 00 00 00 00 0c 1c "
+    "00 00 00 64 00 00 00 3d 2d 6d 8f 9e 00 00 01 e4 00 00 43 4f 52 d7 9c 36 "
+    "00 00 04 73 00 00 00 1c 00 00 00 3d 2d 6d 99 ac 00 00 01 e4 00 10 43 4f "
+    "3f f2 02 3d 00 00 05 58 00 00 00 00 02 00 00 01 00 00 00 00 00 00 00 40 "
+    "00 00 00 2c 55 44 00 30 01 15 31 00 01 28 00 42 46 41 50 49 5f 44 42 47 "
+    "00 00 00 00 00 00 00 00 00 00 00 28 00 00 00 00 00 00 00 28 00 00 00 00 "
+    "00 00 00 00 55 44 01 74 01 15 31 00 01 28 00 42 46 41 50 49 5f 49 00 00 "
+    "00 00 00 00 00 00 00 00 00 00 01 6c 00 00 00 00 00 00 01 6c 00 00 00 0b "
+    "00 00 00 00 00 00 00 3c 0d 52 18 5e 00 00 01 e4 00 08 43 4f 46 79 94 13 "
+    "00 00 0a 5b 00 00 00 00 00 00 2c 00 00 00 00 24 00 00 00 3c 0d 6b 26 6c "
+    "00 00 01 e4 00 00 43 4f 4e 9b 18 74 00 00 01 03 00 00 00 1c 00 00 00 3c "
+    "12 b9 2d 13 00 00 01 e4 00 00 43 4f ea 31 ed d4 00 00 05 c4 00 00 00 1c "
+    "00 00 00 3c 13 02 73 53 00 00 01 e4 00 00 43 4f ea 31 ed d4 00 00 05 c4 "
+    "00 00 00 1c 00 00 00 3c 13 04 7c 94 00 00 01 e4 00 00 43 4f ea 31 ed d4 "
+    "00 00 05 c4 00 00 00 1c 00 00 00 3c 13 06 ad e1 00 00 01 e4 00 00 43 4f "
+    "ea 31 ed d4 00 00 05 c4 00 00 00 1c 00 00 00 3c 13 07 3f 77 00 00 01 e4 "
+    "00 00 43 4f 5e 4a 55 32 00 00 10 f2 00 00 00 1c 00 00 00 3c 13 07 4e e4 "
+    "00 00 01 e4 00 00 43 4f 5e 4a 55 32 00 00 0d 68 00 00 00 1c 00 00 00 3c "
+    "13 36 79 18 00 00 01 e4 00 00 43 4f ea 31 ed d4 00 00 05 c4 00 00 00 1c "
+    "00 00 00 3d 2c 9c 36 70 00 00 01 e4 00 00 43 4f 23 45 90 97 00 00 02 47 "
+    "00 00 00 1c 00 00 00 3d 2d 6d a3 ed 00 00 01 e4 00 08 43 4f 74 3a 5b 1a "
+    "00 00 04 cc 00 00 00 00 02 00 00 01 00 00 00 24 55 44 00 30 01 15 31 00 "
+    "01 28 00 42 53 43 41 4e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 28 "
+    "00 00 00 00 00 00 00 28 00 00 00 00 00 00 00 00"};
+
+TEST_F(ManagerTest, TestESELToRawData)
+{
+    auto data = Manager::eselToRawData(esel);
+
+    EXPECT_EQ(data.size(), 2464);
+
+    PEL pel{data};
+    EXPECT_TRUE(pel.valid());
+}
+
+TEST_F(ManagerTest, TestCreateWithESEL)
+{
+    std::unique_ptr<DataInterfaceBase> dataIface =
+        std::make_unique<DataInterface>(bus);
+
+    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::string adItem = "ESEL=" + esel;
+        std::vector<std::string> additionalData{adItem};
+        std::vector<std::string> associations;
+
+        manager.create("error message", 37, 0,
+                       phosphor::logging::Entry::Level::Error, additionalData,
+                       associations);
+
+        auto data = manager.getPELFromOBMCID(37);
+        PEL pel{data};
+        EXPECT_TRUE(pel.valid());
+    }
+
+    // Now an invalid one
+    {
+        std::string adItem = "ESEL=" + esel;
+
+        // Crop it
+        adItem.resize(adItem.size() - 300);
+
+        std::vector<std::string> additionalData{adItem};
+        std::vector<std::string> associations;
+
+        manager.create("error message", 38, 0,
+                       phosphor::logging::Entry::Level::Error, additionalData,
+                       associations);
+
+        EXPECT_THROW(
+            manager.getPELFromOBMCID(38),
+            sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
+
+        // Run the event loop to log the bad PEL event
+        sdeventplus::Event e{sdEvent};
+        e.run(std::chrono::milliseconds(1));
+
+        EXPECT_EQ(logger.errName, "org.open_power.Logging.Error.BadHostPEL");
+        EXPECT_EQ(logger.errLevel, phosphor::logging::Entry::Level::Error);
+    }
+}