commit fb59198f70ba9b110ba916b013977d04afba094c
parent 0d86c641344f5ddbdbdff08bfb3f9f7432c82ad1
Author: Daniel Barlow <dan@telent.net>
Date: Sun, 25 Jan 2026 00:33:14 +0000
remove read_all, shorten using Result
this has made the "can't happen" error messages a bit less helpful
but we will come back to that
Diffstat:
2 files changed, 49 insertions(+), 39 deletions(-)
diff --git a/ecu-esp32/src/ota.rs b/ecu-esp32/src/ota.rs
@@ -6,8 +6,10 @@ use ed25519_dalek::{VerifyingKey, Verifier, Signature};
use esp_hal_ota::Ota;
use esp_storage::FlashStorage;
+use embedded_io_async::{Read,ReadExactError};
use esp_hal::sha;
+use core::convert::Infallible;
use log::{warn, info, error};
@@ -15,33 +17,38 @@ const ERASE_BLOCK_BYTES : usize = 4096;
const ED25519_SIGNATURE_BYTES : usize = 64;
const SHA256_BYTES : usize = 32;
-async fn read_all(socket: &mut embassy_net::tcp::TcpSocket<'_>,
- buf: &mut [u8],
- len: usize) -> usize {
- let mut n = 0;
- while n < len {
- match socket.read(&mut buf[n..len]).await {
- Ok(0) => {
- warn!("read EOF");
- break;
- },
- Ok(count) => {
- n = n + count;
- }
- Err(e) => {
- warn!("read err {:?}", e);
- return 0; // ew
- }
- }
- }
- n
-}
-
pub struct Flasher<'a> {
ota : Ota<FlashStorage<'a>>,
sha_engine : sha::Sha<'a>
}
+#[derive(Debug)]
+pub enum FlashError {
+ UnexpectedEof,
+ OtaFailed,
+ InvalidSignature,
+ Infallible
+}
+
+impl<E> From<ReadExactError<E>> for FlashError {
+ fn from(_e : ReadExactError<E>) -> Self {
+ Self::UnexpectedEof
+ }
+}
+
+impl From<esp_hal_ota::OtaError> for FlashError {
+ fn from(_e : esp_hal_ota::OtaError) -> Self {
+ Self::OtaFailed
+ }
+}
+
+impl From<Infallible> for FlashError {
+ fn from(_e : Infallible) -> Self {
+ Self::Infallible
+ }
+}
+
+
impl Flasher<'_> {
pub fn new(flash_peripheral: esp_hal::peripherals::FLASH<'static>,
sha_peripheral: esp_hal::peripherals::SHA<'static>) -> Self {
@@ -52,7 +59,7 @@ impl Flasher<'_> {
Self { ota, sha_engine }
}
- pub async fn write(&mut self, sock: &mut embassy_net::tcp::TcpSocket<'_>) {
+ pub async fn write(&mut self, sock: &mut embassy_net::tcp::TcpSocket<'_>) -> Result<(), FlashError> {
write_ota(&mut self.ota, &mut self.sha_engine, sock).await
}
}
@@ -60,7 +67,7 @@ impl Flasher<'_> {
async fn write_ota(ota : &mut Ota<FlashStorage<'_>>,
sha_engine : &mut sha::Sha<'_>,
- sock: &mut embassy_net::tcp::TcpSocket<'_>) {
+ sock: &mut embassy_net::tcp::TcpSocket<'_>) -> Result<(), FlashError> {
let mut buf = [0u8; SHA256_BYTES + ERASE_BLOCK_BYTES];
let mut buf_offset = 0;
let mut signed;
@@ -73,8 +80,8 @@ async fn write_ota(ota : &mut Ota<FlashStorage<'_>>,
let mut block0 = [0u8; SHA256_BYTES + 4];
- read_all(sock, &mut signature, ED25519_SIGNATURE_BYTES).await;
- read_all(sock, &mut block0, SHA256_BYTES + 4).await;
+ sock.read_exact(&mut signature).await?;
+ sock.read_exact(&mut block0[..SHA256_BYTES + 4]).await?;
let verifying_key_bytes = include_bytes!("../../pubkey.bin");
let verifying_key: VerifyingKey = VerifyingKey::from_bytes(verifying_key_bytes).expect("verify");
@@ -88,10 +95,8 @@ async fn write_ota(ota : &mut Ota<FlashStorage<'_>>,
next_block_hash.clone_from_slice(sha);
info!("ota length {}", len);
- if let Err(e) = ota.ota_begin(len, 0) {
- error!("ota_begin failed {:?}", e);
- return;
- };
+
+ ota.ota_begin(len, 0)?;
// total payload to expect is image size plus per-block hashes
let mut remaining = len + (len/(ERASE_BLOCK_BYTES as u32)+ 1) * (SHA256_BYTES as u32);
@@ -123,7 +128,7 @@ async fn write_ota(ota : &mut Ota<FlashStorage<'_>>,
_ => ()
}
}
- block!(hasher.finish(&mut actual_hash)).expect("hasher.finish expected infallible");
+ block!(hasher.finish(&mut actual_hash))?;
signed = signed && next_block_hash == actual_hash;
@@ -135,7 +140,7 @@ async fn write_ota(ota : &mut Ota<FlashStorage<'_>>,
// accept the rest of the update, just don't flash it.
warn!("signature invalid with {remaining} left");
}
- //
+
buf_offset = 0;
next_block_hash.copy_from_slice(&buf[0..SHA256_BYTES]);
}
@@ -145,12 +150,15 @@ async fn write_ota(ota : &mut Ota<FlashStorage<'_>>,
info!("write {:?}", sock.write(b"BYE\n").await);
let _ = sock.flush().await;
sock.close();
- if signed && !ota.ota_flush(false, false).is_ok() {
- error!("ota failed");
- }
- Timer::after_millis(1000).await;
- esp_hal::system::software_reset();
+ if signed {
+ ota.ota_flush(false, false)?;
+ Timer::after_millis(1000).await;
+ esp_hal::system::software_reset();
+ } else {
+ return Err(FlashError::InvalidSignature)
+ }
} else {
warn!("stream ended early or flash failed with {} bytes left", remaining);
+ Err(FlashError::UnexpectedEof)
}
}
diff --git a/ecu-esp32/src/wifi.rs b/ecu-esp32/src/wifi.rs
@@ -38,7 +38,7 @@ use esp_radio::{
use embassy_net::Stack;
use embedded_io_async::Read;
-use log::{warn, info};
+use log::{warn, info, error};
use crate::mdns;
@@ -241,7 +241,9 @@ async fn run_tcp_handler(stack : Stack<'_>,
match &buf[0..4] {
b"ROM0" => {
info!("OTA request");
- flasher.write(&mut socket).await;
+ if let Err(e) = flasher.write(&mut socket).await {
+ error!("ota flash failed: {:?}", e);
+ }
},
b"KEY0" => {
info!("sessionkey");