Skip to content

Commit 9b23488

Browse files
authoredDec 22, 2024··
OTA (#531)
* More efficient firmware info loader * Implement at least ErrorType for the new loader
1 parent ea24ccf commit 9b23488

File tree

1 file changed

+111
-33
lines changed

1 file changed

+111
-33
lines changed
 

‎src/ota.rs

+111-33
Original file line numberDiff line numberDiff line change
@@ -54,42 +54,14 @@ pub use embedded_svc::ota::{FirmwareInfo, LoadResult, Slot, SlotState, UpdatePro
5454
use crate::sys::*;
5555

5656
use crate::io::EspIOError;
57-
use crate::private::{common::*, cstr::*, mutex};
57+
use crate::private::{cstr::*, mutex};
5858

5959
static TAKEN: mutex::Mutex<bool> = mutex::Mutex::new(false);
6060

61-
impl From<Newtype<&esp_app_desc_t>> for FirmwareInfo {
62-
fn from(app_desc: Newtype<&esp_app_desc_t>) -> Self {
63-
let app_desc = app_desc.0;
64-
65-
let mut result = Self {
66-
version: unsafe { from_cstr_ptr(&app_desc.version as *const _) }
67-
.try_into()
68-
.unwrap(),
69-
signature: Some(heapless::Vec::from_slice(&app_desc.app_elf_sha256).unwrap()),
70-
released: "".try_into().unwrap(),
71-
description: Some(
72-
unsafe { from_cstr_ptr(&app_desc.project_name as *const _) }
73-
.try_into()
74-
.unwrap(),
75-
),
76-
download_id: None,
77-
};
78-
79-
write!(
80-
&mut result.released,
81-
"{} {}",
82-
unsafe { from_cstr_ptr(&app_desc.date as *const _) },
83-
unsafe { from_cstr_ptr(&app_desc.time as *const _) }
84-
)
85-
.unwrap();
86-
87-
result
88-
}
89-
}
90-
61+
#[deprecated(note = "Use `EspFirmwareInfoLoad` instead")]
9162
pub struct EspFirmwareInfoLoader(heapless::Vec<u8, 512>);
9263

64+
#[allow(deprecated)]
9365
impl EspFirmwareInfoLoader {
9466
pub const fn new() -> Self {
9567
Self(heapless::Vec::new())
@@ -132,23 +104,37 @@ impl EspFirmwareInfoLoader {
132104
.as_ref()
133105
.unwrap()
134106
};
135-
Ok(Newtype(app_desc).into())
107+
108+
let mut info = FirmwareInfo {
109+
version: heapless::String::new(),
110+
released: heapless::String::new(),
111+
description: None,
112+
signature: None,
113+
download_id: None,
114+
};
115+
116+
EspFirmwareInfoLoad::load_firmware_info(&mut info, app_desc)?;
117+
118+
Ok(info)
136119
} else {
137120
Err(EspError::from_infallible::<ESP_ERR_INVALID_SIZE>())
138121
}
139122
}
140123
}
141124

125+
#[allow(deprecated)]
142126
impl Default for EspFirmwareInfoLoader {
143127
fn default() -> Self {
144128
Self::new()
145129
}
146130
}
147131

132+
#[allow(deprecated)]
148133
impl io::ErrorType for EspFirmwareInfoLoader {
149134
type Error = EspIOError;
150135
}
151136

137+
#[allow(deprecated)]
152138
impl FirmwareInfoLoader for EspFirmwareInfoLoader {
153139
fn load(&mut self, buf: &[u8]) -> Result<LoadResult, Self::Error> {
154140
Ok(EspFirmwareInfoLoader::load(self, buf)?)
@@ -163,6 +149,88 @@ impl FirmwareInfoLoader for EspFirmwareInfoLoader {
163149
}
164150
}
165151

152+
/// A firmware info loader that tries to read the firmware info directly
153+
/// from a user-supplied buffer which can be re-used for other purposes afterwards.
154+
///
155+
/// This is a more efficient version of the now-deprecated `EspFirmwareInfoLoader`.
156+
pub struct EspFirmwareInfoLoad;
157+
158+
impl EspFirmwareInfoLoad {
159+
/// Fetches firmware information from the firmware binary data chunk loaded so far.
160+
///
161+
/// Returns `true` if the information was successfully fetched.
162+
/// Returns `false` if the firmware data has not been loaded completely yet.
163+
pub fn fetch(&self, data: &[u8], info: &mut FirmwareInfo) -> Result<bool, EspIOError> {
164+
let loaded = data.len()
165+
>= mem::size_of::<esp_image_header_t>()
166+
+ mem::size_of::<esp_image_segment_header_t>()
167+
+ mem::size_of::<esp_app_desc_t>();
168+
169+
if loaded {
170+
let app_desc_slice = &data[mem::size_of::<esp_image_header_t>()
171+
+ mem::size_of::<esp_image_segment_header_t>()
172+
..mem::size_of::<esp_image_header_t>()
173+
+ mem::size_of::<esp_image_segment_header_t>()
174+
+ mem::size_of::<esp_app_desc_t>()];
175+
176+
let app_desc = unsafe {
177+
(app_desc_slice.as_ptr() as *const esp_app_desc_t)
178+
.as_ref()
179+
.unwrap()
180+
};
181+
182+
Self::load_firmware_info(info, app_desc)?;
183+
184+
Ok(true)
185+
} else {
186+
Ok(false)
187+
}
188+
}
189+
190+
pub fn load_firmware_info(
191+
info: &mut FirmwareInfo,
192+
app_desc: &esp_app_desc_t,
193+
) -> Result<(), EspError> {
194+
info.version.clear();
195+
info.version
196+
.push_str(unsafe { from_cstr_ptr(&app_desc.version as *const _) })
197+
.map_err(|_| EspError::from_infallible::<ESP_ERR_INVALID_SIZE>())?;
198+
199+
info.released.clear();
200+
write!(
201+
&mut info.released,
202+
"{} {}",
203+
unsafe { from_cstr_ptr(&app_desc.date as *const _) },
204+
unsafe { from_cstr_ptr(&app_desc.time as *const _) }
205+
)
206+
.map_err(|_| EspError::from_infallible::<ESP_ERR_INVALID_SIZE>())?;
207+
208+
if let Some(description) = info.description.as_mut() {
209+
description.clear();
210+
description
211+
.push_str(unsafe { from_cstr_ptr(&app_desc.project_name as *const _) })
212+
.map_err(|_| EspError::from_infallible::<ESP_ERR_INVALID_SIZE>())?;
213+
}
214+
215+
if let Some(signature) = info.signature.as_mut() {
216+
signature.clear();
217+
signature
218+
.extend_from_slice(&app_desc.app_elf_sha256)
219+
.map_err(|_| EspError::from_infallible::<ESP_ERR_INVALID_SIZE>())?;
220+
}
221+
222+
if let Some(download_id) = info.download_id.as_mut() {
223+
download_id.clear();
224+
}
225+
226+
Ok(())
227+
}
228+
}
229+
230+
impl io::ErrorType for EspFirmwareInfoLoad {
231+
type Error = EspIOError;
232+
}
233+
166234
#[derive(Debug)]
167235
pub struct EspOtaUpdate<'a> {
168236
update_partition: *const esp_partition_t,
@@ -487,7 +555,17 @@ impl EspOta {
487555
} else {
488556
esp!(err)?;
489557

490-
Some(Newtype(&app_desc).into())
558+
let mut info = FirmwareInfo {
559+
version: heapless::String::new(),
560+
released: heapless::String::new(),
561+
description: Some(heapless::String::new()),
562+
signature: Some(heapless::Vec::new()),
563+
download_id: None,
564+
};
565+
566+
EspFirmwareInfoLoad::load_firmware_info(&mut info, &app_desc)?;
567+
568+
Some(info)
491569
})
492570
}
493571
}

0 commit comments

Comments
 (0)
Please sign in to comment.