#![no_std] #![no_main] use core::sync::atomic::{AtomicBool, Ordering}; use crate::terminal::{print, println}; use liblbos::fs::{DirectoryReader, FileSystem}; static NO_EXIT: AtomicBool = AtomicBool::new(false); #[panic_handler] fn panic(info: &core::panic::PanicInfo) -> ! { liblbos::syscalls::write_terminal(b"abort\n"); loop {} } fn lsdir() { let mut fs = FileSystem::empty(); if liblbos::ktask::ktask_fsopen(&mut fs) != 0 { println("failed to open fs"); return; } let mut dir = DirectoryReader::empty(); if liblbos::ktask::ktask_fsopendir(&fs, &mut dir, b"/") != 0 { println("failed to open dir"); return; } let mut record = liblbos::fs::Record { name: [0; 12], record_type: 0, target: 0, total_size_bytes: 0, }; while liblbos::ktask::ktask_fsreaddir(&fs, &mut dir, &mut record) == 0 { print("\n"); if record.record_type == 0 { println("unexpected eod"); break; } print(" - "); liblbos::syscalls::write_terminal( &record.name[..record.name.iter().position(|&x| x == 0).unwrap_or(11)], ); if record.record_type == liblbos::fs::RecordType::Directory as u8 { print(" (dir)"); } else { print(" (file)"); } } print("\n"); } fn attempt_run_file(name: &str) { print("\n"); if name.len() > 11 { println("filename too long"); return; } let mut fs = FileSystem::empty(); if liblbos::ktask::ktask_fsopen(&mut fs) != 0 { println("failed to open fs"); return; } let mut dir = DirectoryReader::empty(); if liblbos::ktask::ktask_fsopendir(&fs, &mut dir, b"/") != 0 { println("failed to open dir"); return; } let mut record = liblbos::fs::Record { name: [0; 12], record_type: 0, target: 0, total_size_bytes: 0, }; fn namecmp(record: &liblbos::fs::Record, name: &[u8]) -> bool { let record_name = &record.name[..record.name.iter().position(|&x| x == 0).unwrap_or(11)]; record_name == name } while !namecmp(&record, name.as_bytes()) { if liblbos::ktask::ktask_fsreaddir(&fs, &mut dir, &mut record) != 0 { println("file not found"); return; } if record.record_type == 0 { println("unexpected eod"); return; } if record.record_type == liblbos::fs::RecordType::Directory as u8 && namecmp(&record, name.as_bytes()) { println("not a file"); return; } } // found, load the file let mut reader = liblbos::fs::FileReader::empty(); if liblbos::ktask::ktask_fsopenfile(&fs, &record, &mut reader) != 0 { println("failed to open file"); return; } let size = record.total_size_bytes as usize; let buf = liblbos::syscalls::alloc_blocks(size.div_ceil(512)); if liblbos::ktask::ktask_fsreadfile(&fs, &mut reader, unsafe { core::slice::from_raw_parts_mut(buf as *mut _, size) }) != 0 { println("failed to read file"); } let mut task_setup = liblbos::TaskSetup { epc: 0, ddi_first_addr: 0, ddi_size: 0, wait_for_task_exit: true, }; if liblbos::ktask::ktask_loadddifile(buf, size, &mut task_setup as *mut _ as usize) != 0 { println("failed to load ddi"); liblbos::syscalls::free_blocks(buf, size.div_ceil(512)); return; } liblbos::syscalls::free_blocks(buf, size.div_ceil(512)); let task_id = liblbos::syscalls::create_task(task_setup); println("\ntask exited\n"); } fn execute(cmd: &str) { print("\n"); let mut split = cmd.split_ascii_whitespace(); if let Some(cmd) = split.next() { match cmd { "ls" => { lsdir(); } "exit" => { if NO_EXIT.load(Ordering::Relaxed) { println("cannot exit as task 1"); } else { liblbos::syscalls::exit(); } } _ => { attempt_run_file(cmd); } } } } fn hex(mut n: u8) -> [u8; 2] { let mut buf = [0u8; 2]; for i in (0..2).rev() { let num = n & 0b1111; n >>= 4; if num < 10 { buf[i] = b'0' + num; } else { buf[i] = b'a' + (num - 10); } } buf } mod arch; mod terminal; #[unsafe(no_mangle)] extern "C" fn main() { let tid = liblbos::syscalls::current_task(); NO_EXIT.store(tid == 1, Ordering::Relaxed); print("\n\n"); print("turntable v"); const VERSION: &str = env!("CARGO_PKG_VERSION"); print(VERSION); print("\n"); println("(c) 2025 Real Microsoft, LLC"); print("> "); let mut cmdbuf = [0u8; 256]; let mut cmdbuf_len = 0; let mut inbuf = [0u8; 8]; loop { let read = liblbos::syscalls::read_inbuf(&mut inbuf); if read > 0 { for c in &inbuf[0..read] { if cmdbuf_len >= cmdbuf.len() { print("\x07"); } else { // backspace if *c == 0x7f && cmdbuf_len > 0 { cmdbuf_len -= 1; print("\x08 \x08"); } else { cmdbuf[cmdbuf_len] = *c; cmdbuf_len += 1; if *c == b'\r' { execute(unsafe { core::str::from_utf8_unchecked(&cmdbuf[0..cmdbuf_len - 1]) }); cmdbuf_len = 0; print("> "); break; } else { liblbos::syscalls::write_terminal(&[*c]); } } } } } } }