PEL: Update system info into HB PEL extended user data section

Hostboot requested BMC add a UserData section containing debug
information like internal code level name and the bmc/host/chassis
states that are added to the BMC PELs. To accomodate this BMC code will
look in incoming PELs for an ED section with specific
compID/version/subtype fields, and then modify it with the appropriate
debug contents as mentioned above.

Test: Verified PEL tool output by injecting error to generate
hostboot PEL

Signed-off-by: Sumit Kumar <sumit_kumar@in.ibm.com>
Change-Id: I72288089f2768412eb9033b121e7f02f72f11fc7
diff --git a/extensions/openpower-pels/extended_user_data.hpp b/extensions/openpower-pels/extended_user_data.hpp
index 421a6f8..be3db5b 100644
--- a/extensions/openpower-pels/extended_user_data.hpp
+++ b/extensions/openpower-pels/extended_user_data.hpp
@@ -95,6 +95,47 @@
     }
 
     /**
+     * @brief Returns the section data updated with new data
+     *
+     * @param[in] subType - The type of user data
+     * @param[in] componentID - Component ID of the creator
+     * @param[in] newData - The new data
+     *
+     */
+    void updateDataSection(const uint8_t subType, const uint16_t componentId,
+                           const std::vector<uint8_t>& newData)
+    {
+        auto origDataSize = 0;
+
+        if (newData.size() >= 4)
+        {
+            // Update component Id & subtype in section header of ED
+            _header.componentID = static_cast<uint16_t>(componentId);
+            _header.subType = static_cast<uint8_t>(subType);
+
+            if (newData.size() > _data.size())
+            {
+                // Don't allow section to get bigger
+                origDataSize = _data.size();
+                _data = newData;
+                _data.resize(origDataSize);
+            }
+            else
+            {
+                // Use shrink to handle 4B alignment and update the header size
+                auto status =
+                    shrink(Section::flattenedSize() + 4 + newData.size());
+                if (status)
+                {
+                    origDataSize = _data.size();
+                    _data = newData;
+                    _data.resize(origDataSize);
+                }
+            }
+        }
+    }
+
+    /**
      * @brief Get the section contents in JSON
      *
      * @param[in] creatorID - Creator Subsystem ID - unused (see the .cpp)
diff --git a/extensions/openpower-pels/manager.cpp b/extensions/openpower-pels/manager.cpp
index ef7c789..80687a9 100644
--- a/extensions/openpower-pels/manager.cpp
+++ b/extensions/openpower-pels/manager.cpp
@@ -134,6 +134,9 @@
         pel->assignID();
         pel->setCommitTime();
 
+        // Update System Info to Extended User Data
+        pel->updateSysInfoInExtendedUserDataSection(*_dataIface);
+
         try
         {
             log<level::DEBUG>(
diff --git a/extensions/openpower-pels/pel.cpp b/extensions/openpower-pels/pel.cpp
index 48dff51..a3314cd 100644
--- a/extensions/openpower-pels/pel.cpp
+++ b/extensions/openpower-pels/pel.cpp
@@ -493,6 +493,47 @@
     return calloutPresent;
 }
 
+void PEL::updateSysInfoInExtendedUserDataSection(
+    const DataInterfaceBase& dataIface)
+{
+    const AdditionalData additionalData;
+
+    // Check for PEL from Hostboot
+    if (_ph->creatorID() == static_cast<uint8_t>(CreatorID::hostboot))
+    {
+        // Get the ED section from PEL
+        auto op = std::find_if(_optionalSections.begin(),
+                               _optionalSections.end(), [](auto& section) {
+                                   return section->header().id ==
+                                          static_cast<uint16_t>(
+                                              SectionID::extUserData);
+                               });
+
+        // Check for ED section found and its not the last section of PEL
+        if (op != _optionalSections.end())
+        {
+            // Get the extended user data class mapped to found section
+            auto extUserData = static_cast<ExtendedUserData*>(op->get());
+
+            // Check for the creator ID is for OpenBMC
+            if (extUserData->creatorID() ==
+                static_cast<uint8_t>(CreatorID::openBMC))
+            {
+                // Update subtype and component id
+                auto subType = static_cast<uint8_t>(UserDataFormat::json);
+                auto componentId =
+                    static_cast<uint16_t>(ComponentID::phosphorLogging);
+
+                // Update system data to ED section
+                auto ud =
+                    util::makeSysInfoUserDataSection(additionalData, dataIface);
+                extUserData->updateDataSection(subType, componentId,
+                                               ud->data());
+            }
+        }
+    }
+}
+
 namespace util
 {
 
@@ -554,7 +595,10 @@
     {
     }
 
-    json["Process Name"] = std::move(name);
+    if (pid)
+    {
+        json["Process Name"] = std::move(name);
+    }
 }
 
 void addBMCFWVersionIDToJSON(nlohmann::json& json,
diff --git a/extensions/openpower-pels/pel.hpp b/extensions/openpower-pels/pel.hpp
index d48b346..8b592f7 100644
--- a/extensions/openpower-pels/pel.hpp
+++ b/extensions/openpower-pels/pel.hpp
@@ -291,6 +291,15 @@
      */
     bool isCalloutPresent() const;
 
+    /**
+     * @brief Updates the system info data into HB extended user
+     *        data section to this PEL object
+     *
+     * @param[in] dataIface - The data interface object
+     */
+    void updateSysInfoInExtendedUserDataSection(
+        const DataInterfaceBase& dataIface);
+
   private:
     /**
      * @brief Builds the section objects from a PEL data buffer