PEL: Allow shrinking of a UserData section

Add a shrink() function to the UserData class (with a virtual version of
it in the Section base class) that will shrink the class to a new size.

This is done so that when UserData sections are added to PELs the
sections can be shrunk if necessary to keep the PEL under the maximum
size, which is 16KB.

Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: Iade52dee8a110f7805c40aa50d6e5df45db050bf
diff --git a/extensions/openpower-pels/section.hpp b/extensions/openpower-pels/section.hpp
index 96a1aad..183268c 100644
--- a/extensions/openpower-pels/section.hpp
+++ b/extensions/openpower-pels/section.hpp
@@ -71,6 +71,25 @@
         return std::nullopt;
     }
 
+    /**
+     * @brief Shrinks a PEL section
+     *
+     * If this is even possible for a section depends on which section
+     * it is.  If a section cannot be shrunk, it doesn't need to implement
+     * shrink so it will just return false, meaning no shrinking was done.
+     *
+     * If a section can be shrunk, this function will be overridden in that
+     * class.
+     *
+     * @param[in] newSize - The new size, in bytes, to shrink to
+     *
+     * @return bool - true if successful, false else
+     */
+    virtual bool shrink(size_t newSize)
+    {
+        return false;
+    }
+
   protected:
     /**
      * @brief Returns the flattened size of the section header
diff --git a/extensions/openpower-pels/user_data.cpp b/extensions/openpower-pels/user_data.cpp
index 70acbbb..0ae227b 100644
--- a/extensions/openpower-pels/user_data.cpp
+++ b/extensions/openpower-pels/user_data.cpp
@@ -104,5 +104,22 @@
     return std::nullopt;
 }
 
+bool UserData::shrink(size_t newSize)
+{
+    // minimum size is 4 bytes plus the 8B header
+    if ((newSize < flattenedSize()) &&
+        (newSize >= (Section::flattenedSize() + 4)))
+    {
+        auto dataSize = newSize - Section::flattenedSize();
+
+        // Ensure it's 4B aligned
+        _data.resize((dataSize / 4) * 4);
+        _header.size = Section::flattenedSize() + _data.size();
+        return true;
+    }
+
+    return false;
+}
+
 } // namespace pels
 } // namespace openpower
diff --git a/extensions/openpower-pels/user_data.hpp b/extensions/openpower-pels/user_data.hpp
index 3594849..b1c9084 100644
--- a/extensions/openpower-pels/user_data.hpp
+++ b/extensions/openpower-pels/user_data.hpp
@@ -88,6 +88,19 @@
      */
     std::optional<std::string> getJSON() const override;
 
+    /**
+     * @brief Shrink the section
+     *
+     * The new size must be between the current size and the minimum
+     * size, which is 12 bytes.  If it isn't a 4 byte aligned value
+     * the code will do the aligning before the resize takes place.
+     *
+     * @param[in] newSize - The new size in bytes
+     *
+     * @return bool - true if successful, false else.
+     */
+    bool shrink(size_t newSize) override;
+
   private:
     /**
      * @brief Fills in the object from the stream data