Skip to content

Commit 7bb3e3d

Browse files
committed
pldm-file: use cumulative crc for multipart transfers
Regarding the part checksum field, DSP0240 says: 32-bit cumulative CRC for the entirety of data received so far for this section (all parts concatenated together, excluding checksums). Shall be included with all part transfers. So, we need to keep the checksum Digest around, and use the cumulative value in responses & response checks. We also shift the comment on restarting from a FIRST_PART, as it was incorrectly placed in the non-restart case. Signed-off-by: Jeremy Kerr <[email protected]>
1 parent 11227c1 commit 7bb3e3d

File tree

2 files changed

+29
-14
lines changed

2 files changed

+29
-14
lines changed

pldm-file/src/client.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,8 @@ where
167167
req_offset,
168168
req_length,
169169
};
170+
let crc32 = crc::Crc::<u32>::new(&crc::CRC_32_ISO_HDLC);
171+
let mut digest = crc32.digest();
170172
loop {
171173
let mut tx_buf = [0; 18];
172174
let l = req.to_slice(&mut tx_buf).map_err(|_| PldmError::NoSpace)?;
@@ -196,12 +198,11 @@ where
196198

197199
let (resp_data, resp_cs) = rest.split_at(resp_data_len);
198200

199-
let crc32 = crc::Crc::<u32>::new(&crc::CRC_32_ISO_HDLC);
200-
let calc_cs = crc32.checksum(resp_data);
201+
digest.update(resp_data);
201202
// unwrap: we have asserted the lengths above
202203
let cs = u32::from_le_bytes(resp_cs.try_into().unwrap());
203204

204-
if calc_cs != cs {
205+
if digest.clone().finalize() != cs {
205206
return Err(proto_error!("data checksum mismatch"));
206207
}
207208

pldm-file/src/host.rs

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ pub trait Host {
2323
fn read(&self, buf: &mut [u8], offset: usize) -> std::io::Result<usize>;
2424
}
2525

26+
const CRC32: crc::Crc<u32, crc::Table<16>> =
27+
crc::Crc::<u32, crc::Table<16>>::new(&crc::CRC_32_ISO_HDLC);
28+
2629
// Created at the first stage (XFER_FIRST_PART) of a MultpartReceive,
2730
// where we have the offset and size.
2831
struct FileTransferContext {
@@ -31,6 +34,23 @@ struct FileTransferContext {
3134
len: usize,
3235
// Current transfer 0..len
3336
offset: usize,
37+
digest: crc::Digest<'static, u32, crc::Table<16>>,
38+
}
39+
40+
impl FileTransferContext {
41+
fn new(start: usize, len: usize) -> Self {
42+
Self {
43+
start,
44+
len,
45+
offset: 0,
46+
digest: CRC32.digest(),
47+
}
48+
}
49+
50+
fn reset(&mut self) {
51+
self.offset = 0;
52+
self.digest = CRC32.digest();
53+
}
3454
}
3555

3656
// Created on DfOpen
@@ -80,9 +100,6 @@ impl std::fmt::Display for PldmFileError {
80100
}
81101
}
82102

83-
const CRC32: crc::Crc<u32, crc::Table<16>> =
84-
crc::Crc::<u32, crc::Table<16>>::new(&crc::CRC_32_ISO_HDLC);
85-
86103
type Result<T> = std::result::Result<T, PldmFileError>;
87104

88105
impl<const N: usize> Responder<N> {
@@ -349,10 +366,10 @@ impl<const N: usize> Responder<N> {
349366
// Set new transfer context
350367
if cmd.xfer_op == pldm::control::xfer_op::FIRST_PART {
351368
if let Some(ctx) = file_ctx.xfer_ctx.as_mut() {
352-
ctx.offset = 0;
369+
// a repeated FIRST_PART is valid, and restarts the transfer
370+
ctx.reset();
353371
} else {
354372
let new_ctx = Self::init_read(&cmd)?;
355-
// a repeated FIRST_PART is valid, and restarts the transfer
356373
file_ctx.xfer_ctx.replace(new_ctx);
357374
};
358375
}
@@ -406,7 +423,8 @@ impl<const N: usize> Responder<N> {
406423
host.read(data, xfer_ctx.start + offset)
407424
.map_err(|_| CCode::ERROR)?;
408425

409-
let cs = CRC32.checksum(data);
426+
xfer_ctx.digest.update(data);
427+
let cs = xfer_ctx.digest.clone().finalize();
410428
resp_data.extend_from_slice(&cs.to_le_bytes());
411429

412430
xfer_ctx.offset = offset;
@@ -421,11 +439,7 @@ impl<const N: usize> Responder<N> {
421439
trace!("init_read {req:?}");
422440
let start = req.req_offset as usize;
423441
let len = req.req_length as usize;
424-
Ok(FileTransferContext {
425-
start,
426-
len,
427-
offset: 0,
428-
})
442+
Ok(FileTransferContext::new(start, len))
429443
}
430444
}
431445

0 commit comments

Comments
 (0)