-
Notifications
You must be signed in to change notification settings - Fork 11
Fix logic error that loses the remainder chunk #27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -6,7 +6,7 @@ use crate::protocol_definitions::{ | |||||||||||||||||||||||||
| FW_UPDATE_FLAG_LAST_BLOCK, | ||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||
| use crate::writer::{CfuWriterAsync, CfuWriterError}; | ||||||||||||||||||||||||||
| use crate::{trace, CfuImage, DataChunk}; | ||||||||||||||||||||||||||
| use crate::{error, trace, CfuImage, DataChunk}; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| /// CfuHostStates trait defines behavior needed for a Cfu Host to process available Cfu Offers | ||||||||||||||||||||||||||
| /// and send the appropriate commands to the Cfu Client to update the components | ||||||||||||||||||||||||||
|
|
@@ -77,6 +77,15 @@ impl<W: CfuWriterAsync> CfuUpdateContent<W> for CfuUpdater { | |||||||||||||||||||||||||
| cmpt_id: ComponentId, | ||||||||||||||||||||||||||
| base_offset: usize, | ||||||||||||||||||||||||||
| ) -> Result<FwUpdateContentResponse, CfuProtocolError> { | ||||||||||||||||||||||||||
| let total_bytes: usize = image.get_total_size(); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| if total_bytes <= DEFAULT_DATA_LENGTH { | ||||||||||||||||||||||||||
| error!( | ||||||||||||||||||||||||||
| "image size less than or equal to chunk size, we need at least for 2 chunks for first and last block" | ||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||
| return Err(CfuProtocolError::WriterError(CfuWriterError::Other)); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| // Build update offer command | ||||||||||||||||||||||||||
| let updateoffercmd_bytes = [0u8; 16]; | ||||||||||||||||||||||||||
| let mut offer_resp = [0u8; 16]; | ||||||||||||||||||||||||||
|
|
@@ -93,53 +102,74 @@ impl<W: CfuWriterAsync> CfuUpdateContent<W> for CfuUpdater { | |||||||||||||||||||||||||
| return Err(CfuProtocolError::CfuContentUpdateResponseError(status)); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| let total_bytes: usize = image.get_total_size(); | ||||||||||||||||||||||||||
| let chunk_size = DEFAULT_DATA_LENGTH; | ||||||||||||||||||||||||||
| let num_chunks = total_bytes / chunk_size; | ||||||||||||||||||||||||||
| let remainder = total_bytes % chunk_size; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| // Read and process data in chunks so as to not over-burden memory resources | ||||||||||||||||||||||||||
| let mut resp: FwUpdateContentResponse = | ||||||||||||||||||||||||||
| FwUpdateContentResponse::new(0, CfuUpdateContentResponseStatus::ErrorInvalid); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| for i in 0..num_chunks { | ||||||||||||||||||||||||||
| let mut chunk = [0u8; DEFAULT_DATA_LENGTH]; | ||||||||||||||||||||||||||
| let address_offset = i * DEFAULT_DATA_LENGTH + base_offset; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| image | ||||||||||||||||||||||||||
| .get_bytes_for_chunk(&mut chunk, address_offset) | ||||||||||||||||||||||||||
| .await | ||||||||||||||||||||||||||
| .map_err(|_| CfuProtocolError::WriterError(CfuWriterError::StorageError))?; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| let r = match i { | ||||||||||||||||||||||||||
| 0 => { | ||||||||||||||||||||||||||
| image | ||||||||||||||||||||||||||
| .get_bytes_for_chunk(&mut chunk, address_offset) | ||||||||||||||||||||||||||
| .await | ||||||||||||||||||||||||||
| .map_err(|_| CfuProtocolError::WriterError(CfuWriterError::StorageError))?; | ||||||||||||||||||||||||||
| self.process_first_data_block(writer, chunk).await | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| num if (num < num_chunks) => { | ||||||||||||||||||||||||||
| image | ||||||||||||||||||||||||||
| .get_bytes_for_chunk(&mut chunk, address_offset) | ||||||||||||||||||||||||||
| .await | ||||||||||||||||||||||||||
| .map_err(|_| CfuProtocolError::WriterError(CfuWriterError::StorageError))?; | ||||||||||||||||||||||||||
| num if (num < num_chunks - 1) => { | ||||||||||||||||||||||||||
| self.process_middle_data_block(writer, chunk, i).await | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| _ => { | ||||||||||||||||||||||||||
| image | ||||||||||||||||||||||||||
| .get_bytes_for_chunk( | ||||||||||||||||||||||||||
| chunk | ||||||||||||||||||||||||||
| .get_mut(0..remainder) | ||||||||||||||||||||||||||
| .ok_or(CfuProtocolError::WriterError(CfuWriterError::Other))?, | ||||||||||||||||||||||||||
| address_offset, | ||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||
| .await | ||||||||||||||||||||||||||
| .map_err(|_| CfuProtocolError::WriterError(CfuWriterError::StorageError))?; | ||||||||||||||||||||||||||
| self.process_last_data_block(writer, chunk, i).await | ||||||||||||||||||||||||||
| _ /* num_chunks - 1 */ => { | ||||||||||||||||||||||||||
| if remainder == 0 { | ||||||||||||||||||||||||||
| self.process_last_data_block(writer, chunk, i).await | ||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||
| self.process_middle_data_block(writer, chunk, i).await | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| .map_err(CfuProtocolError::WriterError)?; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| // if no errors in processing the data block, check the response | ||||||||||||||||||||||||||
| if r.status != CfuUpdateContentResponseStatus::Success { | ||||||||||||||||||||||||||
| return Err(CfuProtocolError::UpdateError(cmpt_id)); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| resp = r; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| if remainder != 0 { | ||||||||||||||||||||||||||
| let mut last_chunk = [0u8; DEFAULT_DATA_LENGTH]; | ||||||||||||||||||||||||||
| let address_offset = num_chunks * DEFAULT_DATA_LENGTH + base_offset; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| image | ||||||||||||||||||||||||||
| .get_bytes_for_chunk( | ||||||||||||||||||||||||||
| last_chunk | ||||||||||||||||||||||||||
| .get_mut(0..remainder) | ||||||||||||||||||||||||||
| .ok_or(CfuProtocolError::WriterError(CfuWriterError::Other))?, | ||||||||||||||||||||||||||
| address_offset, | ||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||
| .await | ||||||||||||||||||||||||||
| .map_err(|_| CfuProtocolError::WriterError(CfuWriterError::StorageError))?; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| let r = self | ||||||||||||||||||||||||||
| .process_last_data_block(writer, last_chunk, num_chunks) | ||||||||||||||||||||||||||
| .await | ||||||||||||||||||||||||||
| .map_err(CfuProtocolError::WriterError)?; | ||||||||||||||||||||||||||
|
Comment on lines
+160
to
+163
|
||||||||||||||||||||||||||
| let r = self | |
| .process_last_data_block(writer, last_chunk, num_chunks) | |
| .await | |
| .map_err(CfuProtocolError::WriterError)?; | |
| let r = if num_chunks == 0 { | |
| // Single-chunk transfer: treat this remainder as the first (and only) block | |
| self.process_first_data_block(writer, last_chunk).await | |
| } else { | |
| // There were full-sized chunks before; this is the final (last) block | |
| self.process_last_data_block(writer, last_chunk, num_chunks).await | |
| } | |
| .map_err(CfuProtocolError::WriterError)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@madeleyneVaca @Ctru14 @ankurung Not sure what the correct expectation is here if an image is <= chunk length, marked it as both first and last? I will add check to enforce that there are at least 2 chunks worth of data right now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When processing the last chunk with a remainder (lines 138-162), the data_length field in the FwUpdateContentHeader will be incorrectly set to DEFAULT_DATA_LENGTH instead of the actual remainder size. The process_last_data_block function at line 234 always sets data_length to DEFAULT_DATA_LENGTH, but when called with a partial chunk, it should reflect the actual number of valid bytes (remainder). This could cause the device to process more bytes than actually provided or fail validation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@madeleyneVaca @Ctru14 @ankurung It seems like in
process_last_data_block(), it is always assuming data length to beDEFAULT_DATA_LENGTH:So even if there is fewer bytes, write a whole chunk?