Clear volatile PNOR partitions when required

The OpenPOWER host firmware requires OpenBMC to clear out certain
"volatile" sections of it's flash chip in certain scenarios:
- Any fresh power on
- Any boot/reboot of the server where a certain "volatile" sensor is
  enabled

This commit utilizes the obmc-host-start target, which is only run during
fresh power on operations, to ensure the volatile sensor is set. The new
obmc-host-startmin target is then utilized to check for this sensor and
clear the host volatile flash sections if the sensor is set. In this
way, the volatile flash sections are cleared on all fresh power on
operations and in any reboot loop that the host has set the sensor.

Testing:
- Clean Power On (cleared as expected)
Starting Enable the clearing of the Volatile PNOR partitions in host0...
Started Enable the clearing of the Volatile PNOR partitions in host0.
Starting Clear the Volatile PNOR partitions in host0 if Enabled...
Clear /var/lib/phosphor-software-manager/pnor/rw/HB_VOLATILE
Started Clear the Volatile PNOR partitions in host0 if Enabled.

- Host Reboot with host running (cleared as expected)
Starting Clear the Volatile PNOR partitions in host0 if Enabled...
Clear /var/lib/phosphor-software-manager/pnor/rw/HB_VOLATILE
Started Clear the Volatile PNOR partitions in host0 if Enabled.

- Reboot during hostboot, before istep 16 (nothing cleared as expected)
Starting Clear the Volatile PNOR partitions in host0 if Enabled...
Started Clear the Volatile PNOR partitions in host0 if Enabled.

Resolves openbmc/openbmc#2397

Change-Id: I56a897ce8919a95f9e80ab730ecabf880723f1f6
Signed-off-by: Michael Tritz <mtritz@us.ibm.com>
Signed-off-by: Andrew Geissler <geissonator@yahoo.com>
diff --git a/meta-openbmc-machines/meta-openpower/common/recipes-phosphor/flash/openpower-software-manager.bb b/meta-openbmc-machines/meta-openpower/common/recipes-phosphor/flash/openpower-software-manager.bb
index 2b8c841..93dc56e 100644
--- a/meta-openbmc-machines/meta-openpower/common/recipes-phosphor/flash/openpower-software-manager.bb
+++ b/meta-openbmc-machines/meta-openpower/common/recipes-phosphor/flash/openpower-software-manager.bb
@@ -52,4 +52,19 @@
         obmc-flash-bios-updatesymlinks.service \
         obmc-flash-bios-ubiclear@.service \
         obmc-flash-bios-cleanup.service \
+        obmc-flash-bios-enable-clearvolatile@.service \
+        obmc-flash-bios-check-clearvolatile@.service \
         "
+
+ENABLE_CLEAR_VOLATILE_TMPL = "obmc-flash-bios-enable-clearvolatile@.service"
+HOST_START_TGTFMT = "obmc-host-start@{0}.target"
+ENABLE_CLEAR_VOLATILE_INSTFMT = "obmc-flash-bios-enable-clearvolatile@{0}.service"
+ENABLE_CLEAR_VOLATILE_START_FMT = "../${ENABLE_CLEAR_VOLATILE_TMPL}:${HOST_START_TGTFMT}.requires/${ENABLE_CLEAR_VOLATILE_INSTFMT}"
+
+CHECK_CLEAR_VOLATILE_TMPL = "obmc-flash-bios-check-clearvolatile@.service"
+HOST_STARTMIN_TGTFMT = "obmc-host-startmin@{0}.target"
+CHECK_CLEAR_VOLATILE_INSTFMT = "obmc-flash-bios-check-clearvolatile@{0}.service"
+CHECK_CLEAR_VOLATILE_START_FMT = "../${CHECK_CLEAR_VOLATILE_TMPL}:${HOST_STARTMIN_TGTFMT}.requires/${CHECK_CLEAR_VOLATILE_INSTFMT}"
+
+SYSTEMD_LINK_${PN} += "${@compose_list_zip(d, 'ENABLE_CLEAR_VOLATILE_START_FMT', 'OBMC_HOST_INSTANCES')}"
+SYSTEMD_LINK_${PN} += "${@compose_list_zip(d, 'CHECK_CLEAR_VOLATILE_START_FMT', 'OBMC_HOST_INSTANCES')}"
diff --git a/meta-openbmc-machines/meta-openpower/common/recipes-phosphor/flash/openpower-software-manager/obmc-flash-bios b/meta-openbmc-machines/meta-openpower/common/recipes-phosphor/flash/openpower-software-manager/obmc-flash-bios
index 1c90e8b..dabd538 100644
--- a/meta-openbmc-machines/meta-openpower/common/recipes-phosphor/flash/openpower-software-manager/obmc-flash-bios
+++ b/meta-openbmc-machines/meta-openpower/common/recipes-phosphor/flash/openpower-software-manager/obmc-flash-bios
@@ -293,6 +293,40 @@
     done
 }
 
