From 832ddfc205bc6df59ac5bcaffcb2ed665e1e9497 Mon Sep 17 00:00:00 2001 From: pca006132 Date: Tue, 1 Sep 2020 09:37:45 +0800 Subject: [PATCH 1/4] libconfig refactoring --- src/Cargo.toml | 18 +- src/libconfig/Cargo.toml | 15 ++ .../src/config.rs => libconfig/src/lib.rs} | 21 ++- .../src/net_settings.rs | 38 ++-- src/{runtime => libconfig}/src/sd_reader.rs | 0 src/runtime/Cargo.toml | 4 +- src/runtime/src/comms.rs | 5 +- src/runtime/src/load_pl.rs | 171 ------------------ src/runtime/src/main.rs | 13 +- 9 files changed, 73 insertions(+), 212 deletions(-) create mode 100644 src/libconfig/Cargo.toml rename src/{runtime/src/config.rs => libconfig/src/lib.rs} (88%) rename src/{runtime => libconfig}/src/net_settings.rs (58%) rename src/{runtime => libconfig}/src/sd_reader.rs (100%) delete mode 100644 src/runtime/src/load_pl.rs diff --git a/src/Cargo.toml b/src/Cargo.toml index d3378b1..e68c9bd 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -2,6 +2,7 @@ members = [ "libc", "libdyld", + "libconfig", "libcoreio", "libdwarf", "libunwind", @@ -9,6 +10,16 @@ members = [ "szl" ] +# Note: we are using dev profile for szl to override the opt-level only +[profile.dev] +panic = "abort" +debug = true +codegen-units = 1 +opt-level = 'z' +lto = true +debug-assertions = false +overflow-checks = false + [profile.release] panic = "abort" debug = true @@ -16,13 +27,6 @@ codegen-units = 1 opt-level = 's' lto = true -[profile.release.package.smoltcp] -opt-level = 2 -[profile.release.package.libasync] -opt-level = 2 -[profile.release.package.libboard_zynq] -opt-level = 2 - [patch.crates-io] core_io = { path = "./libcoreio" } compiler_builtins = { git = "https://git.m-labs.hk/M-Labs/compiler-builtins-zynq.git"} diff --git a/src/libconfig/Cargo.toml b/src/libconfig/Cargo.toml new file mode 100644 index 0000000..993cdd6 --- /dev/null +++ b/src/libconfig/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "libconfig" +version = "0.1.0" +authors = ["M-Labs"] +edition = "2018" + +[dependencies] +libboard_zynq = { git = "https://git.m-labs.hk/M-Labs/zynq-rs.git" } +core_io = { version = "0.1", features = ["collections"] } +fatfs = { version = "0.3", features = ["core_io"], default-features = false } +log = "0.4" + +[features] +ipv6 = [] + diff --git a/src/runtime/src/config.rs b/src/libconfig/src/lib.rs similarity index 88% rename from src/runtime/src/config.rs rename to src/libconfig/src/lib.rs index b8e3672..4e5ff30 100644 --- a/src/runtime/src/config.rs +++ b/src/libconfig/src/lib.rs @@ -1,10 +1,15 @@ -use crate::sd_reader; -use core::fmt; -use alloc::{string::FromUtf8Error, string::String, vec::Vec}; -use core_io::{self as io, BufRead, BufReader, Read}; +#![no_std] +extern crate alloc; +use core::fmt; +use alloc::{string::FromUtf8Error, string::String, vec::Vec, rc::Rc}; +use core_io::{self as io, BufRead, BufReader, Read}; use libboard_zynq::sdio; +pub mod sd_reader; +pub mod net_settings; +pub mod bootgen; + #[derive(Debug)] pub enum Error<'a> { SdError(sdio::sd_card::CardInitializationError), @@ -63,7 +68,7 @@ fn parse_config<'a>( } pub struct Config { - fs: Option>, + fs: Option>>, } impl Config { @@ -76,7 +81,11 @@ impl Config { let reader = sd_reader::SdReader::new(sd); let fs = reader.mount_fatfs(sd_reader::PartitionEntry::Entry1)?; - Ok(Config { fs: Some(fs) }) + Ok(Config { fs: Some(Rc::new(fs)) }) + } + + pub fn from_fs(fs: Option>>) -> Self { + Config { fs } } pub fn new_dummy() -> Self { diff --git a/src/runtime/src/net_settings.rs b/src/libconfig/src/net_settings.rs similarity index 58% rename from src/runtime/src/net_settings.rs rename to src/libconfig/src/net_settings.rs index 9bef1ea..76ddbb2 100644 --- a/src/runtime/src/net_settings.rs +++ b/src/libconfig/src/net_settings.rs @@ -2,31 +2,37 @@ use core::fmt; use libboard_zynq::smoltcp::wire::{EthernetAddress, IpAddress}; -use crate::config; +use super::Config; pub struct NetAddresses { pub hardware_addr: EthernetAddress, pub ipv4_addr: IpAddress, + #[cfg(feature = "ipv6")] pub ipv6_ll_addr: IpAddress, + #[cfg(feature = "ipv6")] pub ipv6_addr: Option } impl fmt::Display for NetAddresses { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "MAC={} IPv4={} IPv6-LL={} IPv6=", - self.hardware_addr, self.ipv4_addr, self.ipv6_ll_addr)?; - match self.ipv6_addr { - Some(addr) => write!(f, "{}", addr)?, - None => write!(f, "no configured address")? + write!(f, "MAC={} IPv4={} ", + self.hardware_addr, self.ipv4_addr)?; + + #[cfg(feature = "ipv6")] + { + write!(f, "IPv6-LL={}", self.ipv6_ll_addr)?; + match self.ipv6_addr { + Some(addr) => write!(f, " {}", addr)?, + None => write!(f, " IPv6: no configured address")? + } } Ok(()) } } -pub fn get_adresses(cfg: &config::Config) -> NetAddresses { +pub fn get_adresses(cfg: &Config) -> NetAddresses { let mut hardware_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x52]); let mut ipv4_addr = IpAddress::v4(192, 168, 1, 52); - let mut ipv6_addr = None; if let Ok(Ok(addr)) = cfg.read_str("mac").map(|s| s.parse()) { hardware_addr = addr; @@ -34,10 +40,10 @@ pub fn get_adresses(cfg: &config::Config) -> NetAddresses { if let Ok(Ok(addr)) = cfg.read_str("ip").map(|s| s.parse()) { ipv4_addr = addr; } - if let Ok(Ok(addr)) = cfg.read_str("ip6").map(|s| s.parse()) { - ipv6_addr = Some(addr); - } + #[cfg(feature = "ipv6")] + let ipv6_addr = cfg.read_str("ipv6").ok().and_then(|s| s.parse().ok()); + #[cfg(feature = "ipv6")] let ipv6_ll_addr = IpAddress::v6( 0xfe80, 0x0000, 0x0000, 0x0000, (((hardware_addr.0[0] ^ 0x02) as u16) << 8) | (hardware_addr.0[1] as u16), @@ -46,9 +52,11 @@ pub fn get_adresses(cfg: &config::Config) -> NetAddresses { ((hardware_addr.0[4] as u16) << 8) | (hardware_addr.0[5] as u16)); NetAddresses { - hardware_addr: hardware_addr, - ipv4_addr: ipv4_addr, - ipv6_ll_addr: ipv6_ll_addr, - ipv6_addr: ipv6_addr + hardware_addr, + ipv4_addr, + #[cfg(feature = "ipv6")] + ipv6_ll_addr, + #[cfg(feature = "ipv6")] + ipv6_addr } } diff --git a/src/runtime/src/sd_reader.rs b/src/libconfig/src/sd_reader.rs similarity index 100% rename from src/runtime/src/sd_reader.rs rename to src/libconfig/src/sd_reader.rs diff --git a/src/runtime/Cargo.toml b/src/runtime/Cargo.toml index 0137b05..88e4250 100644 --- a/src/runtime/Cargo.toml +++ b/src/runtime/Cargo.toml @@ -21,12 +21,11 @@ byteorder = { version = "1.3", default-features = false } void = { version = "1", default-features = false } futures = { version = "0.3", default-features = false, features = ["async-await"] } async-recursion = "0.3" -fatfs = { version = "0.3", features = ["core_io"], default-features = false } log_buffer = { version = "1.2" } libm = { version = "0.2", features = ["unstable"] } vcell = "0.1" -libboard_zynq = { git = "https://git.m-labs.hk/M-Labs/zynq-rs.git" } +libboard_zynq = { git = "https://git.m-labs.hk/M-Labs/zynq-rs.git", features = ["ipv6"]} libsupport_zynq = { default-features = false, features = ["alloc_core"], git = "https://git.m-labs.hk/M-Labs/zynq-rs.git" } libcortex_a9 = { git = "https://git.m-labs.hk/M-Labs/zynq-rs.git" } libasync = { git = "https://git.m-labs.hk/M-Labs/zynq-rs.git" } @@ -36,3 +35,4 @@ dyld = { path = "../libdyld" } dwarf = { path = "../libdwarf" } unwind = { path = "../libunwind" } libc = { path = "../libc" } +libconfig = { path = "../libconfig", features = ["ipv6"]} diff --git a/src/runtime/src/comms.rs b/src/runtime/src/comms.rs index b8a71fc..5e42314 100644 --- a/src/runtime/src/comms.rs +++ b/src/runtime/src/comms.rs @@ -20,9 +20,8 @@ use libboard_zynq::{ use libcortex_a9::{semaphore::Semaphore, mutex::Mutex}; use futures::{select_biased, future::FutureExt}; use libasync::{smoltcp::{Sockets, TcpStream}, task}; +use libconfig::{Config, net_settings}; -use crate::config; -use crate::net_settings; use crate::proto_async::*; use crate::kernel; use crate::rpc; @@ -315,7 +314,7 @@ async fn handle_connection(stream: &TcpStream, control: Rc for PlLoadingError { - fn from(error: Error) -> Self { - PlLoadingError::IoError(error) - } -} - -impl From for PlLoadingError { - fn from(error: devc::DevcError) -> Self { - PlLoadingError::DevcError(error) - } -} - -impl core::fmt::Display for PlLoadingError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - use PlLoadingError::*; - match self { - BootImageNotFound => write!( - f, - "Boot image not found, make sure `boot.bin` exists and your SD card is plugged in." - ), - InvalidBootImageHeader => write!( - f, - "Invalid boot image header. Check if the file is correct." - ), - MissingBitstreamPartition => write!( - f, - "Bitstream partition not found. Check your compile configuration." - ), - EncryptedBitstream => write!(f, "Encrypted bitstream is not supported."), - IoError(e) => write!(f, "Error while reading: {}", e), - DevcError(e) => write!(f, "PCAP interface error: {}", e), - } - } -} - -#[repr(C)] -struct PartitionHeader { - pub encrypted_length: u32, - pub unencrypted_length: u32, - pub word_length: u32, - pub dest_load_addr: u32, - pub dest_exec_addr: u32, - pub data_offset: u32, - pub attribute_bits: u32, - pub section_count: u32, - pub checksum_offset: u32, - pub header_offset: u32, - pub cert_offset: u32, - pub reserved: [u32; 4], - pub checksum: u32, -} - -/// Read a u32 word from the reader. -fn read_u32(reader: &mut Reader) -> Result { - let mut buffer: [u8; 4] = [0; 4]; - reader.read_exact(&mut buffer)?; - let mut result: u32 = 0; - for i in 0..4 { - result |= (buffer[i] as u32) << (i * 8); - } - Ok(result) -} - -/// Load PL partition header. -fn load_pl_header( - file: &mut File, -) -> Result, PlLoadingError> { - let mut buffer: [u8; 0x40] = [0; 0x40]; - file.read_exact(&mut buffer)?; - let header = unsafe { core::mem::transmute::<_, PartitionHeader>(buffer) }; - if header.attribute_bits & (2 << 4) != 0 { - Ok(Some(header)) - } else { - Ok(None) - } -} - -/// Locate the PL bitstream from the image, and return the size (in bytes) of the bitstream if successful. -/// This function would seek the file to the location of the bitstream. -fn locate_bitstream(file: &mut File) -> Result { - const BOOT_HEADER_SIGN: u32 = 0x584C4E58; - // read boot header signature - file.seek(SeekFrom::Start(0x24))?; - if read_u32(file)? != BOOT_HEADER_SIGN { - return Err(PlLoadingError::InvalidBootImageHeader); - } - // read partition header offset - file.seek(SeekFrom::Start(0x9C))?; - let ptr = read_u32(file)?; - debug!("Partition header pointer = {:0X}", ptr); - file.seek(SeekFrom::Start(ptr as u64))?; - - let mut header_opt = None; - // at most 3 partition headers - for _ in 0..3 { - let result = load_pl_header(file)?; - if let Some(h) = result { - header_opt = Some(h); - break; - } - } - let header = match header_opt { - None => return Err(PlLoadingError::MissingBitstreamPartition), - Some(h) => h, - }; - - let encrypted_length = header.encrypted_length; - let unencrypted_length = header.unencrypted_length; - debug!("Unencrypted length = {:0X}", unencrypted_length); - if encrypted_length != unencrypted_length { - return Err(PlLoadingError::EncryptedBitstream); - } - - let start_addr = header.data_offset; - debug!("Partition start address: {:0X}", start_addr); - file.seek(SeekFrom::Start(start_addr as u64 * 4))?; - - Ok(unencrypted_length as usize * 4) -} - -/// Load bitstream from bootgen file. -/// This function parses the file, locate the bitstream and load it through the PCAP driver. -/// It requires a large buffer, please enable the DDR RAM before using it. -pub fn load_bitstream( - file: &mut File, -) -> Result<(), PlLoadingError> { - let size = locate_bitstream(file)?; - let mut buffer: alloc::vec::Vec = alloc::vec::Vec::with_capacity(size); - unsafe { - buffer.set_len(buffer.capacity()); - } - file.read_exact(&mut buffer)?; - - let mut devcfg = devc::DevC::new(); - devcfg.enable(); - devcfg.program(&buffer)?; - Ok(()) -} - -pub fn load_bitstream_from_sd() -> Result<(), PlLoadingError> { - let sdio0 = sdio::Sdio::sdio0(true); - if sdio0.is_card_inserted() { - info!("Card inserted. Mounting file system."); - let sd = sdio::sd_card::SdCard::from_sdio(sdio0).unwrap(); - let reader = sd_reader::SdReader::new(sd); - - let fs = reader.mount_fatfs(sd_reader::PartitionEntry::Entry1)?; - let root_dir = fs.root_dir(); - let mut file = root_dir.open_file("/BOOT.BIN").map_err(|_| PlLoadingError::BootImageNotFound)?; - info!("Found boot image!"); - load_bitstream(&mut file) - } else { - info!("SD card not inserted. Bitstream cannot be loaded."); - Err(PlLoadingError::BootImageNotFound) - } -} diff --git a/src/runtime/src/main.rs b/src/runtime/src/main.rs index e974d06..dd91c0b 100644 --- a/src/runtime/src/main.rs +++ b/src/runtime/src/main.rs @@ -21,10 +21,8 @@ use libregister::RegisterW; use nb; use void::Void; use embedded_hal::blocking::delay::DelayMs; +use libconfig::{Config, load_pl}; -mod sd_reader; -mod config; -mod net_settings; mod proto_core_io; mod proto_async; mod comms; @@ -39,7 +37,6 @@ mod rtio; mod rtio; mod kernel; mod moninj; -mod load_pl; mod eh_artiq; mod panic; mod logger; @@ -99,7 +96,7 @@ fn identifier_read(buf: &mut [u8]) -> &str { } } -fn init_rtio(timer: &mut GlobalTimer, cfg: &config::Config) { +fn init_rtio(timer: &mut GlobalTimer, cfg: &Config) { let clock_sel = if let Ok(rtioclk) = cfg.read_str("rtioclk") { match rtioclk.as_ref() { @@ -185,7 +182,7 @@ pub fn main_core0() { let buffer_logger = unsafe { logger::BufferLogger::new(&mut LOG_BUFFER[..]) }; - buffer_logger.set_uart_log_level(log::LevelFilter::Debug); + buffer_logger.set_uart_log_level(log::LevelFilter::Info); buffer_logger.register(); log::set_max_level(log::LevelFilter::Debug); @@ -197,11 +194,11 @@ pub fn main_core0() { init_gateware(); info!("detected gateware: {}", identifier_read(&mut [0; 64])); - let cfg = match config::Config::new() { + let cfg = match Config::new() { Ok(cfg) => cfg, Err(err) => { warn!("config initialization failed: {}", err); - config::Config::new_dummy() + Config::new_dummy() } }; -- 2.42.0 From 3283d7c15bb096fc499cee4f395ffd89460258fe Mon Sep 17 00:00:00 2001 From: pca006132 Date: Tue, 1 Sep 2020 09:39:21 +0800 Subject: [PATCH 2/4] szl: implemented #96 SZL no longer do self-extraction for runtime binary, it would boot from SD/ethernet depending on the boot mode settings. This allows a larger runtime binary, so we can optimize for speed in the runtime firmware for better performance, and allow more features to be added later. --- src/Cargo.lock | 44 ++- src/Makefile | 11 +- src/szl/Cargo.toml | 14 +- src/szl/build.rs | 29 +- src/szl/link.x | 17 +- src/szl/src/main.rs | 168 +++++++---- src/szl/src/netboot.rs | 399 ++++++++++++++++++++++++ src/szl/src/unlzma.c | 670 ----------------------------------------- 8 files changed, 559 insertions(+), 793 deletions(-) create mode 100644 src/szl/src/netboot.rs delete mode 100644 src/szl/src/unlzma.c diff --git a/src/Cargo.lock b/src/Cargo.lock index 5dc6e40..3217e60 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -68,22 +68,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f8cb7306107e4b10e64994de6d3274bd08996a7c1322a27b86482392f96be0a" -[[package]] -name = "cstr_core" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edf9ff5f1182cea3b0f4269dd3edf146b5bfedc5dc8a29b95edf855f438786b7" -dependencies = [ - "cty", - "memchr", -] - -[[package]] -name = "cty" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7313c0d620d0cb4dbd9d019e461a4beb501071ff46ec0ab933efb4daa76d73e3" - [[package]] name = "dwarf" version = "0.0.0" @@ -203,7 +187,7 @@ dependencies = [ [[package]] name = "libasync" version = "0.0.0" -source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#273f9ea72b738c1c85fdc398c3486c2f0564881e" +source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#a73df780d0d0e757738f27feac162904f5bf93f9" dependencies = [ "embedded-hal", "libcortex_a9", @@ -215,7 +199,7 @@ dependencies = [ [[package]] name = "libboard_zynq" version = "0.0.0" -source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#273f9ea72b738c1c85fdc398c3486c2f0564881e" +source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#a73df780d0d0e757738f27feac162904f5bf93f9" dependencies = [ "bit_field", "embedded-hal", @@ -236,10 +220,20 @@ dependencies = [ "libboard_zynq", ] +[[package]] +name = "libconfig" +version = "0.1.0" +dependencies = [ + "core_io", + "fatfs", + "libboard_zynq", + "log", +] + [[package]] name = "libcortex_a9" version = "0.0.0" -source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#273f9ea72b738c1c85fdc398c3486c2f0564881e" +source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#a73df780d0d0e757738f27feac162904f5bf93f9" dependencies = [ "bit_field", "libregister", @@ -255,7 +249,7 @@ checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" [[package]] name = "libregister" version = "0.0.0" -source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#273f9ea72b738c1c85fdc398c3486c2f0564881e" +source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#a73df780d0d0e757738f27feac162904f5bf93f9" dependencies = [ "bit_field", "vcell", @@ -265,7 +259,7 @@ dependencies = [ [[package]] name = "libsupport_zynq" version = "0.0.0" -source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#273f9ea72b738c1c85fdc398c3486c2f0564881e" +source = "git+https://git.m-labs.hk/M-Labs/zynq-rs.git#a73df780d0d0e757738f27feac162904f5bf93f9" dependencies = [ "compiler_builtins", "libboard_zynq", @@ -416,11 +410,11 @@ dependencies = [ "dwarf", "dyld", "embedded-hal", - "fatfs", "futures", "libasync", "libboard_zynq", "libc", + "libconfig", "libcortex_a9", "libm", "libregister", @@ -461,10 +455,12 @@ dependencies = [ name = "szl" version = "0.1.0" dependencies = [ - "cc", - "cstr_core", + "byteorder", + "core_io", "libboard_zynq", + "libconfig", "libcortex_a9", + "libregister", "libsupport_zynq", "log", ] diff --git a/src/Makefile b/src/Makefile index 0256c27..b980026 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,6 +1,6 @@ VARIANT := simple -all: ../build/firmware/armv7-none-eabihf/release/szl +all: ../build/firmware/armv7-none-eabihf/release/szl ../build/firmware/armv7-none-eabihf/release/runtime .PHONY: all @@ -11,10 +11,7 @@ all: ../build/firmware/armv7-none-eabihf/release/szl ../build/firmware/armv7-none-eabihf/release/runtime: ../build/pl.rs ../build/rustc-cfg $(shell find . -path ./szl -prune -o -print) XBUILD_SYSROOT_PATH=`pwd`/../build/sysroot cargo xbuild --release -p runtime --target-dir ../build/firmware + llvm-objcopy -O binary ../build/firmware/armv7-none-eabihf/release/runtime ../build/runtime.bin -../build/szl-payload.bin.lzma: ../build/firmware/armv7-none-eabihf/release/runtime - llvm-objcopy -O binary ../build/firmware/armv7-none-eabihf/release/runtime ../build/szl-payload.bin - lzma --keep -f ../build/szl-payload.bin - -../build/firmware/armv7-none-eabihf/release/szl: .cargo/* armv7-none-eabihf.json Cargo.lock Cargo.toml szl/* szl/src/* ../build/szl-payload.bin.lzma - XBUILD_SYSROOT_PATH=`pwd`/../build/sysroot cargo xbuild --release -p szl --target-dir ../build/firmware +../build/firmware/armv7-none-eabihf/release/szl: .cargo/* armv7-none-eabihf.json Cargo.lock Cargo.toml szl/* szl/src/* + XBUILD_SYSROOT_PATH=`pwd`/../build/sysroot cargo xbuild -p szl --target-dir ../build/firmware diff --git a/src/szl/Cargo.toml b/src/szl/Cargo.toml index 459b6b1..fbd5da7 100644 --- a/src/szl/Cargo.toml +++ b/src/szl/Cargo.toml @@ -11,10 +11,12 @@ default = ["target_zc706"] [dependencies] log = "0.4" -cstr_core = { version = "0.2", default-features = false } -libboard_zynq = { git = "https://git.m-labs.hk/M-Labs/zynq-rs.git" } -libsupport_zynq = { git = "https://git.m-labs.hk/M-Labs/zynq-rs.git", default-features = false, features = ["dummy_irq_handler"] } -libcortex_a9 = { git = "https://git.m-labs.hk/M-Labs/zynq-rs.git" } +byteorder = { version = "1.3", default-features = false } +core_io = { version = "0.1", features = ["collections"] } + +libconfig = { path = "../libconfig" } +libboard_zynq = { git = "https://git.m-labs.hk/M-Labs/zynq-rs.git" } +libsupport_zynq = { git = "https://git.m-labs.hk/M-Labs/zynq-rs.git" } +libcortex_a9 = { git = "https://git.m-labs.hk/M-Labs/zynq-rs.git" } +libregister = { git = "https://git.m-labs.hk/M-Labs/zynq-rs.git" } -[build-dependencies] -cc = { version = "1.0.1" } diff --git a/src/szl/build.rs b/src/szl/build.rs index 90e8692..0a5f68a 100644 --- a/src/szl/build.rs +++ b/src/szl/build.rs @@ -1,14 +1,13 @@ use std::env; use std::fs::File; use std::io::Write; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; fn main() { println!("cargo:rerun-if-changed=build.rs"); let out = env::var("OUT_DIR").unwrap(); let out_dir = &PathBuf::from(&out); - compile_unlzma(); // Put the linker script somewhere the linker can find it File::create(out_dir.join("link.x")) .unwrap() @@ -21,29 +20,3 @@ fn main() { println!("cargo:rerun-if-changed=link.x"); } -pub fn compile_unlzma() { - let cfg = &mut cc::Build::new(); - cfg.compiler("clang"); - cfg.no_default_flags(true); - cfg.warnings(false); - - cfg.flag("-nostdlib"); - cfg.flag("-ffreestanding"); - cfg.flag("-fPIC"); - cfg.flag("-fno-stack-protector"); - cfg.flag("--target=armv7-none-eabihf"); - cfg.flag("-Oz"); - cfg.flag("-flto=full"); - - let sources = vec![ - "unlzma.c", - ]; - - let root = Path::new("./"); - for src in sources { - println!("cargo:rerun-if-changed={}", src); - cfg.file(root.join("src").join(src)); - } - - cfg.compile("unlzma"); -} diff --git a/src/szl/link.x b/src/szl/link.x index 502baab..8ed6397 100644 --- a/src/szl/link.x +++ b/src/szl/link.x @@ -4,6 +4,7 @@ MEMORY { /* 256 kB On-Chip Memory */ OCM : ORIGIN = 0, LENGTH = 0x30000 + SDRAM : ORIGIN = 0x00100000, LENGTH = 0x1FF00000 OCM3 : ORIGIN = 0xFFFF0000, LENGTH = 0x10000 } @@ -25,6 +26,16 @@ SECTIONS { *(.data .data.*); } > OCM + + .heap (NOLOAD) : ALIGN(8) + { + __runtime_start = .; + . += 0x8000000; + __runtime_end = .; + __heap0_start = .; + . += 0x8000000; + __heap0_end = .; + } > SDRAM .bss (NOLOAD) : ALIGN(4) { @@ -34,12 +45,6 @@ SECTIONS __bss_end = .; } > OCM3 - .heap (NOLOAD) : ALIGN(8) - { - __heap0_start = .; - __heap0_end = .; - } > OCM3 - .stack1 (NOLOAD) : ALIGN(8) { __stack1_end = .; diff --git a/src/szl/src/main.rs b/src/szl/src/main.rs index 18bba0a..19e69f0 100644 --- a/src/szl/src/main.rs +++ b/src/szl/src/main.rs @@ -1,47 +1,66 @@ #![no_std] #![no_main] -#![feature(panic_info_message)] +extern crate alloc; extern crate log; -use core::mem; -use log::{debug, info, error}; -use cstr_core::CStr; +mod netboot; -use libcortex_a9::{ - enable_fpu, - l2c::enable_l2_cache, - cache::{dcciall, iciallu, bpiall}, - asm::{dsb, isb}, -}; +use alloc::rc::Rc; +use core::mem; +use core_io::{Read, Seek}; use libboard_zynq::{ - self as zynq, println, - clocks::Clocks, clocks::source::{ClockSource, ArmPll, IoPll}, - stdio, - logger, + self as zynq, + clocks::source::{ArmPll, ClockSource, IoPll}, + clocks::Clocks, + logger, println, sdio, slcr, timer::GlobalTimer, }; -use libsupport_zynq as _; - +use libconfig::{bootgen, sd_reader, Config}; +use libcortex_a9::{ + asm::{dsb, isb}, + cache::{bpiall, dcciall, iciallu}, + enable_fpu, + l2c::enable_l2_cache, +}; +use libregister::RegisterR; +use libsupport_zynq::ram; +use log::info; extern "C" { - fn unlzma_simple(buf: *const u8, in_len: i32, - output: *mut u8, - error: extern fn(*const u8)) -> i32; + static mut __runtime_start: usize; + static mut __runtime_end: usize; } -extern fn lzma_error(message: *const u8) { - let msg = unsafe {CStr::from_ptr(message)}.to_str(); - if let Ok(msg) = msg { - println!("LZMA error: {}", msg); +fn boot_sd( + file: &mut Option, + runtime_start: *mut u8, + runtime_max: usize, +) -> Result<(), ()> { + if file.is_none() { + log::error!("No bootgen file"); + return Err(()); } -} + let mut file = file.as_mut().unwrap(); + info!("Loading gateware"); + bootgen::load_bitstream(&mut file).map_err(|e| log::error!("Cannot load gateware: {:?}", e))?; -#[panic_handler] -fn panic(_: &core::panic::PanicInfo) -> ! { - stdio::drop_uart(); - println!("panicked!"); - loop {} + info!("Loading runtime"); + let runtime = + bootgen::get_runtime(&mut file).map_err(|e| log::error!("Cannot load runtime: {:?}", e))?; + + if runtime.len() > runtime_max { + log::error!( + "Runtime binary too large, max {} but got {}", + runtime_max, + runtime.len() + ); + } + unsafe { + let target = core::slice::from_raw_parts_mut(runtime_start, runtime.len()); + target.copy_from_slice(&runtime); + } + Ok(()) } #[no_mangle] @@ -50,7 +69,8 @@ pub fn main_core0() { enable_fpu(); logger::init().unwrap(); log::set_max_level(log::LevelFilter::Debug); - println!(r#" + println!( + r#" __________ __ / ___/__ / / / @@ -59,12 +79,11 @@ pub fn main_core0() { /____/ /____/_____/ (C) 2020 M-Labs -"#); +"# + ); info!("Simple Zynq Loader starting..."); enable_l2_cache(); - debug!("FPU enabled on Core0"); - const CPU_FREQ: u32 = 800_000_000; ArmPll::setup(2 * CPU_FREQ); @@ -72,28 +91,73 @@ pub fn main_core0() { IoPll::setup(1_000_000_000); libboard_zynq::stdio::drop_uart(); // reinitialize UART after clocking change let mut ddr = zynq::ddr::DdrRam::ddrram(); + ram::init_alloc_core0(); - let payload = include_bytes!("../../../build/szl-payload.bin.lzma"); - info!("decompressing payload"); - let result = unsafe { - unlzma_simple(payload.as_ptr(), payload.len() as i32, ddr.ptr(), lzma_error) - }; - if result < 0 { - error!("decompression failed"); + let sdio0 = sdio::Sdio::sdio0(true); + let fs = if sdio0.is_card_inserted() { + info!("Card inserted. Mounting file system."); + let sd = sdio::sd_card::SdCard::from_sdio(sdio0).unwrap(); + let reader = sd_reader::SdReader::new(sd); + reader + .mount_fatfs(sd_reader::PartitionEntry::Entry1) + .map(|v| Rc::new(v)) + .ok() } else { - // Flush data cache entries for all of L1 cache, including - // Memory/Instruction Synchronization Barriers - dcciall(); - iciallu(); - bpiall(); - dsb(); - isb(); + info!("No SD card inserted."); + None + }; + let fs_ref = fs.as_ref(); + let root_dir = fs_ref.map(|fs| fs.root_dir()); + let mut bootgen_file = root_dir.and_then(|root_dir| root_dir.open_file("/BOOT.BIN").ok()); + let config = Config::from_fs(fs.clone()); - // Start core0 only, for compatibility with FSBL. - info!("executing payload"); - unsafe { - (mem::transmute::<*mut u8, fn()>(ddr.ptr::()))(); - } + unsafe { + let max_len = + &__runtime_end as *const usize as usize - &__runtime_start as *const usize as usize; + match slcr::RegisterBlock::unlocked(|slcr| slcr.boot_mode.read().boot_mode_pins()) { + slcr::BootModePins::Jtag => netboot::netboot( + &mut bootgen_file, + config, + &mut __runtime_start as *mut usize as *mut u8, + max_len, + ), + slcr::BootModePins::SdCard => { + if boot_sd( + &mut bootgen_file, + &mut __runtime_start as *mut usize as *mut u8, + max_len, + ) + .is_err() + { + log::error!("Error booting from SD card"); + log::info!("Fall back on netboot"); + netboot::netboot( + &mut bootgen_file, + config, + &mut __runtime_start as *mut usize as *mut u8, + max_len, + ) + } + } + v => { + panic!("Boot mode {:?} not supported", v); + } + }; + } + + info!("Preparing for runtime execution"); + // Flush data cache entries for all of L1 cache, including + // Memory/Instruction Synchronization Barriers + dcciall(); + iciallu(); + bpiall(); + dsb(); + isb(); + + // Start core0 only, for compatibility with FSBL. + info!("executing payload"); + unsafe { + (mem::transmute::<*mut u8, fn()>(ddr.ptr::()))(); } loop {} diff --git a/src/szl/src/netboot.rs b/src/szl/src/netboot.rs new file mode 100644 index 0000000..02ff235 --- /dev/null +++ b/src/szl/src/netboot.rs @@ -0,0 +1,399 @@ +use alloc::vec; +use alloc::vec::Vec; +use byteorder::{ByteOrder, NetworkEndian}; +use core_io::{Read, Seek}; +use libboard_zynq::{ + devc, + eth::Eth, + smoltcp::{ + self, + iface::{EthernetInterfaceBuilder, NeighborCache}, + time::Instant, + wire::IpCidr, + }, + timer::GlobalTimer, +}; +use libconfig::{bootgen, net_settings, Config}; + +enum NetConnState { + WaitCommand, + FirmwareLength(usize, u8), + FirmwareDownload(usize, usize), + FirmwareWaitO, + FirmwareWaitK, + GatewareLength(usize, u8), + GatewareDownload(usize, usize), + GatewareWaitO, + GatewareWaitK, +} + +struct NetConn { + state: NetConnState, + firmware_downloaded: bool, + gateware_downloaded: bool, +} + +impl NetConn { + pub fn new() -> NetConn { + NetConn { + state: NetConnState::WaitCommand, + firmware_downloaded: false, + gateware_downloaded: false, + } + } + + pub fn reset(&mut self) { + self.state = NetConnState::WaitCommand; + self.firmware_downloaded = false; + self.gateware_downloaded = false; + } + + fn input_partial( + &mut self, + bootgen_file: &mut Option, + runtime_start: *mut u8, + runtime_max_len: usize, + buf: &[u8], + storage: &mut Vec, + mut boot_callback: impl FnMut(), + ) -> Result { + match self.state { + NetConnState::WaitCommand => match buf[0] { + b'F' => { + log::info!("Received firmware load command"); + self.state = NetConnState::FirmwareLength(0, 0); + Ok(1) + } + b'G' => { + log::info!("Received gateware load command"); + self.state = NetConnState::GatewareLength(0, 0); + storage.clear(); + Ok(1) + } + b'B' => { + if !self.gateware_downloaded { + log::info!("Gateware not loaded via netboot"); + if bootgen_file.is_none() { + log::error!("No bootgen file to load gateware"); + return Err(()); + } + log::info!("Attempting to load from SD card"); + if let Err(e) = bootgen::load_bitstream(bootgen_file.as_mut().unwrap()) { + log::error!("Gateware load failed: {:?}", e); + return Err(()); + } + } + if self.firmware_downloaded { + log::info!("Received boot command"); + boot_callback(); + self.state = NetConnState::WaitCommand; + Ok(1) + } else { + log::error!("Received boot command, but no firmware downloaded"); + Err(()) + } + } + _ => { + log::error!("Received unknown netboot command: 0x{:02x}", buf[0]); + Err(()) + } + }, + NetConnState::FirmwareLength(firmware_length, recv_bytes) => { + let firmware_length = (firmware_length << 8) | (buf[0] as usize); + let recv_bytes = recv_bytes + 1; + if recv_bytes == 4 { + if firmware_length > runtime_max_len { + log::error!( + "Runtime too large, maximum {} but requested {}", + runtime_max_len, + firmware_length + ); + return Err(()); + } + self.state = NetConnState::FirmwareDownload(firmware_length, 0); + storage.clear(); + storage.reserve(firmware_length); + } else { + self.state = NetConnState::FirmwareLength(firmware_length, recv_bytes); + } + Ok(1) + } + NetConnState::FirmwareDownload(firmware_length, recv_bytes) => { + let max_length = firmware_length - recv_bytes; + let buf = if buf.len() > max_length { + &buf[..max_length] + } else { + &buf[..] + }; + let length = buf.len(); + + storage.extend_from_slice(buf); + + let recv_bytes = recv_bytes + length; + if recv_bytes == firmware_length { + self.state = NetConnState::FirmwareWaitO; + Ok(length) + } else { + self.state = NetConnState::FirmwareDownload(firmware_length, recv_bytes); + Ok(length) + } + } + NetConnState::FirmwareWaitO => { + if buf[0] == b'O' { + self.state = NetConnState::FirmwareWaitK; + Ok(1) + } else { + log::error!("End-of-firmware confirmation failed"); + Err(()) + } + } + NetConnState::FirmwareWaitK => { + if buf[0] == b'K' { + log::info!("Firmware successfully downloaded"); + self.state = NetConnState::WaitCommand; + self.firmware_downloaded = true; + { + let dest = unsafe { + core::slice::from_raw_parts_mut(runtime_start, storage.len()) + }; + dest.copy_from_slice(storage); + } + Ok(1) + } else { + log::error!("End-of-firmware confirmation failed"); + Err(()) + } + } + + NetConnState::GatewareLength(gateware_length, recv_bytes) => { + let gateware_length = (gateware_length << 8) | (buf[0] as usize); + let recv_bytes = recv_bytes + 1; + if recv_bytes == 4 { + self.state = NetConnState::GatewareDownload(gateware_length, 0); + storage.clear(); + storage.reserve_exact(gateware_length); + } else { + self.state = NetConnState::GatewareLength(gateware_length, recv_bytes); + } + Ok(1) + } + NetConnState::GatewareDownload(gateware_length, recv_bytes) => { + let max_length = gateware_length - recv_bytes; + let buf = if buf.len() > max_length { + &buf[..max_length] + } else { + &buf[..] + }; + let length = buf.len(); + + storage.extend_from_slice(buf); + + let recv_bytes = recv_bytes + length; + if recv_bytes == gateware_length { + self.state = NetConnState::GatewareWaitO; + Ok(length) + } else { + self.state = NetConnState::GatewareDownload(gateware_length, recv_bytes); + Ok(length) + } + } + NetConnState::GatewareWaitO => { + if buf[0] == b'O' { + self.state = NetConnState::GatewareWaitK; + Ok(1) + } else { + log::error!("End-of-gateware confirmation failed"); + Err(()) + } + } + NetConnState::GatewareWaitK => { + if buf[0] == b'K' { + log::info!("Preprocessing bitstream..."); + // find sync word 0xFFFFFFFF AA995566 + let sync_word: [u8; 8] = [0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0x99, 0x55, 0x66]; + let mut i = 0; + let mut state = 0; + while i < storage.len() { + if storage[i] == sync_word[state] { + state += 1; + if state == sync_word.len() { + break; + } + } else { + // backtrack + // not very efficient but we only have 8 elements + 'outer: while state > 0 { + state -= 1; + for j in 0..state { + if storage[i - j] != sync_word[state - j] { + continue 'outer; + } + } + break; + } + } + i += 1; + } + if state != sync_word.len() { + log::error!("Sync word not found in bitstream (corrupted?)"); + return Err(()); + } + // we need the sync word + // i was pointing to the last element in the sync sequence + i -= sync_word.len() - 1; + // // append no-op + // storage.extend_from_slice(&[0x20, 0, 0, 0]); + let bitstream = &mut storage[i..]; + { + // swap endian + let swap = unsafe { + core::slice::from_raw_parts_mut( + bitstream.as_mut_ptr() as usize as *mut u32, + bitstream.len() / 4, + ) + }; + NetworkEndian::from_slice_u32(swap); + } + unsafe { + // align to 64 bytes + let ptr = alloc::alloc::alloc( + alloc::alloc::Layout::from_size_align(bitstream.len(), 64).unwrap(), + ); + let buffer = core::slice::from_raw_parts_mut(ptr, bitstream.len()); + buffer.copy_from_slice(bitstream); + + let mut devcfg = devc::DevC::new(); + devcfg.enable(); + let result = devcfg.program(&buffer); + core::ptr::drop_in_place(ptr); + if let Err(e) = result { + log::error!("Error during FPGA startup: {}", e); + return Err(()); + } + } + + log::info!("Gateware successfully downloaded"); + self.state = NetConnState::WaitCommand; + self.gateware_downloaded = true; + Ok(1) + } else { + log::info!("End-of-gateware confirmation failed"); + Err(()) + } + } + } + } + + fn input( + &mut self, + bootgen_file: &mut Option, + runtime_start: *mut u8, + runtime_max_len: usize, + buf: &[u8], + storage: &mut Vec, + mut boot_callback: impl FnMut(), + ) -> Result<(), ()> { + let mut remaining = &buf[..]; + while !remaining.is_empty() { + let read_cnt = self.input_partial( + bootgen_file, + runtime_start, + runtime_max_len, + remaining, + storage, + &mut boot_callback, + )?; + remaining = &remaining[read_cnt..]; + } + Ok(()) + } +} + +pub fn netboot( + bootgen_file: &mut Option, + cfg: Config, + runtime_start: *mut u8, + runtime_max_len: usize, +) { + log::info!("Preparing network for netboot"); + let net_addresses = net_settings::get_adresses(&cfg); + log::info!("Network addresses: {}", net_addresses); + let eth = Eth::eth0(net_addresses.hardware_addr.0.clone()); + let eth = eth.start_rx(8); + let mut eth = eth.start_tx(8); + + let mut neighbor_map = [None; 2]; + let neighbor_cache = NeighborCache::new(&mut neighbor_map[..]); + let mut ip_addrs = [IpCidr::new(net_addresses.ipv4_addr, 0)]; + let mut interface = EthernetInterfaceBuilder::new(&mut eth) + .ethernet_addr(net_addresses.hardware_addr) + .ip_addrs(&mut ip_addrs[..]) + .neighbor_cache(neighbor_cache) + .finalize(); + + let mut rx_storage = vec![0; 4096]; + let mut tx_storage = vec![0; 128]; + + let mut socket_set_entries: [_; 1] = Default::default(); + let mut sockets = smoltcp::socket::SocketSet::new(&mut socket_set_entries[..]); + + let tcp_rx_buffer = smoltcp::socket::TcpSocketBuffer::new(&mut rx_storage[..]); + let tcp_tx_buffer = smoltcp::socket::TcpSocketBuffer::new(&mut tx_storage[..]); + let tcp_socket = smoltcp::socket::TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer); + let tcp_handle = sockets.add(tcp_socket); + + let mut net_conn = NetConn::new(); + let mut storage = Vec::new(); + let mut boot_flag = false; + let timer = unsafe { GlobalTimer::get() }; + + log::info!("Waiting for connections..."); + loop { + let timestamp = Instant::from_millis(timer.get_time().0 as i64); + { + let socket = &mut *sockets.get::(tcp_handle); + + if boot_flag { + return; + } + if !socket.is_open() { + socket.listen(4269).unwrap() // 0x10ad + } + + if socket.may_recv() { + if socket + .recv(|data| { + ( + data.len(), + net_conn + .input( + bootgen_file, + runtime_start, + runtime_max_len, + data, + &mut storage, + || { + boot_flag = true; + }, + ) + .is_err(), + ) + }) + .unwrap() + { + net_conn.reset(); + socket.close(); + } + } else if socket.may_send() { + net_conn.reset(); + socket.close(); + } + } + + match interface.poll(&mut sockets, timestamp) { + Ok(_) => (), + Err(smoltcp::Error::Unrecognized) => (), + Err(err) => log::error!("Network error: {}", err), + } + } +} diff --git a/src/szl/src/unlzma.c b/src/szl/src/unlzma.c deleted file mode 100644 index 47cd052..0000000 --- a/src/szl/src/unlzma.c +++ /dev/null @@ -1,670 +0,0 @@ -/* - *Taken from: Lzma decompressor for Linux kernel. Shamelessly snarfed - *from busybox 1.1.1 - * - *Linux kernel adaptation - *Copyright (C) 2006 Alain < alain@knaff.lu > - * - *Based on small lzma deflate implementation/Small range coder - *implementation for lzma. - *Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org > - * - *Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/) - *Copyright (C) 1999-2005 Igor Pavlov - * - *Copyrights of the parts, see headers below. - * - * - *This program is free software; you can redistribute it and/or - *modify it under the terms of the GNU Lesser General Public - *License as published by the Free Software Foundation; either - *version 2.1 of the License, or (at your option) any later version. - * - *This program is distributed in the hope that it will be useful, - *but WITHOUT ANY WARRANTY; without even the implied warranty of - *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - *Lesser General Public License for more details. - * - *You should have received a copy of the GNU Lesser General Public - *License along with this library; if not, write to the Free Software - *Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#define NULL ((void *)0) -#define alloca(size) __builtin_alloca(size) -#define malloc alloca -static inline void free(void *p) {} - -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) - -static long long read_int(unsigned char *ptr, int size) -{ - int i; - long long ret = 0; - - for (i = 0; i < size; i++) - ret = (ret << 8) | ptr[size-i-1]; - return ret; -} - -#define ENDIAN_CONVERT(x) \ - x = (typeof(x))read_int((unsigned char *)&x, sizeof(x)) - - -/* Small range coder implementation for lzma. - *Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org > - * - *Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/) - *Copyright (c) 1999-2005 Igor Pavlov - */ - -#define LZMA_IOBUF_SIZE 0x10000 - -struct rc { - int (*fill)(void*, unsigned int); - unsigned char *ptr; - unsigned char *buffer; - unsigned char *buffer_end; - int buffer_size; - unsigned int code; - unsigned int range; - unsigned int bound; - void (*error)(char *); -}; - - -#define RC_TOP_BITS 24 -#define RC_MOVE_BITS 5 -#define RC_MODEL_TOTAL_BITS 11 - - -static int nofill(void *buffer, unsigned int len) -{ - return -1; -} - -/* Called twice: once at startup and once in rc_normalize() */ -static void rc_read(struct rc *rc) -{ - rc->buffer_size = rc->fill((char *)rc->buffer, LZMA_IOBUF_SIZE); - if (rc->buffer_size <= 0) - rc->error("unexpected EOF"); - rc->ptr = rc->buffer; - rc->buffer_end = rc->buffer + rc->buffer_size; -} - -/* Called once */ -static inline void rc_init(struct rc *rc, - int (*fill)(void*, unsigned int), - unsigned char *buffer, int buffer_size) -{ - if (fill) - rc->fill = fill; - else - rc->fill = nofill; - rc->buffer = buffer; - rc->buffer_size = buffer_size; - rc->buffer_end = rc->buffer + rc->buffer_size; - rc->ptr = rc->buffer; - - rc->code = 0; - rc->range = 0xFFFFFFFF; -} - -static inline void rc_init_code(struct rc *rc) -{ - int i; - - for (i = 0; i < 5; i++) { - if (rc->ptr >= rc->buffer_end) - rc_read(rc); - rc->code = (rc->code << 8) | *rc->ptr++; - } -} - - -/* Called twice, but one callsite is in inline'd rc_is_bit_0_helper() */ -static void rc_do_normalize(struct rc *rc) -{ - if (rc->ptr >= rc->buffer_end) - rc_read(rc); - rc->range <<= 8; - rc->code = (rc->code << 8) | *rc->ptr++; -} -static inline void rc_normalize(struct rc *rc) -{ - if (rc->range < (1 << RC_TOP_BITS)) - rc_do_normalize(rc); -} - -/* Called 9 times */ -/* Why rc_is_bit_0_helper exists? - *Because we want to always expose (rc->code < rc->bound) to optimizer - */ -static inline unsigned int rc_is_bit_0_helper(struct rc *rc, unsigned short int *p) -{ - rc_normalize(rc); - rc->bound = *p * (rc->range >> RC_MODEL_TOTAL_BITS); - return rc->bound; -} -static inline int rc_is_bit_0(struct rc *rc, unsigned short int *p) -{ - unsigned int t = rc_is_bit_0_helper(rc, p); - return rc->code < t; -} - -/* Called ~10 times, but very small, thus inlined */ -static inline void rc_update_bit_0(struct rc *rc, unsigned short int *p) -{ - rc->range = rc->bound; - *p += ((1 << RC_MODEL_TOTAL_BITS) - *p) >> RC_MOVE_BITS; -} -static inline void rc_update_bit_1(struct rc *rc, unsigned short int *p) -{ - rc->range -= rc->bound; - rc->code -= rc->bound; - *p -= *p >> RC_MOVE_BITS; -} - -/* Called 4 times in unlzma loop */ -static int rc_get_bit(struct rc *rc, unsigned short int *p, int *symbol) -{ - if (rc_is_bit_0(rc, p)) { - rc_update_bit_0(rc, p); - *symbol *= 2; - return 0; - } else { - rc_update_bit_1(rc, p); - *symbol = *symbol * 2 + 1; - return 1; - } -} - -/* Called once */ -static inline int rc_direct_bit(struct rc *rc) -{ - rc_normalize(rc); - rc->range >>= 1; - if (rc->code >= rc->range) { - rc->code -= rc->range; - return 1; - } - return 0; -} - -/* Called twice */ -static inline void -rc_bit_tree_decode(struct rc *rc, unsigned short int *p, int num_levels, int *symbol) -{ - int i = num_levels; - - *symbol = 1; - while (i--) - rc_get_bit(rc, p + *symbol, symbol); - *symbol -= 1 << num_levels; -} - - -/* - * Small lzma deflate implementation. - * Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org > - * - * Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/) - * Copyright (C) 1999-2005 Igor Pavlov - */ - - -struct lzma_header { - unsigned char pos; - unsigned int dict_size; - unsigned long long int dst_size; -} __attribute__ ((packed)) ; - - -#define LZMA_BASE_SIZE 1846 -#define LZMA_LIT_SIZE 768 - -#define LZMA_NUM_POS_BITS_MAX 4 - -#define LZMA_LEN_NUM_LOW_BITS 3 -#define LZMA_LEN_NUM_MID_BITS 3 -#define LZMA_LEN_NUM_HIGH_BITS 8 - -#define LZMA_LEN_CHOICE 0 -#define LZMA_LEN_CHOICE_2 (LZMA_LEN_CHOICE + 1) -#define LZMA_LEN_LOW (LZMA_LEN_CHOICE_2 + 1) -#define LZMA_LEN_MID (LZMA_LEN_LOW \ - + (1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_LOW_BITS))) -#define LZMA_LEN_HIGH (LZMA_LEN_MID \ - +(1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_MID_BITS))) -#define LZMA_NUM_LEN_PROBS (LZMA_LEN_HIGH + (1 << LZMA_LEN_NUM_HIGH_BITS)) - -#define LZMA_NUM_STATES 12 -#define LZMA_NUM_LIT_STATES 7 - -#define LZMA_START_POS_MODEL_INDEX 4 -#define LZMA_END_POS_MODEL_INDEX 14 -#define LZMA_NUM_FULL_DISTANCES (1 << (LZMA_END_POS_MODEL_INDEX >> 1)) - -#define LZMA_NUM_POS_SLOT_BITS 6 -#define LZMA_NUM_LEN_TO_POS_STATES 4 - -#define LZMA_NUM_ALIGN_BITS 4 - -#define LZMA_MATCH_MIN_LEN 2 - -#define LZMA_IS_MATCH 0 -#define LZMA_IS_REP (LZMA_IS_MATCH + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)) -#define LZMA_IS_REP_G0 (LZMA_IS_REP + LZMA_NUM_STATES) -#define LZMA_IS_REP_G1 (LZMA_IS_REP_G0 + LZMA_NUM_STATES) -#define LZMA_IS_REP_G2 (LZMA_IS_REP_G1 + LZMA_NUM_STATES) -#define LZMA_IS_REP_0_LONG (LZMA_IS_REP_G2 + LZMA_NUM_STATES) -#define LZMA_POS_SLOT (LZMA_IS_REP_0_LONG \ - + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)) -#define LZMA_SPEC_POS (LZMA_POS_SLOT \ - +(LZMA_NUM_LEN_TO_POS_STATES << LZMA_NUM_POS_SLOT_BITS)) -#define LZMA_ALIGN (LZMA_SPEC_POS \ - + LZMA_NUM_FULL_DISTANCES - LZMA_END_POS_MODEL_INDEX) -#define LZMA_LEN_CODER (LZMA_ALIGN + (1 << LZMA_NUM_ALIGN_BITS)) -#define LZMA_REP_LEN_CODER (LZMA_LEN_CODER + LZMA_NUM_LEN_PROBS) -#define LZMA_LITERAL (LZMA_REP_LEN_CODER + LZMA_NUM_LEN_PROBS) - - -struct writer { - unsigned char *buffer; - unsigned char previous_byte; - int buffer_pos; - int bufsize; - int global_pos; - int(*flush)(void*, unsigned int); - struct lzma_header *header; -}; - -struct cstate { - int state; - unsigned int rep0, rep1, rep2, rep3; -}; - -static inline int get_pos(struct writer *wr) -{ - return - wr->global_pos + wr->buffer_pos; -} - -static inline unsigned char peek_old_byte(struct writer *wr, - unsigned int offs) -{ - if (!wr->flush) { - int pos; - while (offs > wr->header->dict_size) - offs -= wr->header->dict_size; - pos = wr->buffer_pos - offs; - return wr->buffer[pos]; - } else { - unsigned int pos = wr->buffer_pos - offs; - while (pos >= wr->header->dict_size) - pos += wr->header->dict_size; - return wr->buffer[pos]; - } - -} - -static inline int write_byte(struct writer *wr, unsigned char byte) -{ - wr->buffer[wr->buffer_pos++] = wr->previous_byte = byte; - if (wr->flush && wr->buffer_pos == wr->header->dict_size) { - wr->buffer_pos = 0; - wr->global_pos += wr->header->dict_size; - if (wr->flush((char *)wr->buffer, wr->header->dict_size) - != wr->header->dict_size) - return -1; - } - return 0; -} - - -static inline int copy_byte(struct writer *wr, unsigned int offs) -{ - return write_byte(wr, peek_old_byte(wr, offs)); -} - -static inline int copy_bytes(struct writer *wr, - unsigned int rep0, int len) -{ - do { - if (copy_byte(wr, rep0)) - return -1; - len--; - } while (len != 0 && wr->buffer_pos < wr->header->dst_size); - - return len; -} - -static inline int process_bit0(struct writer *wr, struct rc *rc, - struct cstate *cst, unsigned short int *p, - int pos_state, unsigned short int *prob, - int lc, unsigned int literal_pos_mask) { - int mi = 1; - rc_update_bit_0(rc, prob); - prob = (p + LZMA_LITERAL + - (LZMA_LIT_SIZE - * (((get_pos(wr) & literal_pos_mask) << lc) - + (wr->previous_byte >> (8 - lc)))) - ); - - if (cst->state >= LZMA_NUM_LIT_STATES) { - int match_byte = peek_old_byte(wr, cst->rep0); - do { - int bit; - unsigned short int *prob_lit; - - match_byte <<= 1; - bit = match_byte & 0x100; - prob_lit = prob + 0x100 + bit + mi; - if (rc_get_bit(rc, prob_lit, &mi)) { - if (!bit) - break; - } else { - if (bit) - break; - } - } while (mi < 0x100); - } - while (mi < 0x100) { - unsigned short int *prob_lit = prob + mi; - rc_get_bit(rc, prob_lit, &mi); - } - if (cst->state < 4) - cst->state = 0; - else if (cst->state < 10) - cst->state -= 3; - else - cst->state -= 6; - - return write_byte(wr, mi); -} - -static inline int process_bit1(struct writer *wr, struct rc *rc, - struct cstate *cst, unsigned short int *p, - int pos_state, unsigned short int *prob) { - int offset; - unsigned short int *prob_len; - int num_bits; - int len; - - rc_update_bit_1(rc, prob); - prob = p + LZMA_IS_REP + cst->state; - if (rc_is_bit_0(rc, prob)) { - rc_update_bit_0(rc, prob); - cst->rep3 = cst->rep2; - cst->rep2 = cst->rep1; - cst->rep1 = cst->rep0; - cst->state = cst->state < LZMA_NUM_LIT_STATES ? 0 : 3; - prob = p + LZMA_LEN_CODER; - } else { - rc_update_bit_1(rc, prob); - prob = p + LZMA_IS_REP_G0 + cst->state; - if (rc_is_bit_0(rc, prob)) { - rc_update_bit_0(rc, prob); - prob = (p + LZMA_IS_REP_0_LONG - + (cst->state << - LZMA_NUM_POS_BITS_MAX) + - pos_state); - if (rc_is_bit_0(rc, prob)) { - rc_update_bit_0(rc, prob); - - cst->state = cst->state < LZMA_NUM_LIT_STATES ? - 9 : 11; - return copy_byte(wr, cst->rep0); - } else { - rc_update_bit_1(rc, prob); - } - } else { - unsigned int distance; - - rc_update_bit_1(rc, prob); - prob = p + LZMA_IS_REP_G1 + cst->state; - if (rc_is_bit_0(rc, prob)) { - rc_update_bit_0(rc, prob); - distance = cst->rep1; - } else { - rc_update_bit_1(rc, prob); - prob = p + LZMA_IS_REP_G2 + cst->state; - if (rc_is_bit_0(rc, prob)) { - rc_update_bit_0(rc, prob); - distance = cst->rep2; - } else { - rc_update_bit_1(rc, prob); - distance = cst->rep3; - cst->rep3 = cst->rep2; - } - cst->rep2 = cst->rep1; - } - cst->rep1 = cst->rep0; - cst->rep0 = distance; - } - cst->state = cst->state < LZMA_NUM_LIT_STATES ? 8 : 11; - prob = p + LZMA_REP_LEN_CODER; - } - - prob_len = prob + LZMA_LEN_CHOICE; - if (rc_is_bit_0(rc, prob_len)) { - rc_update_bit_0(rc, prob_len); - prob_len = (prob + LZMA_LEN_LOW - + (pos_state << - LZMA_LEN_NUM_LOW_BITS)); - offset = 0; - num_bits = LZMA_LEN_NUM_LOW_BITS; - } else { - rc_update_bit_1(rc, prob_len); - prob_len = prob + LZMA_LEN_CHOICE_2; - if (rc_is_bit_0(rc, prob_len)) { - rc_update_bit_0(rc, prob_len); - prob_len = (prob + LZMA_LEN_MID - + (pos_state << - LZMA_LEN_NUM_MID_BITS)); - offset = 1 << LZMA_LEN_NUM_LOW_BITS; - num_bits = LZMA_LEN_NUM_MID_BITS; - } else { - rc_update_bit_1(rc, prob_len); - prob_len = prob + LZMA_LEN_HIGH; - offset = ((1 << LZMA_LEN_NUM_LOW_BITS) - + (1 << LZMA_LEN_NUM_MID_BITS)); - num_bits = LZMA_LEN_NUM_HIGH_BITS; - } - } - - rc_bit_tree_decode(rc, prob_len, num_bits, &len); - len += offset; - - if (cst->state < 4) { - int pos_slot; - - cst->state += LZMA_NUM_LIT_STATES; - prob = - p + LZMA_POS_SLOT + - ((len < - LZMA_NUM_LEN_TO_POS_STATES ? len : - LZMA_NUM_LEN_TO_POS_STATES - 1) - << LZMA_NUM_POS_SLOT_BITS); - rc_bit_tree_decode(rc, prob, - LZMA_NUM_POS_SLOT_BITS, - &pos_slot); - if (pos_slot >= LZMA_START_POS_MODEL_INDEX) { - int i, mi; - num_bits = (pos_slot >> 1) - 1; - cst->rep0 = 2 | (pos_slot & 1); - if (pos_slot < LZMA_END_POS_MODEL_INDEX) { - cst->rep0 <<= num_bits; - prob = p + LZMA_SPEC_POS + - cst->rep0 - pos_slot - 1; - } else { - num_bits -= LZMA_NUM_ALIGN_BITS; - while (num_bits--) - cst->rep0 = (cst->rep0 << 1) | - rc_direct_bit(rc); - prob = p + LZMA_ALIGN; - cst->rep0 <<= LZMA_NUM_ALIGN_BITS; - num_bits = LZMA_NUM_ALIGN_BITS; - } - i = 1; - mi = 1; - while (num_bits--) { - if (rc_get_bit(rc, prob + mi, &mi)) - cst->rep0 |= i; - i <<= 1; - } - } else - cst->rep0 = pos_slot; - if (++(cst->rep0) == 0) - return 0; - if (cst->rep0 > wr->header->dict_size - || cst->rep0 > get_pos(wr)) - return -1; - } - - len += LZMA_MATCH_MIN_LEN; - - return copy_bytes(wr, cst->rep0, len); -} - - - -int unlzma(unsigned char *buf, int in_len, - int(*fill)(void*, unsigned int), - int(*flush)(void*, unsigned int), - unsigned char *output, - int *posp, - void(*error)(char *x) - ) -{ - struct lzma_header header; - int lc, pb, lp; - unsigned int pos_state_mask; - unsigned int literal_pos_mask; - unsigned short int *p; - int num_probs; - struct rc rc; - int i, mi; - struct writer wr; - struct cstate cst; - unsigned char *inbuf; - int ret = -1; - - rc.error = error; - - if (buf) - inbuf = buf; - else - inbuf = malloc(LZMA_IOBUF_SIZE); - if (!inbuf) { - error("Could not allocate input bufer"); - goto exit_0; - } - - cst.state = 0; - cst.rep0 = cst.rep1 = cst.rep2 = cst.rep3 = 1; - - wr.header = &header; - wr.flush = flush; - wr.global_pos = 0; - wr.previous_byte = 0; - wr.buffer_pos = 0; - - rc_init(&rc, fill, inbuf, in_len); - - for (i = 0; i < sizeof(header); i++) { - if (rc.ptr >= rc.buffer_end) - rc_read(&rc); - ((unsigned char *)&header)[i] = *rc.ptr++; - } - - if (header.pos >= (9 * 5 * 5)) { - error("bad header"); - goto exit_1; - } - - mi = 0; - lc = header.pos; - while (lc >= 9) { - mi++; - lc -= 9; - } - pb = 0; - lp = mi; - while (lp >= 5) { - pb++; - lp -= 5; - } - pos_state_mask = (1 << pb) - 1; - literal_pos_mask = (1 << lp) - 1; - - ENDIAN_CONVERT(header.dict_size); - ENDIAN_CONVERT(header.dst_size); - - if (header.dict_size == 0) - header.dict_size = 1; - - if (output) - wr.buffer = output; - else { - wr.bufsize = MIN(header.dst_size, header.dict_size); - wr.buffer = malloc(wr.bufsize); - } - if (wr.buffer == NULL) - goto exit_1; - - num_probs = LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp)); - p = (unsigned short int *) malloc(num_probs * sizeof(*p)); - if (p == 0) - goto exit_2; - num_probs = LZMA_LITERAL + (LZMA_LIT_SIZE << (lc + lp)); - for (i = 0; i < num_probs; i++) - p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1; - - rc_init_code(&rc); - - while (get_pos(&wr) < header.dst_size) { - int pos_state = get_pos(&wr) & pos_state_mask; - unsigned short int *prob = p + LZMA_IS_MATCH + - (cst.state << LZMA_NUM_POS_BITS_MAX) + pos_state; - if (rc_is_bit_0(&rc, prob)) { - if (process_bit0(&wr, &rc, &cst, p, pos_state, prob, - lc, literal_pos_mask)) { - error("LZMA data is corrupt"); - goto exit_3; - } - } else { - if (process_bit1(&wr, &rc, &cst, p, pos_state, prob)) { - error("LZMA data is corrupt"); - goto exit_3; - } - if (cst.rep0 == 0) - break; - } - if (rc.buffer_size <= 0) - goto exit_3; - } - - if (posp) - *posp = rc.ptr-rc.buffer; - if (!wr.flush || wr.flush(wr.buffer, wr.buffer_pos) == wr.buffer_pos) - ret = 0; -exit_3: - free(p); -exit_2: - if (!output) - free(wr.buffer); -exit_1: - if (!buf) - free(inbuf); -exit_0: - return ret; -} - -int unlzma_simple(unsigned char *buf, int in_len, - unsigned char *output, - void(*error)(char *x)) -{ - return unlzma(buf, in_len, NULL, NULL, output, NULL, error); -} -- 2.42.0 From d499a5e9b23412acb1885597b499cc72a824314f Mon Sep 17 00:00:00 2001 From: pca006132 Date: Tue, 1 Sep 2020 09:41:02 +0800 Subject: [PATCH 3/4] Updated build scripts --- default.nix | 9 +++++++-- local_run.sh | 17 ++++++++++++----- remote_run.sh | 20 ++++++++++++-------- 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/default.nix b/default.nix index c80a7f4..252e652 100644 --- a/default.nix +++ b/default.nix @@ -15,7 +15,7 @@ let version = "0.1.0"; src = ./src; - cargoSha256 = "17qqaf3fpgxd8my721i8djkcc8y04xpi50la61s2pmr6lgdnj0wi"; + cargoSha256 = "0mf4jyhirkz3grcp2459b8rhw36xkx3rhpz6af0j4knyxb2w707n"; nativeBuildInputs = [ pkgs.gnumake @@ -32,8 +32,10 @@ let installPhase = '' mkdir -p $out $out/nix-support + cp ../build/runtime.bin $out/runtime.bin cp ../build/firmware/armv7-none-eabihf/release/runtime $out/runtime.elf - cp ../build/firmware/armv7-none-eabihf/release/szl $out/szl.elf + cp ../build/firmware/armv7-none-eabihf/debug/szl $out/szl.elf + echo file binary-dist $out/runtime.bin >> $out/nix-support/hydra-build-products echo file binary-dist $out/runtime.elf >> $out/nix-support/hydra-build-products echo file binary-dist $out/szl.elf >> $out/nix-support/hydra-build-products ''; @@ -60,6 +62,7 @@ let '' mkdir $out ln -s ${firmware}/szl.elf $out + ln -s ${firmware}/runtime.bin $out ln -s ${gateware}/top.bit $out ''; sd = pkgs.runCommand "zc706-${variant}-sd" @@ -72,12 +75,14 @@ let bifdir=`mktemp -d` cd $bifdir ln -s ${firmware}/szl.elf szl.elf + ln -s ${firmware}/runtime.elf runtime.elf ln -s ${gateware}/top.bit top.bit cat > boot.bif << EOF the_ROM_image: { [bootloader]szl.elf top.bit + runtime.elf } EOF mkdir $out $out/nix-support diff --git a/local_run.sh b/local_run.sh index 899fb44..9b9191b 100755 --- a/local_run.sh +++ b/local_run.sh @@ -4,8 +4,9 @@ set -e impure=0 load_bitstream=1 +board_host="192.168.1.52" -while getopts "h:il" opt; do +while getopts "ilb:" opt; do case "$opt" in \?) exit 1 ;; @@ -13,6 +14,8 @@ while getopts "h:il" opt; do ;; l) load_bitstream=0 ;; + b) board_host=$OPTARG + ;; esac done @@ -21,12 +24,16 @@ load_bitstream_cmd="" cd openocd if [ $impure -eq 1 ]; then if [ $load_bitstream -eq 1 ]; then - load_bitstream_cmd="pld load 0 ../build/gateware/top.bit;" + load_bitstream_cmd="-g ../build/gateware/top.bit" fi - openocd -f zc706.cfg -c "$load_bitstream_cmd load_image ../build/firmware/armv7-none-eabihf/release/szl; resume 0; exit" + openocd -f zc706.cfg -c "load_image ../build/firmware/armv7-none-eabihf/debug/szl; resume 0; exit" + sleep 5 + artiq_netboot $load_bitstream_cmd -f ../build/runtime.bin -b $board_host else if [ $load_bitstream -eq 1 ]; then - load_bitstream_cmd="pld load 0 ../result/top.bit;" + load_bitstream_cmd="-g ../result/top.bit" fi - openocd -f zc706.cfg -c "$load_bitstream_cmd load_image ../result/szl.elf; resume 0; exit" + openocd -f zc706.cfg -c "load_image ../result/szl.elf; resume 0; exit" + sleep 5 + artiq_netboot $load_bitstream_cmd -f ../result/runtime.bin -b $board_host fi diff --git a/remote_run.sh b/remote_run.sh index 55d3a1d..b781fa5 100755 --- a/remote_run.sh +++ b/remote_run.sh @@ -8,6 +8,7 @@ pure_dir="result" impure_dir="build" sshopts="" load_bitstream=1 +board_host="192.168.1.52" while getopts "h:id:o:l" opt; do case "$opt" in @@ -24,29 +25,32 @@ while getopts "h:id:o:l" opt; do ;; l) load_bitstream=0 ;; + b) board_host=$OPTARG + ;; esac done target_folder="/tmp/zynq-$USER" load_bitstream_cmd="" -if [ $load_bitstream -eq 1 ]; then - load_bitstream_cmd="pld load 0 top.bit;" -fi echo "Creating $target_folder..." ssh $sshopts $target_host "mkdir -p $target_folder" echo "Copying files..." rsync -e "ssh $sshopts" openocd/* $target_host:$target_folder if [ $impure -eq 1 ]; then - rsync -e "ssh $sshopts" $impure_dir/firmware/armv7-none-eabihf/release/szl $target_host:$target_folder/szl.elf if [ $load_bitstream -eq 1 ]; then - rsync -e "ssh $sshopts" $impure_dir/gateware/top.bit $target_host:$target_folder + load_bitstream_cmd="-g build/gateware/top.bit" fi + firmware="build/runtime.bin" + rsync -e "ssh $sshopts" $impure_dir/firmware/armv7-none-eabihf/debug/szl $target_host:$target_folder/szl.elf else - rsync -e "ssh $sshopts" -Lc $pure_dir/szl.elf $target_host:$target_folder if [ $load_bitstream -eq 1 ]; then - rsync -e "ssh $sshopts" -Lc $pure_dir/top.bit $target_host:$target_folder + load_bitstream_cmd="-g result/top.bit" fi + firmware="result/runtime.bin" + rsync -e "ssh $sshopts" -Lc $pure_dir/szl.elf $target_host:$target_folder fi echo "Programming board..." -ssh $sshopts $target_host "cd $target_folder; openocd -f zc706.cfg -c'$load_bitstream_cmd load_image szl.elf; resume 0; exit'" +ssh $sshopts $target_host "cd $target_folder; openocd -f zc706.cfg -c'load_image szl.elf; resume 0; exit'" +sleep 5 +artiq_netboot $load_bitstream_cmd -f $firmware -b $board_host -- 2.42.0 From a1cd56299d1c8faf081930423e63179b527dfea8 Mon Sep 17 00:00:00 2001 From: pca006132 Date: Tue, 1 Sep 2020 13:50:25 +0800 Subject: [PATCH 4/4] fixed runtime compilation error --- src/runtime/src/main.rs | 46 ++--------------------------------------- 1 file changed, 2 insertions(+), 44 deletions(-) diff --git a/src/runtime/src/main.rs b/src/runtime/src/main.rs index dd91c0b..49740d1 100644 --- a/src/runtime/src/main.rs +++ b/src/runtime/src/main.rs @@ -14,14 +14,13 @@ extern crate alloc; use core::{cmp, str}; use log::{info, warn, error}; -use libboard_zynq::{timer::GlobalTimer, devc, slcr, mpcore, gic}; +use libboard_zynq::{timer::GlobalTimer, mpcore, gic}; use libasync::{task, block_async}; use libsupport_zynq::ram; -use libregister::RegisterW; use nb; use void::Void; use embedded_hal::blocking::delay::DelayMs; -use libconfig::{Config, load_pl}; +use libconfig::Config; mod proto_core_io; mod proto_async; @@ -44,45 +43,6 @@ mod mgmt; mod analyzer; mod irq; -fn init_gateware() { - // Set up PS->PL clocks - slcr::RegisterBlock::unlocked(|slcr| { - // As we are touching the mux, the clock may glitch, so reset the PL. - slcr.fpga_rst_ctrl.write( - slcr::FpgaRstCtrl::zeroed() - .fpga0_out_rst(true) - .fpga1_out_rst(true) - .fpga2_out_rst(true) - .fpga3_out_rst(true) - ); - slcr.fpga0_clk_ctrl.write( - slcr::Fpga0ClkCtrl::zeroed() - .src_sel(slcr::PllSource::IoPll) - .divisor0(8) - .divisor1(1) - ); - slcr.fpga_rst_ctrl.write( - slcr::FpgaRstCtrl::zeroed() - ); - }); - if devc::DevC::new().is_done() { - info!("gateware already loaded"); - // Do not load again: assume that the gateware already present is - // what we want (e.g. gateware configured via JTAG before PS - // startup, or by FSBL). - // Make sure that the PL/PS interface is enabled (e.g. OpenOCD does not enable it). - slcr::RegisterBlock::unlocked(|slcr| { - slcr.init_postload_fpga(); - }); - } else { - // Load from SD card - match load_pl::load_bitstream_from_sd() { - Ok(_) => info!("Bitstream loaded successfully!"), - Err(e) => info!("Failure loading bitstream: {}", e), - } - } -} - fn identifier_read(buf: &mut [u8]) -> &str { unsafe { pl::csr::identifier::address_write(0); @@ -191,9 +151,7 @@ pub fn main_core0() { ram::init_alloc_core0(); gic::InterruptController::gic(mpcore::RegisterBlock::mpcore()).enable_interrupts(); - init_gateware(); info!("detected gateware: {}", identifier_read(&mut [0; 64])); - let cfg = match Config::new() { Ok(cfg) => cfg, Err(err) => { -- 2.42.0