From 027dcc2dbea9b34189f8617a20c22831bd95bdb5 Mon Sep 17 00:00:00 2001
From: Robert Collins <rbtcollins@hp.com>
Date: Wed, 16 Jul 2014 18:58:02 +1200
Subject: [PATCH] Add support for flashing ILO BMC's from ramdisks

This is more than a bit hard to test, requiring as it does an actual
iLO BMC, so sadly I have no tests :(.

HP Hardware really wants to be running latest firmware, and its
commonly agreed that one place where it can be sanely applied is in
the deploy environment, so this is my long threatened implementation
of that.

Change-Id: I3117a250d0d0eb8ee33eb4b15c837485a5cbf476
---
 elements/ilo/README.md                        | 15 +++++++++++
 elements/ilo/extra-data.d/50-ilo-firmware     | 25 +++++++++++++++++++
 elements/ilo/init.d/50-ilo-firmware           | 22 ++++++++++++++++
 .../ilo/ramdisk-install.d/50-ilo-firmware     | 10 ++++++++
 4 files changed, 72 insertions(+)
 create mode 100644 elements/ilo/README.md
 create mode 100755 elements/ilo/extra-data.d/50-ilo-firmware
 create mode 100644 elements/ilo/init.d/50-ilo-firmware
 create mode 100755 elements/ilo/ramdisk-install.d/50-ilo-firmware

diff --git a/elements/ilo/README.md b/elements/ilo/README.md
new file mode 100644
index 000000000..a9d9e11f3
--- /dev/null
+++ b/elements/ilo/README.md
@@ -0,0 +1,15 @@
+Ramdisk support for applying HP iLO firmware.
+
+The firmware files are copied in via an extra-data hook: the variable
+DIB\_ILO\_FIRMWARE\_PATH specifies a directory, and every file in that directory
+will be unpacked into a same-named directory in the ramdisk (using
+--unpack=...). If the path is not specified, a diagnostic is output but no
+error is triggered.
+
+During ramdisk init every found firmware installer will be executed using
+--silent --log=log The log is displayed after the firmware has executed.
+
+If the firmware exits with status 0 (ok), status 2 (same or older version) or 4
+(ilo not detected) a diagnostic message is logged and init proceeds.
+
+Any other status code is treated as an error.
diff --git a/elements/ilo/extra-data.d/50-ilo-firmware b/elements/ilo/extra-data.d/50-ilo-firmware
new file mode 100755
index 000000000..aa8c4784b
--- /dev/null
+++ b/elements/ilo/extra-data.d/50-ilo-firmware
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+set -eu
+set -o pipefail
+
+if [ -z "${DIB_ILO_FIRMWARE_PATH:-}" ]; then
+    echo "DIB_ILO_FIRMWARE_PATH not set in ilo element" >&2
+    exit 0
+fi
+
+if [ ! -d "${DIB_ILO_FIRMWARE_PATH}" ]; then
+    echo "Firmware path not found: ${DIB_ILO_FIRMWARE_PATH}"
+    exit 1
+fi
+
+# We copy to /tmp because its temporary - we do a mv later into the initramfs
+# image.
+mkdir -p "$TMP_MOUNT_PATH/tmp/ilo/"
+find "${DIB_ILO_FIRMWARE_PATH}" -type f \( -name '*.scexe' -o -name '*.exe' \) | while read FWNAME
+do
+    TARGET="$TMP_MOUNT_PATH/tmp/ilo/$(basename "$FWNAME")"
+    echo Unpacking $FWNAME to $TARGET
+    bash "$FWNAME" "--unpack=$TARGET"
+    echo Done
+done
diff --git a/elements/ilo/init.d/50-ilo-firmware b/elements/ilo/init.d/50-ilo-firmware
new file mode 100644
index 000000000..bb6cb064d
--- /dev/null
+++ b/elements/ilo/init.d/50-ilo-firmware
@@ -0,0 +1,22 @@
+if [ -d /ilo ]; then
+    find /ilo -type f \( -name flash_ilo3 -o -name flash_ilo4 \) | while read FWNAME
+    do
+        cd "$(dirname "$FWNAME")"
+        logname="$(basename "$(dirname "$FWNAME")").log"
+        echo Running $FWNAME
+        "$FWNAME" --silent --log "$logname"
+        result=$?
+        echo Finished $FWNAME with result $?
+        cat "$logname"
+        #avoid leaking space during large runs
+        rm "$logname"
+        if [ $result -eq 2 ]; then
+            echo "Firmware already up to date"
+        elif [ $result -eq 4 ]; then
+            echo "Firmware not applicable to machine"
+        elif [ $result -ne 0 ]; then
+            echo "Error applying firmware"
+            troubleshoot
+        fi
+    done
+fi
diff --git a/elements/ilo/ramdisk-install.d/50-ilo-firmware b/elements/ilo/ramdisk-install.d/50-ilo-firmware
new file mode 100755
index 000000000..24117bc4f
--- /dev/null
+++ b/elements/ilo/ramdisk-install.d/50-ilo-firmware
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+set -eu
+set -o pipefail
+
+if [ ! -d /tmp/ilo ]; then
+    exit 0
+fi
+
+mv /tmp/ilo "$TMP_MOUNT_PATH"