From 96f101732c0f35756680c74339e8e6c1406a7796 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Fri, 29 Mar 2019 12:02:59 +0100 Subject: [PATCH] Implement BIOS update for PC Engines APU Signed-off-by: Michael Tremer --- Makefile.am | 1 + src/firmware-update.in | 124 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 120 insertions(+), 5 deletions(-) diff --git a/Makefile.am b/Makefile.am index f3438f1..29e42c0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -44,6 +44,7 @@ substitutions = \ '|PACKAGE_NAME=$(PACKAGE_NAME)|' \ '|PACKAGE_VERSION=$(PACKAGE_VERSION)|' \ '|configsdir=$(configsdir)|' \ + '|firmwaredir=$(firmwaredir)|' \ '|sbindir=$(sbindir)|' SED_PROCESS = \ diff --git a/src/firmware-update.in b/src/firmware-update.in index b635ba4..6e1f75a 100644 --- a/src/firmware-update.in +++ b/src/firmware-update.in @@ -19,9 +19,13 @@ # # ############################################################################### +shopt -s nullglob + PACKAGE_NAME="@PACKAGE_NAME@" PACKAGE_VERSION="@PACKAGE_VERSION@" +FIRMWARE_DIR="@firmwaredir@" + read_dmi() { local what="${1}" @@ -40,10 +44,12 @@ read_dmi() { return 1 } -board_string() { - printf "%s %s\n" \ - "$(read_dmi "board_vendor")" \ - "$(read_dmi "board_name")" +board_vendor() { + read_dmi "board_vendor" +} + +board_name() { + read_dmi "board_name" } board_version() { @@ -62,13 +68,117 @@ bios_date() { read_dmi "bios_date" } +do_flashrom() { + echo "Flashing process is starting now..." + echo "PLEASE DO NOT TURN OFF THE SYSTEM WHILE FLASHING!" + + if ! flashrom "$@"; then + echo "Error: Flashing the firmware was not successful" >&2 + return 1 + fi + + echo "Flashing was successful! Please reboot." + return 0 +} + +find_firmware() { + local path="${FIRMWARE_DIR}/${1}" + + # Expand globbing + local files=( ${path} ) + + # Return file with highest order + local file="${files[-1]}" + + # Check if we can read the file + if [ ! -r "${file}" ]; then + echo "Error: Cannot read firmware file: ${file}" >&2 + return 1 + fi + + echo "${file}" + return 0 +} + +# Returns true if a is greater than b +version_is_gt() { + local a="${1}" + local b="${2}" + + # Check if a == b + [ "${a}" = "${b}" ] && return 1 + + # Sort by version + local sorted=( $(printf "${a}\n${b}\n" | sort -Vr) ) + + # If a comes first in the sorted order, it is largest + [ "${a}" = "${sorted[0]}" ] && return 0 + + # Otherwise b is greater than a + return 1 +} + +update_pcengines_apu() { + local board="${1}" + local running_version="${2}" + shift 2 + + # Find a new firmware file + local firmware="$(find_firmware "pcengines/apu/${board}_*.rom")" + if [ -z "${firmware}" ]; then + echo "Error: No firmware found" >&2 + return 1 + fi + + # Get basename and remove suffix + local new_version="$(basename "${firmware%.rom}")" + new_version="${new_version#*_}" + + # Check if we actually have a new version + if ! version_is_gt "${new_version}" "${running_version}"; then + echo "We have ${new_version} and this board is already on ${running_version}" + echo "No new firmware available. Aborting." + return 1 + fi + + # Perform update + do_flashrom -p "internal" -w "${firmware}" +} + +do_update() { + local vendor="$(board_vendor)" + local board="$(board_name)" + local bios_version="$(bios_version)" + + # Check if we could read the BIOS version + if [ -z "${bios_version}" ]; then + echo "Error: Could not detect BIOS version" >&2 + return 1 + fi + + echo "Detected ${vendor} ${board} running BIOS version ${bios_version}" + + case "${vendor},${board}" in + "PC Engines",apu*) + update_pcengines_apu "${board}" "${bios_version}" "$@" + ;; + + *) + echo "Unkown vendor: ${vendor}" >&2 + echo "Support for this vendor might not have been implement, yet" >&2 + return 1 + ;; + esac +} + main() { local action="${1}" shift case "${action}" in info) - printf "%-12s: %s\n" "Board" "$(board_string)" + printf "%-12s: %s %s\n" "Board" \ + "$(board_vendor)" "$(board_name)" printf "%-12s: %s\n" "HW Version" "$(board_version)" printf "%-12s: %s\n" "Serial" "$(board_serial)" printf "%-12s: %s (%s)\n" "BIOS Version" \ @@ -76,6 +186,10 @@ main() { return 0 ;; + update) + do_update + ;; + version) echo "${PACKAGE_NAME}: Version ${PACKAGE_VERSION}" return 0 -- 2.47.3