Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions services/pldm/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,25 @@ rust_test(
],
)

rust_test(
name = "inventory_host_test",
srcs = [
"tests/common.rs",
"tests/inventory_host.rs",
],
crate_root = "tests/inventory_host.rs",
edition = "2024",
deps = [
":pldm_service",
"//services/mctp/api:mctp_api",
"//services/mctp/server:mctp_server_lib",
"@rust_crates//:mctp",
"@rust_crates//:mctp-lib",
"@rust_crates//:pldm-common",
"@rust_crates//:pldm-interface",
],
)

rust_test(
name = "unexpected_eid_host_test",
srcs = [
Expand Down
50 changes: 40 additions & 10 deletions services/pldm/tests/firmware_update_host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ const IMAGE_SIZE: u32 = 1024;
struct MockFdOps {
component_accepted: Cell<bool>,
download_bytes_received: Cell<usize>,
downloaded_image: RefCell<[u8; IMAGE_SIZE as usize]>,
verified: Cell<bool>,
applied: Cell<bool>,
}
Expand Down Expand Up @@ -112,17 +113,29 @@ impl FdOps for MockFdOps {
&self,
_component: &FirmwareComponent,
) -> Result<(usize, usize), FdOpsError> {
Ok((0, IMAGE_SIZE as usize))
let offset = self.download_bytes_received.get();
let length = (IMAGE_SIZE as usize)
.checked_sub(offset)
.ok_or(FdOpsError::FwDownloadError)?;
Ok((offset, length))
}

fn download_fw_data(
&self,
_offset: usize,
offset: usize,
data: &[u8],
_component: &FirmwareComponent,
) -> Result<TransferResult, FdOpsError> {
let end = offset
.checked_add(data.len())
.ok_or(FdOpsError::FwDownloadError)?;
let mut downloaded_image = self.downloaded_image.borrow_mut();
let destination = downloaded_image
.get_mut(offset..end)
.ok_or(FdOpsError::FwDownloadError)?;
destination.copy_from_slice(data);
self.download_bytes_received
.set(self.download_bytes_received.get() + data.len());
.set(end.max(self.download_bytes_received.get()));
Ok(TransferResult::TransferSuccess)
}

Expand Down Expand Up @@ -200,6 +213,7 @@ fn fw_string(s: &str) -> PldmFirmwareString {
fn serve_ua_fw_request<S: Sender, const N: usize>(
ua_server: &RefCell<Server<S, N>>,
listener: Handle,
component_image: &[u8],
) {
let mut req = [0u8; 1024];
let meta = match ua_server.borrow_mut().try_recv(listener, &mut req) {
Expand All @@ -218,10 +232,14 @@ fn serve_ua_fw_request<S: Sender, const N: usize>(
Ok(FwUpdateCmd::RequestFirmwareData) => {
let fw_req =
RequestFirmwareDataRequest::decode(payload).expect("decode RequestFirmwareData");
let offset = fw_req.offset as usize;
let length = fw_req.length as usize;
assert!(length <= MAX_TRANSFER_SIZE, "requested chunk exceeds MTU");
let data = [0xA5u8; MAX_TRANSFER_SIZE];
let resp_msg = RequestFirmwareDataResponse::new(instance_id, success, &data[..length]);
let end = offset.checked_add(length).expect("firmware range overflow");
let data = component_image
.get(offset..end)
.expect("requested range should be within the component image");
Comment thread
CourtneyDrant marked this conversation as resolved.
let resp_msg = RequestFirmwareDataResponse::new(instance_id, success, data);
PldmCodecWithLifetime::encode(&resp_msg, &mut resp)
.expect("encode RequestFirmwareData response")
}
Expand Down Expand Up @@ -256,9 +274,12 @@ fn serve_ua_fw_request<S: Sender, const N: usize>(

#[test]
fn firmware_update_full_flow_via_requester() {
let component_image: [u8; IMAGE_SIZE as usize] =
core::array::from_fn(|offset| (offset as u8).wrapping_mul(31).wrapping_add(7));
let fd_ops = MockFdOps {
component_accepted: Cell::new(false),
download_bytes_received: Cell::new(0),
downloaded_image: RefCell::new([0u8; IMAGE_SIZE as usize]),
verified: Cell::new(false),
applied: Cell::new(false),
};
Expand Down Expand Up @@ -291,7 +312,7 @@ fn firmware_update_full_flow_via_requester() {
transfer(&fd_to_ua_packets, &mut ua_server.borrow_mut());
fd_to_ua_packets.borrow_mut().clear();
// UA answers the request.
serve_ua_fw_request(&ua_server, ua_fw_listener);
serve_ua_fw_request(&ua_server, ua_fw_listener, &component_image);
// Deliver the UA response back to the FD.
transfer(&ua_to_fd_packets, &mut fd_server.borrow_mut());
ua_to_fd_packets.borrow_mut().clear();
Expand Down Expand Up @@ -376,7 +397,8 @@ fn firmware_update_full_flow_via_requester() {
let len = req_update.encode(&mut buf).expect("encode RequestUpdate");
let resp = ua_transact(&buf[..len]);
assert_eq!(
resp[3], 0,
resp[3],
PldmBaseCompletionCode::Success as u8,
"RequestUpdate completion code should be success"
);
assert_eq!(
Expand Down Expand Up @@ -433,7 +455,8 @@ fn firmware_update_full_flow_via_requester() {
.expect("encode PassComponentTable");
let resp = ua_transact(&buf[..len]);
assert_eq!(
resp[3], 0,
resp[3],
PldmBaseCompletionCode::Success as u8,
"PassComponentTable completion code should be success"
);
assert!(
Expand All @@ -459,7 +482,8 @@ fn firmware_update_full_flow_via_requester() {
.expect("encode UpdateComponent");
let resp = ua_transact(&buf[..len]);
assert_eq!(
resp[3], 0,
resp[3],
PldmBaseCompletionCode::Success as u8,
"UpdateComponent completion code should be success"
);

Expand All @@ -478,7 +502,8 @@ fn firmware_update_full_flow_via_requester() {
let resp = ua_transact(&b[..n]);
let status = GetStatusResponse::decode(&resp).expect("decode GetStatusResponse");
assert_eq!(
status.completion_code, 0,
status.completion_code,
PldmBaseCompletionCode::Success as u8,
"GetStatus completion should be success"
);
assert_eq!(
Expand All @@ -493,6 +518,11 @@ fn firmware_update_full_flow_via_requester() {
IMAGE_SIZE as usize,
"the full firmware image should have been downloaded"
);
assert_eq!(
*fd_ops.downloaded_image.borrow(),
component_image,
"the downloaded component image should match the Update Agent image"
);
assert!(fd_ops.verified.get(), "firmware should have been verified");
assert!(fd_ops.applied.get(), "firmware should have been applied");
assert_eq!(
Expand Down
Loading