support .tar flashed idle/startup kernels

This commit is contained in:
mwojcik 2023-10-30 17:15:19 +08:00 committed by Sébastien Bourdeauducq
parent 875666f3ec
commit de10e584f6
5 changed files with 98 additions and 5 deletions

View File

@ -13,6 +13,12 @@ dependencies = [
name = "alloc_list"
version = "0.0.0"
[[package]]
name = "arrayvec"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
[[package]]
name = "bare-metal"
version = "0.2.5"
@ -332,6 +338,7 @@ dependencies = [
"proto_artiq",
"riscv",
"smoltcp",
"tar-no-std",
"unwind_backtrace",
]
@ -416,6 +423,16 @@ dependencies = [
"syn",
]
[[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]]
name = "unicode-xid"
version = "0.0.4"

View File

@ -40,3 +40,7 @@ git = "https://git.m-labs.hk/M-Labs/libfringe.git"
rev = "3ecbe5"
default-features = false
features = ["alloc"]
[dependencies.tar-no-std]
git = "https://git.m-labs.hk/M-Labs/tar-no-std"
rev = "2ab6dc5"

View File

@ -25,6 +25,8 @@ extern crate board_artiq;
extern crate logger_artiq;
extern crate proto_artiq;
extern crate riscv;
#[cfg(has_drtio)]
extern crate tar_no_std;
use alloc::collections::BTreeMap;
use core::cell::RefCell;

View File

@ -2,7 +2,10 @@ use core::{mem, str, cell::{Cell, RefCell}, fmt::Write as FmtWrite};
use alloc::{vec::Vec, string::{String, ToString}};
use byteorder::{ByteOrder, NativeEndian};
use cslice::CSlice;
#[cfg(has_drtio)]
use tar_no_std::TarArchiveRef;
use dyld::elf;
use io::{Read, Write, Error as IoError};
#[cfg(has_drtio)]
use io::Cursor;
@ -45,6 +48,9 @@ pub enum Error<T> {
#[fail(display = "DDMA error: {}", _0)]
Ddma(#[cause] remote_dma::Error),
#[cfg(has_drtio)]
#[fail(display = "subkernel destination is down")]
DestinationDown,
#[cfg(has_drtio)]
#[fail(display = "subkernel error: {}", _0)]
Subkernel(#[cause] SubkernelError),
#[cfg(has_drtio)]
@ -309,6 +315,63 @@ fn kern_run(session: &mut Session) -> Result<(), Error<SchedError>> {
kern_acknowledge()
}
fn process_flash_kernel(io: &Io, _aux_mutex: &Mutex, _subkernel_mutex: &Mutex,
_routing_table: &drtio_routing::RoutingTable,
_up_destinations: &Urc<RefCell<[bool; drtio_routing::DEST_COUNT]>>,
session: &mut Session, kernel: &[u8]
) -> Result<(), Error<SchedError>> {
// handle ELF and TAR files
if kernel[0] == elf::ELFMAG0 && kernel[1] == elf::ELFMAG1 &&
kernel[2] == elf::ELFMAG2 && kernel[3] == elf::ELFMAG3 {
// assume ELF file, proceed as before
unsafe {
// make a copy as kernel CPU cannot read SPI directly
kern_load(io, session, Vec::from(kernel).as_ref())
}
} else {
#[cfg(has_drtio)]
{
let archive = TarArchiveRef::new(kernel);
let entries = archive.entries();
let mut main_lib: Option<&[u8]> = None;
for entry in entries {
if entry.filename().as_str() == "main.elf" {
main_lib = Some(entry.data());
} 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 = {
let up_destinations = _up_destinations.borrow();
up_destinations[dest as usize]
};
if up {
let subkernel_lib = entry.data().to_vec();
subkernel::add_subkernel(io, _subkernel_mutex, sid, dest, subkernel_lib)?;
subkernel::upload(io, _aux_mutex, _subkernel_mutex, _routing_table, sid)?;
} else {
return Err(Error::DestinationDown);
}
}
}
unsafe {
kern_load(io, session, Vec::from(main_lib.unwrap()).as_ref())
}
}
#[cfg(not(has_drtio))]
{
unexpected!("multi-kernel libraries are not supported in standalone systems")
}
}
}
fn process_host_message(io: &Io, _aux_mutex: &Mutex, _ddma_mutex: &Mutex, _subkernel_mutex: &Mutex,
_routing_table: &drtio_routing::RoutingTable, stream: &mut TcpStream,
session: &mut Session) -> Result<(), Error<SchedError>> {
@ -777,11 +840,17 @@ fn flash_kernel_worker(io: &Io, aux_mutex: &Mutex,
config::read(config_key, |result| {
match result {
Ok(kernel) => unsafe {
// kernel CPU cannot access the SPI flash address space directly,
// so make a copy.
kern_load(io, &mut session, Vec::from(kernel).as_ref())
},
Ok(kernel) => {
// process .ELF or .TAR kernels
let res = process_flash_kernel(io, aux_mutex, subkernel_mutex, routing_table, up_destinations, &mut session, kernel);
#[cfg(has_drtio)]
match res {
// wait to establish the DRTIO connection
Err(Error::DestinationDown) => io.sleep(500)?,
_ => ()
}
res
}
_ => Err(Error::KernelNotFound)
}
})?;

View File

@ -249,6 +249,7 @@
lockFile = ./artiq/firmware/Cargo.lock;
outputHashes = {
"fringe-1.2.1" = "sha256-m4rzttWXRlwx53LWYpaKuU5AZe4GSkbjHS6oINt5d3Y=";
"tar-no-std-0.1.8" = "sha256-xm17108v4smXOqxdLvHl9CxTCJslmeogjm4Y87IXFuM=";
};
};
nativeBuildInputs = [