Add YAML and error function for MEM_GOODx faults

Add a section to the error and metadata YAML files for the MEM_GOODx
faults. Use that to update/generate a new elog-errors.hpp include file.

Update the power sequencer source to have a memGoodFault function for
handling callouts for MEM_GOODx type errors.

Change-Id: Ia08dc88f29f00f749e7995f97f37647b02135a2b
Signed-off-by: Brandon Wyman <bjwyman@gmail.com>
diff --git a/elog-errors.hpp b/elog-errors.hpp
index f4d45f8..44bc5eb 100644
--- a/elog-errors.hpp
+++ b/elog-errors.hpp
@@ -31,6 +31,26 @@
 
 namespace sdbusplus
 {
+namespace org
+{
+namespace open_power
+{
+namespace Witherspoon
+{
+namespace Fault
+{
+namespace Error
+{
+struct MemoryPowerFault;
+} // namespace Error
+} // namespace Fault
+} // namespace Witherspoon
+} // namespace open_power
+} // namespace org
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
 namespace xyz
 {
 namespace openbmc_project
@@ -388,19 +408,30 @@
 
 struct CALLOUT_ERRNO
 {
-    static constexpr auto str = "CALLOUT_ERRNO=%d";
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
     static constexpr auto str_short = "CALLOUT_ERRNO";
-    using type = std::tuple<std::decay_t<decltype(str)>, int32_t>;
-    explicit constexpr CALLOUT_ERRNO(int32_t a) : _entry(entry(str, a)){};
+    using type =
+        std::tuple<std::decay_t<decltype("CALLOUT_ERRNO=%d")>, int32_t>;
+    explicit constexpr CALLOUT_ERRNO(int32_t a) :
+        _entry(entry("CALLOUT_ERRNO=%d", a)){};
     type _entry;
 };
 struct CALLOUT_DEVICE_PATH
 {
-    static constexpr auto str = "CALLOUT_DEVICE_PATH=%s";
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
     static constexpr auto str_short = "CALLOUT_DEVICE_PATH";
-    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
+    using type = std::tuple<std::decay_t<decltype("CALLOUT_DEVICE_PATH=%s")>,
+                            const char*>;
     explicit constexpr CALLOUT_DEVICE_PATH(const char* a) :
-        _entry(entry(str, a)){};
+        _entry(entry("CALLOUT_DEVICE_PATH=%s", a)){};
     type _entry;
 };
 
@@ -444,10 +475,16 @@
 
 struct CALLOUT_GPIO_NUM
 {
-    static constexpr auto str = "CALLOUT_GPIO_NUM=%u";
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
     static constexpr auto str_short = "CALLOUT_GPIO_NUM";
-    using type = std::tuple<std::decay_t<decltype(str)>, uint32_t>;
-    explicit constexpr CALLOUT_GPIO_NUM(uint32_t a) : _entry(entry(str, a)){};
+    using type =
+        std::tuple<std::decay_t<decltype("CALLOUT_GPIO_NUM=%u")>, uint32_t>;
+    explicit constexpr CALLOUT_GPIO_NUM(uint32_t a) :
+        _entry(entry("CALLOUT_GPIO_NUM=%u", a)){};
     type _entry;
 };
 
@@ -495,18 +532,30 @@
 
 struct CALLOUT_IIC_BUS
 {
-    static constexpr auto str = "CALLOUT_IIC_BUS=%s";
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
     static constexpr auto str_short = "CALLOUT_IIC_BUS";
-    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
-    explicit constexpr CALLOUT_IIC_BUS(const char* a) : _entry(entry(str, a)){};
+    using type =
+        std::tuple<std::decay_t<decltype("CALLOUT_IIC_BUS=%s")>, const char*>;
+    explicit constexpr CALLOUT_IIC_BUS(const char* a) :
+        _entry(entry("CALLOUT_IIC_BUS=%s", a)){};
     type _entry;
 };
 struct CALLOUT_IIC_ADDR
 {
-    static constexpr auto str = "CALLOUT_IIC_ADDR=0x%hx";
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
     static constexpr auto str_short = "CALLOUT_IIC_ADDR";
-    using type = std::tuple<std::decay_t<decltype(str)>, uint16_t>;
-    explicit constexpr CALLOUT_IIC_ADDR(uint16_t a) : _entry(entry(str, a)){};
+    using type =
+        std::tuple<std::decay_t<decltype("CALLOUT_IIC_ADDR=0x%hx")>, uint16_t>;
+    explicit constexpr CALLOUT_IIC_ADDR(uint16_t a) :
+        _entry(entry("CALLOUT_IIC_ADDR=0x%hx", a)){};
     type _entry;
 };
 
@@ -555,11 +604,16 @@
 
 struct CALLOUT_INVENTORY_PATH
 {
-    static constexpr auto str = "CALLOUT_INVENTORY_PATH=%s";
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
     static constexpr auto str_short = "CALLOUT_INVENTORY_PATH";
-    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
+    using type = std::tuple<std::decay_t<decltype("CALLOUT_INVENTORY_PATH=%s")>,
+                            const char*>;
     explicit constexpr CALLOUT_INVENTORY_PATH(const char* a) :
-        _entry(entry(str, a)){};
+        _entry(entry("CALLOUT_INVENTORY_PATH=%s", a)){};
     type _entry;
 };
 
@@ -602,11 +656,17 @@
 
 struct CALLOUT_IPMI_SENSOR_NUM
 {
-    static constexpr auto str = "CALLOUT_IPMI_SENSOR_NUM=%u";
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
     static constexpr auto str_short = "CALLOUT_IPMI_SENSOR_NUM";
-    using type = std::tuple<std::decay_t<decltype(str)>, uint32_t>;
+    using type =
+        std::tuple<std::decay_t<decltype("CALLOUT_IPMI_SENSOR_NUM=%u")>,
+                   uint32_t>;
     explicit constexpr CALLOUT_IPMI_SENSOR_NUM(uint32_t a) :
-        _entry(entry(str, a)){};
+        _entry(entry("CALLOUT_IPMI_SENSOR_NUM=%u", a)){};
     type _entry;
 };
 
@@ -649,10 +709,16 @@
 
 struct RAW_STATUS
 {
-    static constexpr auto str = "RAW_STATUS=%s";
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
     static constexpr auto str_short = "RAW_STATUS";
-    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
-    explicit constexpr RAW_STATUS(const char* a) : _entry(entry(str, a)){};
+    using type =
+        std::tuple<std::decay_t<decltype("RAW_STATUS=%s")>, const char*>;
+    explicit constexpr RAW_STATUS(const char* a) :
+        _entry(entry("RAW_STATUS=%s", a)){};
     type _entry;
 };
 
@@ -697,10 +763,16 @@
 
 struct RAW_STATUS
 {
-    static constexpr auto str = "RAW_STATUS=%s";
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
     static constexpr auto str_short = "RAW_STATUS";
-    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
-    explicit constexpr RAW_STATUS(const char* a) : _entry(entry(str, a)){};
+    using type =
+        std::tuple<std::decay_t<decltype("RAW_STATUS=%s")>, const char*>;
+    explicit constexpr RAW_STATUS(const char* a) :
+        _entry(entry("RAW_STATUS=%s", a)){};
     type _entry;
 };
 
@@ -745,10 +817,16 @@
 
 struct RAW_STATUS
 {
-    static constexpr auto str = "RAW_STATUS=%s";
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
     static constexpr auto str_short = "RAW_STATUS";
-    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
-    explicit constexpr RAW_STATUS(const char* a) : _entry(entry(str, a)){};
+    using type =
+        std::tuple<std::decay_t<decltype("RAW_STATUS=%s")>, const char*>;
+    explicit constexpr RAW_STATUS(const char* a) :
+        _entry(entry("RAW_STATUS=%s", a)){};
     type _entry;
 };
 
@@ -794,10 +872,16 @@
 
 struct RAW_STATUS
 {
-    static constexpr auto str = "RAW_STATUS=%s";
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
     static constexpr auto str_short = "RAW_STATUS";
-    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
-    explicit constexpr RAW_STATUS(const char* a) : _entry(entry(str, a)){};
+    using type =
+        std::tuple<std::decay_t<decltype("RAW_STATUS=%s")>, const char*>;
+    explicit constexpr RAW_STATUS(const char* a) :
+        _entry(entry("RAW_STATUS=%s", a)){};
     type _entry;
 };
 
@@ -843,10 +927,16 @@
 
 struct RAW_STATUS
 {
-    static constexpr auto str = "RAW_STATUS=%s";
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
     static constexpr auto str_short = "RAW_STATUS";
-    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
-    explicit constexpr RAW_STATUS(const char* a) : _entry(entry(str, a)){};
+    using type =
+        std::tuple<std::decay_t<decltype("RAW_STATUS=%s")>, const char*>;
+    explicit constexpr RAW_STATUS(const char* a) :
+        _entry(entry("RAW_STATUS=%s", a)){};
     type _entry;
 };
 
@@ -891,10 +981,16 @@
 
 struct RAW_STATUS
 {
-    static constexpr auto str = "RAW_STATUS=%s";
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
     static constexpr auto str_short = "RAW_STATUS";
-    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
-    explicit constexpr RAW_STATUS(const char* a) : _entry(entry(str, a)){};
+    using type =
+        std::tuple<std::decay_t<decltype("RAW_STATUS=%s")>, const char*>;
+    explicit constexpr RAW_STATUS(const char* a) :
+        _entry(entry("RAW_STATUS=%s", a)){};
     type _entry;
 };
 
@@ -1012,26 +1108,42 @@
 
 struct RAIL
 {
-    static constexpr auto str = "RAIL=%d";
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
     static constexpr auto str_short = "RAIL";
-    using type = std::tuple<std::decay_t<decltype(str)>, uint16_t>;
-    explicit constexpr RAIL(uint16_t a) : _entry(entry(str, a)){};
+    using type = std::tuple<std::decay_t<decltype("RAIL=%d")>, uint16_t>;
+    explicit constexpr RAIL(uint16_t a) : _entry(entry("RAIL=%d", a)){};
     type _entry;
 };
 struct RAIL_NAME
 {
-    static constexpr auto str = "RAIL_NAME=%s";
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
     static constexpr auto str_short = "RAIL_NAME";
-    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
-    explicit constexpr RAIL_NAME(const char* a) : _entry(entry(str, a)){};
+    using type =
+        std::tuple<std::decay_t<decltype("RAIL_NAME=%s")>, const char*>;
+    explicit constexpr RAIL_NAME(const char* a) :
+        _entry(entry("RAIL_NAME=%s", a)){};
     type _entry;
 };
 struct RAW_STATUS
 {
-    static constexpr auto str = "RAW_STATUS=%s";
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
     static constexpr auto str_short = "RAW_STATUS";
-    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
-    explicit constexpr RAW_STATUS(const char* a) : _entry(entry(str, a)){};
+    using type =
+        std::tuple<std::decay_t<decltype("RAW_STATUS=%s")>, const char*>;
+    explicit constexpr RAW_STATUS(const char* a) :
+        _entry(entry("RAW_STATUS=%s", a)){};
     type _entry;
 };
 
@@ -1077,26 +1189,43 @@
 
 struct INPUT_NUM
 {
-    static constexpr auto str = "INPUT_NUM=%d";
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
     static constexpr auto str_short = "INPUT_NUM";
-    using type = std::tuple<std::decay_t<decltype(str)>, uint16_t>;
-    explicit constexpr INPUT_NUM(uint16_t a) : _entry(entry(str, a)){};
+    using type = std::tuple<std::decay_t<decltype("INPUT_NUM=%d")>, uint16_t>;
+    explicit constexpr INPUT_NUM(uint16_t a) :
+        _entry(entry("INPUT_NUM=%d", a)){};
     type _entry;
 };
 struct INPUT_NAME
 {
-    static constexpr auto str = "INPUT_NAME=%s";
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
     static constexpr auto str_short = "INPUT_NAME";
-    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
-    explicit constexpr INPUT_NAME(const char* a) : _entry(entry(str, a)){};
+    using type =
+        std::tuple<std::decay_t<decltype("INPUT_NAME=%s")>, const char*>;
+    explicit constexpr INPUT_NAME(const char* a) :
+        _entry(entry("INPUT_NAME=%s", a)){};
     type _entry;
 };
 struct RAW_STATUS
 {
-    static constexpr auto str = "RAW_STATUS=%s";
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
     static constexpr auto str_short = "RAW_STATUS";
-    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
-    explicit constexpr RAW_STATUS(const char* a) : _entry(entry(str, a)){};
+    using type =
+        std::tuple<std::decay_t<decltype("RAW_STATUS=%s")>, const char*>;
+    explicit constexpr RAW_STATUS(const char* a) :
+        _entry(entry("RAW_STATUS=%s", a)){};
     type _entry;
 };
 
@@ -1141,10 +1270,16 @@
 
 struct RAW_STATUS
 {
-    static constexpr auto str = "RAW_STATUS=%s";
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
     static constexpr auto str_short = "RAW_STATUS";
-    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
-    explicit constexpr RAW_STATUS(const char* a) : _entry(entry(str, a)){};
+    using type =
+        std::tuple<std::decay_t<decltype("RAW_STATUS=%s")>, const char*>;
+    explicit constexpr RAW_STATUS(const char* a) :
+        _entry(entry("RAW_STATUS=%s", a)){};
     type _entry;
 };
 
@@ -1187,10 +1322,16 @@
 
 struct RAW_STATUS
 {
-    static constexpr auto str = "RAW_STATUS=%s";
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
     static constexpr auto str_short = "RAW_STATUS";
-    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
-    explicit constexpr RAW_STATUS(const char* a) : _entry(entry(str, a)){};
+    using type =
+        std::tuple<std::decay_t<decltype("RAW_STATUS=%s")>, const char*>;
+    explicit constexpr RAW_STATUS(const char* a) :
+        _entry(entry("RAW_STATUS=%s", a)){};
     type _entry;
 };
 
@@ -1235,10 +1376,16 @@
 
 struct RAW_STATUS
 {
-    static constexpr auto str = "RAW_STATUS=%s";
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
     static constexpr auto str_short = "RAW_STATUS";
-    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
-    explicit constexpr RAW_STATUS(const char* a) : _entry(entry(str, a)){};
+    using type =
+        std::tuple<std::decay_t<decltype("RAW_STATUS=%s")>, const char*>;
+    explicit constexpr RAW_STATUS(const char* a) :
+        _entry(entry("RAW_STATUS=%s", a)){};
     type _entry;
 };
 
@@ -1270,6 +1417,60 @@
 
 } // namespace details
 
+namespace org
+{
+namespace open_power
+{
+namespace Witherspoon
+{
+namespace Fault
+{
+namespace _MemoryPowerFault
+{
+
+struct RAW_STATUS
+{
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
+    static constexpr auto str_short = "RAW_STATUS";
+    using type =
+        std::tuple<std::decay_t<decltype("RAW_STATUS=%s")>, const char*>;
+    explicit constexpr RAW_STATUS(const char* a) :
+        _entry(entry("RAW_STATUS=%s", a)){};
+    type _entry;
+};
+
+} // namespace _MemoryPowerFault
+
+struct MemoryPowerFault
+{
+    static constexpr auto L = level::ERR;
+    using RAW_STATUS = _MemoryPowerFault::RAW_STATUS;
+    using CALLOUT_INVENTORY_PATH = xyz::openbmc_project::Common::Callout::
+        Inventory::CALLOUT_INVENTORY_PATH;
+    using metadata_types = std::tuple<RAW_STATUS, CALLOUT_INVENTORY_PATH>;
+};
+
+} // namespace Fault
+} // namespace Witherspoon
+} // namespace open_power
+} // namespace org
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::org::open_power::Witherspoon::Fault::Error::MemoryPowerFault>
+{
+    using type = org::open_power::Witherspoon::Fault::MemoryPowerFault;
+};
+
+} // namespace details
+
 } // namespace logging
 
 } // namespace phosphor
