diff --git a/Makefile b/Makefile index d879ba5..eadb0d5 100644 --- a/Makefile +++ b/Makefile @@ -51,7 +51,13 @@ build/libcollections.rlib: rust/src/libcollections/lib.rs build/libcore.rlib bui mkdir -p build ./rustc.sh $(RUSTCFLAGS) -o $@ $< -build/libkernel.a: build/libcore.rlib build/liballoc.rlib build/libcollections.rlib FORCE +build/libinit.a: init/src/*.rs + RUSTC="./rustc.sh" cargo rustc --manifest-path init/Cargo.toml $(CARGOFLAGS) -o $@ + +build/init: build/libinit.a + $(LD) -e _start --gc-sections -o $@ $< + +build/libkernel.a: build/libcore.rlib build/liballoc.rlib build/libcollections.rlib build/init FORCE mkdir -p build RUSTC="./rustc.sh" cargo rustc $(CARGOFLAGS) -o $@ diff --git a/init/Cargo.toml b/init/Cargo.toml new file mode 100644 index 0000000..1aeb3c2 --- /dev/null +++ b/init/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "init" +version = "0.1.0" + +[lib] +name = "init" +crate-type = ["staticlib"] + +[dependencies] +syscall = { path = "../syscall/" } diff --git a/init/main b/init/main deleted file mode 100755 index 872fc33..0000000 Binary files a/init/main and /dev/null differ diff --git a/init/main.asm b/init/main.asm deleted file mode 100644 index 514295b..0000000 --- a/init/main.asm +++ /dev/null @@ -1,20 +0,0 @@ -[bits 64] -section .text -global _start ;must be declared for linker (ld) - -_start: ;tell linker entry point - - xchg bx, bx - mov rdx,len ;message length - mov rcx,msg ;message to write - mov rbx,1 ;file descriptor (stdout) - mov rax,4 ;system call number (sys_write) - int 0x80 ;call kernel - - mov rax,1 ;system call number (sys_exit) - int 0x80 ;call kernel - -section .data - -msg db 'Hello, world!',0xa ;our dear string -len equ $ - msg ;length of our dear string diff --git a/init/main.o b/init/main.o deleted file mode 100644 index 5c5b590..0000000 Binary files a/init/main.o and /dev/null differ diff --git a/init/src/lib.rs b/init/src/lib.rs new file mode 100644 index 0000000..dd8be37 --- /dev/null +++ b/init/src/lib.rs @@ -0,0 +1,97 @@ +#![feature(asm)] +#![feature(lang_items)] +#![no_std] + +#[macro_use] +extern crate syscall; + +use syscall::{exit, write}; + +#[no_mangle] +pub unsafe extern fn _start() { + let string = b"Hello, World!\n"; + write(1, string); + exit(1); +} + +#[cfg(not(test))] +#[lang = "eh_personality"] +extern "C" fn eh_personality() {} + +#[cfg(not(test))] +/// Required to handle panics +#[lang = "panic_fmt"] +extern "C" fn panic_fmt(_fmt: ::core::fmt::Arguments, _file: &str, _line: u32) -> ! { + loop {} +} + +/// Memcpy +/// +/// Copy N bytes of memory from one location to another. +#[no_mangle] +pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8, + n: usize) -> *mut u8 { + let mut i = 0; + while i < n { + *dest.offset(i as isize) = *src.offset(i as isize); + i += 1; + } + + dest +} + +/// Memmove +/// +/// Copy N bytes of memory from src to dest. The memory areas may overlap. +#[no_mangle] +pub unsafe extern fn memmove(dest: *mut u8, src: *const u8, + n: usize) -> *mut u8 { + if src < dest as *const u8 { + let mut i = n; + while i != 0 { + i -= 1; + *dest.offset(i as isize) = *src.offset(i as isize); + } + } else { + let mut i = 0; + while i < n { + *dest.offset(i as isize) = *src.offset(i as isize); + i += 1; + } + } + + dest +} + +/// Memset +/// +/// Fill a block of memory with a specified value. +#[no_mangle] +pub unsafe extern fn memset(s: *mut u8, c: i32, n: usize) -> *mut u8 { + let mut i = 0; + while i < n { + *s.offset(i as isize) = c as u8; + i += 1; + } + + s +} + +/// Memcmp +/// +/// Compare two blocks of memory. +#[no_mangle] +pub unsafe extern fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 { + let mut i = 0; + + while i < n { + let a = *s1.offset(i as isize); + let b = *s2.offset(i as isize); + if a != b { + return a as i32 - b as i32 + } + i += 1; + } + + 0 +} diff --git a/kernel/lib.rs b/kernel/lib.rs index bc93fc5..19731e1 100644 --- a/kernel/lib.rs +++ b/kernel/lib.rs @@ -135,14 +135,14 @@ pub extern fn kmain() { let stdin = syscall::open("debug:".as_bytes(), 0); println!("STDIN: {:?}", stdin); - + let stdout = syscall::open("debug:".as_bytes(), 0); println!("STDOUT: {:?}", stdout); let stderr = syscall::open("debug:".as_bytes(), 0); println!("STDERR: {:?}", stderr); - let elf = elf::Elf::from(include_bytes!("../init/main")).expect("could not load elf"); + let elf = elf::Elf::from(include_bytes!("../build/init")).expect("could not load elf"); elf.run(); /* diff --git a/syscall/Cargo.toml b/syscall/Cargo.toml new file mode 100644 index 0000000..e5b3417 --- /dev/null +++ b/syscall/Cargo.toml @@ -0,0 +1,3 @@ +[package] +name = "syscall" +version = "0.1.0" diff --git a/syscall/src/error.rs b/syscall/src/error.rs new file mode 100644 index 0000000..9af8f4a --- /dev/null +++ b/syscall/src/error.rs @@ -0,0 +1,314 @@ +use core::{fmt, result}; + +pub struct Error { + pub errno: isize, +} + +pub type Result = result::Result; + +impl Error { + pub fn new(errno: isize) -> Error { + Error { errno: errno } + } + + pub fn mux(result: Result) -> usize { + match result { + Ok(value) => value, + Err(error) => -error.errno as usize, + } + } + + pub fn demux(value: usize) -> Result { + let errno = -(value as isize); + if errno >= 1 && errno < STR_ERROR.len() as isize { + Err(Error::new(errno)) + } else { + Ok(value) + } + } + + pub fn text(&self) -> &str { + if let Some(description) = STR_ERROR.get(self.errno as usize) { + description + } else { + "Unknown Error" + } + } +} + +impl fmt::Debug for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> { + f.write_str(self.text()) + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> { + f.write_str(self.text()) + } +} + +pub const EPERM: isize = 1; /* Operation not permitted */ +pub const ENOENT: isize = 2; /* No such file or directory */ +pub const ESRCH: isize = 3; /* No such process */ +pub const EINTR: isize = 4; /* Interrupted system call */ +pub const EIO: isize = 5; /* I/O error */ +pub const ENXIO: isize = 6; /* No such device or address */ +pub const E2BIG: isize = 7; /* Argument list too long */ +pub const ENOEXEC: isize = 8; /* Exec format error */ +pub const EBADF: isize = 9; /* Bad file number */ +pub const ECHILD: isize = 10; /* No child processes */ +pub const EAGAIN: isize = 11; /* Try again */ +pub const ENOMEM: isize = 12; /* Out of memory */ +pub const EACCES: isize = 13; /* Permission denied */ +pub const EFAULT: isize = 14; /* Bad address */ +pub const ENOTBLK: isize = 15; /* Block device required */ +pub const EBUSY: isize = 16; /* Device or resource busy */ +pub const EEXIST: isize = 17; /* File exists */ +pub const EXDEV: isize = 18; /* Cross-device link */ +pub const ENODEV: isize = 19; /* No such device */ +pub const ENOTDIR: isize = 20; /* Not a directory */ +pub const EISDIR: isize = 21; /* Is a directory */ +pub const EINVAL: isize = 22; /* Invalid argument */ +pub const ENFILE: isize = 23; /* File table overflow */ +pub const EMFILE: isize = 24; /* Too many open files */ +pub const ENOTTY: isize = 25; /* Not a typewriter */ +pub const ETXTBSY: isize = 26; /* Text file busy */ +pub const EFBIG: isize = 27; /* File too large */ +pub const ENOSPC: isize = 28; /* No space left on device */ +pub const ESPIPE: isize = 29; /* Illegal seek */ +pub const EROFS: isize = 30; /* Read-only file system */ +pub const EMLINK: isize = 31; /* Too many links */ +pub const EPIPE: isize = 32; /* Broken pipe */ +pub const EDOM: isize = 33; /* Math argument out of domain of func */ +pub const ERANGE: isize = 34; /* Math result not representable */ +pub const EDEADLK: isize = 35; /* Resource deadlock would occur */ +pub const ENAMETOOLONG: isize = 36; /* File name too long */ +pub const ENOLCK: isize = 37; /* No record locks available */ +pub const ENOSYS: isize = 38; /* Function not implemented */ +pub const ENOTEMPTY: isize = 39; /* Directory not empty */ +pub const ELOOP: isize = 40; /* Too many symbolic links encountered */ +pub const EWOULDBLOCK: isize = 41; /* Operation would block */ +pub const ENOMSG: isize = 42; /* No message of desired type */ +pub const EIDRM: isize = 43; /* Identifier removed */ +pub const ECHRNG: isize = 44; /* Channel number out of range */ +pub const EL2NSYNC: isize = 45; /* Level 2 not synchronized */ +pub const EL3HLT: isize = 46; /* Level 3 halted */ +pub const EL3RST: isize = 47; /* Level 3 reset */ +pub const ELNRNG: isize = 48; /* Link number out of range */ +pub const EUNATCH: isize = 49; /* Protocol driver not attached */ +pub const ENOCSI: isize = 50; /* No CSI structure available */ +pub const EL2HLT: isize = 51; /* Level 2 halted */ +pub const EBADE: isize = 52; /* Invalid exchange */ +pub const EBADR: isize = 53; /* Invalid request descriptor */ +pub const EXFULL: isize = 54; /* Exchange full */ +pub const ENOANO: isize = 55; /* No anode */ +pub const EBADRQC: isize = 56; /* Invalid request code */ +pub const EBADSLT: isize = 57; /* Invalid slot */ +pub const EDEADLOCK: isize = 58; /* Resource deadlock would occur */ +pub const EBFONT: isize = 59; /* Bad font file format */ +pub const ENOSTR: isize = 60; /* Device not a stream */ +pub const ENODATA: isize = 61; /* No data available */ +pub const ETIME: isize = 62; /* Timer expired */ +pub const ENOSR: isize = 63; /* Out of streams resources */ +pub const ENONET: isize = 64; /* Machine is not on the network */ +pub const ENOPKG: isize = 65; /* Package not installed */ +pub const EREMOTE: isize = 66; /* Object is remote */ +pub const ENOLINK: isize = 67; /* Link has been severed */ +pub const EADV: isize = 68; /* Advertise error */ +pub const ESRMNT: isize = 69; /* Srmount error */ +pub const ECOMM: isize = 70; /* Communication error on send */ +pub const EPROTO: isize = 71; /* Protocol error */ +pub const EMULTIHOP: isize = 72; /* Multihop attempted */ +pub const EDOTDOT: isize = 73; /* RFS specific error */ +pub const EBADMSG: isize = 74; /* Not a data message */ +pub const EOVERFLOW: isize = 75; /* Value too large for defined data type */ +pub const ENOTUNIQ: isize = 76; /* Name not unique on network */ +pub const EBADFD: isize = 77; /* File descriptor in bad state */ +pub const EREMCHG: isize = 78; /* Remote address changed */ +pub const ELIBACC: isize = 79; /* Can not access a needed shared library */ +pub const ELIBBAD: isize = 80; /* Accessing a corrupted shared library */ +pub const ELIBSCN: isize = 81; /* .lib section in a.out corrupted */ +pub const ELIBMAX: isize = 82; /* Attempting to link in too many shared libraries */ +pub const ELIBEXEC: isize = 83; /* Cannot exec a shared library directly */ +pub const EILSEQ: isize = 84; /* Illegal byte sequence */ +pub const ERESTART: isize = 85; /* Interrupted system call should be restarted */ +pub const ESTRPIPE: isize = 86; /* Streams pipe error */ +pub const EUSERS: isize = 87; /* Too many users */ +pub const ENOTSOCK: isize = 88; /* Socket operation on non-socket */ +pub const EDESTADDRREQ: isize = 89; /* Destination address required */ +pub const EMSGSIZE: isize = 90; /* Message too long */ +pub const EPROTOTYPE: isize = 91; /* Protocol wrong type for socket */ +pub const ENOPROTOOPT: isize = 92; /* Protocol not available */ +pub const EPROTONOSUPPORT: isize = 93; /* Protocol not supported */ +pub const ESOCKTNOSUPPORT: isize = 94; /* Socket type not supported */ +pub const EOPNOTSUPP: isize = 95; /* Operation not supported on transport endpoint */ +pub const EPFNOSUPPORT: isize = 96; /* Protocol family not supported */ +pub const EAFNOSUPPORT: isize = 97; /* Address family not supported by protocol */ +pub const EADDRINUSE: isize = 98; /* Address already in use */ +pub const EADDRNOTAVAIL: isize = 99; /* Cannot assign requested address */ +pub const ENETDOWN: isize = 100; /* Network is down */ +pub const ENETUNREACH: isize = 101; /* Network is unreachable */ +pub const ENETRESET: isize = 102; /* Network dropped connection because of reset */ +pub const ECONNABORTED: isize = 103; /* Software caused connection abort */ +pub const ECONNRESET: isize = 104; /* Connection reset by peer */ +pub const ENOBUFS: isize = 105; /* No buffer space available */ +pub const EISCONN: isize = 106; /* Transport endpoint is already connected */ +pub const ENOTCONN: isize = 107; /* Transport endpoint is not connected */ +pub const ESHUTDOWN: isize = 108; /* Cannot send after transport endpoint shutdown */ +pub const ETOOMANYREFS: isize = 109; /* Too many references: cannot splice */ +pub const ETIMEDOUT: isize = 110; /* Connection timed out */ +pub const ECONNREFUSED: isize = 111; /* Connection refused */ +pub const EHOSTDOWN: isize = 112; /* Host is down */ +pub const EHOSTUNREACH: isize = 113; /* No route to host */ +pub const EALREADY: isize = 114; /* Operation already in progress */ +pub const EINPROGRESS: isize = 115; /* Operation now in progress */ +pub const ESTALE: isize = 116; /* Stale NFS file handle */ +pub const EUCLEAN: isize = 117; /* Structure needs cleaning */ +pub const ENOTNAM: isize = 118; /* Not a XENIX named type file */ +pub const ENAVAIL: isize = 119; /* No XENIX semaphores available */ +pub const EISNAM: isize = 120; /* Is a named type file */ +pub const EREMOTEIO: isize = 121; /* Remote I/O error */ +pub const EDQUOT: isize = 122; /* Quota exceeded */ +pub const ENOMEDIUM: isize = 123; /* No medium found */ +pub const EMEDIUMTYPE: isize = 124; /* Wrong medium type */ +pub const ECANCELED: isize = 125; /* Operation Canceled */ +pub const ENOKEY: isize = 126; /* Required key not available */ +pub const EKEYEXPIRED: isize = 127; /* Key has expired */ +pub const EKEYREVOKED: isize = 128; /* Key has been revoked */ +pub const EKEYREJECTED: isize = 129; /* Key was rejected by service */ +pub const EOWNERDEAD: isize = 130; /* Owner died */ +pub const ENOTRECOVERABLE: isize = 131; /* State not recoverable */ + +pub static STR_ERROR: [&'static str; 132] = ["Success", + "Operation not permitted", + "No such file or directory", + "No such process", + "Interrupted system call", + "I/O error", + "No such device or address", + "Argument list too long", + "Exec format error", + "Bad file number", + "No child processes", + "Try again", + "Out of memory", + "Permission denied", + "Bad address", + "Block device required", + "Device or resource busy", + "File exists", + "Cross-device link", + "No such device", + "Not a directory", + "Is a directory", + "Invalid argument", + "File table overflow", + "Too many open files", + "Not a typewriter", + "Text file busy", + "File too large", + "No space left on device", + "Illegal seek", + "Read-only file system", + "Too many links", + "Broken pipe", + "Math argument out of domain of func", + "Math result not representable", + "Resource deadlock would occur", + "File name too long", + "No record locks available", + "Function not implemented", + "Directory not empty", + "Too many symbolic links encountered", + "Operation would block", + "No message of desired type", + "Identifier removed", + "Channel number out of range", + "Level 2 not synchronized", + "Level 3 halted", + "Level 3 reset", + "Link number out of range", + "Protocol driver not attached", + "No CSI structure available", + "Level 2 halted", + "Invalid exchange", + "Invalid request descriptor", + "Exchange full", + "No anode", + "Invalid request code", + "Invalid slot", + "Resource deadlock would occur", + "Bad font file format", + "Device not a stream", + "No data available", + "Timer expired", + "Out of streams resources", + "Machine is not on the network", + "Package not installed", + "Object is remote", + "Link has been severed", + "Advertise error", + "Srmount error", + "Communication error on send", + "Protocol error", + "Multihop attempted", + "RFS specific error", + "Not a data message", + "Value too large for defined data type", + "Name not unique on network", + "File descriptor in bad state", + "Remote address changed", + "Can not access a needed shared library", + "Accessing a corrupted shared library", + ".lib section in a.out corrupted", + "Attempting to link in too many shared libraries", + "Cannot exec a shared library directly", + "Illegal byte sequence", + "Interrupted system call should be restarted", + "Streams pipe error", + "Too many users", + "Socket operation on non-socket", + "Destination address required", + "Message too long", + "Protocol wrong type for socket", + "Protocol not available", + "Protocol not supported", + "Socket type not supported", + "Operation not supported on transport endpoint", + "Protocol family not supported", + "Address family not supported by protocol", + "Address already in use", + "Cannot assign requested address", + "Network is down", + "Network is unreachable", + "Network dropped connection because of reset", + "Software caused connection abort", + "Connection reset by peer", + "No buffer space available", + "Transport endpoint is already connected", + "Transport endpoint is not connected", + "Cannot send after transport endpoint shutdown", + "Too many references: cannot splice", + "Connection timed out", + "Connection refused", + "Host is down", + "No route to host", + "Operation already in progress", + "Operation now in progress", + "Stale NFS file handle", + "Structure needs cleaning", + "Not a XENIX named type file", + "No XENIX semaphores available", + "Is a named type file", + "Remote I/O error", + "Quota exceeded", + "No medium found", + "Wrong medium type", + "Operation Canceled", + "Required key not available", + "Key has expired", + "Key has been revoked", + "Key was rejected by service", + "Owner died", + "State not recoverable"]; diff --git a/syscall/src/lib.rs b/syscall/src/lib.rs new file mode 100644 index 0000000..bb441de --- /dev/null +++ b/syscall/src/lib.rs @@ -0,0 +1,210 @@ +#![feature(asm)] +#![no_std] + +pub use self::arch::*; +pub use self::error::*; + +#[cfg(target_arch = "x86")] +#[path="x86.rs"] +pub mod arch; + +#[cfg(target_arch = "x86_64")] +#[path="x86_64.rs"] +pub mod arch; + +pub mod error; + +pub const SYS_BRK: usize = 45; +pub const SYS_CHDIR: usize = 12; +pub const SYS_CLONE: usize = 120; + pub const CLONE_VM: usize = 0x100; + pub const CLONE_FS: usize = 0x200; + pub const CLONE_FILES: usize = 0x400; + pub const CLONE_VFORK: usize = 0x4000; + /// Mark this clone as supervised. + /// + /// This means that the process can run in supervised mode, even not being connected to + /// a supervisor yet. In other words, the parent can later on supervise the process and handle + /// the potential blocking syscall. + /// + /// This is an important security measure, since otherwise the process would be able to fork it + /// self right after starting, making supervising it impossible. + pub const CLONE_SUPERVISE: usize = 0x400000; +pub const SYS_CLOSE: usize = 6; +pub const SYS_CLOCK_GETTIME: usize = 265; + pub const CLOCK_REALTIME: usize = 1; + pub const CLOCK_MONOTONIC: usize = 4; +pub const SYS_DUP: usize = 41; +pub const SYS_EXECVE: usize = 11; +pub const SYS_EXIT: usize = 1; +pub const SYS_FPATH: usize = 928; +pub const SYS_FSTAT: usize = 28; + pub const MODE_DIR: u16 = 0x4000; + pub const MODE_FILE: u16 = 0x8000; + pub const MODE_ALL: u16 = MODE_DIR | MODE_FILE; +pub const SYS_FSYNC: usize = 118; +pub const SYS_FTRUNCATE: usize = 93; +pub const SYS_FUTEX: usize = 240; + pub const FUTEX_WAIT: usize = 0; + pub const FUTEX_WAKE: usize = 1; + pub const FUTEX_REQUEUE: usize = 2; +pub const SYS_GETPID: usize = 20; +pub const SYS_IOPL: usize = 110; +pub const SYS_LINK: usize = 9; +pub const SYS_LSEEK: usize = 19; + pub const SEEK_SET: usize = 0; + pub const SEEK_CUR: usize = 1; + pub const SEEK_END: usize = 2; +pub const SYS_MKDIR: usize = 39; +pub const SYS_NANOSLEEP: usize = 162; +pub const SYS_OPEN: usize = 5; + pub const O_RDONLY: usize = 0; + pub const O_WRONLY: usize = 1; + pub const O_RDWR: usize = 2; + pub const O_NONBLOCK: usize = 4; + pub const O_APPEND: usize = 8; + pub const O_SHLOCK: usize = 0x10; + pub const O_EXLOCK: usize = 0x20; + pub const O_ASYNC: usize = 0x40; + pub const O_FSYNC: usize = 0x80; + pub const O_CREAT: usize = 0x200; + pub const O_TRUNC: usize = 0x400; + pub const O_EXCL: usize = 0x800; +pub const SYS_PIPE2: usize = 331; +pub const SYS_READ: usize = 3; +pub const SYS_RMDIR: usize = 84; +pub const SYS_UNLINK: usize = 10; +pub const SYS_WAITPID: usize = 7; +pub const SYS_WRITE: usize = 4; +pub const SYS_YIELD: usize = 158; + +#[derive(Copy, Clone, Debug, Default)] +#[repr(packed)] +pub struct Stat { + pub st_dev: u16, + pub st_ino: u16, + pub st_mode: u16, + pub st_nlink: u16, + pub st_uid: u16, + pub st_gid: u16, + pub st_rdev: u16, + pub st_size: u32, + pub st_atime: u32, + pub st_mtime: u32, + pub st_ctime: u32 +} + +#[derive(Copy, Clone, Debug, Default)] +#[repr(packed)] +pub struct TimeSpec { + pub tv_sec: i64, + pub tv_nsec: i32, +} + +pub unsafe fn brk(addr: usize) -> Result { + syscall1(SYS_BRK, addr) +} + +pub fn chdir(path: &str) -> Result { + unsafe { syscall2(SYS_CHDIR, path.as_ptr() as usize, path.len()) } +} + +pub unsafe fn clone(flags: usize) -> Result { + syscall1(SYS_CLONE, flags) +} + +pub fn close(fd: usize) -> Result { + unsafe { syscall1(SYS_CLOSE, fd) } +} + +pub fn clock_gettime(clock: usize, tp: &mut TimeSpec) -> Result { + unsafe { syscall2(SYS_CLOCK_GETTIME, clock, tp as *mut TimeSpec as usize) } +} + +pub fn dup(fd: usize) -> Result { + unsafe { syscall1(SYS_DUP, fd) } +} + +pub unsafe fn execve(path: *const u8, args: *const *const u8) -> Result { + syscall2(SYS_EXECVE, path as usize, args as usize) +} + +pub fn exit(status: usize) -> Result { + unsafe { syscall1(SYS_EXIT, status) } +} + +pub fn fpath(fd: usize, buf: &mut [u8]) -> Result { + unsafe { syscall3(SYS_FPATH, fd, buf.as_mut_ptr() as usize, buf.len()) } +} + +pub fn fstat(fd: usize, stat: &mut Stat) -> Result { + unsafe { syscall2(SYS_FSTAT, fd, stat as *mut Stat as usize) } +} + +pub fn fsync(fd: usize) -> Result { + unsafe { syscall1(SYS_FSYNC, fd) } +} + +pub fn ftruncate(fd: usize, len: usize) -> Result { + unsafe { syscall2(SYS_FTRUNCATE, fd, len) } +} + +pub unsafe fn futex(addr: *mut i32, op: usize, val: i32, val2: usize, addr2: *mut i32) -> Result { + syscall5(SYS_FUTEX, addr as usize, op, (val as isize) as usize, val2, addr2 as usize) +} + +pub fn getpid() -> Result { + unsafe { syscall0(SYS_GETPID) } +} + +pub unsafe fn iopl(level: usize) -> Result { + syscall1(SYS_IOPL, level) +} + +pub unsafe fn link(old: *const u8, new: *const u8) -> Result { + syscall2(SYS_LINK, old as usize, new as usize) +} + +pub fn lseek(fd: usize, offset: isize, whence: usize) -> Result { + unsafe { syscall3(SYS_LSEEK, fd, offset as usize, whence) } +} + +pub fn mkdir(path: &str, mode: usize) -> Result { + unsafe { syscall3(SYS_MKDIR, path.as_ptr() as usize, path.len(), mode) } +} + +pub fn nanosleep(req: &TimeSpec, rem: &mut TimeSpec) -> Result { + unsafe { syscall2(SYS_NANOSLEEP, req as *const TimeSpec as usize, rem as *mut TimeSpec as usize) } +} + +pub fn open(path: &str, flags: usize) -> Result { + unsafe { syscall3(SYS_OPEN, path.as_ptr() as usize, path.len(), flags) } +} + +pub fn pipe2(fds: &mut [usize; 2], flags: usize) -> Result { + unsafe { syscall2(SYS_PIPE2, fds.as_ptr() as usize, flags) } +} + +pub fn read(fd: usize, buf: &mut [u8]) -> Result { + unsafe { syscall3(SYS_READ, fd, buf.as_mut_ptr() as usize, buf.len()) } +} + +pub fn rmdir(path: &str) -> Result { + unsafe { syscall2(SYS_RMDIR, path.as_ptr() as usize, path.len()) } +} + +pub fn unlink(path: &str) -> Result { + unsafe { syscall2(SYS_UNLINK, path.as_ptr() as usize, path.len()) } +} + +pub fn waitpid(pid: usize, status: &mut usize, options: usize) -> Result { + unsafe { syscall3(SYS_WAITPID, pid, status as *mut usize as usize, options) } +} + +pub fn write(fd: usize, buf: &[u8]) -> Result { + unsafe { syscall3(SYS_WRITE, fd, buf.as_ptr() as usize, buf.len()) } +} + +pub fn sched_yield() -> Result { + unsafe { syscall0(SYS_YIELD) } +} diff --git a/syscall/src/x86.rs b/syscall/src/x86.rs new file mode 100644 index 0000000..d4b53e9 --- /dev/null +++ b/syscall/src/x86.rs @@ -0,0 +1,61 @@ +use error::{Error, Result}; + +pub unsafe fn syscall0(mut a: usize) -> Result { + asm!("int 0x80" + : "={eax}"(a) + : "{eax}"(a) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall1(mut a: usize, b: usize) -> Result { + asm!("int 0x80" + : "={eax}"(a) + : "{eax}"(a), "{ebx}"(b) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall2(mut a: usize, b: usize, c: usize) -> Result { + asm!("int 0x80" + : "={eax}"(a) + : "{eax}"(a), "{ebx}"(b), "{ecx}"(c) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall3(mut a: usize, b: usize, c: usize, d: usize) -> Result { + asm!("int 0x80" + : "={eax}"(a) + : "{eax}"(a), "{ebx}"(b), "{ecx}"(c), "{edx}"(d) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Result { + asm!("int 0x80" + : "={eax}"(a) + : "{eax}"(a), "{ebx}"(b), "{ecx}"(c), "{edx}"(d), "{esi}"(e) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -> Result { + asm!("int 0x80" + : "={eax}"(a) + : "{eax}"(a), "{ebx}"(b), "{ecx}"(c), "{edx}"(d), "{esi}"(e), "{edi}"(f) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} diff --git a/syscall/src/x86_64.rs b/syscall/src/x86_64.rs new file mode 100644 index 0000000..3de2d5f --- /dev/null +++ b/syscall/src/x86_64.rs @@ -0,0 +1,61 @@ +use error::{Error, Result}; + +pub unsafe fn syscall0(mut a: usize) -> Result { + asm!("int 0x80" + : "={rax}"(a) + : "{rax}"(a) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall1(mut a: usize, b: usize) -> Result { + asm!("int 0x80" + : "={rax}"(a) + : "{rax}"(a), "{rbx}"(b) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall2(mut a: usize, b: usize, c: usize) -> Result { + asm!("int 0x80" + : "={rax}"(a) + : "{rax}"(a), "{rbx}"(b), "{rcx}"(c) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall3(mut a: usize, b: usize, c: usize, d: usize) -> Result { + asm!("int 0x80" + : "={rax}"(a) + : "{rax}"(a), "{rbx}"(b), "{rcx}"(c), "{rdx}"(d) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Result { + asm!("int 0x80" + : "={rax}"(a) + : "{rax}"(a), "{rbx}"(b), "{rcx}"(c), "{rdx}"(d), "{rsi}"(e) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -> Result { + asm!("int 0x80" + : "={rax}"(a) + : "{rax}"(a), "{rbx}"(b), "{rcx}"(c), "{rdx}"(d), "{rsi}"(e), "{rdi}"(f) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +}