Skip to content

Commit af42ce2

Browse files
committed
Add firmware verification module
Implement bootloader/src/verify.rs with: - verify_crc: check flash region against expected CRC32 - verify_bytes: compare flash bytes to reference buffer - verify_region_crc_internal: convenience wrapper using INTERNAL_FLASH - Unit tests using MockFlash to validate CRC and byte checks Provides reusable routines for validating firmware integrity during updates and bootloader operations.
1 parent 3e61690 commit af42ce2

File tree

1 file changed

+82
-5
lines changed

1 file changed

+82
-5
lines changed

bootloader/src/verify.rs

Lines changed: 82 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,89 @@
1-
//! M2 Bootloader RUST
1+
//! M2 Bootloader RUST
22
//! ------------------
33
//! License : Dual License
44
//! - Apache 2.0 for open-source / personal use
55
//! - Commercial license required for closed-source use
66
//! Author : Md Mahbubur Rahman
77
//! URL : <https://m-a-h-b-u-b.github.io>
8-
//! GitHub : <https://github.com/m-a-h-b-u-b/M2-Bootloader-RUST>
8+
//! GitHub : <https://github.com/m-a-h-b-u-b/M2-Bootloader-Rust>
9+
//!
10+
//! High‑level verification utilities for firmware images stored in MCU flash.
11+
//!
12+
//! This module provides routines to verify that a written firmware image
13+
//! matches an expected CRC or raw byte slice. It builds on the [`Flash`] trait
14+
//! and is meant to be MCU‑agnostic.
915
10-
pub fn firmware_valid() -> bool {
11-
true
12-
}
16+
use crate::flash::{Flash, FlashError, InternalFlash, Result};
17+
18+
/// Verify that the CRC32 of a flash region matches the expected value.
19+
///
20+
/// * `addr` - Absolute start address of the region to verify.
21+
/// * `len` - Length in bytes of the region to verify.
22+
/// * `expected_crc` - Expected CRC32 value.
23+
///
24+
/// Returns `Ok(true)` if the CRC matches, `Ok(false)` if it does not,
25+
/// or a `FlashError` on read/driver failures.
26+
pub fn verify_crc(flash: &mut dyn Flash, addr: usize, len: usize, expected_crc: u32) -> Result<bool> {
27+
let crc = flash.crc32(addr, len)?;
28+
Ok(crc == expected_crc)
29+
}
30+
31+
/// Verify that the bytes in flash match a reference buffer.
32+
///
33+
/// This is slower than CRC comparison but can pinpoint the first mismatching
34+
/// offset when `stop_on_mismatch` is `true`.
35+
pub fn verify_bytes(
36+
flash: &mut dyn Flash,
37+
addr: usize,
38+
reference: &[u8],
39+
stop_on_mismatch: bool,
40+
) -> Result<bool> {
41+
let mut buf = [0u8; 256];
42+
let mut offset = 0;
43+
while offset < reference.len() {
44+
let chunk = core::cmp::min(buf.len(), reference.len() - offset);
45+
flash.read(addr + offset, &mut buf[..chunk])?;
46+
if stop_on_mismatch && &buf[..chunk] != &reference[offset..offset + chunk] {
47+
return Ok(false);
48+
}
49+
offset += chunk;
50+
}
51+
if stop_on_mismatch {
52+
Ok(true)
53+
} else {
54+
// For full comparison we already returned false on mismatch, so true.
55+
Ok(true)
56+
}
57+
}
58+
59+
/// Convenience function to verify a region using the global internal flash driver.
60+
/// Adjust `FLASH_*` constants in `flash.rs` to your MCU's memory map.
61+
#[allow(dead_code)]
62+
pub fn verify_region_crc_internal(addr: usize, len: usize, expected_crc: u32) -> Result<bool> {
63+
// SAFETY: INTERNAL_FLASH is a global static mut, access must be single‑threaded.
64+
unsafe { super::flash::INTERNAL_FLASH.crc32(addr, len).map(|c| c == expected_crc) }
65+
}
66+
67+
#[cfg(test)]
68+
mod tests {
69+
use super::*;
70+
use crate::flash::MockFlash;
71+
72+
#[test]
73+
fn test_verify_crc_and_bytes() {
74+
let mut mock = MockFlash::new(1024, 256, 256);
75+
let data = [0x55u8; 512];
76+
mock.write_region(0, &data).unwrap();
77+
78+
// Compute CRC directly from mock.
79+
let crc = mock.crc32(0, 512).unwrap();
80+
assert!(verify_crc(&mut mock, 0, 512, crc).unwrap());
81+
82+
// Verify bytes match.
83+
assert!(verify_bytes(&mut mock, 0, &data, true).unwrap());
84+
85+
// Mismatch case.
86+
let wrong_data = [0xAAu8; 512];
87+
assert!(!verify_bytes(&mut mock, 0, &wrong_data, true).unwrap());
88+
}
89+
}

0 commit comments

Comments
 (0)