forked from M-Labs/nac3
add support for tar flashable (sub)kernels
This commit is contained in:
parent
e1b2c45813
commit
aebc739c1e
|
@ -122,6 +122,9 @@
|
||||||
src = ./src;
|
src = ./src;
|
||||||
cargoLock = {
|
cargoLock = {
|
||||||
lockFile = src/Cargo.lock;
|
lockFile = src/Cargo.lock;
|
||||||
|
outputHashes = {
|
||||||
|
"tar-no-std-0.1.8" = "sha256-xm17108v4smXOqxdLvHl9CxTCJslmeogjm4Y87IXFuM=";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
|
|
|
@ -2,6 +2,12 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "arrayvec"
|
||||||
|
version = "0.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-recursion"
|
name = "async-recursion"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
|
@ -474,6 +480,7 @@ dependencies = [
|
||||||
"log_buffer",
|
"log_buffer",
|
||||||
"num-derive",
|
"num-derive",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
|
"tar-no-std",
|
||||||
"unwind",
|
"unwind",
|
||||||
"vcell",
|
"vcell",
|
||||||
"void",
|
"void",
|
||||||
|
@ -538,6 +545,16 @@ dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tar-no-std"
|
||||||
|
version = "0.1.8"
|
||||||
|
source = "git+https://git.m-labs.hk/M-Labs/tar-no-std?rev=2ab6dc5#2ab6dc58e5249c59c4eb03eaf3a119bcdd678d32"
|
||||||
|
dependencies = [
|
||||||
|
"arrayvec",
|
||||||
|
"bitflags",
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.5"
|
version = "1.0.5"
|
||||||
|
|
|
@ -41,3 +41,7 @@ libc = { path = "../libc" }
|
||||||
io = { path = "../libio", features = ["alloc"] }
|
io = { path = "../libio", features = ["alloc"] }
|
||||||
ksupport = { path = "../libksupport" }
|
ksupport = { path = "../libksupport" }
|
||||||
libboard_artiq = { path = "../libboard_artiq" }
|
libboard_artiq = { path = "../libboard_artiq" }
|
||||||
|
|
||||||
|
[dependencies.tar-no-std]
|
||||||
|
git = "https://git.m-labs.hk/M-Labs/tar-no-std"
|
||||||
|
rev = "2ab6dc5"
|
|
@ -3,17 +3,23 @@ use core::{cell::RefCell, fmt, slice, str};
|
||||||
|
|
||||||
use core_io::Error as IoError;
|
use core_io::Error as IoError;
|
||||||
use cslice::CSlice;
|
use cslice::CSlice;
|
||||||
|
#[cfg(has_drtio)]
|
||||||
|
use dyld::elf;
|
||||||
use futures::{future::FutureExt, select_biased};
|
use futures::{future::FutureExt, select_biased};
|
||||||
#[cfg(has_drtio)]
|
#[cfg(has_drtio)]
|
||||||
use io::Cursor;
|
use io::Cursor;
|
||||||
#[cfg(has_drtio)]
|
#[cfg(has_drtio)]
|
||||||
use ksupport::rpc;
|
use ksupport::rpc;
|
||||||
use ksupport::{kernel, resolve_channel_name};
|
use ksupport::{kernel, resolve_channel_name};
|
||||||
|
#[cfg(has_drtio)]
|
||||||
|
use libasync::delay;
|
||||||
use libasync::{smoltcp::{Sockets, TcpStream},
|
use libasync::{smoltcp::{Sockets, TcpStream},
|
||||||
task};
|
task};
|
||||||
use libboard_artiq::drtio_routing;
|
use libboard_artiq::drtio_routing;
|
||||||
#[cfg(feature = "target_kasli_soc")]
|
#[cfg(feature = "target_kasli_soc")]
|
||||||
use libboard_zynq::error_led::ErrorLED;
|
use libboard_zynq::error_led::ErrorLED;
|
||||||
|
#[cfg(has_drtio)]
|
||||||
|
use libboard_zynq::time::Milliseconds;
|
||||||
use libboard_zynq::{self as zynq,
|
use libboard_zynq::{self as zynq,
|
||||||
smoltcp::{self,
|
smoltcp::{self,
|
||||||
iface::{EthernetInterfaceBuilder, NeighborCache},
|
iface::{EthernetInterfaceBuilder, NeighborCache},
|
||||||
|
@ -27,6 +33,8 @@ use libcortex_a9::{mutex::Mutex,
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use num_derive::{FromPrimitive, ToPrimitive};
|
use num_derive::{FromPrimitive, ToPrimitive};
|
||||||
use num_traits::{FromPrimitive, ToPrimitive};
|
use num_traits::{FromPrimitive, ToPrimitive};
|
||||||
|
#[cfg(has_drtio)]
|
||||||
|
use tar_no_std::TarArchiveRef;
|
||||||
|
|
||||||
#[cfg(has_drtio)]
|
#[cfg(has_drtio)]
|
||||||
use crate::pl;
|
use crate::pl;
|
||||||
|
@ -43,6 +51,8 @@ pub enum Error {
|
||||||
BufferExhausted,
|
BufferExhausted,
|
||||||
#[cfg(has_drtio)]
|
#[cfg(has_drtio)]
|
||||||
SubkernelError(subkernel::Error),
|
SubkernelError(subkernel::Error),
|
||||||
|
#[cfg(has_drtio)]
|
||||||
|
DestinationDown,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Result<T> = core::result::Result<T, Error>;
|
pub type Result<T> = core::result::Result<T, Error>;
|
||||||
|
@ -57,6 +67,8 @@ impl fmt::Display for Error {
|
||||||
Error::BufferExhausted => write!(f, "buffer exhausted"),
|
Error::BufferExhausted => write!(f, "buffer exhausted"),
|
||||||
#[cfg(has_drtio)]
|
#[cfg(has_drtio)]
|
||||||
Error::SubkernelError(error) => write!(f, "subkernel error: {:?}", error),
|
Error::SubkernelError(error) => write!(f, "subkernel error: {:?}", error),
|
||||||
|
#[cfg(has_drtio)]
|
||||||
|
Error::DestinationDown => write!(f, "subkernel destination down"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -538,6 +550,56 @@ async fn handle_run_kernel(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn handle_flash_kernel(
|
||||||
|
buffer: &Vec<u8>,
|
||||||
|
control: &Rc<RefCell<kernel::Control>>,
|
||||||
|
_up_destinations: &Rc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
|
||||||
|
_aux_mutex: &Rc<Mutex<bool>>,
|
||||||
|
_routing_table: &drtio_routing::RoutingTable,
|
||||||
|
_timer: GlobalTimer,
|
||||||
|
) -> Result<()> {
|
||||||
|
if buffer[0] == elf::ELFMAG0 && buffer[1] == elf::ELFMAG1 && buffer[2] == elf::ELFMAG2 && buffer[3] == elf::ELFMAG3
|
||||||
|
{
|
||||||
|
// assume ELF file, proceed as before
|
||||||
|
load_kernel(buffer, control, None).await
|
||||||
|
} else {
|
||||||
|
#[cfg(has_drtio)]
|
||||||
|
{
|
||||||
|
let archive = TarArchiveRef::new(buffer.as_ref());
|
||||||
|
let entries = archive.entries();
|
||||||
|
let mut main_lib: Vec<u8> = Vec::new();
|
||||||
|
for entry in entries {
|
||||||
|
if entry.filename().as_str() == "main.elf" {
|
||||||
|
main_lib = entry.data().to_vec();
|
||||||
|
} else {
|
||||||
|
// subkernel filename must be in format:
|
||||||
|
// "<subkernel id> <destination>.elf"
|
||||||
|
let filename = entry.filename();
|
||||||
|
let mut iter = filename.as_str().split_whitespace();
|
||||||
|
let sid: u32 = iter.next().unwrap().parse().unwrap();
|
||||||
|
let dest: u8 = iter.next().unwrap().strip_suffix(".elf").unwrap().parse().unwrap();
|
||||||
|
let up = _up_destinations.borrow()[dest as usize];
|
||||||
|
if up {
|
||||||
|
let subkernel_lib = entry.data().to_vec();
|
||||||
|
subkernel::add_subkernel(sid, dest, subkernel_lib).await;
|
||||||
|
match subkernel::upload(_aux_mutex, _routing_table, _timer, sid).await {
|
||||||
|
Ok(_) => (),
|
||||||
|
Err(_) => return Err(Error::UnexpectedPattern),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Err(Error::DestinationDown);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
load_kernel(&main_lib, control, None).await
|
||||||
|
}
|
||||||
|
#[cfg(not(has_drtio))]
|
||||||
|
{
|
||||||
|
panic!("multi-kernel libraries are not supported in standalone systems");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn load_kernel(
|
async fn load_kernel(
|
||||||
buffer: &Vec<u8>,
|
buffer: &Vec<u8>,
|
||||||
control: &Rc<RefCell<kernel::Control>>,
|
control: &Rc<RefCell<kernel::Control>>,
|
||||||
|
@ -693,7 +755,6 @@ pub fn main(timer: GlobalTimer, cfg: Config) {
|
||||||
|
|
||||||
Sockets::init(32);
|
Sockets::init(32);
|
||||||
|
|
||||||
// before, mutex was on io, but now that io isn't used...?
|
|
||||||
let aux_mutex: Rc<Mutex<bool>> = Rc::new(Mutex::new(false));
|
let aux_mutex: Rc<Mutex<bool>> = Rc::new(Mutex::new(false));
|
||||||
#[cfg(has_drtio)]
|
#[cfg(has_drtio)]
|
||||||
let drtio_routing_table = Rc::new(RefCell::new(drtio_routing::config_routing_table(
|
let drtio_routing_table = Rc::new(RefCell::new(drtio_routing::config_routing_table(
|
||||||
|
@ -716,9 +777,16 @@ pub fn main(timer: GlobalTimer, cfg: Config) {
|
||||||
let idle_kernel = Rc::new(cfg.read("idle_kernel").ok());
|
let idle_kernel = Rc::new(cfg.read("idle_kernel").ok());
|
||||||
if let Ok(buffer) = cfg.read("startup_kernel") {
|
if let Ok(buffer) = cfg.read("startup_kernel") {
|
||||||
info!("Loading startup kernel...");
|
info!("Loading startup kernel...");
|
||||||
if let Ok(()) = task::block_on(load_kernel(&buffer, &control, None)) {
|
|
||||||
info!("Starting startup kernel...");
|
|
||||||
let routing_table = drtio_routing_table.borrow();
|
let routing_table = drtio_routing_table.borrow();
|
||||||
|
if let Ok(()) = task::block_on(handle_flash_kernel(
|
||||||
|
&buffer,
|
||||||
|
&control,
|
||||||
|
&up_destinations,
|
||||||
|
&aux_mutex,
|
||||||
|
&routing_table,
|
||||||
|
timer,
|
||||||
|
)) {
|
||||||
|
info!("Starting startup kernel...");
|
||||||
let _ = task::block_on(handle_run_kernel(
|
let _ = task::block_on(handle_run_kernel(
|
||||||
None,
|
None,
|
||||||
&control,
|
&control,
|
||||||
|
@ -766,8 +834,17 @@ pub fn main(timer: GlobalTimer, cfg: Config) {
|
||||||
.map_err(|e| warn!("connection terminated: {}", e));
|
.map_err(|e| warn!("connection terminated: {}", e));
|
||||||
if let Some(buffer) = &*idle_kernel {
|
if let Some(buffer) = &*idle_kernel {
|
||||||
info!("Loading idle kernel");
|
info!("Loading idle kernel");
|
||||||
let _ = load_kernel(&buffer, &control, None)
|
let res = handle_flash_kernel(&buffer, &control, &up_destinations, &aux_mutex, &routing_table, timer)
|
||||||
.await.map_err(|_| warn!("error loading idle kernel"));
|
.await;
|
||||||
|
match res {
|
||||||
|
#[cfg(has_drtio)]
|
||||||
|
Err(Error::DestinationDown) => {
|
||||||
|
let mut countdown = timer.countdown();
|
||||||
|
delay(&mut countdown, Milliseconds(500)).await;
|
||||||
|
}
|
||||||
|
Err(_) => warn!("error loading idle kernel"),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
info!("Running idle kernel");
|
info!("Running idle kernel");
|
||||||
let _ = handle_run_kernel(None, &control, &up_destinations, &aux_mutex, &routing_table, timer)
|
let _ = handle_run_kernel(None, &control, &up_destinations, &aux_mutex, &routing_table, timer)
|
||||||
.await.map_err(|_| warn!("error running idle kernel"));
|
.await.map_err(|_| warn!("error running idle kernel"));
|
||||||
|
|
Loading…
Reference in New Issue