Add get_state helpers to allow self-testing before calling mark_booted

This commit is contained in:
Mathias 2022-09-26 06:53:40 +02:00
parent 7f16b1cd23
commit b2a327a858

View File

@ -604,6 +604,21 @@ impl FirmwareUpdater {
self.dfu.len() self.dfu.len()
} }
/// Obtain the current state.
///
/// This is useful to check if the bootloader has just done a swap, in order
/// to do verifications and self-tests of the new image before calling
/// `mark_booted`.
pub async fn get_state<F: AsyncNorFlash>(&mut self, flash: &mut F, aligned: &mut [u8]) -> Result<State, F::Error> {
flash.read(self.state.from as u32, aligned).await?;
if !aligned.iter().any(|&b| b != SWAP_MAGIC) {
Ok(State::Swap)
} else {
Ok(State::Boot)
}
}
/// Mark to trigger firmware swap on next boot. /// Mark to trigger firmware swap on next boot.
/// ///
/// # Safety /// # Safety
@ -673,8 +688,8 @@ impl FirmwareUpdater {
self.dfu.from + offset + data.len() self.dfu.from + offset + data.len()
); );
FirmwareWriter(self) FirmwareWriter(self.dfu)
.write_firmware(offset, data, flash, block_size) .write_block(offset, data, flash, block_size)
.await?; .await?;
Ok(()) Ok(())
@ -690,13 +705,28 @@ impl FirmwareUpdater {
trace!("Erased from {} to {}", self.dfu.from, self.dfu.to); trace!("Erased from {} to {}", self.dfu.from, self.dfu.to);
Ok(FirmwareWriter(self)) Ok(FirmwareWriter(self.dfu))
} }
// //
// Blocking API // Blocking API
// //
/// Obtain the current state.
///
/// This is useful to check if the bootloader has just done a swap, in order
/// to do verifications and self-tests of the new image before calling
/// `mark_booted`.
pub fn get_state_blocking<F: NorFlash>(&mut self, flash: &mut F, aligned: &mut [u8]) -> Result<State, F::Error> {
flash.read(self.state.from as u32, aligned)?;
if !aligned.iter().any(|&b| b != SWAP_MAGIC) {
Ok(State::Swap)
} else {
Ok(State::Boot)
}
}
/// Mark to trigger firmware swap on next boot. /// Mark to trigger firmware swap on next boot.
/// ///
/// # Safety /// # Safety
@ -764,7 +794,7 @@ impl FirmwareUpdater {
self.dfu.from + offset + data.len() self.dfu.from + offset + data.len()
); );
FirmwareWriter(self).write_firmware_blocking(offset, data, flash, block_size)?; FirmwareWriter(self.dfu).write_block_blocking(offset, data, flash, block_size)?;
Ok(()) Ok(())
} }
@ -779,14 +809,14 @@ impl FirmwareUpdater {
trace!("Erased from {} to {}", self.dfu.from, self.dfu.to); trace!("Erased from {} to {}", self.dfu.from, self.dfu.to);
Ok(FirmwareWriter(self)) Ok(FirmwareWriter(self.dfu))
} }
} }
/// FirmwareWriter allows writing blocks to an already erased flash. /// FirmwareWriter allows writing blocks to an already erased flash.
pub struct FirmwareWriter<'a>(&'a mut FirmwareUpdater); pub struct FirmwareWriter(Partition);
impl<'a> FirmwareWriter<'a> { impl FirmwareWriter {
/// Write data to a flash page. /// Write data to a flash page.
/// ///
/// The buffer must follow alignment requirements of the target flash and a multiple of page size big. /// The buffer must follow alignment requirements of the target flash and a multiple of page size big.
@ -794,7 +824,7 @@ impl<'a> FirmwareWriter<'a> {
/// # Safety /// # Safety
/// ///
/// Failing to meet alignment and size requirements may result in a panic. /// Failing to meet alignment and size requirements may result in a panic.
pub async fn write_firmware<F: AsyncNorFlash>( pub async fn write_block<F: AsyncNorFlash>(
&mut self, &mut self,
offset: usize, offset: usize,
data: &[u8], data: &[u8],
@ -803,11 +833,11 @@ impl<'a> FirmwareWriter<'a> {
) -> Result<(), F::Error> { ) -> Result<(), F::Error> {
trace!( trace!(
"Writing firmware at offset 0x{:x} len {}", "Writing firmware at offset 0x{:x} len {}",
self.0.dfu.from + offset, self.0.from + offset,
data.len() data.len()
); );
let mut write_offset = self.0.dfu.from + offset; let mut write_offset = self.0.from + offset;
for chunk in data.chunks(block_size) { for chunk in data.chunks(block_size) {
trace!("Wrote chunk at {}: {:?}", write_offset, chunk); trace!("Wrote chunk at {}: {:?}", write_offset, chunk);
flash.write(write_offset as u32, chunk).await?; flash.write(write_offset as u32, chunk).await?;
@ -838,7 +868,7 @@ impl<'a> FirmwareWriter<'a> {
/// # Safety /// # Safety
/// ///
/// Failing to meet alignment and size requirements may result in a panic. /// Failing to meet alignment and size requirements may result in a panic.
pub fn write_firmware_blocking<F: NorFlash>( pub fn write_block_blocking<F: NorFlash>(
&mut self, &mut self,
offset: usize, offset: usize,
data: &[u8], data: &[u8],
@ -847,11 +877,11 @@ impl<'a> FirmwareWriter<'a> {
) -> Result<(), F::Error> { ) -> Result<(), F::Error> {
trace!( trace!(
"Writing firmware at offset 0x{:x} len {}", "Writing firmware at offset 0x{:x} len {}",
self.0.dfu.from + offset, self.0.from + offset,
data.len() data.len()
); );
let mut write_offset = self.0.dfu.from + offset; let mut write_offset = self.0.from + offset;
for chunk in data.chunks(block_size) { for chunk in data.chunks(block_size) {
trace!("Wrote chunk at {}: {:?}", write_offset, chunk); trace!("Wrote chunk at {}: {:?}", write_offset, chunk);
flash.write(write_offset as u32, chunk)?; flash.write(write_offset as u32, chunk)?;