+clear_volatile() {
+  service=$(mapper get-service /org/open_power/control/volatile)
+  clearVolatileEnabled=$(busctl get-property $service /org/open_power/control/volatile xyz.openbmc_project.Object.Enable Enabled)
+  if [[ "$clearVolatileEnabled" != "b true" ]]; then
+    return 0
+  fi
+
+  PNOR_TOC_FILE="pnor.toc"
+  PNOR_RO_ACTIVE_PATH="/var/lib/phosphor-software-manager/pnor/ro/"
+  PNOR_RW_ACTIVE_PATH="/var/lib/phosphor-software-manager/pnor/rw/"
+  PNOR_PRSV_ACTIVE_PATH="/var/lib/phosphor-software-manager/pnor/prsv/"
+
+  # toc partition string format:
+  # partition27=HB_VOLATILE,0x02ba9000,0x02bae000,00,ECC,VOLATILE,READWRITE
+  tocFilePath="${PNOR_RO_ACTIVE_PATH}${PNOR_TOC_FILE}"
+  volatiles=($(grep VOLATILE "${tocFilePath}" | grep -Eo '^partition([0-9]+)=([A-Za-z0-9_]+)'))
+  for (( index=0; index<${#volatiles[@]}; index++ )); do
+    volatileName="$(echo ${volatiles[${index}]} | awk -F '=' '{print $2}')"
+
+    rwVolatile="${PNOR_RW_ACTIVE_PATH}${volatileName}"
+    if [ -f "${rwVolatile}" ]; then
+      echo "Clear $rwVolatile"
+      rm "${rwVolatile}"
+    fi
+    prsvVolatile="${PNOR_PRSV_ACTIVE_PATH}${volatileName}"
+    if [ -f "${prsvVolatile}" ]; then
+      echo "Clear $prsvVolatile"
+      rm "${prsvVolatile}"
+    fi
+  done
+  # Always reset the sensor after clearing
+  busctl set-property $service /org/open_power/control/volatile xyz.openbmc_project.Object.Enable Enabled b false
+}
+
 case "$1" in
   ubiattach)
     attach_ubi
@@ -323,6 +357,9 @@
   ubicleanup)
     ubi_cleanup
     ;;
+  clearvolatile)
+    clear_volatile
+    ;;
   *)
     echo "Invalid argument"
     exit 1
diff --git a/meta-openbmc-machines/meta-openpower/common/recipes-phosphor/flash/openpower-software-manager/obmc-flash-bios-check-clearvolatile@.service b/meta-openbmc-machines/meta-openpower/common/recipes-phosphor/flash/openpower-software-manager/obmc-flash-bios-check-clearvolatile@.service
new file mode 100644
index 0000000..af66b4d
--- /dev/null
+++ b/meta-openbmc-machines/meta-openpower/common/recipes-phosphor/flash/openpower-software-manager/obmc-flash-bios-check-clearvolatile@.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=Clear the Volatile PNOR partitions in host%i if Enabled
+After=obmc-flash-bios-enable-clearvolatile@%i.service
+Before=obmc-host-start-pre@%i.target
+ConditionPathExists=!/run/openbmc/host@%i-on
+
+[Service]
+Type=oneshot
+RemainAfterExit=no
+ExecStart=/usr/bin/env obmc-flash-bios clearvolatile
+SyslogIdentifier=obmc-flash-bios-check-clearvolatile
+
+[Install]
+RequiredBy=obmc-host-startmin@%i.target
diff --git a/meta-openbmc-machines/meta-openpower/common/recipes-phosphor/flash/openpower-software-manager/obmc-flash-bios-enable-clearvolatile@.service b/meta-openbmc-machines/meta-openpower/common/recipes-phosphor/flash/openpower-software-manager/obmc-flash-bios-enable-clearvolatile@.service
new file mode 100644
index 0000000..98778b7
--- /dev/null
+++ b/meta-openbmc-machines/meta-openpower/common/recipes-phosphor/flash/openpower-software-manager/obmc-flash-bios-enable-clearvolatile@.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=Enable the clearing of the Volatile PNOR partitions in host%i
+After=mapper-wait@-org-open_power-control-volatile.service
+Before=obmc-flash-bios-check-clearvolatile.service
+ConditionPathExists=!/run/openbmc/host@%i-on
+
+[Service]
+Type=oneshot
+RemainAfterExit=no
+ExecStart=/bin/sh -c "busctl set-property `mapper get-service /org/open_power/control/volatile` /org/open_power/control/volatile xyz.openbmc_project.Object.Enable Enabled b true"
+SyslogIdentifier=obmc-flash-bios-enable-clearvolatile
+
+[Install]
+RequiredBy=obmc-host-start@%i.target