]> git.ipfire.org Git - people/ms/firmware-update.git/commitdiff
Implement BIOS update for PC Engines APU
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 29 Mar 2019 11:02:59 +0000 (12:02 +0100)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 29 Mar 2019 11:02:59 +0000 (12:02 +0100)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Makefile.am
src/firmware-update.in

index f3438f115426c31fe6a25721c92af61fd0411d6d..29e42c05d2dc76a4a8524877e90394aaff9c4e03 100644 (file)
@@ -44,6 +44,7 @@ substitutions = \
        '|PACKAGE_NAME=$(PACKAGE_NAME)|' \
        '|PACKAGE_VERSION=$(PACKAGE_VERSION)|' \
        '|configsdir=$(configsdir)|' \
+       '|firmwaredir=$(firmwaredir)|' \
        '|sbindir=$(sbindir)|'
 
 SED_PROCESS = \
index b635ba442b1e601cd63289a712c834b363e2552d..6e1f75a34d9ac8d1996a1ee994ce4d9b175999c7 100644 (file)
 #                                                                             #
 ###############################################################################
 
+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