diff --git a/src/Cargo.lock b/src/Cargo.lock index 739f2e62..1cd121cd 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -559,7 +559,9 @@ name = "satman" version = "0.0.0" dependencies = [ "build_zynq", + "byteorder", "core_io", + "crc", "cslice", "embedded-hal", "io", diff --git a/src/satman/Cargo.toml.tpl b/src/satman/Cargo.toml.tpl index d4fa63c5..38f64e68 100644 --- a/src/satman/Cargo.toml.tpl +++ b/src/satman/Cargo.toml.tpl @@ -15,7 +15,9 @@ build_zynq = { path = "../libbuild_zynq" } [dependencies] log = { version = "0.4", default-features = false } +byteorder = { version = "1.3", default-features = false } core_io = { version = "0.1", features = ["collections"] } +crc = { version = "1.7", default-features = false } cslice = "0.3" embedded-hal = "0.2" diff --git a/src/satman/src/main.rs b/src/satman/src/main.rs index cf62b536..a6baf5c3 100644 --- a/src/satman/src/main.rs +++ b/src/satman/src/main.rs @@ -4,7 +4,9 @@ #[macro_use] extern crate log; +extern crate byteorder; extern crate core_io; +extern crate crc; extern crate cslice; extern crate embedded_hal; @@ -1144,7 +1146,7 @@ fn process_aux_packet( }, ) } else { - drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: false }) + drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: false }) } } } @@ -1280,6 +1282,53 @@ fn process_aux_packet( error!("debug allocator not supported on zynq device"); drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: false }) } + drtioaux::Packet::CoreMgmtFlashRequest { + destination: _destination, + last, + length, + data, + } => { + forward!( + router, + _routing_table, + _destination, + *rank, + *self_destination, + _repeaters, + &packet, + timer + ); + + core_manager.add_image_data(&data, length as usize); + + if last { + drtioaux::send(0, &drtioaux::Packet::CoreMgmtDropLink) + } else { + drtioaux::send(0, &drtioaux::Packet::CoreMgmtReply { succeeded: true }) + } + } + drtioaux::Packet::CoreMgmtDropLinkAck { + destination: _destination, + } => { + forward!( + router, + _routing_table, + _destination, + *rank, + *self_destination, + _repeaters, + &packet, + timer + ); + + unsafe { + csr::gt_drtio::txenable_write(0); + } + core_manager.write_image(); + info!("reboot imminent"); + slcr::reboot(); + Ok(()) + } p => { warn!("received unexpected aux packet: {:?}", p); diff --git a/src/satman/src/mgmt.rs b/src/satman/src/mgmt.rs index d6674832..8b7e5694 100644 --- a/src/satman/src/mgmt.rs +++ b/src/satman/src/mgmt.rs @@ -1,5 +1,7 @@ use alloc::vec::Vec; +use byteorder::{ByteOrder, NativeEndian}; +use crc::crc32; use io::{Cursor, ProtoRead, ProtoWrite}; use libboard_artiq::{drtioaux_proto::SAT_PAYLOAD_MAX_SIZE, logger::{BufferLogger, LogBufferRef}}; @@ -48,6 +50,7 @@ pub struct Manager<'a> { last_log: Sliceable, config_payload: Cursor>, last_value: Sliceable, + image_payload: Vec, } impl<'a> Manager<'_> { @@ -57,6 +60,7 @@ impl<'a> Manager<'_> { last_log: Sliceable::new(0, Vec::new()), config_payload: Cursor::new(Vec::new()), last_value: Sliceable::new(0, Vec::new()), + image_payload: Vec::new(), } } @@ -113,4 +117,31 @@ impl<'a> Manager<'_> { .map(|()| debug!("erase success")) .map_err(|err| warn!("failed to erase: {:?}", err)) } + + pub fn add_image_data(&mut self, data: &[u8], data_len: usize) { + self.image_payload.extend(&data[..data_len]); + } + + pub fn write_image(&self) { + let mut image = self.image_payload.clone(); + let image_ref = &image[..]; + let bin_len = image.len() - 4; + + let (image_ref, expected_crc) = { + let (image_ref, crc_slice) = image_ref.split_at(bin_len); + (image_ref, NativeEndian::read_u32(crc_slice)) + }; + + let actual_crc = crc32::checksum_ieee(image_ref); + + if actual_crc == expected_crc { + image.truncate(bin_len); + self.cfg.write("boot", image).expect("failed to write boot image"); + } else { + panic!( + "CRC failed in SDRAM (actual {:08x}, expected {:08x})", + actual_crc, expected_crc + ); + } + } }