From dd5899a74d41eeee4b41e80d16d03c4356efe5f6 Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Tue, 14 Jun 2022 22:43:33 +0200 Subject: [PATCH] Read command line args from userspace programs (#351) * Read command line args from userspace programs * Use Stop syscall to debug pointers from userpace * Fix address translation system * Update binaries * Move print to bin * Add hardcoded alias system * Strip debug from binaries * Build userspace binaries before running tests * Save all the args in args including the command invocation name * Move sleep command to /bin * Rebuild binaries --- .github/workflows/rust.yml | 1 + Makefile | 1 + dsk/bin/clear | Bin 11184 -> 1000 bytes dsk/bin/halt | Bin 11416 -> 1168 bytes dsk/bin/hello | Bin 11200 -> 1016 bytes dsk/bin/print | Bin 0 -> 1112 bytes dsk/bin/reboot | Bin 11424 -> 1168 bytes dsk/bin/sleep | Bin 12216 -> 24608 bytes src/api/process.rs | 4 +- src/api/syscall.rs | 18 ++++--- src/bin/print.rs | 30 ++++++++++++ src/bin/sleep.rs | 28 +++++++++++ src/sys/allocator.rs | 10 ++-- src/sys/idt.rs | 3 +- src/sys/process.rs | 93 ++++++++++++++++++++++++------------- src/sys/syscall/mod.rs | 30 +++++++++--- src/sys/syscall/service.rs | 8 ++-- src/usr/install.rs | 2 + src/usr/mod.rs | 2 - src/usr/print.rs | 13 ------ src/usr/shell.rs | 18 +++---- src/usr/sleep.rs | 12 ----- 22 files changed, 184 insertions(+), 89 deletions(-) create mode 100644 dsk/bin/print create mode 100644 src/bin/print.rs create mode 100644 src/bin/sleep.rs delete mode 100644 src/usr/print.rs delete mode 100644 src/usr/sleep.rs diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index d990497..826b8ef 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -17,4 +17,5 @@ jobs: - run: sudo apt-get -qqy update - run: sudo apt-get -qqy install qemu-system-x86 - run: make + - run: make user-rust - run: make test diff --git a/Makefile b/Makefile index 3cf4921..068c057 100644 --- a/Makefile +++ b/Makefile @@ -28,6 +28,7 @@ user-rust: -C relocation-model=static basename -s .rs src/bin/*.rs | xargs -I {} \ cp target/x86_64-moros/release/{} dsk/bin/{} + strip dsk/bin/* bin = target/x86_64-moros/release/bootimage-moros.bin img = disk.img diff --git a/dsk/bin/clear b/dsk/bin/clear index 034d10fcb739677d343a1b38663b5d894da6a6c6..ff53afd2f63c3f881c87a2417111d14ea3ee01cc 100644 GIT binary patch delta 106 zcmdlG{(^mihPVb30~|OoSTL|MI54m?ux+$o&&a7)oKaj-RFar9Nz7n!k)|CBP$l=| xjhgn1!jnI0+D|Uf;+SlqWx=RDxlqfV(QxucAjvq{P+OeyEhEHGtH~EN`HH;CHP0jd7XJgu^~;$vTSWqsU%gno#)=0+`IR7 z?yS3Oltw6pKxZPf}TyM!k;(C22c zQCvsc*A`ah?-H$IrA}|Ds;<*bWmwUMDtBdRRjXzCt*Ts|im5VN@do-kUgg*QtkbzN zOw?&zZr?k3tlEpKa`8l~h^*5aiY+1PwC>w}DyR1Ge_f{UGv}u7Gwv{Eg_xMW=8k&5 zZ>lPqc<@VNVr6P#`i700>U~jJ`+lK1cp& z-vfRUxH{dq{{Ip9-++GzeCs4%{|?}H0^bij1%3qhcYr?){6*krfS&{Y9`KEHU323< z4g7ZCp96kB@CSe&2mTE3Ujly%_y@pmrfG~D2Lt##@D%t_;6DQX0`Ol0KM#D8ZdTlW z%>eg--wXT@@NWQr68Q7LUju#)_$A;s(oK{bhfe|D349;$6!=5H9|L{@_$lCj0RArU z$&LItYzJ-vp93BMUj_bM;3t8<4E#;te+RyS9*DT}VFtJbd=7X3{0Q(TfIkcTSHRx} zei``o&HOk>;CBOG0Dcts4}m`q{0#87f&UBmt@KdK9rxY97l1zu{BhvV0Dl$upMYNk ze%BfuXAeggQ6Qc z3;cfIUjzP4;750e-!w0 zz<&q)J>WNO<@Z+tzZdv2@E-twiF_-ai7#(y(Jxa%Y%e~AxKMfhd+4o|U#$GODxMx= z%0OFHc|3;IdB6K7Ypgq9~OxzM6Pzn?79%4oHp2O*`MQJ$4+Wh$ax5@ecT z=rXl!=QGj568+?8^tvmql^^m(VJ1_rC;EeIFwz1qjgllziYSLelS6|=UTrp3XO(SC za-kN71{=zEfUSV-mCH5dap;RM7$uIa#nSiF*z&8v=hR|jZB|{;>xO;Jj%4T?L0r^o zSPbfn8Jw9MvXN|+HdkCS$hE_DoU4$l&tcl&M#p2~d@`kL)WGICQYOF7dn9~pNI^UVWSLnk+W5) z$%oBwQ3mW4or1&eqGot;8ilq|4SrAkpE+*#x}&@u^m>CR$OoC`TDoP0wq69OY5S@{ z>b7*%AWN)xPMe-|T*vV3)UKXMc-46}cs6+kElM_;59VWi5%hbS9mi=Zt?~pjn?y5j zBh299tY#cnR5rs5h8SZSph>3DIfj@von}F|NnVqDvAp`A78*%lqms*oY!n9rCY z9>^2TN<2F?gYt30YLaY{CzkTm8wS}Z(PV6!Ax#|B1YAtInxXrtlx{iU(wU@Y;lkS1g2{oEyn@~eLHb9Nv*Z^O&zjC)MewDK5R^X0SM-iQnayjefiQ#s1pGG!~Ju{Sk z8U^NF(H`aW1&l9dCoA2YN*Pj5=$A0xG=m`aZ7TJDTIe;a;@wGlov2vUi-Kx7pfYIr z&+mHWW)WMh776`Zc1`(sqE&ePUL^e+YRy8gwX9h_PFt#}y8Yoqi?-rV BI`{wp diff --git a/dsk/bin/halt b/dsk/bin/halt index aad42b0e6b3ac680270ec42d04133ad6b8c5235e..65e3a9075c3ce62726c66a4c28e641535cf2f822 100644 GIT binary patch delta 114 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 KRvp0V^8W!n1U?4< diff --git a/dsk/bin/print b/dsk/bin/print new file mode 100644 index 0000000000000000000000000000000000000000..6920fbcb77e8d6792f584493174dfaa708de5ced GIT binary patch literal 1112 zcmbtT%}X0m5T6%6se%zb2nv0kg~d>jYN5>om8Wbl^*fjt(q?5#iNaYKN3O!QVd%f6ZU&HUcXB(pz9?Xd`BKoWtEfL^(sYbdTy zfSrgjl#0W9Xi#SpG^z)nUSnZA4qO|gyUf+3o5M6+19?^9#tikQ;gN=D7)H23y=4=p zK1uI|X+WBI$xA;^B<{D*O!q>#qAi^LCmG*!mQ(wJ7Uu zZEB_&YVQ{FVouD8nQ2-28}TyZ!JQ25?d>0rvQ+63``G<$=d#uIc2l#;3XUd*uKah2 z;Bvfl!sJ%*kKF1w#Kh}KbtHx!iWk~FSYRCXbYM^gZcjoq^^9_b#vT_%T4cnM$lfRy zlDkMa+elSTwIp}(mpR*z!IAuZE{|?L$>3N9zfu+Z+sb#x8|Jn>!eawgzts<572Trm z`MED(d8_%Hp99Nrv&&wt;AGvrSM|X1oi!hV}4($v1y|4H#<2vM;`aRmK9<(Qf^eF>VY4>QqX=k4I+Yrp> mL3D^2zWNhh$b=aj=c^Udmad67`gOGl#?Bc2@T(Z{34Q{@?sQ}T literal 0 HcmV?d00001 diff --git a/dsk/bin/reboot b/dsk/bin/reboot index 9a2dc21c769baeb307c084383c54b7edade6bdec..c83f324afb93e0884acf0fb5f895a61c58fcb33b 100644 GIT binary patch delta 108 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 literal 12216 zcmbuFYpfkr7036z6nddNYD=&}O^)%H_DiSpepDnCZ}EoIa*K#yh^O=HIrO}oGpFq> zC6;K6{lG(ni1LNV7a9^FXhPBOh)obv6oU`qCx}95#2^MjObA@pp4roK?^*xb7xy>PV>GQOJm zm0Z+$9gE%6PWJPEO`U#`=KZkSNb`JFTI87Skex8PLJB+$%BOWB_D37;Bo&MHQ zH%*6HK6+=WQMyv6Tb{Oz@6;9Ne7^3R6kJ-Wh#$IMOdVW1b;X6NXYNt4R#j#8)<-Wc zN%M2hR@IkoKc!R2SUmM9%AS2;sv(})Or>86ip(j8N|&smmh;D@(cc}p`9x)A{`i{m z_$GC%veQ21zVpwyxub`hGjm6a=GwVCXJu)&xnb@%v(1JyB@5Dzn7i}bP5)Y4l(oKu z+bejOv`7DPO2%Jyfb4B1<%e%e<*FtXw^3+hBeHv#Jdm3W&r92LN8dbk@#5lQ+3hp^ zIez@jTRxh7`e!FjNc-Y(H9pG&`l>@VzrInTot^%^l&;s#owE(Y)^tq2j{!dj_?>{? zy}sJdsrQfQ=Xsg7&_w<(NuYlb@Yeu;5Ac~!@NwG+xDNO% z;5Px@1^h0+9|!zpz~2S@Qrdsx#)$*?jes8j`~kpE5?@E2>;3vI>iWK{_(N*{k(NDW znx^p}_4h2}hT_jDzDw!9srcIUjgr`k3oRccVG#-~ZMU*K?4_-ClAk#eT9F&)S#76*BwY}tW}S5<#R9)Q8-Fn zTT7fE$Pz11!RM&OYHgN!qT7jjnjJe)V1!9&)vy?-GtA(a$w5}hnzXs*4g)zqT*o48pvuNIqu<7cK<*2wVjHO2~6@=AbKxJJerG?F0)RWkCRN?riI z3cJFdup{h8UT(ez@}l!K^3wA)fyl#t(mFWEN9|5lXm(^-cHmW0q`6Y1E&79=7A3wF zhe@S3Y%vb=qGh;_qiaqUrc@V~*W9U0wPP(Y?7+06Y90XC5QFH}G%jdhx~^?n^^DC? z8Z#{BZBQ3kwZmeQrMzX{FmKmo?RqSwSvBp&?Oda0QV{8Wr0$_%C-zMz(Ci>~VmI*> z9`y#@A|7fh)VT4ku~foe?HhMsr8nk$BJYhSt$4Z=LpEZ1@(Cv-|j7Ot{!m4mB% zx?vBr;^DYMo(w;7L#J918K}ZW74jx$P07iJt?*C<>=g~cVW+Pdev-wJZK&XP<=@~* ztJ@hBt+3l2#9=YWHP6y5E3)-cB&Y4OisWPItRhPs^xYP%bUfDx?95hc5}xWjHh66E z78wc|*VLJm84O|=!K5+}@gPq% z--^=6imK(9!7-hKtkUF^76%;$a;>1$;h^6XYr$dIfkIIEAdx{%Ra(S;1{iUJwG6$P|D8q>-pO80j9 zt#O}zNhhK;D(EMcXnkXsQ*KvT^o;OE3!|7us#9)r8D2Z|O~ZA4S5HjOvlD#>ueZ~K zor2_sqo)Slq^22$Nno3$+?Jy}7>4~$ypNt=PFW(c9vL+3gE(;m&+-$O6IabzSx;Iw z<@3<@-PDY2J&J=f4Xk02n|_iHhAle5VKgmmOlOmL zw(oi74z1hW-_rt`P#nh&+`zFsdOliCAWzbAThhc0&9SLB!%>-)x2qQR7c}jQ{RL^( zD;9=ntCNuVz;^Y>j_m4&S@V;$T>G27OJtuFR#|@u+hsl@3(jb<0Z~ z-AS|9cEdP|SLl1a0s8;taz9^wXq&c7FHAL5US?vx%1(dN>jz5`{XJi{r`OWTRKHhT zzi&)`M=nY9def5hNjj4L>-L+c8)f}w1vZvPXTFyE{|r^h_Vk)enda5Las6KQ>G!Wy zJ^f9vByFN2*`8h}D^vX*cKx1pL-9IW?qBXh%l3LLQ27yMkhZOtB&n6D&c8tA`rOM3 z_4R;i|B!m&S;qMl`qch6DBTXq>%J>gX1)@9{o|0zwci?FM+L6^-Kzb=%73k2-u}PY Cz%IT3 diff --git a/src/api/process.rs b/src/api/process.rs index 641f3f5..20f89d2 100644 --- a/src/api/process.rs +++ b/src/api/process.rs @@ -1,8 +1,8 @@ use crate::api::syscall; -pub fn spawn(path: &str) -> Result<(), ()> { +pub fn spawn(path: &str, args: &[&str]) -> Result<(), ()> { if syscall::info(path).is_some() { - return syscall::spawn(path); + return syscall::spawn(path, args); } Err(()) } diff --git a/src/api/syscall.rs b/src/api/syscall.rs index 708341b..0dcaae0 100644 --- a/src/api/syscall.rs +++ b/src/api/syscall.rs @@ -80,10 +80,12 @@ pub fn close(handle: usize) { unsafe { syscall!(CLOSE, handle as usize) }; } -pub fn spawn(path: &str) -> Result<(), ()> { - let ptr = path.as_ptr() as usize; - let len = path.len() as usize; - let res = unsafe { syscall!(SPAWN, ptr, len) } as isize; +pub fn spawn(path: &str, args: &[&str]) -> Result<(), ()> { + let path_ptr = path.as_ptr() as usize; + let path_len = path.len() as usize; + let args_ptr = args.as_ptr() as usize; + let args_len = args.len() as usize; + let res = unsafe { syscall!(SPAWN, path_ptr, path_len, args_ptr, args_len) } as isize; if res.is_negative() { Err(()) } else { @@ -91,12 +93,16 @@ pub fn spawn(path: &str) -> Result<(), ()> { } } +pub fn stop(code: usize) { + unsafe { syscall!(STOP, code) }; +} + pub fn reboot() { - unsafe { syscall!(STOP, 0xcafe) }; + stop(0xcafe); } pub fn halt() { - unsafe { syscall!(STOP, 0xdead) }; + stop(0xdead); } #[test_case] diff --git a/src/bin/print.rs b/src/bin/print.rs new file mode 100644 index 0000000..efca1fc --- /dev/null +++ b/src/bin/print.rs @@ -0,0 +1,30 @@ +#![no_std] +#![no_main] + +use moros::api::syscall; +use core::panic::PanicInfo; + +#[panic_handler] +fn panic(_info: &PanicInfo) -> ! { + syscall::write(1, b"An exception occured!\n"); + loop {} +} + +#[no_mangle] +pub unsafe extern "sysv64" fn _start(args_ptr: u64, args_len: usize) { + let args = core::slice::from_raw_parts(args_ptr as *const _, args_len); + let code = main(args); + syscall::exit(code); +} + +fn main(args: &[&str]) -> usize { + let n = args.len(); + for i in 1..n { + syscall::write(1, args[i].as_bytes()); + if i < n - 1 { + syscall::write(1, b" "); + } + } + syscall::write(1, b"\n"); + 0 +} diff --git a/src/bin/sleep.rs b/src/bin/sleep.rs new file mode 100644 index 0000000..ab11079 --- /dev/null +++ b/src/bin/sleep.rs @@ -0,0 +1,28 @@ +#![no_std] +#![no_main] + +use moros::api::syscall; +use core::panic::PanicInfo; + +#[panic_handler] +fn panic(_info: &PanicInfo) -> ! { + syscall::write(1, b"An exception occured!\n"); + loop {} +} + +#[no_mangle] +pub unsafe extern "sysv64" fn _start(args_ptr: u64, args_len: usize) { + let args = core::slice::from_raw_parts(args_ptr as *const _, args_len); + let code = main(args); + syscall::exit(code); +} + +fn main(args: &[&str]) -> usize { + if args.len() == 2 { + if let Ok(duration) = args[1].parse::() { + syscall::sleep(duration); + return 0 + } + } + 1 +} diff --git a/src/sys/allocator.rs b/src/sys/allocator.rs index ce474e5..d0069be 100644 --- a/src/sys/allocator.rs +++ b/src/sys/allocator.rs @@ -44,16 +44,18 @@ pub fn init_heap(mapper: &mut impl Mapper, frame_allocator: &mut impl Ok(()) } -pub fn alloc_pages(addr: u64, size: u64) { +pub fn alloc_pages(addr: u64, size: usize) { + //debug!("Alloc pages (addr={:#x}, size={})", addr, size); let mut mapper = unsafe { sys::mem::mapper(VirtAddr::new(sys::mem::PHYS_MEM_OFFSET)) }; let mut frame_allocator = unsafe { sys::mem::BootInfoFrameAllocator::init(sys::mem::MEMORY_MAP.unwrap()) }; let flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE | PageTableFlags::USER_ACCESSIBLE; let pages = { let start_page = Page::containing_address(VirtAddr::new(addr)); - let end_page = Page::containing_address(VirtAddr::new(addr + size - 1)); + let end_page = Page::containing_address(VirtAddr::new(addr + (size as u64) - 1)); Page::range_inclusive(start_page, end_page) }; for page in pages { + //debug!("Alloc page {:?}", page); if let Some(frame) = frame_allocator.allocate_frame() { unsafe { if let Ok(mapping) = mapper.map_to(page, frame, flags, &mut frame_allocator) { @@ -71,11 +73,11 @@ pub fn alloc_pages(addr: u64, size: u64) { use x86_64::structures::paging::page::PageRangeInclusive; // TODO: Replace `free` by `dealloc` -pub fn free_pages(addr: u64, size: u64) { +pub fn free_pages(addr: u64, size: usize) { let mut mapper = unsafe { sys::mem::mapper(VirtAddr::new(sys::mem::PHYS_MEM_OFFSET)) }; let pages: PageRangeInclusive = { let start_page = Page::containing_address(VirtAddr::new(addr)); - let end_page = Page::containing_address(VirtAddr::new(addr + size - 1)); + let end_page = Page::containing_address(VirtAddr::new(addr + (size as u64) - 1)); Page::range_inclusive(start_page, end_page) }; for page in pages { diff --git a/src/sys/idt.rs b/src/sys/idt.rs index a766770..276c262 100644 --- a/src/sys/idt.rs +++ b/src/sys/idt.rs @@ -180,13 +180,14 @@ extern "sysv64" fn syscall_handler(stack_frame: &mut InterruptStackFrame, regs: let arg1 = regs.rdi; let arg2 = regs.rsi; let arg3 = regs.rdx; + let arg4 = regs.r8; if n == sys::syscall::number::SPAWN { // Backup CPU context sys::process::set_stack_frame(**stack_frame); sys::process::set_registers(*regs); } - let res = sys::syscall::dispatcher(n, arg1, arg2, arg3); + let res = sys::syscall::dispatcher(n, arg1, arg2, arg3, arg4); if n == sys::syscall::number::EXIT { // Restore CPU context let sf = sys::process::stack_frame(); diff --git a/src/sys/process.rs b/src/sys/process.rs index 6746045..cabf7cc 100644 --- a/src/sys/process.rs +++ b/src/sys/process.rs @@ -14,6 +14,7 @@ use x86_64::structures::idt::InterruptStackFrameValue; const MAX_FILE_HANDLES: usize = 64; const MAX_PROCS: usize = 2; // TODO: Update this when more than one process can run at once +const MAX_PROC_SIZE: usize = 1 << 20; // 1 MB lazy_static! { pub static ref PID: AtomicUsize = AtomicUsize::new(0); @@ -145,7 +146,12 @@ pub fn set_code_addr(addr: u64) { } pub fn ptr_from_addr(addr: u64) -> *mut u8 { - (code_addr() + addr) as *mut u8 + let base = code_addr(); + if addr < base { + (base + addr) as *mut u8 + } else { + addr as *mut u8 + } } pub fn registers() -> Registers { @@ -175,7 +181,7 @@ pub fn set_stack_frame(stack_frame: InterruptStackFrameValue) { pub fn exit() { let table = PROCESS_TABLE.read(); let proc = &table[id()]; - sys::allocator::free_pages(proc.code_addr, proc.code_size); + sys::allocator::free_pages(proc.code_addr, MAX_PROC_SIZE); MAX_PID.fetch_sub(1, Ordering::SeqCst); set_id(0); // FIXME: No process manager so we switch back to process 0 } @@ -193,7 +199,6 @@ use core::sync::atomic::AtomicU64; use x86_64::VirtAddr; static CODE_ADDR: AtomicU64 = AtomicU64::new((sys::allocator::HEAP_START as u64) + (16 << 20)); -const PAGE_SIZE: u64 = 4 * 1024; #[repr(align(8), C)] #[derive(Debug, Clone, Copy, Default)] @@ -216,7 +221,7 @@ const BIN_MAGIC: [u8; 4] = [0x7F, b'B', b'I', b'N']; pub struct Process { id: usize, code_addr: u64, - code_size: u64, + stack_addr: u64, entry_point: u64, stack_frame: InterruptStackFrameValue, registers: Registers, @@ -235,7 +240,7 @@ impl Process { Self { id, code_addr: 0, - code_size: 0, + stack_addr: 0, entry_point: 0, stack_frame: isf, registers: Registers::default(), @@ -243,13 +248,13 @@ impl Process { } } - pub fn spawn(bin: &[u8]) -> Result<(), ()> { + pub fn spawn(bin: &[u8], args_ptr: usize, args_len: usize) -> Result<(), ()> { if let Ok(pid) = Self::create(bin) { let proc = { let table = PROCESS_TABLE.read(); table[pid].clone() }; - proc.exec(); + proc.exec(args_ptr, args_len); Ok(()) } else { Err(()) @@ -257,35 +262,29 @@ impl Process { } fn create(bin: &[u8]) -> Result { - // Allocate some memory for the code and the stack of the program - let code_size = 1 * PAGE_SIZE; - let code_addr = CODE_ADDR.fetch_add(code_size, Ordering::SeqCst); + let proc_size = MAX_PROC_SIZE as u64; + let code_addr = CODE_ADDR.fetch_add(proc_size, Ordering::SeqCst); + let stack_addr = code_addr + proc_size; let mut entry_point = 0; let code_ptr = code_addr as *mut u8; if bin[0..4] == ELF_MAGIC { // ELF binary if let Ok(obj) = object::File::parse(bin) { - sys::allocator::alloc_pages(code_addr, code_size); + //sys::allocator::alloc_pages(code_addr, code_size); entry_point = obj.entry(); for segment in obj.segments() { let addr = segment.address() as usize; if let Ok(data) = segment.data() { - for (i, op) in data.iter().enumerate() { - unsafe { - let ptr = code_ptr.add(addr + i); - core::ptr::write(ptr, *op); - } + for (i, b) in data.iter().enumerate() { + unsafe { core::ptr::write(code_ptr.add(addr + i), *b) }; } } } } } else if bin[0..4] == BIN_MAGIC { // Flat binary - sys::allocator::alloc_pages(code_addr, code_size); - for (i, op) in bin.iter().skip(4).enumerate() { - unsafe { - let ptr = code_ptr.add(i); - core::ptr::write(ptr, *op); - } + //sys::allocator::alloc_pages(code_addr, code_size); + for (i, b) in bin.iter().skip(4).enumerate() { + unsafe { core::ptr::write(code_ptr.add(i), *b) }; } } else { return Err(()); @@ -299,28 +298,58 @@ impl Process { let stack_frame = parent.stack_frame; let id = MAX_PID.fetch_add(1, Ordering::SeqCst); - let proc = Process { id, code_addr, code_size, entry_point, data, stack_frame, registers }; + let proc = Process { id, code_addr, stack_addr, entry_point, data, stack_frame, registers }; table[id] = Box::new(proc); Ok(id) } // Switch to user mode and execute the program - fn exec(&self) { + fn exec(&self, args_ptr: usize, args_len: usize) { + let args_ptr = ptr_from_addr(args_ptr as u64) as usize; + let args: &[&str] = unsafe { core::slice::from_raw_parts(args_ptr as *const &str, args_len) }; + let heap_addr = self.code_addr + (self.stack_addr - self.code_addr) / 2; + let mut ptr = heap_addr; + let vec: Vec<&str> = args.iter().map(|arg| { + let src_len = arg.len(); + let src_ptr = arg.as_ptr(); + let dst_ptr = ptr as *mut u8; + //let dst_ptr_translated = ((dst_ptr as u64) - self.code_addr) as *const u8; // Userspace address + ptr = ((dst_ptr as usize) + src_len) as u64; + unsafe { + core::ptr::copy_nonoverlapping(src_ptr, dst_ptr, src_len); + //core::str::from_utf8_unchecked(core::slice::from_raw_parts(dst_ptr_translated, src_len)) + core::str::from_utf8_unchecked(core::slice::from_raw_parts(dst_ptr, src_len)) + } + }).collect(); + let args = vec.as_slice(); + let src_len = args.len(); + let src_ptr = args.as_ptr(); + let dst_ptr = ptr as *mut &str; + let args: &[&str] = unsafe { + core::ptr::copy_nonoverlapping(src_ptr, dst_ptr, src_len); + core::slice::from_raw_parts(dst_ptr, src_len) + }; + + //let args_ptr = (args.as_ptr() as u64) - self.code_addr; // userspace address + let args_ptr = args.as_ptr() as u64; + set_id(self.id); // Change PID unsafe { asm!( "cli", // Disable interrupts - "push rax", // Stack segment (SS) - "push rsi", // Stack pointer (RSP) + "push {:r}", // Stack segment (SS) + "push {:r}", // Stack pointer (RSP) "push 0x200", // RFLAGS with interrupts enabled - "push rdx", // Code segment (CS) - "push rdi", // Instruction pointer (RIP) + "push {:r}", // Code segment (CS) + "push {:r}", // Instruction pointer (RIP) "iretq", - in("rax") GDT.1.user_data.0, - in("rsi") self.code_addr + self.code_size, - in("rdx") GDT.1.user_code.0, - in("rdi") self.code_addr + self.entry_point, + in(reg) GDT.1.user_data.0, + in(reg) self.stack_addr, + in(reg) GDT.1.user_code.0, + in(reg) self.code_addr + self.entry_point, + in("rdi") args_ptr, + in("rsi") args_len, ); } } diff --git a/src/sys/syscall/mod.rs b/src/sys/syscall/mod.rs index 3dc6a6b..00f4313 100644 --- a/src/sys/syscall/mod.rs +++ b/src/sys/syscall/mod.rs @@ -10,7 +10,7 @@ use core::arch::asm; * Dispatching system calls */ -pub fn dispatcher(n: usize, arg1: usize, arg2: usize, arg3: usize) -> usize { +pub fn dispatcher(n: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize) -> usize { match n { number::EXIT => { service::exit(arg1) @@ -50,7 +50,7 @@ pub fn dispatcher(n: usize, arg1: usize, arg2: usize, arg3: usize) -> usize { let handle = arg1; let ptr = sys::process::ptr_from_addr(arg2 as u64); let len = arg3; - let buf = unsafe { core::slice::from_raw_parts_mut(ptr, len) }; + let buf = unsafe { core::slice::from_raw_parts_mut(ptr, len) }; // TODO: Remove mut service::write(handle, buf) as usize } number::CLOSE => { @@ -64,10 +64,14 @@ pub fn dispatcher(n: usize, arg1: usize, arg2: usize, arg3: usize) -> usize { service::dup(old_handle, new_handle) as usize } number::SPAWN => { - let ptr = sys::process::ptr_from_addr(arg1 as u64); - let len = arg2; - let path = unsafe { core::str::from_utf8_unchecked(core::slice::from_raw_parts(ptr, len)) }; - service::spawn(path) as usize + let path_ptr = sys::process::ptr_from_addr(arg1 as u64); + let path_len = arg2; + let path = unsafe { core::str::from_utf8_unchecked(core::slice::from_raw_parts(path_ptr, path_len)) }; + + let args_ptr = arg3; + let args_len = arg4; + + service::spawn(path, args_ptr, args_len) as usize } number::STOP => { service::stop(arg1) @@ -125,6 +129,17 @@ pub unsafe fn syscall3(n: usize, arg1: usize, arg2: usize, arg3: usize) -> usize res } +#[doc(hidden)] +pub unsafe fn syscall4(n: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize) -> usize { + let res: usize; + asm!( + "int 0x80", in("rax") n, + in("rdi") arg1, in("rsi") arg2, in("rdx") arg3, in("r8") arg4, + lateout("rax") res + ); + res +} + #[macro_export] macro_rules! syscall { ($n:expr) => ( @@ -139,4 +154,7 @@ macro_rules! syscall { ($n:expr, $a1:expr, $a2:expr, $a3:expr) => ( $crate::sys::syscall::syscall3( $n as usize, $a1 as usize, $a2 as usize, $a3 as usize)); + ($n:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr) => ( + $crate::sys::syscall::syscall4( + $n as usize, $a1 as usize, $a2 as usize, $a3 as usize, $a4 as usize)); } diff --git a/src/sys/syscall/service.rs b/src/sys/syscall/service.rs index ecbfb52..b1c7b6e 100644 --- a/src/sys/syscall/service.rs +++ b/src/sys/syscall/service.rs @@ -80,7 +80,7 @@ pub fn close(handle: usize) { sys::process::delete_file_handle(handle); } -pub fn spawn(path: &str) -> isize { +pub fn spawn(path: &str, args_ptr: usize, args_len: usize) -> isize { let path = match sys::fs::canonicalize(path) { Ok(path) => path, Err(_) => return -1, @@ -89,7 +89,7 @@ pub fn spawn(path: &str) -> isize { let mut buf = vec![0; file.size()]; if let Ok(bytes) = file.read(&mut buf) { buf.resize(bytes, 0); - if Process::spawn(&buf).is_ok() { + if Process::spawn(&buf, args_ptr, args_len).is_ok() { return 0; } } @@ -110,7 +110,9 @@ pub fn stop(code: usize) -> usize { 0xdead => { // Halt sys::acpi::shutdown(); } - _ => {} + _ => { + debug!("STOP SYSCALL: Invalid code '{:#x}' received", code); + } } 0 } diff --git a/src/usr/install.rs b/src/usr/install.rs index 54ee53e..114e707 100644 --- a/src/usr/install.rs +++ b/src/usr/install.rs @@ -20,7 +20,9 @@ pub fn copy_files(verbose: bool) { copy_file("/bin/clear", include_bytes!("../../dsk/bin/clear"), verbose); copy_file("/bin/halt", include_bytes!("../../dsk/bin/halt"), verbose); copy_file("/bin/hello", include_bytes!("../../dsk/bin/hello"), verbose); + copy_file("/bin/print", include_bytes!("../../dsk/bin/print"), verbose); copy_file("/bin/reboot", include_bytes!("../../dsk/bin/reboot"), verbose); + copy_file("/bin/sleep", include_bytes!("../../dsk/bin/sleep"), verbose); create_dir("/dev/clk", verbose); // Clocks create_dev("/dev/clk/uptime", DeviceType::Uptime, verbose); diff --git a/src/usr/mod.rs b/src/usr/mod.rs index 4e4fe60..1bbaec8 100644 --- a/src/usr/mod.rs +++ b/src/usr/mod.rs @@ -26,11 +26,9 @@ pub mod memory; pub mod net; pub mod pci; pub mod pow; -pub mod print; pub mod r#move; pub mod read; pub mod shell; -pub mod sleep; pub mod socket; pub mod tcp; pub mod time; diff --git a/src/usr/print.rs b/src/usr/print.rs deleted file mode 100644 index 33b11f4..0000000 --- a/src/usr/print.rs +++ /dev/null @@ -1,13 +0,0 @@ -use crate::usr; - -pub fn main(args: &[&str]) -> usr::shell::ExitCode { - let n = args.len(); - for i in 1..n { - print!("{}", args[i]); - if i < n - 1 { - print!(" "); - } - } - println!(); - usr::shell::ExitCode::CommandSuccessful -} diff --git a/src/usr/shell.rs b/src/usr/shell.rs index 0cbaf96..e1d78ff 100644 --- a/src/usr/shell.rs +++ b/src/usr/shell.rs @@ -12,11 +12,11 @@ use alloc::vec::Vec; use alloc::string::{String, ToString}; // TODO: Scan /bin -const AUTOCOMPLETE_COMMANDS: [&str; 37] = [ +const AUTOCOMPLETE_COMMANDS: [&str; 35] = [ "2048", "base64", "calc", "colors", "copy", "date", "delete", "dhcp", "disk", "edit", "env", "exit", "geotime", "goto", "help", "hex", "host", "http", "httpd", "install", - "keyboard", "lisp", "list", "memory", "move", "net", "pci", "print", "read", - "shell", "sleep", "socket", "tcp", "time", "user", "vga", "write" + "keyboard", "lisp", "list", "memory", "move", "net", "pci", "read", + "shell", "socket", "tcp", "time", "user", "vga", "write" ]; #[repr(u8)] @@ -276,7 +276,6 @@ pub fn exec(cmd: &str, env: &mut BTreeMap) -> ExitCode { "m" | "move" => usr::r#move::main(&args), "n" => ExitCode::CommandUnknown, "o" => ExitCode::CommandUnknown, - "p" | "print" => usr::print::main(&args), "q" | "quit" | "exit" => ExitCode::ShellExit, "r" | "read" => usr::read::main(&args), "s" => ExitCode::CommandUnknown, @@ -289,7 +288,6 @@ pub fn exec(cmd: &str, env: &mut BTreeMap) -> ExitCode { "z" => ExitCode::CommandUnknown, "vga" => usr::vga::main(&args), "sh" | "shell" => usr::shell::main(&args), - "sleep" => usr::sleep::main(&args), "calc" => usr::calc::main(&args), "base64" => usr::base64::main(&args), "date" => usr::date::main(&args), @@ -328,7 +326,7 @@ pub fn exec(cmd: &str, env: &mut BTreeMap) -> ExitCode { ExitCode::CommandSuccessful } Some(FileType::File) => { - if api::process::spawn(&path).is_ok() { + if api::process::spawn(&path, &args[1..]).is_ok() { // TODO: get exit code ExitCode::CommandSuccessful } else { @@ -337,8 +335,12 @@ pub fn exec(cmd: &str, env: &mut BTreeMap) -> ExitCode { } } _ => { - // TODO: add aliases - if api::process::spawn(&format!("/bin/{}", args[0])).is_ok() { + // TODO: add aliases command instead of hardcoding them + let name = match args[0] { + "p" => "print", + arg => arg, + }; + if api::process::spawn(&format!("/bin/{}", name), &args).is_ok() { ExitCode::CommandSuccessful } else { error!("Could not execute '{}'", cmd); diff --git a/src/usr/sleep.rs b/src/usr/sleep.rs deleted file mode 100644 index 047bb9b..0000000 --- a/src/usr/sleep.rs +++ /dev/null @@ -1,12 +0,0 @@ -use crate::usr; -use crate::api::syscall; - -pub fn main(args: &[&str]) -> usr::shell::ExitCode { - if args.len() == 2 { - if let Ok(duration) = args[1].parse::() { - syscall::sleep(duration); - return usr::shell::ExitCode::CommandSuccessful; - } - } - usr::shell::ExitCode::CommandError -}