mirror of
https://github.com/iceHtwoO/novaOS.git
synced 2026-04-16 20:22:26 +00:00
feat: support CLI args, by applying System V ABI concepts
This commit is contained in:
@@ -6,7 +6,7 @@ use crate::{
|
||||
configuration::memory_mapping::{APPLICATION_TRANSLATION_TABLE_VA, EL0_STACK_TOP},
|
||||
};
|
||||
use alloc::vec::Vec;
|
||||
use core::arch::asm;
|
||||
use core::{arch::asm, mem, ptr::write_volatile};
|
||||
use log::error;
|
||||
use nova_error::NovaError;
|
||||
use spin::Mutex;
|
||||
@@ -49,17 +49,42 @@ impl Application {
|
||||
/// `SPSR_EL1` -> Saved Program State Register (settings for `eret` behaviour)
|
||||
/// `SP_EL0` -> Stack Pointer Register (virtual_address of stack Pointer)
|
||||
/// `TTBR0_EL1` -> Translation Table base Register Register
|
||||
pub fn start(&self) {
|
||||
pub fn start(&self, args: Vec<&str>) {
|
||||
let size = args.len();
|
||||
|
||||
let mut sp = EL0_STACK_TOP;
|
||||
let mut arg_addresses = Vec::with_capacity(size);
|
||||
for value in args {
|
||||
sp -= value.len() * mem::size_of::<u8>();
|
||||
let pointer = sp as *mut u8;
|
||||
unsafe { core::ptr::copy(value.as_ptr(), pointer, value.len()) };
|
||||
arg_addresses.push(pointer);
|
||||
}
|
||||
sp = align_down(sp, 16);
|
||||
|
||||
let argv = sp;
|
||||
|
||||
for addr in arg_addresses {
|
||||
unsafe { write_volatile(sp as *mut *const u8, addr) };
|
||||
sp -= mem::size_of::<*const u8>();
|
||||
}
|
||||
|
||||
unsafe {
|
||||
asm!("msr ELR_EL1, {}", in(reg) self.start_addr);
|
||||
asm!("msr SPSR_EL1, {0:x}", in(reg) 0);
|
||||
asm!("msr SP_EL0, {0:x}", in(reg) EL0_STACK_TOP);
|
||||
asm!("msr SP_EL0, {0:x}", in(reg) sp);
|
||||
asm!("msr TTBR0_EL1, {}", in(reg) self.table_ptr as usize);
|
||||
asm!("", in("x0") size);
|
||||
asm!("", in("x1") argv);
|
||||
asm!("eret");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn align_down(sp: usize, align: usize) -> usize {
|
||||
sp & !(align - 1)
|
||||
}
|
||||
|
||||
struct AppManager {
|
||||
apps: Option<Vec<Application>>,
|
||||
}
|
||||
@@ -87,15 +112,13 @@ pub fn add_app(app: Application) -> Result<(), NovaError> {
|
||||
Err(NovaError::General("AppManager not initalized."))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start_app(index: usize) -> Result<(), NovaError> {
|
||||
if let Some(app) = APP_MANAGER
|
||||
pub fn start_app(index: usize, args: Vec<&str>) -> Result<(), NovaError> { if let Some(app) = APP_MANAGER
|
||||
.lock()
|
||||
.apps
|
||||
.as_mut()
|
||||
.and_then(|am| am.get(index))
|
||||
{
|
||||
app.start();
|
||||
app.start(args);
|
||||
unreachable!()
|
||||
} else {
|
||||
error!("Unable to start app due to invalid App ID.");
|
||||
|
||||
@@ -20,14 +20,15 @@ unsafe extern "C" fn rust_synchronous_interrupt_imm_lower_aarch64(frame: &mut Tr
|
||||
log_sync_exception();
|
||||
match esr.ec {
|
||||
0b100100 => {
|
||||
error!("Cause: Data Abort from a lower Exception level");
|
||||
error!("Data Abort from a lower Exception level");
|
||||
error!("Cause: {}", decode_data_abort(esr.iss as usize));
|
||||
}
|
||||
0b010101 => {
|
||||
debug!("Cause: SVC instruction execution in AArch64");
|
||||
debug!("SVC instruction execution in AArch64");
|
||||
return handle_svc(frame);
|
||||
}
|
||||
0b100010 => {
|
||||
error!("Cause: PC alignment fault.");
|
||||
error!("PC alignment fault.");
|
||||
}
|
||||
_ => {
|
||||
error!("Synchronous interrupt: Unknown Error Code: {:b}", esr.ec);
|
||||
@@ -39,8 +40,62 @@ unsafe extern "C" fn rust_synchronous_interrupt_imm_lower_aarch64(frame: &mut Tr
|
||||
0
|
||||
}
|
||||
|
||||
fn decode_data_abort(iss: usize) -> &'static str {
|
||||
match iss & 0b111111 {
|
||||
0b000000 => "Address size fault, level 0",
|
||||
0b000001 => "Address size fault, level 1",
|
||||
0b000010 => "Address size fault, level 2",
|
||||
0b000011 => "Address size fault, level 3",
|
||||
|
||||
0b000100 => "Translation fault, level 0",
|
||||
0b000101 => "Translation fault, level 1",
|
||||
0b000110 => "Translation fault, level 2",
|
||||
0b000111 => "Translation fault, level 3",
|
||||
|
||||
0b001001 => "Access flag fault, level 1",
|
||||
0b001010 => "Access flag fault, level 2",
|
||||
0b001011 => "Access flag fault, level 3",
|
||||
|
||||
0b001101 => "Permission fault, level 1",
|
||||
0b001110 => "Permission fault, level 2",
|
||||
0b001111 => "Permission fault, level 3",
|
||||
|
||||
0b010000 => "Synchronous External abort, not on translation table walk",
|
||||
0b011000 => {
|
||||
"Synchronous parity or ECC error on memory access, not on translation table walk"
|
||||
}
|
||||
|
||||
0b010100 => "Synchronous External abort, on translation table walk, level 0",
|
||||
0b010101 => "Synchronous External abort, on translation table walk, level 1",
|
||||
0b010110 => "Synchronous External abort, on translation table walk, level 2",
|
||||
0b010111 => "Synchronous External abort, on translation table walk, level 3",
|
||||
|
||||
0b011100 => "Synchronous parity or ECC error on translation table walk, level 0",
|
||||
0b011101 => "Synchronous parity or ECC error on translation table walk, level 1",
|
||||
0b011110 => "Synchronous parity or ECC error on translation table walk, level 2",
|
||||
0b011111 => "Synchronous parity or ECC error on translation table walk, level 3",
|
||||
|
||||
0b100001 => "Alignment fault",
|
||||
0b110000 => "TLB conflict abort",
|
||||
0b110001 => "Unsupported atomic hardware update fault",
|
||||
|
||||
0b110100 => "IMPLEMENTATION DEFINED fault (Lockdown)",
|
||||
0b110101 => "IMPLEMENTATION DEFINED fault (Unsupported Exclusive or Atomic access)",
|
||||
|
||||
0b111101 => "Section Domain Fault",
|
||||
0b111110 => "Page Domain Fault",
|
||||
|
||||
_ => "Reserved / Unknown",
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_svc(frame: &mut TrapFrame) -> usize {
|
||||
match frame.x8 {
|
||||
0 => {
|
||||
debug!("Program exited!");
|
||||
set_return_to_kernel_loop();
|
||||
0
|
||||
}
|
||||
67 => {
|
||||
let response = mailbox::read_soc_temp([0]).unwrap();
|
||||
response[1] as usize
|
||||
|
||||
56
src/main.rs
56
src/main.rs
@@ -10,7 +10,7 @@ use log::{debug, info};
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use alloc::{slice, vec::Vec};
|
||||
use nova::{
|
||||
aarch64::registers::{daif, read_id_aa64mmfr0_el1},
|
||||
application_manager::{add_app, Application},
|
||||
@@ -25,6 +25,7 @@ use nova::{
|
||||
},
|
||||
uart::uart_init,
|
||||
},
|
||||
pi3::timer::sleep_s,
|
||||
print, println,
|
||||
};
|
||||
|
||||
@@ -101,7 +102,6 @@ pub extern "C" fn kernel_main() {
|
||||
test_vector.push(i);
|
||||
}
|
||||
debug!("heap allocation test: {:?}", test_vector);
|
||||
|
||||
enable_irq_source(IRQSource::UartInt);
|
||||
|
||||
let app = Application::new(el0 as *const () as usize);
|
||||
@@ -109,18 +109,33 @@ pub extern "C" fn kernel_main() {
|
||||
|
||||
kernel_loop();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn kernel_loop() {
|
||||
daif::unmask_all();
|
||||
|
||||
#[allow(clippy::empty_loop)]
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn el0(input: usize) {
|
||||
pub unsafe extern "C" fn el0(argc: usize, argv: *const *const u8) {
|
||||
println!("Jumped into EL0");
|
||||
println!("num: {}", argc);
|
||||
println!("argv: {:?}", argv);
|
||||
|
||||
let raw_args = unsafe { slice::from_raw_parts(argv, argc) };
|
||||
let first_arg = raw_args
|
||||
.iter()
|
||||
.map(|&arg_ptr| {
|
||||
if arg_ptr.is_null() {
|
||||
return "";
|
||||
}
|
||||
|
||||
let c_str = unsafe { core::ffi::CStr::from_ptr(arg_ptr) };
|
||||
let str_slice = c_str.to_str().unwrap();
|
||||
str_slice
|
||||
})
|
||||
.next();
|
||||
|
||||
sleep_s(1);
|
||||
|
||||
// Set GPIO 26 to Input
|
||||
enable_irq_source(IRQSource::GpioInt0); //26 is on the first GPIO bank
|
||||
@@ -143,25 +158,30 @@ pub extern "C" fn el0(input: usize) {
|
||||
|
||||
let _temp = syscall(67);
|
||||
|
||||
println!("Calculting prime to: {}", input);
|
||||
if let Some(num) = first_arg.and_then(|val| val.parse::<usize>().ok()) {
|
||||
println!("Calculting prime to: {}", num);
|
||||
|
||||
for i in 3..input {
|
||||
let mut is_prime = true;
|
||||
for j in 3..i {
|
||||
if i == j {
|
||||
continue;
|
||||
for i in 3..num {
|
||||
let mut is_prime = true;
|
||||
for j in 3..i {
|
||||
if i == j {
|
||||
continue;
|
||||
}
|
||||
if i % j == 0 {
|
||||
is_prime = false;
|
||||
}
|
||||
}
|
||||
if i % j == 0 {
|
||||
is_prime = false;
|
||||
if is_prime {
|
||||
print!("{} ", i);
|
||||
}
|
||||
}
|
||||
if is_prime {
|
||||
print!("{} ", i);
|
||||
}
|
||||
println!("");
|
||||
} else {
|
||||
println!("Input NaN");
|
||||
}
|
||||
println!("");
|
||||
|
||||
blink_gpio(SpecificGpio::OnboardLed as u8, 500);
|
||||
syscall(0);
|
||||
}
|
||||
|
||||
fn cos(x: u32) -> f64 {
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
use core::arch::asm;
|
||||
|
||||
use alloc::string::String;
|
||||
|
||||
use crate::{
|
||||
@@ -44,15 +42,14 @@ impl Terminal {
|
||||
"temp" => {
|
||||
println!("{}", read_soc_temp([0]).unwrap()[1]);
|
||||
}
|
||||
"app" => unsafe {
|
||||
"app" => {
|
||||
if let Some(app_id) = parts.next().and_then(|a| a.parse::<usize>().ok()) {
|
||||
let i = 69;
|
||||
asm!("", in("x0") i);
|
||||
let _ = start_app(app_id);
|
||||
let args = parts.collect();
|
||||
let _ = start_app(app_id, args);
|
||||
} else {
|
||||
println!("App ID not set.");
|
||||
}
|
||||
},
|
||||
}
|
||||
_ => {
|
||||
println!("Unknown command: \"{}\"", self.input);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user