meta-quanta: gbs: inband bmc/bios image update

gbs-bmc-update and gbs-bios-update packages do
inband bmc/bios image update via Nuvoton PCI mailbox

Tested:
Set PCI mailbox memory space as writable
~# sudo setpci -d 1050:0750 04.B=02

bmc update:
~# sudo burn_my_bmc --command update --interface ipmipci
--image image-bmc --sig image-bmc.sig --type image

bios update:
~# sudo burn_my_bmc --command update --interface ipmipci
--image image-bios --sig image-bios.sig --type bios

Signed-off-by: George Hung <george.hung@quantatw.com>
Change-Id: I69df209d74ae8321b8f50b3cd390eca79a41e902
diff --git a/meta-gbs/recipes-gbs/gbs-bios-update/files/bios-update.sh b/meta-gbs/recipes-gbs/gbs-bios-update/files/bios-update.sh
new file mode 100644
index 0000000..3a215fa
--- /dev/null
+++ b/meta-gbs/recipes-gbs/gbs-bios-update/files/bios-update.sh
@@ -0,0 +1,84 @@
+#!/bin/sh
+# Copyright 2020 Google LLC
+# Copyright 2020 Quanta Computer Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Global variables
+
+# GPIO to control the host SPI mux
+SPI_SW_SELECT=169
+
+# Kernel control string for bind/unbind
+KERNEL_FIU_ID="c0000000.fiu"
+
+# Kernel sysfs path for bind/unbind
+KERNEL_SYSFS_FIU="/sys/bus/platform/drivers/NPCM-FIU"
+
+IMAGE_FILE="/tmp/image-bios"
+
+# Taken from /run/initramfs/update
+# Given label name, return mtd node. e.g. `findmtd bmc` returns 'mtd0'
+findmtd() {
+    m=$(grep -xl "$1" /sys/class/mtd/*/name)
+    m=${m%/name}
+    m=${m##*/}
+    echo $m
+}
+
+cleanup() {
+    if [ -d "${KERNEL_SYSFS_FIU}/${KERNEL_FIU_ID}" ]; then
+        echo "${KERNEL_FIU_ID}" > "${KERNEL_SYSFS_FIU}"/unbind
+    fi
+    echo low > /sys/class/gpio/gpio${SPI_SW_SELECT}/direction  # Switch mux to host
+    rm -f ${IMAGE_FILE}
+}
+trap cleanup EXIT SIGHUP SIGINT SIGTERM
+
+main() {
+    if [ ! -f ${IMAGE_FILE} ]; then
+        echo "Invalid bios image file!"
+        exit 1
+    fi
+
+    echo "Starting bios update..."
+    if [ ! -d "/sys/class/gpio/gpio${SPI_SW_SELECT}" ]; then
+        echo "${SPI_SW_SELECT}" > /sys/class/gpio/export
+    fi
+
+    echo high > /sys/class/gpio/gpio${SPI_SW_SELECT}/direction  # Switch mux to BMC
+
+    if [ -d "${KERNEL_SYSFS_FIU}/${KERNEL_FIU_ID}" ]; then
+        echo "${KERNEL_FIU_ID}" > "${KERNEL_SYSFS_FIU}"/unbind
+    fi
+    echo "${KERNEL_FIU_ID}" > "${KERNEL_SYSFS_FIU}"/bind
+
+    # BIOS flash is labelled 'pnor'
+    pnor_mtd=$(findmtd pnor)
+    if [ -z "${pnor_mtd}" ]; then
+        echo "Cannot find bios flash mtd partition!"
+        exit 1
+    fi
+
+    flashcp -v $IMAGE_FILE /dev/"${pnor_mtd}"
+    if [ $? -eq 0 ]; then
+        echo "bios update successfully..."
+    else
+        echo "bios update failed..."
+        exit 1
+    fi
+}
+# Exit without running main() if sourced
+return 0 2>/dev/null
+
+main "$@"
diff --git a/meta-gbs/recipes-gbs/gbs-bios-update/files/bios-verify.sh b/meta-gbs/recipes-gbs/gbs-bios-update/files/bios-verify.sh
new file mode 100644
index 0000000..3da25e4
--- /dev/null
+++ b/meta-gbs/recipes-gbs/gbs-bios-update/files/bios-verify.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+# Copyright (c) 2019-present Lenovo
+# Copyright (c) 2020 Quanta Computer Inc.
+# Licensed under BSD-3, see COPYING.BSD file for details.
+
+IMAGE_FILE="/tmp/bios-image"
+SIG_FILE="/tmp/bmc.sig"
+BURN_IMAGE="/tmp/image-bios"
+sha256_image="FFFF"
+sha256_file="EEEE"
+
+echo "Verify bios image..."
+
+if [ -e $IMAGE_FILE ] && [ -e $SIG_FILE ];
+then
+    sha256_image=`sha256sum "$IMAGE_FILE" | awk '{print $1}'`
+    sha256_file=`awk '{print $1}' $SIG_FILE`
+fi
+
+if [[ $sha256_image != $sha256_file ]];
+then
+    echo "bios image verify fail."
+    rm -f $IMAGE_FILE
+    echo "Remove bios image"
+    exit 1
+else
+    echo "bios image verify ok."
+    mv $IMAGE_FILE $BURN_IMAGE
+    rm -f $SIG_FILE
+    exit 0
+fi
diff --git a/meta-gbs/recipes-gbs/gbs-bios-update/files/config-bios.json b/meta-gbs/recipes-gbs/gbs-bios-update/files/config-bios.json
new file mode 100644
index 0000000..efbe6f8
--- /dev/null
+++ b/meta-gbs/recipes-gbs/gbs-bios-update/files/config-bios.json
@@ -0,0 +1,20 @@
+[{
+    "blob": "/flash/bios",
+    "handler": {
+        "type": "file",
+        "path": "/tmp/bios-image"
+    },
+    "actions": {
+        "preparation": {
+            "type": "skip"
+        },
+        "verification": {
+            "type": "systemd",
+            "unit": "phosphor-ipmi-flash-bios-verify.service"
+        },
+        "update": {
+            "type": "systemd",
+            "unit": "phosphor-ipmi-flash-bios-update.service"
+        }
+    }
+}]
diff --git a/meta-gbs/recipes-gbs/gbs-bios-update/files/phosphor-ipmi-flash-bios-update.service b/meta-gbs/recipes-gbs/gbs-bios-update/files/phosphor-ipmi-flash-bios-update.service
new file mode 100644
index 0000000..a08816a
--- /dev/null
+++ b/meta-gbs/recipes-gbs/gbs-bios-update/files/phosphor-ipmi-flash-bios-update.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Phosphor-ipmi-flash update BIOS service
+
+[Service]
+ExecStart=/usr/bin/bios-update.sh
+Type=oneshot
+
+[Install]
+WantedBy=phosphor-ipmi-flash-bios-update.target
diff --git a/meta-gbs/recipes-gbs/gbs-bios-update/files/phosphor-ipmi-flash-bios-verify.service b/meta-gbs/recipes-gbs/gbs-bios-update/files/phosphor-ipmi-flash-bios-verify.service
new file mode 100644
index 0000000..af0e196
--- /dev/null
+++ b/meta-gbs/recipes-gbs/gbs-bios-update/files/phosphor-ipmi-flash-bios-verify.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Phosphor-ipmi-flash verify BIOS service
+
+[Service]
+ExecStart=/usr/bin/bios-verify.sh
+Type=oneshot
+
+[Install]
+WantedBy=phosphor-ipmi-flash-bios-verify.target