From daad28efa2bfd8445abe4821fcecb5585477b9b3 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu <sam@rfc1149.net> Date: Tue, 30 Jul 2024 19:00:00 +0200 Subject: [PATCH] Check that the bootloader and firmware-updater are compatible --- Cargo.lock | 111 +++++++++++++++++++++++++++++ bootloader/python/bootloader.py | 2 +- firmware-updater/Cargo.toml | 3 + firmware-updater/src/bootloader.rs | 35 ++++----- firmware-updater/src/main.rs | 3 + 5 files changed, 132 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 31bc357..9ab363e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,15 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + [[package]] name = "anstream" version = "0.6.15" @@ -667,6 +676,19 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" +[[package]] +name = "env_logger" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + [[package]] name = "eyre" version = "0.6.12" @@ -686,7 +708,10 @@ dependencies = [ "color-eyre", "elf", "indicatif", + "log", + "pretty_env_logger", "rppal", + "semver 1.0.23", "thiserror", ] @@ -788,6 +813,18 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "i2c2-target" version = "0.1.0" @@ -832,6 +869,17 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "is-terminal" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys", +] + [[package]] name = "is_terminal_polyfill" version = "1.70.1" @@ -856,6 +904,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + [[package]] name = "memchr" version = "2.7.4" @@ -957,6 +1011,16 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" +[[package]] +name = "pretty_env_logger" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "865724d4dbe39d9f3dd3b52b88d859d66bcb2d6a0acfd5ea68a65fb66d4bdc1c" +dependencies = [ + "env_logger", + "log", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -1005,6 +1069,35 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +[[package]] +name = "regex" +version = "1.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + [[package]] name = "rppal" version = "0.18.0" @@ -1136,6 +1229,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + [[package]] name = "thiserror" version = "1.0.63" @@ -1258,6 +1360,15 @@ dependencies = [ "vcell", ] +[[package]] +name = "winapi-util" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +dependencies = [ + "windows-sys", +] + [[package]] name = "windows-sys" version = "0.52.0" diff --git a/bootloader/python/bootloader.py b/bootloader/python/bootloader.py index dbb7544..7c72417 100644 --- a/bootloader/python/bootloader.py +++ b/bootloader/python/bootloader.py @@ -1,7 +1,7 @@ import struct # Major and minor version of required firmware -_REQUIRED_FIRMWARE_VERSION = (0, 1) +_REQUIRED_FIRMWARE_VERSION = (0, 2) class FirmwareVersionMismatch(Exception): diff --git a/firmware-updater/Cargo.toml b/firmware-updater/Cargo.toml index 41a7a09..7805229 100644 --- a/firmware-updater/Cargo.toml +++ b/firmware-updater/Cargo.toml @@ -12,5 +12,8 @@ clap = { version = "4.5.9", features = ["cargo", "derive"] } color-eyre = "0.6.3" elf = "0.7.4" indicatif = "0.17.8" +log = "0.4.22" +pretty_env_logger = "0.5.0" rppal = "0.18.0" +semver = "1.0.23" thiserror = "1.0.63" diff --git a/firmware-updater/src/bootloader.rs b/firmware-updater/src/bootloader.rs index eaaae3c..dd8c36f 100644 --- a/firmware-updater/src/bootloader.rs +++ b/firmware-updater/src/bootloader.rs @@ -5,30 +5,17 @@ use bootloader_params::commands::{ }; use indicatif::ProgressBar; use rppal::i2c::{self, I2c}; +use semver::{Version, VersionReq}; use std::{fmt::Display, thread, time::Duration}; use crate::elf_loader::Segment; -pub struct Version { - major: u8, - minor: u8, - patch: u8, -} - -impl Display for Version { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}.{}.{}", self.major, self.minor, self.patch) - } -} - -impl From<&[u8; 3]> for Version { - fn from(value: &[u8; 3]) -> Self { - Self { - major: value[0], - minor: value[1], - patch: value[2], - } - } +fn version_from_bytes(bytes: &[u8; 3]) -> Version { + Version::new( + u64::from(bytes[0]), + u64::from(bytes[1]), + u64::from(bytes[2]), + ) } pub enum ActiveProgram { @@ -59,6 +46,8 @@ pub enum Error { ChecksumMismatch, #[error("memory does not match expected content")] MemoryContentMismatch, + #[error(transparent)] + SemVer(#[from] semver::Error), } pub type Result<T, E = Error> = std::result::Result<T, E>; @@ -82,10 +71,14 @@ pub fn active_program(i2c: &mut I2c) -> Result<ActiveProgram> { && buffer[0] == device && i2c.block_read(CMD_FIRMWARE_VERSION, &mut buffer).is_ok() { - let version = Version::from(&buffer); + let version = version_from_bytes(&buffer); if device == CONTROLLER_ID { return Ok(ActiveProgram::Controller(version)); } else { + let fwupd_req = VersionReq::parse(env!("CARGO_PKG_VERSION"))?; + if !fwupd_req.matches(&version) { + log::warn!("Bootloader version {version} does not match requirement for firmware-updater {fwupd_req}"); + } return Ok(ActiveProgram::Bootloader(version)); } } diff --git a/firmware-updater/src/main.rs b/firmware-updater/src/main.rs index 6b6bba6..b40b5bc 100644 --- a/firmware-updater/src/main.rs +++ b/firmware-updater/src/main.rs @@ -32,6 +32,9 @@ type Result<T, E = Error> = std::result::Result<T, E>; fn main() -> color_eyre::Result<()> { color_eyre::install()?; + pretty_env_logger::formatted_builder() + .filter_level(log::LevelFilter::Info) + .init(); match Cli::parse().command { Command::CheckFile(args) => cmd_check_file(args)?, Command::Flash(args) => cmd_flash(args)?, -- GitLab