runtime coremgmt: implement firmware rewrite

This commit is contained in:
occheung 2024-09-04 17:47:10 +08:00
parent 3cf2d6be9d
commit dd7c8c8c3d
1 changed files with 88 additions and 1 deletions

View File

@ -70,6 +70,8 @@ pub enum Request {
ConfigErase = 15, ConfigErase = 15,
DebugAllocator = 8, DebugAllocator = 8,
Flash = 9,
} }
#[repr(i8)] #[repr(i8)]
@ -132,8 +134,10 @@ async fn read_key(stream: &mut TcpStream) -> Result<String> {
#[cfg(has_drtio)] #[cfg(has_drtio)]
mod remote_coremgmt { mod remote_coremgmt {
use core_io::Read;
use io::{Cursor, ProtoWrite}; use io::{Cursor, ProtoWrite};
use libboard_artiq::drtioaux_proto::{Packet, MASTER_PAYLOAD_MAX_SIZE}; use libboard_artiq::{drtioaux_async,
drtioaux_proto::{Packet, MASTER_PAYLOAD_MAX_SIZE}};
use super::*; use super::*;
use crate::rtio_mgt::drtio; use crate::rtio_mgt::drtio;
@ -616,6 +620,64 @@ mod remote_coremgmt {
} }
} }
} }
pub async fn image_write(
stream: &mut TcpStream,
aux_mutex: &Rc<Mutex<bool>>,
routing_table: &drtio_routing::RoutingTable,
timer: GlobalTimer,
linkno: u8,
destination: u8,
_cfg: &Rc<Config>,
image: Vec<u8>,
) -> Result<()> {
let mut image = &image[..];
while !image.is_empty() {
let mut data = [0; MASTER_PAYLOAD_MAX_SIZE];
let len = image.read(&mut data).unwrap();
let last = image.is_empty();
let reply = drtio::aux_transact(
aux_mutex,
linkno,
routing_table,
&Packet::CoreMgmtFlashRequest {
destination: destination,
last: last,
length: len as u16,
data: data,
},
timer,
)
.await;
match reply {
Ok(Packet::CoreMgmtReply { succeeded: true }) if !last => Ok(()),
Ok(Packet::CoreMgmtDropLink) if last => drtioaux_async::send(
linkno,
&Packet::CoreMgmtDropLinkAck {
destination: destination,
},
)
.await
.map_err(|_| drtio::Error::AuxError),
Ok(packet) => {
error!("received unexpected aux packet: {:?}", packet);
write_i8(stream, Reply::Error as i8).await?;
Err(drtio::Error::UnexpectedReply)
}
Err(e) => {
error!("aux packet error ({})", e);
write_i8(stream, Reply::Error as i8).await?;
Err(drtio::Error::AuxError)
}
}?;
}
write_i8(stream, Reply::RebootImminent as i8).await?;
Ok(())
}
} }
mod local_coremgmt { mod local_coremgmt {
@ -744,6 +806,18 @@ mod local_coremgmt {
error!("zynq device does not support allocator debug print"); error!("zynq device does not support allocator debug print");
Ok(()) Ok(())
} }
pub async fn image_write(stream: &mut TcpStream, cfg: &Rc<Config>, image: Vec<u8>) -> Result<()> {
let value = cfg.write("boot", image);
if value.is_ok() {
reboot(stream).await?;
} else {
// this is an error because we do not expect write to fail
error!("failed to write boot file: {:?}", value);
write_i8(stream, Reply::Error as i8).await?;
}
Ok(())
}
} }
#[cfg(has_drtio)] #[cfg(has_drtio)]
@ -829,6 +903,19 @@ async fn handle_connection(
Request::DebugAllocator => { Request::DebugAllocator => {
process!(stream, _drtio_tuple, _destination, debug_allocator) process!(stream, _drtio_tuple, _destination, debug_allocator)
} }
Request::Flash => {
let len = read_i32(stream).await?;
if len <= 0 {
write_i8(stream, Reply::Error as i8).await?;
return Err(Error::UnexpectedPattern);
}
let mut buffer = Vec::with_capacity(len as usize);
unsafe {
buffer.set_len(len as usize);
}
read_chunk(stream, &mut buffer).await?;
process!(stream, _drtio_tuple, _destination, image_write, &cfg, buffer)
}
}?; }?;
} }
} }