Add common gBMC system init script
Create a configurable sysinit script for all gBMC system to use. This
prevents difference in implementation during bootup between platforms.
The plan is to have each system that uses `gbmc-sysinit` to
replace the `gbmc_sysinit_helper.sh` and its function. It should be
flexible enough to support most current use cases. The service
dependencies will be configured with `service-override.conf` to make
sure that all dependencies are met on different systems.
The `gbmc_sysinit.sh` has `BIOS_PARTITION`, `BIOS_SIZE`, `BIOS_KEY` as
configurable variable depending on the BIOS image supported on the
different systems.
Google-Bug-Id: 231234523
Change-Id: Iea600521e0be4254d45731fd09a23f4db8af01f8
Signed-off-by: Willy Tu <wltu@google.com>
diff --git a/recipes-google/gbmc-sysinit/gbmc-sysinit.bb b/recipes-google/gbmc-sysinit/gbmc-sysinit.bb
new file mode 100644
index 0000000..b2172d0
--- /dev/null
+++ b/recipes-google/gbmc-sysinit/gbmc-sysinit.bb
@@ -0,0 +1,50 @@
+SUMMARY = "gBMC System Initialization Service"
+DESCRIPTION = "Verify the BIOS and release initalize the system"
+PR = "r1"
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
+
+S = "${WORKDIR}"
+
+inherit systemd
+
+DEPENDS = "systemd"
+RDEPENDS:${PN} = " \
+ bash \
+ libsystemd \
+"
+
+BIOS_PARTITION ?= "bios-primary"
+BIOS_SIZE ?= "67108864"
+BIOS_KEY ?= "/usr/share/google-bios-key/platforms_secure.pem"
+
+SRC_URI = " \
+ file://gbmc_sysinit.sh.in \
+ file://gbmc_sysinit_helper.sh \
+ file://gbmc-host-ready.target \
+ file://gbmc-sysinit.service \
+"
+
+SYSTEMD_PACKAGES = "${PN}"
+SYSTEMD_SERVICE:${PN}:append = " \
+ gbmc-sysinit.service \
+ gbmc-host-ready.target \
+"
+
+do_install () {
+ sed ${WORKDIR}/gbmc_sysinit.sh.in \
+ -e "s#@BIOS_PARTITION@#${BIOS_PARTITION}#" \
+ -e "s#@BIOS_SIZE@#${BIOS_SIZE}#" \
+ -e "s#@BIOS_KEY@#${BIOS_KEY}#" \
+ > ${WORKDIR}/gbmc_sysinit.sh
+
+ install -d ${D}${bindir}
+ install -m 0755 ${WORKDIR}/gbmc_sysinit.sh ${D}${bindir}/
+
+ install -d ${D}${systemd_unitdir}/system/
+ install -m 0644 ${WORKDIR}/gbmc-sysinit.service ${D}${systemd_unitdir}/system
+ install -m 0644 ${WORKDIR}/gbmc-host-ready.target ${D}${systemd_unitdir}/system
+
+ install -d ${D}${datadir}/gbmc-sysinit
+ install -m 0755 ${WORKDIR}/gbmc_sysinit_helper.sh ${D}${datadir}/gbmc-sysinit/
+}
diff --git a/recipes-google/gbmc-sysinit/gbmc-sysinit/gbmc-host-ready.target b/recipes-google/gbmc-sysinit/gbmc-sysinit/gbmc-host-ready.target
new file mode 100644
index 0000000..1e76dc2
--- /dev/null
+++ b/recipes-google/gbmc-sysinit/gbmc-sysinit/gbmc-host-ready.target
@@ -0,0 +1,5 @@
+[Unit]
+Description=The host is ready to be powered on
+Wants=phosphor-ipmi-host.service
+After=phosphor-ipmi-host.service
+RefuseManualStop=yes
diff --git a/recipes-google/gbmc-sysinit/gbmc-sysinit/gbmc-sysinit.service b/recipes-google/gbmc-sysinit/gbmc-sysinit/gbmc-sysinit.service
new file mode 100644
index 0000000..64f5714
--- /dev/null
+++ b/recipes-google/gbmc-sysinit/gbmc-sysinit/gbmc-sysinit.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=gBMC System Initialization and release Host from reset
+Requires=gbmc-host-ready.target
+After=gbmc-host-ready.target
+Requires=hothd.service
+After=hothd.service
+
+[Service]
+Type=oneshot
+ExecStart=/usr/bin/gbmc_sysinit.sh
+
+[Install]
+WantedBy=multi-user.target
diff --git a/recipes-google/gbmc-sysinit/gbmc-sysinit/gbmc_sysinit.sh.in b/recipes-google/gbmc-sysinit/gbmc-sysinit/gbmc_sysinit.sh.in
new file mode 100644
index 0000000..eb584ad
--- /dev/null
+++ b/recipes-google/gbmc-sysinit/gbmc-sysinit/gbmc_sysinit.sh.in
@@ -0,0 +1,93 @@
+#!/bin/bash
+# Copyright 2022 Google LLC
+#
+# 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.
+
+# Platform specific helper function.
+# Need to support bind_host_mtd, unbind_host_mtd, is_bios_down,
+# release_host_bios, cleanup, and bios_validator.
+source /usr/share/gbmc-sysinit/*.sh
+
+# Internal gBMC BIOS Update Functions. Expected to fail with OpenBMC image.
+source /usr/libexec/bios-common.sh
+
+trap unbind_host_mtd EXIT SIGHUP SIGINT SIGTERM
+
+# 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}"
+}
+
+# Verity the BIOS image before releasing it to the CPU.
+verify_host_bios() {
+ trap verify_bios_cleanup RETURN
+ trap unbind_host_mtd RETURN
+
+ setup_bios_validation
+
+ echo "BIOS verification start!" >&2
+ local PERSIST_LOCATION="/var/google"
+ local BIOS_PERSIST_FILE="${PERSIST_LOCATION}/host_bios_version"
+
+ # Take control of the BIOS SPI Flash.
+ bind_host_mtd || { echo "Failed to bind SPI driver for host MTD" >&2; return 1; }
+
+ bios_mtd="$(findmtd @BIOS_PARTITION@)"
+ [[ -z "${bios_mtd}" ]] && { echo "Failed to find host MTD partition!" >&2; return 1; }
+
+ # Attempt to make persist directory if it doesn't exist.
+ mkdir -p "${PERSIST_LOCATION}"
+
+ # Make sure the bios version does not persist reboots.
+ rm -f "${BIOS_PERSIST_FILE}"
+ # bios_validator will freeze the secondary token on failure
+ bios_validator validate "/dev/${bios_mtd}ro" @BIOS_SIZE@ \
+ @BIOS_KEY@ --send_tokens --write_version "${BIOS_PERSIST_FILE}"
+
+ # Validate Stage Version
+ bios_init_stage
+
+ # Validate Active Version
+ bios_init_active "${BIOS_PERSIST_FILE}"
+
+ echo "BIOS verification complete!" >&2
+}
+
+verify_bios_cleanup() {
+ bios_validator freeze
+}
+
+main() {
+ trap verify_bios_cleanup RETURN
+
+ # Validate the BIOS if it is down when the gBMC is booting up.
+ if is_bios_down; then
+ verify_host_bios
+
+ echo "Release host from reset!" >&2
+ release_host_bios
+ else
+ bios_validator freeze
+ echo "Host is already running. Tried to freeze the secondary token set!" >&2
+ fi
+
+ cleanup || true
+}
+
+# Exit without running main() if sourced
+return 0 2>/dev/null
+
+main "$@"
diff --git a/recipes-google/gbmc-sysinit/gbmc-sysinit/gbmc_sysinit_helper.sh b/recipes-google/gbmc-sysinit/gbmc-sysinit/gbmc_sysinit_helper.sh
new file mode 100644
index 0000000..caa03aa
--- /dev/null
+++ b/recipes-google/gbmc-sysinit/gbmc-sysinit/gbmc_sysinit_helper.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+# Copyright 2022 Google LLC
+#
+# 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.
+bind_host_mtd() {
+ echo "bind_host_mtd is not implemented" >&2
+ return 1
+}
+
+unbind_host_mtd() {
+ echo "unbind_host_mtd is not implemented" >&2
+ return 1
+}
+
+is_bios_down() {
+ echo "is_bios_down is not implemented" >&2
+ return 0
+}
+
+setup_bios_validation() {
+ echo "setup_bios_validation is not implemented" >&2
+ return 0
+}
+
+release_host_bios() {
+ echo "release_host_bios is not implemented" >&2
+ return 1
+}
+
+cleanup(){
+ echo "cleanup is not implemented" >&2
+ return 1
+}
+
+# Test timing by computing SHA256SUM.
+bios_validator(){
+ if [[ "$1" == "validate" ]]; then
+ sha256sum "$2"
+ fi
+}