diff --git a/org/open_power/Witherspoon/Fault.errors.yaml b/org/open_power/Witherspoon/Fault.errors.yaml
index 801773c..668568d 100644
--- a/org/open_power/Witherspoon/Fault.errors.yaml
+++ b/org/open_power/Witherspoon/Fault.errors.yaml
@@ -38,3 +38,6 @@
 
 - name: GPUOverTemp
   description: A GPU suffered an over-temperature fault
+
+- name: MemoryPowerFault
+  description: A memory device suffered a power fault
diff --git a/org/open_power/Witherspoon/Fault.metadata.yaml b/org/open_power/Witherspoon/Fault.metadata.yaml
index c8cdad0..c8bfab8 100644
--- a/org/open_power/Witherspoon/Fault.metadata.yaml
+++ b/org/open_power/Witherspoon/Fault.metadata.yaml
@@ -93,3 +93,11 @@
       type: string
   inherits:
     - xyz.openbmc_project.Common.Callout.Inventory
+
+- name: MemoryPowerFault
+  level: ERR
+  meta:
+    - str: "RAW_STATUS=%s"
+      type: string
+  inherits:
+    - xyz.openbmc_project.Common.Callout.Inventory
diff --git a/power-sequencer/types.hpp b/power-sequencer/types.hpp
index fcb30e3..7edfa59 100644
--- a/power-sequencer/types.hpp
+++ b/power-sequencer/types.hpp
@@ -24,7 +24,9 @@
 {
     none,
     gpuPGOOD,
-    gpuOverTemp
+    gpuOverTemp,
+    memGOOD0,
+    memGOOD1
 };
 
 /**
diff --git a/power-sequencer/ucd90160.cpp b/power-sequencer/ucd90160.cpp
index 203004d..2b83918 100644
--- a/power-sequencer/ucd90160.cpp
+++ b/power-sequencer/ucd90160.cpp
@@ -476,5 +476,27 @@
         metadata::CALLOUT_INVENTORY_PATH(callout.c_str()));
 }
 
+void UCD90160::memGoodError(const std::string& callout)
+{
+    util::NamesValues nv;
+
+    try
+    {
+        nv.add("STATUS_WORD", readStatusWord());
+        nv.add("MFR_STATUS", readMFRStatus());
+    }
+    catch (device_error::ReadFailure& e)
+    {
+        log<level::ERR>("ReadFailure when collecting metadata");
+        commit<device_error::ReadFailure>();
+    }
+
+    using metadata = org::open_power::Witherspoon::Fault::MemoryPowerFault;
+
+    report<power_error::MemoryPowerFault>(
+        metadata::RAW_STATUS(nv.get().c_str()),
+        metadata::CALLOUT_INVENTORY_PATH(callout.c_str()));
+}
+
 } // namespace power
 } // namespace witherspoon
diff --git a/power-sequencer/ucd90160.hpp b/power-sequencer/ucd90160.hpp
index 5eedda8..3169de6 100644
--- a/power-sequencer/ucd90160.hpp
+++ b/power-sequencer/ucd90160.hpp
@@ -79,6 +79,13 @@
     void gpuOverTempError(const std::string& callout);
 
     /**
+     * Reports an error for a MEM_GOODx failure.
+     *
+     * @param[in] callout - The MEM callout string
+     */
+    void memGoodError(const std::string& callout);
+
+    /**
      * Given the device path for a chip, find its gpiochip
      * path
      *