diff --git a/Cargo.lock b/Cargo.lock index 0730d60..bde8f32 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -212,9 +212,9 @@ dependencies = [ [[package]] name = "panic-halt" -version = "0.2.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de96540e0ebde571dc55c73d60ef407c653844e6f9a1e2fdbd40c07b9252d812" +checksum = "a513e167849a384b7f9b746e517604398518590a9142f4846a32e3c2a4de7b11" [[package]] name = "paste" @@ -308,7 +308,7 @@ dependencies = [ "log", "rcore-console", "riscv 0.11.1", - "sbi-spec 0.0.8", + "sbi-spec 0.0.8 (git+https://github.com/rustsbi/rustsbi?rev=4821073)", "sbi-testing 0.0.3-alpha.2 (git+https://github.com/rustsbi/rustsbi?rev=4821073)", "serde", "serde-device-tree", @@ -332,13 +332,14 @@ name = "rustsbi-prototyper" version = "0.0.0" dependencies = [ "aclint", + "cfg-if", "fast-trap", "log", "panic-halt", "riscv 0.11.1", "riscv-decode", "rustsbi", - "sbi-spec 0.0.7", + "sbi-spec 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde", "serde-device-tree", "sifive-test-device", @@ -383,7 +384,7 @@ name = "sbi-rt" version = "0.0.3" source = "git+https://github.com/rustsbi/rustsbi?rev=4821073#4821073b56a7223781c11a49aba743785d89d3ea" dependencies = [ - "sbi-spec 0.0.8", + "sbi-spec 0.0.8 (git+https://github.com/rustsbi/rustsbi?rev=4821073)", ] [[package]] @@ -392,6 +393,12 @@ version = "0.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e36312fb5ddc10d08ecdc65187402baba4ac34585cb9d1b78522ae2358d890" +[[package]] +name = "sbi-spec" +version = "0.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8309630ab2b300d4fe52b6757e53a7cbb6672f55aa08b50e28b1952c06dd994d" + [[package]] name = "sbi-spec" version = "0.0.8" @@ -420,7 +427,7 @@ dependencies = [ "log", "riscv 0.12.1", "sbi-rt 0.0.3 (git+https://github.com/rustsbi/rustsbi?rev=4821073)", - "sbi-spec 0.0.8", + "sbi-spec 0.0.8 (git+https://github.com/rustsbi/rustsbi?rev=4821073)", ] [[package]] diff --git a/prototyper/Cargo.toml b/prototyper/Cargo.toml index c8ea916..a1d8e3d 100644 --- a/prototyper/Cargo.toml +++ b/prototyper/Cargo.toml @@ -11,10 +11,10 @@ forced-target = "riscv64imac-unknown-none-elf" [dependencies] aclint = "0.0.0" log = "0.4.21" -panic-halt = "0.2.0" +panic-halt = "1.0.0" riscv = "0.11.1" rustsbi = { version = "0.4.0", features = ["machine"] } -sbi-spec = { version = "0.0.7", features = ["legacy"] } +sbi-spec = { version = "0.0.8", features = ["legacy"] } serde = { version = "1.0.202", default-features = false, features = ["derive"] } serde-device-tree = { git = "https://github.com/rustsbi/serde-device-tree", default-features = false } sifive-test-device = "0.0.0" @@ -24,6 +24,7 @@ riscv-decode = "0.2.1" fast-trap = { version = "0.0.1", features = ["riscv-m"] } uart_xilinx = { git = "https://github.com/duskmoon314/uart-rs/" } xuantie-riscv = { git= "https://github.com/rustsbi/xuantie" } +cfg-if = "1.0.0" [[bin]] name = "rustsbi-prototyper" @@ -33,4 +34,5 @@ bench = false [features] nemu = [] payload = [] +jump = [] fdt = [] diff --git a/prototyper/src/cfg.rs b/prototyper/src/cfg.rs new file mode 100644 index 0000000..a5036db --- /dev/null +++ b/prototyper/src/cfg.rs @@ -0,0 +1,13 @@ +/// Maximum number of supported harts. +pub const NUM_HART_MAX: usize = 8; +/// Stack size per hart (hardware thread) in bytes. +pub const LEN_STACK_PER_HART: usize = 16 * 1024; +/// Page size +pub const PAGE_SIZE: usize = 4096; +/// TLB_FLUSH_LIMIT defines the TLB refresh range limit. +/// If the TLB refresh range is greater than TLB_FLUSH_LIMIT, the entire TLB is refreshed. +pub const TLB_FLUSH_LIMIT: usize = 4 * PAGE_SIZE; + + +#[cfg(feature = "jump")] +pub const JUMP_ADDRESS: usize = 0x80200000; diff --git a/prototyper/src/dt.rs b/prototyper/src/devicetree.rs similarity index 100% rename from prototyper/src/dt.rs rename to prototyper/src/devicetree.rs diff --git a/prototyper/src/fail.rs b/prototyper/src/fail.rs index 14ccad7..f1536c5 100644 --- a/prototyper/src/fail.rs +++ b/prototyper/src/fail.rs @@ -1,19 +1,14 @@ use serde_device_tree::Dtb; -use crate::dt; +use crate::devicetree; -#[cfg(not(feature = "payload"))] -use crate::firmware::dynamic; -#[cfg(not(feature = "payload"))] -use crate::sbi::reset; -#[cfg(not(feature = "payload"))] -use riscv::register::mstatus; +#[cfg(all(feature = "payload", feature = "jump"))] +compile_error!("feature \"payload\" and feature \"jump\" cannot be enabled at the same time"); -// TODO: Need a better way to handle device tree parsing errors /// Handles device tree format parsing errors by logging and resetting. #[cold] -pub fn device_tree_format(_err: dt::ParseDeviceTreeError) -> Dtb { +pub fn device_tree_format(_err: devicetree::ParseDeviceTreeError) -> Dtb { loop { core::hint::spin_loop() } @@ -28,72 +23,78 @@ pub fn device_tree_deserialize_root<'a>( } } -/// Handles invalid dynamic information data by logging details and resetting. -#[cold] -#[cfg(not(feature = "payload"))] -pub fn invalid_dynamic_data(err: dynamic::DynamicError) -> (mstatus::MPP, usize) { - error!("Invalid data in dynamic information:"); - if err.invalid_mpp { - error!("* dynamic information contains invalid privilege mode"); - } - if err.invalid_next_addr { - error!("* dynamic information contains invalid next jump address"); - } - let explain_next_mode = match err.bad_info.next_mode { - 3 => "Machine", - 1 => "Supervisor", - 0 => "User", - _ => "Invalid", - }; - error!( - "@ help: dynamic information contains magic value 0x{:x}, version {}, next jump address 0x{:x}, next privilege mode {} ({}), options {:x}, boot hart ID {}", - err.bad_info.magic, err.bad_info.version, err.bad_info.next_addr, err.bad_info.next_mode, explain_next_mode, err.bad_info.options, err.bad_info.boot_hart - ); - reset::fail() -} - -/// Handles case where dynamic information is not available by logging details and resetting. -#[cold] -#[cfg(not(feature = "payload"))] -pub fn no_dynamic_info_available(err: dynamic::DynamicReadError) -> dynamic::DynamicInfo { - if let Some(bad_paddr) = err.bad_paddr { - error!( - "No dynamic information available at address 0x{:x}", - bad_paddr - ); +cfg_if::cfg_if! { + if #[cfg(feature = "payload")] { + } else if #[cfg(feature = "jump")] { } else { - error!("No valid dynamic information available:"); - if let Some(bad_magic) = err.bad_magic { + use crate::firmware::dynamic; + use crate::sbi::reset; + use riscv::register::mstatus; + /// Handles invalid dynamic information data by logging details and resetting. + #[cold] + pub fn invalid_dynamic_data(err: dynamic::DynamicError) -> (mstatus::MPP, usize) { + error!("Invalid data in dynamic information:"); + if err.invalid_mpp { + error!("* dynamic information contains invalid privilege mode"); + } + if err.invalid_next_addr { + error!("* dynamic information contains invalid next jump address"); + } + let explain_next_mode = match err.bad_info.next_mode { + 3 => "Machine", + 1 => "Supervisor", + 0 => "User", + _ => "Invalid", + }; error!( - "* tried to identify dynamic information, but found invalid magic number 0x{:x}", - bad_magic + "@ help: dynamic information contains magic value 0x{:x}, version {}, next jump address 0x{:x}, next privilege mode {} ({}), options {:x}, boot hart ID {}", + err.bad_info.magic, err.bad_info.version, err.bad_info.next_addr, err.bad_info.next_mode, explain_next_mode, err.bad_info.options, err.bad_info.boot_hart ); + reset::fail() } - if let Some(bad_version) = err.bad_version { - error!("* tries to identify version of dynamic information, but the version number {} is not supported", bad_version); - } - if err.bad_magic.is_none() { - error!("@ help: magic number is valid") - } - if err.bad_version.is_none() { - error!("@ help: dynamic information version is valid") + + /// Handles case where dynamic information is not available by logging details and resetting. + #[cold] + pub fn no_dynamic_info_available(err: dynamic::DynamicReadError) -> dynamic::DynamicInfo { + if let Some(bad_paddr) = err.bad_paddr { + error!( + "No dynamic information available at address 0x{:x}", + bad_paddr + ); + } else { + error!("No valid dynamic information available:"); + if let Some(bad_magic) = err.bad_magic { + error!( + "* tried to identify dynamic information, but found invalid magic number 0x{:x}", + bad_magic + ); + } + if let Some(bad_version) = err.bad_version { + error!("* tries to identify version of dynamic information, but the version number {} is not supported", bad_version); + } + if err.bad_magic.is_none() { + error!("@ help: magic number is valid") + } + if err.bad_version.is_none() { + error!("@ help: dynamic information version is valid") + } + } + reset::fail() } - } - reset::fail() -} -/// Fallback function that returns default dynamic info with boot_hart set to MAX. -/// -/// Used when dynamic info read fails but execution should continue. -#[cold] -#[cfg(not(feature = "payload"))] -pub fn use_lottery(_err: dynamic::DynamicReadError) -> dynamic::DynamicInfo { - dynamic::DynamicInfo { - magic: 0, - version: 0, - next_addr: 0, - next_mode: 0, - options: 0, - boot_hart: usize::MAX, + /// Fallback function that returns default dynamic info with boot_hart set to MAX. + /// + /// Used when dynamic info read fails but execution should continue. + #[cold] + pub fn use_lottery(_err: dynamic::DynamicReadError) -> dynamic::DynamicInfo { + dynamic::DynamicInfo { + magic: 0, + version: 0, + next_addr: 0, + next_mode: 0, + options: 0, + boot_hart: usize::MAX, + } + } } } diff --git a/prototyper/src/firmware/dynamic.rs b/prototyper/src/firmware/dynamic.rs index 4b739d4..12b671c 100644 --- a/prototyper/src/firmware/dynamic.rs +++ b/prototyper/src/firmware/dynamic.rs @@ -5,7 +5,7 @@ use core::sync::atomic::{AtomicBool, Ordering}; use super::BootInfo; use crate::fail; -use crate::riscv_spec::current_hartid; +use crate::riscv::current_hartid; use riscv::register::mstatus; diff --git a/prototyper/src/firmware/jump.rs b/prototyper/src/firmware/jump.rs new file mode 100644 index 0000000..788cecd --- /dev/null +++ b/prototyper/src/firmware/jump.rs @@ -0,0 +1,20 @@ +use core::sync::atomic::{AtomicBool, Ordering}; +use riscv::register::mstatus; + +use super::BootInfo; +use crate::cfg::JUMP_ADDRESS; + +/// Determine whether the current hart is boot hart. +/// +/// Return true if the current hart is boot hart. +pub fn is_boot_hart(_nonstandard_a2: usize) -> bool { + static GENESIS: AtomicBool = AtomicBool::new(true); + GENESIS.swap(false, Ordering::AcqRel) +} + +pub fn get_boot_info(_nonstandard_a2: usize) -> BootInfo { + BootInfo { + next_address: JUMP_ADDRESS, + mpp: mstatus::MPP::Supervisor, + } +} diff --git a/prototyper/src/firmware/mod.rs b/prototyper/src/firmware/mod.rs index b0a17a6..62a7868 100644 --- a/prototyper/src/firmware/mod.rs +++ b/prototyper/src/firmware/mod.rs @@ -1,7 +1,15 @@ -#[cfg(not(feature = "payload"))] -pub mod dynamic; -#[cfg(feature = "payload")] -pub mod payload; +cfg_if::cfg_if! { + if #[cfg(feature = "payload")] { + pub mod payload; + pub use payload::{get_boot_info, is_boot_hart}; + } else if #[cfg(feature = "jump")] { + pub mod jump; + pub use jump::{get_boot_info, is_boot_hart}; + } else { + pub mod dynamic; + pub use dynamic::{get_boot_info, is_boot_hart}; + } +} use core::arch::asm; use core::ops::Range; @@ -34,10 +42,6 @@ fn get_fdt_address() -> usize { raw_fdt as usize } -#[cfg(not(feature = "payload"))] -pub use dynamic::{get_boot_info, is_boot_hart}; -#[cfg(feature = "payload")] -pub use payload::{get_boot_info, is_boot_hart}; /// Gets boot hart information based on opaque and nonstandard_a2 parameters. /// diff --git a/prototyper/src/main.rs b/prototyper/src/main.rs index 39fec02..c16902a 100644 --- a/prototyper/src/main.rs +++ b/prototyper/src/main.rs @@ -9,17 +9,19 @@ extern crate log; #[macro_use] mod macros; -mod dt; +mod cfg; +mod devicetree; mod fail; mod firmware; mod platform; -mod riscv_spec; +mod riscv; mod sbi; use core::arch::asm; use crate::platform::PLATFORM; -use crate::riscv_spec::{current_hartid, menvcfg}; +use crate::riscv::csr::menvcfg; +use crate::riscv::current_hartid; use crate::sbi::extensions::{ hart_extension_probe, hart_privileged_version, privileged_version_detection, Extension, PrivilegedVersion, @@ -98,7 +100,7 @@ extern "C" fn rust_main(_hart_id: usize, opaque: usize, nonstandard_a2: usize) { asm!("csrw medeleg, {}", in(reg) !0); asm!("csrw mcounteren, {}", in(reg) !0); asm!("csrw scounteren, {}", in(reg) !0); - use riscv::register::{medeleg, mtvec}; + use ::riscv::register::{medeleg, mtvec}; // Keep supervisor environment calls and illegal instructions in M-mode. medeleg::clear_supervisor_env_call(); medeleg::clear_illegal_instruction(); @@ -199,8 +201,8 @@ unsafe extern "C" fn relocation_update() { #[panic_handler] fn panic(info: &core::panic::PanicInfo) -> ! { - use riscv::register::*; - error!("Hart {} {info}", riscv::register::mhartid::read()); + use ::riscv::register::*; + error!("Hart {} {info}", current_hartid()); error!("-----------------------------"); error!("mcause: {:?}", mcause::read().cause()); error!("mepc: {:#018x}", mepc::read()); diff --git a/prototyper/src/platform/mod.rs b/prototyper/src/platform/mod.rs index e5a6f8b..6b55740 100644 --- a/prototyper/src/platform/mod.rs +++ b/prototyper/src/platform/mod.rs @@ -1,3 +1,5 @@ +use crate::cfg::NUM_HART_MAX; +use crate::devicetree::*; use crate::fail; use crate::platform::clint::{MachineClint, MachineClintType, CLINT_COMPATIBLE}; use crate::platform::console::{ @@ -11,10 +13,9 @@ use crate::sbi::hsm::SbiHsm; use crate::sbi::ipi::SbiIpi; use crate::sbi::logger; use crate::sbi::reset::SbiReset; +use crate::sbi::rfence::SbiRFence; use crate::sbi::trap_stack; -use crate::sbi::trap_stack::NUM_HART_MAX; use crate::sbi::SBI; -use crate::{dt, sbi::rfence::SbiRFence}; use core::{ fmt::{Display, Formatter, Result}, ops::Range, @@ -40,7 +41,7 @@ impl Display for StringInline { } } -type CpuEnableList = [bool; trap_stack::NUM_HART_MAX]; +type CpuEnableList = [bool; NUM_HART_MAX]; pub struct BoardInfo { pub memory_range: Option>, @@ -90,17 +91,17 @@ impl Platform { } fn info_init(&mut self, fdt_address: usize) { - let dtb = dt::parse_device_tree(fdt_address).unwrap_or_else(fail::device_tree_format); + let dtb = parse_device_tree(fdt_address).unwrap_or_else(fail::device_tree_format); let dtb = dtb.share(); let root: serde_device_tree::buildin::Node = serde_device_tree::from_raw_mut(&dtb) .unwrap_or_else(fail::device_tree_deserialize_root); - let tree: dt::Tree = root.deserialize(); + let tree: Tree = root.deserialize(); // Get console device info for console_path in tree.chosen.stdout_path.iter() { if let Some(node) = root.find(console_path) { - let info = dt::get_compatible_and_range(&node); + let info = get_compatible_and_range(&node); let result = info.is_some_and(|info| { let (compatible, regs) = info; for device_id in compatible.iter() { @@ -128,7 +129,7 @@ impl Platform { // Get ipi and reset device info let mut find_device = |node: &serde_device_tree::buildin::Node| { - let info = dt::get_compatible_and_range(node); + let info = get_compatible_and_range(node); if let Some(info) = info { let (compatible, regs) = info; let base_address = regs.start; @@ -157,7 +158,7 @@ impl Platform { .iter() .next() .unwrap() - .deserialize::() + .deserialize::() .reg; let memory_range = memory_reg.iter().next().unwrap().0; self.info.memory_range = Some(memory_range); @@ -180,9 +181,8 @@ impl Platform { extensions::init(&tree.cpus.cpu); // Find which hart is enabled by fdt - let mut cpu_list: CpuEnableList = [false; trap_stack::NUM_HART_MAX]; + let mut cpu_list: CpuEnableList = [false; NUM_HART_MAX]; for cpu_iter in tree.cpus.cpu.iter() { - use dt::Cpu; let cpu = cpu_iter.deserialize::(); let hart_id = cpu.reg.iter().next().unwrap().0.start; if let Some(x) = cpu_list.get_mut(hart_id) { @@ -281,7 +281,7 @@ impl Platform { ); if let Some(cpu_enabled) = &self.info.cpu_enabled { - let mut enabled_harts = [0; trap_stack::NUM_HART_MAX]; + let mut enabled_harts = [0; NUM_HART_MAX]; let mut count = 0; for (i, &enabled) in cpu_enabled.iter().enumerate() { if enabled { diff --git a/prototyper/src/riscv_spec.rs b/prototyper/src/riscv/csr.rs similarity index 93% rename from prototyper/src/riscv_spec.rs rename to prototyper/src/riscv/csr.rs index 3180c24..32c0c3f 100644 --- a/prototyper/src/riscv_spec.rs +++ b/prototyper/src/riscv/csr.rs @@ -61,9 +61,3 @@ pub mod stimecmp { } } } - -/// Returns the current hart (hardware thread) ID. -#[inline] -pub fn current_hartid() -> usize { - riscv::register::mhartid::read() -} diff --git a/prototyper/src/riscv/mod.rs b/prototyper/src/riscv/mod.rs new file mode 100644 index 0000000..b346407 --- /dev/null +++ b/prototyper/src/riscv/mod.rs @@ -0,0 +1,7 @@ +pub mod csr; + +/// Returns the current hart (hardware thread) ID. +#[inline] +pub fn current_hartid() -> usize { + riscv::register::mhartid::read() +} diff --git a/prototyper/src/sbi/extensions.rs b/prototyper/src/sbi/extensions.rs index 510d593..864c80a 100644 --- a/prototyper/src/sbi/extensions.rs +++ b/prototyper/src/sbi/extensions.rs @@ -1,6 +1,6 @@ use serde_device_tree::buildin::NodeSeq; -use crate::riscv_spec::current_hartid; +use crate::riscv::current_hartid; use crate::sbi::trap_stack::ROOT_STACK; pub struct HartFeatures { @@ -57,7 +57,7 @@ pub fn hart_privileged_version(hart_id: usize) -> PrivilegedVersion { #[cfg(not(feature = "nemu"))] pub fn init(cpus: &NodeSeq) { - use crate::dt::Cpu; + use crate::devicetree::Cpu; for cpu_iter in cpus.iter() { let cpu = cpu_iter.deserialize::(); let hart_id = cpu.reg.iter().next().unwrap().0.start; diff --git a/prototyper/src/sbi/hsm.rs b/prototyper/src/sbi/hsm.rs index ccf7dd6..ccde5fd 100644 --- a/prototyper/src/sbi/hsm.rs +++ b/prototyper/src/sbi/hsm.rs @@ -7,7 +7,7 @@ use riscv::register::mstatus::MPP; use rustsbi::{spec::hsm::hart_state, SbiRet}; use crate::platform::PLATFORM; -use crate::riscv_spec::current_hartid; +use crate::riscv::current_hartid; use crate::sbi::hart_context::NextStage; use crate::sbi::trap_stack::ROOT_STACK; diff --git a/prototyper/src/sbi/ipi.rs b/prototyper/src/sbi/ipi.rs index f8b359e..a10e647 100644 --- a/prototyper/src/sbi/ipi.rs +++ b/prototyper/src/sbi/ipi.rs @@ -1,5 +1,6 @@ use crate::platform::PLATFORM; -use crate::riscv_spec::{current_hartid, stimecmp}; +use crate::riscv::csr::stimecmp; +use crate::riscv::current_hartid; use crate::sbi::extensions::{hart_extension_probe, Extension}; use crate::sbi::hsm::remote_hsm; use crate::sbi::rfence; diff --git a/prototyper/src/sbi/rfence.rs b/prototyper/src/sbi/rfence.rs index 6eef14d..5f46aa8 100644 --- a/prototyper/src/sbi/rfence.rs +++ b/prototyper/src/sbi/rfence.rs @@ -2,7 +2,7 @@ use rustsbi::{HartMask, SbiRet}; use spin::Mutex; use crate::platform::PLATFORM; -use crate::riscv_spec::current_hartid; +use crate::riscv::current_hartid; use crate::sbi::fifo::{Fifo, FifoError}; use crate::sbi::trap; use crate::sbi::trap_stack::ROOT_STACK; diff --git a/prototyper/src/sbi/trap.rs b/prototyper/src/sbi/trap.rs index b2acad2..da8bedf 100644 --- a/prototyper/src/sbi/trap.rs +++ b/prototyper/src/sbi/trap.rs @@ -6,18 +6,15 @@ use riscv::register::{ }; use rustsbi::RustSBI; +use crate::cfg::{PAGE_SIZE, TLB_FLUSH_LIMIT}; use crate::platform::PLATFORM; -use crate::riscv_spec::{current_hartid, CSR_TIME, CSR_TIMEH}; +use crate::riscv::csr::{CSR_TIME, CSR_TIMEH}; +use crate::riscv::current_hartid; use crate::sbi::console; use crate::sbi::hsm::local_hsm; use crate::sbi::ipi; use crate::sbi::rfence::{self, local_rfence, RFenceType}; -// Constants for page and TLB management -const PAGE_SIZE: usize = 4096; -// TODO: `TLB_FLUSH_LIMIT` is a platform-dependent parameter -const TLB_FLUSH_LIMIT: usize = 4 * PAGE_SIZE; - /// Trap vector table entry point. Maps different trap types to their handlers. #[naked] pub(crate) unsafe extern "C" fn trap_vec() { diff --git a/prototyper/src/sbi/trap_stack.rs b/prototyper/src/sbi/trap_stack.rs index c3b4808..d31aa8e 100644 --- a/prototyper/src/sbi/trap_stack.rs +++ b/prototyper/src/sbi/trap_stack.rs @@ -1,13 +1,9 @@ -use crate::riscv_spec::current_hartid; +use crate::riscv::current_hartid; use crate::sbi::hart_context::HartContext; use crate::sbi::trap::fast_handler; use core::mem::forget; use fast_trap::FreeTrapStack; - -/// Stack size per hart (hardware thread) in bytes. -const LEN_STACK_PER_HART: usize = 16 * 1024; -/// Maximum number of supported harts. -pub const NUM_HART_MAX: usize = 8; +use crate::cfg::{NUM_HART_MAX, LEN_STACK_PER_HART}; /// Root stack array for all harts, placed in uninitialized BSS section. #[link_section = ".bss.uninit"] diff --git a/xtask/src/prototyper.rs b/xtask/src/prototyper.rs index 870e385..ef03406 100644 --- a/xtask/src/prototyper.rs +++ b/xtask/src/prototyper.rs @@ -19,6 +19,9 @@ pub struct PrototyperArg { #[clap(long, env = "PROTOTYPER_PAYLOAD_PATH")] pub payload: Option, + #[clap(long)] + pub jump: bool, + #[clap(long, default_value = "INFO")] pub log_level: String, } @@ -29,6 +32,7 @@ pub fn run(arg: &PrototyperArg) -> Option { let arch = "riscv64imac-unknown-none-elf"; let fdt = arg.fdt.clone(); let payload = arg.payload.clone(); + let jump = arg.jump; let current_dir = env::current_dir(); let target_dir = current_dir .as_ref() @@ -52,6 +56,9 @@ pub fn run(arg: &PrototyperArg) -> Option { cargo.env("PROTOTYPER_PAYLOAD_PATH", payload.as_ref().unwrap()); cargo.features(["payload".to_string()]) }) + .optional(jump, |cargo| { + cargo.features(["jump".to_string()]) + }) .env("RUST_LOG", &arg.log_level) .release() .status() @@ -82,6 +89,18 @@ pub fn run(arg: &PrototyperArg) -> Option { target_dir.join("rustsbi-prototyper-payload.bin"), ) .ok()?; + } else if arg.jump { + info!("Copy for jump mode"); + fs::copy( + target_dir.join("rustsbi-prototyper"), + target_dir.join("rustsbi-prototyper-jump.elf"), + ) + .ok()?; + fs::copy( + target_dir.join("rustsbi-prototyper.bin"), + target_dir.join("rustsbi-prototyper-jump.bin"), + ) + .ok()?; } else { info!("Copy for dynamic mode"); fs::copy( @@ -94,6 +113,7 @@ pub fn run(arg: &PrototyperArg) -> Option { target_dir.join("rustsbi-prototyper-dynamic.bin"), ) .ok()?; + } Some(exit_status)