2016-08-14 00:34:27 +02:00
|
|
|
//! # The Redox OS Kernel, version 2
|
|
|
|
//!
|
|
|
|
//! The Redox OS Kernel is a hybrid kernel that supports X86 systems and
|
|
|
|
//! provides Unix-like syscalls for primarily Rust applications
|
2016-08-14 00:53:05 +02:00
|
|
|
//!
|
|
|
|
//! ## Syscalls
|
|
|
|
//! Syscalls in Redox are often handled by userspace `schemes`.
|
|
|
|
//! The essential syscalls in Redox are as follows:
|
|
|
|
//!
|
2016-08-14 00:57:21 +02:00
|
|
|
//! ### Open
|
|
|
|
//! `open(path: &str, flags: usize) -> Result<file_descriptor: usize>`
|
|
|
|
//!
|
2016-08-14 00:53:05 +02:00
|
|
|
//! Open a file, providing a path as a `&str` and flags, defined elsewhere.
|
2016-08-14 02:21:46 +02:00
|
|
|
//!
|
2016-08-14 00:53:05 +02:00
|
|
|
//! Returns a number, known as a file descriptor, that is passed to other syscalls
|
|
|
|
//!
|
2016-08-14 00:57:21 +02:00
|
|
|
//! ### Close
|
|
|
|
//! `close(file_descriptor: usize) -> Result<()>`
|
|
|
|
//!
|
2016-08-14 00:53:05 +02:00
|
|
|
//! Close a file descriptor, providing the file descriptor from `open`
|
2016-08-14 02:21:46 +02:00
|
|
|
//!
|
2016-08-14 00:53:05 +02:00
|
|
|
//! Returns an error, `EBADF`, if the file descriptor was not found.
|
2016-08-14 02:21:46 +02:00
|
|
|
//!
|
2016-08-14 00:53:05 +02:00
|
|
|
//! This potential error is often ignored by userspace
|
|
|
|
//!
|
2016-08-14 00:57:21 +02:00
|
|
|
//! ### Duplicate
|
|
|
|
//! `dup(file_descriptor: usize) -> Result<file_descriptor: usize>`
|
|
|
|
//!
|
2016-08-14 00:53:05 +02:00
|
|
|
//! Duplicate a file descriptor, providing the file descriptor from `open`
|
2016-08-14 02:21:46 +02:00
|
|
|
//!
|
2016-08-14 00:53:05 +02:00
|
|
|
//! Returns a new file descriptor, or an error
|
|
|
|
//!
|
2016-08-14 00:57:21 +02:00
|
|
|
//! ### Read
|
|
|
|
//! `read(file_descriptor: usize, buffer: &mut [u8]) -> Result<count: usize>`
|
|
|
|
//!
|
2016-08-14 00:53:05 +02:00
|
|
|
//! Read from a file descriptor, providing the file descriptor from `open` and a mutable buffer
|
2016-08-14 02:21:46 +02:00
|
|
|
//!
|
2016-08-14 00:53:05 +02:00
|
|
|
//! Returns the number of bytes actually read, or an error
|
|
|
|
//!
|
2016-08-14 00:57:21 +02:00
|
|
|
//! ### Write
|
|
|
|
//! `write(file_descriptor: usize, buffer: &[u8]) -> Result<count: usize>`
|
|
|
|
//!
|
2016-08-14 00:53:05 +02:00
|
|
|
//! Write to a file descriptor, providing the file descriptor from `open` and a const buffer
|
2016-08-14 02:21:46 +02:00
|
|
|
//!
|
2016-08-14 00:53:05 +02:00
|
|
|
//! Returns the number of bytes actually written, or an error
|
|
|
|
//!
|
2016-08-14 00:57:21 +02:00
|
|
|
//! ### Stat
|
|
|
|
//! `fstat(file_descriptor: usize, stat: &mut Stat) -> Result<()>`
|
|
|
|
//!
|
2016-08-14 00:53:05 +02:00
|
|
|
//! Get information from a file descriptor, providing the file descriptor from `open`
|
|
|
|
//! and a mutable Stat struct, defined elsewhere.
|
2016-08-14 02:21:46 +02:00
|
|
|
//!
|
2016-08-14 00:53:05 +02:00
|
|
|
//! Returns an error if the operation failed
|
|
|
|
//!
|
2016-08-14 00:57:21 +02:00
|
|
|
//! ### Path
|
|
|
|
//! `fpath(file_descriptor: usize, buffer: &mut [u8]) -> Result<count: usize>`
|
|
|
|
//!
|
2016-08-14 02:21:46 +02:00
|
|
|
//! Read the path of a file descriptor, providing the file descriptor from `open` and
|
|
|
|
//! a mutable buffer.
|
|
|
|
//!
|
2016-08-14 00:53:05 +02:00
|
|
|
//! Returns the number of bytes actually read, or an error
|
2016-08-14 02:21:46 +02:00
|
|
|
//!
|
|
|
|
//! The buffer should be 4096 bytes, to ensure that the entire path will fit.
|
|
|
|
//! An error will be returned, `ENOBUFS`, if the buffer is not long enough for the name.
|
|
|
|
//! In this case, it is recommended to add one page, 4096 bytes, to the buffer and retry.
|
|
|
|
|
2016-08-15 06:05:32 +02:00
|
|
|
#![feature(alloc)]
|
2016-10-07 02:46:24 +02:00
|
|
|
#![feature(arc_counts)]
|
2016-08-19 03:44:31 +02:00
|
|
|
#![feature(asm)]
|
2016-08-15 06:05:32 +02:00
|
|
|
#![feature(collections)]
|
2016-08-15 02:16:56 +02:00
|
|
|
#![feature(const_fn)]
|
Orbital (#16)
* Port previous ethernet scheme
* Add ipd
* Fix initfs rebuilds, use QEMU user networking addresses in ipd
* Add tcp/udp, netutils, dns, and network config
* Add fsync to network driver
* Add dns, router, subnet by default
* Fix e1000 driver. Make ethernet and IP non-blocking to avoid deadlocks
* Add orbital server, WIP
* Add futex
* Add orbutils and orbital
* Update libstd, orbutils, and orbital
Move ANSI key encoding to vesad
* Add orbital assets
* Update orbital
* Update to add login manager
* Add blocking primitives, block for most things except waitpid, update orbital
* Wait in waitpid and IRQ, improvements for other waits
* Fevent in root scheme
* WIP: Switch to using fevent
* Reorganize
* Event based e1000d driver
* Superuser-only access to some network schemes, display, and disk
* Superuser root and irq schemes
* Fix orbital
2016-10-14 01:21:42 +02:00
|
|
|
#![feature(core_intrinsics)]
|
2016-08-18 16:10:08 +02:00
|
|
|
#![feature(drop_types_in_const)]
|
2016-09-23 00:14:45 +02:00
|
|
|
#![feature(heap_api)]
|
2016-10-05 22:24:08 +02:00
|
|
|
#![feature(integer_atomics)]
|
2016-09-12 05:04:34 +02:00
|
|
|
#![feature(never_type)]
|
2016-08-20 21:43:35 +02:00
|
|
|
#![feature(thread_local)]
|
2016-08-14 02:21:46 +02:00
|
|
|
#![no_std]
|
|
|
|
|
2016-08-18 03:34:33 +02:00
|
|
|
use arch::interrupt;
|
2016-08-14 17:31:35 +02:00
|
|
|
|
2016-08-14 22:59:18 +02:00
|
|
|
/// Architecture specific items (test)
|
|
|
|
#[cfg(test)]
|
2016-08-14 19:45:47 +02:00
|
|
|
#[macro_use]
|
2016-08-14 22:59:18 +02:00
|
|
|
extern crate arch_test as arch;
|
|
|
|
|
2016-08-26 01:03:01 +02:00
|
|
|
/// Architecture specific items (ARM)
|
|
|
|
#[cfg(all(not(test), target_arch = "arm"))]
|
|
|
|
#[macro_use]
|
|
|
|
extern crate arch_arm as arch;
|
|
|
|
|
2016-08-14 22:59:18 +02:00
|
|
|
/// Architecture specific items (x86_64)
|
|
|
|
#[cfg(all(not(test), target_arch = "x86_64"))]
|
|
|
|
#[macro_use]
|
|
|
|
extern crate arch_x86_64 as arch;
|
2016-08-14 02:21:46 +02:00
|
|
|
|
2016-08-15 06:05:32 +02:00
|
|
|
extern crate alloc;
|
|
|
|
#[macro_use]
|
|
|
|
extern crate collections;
|
|
|
|
|
2016-08-16 19:04:14 +02:00
|
|
|
#[macro_use]
|
|
|
|
extern crate bitflags;
|
2016-08-19 15:57:24 +02:00
|
|
|
extern crate goblin;
|
2016-08-16 19:04:14 +02:00
|
|
|
extern crate spin;
|
|
|
|
|
2016-09-15 16:35:07 +02:00
|
|
|
use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
|
|
|
|
|
2016-08-15 02:16:56 +02:00
|
|
|
/// Context management
|
|
|
|
pub mod context;
|
|
|
|
|
2016-08-19 03:44:31 +02:00
|
|
|
/// ELF file parsing
|
2016-08-26 01:03:01 +02:00
|
|
|
#[cfg(all(not(test), target_arch = "x86_64"))]
|
2016-08-19 03:44:31 +02:00
|
|
|
pub mod elf;
|
|
|
|
|
2016-08-15 05:38:32 +02:00
|
|
|
/// Schemes, filesystem handlers
|
|
|
|
pub mod scheme;
|
|
|
|
|
Orbital (#16)
* Port previous ethernet scheme
* Add ipd
* Fix initfs rebuilds, use QEMU user networking addresses in ipd
* Add tcp/udp, netutils, dns, and network config
* Add fsync to network driver
* Add dns, router, subnet by default
* Fix e1000 driver. Make ethernet and IP non-blocking to avoid deadlocks
* Add orbital server, WIP
* Add futex
* Add orbutils and orbital
* Update libstd, orbutils, and orbital
Move ANSI key encoding to vesad
* Add orbital assets
* Update orbital
* Update to add login manager
* Add blocking primitives, block for most things except waitpid, update orbital
* Wait in waitpid and IRQ, improvements for other waits
* Fevent in root scheme
* WIP: Switch to using fevent
* Reorganize
* Event based e1000d driver
* Superuser-only access to some network schemes, display, and disk
* Superuser root and irq schemes
* Fix orbital
2016-10-14 01:21:42 +02:00
|
|
|
/// Synchronization primitives
|
|
|
|
pub mod sync;
|
|
|
|
|
2016-08-14 23:58:35 +02:00
|
|
|
/// Syscall handlers
|
|
|
|
pub mod syscall;
|
|
|
|
|
2016-08-14 22:59:18 +02:00
|
|
|
/// Tests
|
|
|
|
#[cfg(test)]
|
|
|
|
pub mod tests;
|
|
|
|
|
2016-09-15 16:35:07 +02:00
|
|
|
#[thread_local]
|
|
|
|
static CPU_ID: AtomicUsize = ATOMIC_USIZE_INIT;
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
pub fn cpu_id() -> usize {
|
|
|
|
CPU_ID.load(Ordering::Relaxed)
|
|
|
|
}
|
|
|
|
|
2016-09-11 06:06:09 +02:00
|
|
|
pub extern fn userspace_init() {
|
2016-09-27 01:39:58 +02:00
|
|
|
assert_eq!(syscall::chdir(b"initfs:bin"), Ok(0));
|
2016-09-18 03:01:34 +02:00
|
|
|
|
2016-09-11 06:06:09 +02:00
|
|
|
assert_eq!(syscall::open(b"debug:", 0), Ok(0));
|
|
|
|
assert_eq!(syscall::open(b"debug:", 0), Ok(1));
|
|
|
|
assert_eq!(syscall::open(b"debug:", 0), Ok(2));
|
2016-08-24 18:35:42 +02:00
|
|
|
|
2016-09-12 00:48:58 +02:00
|
|
|
syscall::exec(b"initfs:bin/init", &[]).expect("failed to execute initfs:init");
|
2016-09-11 06:06:09 +02:00
|
|
|
|
|
|
|
panic!("initfs:init returned")
|
2016-08-24 18:35:42 +02:00
|
|
|
}
|
|
|
|
|
2016-08-14 17:31:35 +02:00
|
|
|
#[no_mangle]
|
2016-08-14 19:45:47 +02:00
|
|
|
pub extern fn kmain() {
|
2016-09-15 16:35:07 +02:00
|
|
|
CPU_ID.store(0, Ordering::SeqCst);
|
|
|
|
|
2016-08-20 22:32:45 +02:00
|
|
|
context::init();
|
|
|
|
|
2016-09-01 19:51:33 +02:00
|
|
|
let pid = syscall::getpid();
|
|
|
|
println!("BSP: {:?}", pid);
|
2016-08-19 03:44:31 +02:00
|
|
|
|
2016-09-12 02:03:10 +02:00
|
|
|
match context::contexts_mut().spawn(userspace_init) {
|
|
|
|
Ok(context_lock) => {
|
|
|
|
let mut context = context_lock.write();
|
2016-09-16 19:10:53 +02:00
|
|
|
context.status = context::Status::Runnable;
|
2016-09-12 02:03:10 +02:00
|
|
|
},
|
|
|
|
Err(err) => {
|
|
|
|
panic!("failed to spawn userspace_init: {:?}", err);
|
|
|
|
}
|
|
|
|
}
|
2016-08-24 18:35:42 +02:00
|
|
|
|
2016-08-14 19:45:47 +02:00
|
|
|
loop {
|
2016-09-15 16:39:20 +02:00
|
|
|
unsafe {
|
2016-09-15 16:40:16 +02:00
|
|
|
interrupt::disable();
|
2016-09-23 23:47:53 +02:00
|
|
|
if context::switch() {
|
|
|
|
interrupt::enable_and_nop();
|
|
|
|
} else {
|
|
|
|
interrupt::enable_and_halt();
|
|
|
|
}
|
2016-09-15 16:39:20 +02:00
|
|
|
}
|
2016-08-18 03:38:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2016-08-19 03:44:31 +02:00
|
|
|
pub extern fn kmain_ap(id: usize) {
|
2016-09-15 16:35:07 +02:00
|
|
|
CPU_ID.store(id, Ordering::SeqCst);
|
|
|
|
|
2016-08-20 22:32:45 +02:00
|
|
|
context::init();
|
|
|
|
|
2016-09-01 19:51:33 +02:00
|
|
|
let pid = syscall::getpid();
|
|
|
|
println!("AP {}: {:?}", id, pid);
|
2016-08-19 03:44:31 +02:00
|
|
|
|
2016-08-18 03:38:04 +02:00
|
|
|
loop {
|
|
|
|
unsafe { interrupt::enable_and_halt() }
|
2016-08-14 19:45:47 +02:00
|
|
|
}
|
2016-08-14 17:31:35 +02:00
|
|
|
}
|