From f39496306b68d6508b7554dbeb42ac343cc20f45 Mon Sep 17 00:00:00 2001 From: Emanuele Antonio Faraone Date: Sun, 1 Jan 2017 16:55:35 +0100 Subject: [PATCH 001/522] moved "old kernel" and "ZFS" at the bottom of the software list moved "old kernel" and "ZFS" at the bottom of the software list, because they are abandoned and the 'interest is smaller than the other --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 82c53ca..27a6578 100644 --- a/README.md +++ b/README.md @@ -46,8 +46,6 @@ The ecosystem and software Redox OS provides is listed below. | [Standard library](https://github.com/redox-os/libstd) | [**@jackpot51**](https://github.com/jackpot51) | [TFS (filesystem)](https://github.com/ticki/tfs) | [**@ticki**](https://github.com/ticki) | [The Redox book](https://github.com/redox-os/book) | [**@ticki**](https://github.com/ticki) -| [The old kernel](https://github.com/redox-os/old) | abandoned -| [ZFS](https://github.com/redox-os/zfs) | abandoned, superseded by TFS | [acid tests](https://github.com/redox-os/acid) | [**@jackpot51**](https://github.com/jackpot51) (co.: [**@ticki**](https://github.com/ticki), [**@nilset](https://github.com/nilset)) | [binutils](https://github.com/redox-os/binutils) | [**@ticki**](https://github.com/ticki) | [bots (other internal bots)](https://github.com/redox-os/bots) | [**@ticki**](https://github.com/ticki) @@ -71,6 +69,8 @@ The ecosystem and software Redox OS provides is listed below. | [redoxfs (old filesystem)](https://github.com/redox-os/redoxfs) | [**@jackpot51**](https://github.com/jackpot51) | [syscall](https://github.com/redox-os/syscall) | [**@jackpot51**](https://github.com/jackpot51) | [userutils](https://github.com/redox-os/userutils) | [**@jackpot51**](https://github.com/jackpot51) +| [The old kernel](https://github.com/redox-os/old) | **abandoned** +| [ZFS](https://github.com/redox-os/zfs) | **abandoned, superseded by TFS** ## Help! Redox won't compile! From 124c8c4f2e9847e565c09fc3146304185abedd3f Mon Sep 17 00:00:00 2001 From: Emanuele Antonio Faraone Date: Sun, 1 Jan 2017 18:45:33 +0100 Subject: [PATCH 002/522] Updated in alphabetic order --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 27a6578..f4ada3d 100644 --- a/README.md +++ b/README.md @@ -40,12 +40,6 @@ The ecosystem and software Redox OS provides is listed below. | Name (lexicographic order) | Maintainer |-----------------------------------------------------------------------------|--------------------------- -| [Ion (shell)](https://github.com/redox-os/ion) | [**@skylerberg**](https://github.com/skylerberg) & [**@jackpot51**](https://github.com/jackpot51) -| [RANSID](https://github.com/redox-os/ransid) | [**@jackpot51**](https://github.com/jackpot51) -| [Sodium (editor)](https://github.com/redox-os/sodium) | [**@ticki**](https://github.com/ticki) -| [Standard library](https://github.com/redox-os/libstd) | [**@jackpot51**](https://github.com/jackpot51) -| [TFS (filesystem)](https://github.com/ticki/tfs) | [**@ticki**](https://github.com/ticki) -| [The Redox book](https://github.com/redox-os/book) | [**@ticki**](https://github.com/ticki) | [acid tests](https://github.com/redox-os/acid) | [**@jackpot51**](https://github.com/jackpot51) (co.: [**@ticki**](https://github.com/ticki), [**@nilset](https://github.com/nilset)) | [binutils](https://github.com/redox-os/binutils) | [**@ticki**](https://github.com/ticki) | [bots (other internal bots)](https://github.com/redox-os/bots) | [**@ticki**](https://github.com/ticki) @@ -53,6 +47,7 @@ The ecosystem and software Redox OS provides is listed below. | [coreutils](https://github.com/redox-os/coreutils) | [**@ticki**](https://github.com/ticki) (co.: [**@stratact**](https://github.com/stratact)) | [extrautils](https://github.com/redox-os/extrautils) | [**@ticki**](https://github.com/ticki) | [games](https://github.com/redox-os/games) | [**@ticki**](https://github.com/ticki) +| [Ion (shell)](https://github.com/redox-os/ion) | [**@skylerberg**](https://github.com/skylerberg) & [**@jackpot51**](https://github.com/jackpot51) | [kernel](https://github.com/redox-os/kernel) | [**@jackpot51**](https://github.com/jackpot51) | [libextra](https://github.com/redox-os/libextra) | [**@ticki**](https://github.com/ticki) | [libpager](https://github.com/redox-os/libpager) | [**@ticki**](https://github.com/ticki) @@ -66,9 +61,14 @@ The ecosystem and software Redox OS provides is listed below. | [pkgutils (current package manager)](https://github.com/redox-os/pkgutils) | [**@jackpot51**](https://github.com/jackpot51) | [playbot (internal REPL bot)](https://github.com/redox-os/playbot) | [**@ticki**](https://github.com/ticki) | [ralloc](https://github.com/redox-os/ralloc) | [**@ticki**](https://github.com/ticki) +| [RANSID](https://github.com/redox-os/ransid) | [**@jackpot51**](https://github.com/jackpot51) | [redoxfs (old filesystem)](https://github.com/redox-os/redoxfs) | [**@jackpot51**](https://github.com/jackpot51) | [syscall](https://github.com/redox-os/syscall) | [**@jackpot51**](https://github.com/jackpot51) +| [Sodium (editor)](https://github.com/redox-os/sodium) | [**@ticki**](https://github.com/ticki) +| [Standard library](https://github.com/redox-os/libstd) | [**@jackpot51**](https://github.com/jackpot51) | [userutils](https://github.com/redox-os/userutils) | [**@jackpot51**](https://github.com/jackpot51) +| [TFS (filesystem)](https://github.com/ticki/tfs) | [**@ticki**](https://github.com/ticki) +| [The Redox book](https://github.com/redox-os/book) | [**@ticki**](https://github.com/ticki) | [The old kernel](https://github.com/redox-os/old) | **abandoned** | [ZFS](https://github.com/redox-os/zfs) | **abandoned, superseded by TFS** From bc57e608bca222f7517cb19c95cb575abae257e9 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 1 Jan 2017 16:45:30 -0700 Subject: [PATCH 003/522] Reduce size of kernel heap --- Makefile | 2 +- arch/x86_64/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 1329ee8..2cdb525 100644 --- a/Makefile +++ b/Makefile @@ -593,7 +593,7 @@ build/filesystem.bin: \ filesystem/bin/tar -$(FUMOUNT) build/filesystem/ rm -rf $@ build/filesystem/ - dd if=/dev/zero of=$@ bs=1M count=128 + dd if=/dev/zero of=$@ bs=1M count=64 cargo run --manifest-path schemes/redoxfs/Cargo.toml --release --bin redoxfs-mkfs $@ mkdir -p build/filesystem/ cargo build --manifest-path schemes/redoxfs/Cargo.toml --release --bin redoxfs diff --git a/arch/x86_64/src/lib.rs b/arch/x86_64/src/lib.rs index dc30d69..3a98ba0 100644 --- a/arch/x86_64/src/lib.rs +++ b/arch/x86_64/src/lib.rs @@ -37,7 +37,7 @@ pub extern crate x86; /// Offset to kernel heap pub const KERNEL_HEAP_OFFSET: usize = KERNEL_OFFSET + PML4_SIZE/2; /// Size of kernel heap - pub const KERNEL_HEAP_SIZE: usize = 256 * 1024 * 1024; // 256 MB + pub const KERNEL_HEAP_SIZE: usize = 128 * 1024 * 1024; // 128 MB /// Offset to kernel percpu variables //TODO: Use 64-bit fs offset to enable this pub const KERNEL_PERCPU_OFFSET: usize = KERNEL_HEAP_OFFSET - PML4_SIZE; From a8fd18cdeb2d16188b7f7288f3f5b4d21a6758cb Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 1 Jan 2017 17:59:10 -0700 Subject: [PATCH 004/522] Better panics --- arch/x86_64/src/lib.rs | 3 +++ arch/x86_64/src/paging/mapper.rs | 4 ++-- arch/x86_64/src/paging/mod.rs | 4 ++-- arch/x86_64/src/paging/table.rs | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/arch/x86_64/src/lib.rs b/arch/x86_64/src/lib.rs index 3a98ba0..609596b 100644 --- a/arch/x86_64/src/lib.rs +++ b/arch/x86_64/src/lib.rs @@ -83,6 +83,9 @@ pub extern crate x86; /// Offset to user temporary tls (used when cloning) pub const USER_TMP_TLS_OFFSET: usize = USER_TMP_STACK_OFFSET + PML4_SIZE; + /// Offset for usage in other temporary pages + pub const USER_TMP_MISC_OFFSET: usize = USER_TMP_TLS_OFFSET + PML4_SIZE; + /// Print to console #[macro_export] diff --git a/arch/x86_64/src/paging/mapper.rs b/arch/x86_64/src/paging/mapper.rs index cb4eccd..e53a080 100644 --- a/arch/x86_64/src/paging/mapper.rs +++ b/arch/x86_64/src/paging/mapper.rs @@ -67,7 +67,7 @@ impl Mapper { .next_table_mut(page.p4_index()) .and_then(|p3| p3.next_table_mut(page.p3_index())) .and_then(|p2| p2.next_table_mut(page.p2_index())) - .expect("mapping code does not support huge pages"); + .expect("unmap does not support huge pages"); let frame = p1[page.p1_index()].pointed_frame().unwrap(); p1[page.p1_index()].set_unused(); // TODO free p(1,2,3) table if empty @@ -80,7 +80,7 @@ impl Mapper { .next_table_mut(page.p4_index()) .and_then(|p3| p3.next_table_mut(page.p3_index())) .and_then(|p2| p2.next_table_mut(page.p2_index())) - .expect("mapping code does not support huge pages"); + .expect("unmap_return code does not support huge pages"); let frame = p1[page.p1_index()].pointed_frame().unwrap(); p1[page.p1_index()].set_unused(); frame diff --git a/arch/x86_64/src/paging/mod.rs b/arch/x86_64/src/paging/mod.rs index 2221438..fd289ce 100644 --- a/arch/x86_64/src/paging/mod.rs +++ b/arch/x86_64/src/paging/mod.rs @@ -110,7 +110,7 @@ pub unsafe fn init(cpu_id: usize, stack_start: usize, stack_end: usize) -> (Acti let mut active_table = ActivePageTable::new(); - let mut temporary_page = TemporaryPage::new(Page::containing_address(VirtualAddress::new(0x8_0000_0000))); + let mut temporary_page = TemporaryPage::new(Page::containing_address(VirtualAddress::new(::USER_TMP_MISC_OFFSET))); let mut new_table = { let frame = allocate_frame().expect("no more frames in paging::init new_table"); @@ -187,7 +187,7 @@ pub unsafe fn init_ap(cpu_id: usize, bsp_table: usize, stack_start: usize, stack let mut new_table = InactivePageTable::from_address(bsp_table); - let mut temporary_page = TemporaryPage::new(Page::containing_address(VirtualAddress::new(0x8_0000_0000))); + let mut temporary_page = TemporaryPage::new(Page::containing_address(VirtualAddress::new(::USER_TMP_MISC_OFFSET))); active_table.with(&mut new_table, &mut temporary_page, |mapper| { // Map tdata and tbss diff --git a/arch/x86_64/src/paging/table.rs b/arch/x86_64/src/paging/table.rs index f2fa466..c28db79 100644 --- a/arch/x86_64/src/paging/table.rs +++ b/arch/x86_64/src/paging/table.rs @@ -64,7 +64,7 @@ impl Table where L: HierarchicalLevel { pub fn next_table_create(&mut self, index: usize) -> &mut Table { if self.next_table(index).is_none() { assert!(!self[index].flags().contains(HUGE_PAGE), - "mapping code does not support huge pages"); + "next_table_create does not support huge pages"); let frame = allocate_frame().expect("no frames available"); self[index].set(frame, PRESENT | WRITABLE | USER_ACCESSIBLE /* Allow users to go down the page table, implement permissions at the page level */); self.next_table_mut(index).unwrap().zero(); From feee00039fac99dc01a9f8a795a5d8fc89d0e609 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 1 Jan 2017 18:00:24 -0700 Subject: [PATCH 005/522] Use variable for temporary page location --- kernel/syscall/process.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/syscall/process.rs b/kernel/syscall/process.rs index 8ffadf5..aeb7b7d 100644 --- a/kernel/syscall/process.rs +++ b/kernel/syscall/process.rs @@ -325,7 +325,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { let mut active_table = unsafe { ActivePageTable::new() }; - let mut temporary_page = TemporaryPage::new(Page::containing_address(VirtualAddress::new(0x8_0000_0000))); + let mut temporary_page = TemporaryPage::new(Page::containing_address(VirtualAddress::new(arch::USER_TMP_MISC_OFFSET))); let mut new_table = { let frame = allocate_frame().expect("no more frames in syscall::clone new_table"); From 4b780927d275ffcbb3b5f71d18e4ae23d98f1f0f Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 2 Jan 2017 08:53:50 -0700 Subject: [PATCH 006/522] Fallback in ahci driver when disk: not available, ability to list disk devices --- drivers/ahcid/src/ahci/disk.rs | 4 +- drivers/ahcid/src/ahci/hba.rs | 6 +- drivers/ahcid/src/main.rs | 15 +++- drivers/ahcid/src/scheme.rs | 128 +++++++++++++++++++++++---------- 4 files changed, 109 insertions(+), 44 deletions(-) diff --git a/drivers/ahcid/src/ahci/disk.rs b/drivers/ahcid/src/ahci/disk.rs index f28d5e8..4389425 100644 --- a/drivers/ahcid/src/ahci/disk.rs +++ b/drivers/ahcid/src/ahci/disk.rs @@ -11,7 +11,7 @@ pub struct Disk { size: u64, clb: Dma<[HbaCmdHeader; 32]>, ctbas: [Dma; 32], - fb: Dma<[u8; 256]>, + _fb: Dma<[u8; 256]>, buf: Dma<[u8; 256 * 512]> } @@ -41,7 +41,7 @@ impl Disk { size: size, clb: clb, ctbas: ctbas, - fb: fb, + _fb: fb, buf: buf }) } diff --git a/drivers/ahcid/src/ahci/hba.rs b/drivers/ahcid/src/ahci/hba.rs index 1981847..d22b706 100644 --- a/drivers/ahcid/src/ahci/hba.rs +++ b/drivers/ahcid/src/ahci/hba.rs @@ -389,7 +389,7 @@ pub struct HbaCmdTable { cfis: [Mmio; 64], // Command FIS // 0x40 - acmd: [Mmio; 16], // ATAPI command, 12 or 16 bytes + _acmd: [Mmio; 16], // ATAPI command, 12 or 16 bytes // 0x50 _rsv: [Mmio; 48], // Reserved @@ -402,12 +402,12 @@ pub struct HbaCmdTable { pub struct HbaCmdHeader { // DW0 cfl: Mmio, /* Command FIS length in DWORDS, 2 ~ 16, atapi: 4, write - host to device: 2, prefetchable: 1 */ - pm: Mmio, // Reset - 0x80, bist: 0x40, clear busy on ok: 0x20, port multiplier + _pm: Mmio, // Reset - 0x80, bist: 0x40, clear busy on ok: 0x20, port multiplier prdtl: Mmio, // Physical region descriptor table length in entries // DW1 - prdbc: Mmio, // Physical region descriptor byte count transferred + _prdbc: Mmio, // Physical region descriptor byte count transferred // DW2, 3 ctba: Mmio, // Command table descriptor base address diff --git a/drivers/ahcid/src/main.rs b/drivers/ahcid/src/main.rs index 1cd417c..4e8cbc9 100644 --- a/drivers/ahcid/src/main.rs +++ b/drivers/ahcid/src/main.rs @@ -10,14 +10,23 @@ extern crate syscall; use std::{env, usize}; use std::fs::File; use std::io::{Read, Write}; -use std::os::unix::io::{AsRawFd, FromRawFd}; -use syscall::{EVENT_READ, MAP_WRITE, Event, Packet, Scheme}; +use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; +use syscall::{EVENT_READ, MAP_WRITE, Event, Packet, Result, Scheme}; use scheme::DiskScheme; pub mod ahci; pub mod scheme; +fn create_scheme_fallback<'a>(name: &'a str, fallback: &'a str) -> Result<(&'a str, RawFd)> { + if let Ok(fd) = syscall::open(&format!(":{}", name), syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK) { + Ok((name, fd)) + } else { + syscall::open(&format!(":{}", fallback), syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK) + .map(|fd| (fallback, fd)) + } +} + fn main() { let mut args = env::args().skip(1); @@ -36,7 +45,7 @@ fn main() { if unsafe { syscall::clone(0).unwrap() } == 0 { let address = unsafe { syscall::physmap(bar, 4096, MAP_WRITE).expect("ahcid: failed to map address") }; { - let socket_fd = syscall::open(":disk", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK).expect("ahcid: failed to create disk scheme"); + let (_scheme_name, socket_fd) = create_scheme_fallback("disk", &name).expect("ahcid: failed to create disk scheme"); let mut socket = unsafe { File::from_raw_fd(socket_fd) }; syscall::fevent(socket_fd, EVENT_READ).expect("ahcid: failed to fevent disk scheme"); diff --git a/drivers/ahcid/src/scheme.rs b/drivers/ahcid/src/scheme.rs index 96a7c20..cd35d76 100644 --- a/drivers/ahcid/src/scheme.rs +++ b/drivers/ahcid/src/scheme.rs @@ -1,15 +1,24 @@ use std::collections::BTreeMap; use std::{cmp, str}; +use std::fmt::Write; +use std::io::Read; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; use spin::Mutex; -use syscall::{Error, EACCES, EBADF, EINVAL, ENOENT, Result, Scheme, Stat, MODE_FILE, SEEK_CUR, SEEK_END, SEEK_SET}; +use syscall::{Error, EACCES, EBADF, EINVAL, EISDIR, ENOENT, Result, Scheme, Stat, MODE_DIR, MODE_FILE, O_DIRECTORY, O_STAT, SEEK_CUR, SEEK_END, SEEK_SET}; use ahci::disk::Disk; +#[derive(Clone)] +enum Handle { + //TODO: Make these enum variants normal tuples (), not nested tuples (()) + List((Vec, usize)), + Disk((Arc>, usize)) +} + pub struct DiskScheme { disks: Box<[Arc>]>, - handles: Mutex>, usize)>>, + handles: Mutex>, next_id: AtomicUsize } @@ -29,18 +38,33 @@ impl DiskScheme { } impl Scheme for DiskScheme { - fn open(&self, path: &[u8], _flags: usize, uid: u32, _gid: u32) -> Result { + fn open(&self, path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result { if uid == 0 { - let path_str = str::from_utf8(path).or(Err(Error::new(ENOENT)))?; + let path_str = str::from_utf8(path).or(Err(Error::new(ENOENT)))?.trim_matches('/'); + if path_str.is_empty() { + if flags & O_DIRECTORY == O_DIRECTORY || flags & O_STAT == O_STAT { + let mut list = String::new(); - let i = path_str.parse::().or(Err(Error::new(ENOENT)))?; + for i in 0..self.disks.len() { + write!(list, "{}\n", i).unwrap(); + } - if let Some(disk) = self.disks.get(i) { - let id = self.next_id.fetch_add(1, Ordering::SeqCst); - self.handles.lock().insert(id, (disk.clone(), 0)); - Ok(id) + let id = self.next_id.fetch_add(1, Ordering::SeqCst); + self.handles.lock().insert(id, Handle::List((list.into_bytes(), 0))); + Ok(id) + } else { + Err(Error::new(EISDIR)) + } } else { - Err(Error::new(ENOENT)) + let i = path_str.parse::().or(Err(Error::new(ENOENT)))?; + + if let Some(disk) = self.disks.get(i) { + let id = self.next_id.fetch_add(1, Ordering::SeqCst); + self.handles.lock().insert(id, Handle::Disk((disk.clone(), 0))); + Ok(id) + } else { + Err(Error::new(ENOENT)) + } } } else { Err(Error::new(EACCES)) @@ -61,46 +85,78 @@ impl Scheme for DiskScheme { fn fstat(&self, id: usize, stat: &mut Stat) -> Result { let handles = self.handles.lock(); - let handle = handles.get(&id).ok_or(Error::new(EBADF))?; - - stat.st_mode = MODE_FILE; - stat.st_size = handle.0.lock().size(); - Ok(0) + match *handles.get(&id).ok_or(Error::new(EBADF))? { + Handle::List(ref handle) => { + stat.st_mode = MODE_DIR; + stat.st_size = handle.0.len() as u64; + Ok(0) + }, + Handle::Disk(ref handle) => { + stat.st_mode = MODE_FILE; + stat.st_size = handle.0.lock().size(); + Ok(0) + } + } } fn read(&self, id: usize, buf: &mut [u8]) -> Result { let mut handles = self.handles.lock(); - let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; - - let mut disk = handle.0.lock(); - let count = disk.read((handle.1 as u64)/512, buf)?; - handle.1 += count; - Ok(count) + match *handles.get_mut(&id).ok_or(Error::new(EBADF))? { + Handle::List(ref mut handle) => { + let count = (&handle.0[handle.1..]).read(buf).unwrap(); + handle.1 += count; + Ok(count) + }, + Handle::Disk(ref mut handle) => { + let mut disk = handle.0.lock(); + let count = disk.read((handle.1 as u64)/512, buf)?; + handle.1 += count; + Ok(count) + } + } } fn write(&self, id: usize, buf: &[u8]) -> Result { let mut handles = self.handles.lock(); - let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; - - let mut disk = handle.0.lock(); - let count = disk.write((handle.1 as u64)/512, buf)?; - handle.1 += count; - Ok(count) + match *handles.get_mut(&id).ok_or(Error::new(EBADF))? { + Handle::List(_) => { + Err(Error::new(EBADF)) + }, + Handle::Disk(ref mut handle) => { + let mut disk = handle.0.lock(); + let count = disk.write((handle.1 as u64)/512, buf)?; + handle.1 += count; + Ok(count) + } + } } fn seek(&self, id: usize, pos: usize, whence: usize) -> Result { let mut handles = self.handles.lock(); - let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; + match *handles.get_mut(&id).ok_or(Error::new(EBADF))? { + Handle::List(ref mut handle) => { + let len = handle.0.len() as usize; + handle.1 = match whence { + SEEK_SET => cmp::min(len, pos), + SEEK_CUR => cmp::max(0, cmp::min(len as isize, handle.1 as isize + pos as isize)) as usize, + SEEK_END => cmp::max(0, cmp::min(len as isize, len as isize + pos as isize)) as usize, + _ => return Err(Error::new(EINVAL)) + }; - let len = handle.0.lock().size() as usize; - handle.1 = match whence { - SEEK_SET => cmp::min(len, pos), - SEEK_CUR => cmp::max(0, cmp::min(len as isize, handle.1 as isize + pos as isize)) as usize, - SEEK_END => cmp::max(0, cmp::min(len as isize, len as isize + pos as isize)) as usize, - _ => return Err(Error::new(EINVAL)) - }; + Ok(handle.1) + }, + Handle::Disk(ref mut handle) => { + let len = handle.0.lock().size() as usize; + handle.1 = match whence { + SEEK_SET => cmp::min(len, pos), + SEEK_CUR => cmp::max(0, cmp::min(len as isize, handle.1 as isize + pos as isize)) as usize, + SEEK_END => cmp::max(0, cmp::min(len as isize, len as isize + pos as isize)) as usize, + _ => return Err(Error::new(EINVAL)) + }; - Ok(handle.1) + Ok(handle.1) + } + } } fn close(&self, id: usize) -> Result { From a769dcb9176a1c611b055551f945ad4fde25ceb6 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 2 Jan 2017 12:59:41 -0700 Subject: [PATCH 007/522] Update libc artifacts, pass linker arguments to fix linking --- Makefile | 14 +++++++------- libc-artifacts | 2 +- libstd/openlibm | 1 + x86_64-unknown-redox.json | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) create mode 160000 libstd/openlibm diff --git a/Makefile b/Makefile index 2cdb525..bbdbc15 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ ROOT=$(PWD) export RUST_TARGET_PATH=$(ROOT)/targets #TODO: Use libssp -export CFLAGS=-fno-stack-protector -U_FORTIFY_SOURCE +export CFLAGS=-fno-stack-protector -U_FORTIFY_SOURCE -I $(ROOT)/libc-artifacts/usr/include # Kernel variables KTARGET=$(ARCH)-unknown-none @@ -234,10 +234,10 @@ else VBM=VBoxManage endif - KRUSTCFLAGS+=-C linker=$(CC) - KCARGOFLAGS+=-C linker=$(CC) - RUSTCFLAGS+=-C linker=$(CC) - CARGOFLAGS+=-C linker=$(CC) + KRUSTCFLAGS+=-C linker=$(CC) -C link-args="$(CFLAGS)" + KCARGOFLAGS+=-C linker=$(CC) -C link-args="$(CFLAGS)" + RUSTCFLAGS+=-C linker=$(CC) -C link-args="$(CFLAGS)" + CARGOFLAGS+=-C linker=$(CC) -C link-args="$(CFLAGS)" %.list: % objdump -C -M intel -D $< > $@ @@ -362,7 +362,7 @@ $(KBUILD)/kernel_live: $(KBUILD)/libkernel_live.a # Userspace recipes $(BUILD)/libstd.rlib: rust/src/libstd/Cargo.toml rust/src/libstd/** mkdir -p $(BUILD) - $(CARGO) rustc --verbose --manifest-path $< $(CARGOFLAGS) -L native=libc-artifacts/lib -o $@ + $(CARGO) rustc --verbose --manifest-path $< $(CARGOFLAGS) -L native=libc-artifacts/usr/lib -o $@ cp rust/src/target/$(TARGET)/release/deps/*.rlib $(BUILD) initfs/bin/%: drivers/%/Cargo.toml drivers/%/src/** $(BUILD)/libstd.rlib @@ -373,7 +373,7 @@ initfs/bin/%: drivers/%/Cargo.toml drivers/%/src/** $(BUILD)/libstd.rlib initfs/bin/%: programs/%/Cargo.toml programs/%/src/** $(BUILD)/libstd.rlib mkdir -p initfs/bin $(CARGO) rustc --manifest-path $< $(CARGOFLAGS) -o $@ - #strip $@ + strip $@ initfs/bin/%: schemes/%/Cargo.toml schemes/%/src/** $(BUILD)/libstd.rlib mkdir -p initfs/bin diff --git a/libc-artifacts b/libc-artifacts index b0e2a74..e1201a1 160000 --- a/libc-artifacts +++ b/libc-artifacts @@ -1 +1 @@ -Subproject commit b0e2a74a505d0bc6ffea05d81fe239b1beb5c246 +Subproject commit e1201a13a85c35e053dcf583aadfee27cdd12f7c diff --git a/libstd/openlibm b/libstd/openlibm new file mode 160000 index 0000000..3c837e7 --- /dev/null +++ b/libstd/openlibm @@ -0,0 +1 @@ +Subproject commit 3c837e79655c4be724efb945a6345ec97c07635c diff --git a/x86_64-unknown-redox.json b/x86_64-unknown-redox.json index 362ef9c..d9df631 100644 --- a/x86_64-unknown-redox.json +++ b/x86_64-unknown-redox.json @@ -9,7 +9,7 @@ "vendor": "unknown", "target-family": "redox", "pre-link-args": ["-m64", "-Wl,--as-needed", "-Wl,-z,noexecstack", "-nostartfiles", "-nostdlib", "-static"], - "late-link-args": ["libc-artifacts/lib/crt0.o", "libc-artifacts/lib/libm.a", "libc-artifacts/lib/libc.a", "libc-artifacts/lib/libgcc.a"], + "late-link-args": ["libc-artifacts/usr/lib/crt0.o", "libc-artifacts/usr/lib/libm.a", "libc-artifacts/usr/lib/libc.a", "libc-artifacts/usr/lib/libgcc.a"], "features": "", "dynamic-linking": false, "executables": true, From f6e32cdc4e95f816da5c4bd941820dfd78585e33 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 2 Jan 2017 13:05:59 -0700 Subject: [PATCH 008/522] Remove openlibm --- libstd/openlibm | 1 - 1 file changed, 1 deletion(-) delete mode 160000 libstd/openlibm diff --git a/libstd/openlibm b/libstd/openlibm deleted file mode 160000 index 3c837e7..0000000 --- a/libstd/openlibm +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 3c837e79655c4be724efb945a6345ec97c07635c From 289671b4c1362abc50e3fa79b8b34b32de27dceb Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 2 Jan 2017 13:54:53 -0700 Subject: [PATCH 009/522] Update libc artifacts --- libc-artifacts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libc-artifacts b/libc-artifacts index e1201a1..3ee3dad 160000 --- a/libc-artifacts +++ b/libc-artifacts @@ -1 +1 @@ -Subproject commit e1201a13a85c35e053dcf583aadfee27cdd12f7c +Subproject commit 3ee3dad4f58f9ad4048c9ec0601c5c0fab32640f From c8cbefc788fa94b35d71aa9df96993aa963e8ab8 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 2 Jan 2017 14:35:04 -0700 Subject: [PATCH 010/522] Update to use define file --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index bbdbc15..46b42d3 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,10 @@ ROOT=$(PWD) export RUST_TARGET_PATH=$(ROOT)/targets #TODO: Use libssp -export CFLAGS=-fno-stack-protector -U_FORTIFY_SOURCE -I $(ROOT)/libc-artifacts/usr/include +export CFLAGS=-ffreestanding -nostartfiles -nostdlib -nodefaultlibs \ + -undef -imacros $(ROOT)/libc-artifacts/define.h \ + -isystem $(ROOT)/libc-artifacts/usr/include \ + -fno-stack-protector -U_FORTIFY_SOURCE # Kernel variables KTARGET=$(ARCH)-unknown-none From 9e63156c09d4d766a3bfe2ce320813aea80bba1e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 2 Jan 2017 14:35:30 -0700 Subject: [PATCH 011/522] Update libc --- libc-artifacts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libc-artifacts b/libc-artifacts index 3ee3dad..0f3467f 160000 --- a/libc-artifacts +++ b/libc-artifacts @@ -1 +1 @@ -Subproject commit 3ee3dad4f58f9ad4048c9ec0601c5c0fab32640f +Subproject commit 0f3467ff1925c0b03b58110aeda924b38ae1c6fc From 6205765d07ca21a1785f80ab39f509c5a55a4648 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 2 Jan 2017 14:46:23 -0700 Subject: [PATCH 012/522] Attempt to fix builds on OS X --- .travis.yml | 5 ++--- bootstrap.sh | 33 ++++++++++++++++----------------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/.travis.yml b/.travis.yml index 22670b6..f2c97b2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ rust: cache: cargo os: - linux +- osx dist: trusty before_install: - if [ `uname` = "Linux" ]; then @@ -14,9 +15,7 @@ before_install: sudo chown root:$USER /etc/fuse.conf; fi - if [ `uname` = "Darwin" ]; then brew update && - brew install nasm gcc49 pkg-config Caskroom/cask/osxfuse && - brew tap glendc/gcc_cross_compilers && - brew install glendc/gcc_cross_compilers/x64-elf-binutils glendc/gcc_cross_compilers/x64-elf-gcc; + brew install nasm gcc49 pkg-config Caskroom/cask/osxfuse djphoenix/gcc_cross_compilers/x86_64-elf-gcc; fi script: - make clean && diff --git a/bootstrap.sh b/bootstrap.sh index 7e1c9a8..1d1be78 100644 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -4,7 +4,7 @@ # This function is simply a banner to introduce the script ########################################################## banner() -{ +{ echo "|------------------------------------------|" echo "|----- Welcome to the redox bootstrap -----|" echo "|------------------------------------------|" @@ -129,8 +129,7 @@ osx_homebrew() install_brew_pkg "pkg-config" install_brew_cask_pkg "osxfuse" - install_brew_pkg "glendc/gcc_cross_compilers/x64-elf-binutils" "x86_64-elf-gcc" - install_brew_pkg "glendc/gcc_cross_compilers/x64-elf-gcc" "x86_64-elf-gcc" + install_brew_pkg "djphoenix/gcc_cross_compilers/x86_64-elf-gcc" } ############################################################################### @@ -171,7 +170,7 @@ archLinux() # This function takes care of installing all dependencies for building redox on # debian based linux # @params: $1 the emulator to install, virtualbox or qemu -# $2 the package manager to use +# $2 the package manager to use ############################################################################### ubuntu() { @@ -348,7 +347,7 @@ usage() echo " -e [emulator] Install specific emulator, virtualbox or qemu" echo " -p [package Choose an Ubuntu package manager, apt-fast or" echo " manager] aptitude" - echo " -d Only install the dependencies, skip boot step" + echo " -d Only install the dependencies, skip boot step" echo "EXAMPLES:" echo echo "./bootstrap.sh -b buddy -e qemu" @@ -357,7 +356,7 @@ usage() #################################################################################### # This function takes care of everything associated to rust, and the version manager -# That controls it, it can install rustup and uninstall multirust as well as making +# That controls it, it can install rustup and uninstall multirust as well as making # sure that the correct version of rustc is selected by rustup #################################################################################### rustInstall() { @@ -370,7 +369,7 @@ rustInstall() { printf "Uninstall multirust (y/N):" read multirust if echo "$multirust" | grep -iq "^y" ;then - sudo /usr/local/lib/rustlib/uninstall.sh + sudo /usr/local/lib/rustlib/uninstall.sh else echo "Please manually uninstall multirust and any other versions of rust, then re-run bootstrap." exit @@ -378,7 +377,7 @@ rustInstall() { else echo "Old multirust not installed, you are good to go." fi - # If rustup is not installed we should offer to install it for them + # If rustup is not installed we should offer to install it for them if [ -z "$(which rustup)" ]; then echo "You do not have rustup installed." echo "We HIGHLY reccomend using rustup." @@ -389,22 +388,22 @@ rustInstall() { if echo "$rustup" | grep -iq "^y" ;then #install rustup curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain nightly - # You have to add the rustup variables to the $PATH + # You have to add the rustup variables to the $PATH echo "export PATH=\"\$HOME/.cargo/bin:\$PATH\"" >> ~/.bashrc # source the variables so that we can execute rustup commands in the current shell - source ~/.cargo/env + source ~/.cargo/env rustup default nightly else echo "Rustup will not be installed!" fi - fi - # + fi + # if [ -z "$(which rustc)" ]; then echo "Rust is not installed" echo "Please either run the script again, accepting rustup install" echo "or install rustc nightly manually (not reccomended) via:" echo "\#curl -sSf https://static.rust-lang.org/rustup.sh | sh -s -- --channel=nightly" - exit + exit fi # If the system has rustup installed then update rustc to the latest nightly if hash 2>/dev/null rustup; then @@ -425,7 +424,7 @@ rustInstall() { } #################################################################### -# This function gets the current build status from travis and prints +# This function gets the current build status from travis and prints # a message to the user #################################################################### statusCheck() { @@ -440,7 +439,7 @@ statusCheck() { echo "********************************************" elif echo "$i" | grep -iq "null" ;then echo - echo "******************************************************************" + echo "******************************************************************" echo "The Travis build did not finish, this is an error with its config." echo "I cannot reliably determine whether the build is succeding or not." echo "Consider checking for and maybe opening an issue on github" @@ -463,7 +462,7 @@ statusCheck() { boot() { echo "Cloning github repo..." - git clone https://github.com/redox-os/redox.git --origin upstream --recursive + git clone https://github.com/redox-os/redox.git --origin upstream --recursive rustInstall echo "Cleaning up..." rm bootstrap.sh @@ -511,7 +510,7 @@ banner if [ "Darwin" == "$(uname -s)" ]; then osx "$emulator" else - # Here we will user package managers to determine which operating system the user is using + # Here we will user package managers to determine which operating system the user is using # Arch linux if hash 2>/dev/null pacman; then archLinux "$emulator" From 93fbb22fd2e35c1547cd95e0c2b8e011ced22764 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 2 Jan 2017 15:37:24 -0700 Subject: [PATCH 013/522] Update --- Makefile | 5 ++++- libc-artifacts | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 46b42d3..8ecad08 100644 --- a/Makefile +++ b/Makefile @@ -4,10 +4,13 @@ ROOT=$(PWD) export RUST_TARGET_PATH=$(ROOT)/targets #TODO: Use libssp -export CFLAGS=-ffreestanding -nostartfiles -nostdlib -nodefaultlibs \ +export CFLAGS=-nostartfiles -nostdlib -nodefaultlibs \ -undef -imacros $(ROOT)/libc-artifacts/define.h \ -isystem $(ROOT)/libc-artifacts/usr/include \ -fno-stack-protector -U_FORTIFY_SOURCE +export CXXFLAGS=$(CFLAGS) -nostdinc++ \ + -isystem $(ROOT)/libc-artifacts/usr/include/c++/7.0.0 \ + -isystem $(ROOT)/libc-artifacts/usr/include/c++/7.0.0/x86_64-elf-redox # Kernel variables KTARGET=$(ARCH)-unknown-none diff --git a/libc-artifacts b/libc-artifacts index 0f3467f..44e8068 160000 --- a/libc-artifacts +++ b/libc-artifacts @@ -1 +1 @@ -Subproject commit 0f3467ff1925c0b03b58110aeda924b38ae1c6fc +Subproject commit 44e806831acb32362e0d0fd55fad01e2f7ff443f From cec121273f78bb8e37c77adb0c5c4ac955e67d5f Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 2 Jan 2017 16:06:57 -0700 Subject: [PATCH 014/522] Fix unmap_return panic --- arch/x86_64/src/paging/mapper.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86_64/src/paging/mapper.rs b/arch/x86_64/src/paging/mapper.rs index e53a080..faa5ec6 100644 --- a/arch/x86_64/src/paging/mapper.rs +++ b/arch/x86_64/src/paging/mapper.rs @@ -80,7 +80,7 @@ impl Mapper { .next_table_mut(page.p4_index()) .and_then(|p3| p3.next_table_mut(page.p3_index())) .and_then(|p2| p2.next_table_mut(page.p2_index())) - .expect("unmap_return code does not support huge pages"); + .expect("unmap_return does not support huge pages"); let frame = p1[page.p1_index()].pointed_frame().unwrap(); p1[page.p1_index()].set_unused(); frame From 6d923ad96fb4f6db54d5964d2a3abb9c419375e4 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 2 Jan 2017 16:14:12 -0700 Subject: [PATCH 015/522] Update artifacts --- Makefile | 13 ++++++++----- libc-artifacts | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 8ecad08..f0bee80 100644 --- a/Makefile +++ b/Makefile @@ -5,12 +5,15 @@ export RUST_TARGET_PATH=$(ROOT)/targets #TODO: Use libssp export CFLAGS=-nostartfiles -nostdlib -nodefaultlibs \ - -undef -imacros $(ROOT)/libc-artifacts/define.h \ - -isystem $(ROOT)/libc-artifacts/usr/include \ - -fno-stack-protector -U_FORTIFY_SOURCE -export CXXFLAGS=$(CFLAGS) -nostdinc++ \ + -undef -imacros $(ROOT)/libc-artifacts/define.h \ + -isystem $(ROOT)/libc-artifacts/usr/lib/gcc/x86_64-elf-redox/7.0.0/include \ + -isystem $(ROOT)/libc-artifacts/usr/lib/gcc/x86_64-elf-redox/7.0.0/include-fixed \ + -isystem $(ROOT)/libc-artifacts/usr/include \ + -fno-stack-protector -U_FORTIFY_SOURCE +export CXXFLAGS=$(CFLAGS) \ -isystem $(ROOT)/libc-artifacts/usr/include/c++/7.0.0 \ - -isystem $(ROOT)/libc-artifacts/usr/include/c++/7.0.0/x86_64-elf-redox + -isystem $(ROOT)/libc-artifacts/usr/include/c++/7.0.0/x86_64-elf-redox \ + -isystem $(ROOT)/libc-artifacts/usr/include/c++/7.0.0/backward # Kernel variables KTARGET=$(ARCH)-unknown-none diff --git a/libc-artifacts b/libc-artifacts index 44e8068..8e0ed0a 160000 --- a/libc-artifacts +++ b/libc-artifacts @@ -1 +1 @@ -Subproject commit 44e806831acb32362e0d0fd55fad01e2f7ff443f +Subproject commit 8e0ed0ac0368be54ca375147b758b669a98c652f From 46c5ee0b4e234d8d7f7204fafc86c40f75bc1cb8 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 2 Jan 2017 16:20:51 -0700 Subject: [PATCH 016/522] Remove CXX --- Makefile | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Makefile b/Makefile index f0bee80..a10c240 100644 --- a/Makefile +++ b/Makefile @@ -10,10 +10,6 @@ export CFLAGS=-nostartfiles -nostdlib -nodefaultlibs \ -isystem $(ROOT)/libc-artifacts/usr/lib/gcc/x86_64-elf-redox/7.0.0/include-fixed \ -isystem $(ROOT)/libc-artifacts/usr/include \ -fno-stack-protector -U_FORTIFY_SOURCE -export CXXFLAGS=$(CFLAGS) \ - -isystem $(ROOT)/libc-artifacts/usr/include/c++/7.0.0 \ - -isystem $(ROOT)/libc-artifacts/usr/include/c++/7.0.0/x86_64-elf-redox \ - -isystem $(ROOT)/libc-artifacts/usr/include/c++/7.0.0/backward # Kernel variables KTARGET=$(ARCH)-unknown-none @@ -182,7 +178,6 @@ ifeq ($(ARCH),arm) QEMUFLAGS+=-nographic export CC=$(ARCH)-none-eabi-gcc - export CXX=$(ARCH)-none-eabi-g++ export LD=$(ARCH)-none-eabi-ld KRUSTCFLAGS+=-C linker=$(CC) @@ -222,7 +217,6 @@ else UNAME := $(shell uname) ifeq ($(UNAME),Darwin) export CC=$(ARCH)-elf-gcc - export CXX=$(ARCH)-elf-g++ ECHO=/bin/echo FUMOUNT=sudo umount export LD=$(ARCH)-elf-ld @@ -231,7 +225,6 @@ else VBM="/Applications/VirtualBox.app/Contents/MacOS/VBoxManage" else export CC=gcc - export CXX=g++ ECHO=echo FUMOUNT=fusermount -u export LD=ld From 0fee203197cb6c75234c6b63ebfc62978951e08f Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 2 Jan 2017 16:24:41 -0700 Subject: [PATCH 017/522] Revert c++ headers --- libc-artifacts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libc-artifacts b/libc-artifacts index 8e0ed0a..0f3467f 160000 --- a/libc-artifacts +++ b/libc-artifacts @@ -1 +1 @@ -Subproject commit 8e0ed0ac0368be54ca375147b758b669a98c652f +Subproject commit 0f3467ff1925c0b03b58110aeda924b38ae1c6fc From cfec167ab6801ca9f184701dcf3fb9f1ae729bcd Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 2 Jan 2017 16:25:07 -0700 Subject: [PATCH 018/522] Simplify include path --- Makefile | 2 -- 1 file changed, 2 deletions(-) diff --git a/Makefile b/Makefile index a10c240..4cad623 100644 --- a/Makefile +++ b/Makefile @@ -6,8 +6,6 @@ export RUST_TARGET_PATH=$(ROOT)/targets #TODO: Use libssp export CFLAGS=-nostartfiles -nostdlib -nodefaultlibs \ -undef -imacros $(ROOT)/libc-artifacts/define.h \ - -isystem $(ROOT)/libc-artifacts/usr/lib/gcc/x86_64-elf-redox/7.0.0/include \ - -isystem $(ROOT)/libc-artifacts/usr/lib/gcc/x86_64-elf-redox/7.0.0/include-fixed \ -isystem $(ROOT)/libc-artifacts/usr/include \ -fno-stack-protector -U_FORTIFY_SOURCE From a1f0e0e5471f7f5ee9285bae0787d27751b06870 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 2 Jan 2017 16:31:54 -0700 Subject: [PATCH 019/522] Fix strip command on OS X --- Makefile | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index 4cad623..5e15394 100644 --- a/Makefile +++ b/Makefile @@ -219,6 +219,7 @@ else FUMOUNT=sudo umount export LD=$(ARCH)-elf-ld export LDFLAGS=--gc-sections + export STRIP=$(ARCH)-elf-strip VB_AUDIO=coreaudio VBM="/Applications/VirtualBox.app/Contents/MacOS/VBoxManage" else @@ -227,6 +228,7 @@ else FUMOUNT=fusermount -u export LD=ld export LDFLAGS=--gc-sections + export STRIP=strip ifneq ($(kvm),no) QEMUFLAGS+=-enable-kvm -cpu host endif @@ -368,17 +370,17 @@ $(BUILD)/libstd.rlib: rust/src/libstd/Cargo.toml rust/src/libstd/** initfs/bin/%: drivers/%/Cargo.toml drivers/%/src/** $(BUILD)/libstd.rlib mkdir -p initfs/bin $(CARGO) rustc --manifest-path $< $(CARGOFLAGS) -o $@ - strip $@ + $(STRIP) $@ initfs/bin/%: programs/%/Cargo.toml programs/%/src/** $(BUILD)/libstd.rlib mkdir -p initfs/bin $(CARGO) rustc --manifest-path $< $(CARGOFLAGS) -o $@ - strip $@ + $(STRIP) $@ initfs/bin/%: schemes/%/Cargo.toml schemes/%/src/** $(BUILD)/libstd.rlib mkdir -p initfs/bin $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - strip $@ + $(STRIP) $@ $(BUILD)/initfs.rs: \ initfs/bin/init \ @@ -405,12 +407,12 @@ $(BUILD)/initfs.rs: \ filesystem/sbin/%: drivers/%/Cargo.toml drivers/%/src/** $(BUILD)/libstd.rlib mkdir -p filesystem/sbin $(CARGO) rustc --manifest-path $< $(CARGOFLAGS) -o $@ - strip $@ + $(STRIP) $@ filesystem/bin/%: programs/%/Cargo.toml programs/%/src/** $(BUILD)/libstd.rlib mkdir -p filesystem/bin $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - strip $@ + $(STRIP) $@ filesystem/bin/sh: filesystem/bin/ion cp $< $@ @@ -418,52 +420,52 @@ filesystem/bin/sh: filesystem/bin/ion filesystem/bin/%: programs/binutils/Cargo.toml programs/binutils/src/bin/%.rs $(BUILD)/libstd.rlib mkdir -p filesystem/bin $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - strip $@ + $(STRIP) $@ filesystem/bin/%: programs/coreutils/Cargo.toml programs/coreutils/src/bin/%.rs $(BUILD)/libstd.rlib mkdir -p filesystem/bin $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - strip $@ + $(STRIP) $@ filesystem/bin/%: programs/extrautils/Cargo.toml programs/extrautils/src/bin/%.rs $(BUILD)/libstd.rlib mkdir -p filesystem/bin $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - strip $@ + $(STRIP) $@ filesystem/bin/%: programs/games/Cargo.toml programs/games/src/%/**.rs $(BUILD)/libstd.rlib mkdir -p filesystem/bin $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - strip $@ + $(STRIP) $@ filesystem/bin/%: programs/netutils/Cargo.toml programs/netutils/src/%/**.rs $(BUILD)/libstd.rlib mkdir -p filesystem/bin $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - strip $@ + $(STRIP) $@ filesystem/ui/bin/%: programs/orbutils/Cargo.toml programs/orbutils/src/%/**.rs $(BUILD)/libstd.rlib mkdir -p filesystem/ui/bin $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - strip $@ + $(STRIP) $@ filesystem/bin/%: programs/pkgutils/Cargo.toml programs/pkgutils/src/%/**.rs $(BUILD)/libstd.rlib mkdir -p filesystem/bin $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - strip $@ + $(STRIP) $@ filesystem/bin/%: programs/userutils/Cargo.toml programs/userutils/src/bin/%.rs $(BUILD)/libstd.rlib mkdir -p filesystem/bin $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - strip $@ + $(STRIP) $@ filesystem/sbin/%: schemes/%/Cargo.toml schemes/%/src/** $(BUILD)/libstd.rlib mkdir -p filesystem/sbin $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - strip $@ + $(STRIP) $@ filesystem/sbin/redoxfs-mkfs: schemes/redoxfs/Cargo.toml schemes/redoxfs/src/** $(BUILD)/libstd.rlib mkdir -p filesystem/bin $(CARGO) rustc --manifest-path $< --bin redoxfs-mkfs $(CARGOFLAGS) -o $@ - strip $@ + $(STRIP) $@ drivers: \ filesystem/sbin/pcid \ From 68093986b5540bb32022c06f55c103694538f3c3 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 2 Jan 2017 16:50:05 -0700 Subject: [PATCH 020/522] Export target --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5e15394..2062506 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ KCARGO=RUSTC="$(KRUSTC)" RUSTDOC="$(KRUSTDOC)" cargo KCARGOFLAGS=--target $(KTARGET) --release -- -C soft-float # Userspace variables -TARGET=$(ARCH)-unknown-redox +export TARGET=$(ARCH)-unknown-redox BUILD=build/userspace RUSTC=./rustc.sh RUSTCFLAGS=--target $(TARGET).json -C opt-level=2 -C debuginfo=0 From 20ecb34acc2758a083654dbaaa6503c4ecab1f09 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 2 Jan 2017 17:04:30 -0700 Subject: [PATCH 021/522] Fix build on OS X --- Makefile | 1 + libc-artifacts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 2062506..c8d454e 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,7 @@ export RUST_TARGET_PATH=$(ROOT)/targets export CFLAGS=-nostartfiles -nostdlib -nodefaultlibs \ -undef -imacros $(ROOT)/libc-artifacts/define.h \ -isystem $(ROOT)/libc-artifacts/usr/include \ + -L $(ROOT)/libc-artifacts/usr/lib \ -fno-stack-protector -U_FORTIFY_SOURCE # Kernel variables diff --git a/libc-artifacts b/libc-artifacts index 0f3467f..4bff613 160000 --- a/libc-artifacts +++ b/libc-artifacts @@ -1 +1 @@ -Subproject commit 0f3467ff1925c0b03b58110aeda924b38ae1c6fc +Subproject commit 4bff613d3c4214ef4081427ab0a74d8f6f724935 From dd60ff5d4f28b78d1a16d10aa28f0f5d0cd3304d Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 2 Jan 2017 17:19:49 -0700 Subject: [PATCH 022/522] Byte block sizes for OSX support --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index c8d454e..30d36b1 100644 --- a/Makefile +++ b/Makefile @@ -268,7 +268,7 @@ qemu: build/harddrive.bin $(QEMU) $(QEMUFLAGS) -drive file=$<,format=raw qemu_extra: build/harddrive.bin - if [ ! -e build/extra.bin ]; then dd if=/dev/zero of=build/extra.bin bs=1M count=1024; fi + if [ ! -e build/extra.bin ]; then dd if=/dev/zero of=build/extra.bin bs=1048576 count=1024; fi $(QEMU) $(QEMUFLAGS) -drive file=$<,format=raw -drive file=build/extra.bin,format=raw qemu_no_build: @@ -596,7 +596,7 @@ build/filesystem.bin: \ filesystem/bin/tar -$(FUMOUNT) build/filesystem/ rm -rf $@ build/filesystem/ - dd if=/dev/zero of=$@ bs=1M count=64 + dd if=/dev/zero of=$@ bs=1048576 count=64 cargo run --manifest-path schemes/redoxfs/Cargo.toml --release --bin redoxfs-mkfs $@ mkdir -p build/filesystem/ cargo build --manifest-path schemes/redoxfs/Cargo.toml --release --bin redoxfs From 8f8b3a3759b22a4e8e6dbef67707981d4c188019 Mon Sep 17 00:00:00 2001 From: Martin Lindhe Date: Tue, 3 Jan 2017 13:14:37 +0100 Subject: [PATCH 023/522] fix some typos --- bootstrap.sh | 20 ++++++++++---------- drivers/e1000d/src/device.rs | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/bootstrap.sh b/bootstrap.sh index 1d1be78..b2e808e 100644 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -53,7 +53,7 @@ install_brew_cask_pkg() ############################################################################### # This function checks which of the supported package managers # is available on the OSX Host. -# If a support package manager is found, it delegates the installing work to +# If a supported package manager is found, it delegates the installing work to # the relevant function. # Otherwise this function will exit this script with an error. ############################################################################### @@ -66,7 +66,7 @@ osx() elif [ ! -z "$(which port)" ]; then osx_macports $@ else - echo "Please install either Hombrew or MacPorts, if you wish to use this script" + echo "Please install either Homebrew or MacPorts, if you wish to use this script" echo "Re-run this script once you installed one of those package managers" echo "Will not install, now exiting..." exit 1 @@ -101,7 +101,7 @@ osx_macports() } ############################################################################### -# This function takes care of installing all dependencies using Hombrew +# This function takes care of installing all dependencies using Homebrew # for building redox on Mac OSX # @params: $1 the emulator to install, virtualbox or qemu ############################################################################### @@ -240,7 +240,7 @@ fedora() ############################################################################### suse() { - echo "Detected a suse" + echo "Detected SUSE Linux" if [ -z "$(which git)" ]; then echo "Installing git..." zypper install git @@ -380,7 +380,7 @@ rustInstall() { # If rustup is not installed we should offer to install it for them if [ -z "$(which rustup)" ]; then echo "You do not have rustup installed." - echo "We HIGHLY reccomend using rustup." + echo "We HIGHLY recommend using rustup." echo "Would you like to install it now?" echo "*WARNING* this involves a 'curl | sh' style command" printf "(y/N): " @@ -401,7 +401,7 @@ rustInstall() { if [ -z "$(which rustc)" ]; then echo "Rust is not installed" echo "Please either run the script again, accepting rustup install" - echo "or install rustc nightly manually (not reccomended) via:" + echo "or install rustc nightly manually (not recommended) via:" echo "\#curl -sSf https://static.rust-lang.org/rustup.sh | sh -s -- --channel=nightly" exit fi @@ -414,8 +414,8 @@ rustInstall() { if echo "$(rustc --version)" | grep -viq "nightly" ;then echo "It appears that you have rust installed, but it" echo "is not the nightly version, please either install" - echo "the nightly manually (not reccomended) or run this" - echo "script again, accepting the multirust install" + echo "the nightly manually (not recommended) or run this" + echo "script again, accepting the rustup install" echo else echo "Your rust install looks good!" @@ -434,14 +434,14 @@ statusCheck() { if echo "$i" | grep -iq "0" ;then echo echo "********************************************" - echo "Travis reports that the last build succeded!" + echo "Travis reports that the last build succeeded!" echo "Looks like you are good to go!" echo "********************************************" elif echo "$i" | grep -iq "null" ;then echo echo "******************************************************************" echo "The Travis build did not finish, this is an error with its config." - echo "I cannot reliably determine whether the build is succeding or not." + echo "I cannot reliably determine whether the build is succeeding or not." echo "Consider checking for and maybe opening an issue on github" echo "******************************************************************" else diff --git a/drivers/e1000d/src/device.rs b/drivers/e1000d/src/device.rs index fe2df01..8cb46f3 100644 --- a/drivers/e1000d/src/device.rs +++ b/drivers/e1000d/src/device.rs @@ -338,7 +338,7 @@ impl Intel8254x { self.flag(TCTL, TCTL_EN, true); self.flag(TCTL, TCTL_PSP, true); - // TCTL.CT = Collition threshold + // TCTL.CT = Collision threshold // TCTL.COLD = Collision distance // TIPG Packet Gap // TODO ... From e3635f37f6a190ebbec69c730a199f375def3b83 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 3 Jan 2017 12:40:55 -0700 Subject: [PATCH 024/522] Add settings for TCP --- schemes/tcpd/src/main.rs | 719 +++++++++++++++++++++++---------------- 1 file changed, 419 insertions(+), 300 deletions(-) diff --git a/schemes/tcpd/src/main.rs b/schemes/tcpd/src/main.rs index 64661ce..9fb5935 100644 --- a/schemes/tcpd/src/main.rs +++ b/schemes/tcpd/src/main.rs @@ -9,12 +9,13 @@ use std::cell::RefCell; use std::fs::File; use std::io::{self, Read, Write}; use std::{mem, slice, str}; +use std::ops::{Deref, DerefMut}; use std::os::unix::io::FromRawFd; use std::rc::Rc; use event::EventQueue; use netutils::{n16, n32, Ipv4, Ipv4Addr, Ipv4Header, Tcp, TcpHeader, Checksum, TCP_FIN, TCP_SYN, TCP_RST, TCP_PSH, TCP_ACK}; -use syscall::data::Packet; +use syscall::data::{Packet, TimeSpec}; use syscall::error::{Error, Result, EACCES, EADDRINUSE, EBADF, EIO, EINVAL, EISCONN, EMSGSIZE, ENOTCONN, EWOULDBLOCK}; use syscall::flag::{EVENT_READ, F_GETFL, F_SETFL, O_ACCMODE, O_CREAT, O_RDWR, O_NONBLOCK}; use syscall::scheme::SchemeMut; @@ -41,11 +42,14 @@ enum State { Closed } -struct Handle { +struct TcpHandle { local: (Ipv4Addr, u16), remote: (Ipv4Addr, u16), flags: usize, events: usize, + read_timeout: Option, + write_timeout: Option, + ttl: u8, state: State, seq: u32, ack: u32, @@ -55,7 +59,7 @@ struct Handle { todo_write: VecDeque, } -impl Handle { +impl TcpHandle { fn is_connected(&self) -> bool { self.remote.0 != Ipv4Addr::NULL && self.remote.1 != 0 } @@ -100,7 +104,7 @@ impl Handle { len: n16::new((data.len() + mem::size_of::()) as u16), id: n16::new(id), flags_fragment: n16::new(0), - ttl: 127, + ttl: self.ttl, proto: 0x06, checksum: Checksum { data: 0 }, src: self.local.0, @@ -112,6 +116,18 @@ impl Handle { } } +#[derive(Copy, Clone)] +enum SettingKind { + Ttl, + ReadTimeout, + WriteTimeout +} + +enum Handle { + Tcp(TcpHandle), + Setting(usize, SettingKind), +} + struct Tcpd { scheme_file: File, tcp_file: File, @@ -144,21 +160,23 @@ impl Tcpd { self.handle(&mut packet); if packet.a == (-EWOULDBLOCK) as usize { if let Some(mut handle) = self.handles.get_mut(&packet.b) { - match a { - syscall::number::SYS_DUP => { - packet.a = a; - handle.todo_dup.push_back(packet); - }, - syscall::number::SYS_READ => { - packet.a = a; - handle.todo_read.push_back(packet); - }, - syscall::number::SYS_WRITE => { - packet.a = a; - handle.todo_write.push_back(packet); - }, - _ => { - self.scheme_file.write(&packet)?; + if let Handle::Tcp(ref mut handle) = *handle { + match a { + syscall::number::SYS_DUP => { + packet.a = a; + handle.todo_dup.push_back(packet); + }, + syscall::number::SYS_READ => { + packet.a = a; + handle.todo_read.push_back(packet); + }, + syscall::number::SYS_WRITE => { + packet.a = a; + handle.todo_write.push_back(packet); + }, + _ => { + self.scheme_file.write(&packet)?; + } } } } @@ -182,46 +200,61 @@ impl Tcpd { let mut closing = Vec::new(); let mut found_connection = false; for (id, handle) in self.handles.iter_mut() { - if handle.state != State::Listen && handle.matches(&ip, &tcp) { - found_connection = true; + if let Handle::Tcp(ref mut handle) = *handle { + if handle.state != State::Listen && handle.matches(&ip, &tcp) { + found_connection = true; - match handle.state { - State::SynReceived => if tcp.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_ACK && tcp.header.ack_num.get() == handle.seq { - handle.state = State::Established; - }, - State::SynSent => if tcp.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_SYN | TCP_ACK && tcp.header.ack_num.get() == handle.seq { - handle.state = State::Established; - handle.ack = tcp.header.sequence.get() + 1; - - let tcp = handle.create_tcp(TCP_ACK, Vec::new()); - let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes())?; - }, - State::Established => if tcp.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_ACK && tcp.header.ack_num.get() == handle.seq { - handle.ack = tcp.header.sequence.get(); - - if ! tcp.data.is_empty() { - handle.data.push_back((ip.clone(), tcp.clone())); - handle.ack += tcp.data.len() as u32; + match handle.state { + State::SynReceived => if tcp.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_ACK && tcp.header.ack_num.get() == handle.seq { + handle.state = State::Established; + }, + State::SynSent => if tcp.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_SYN | TCP_ACK && tcp.header.ack_num.get() == handle.seq { + handle.state = State::Established; + handle.ack = tcp.header.sequence.get() + 1; let tcp = handle.create_tcp(TCP_ACK, Vec::new()); let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); self.tcp_file.write(&ip.to_bytes())?; - } else if tcp.header.flags.get() & TCP_FIN == TCP_FIN { - handle.state = State::CloseWait; + }, + State::Established => if tcp.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_ACK && tcp.header.ack_num.get() == handle.seq { + handle.ack = tcp.header.sequence.get(); - handle.ack += 1; + if ! tcp.data.is_empty() { + handle.data.push_back((ip.clone(), tcp.clone())); + handle.ack += tcp.data.len() as u32; - let tcp = handle.create_tcp(TCP_ACK, Vec::new()); - let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes())?; - } - }, - //TODO: Time wait - State::FinWait1 => if tcp.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_ACK && tcp.header.ack_num.get() == handle.seq { - handle.ack = tcp.header.sequence.get() + 1; + let tcp = handle.create_tcp(TCP_ACK, Vec::new()); + let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); + self.tcp_file.write(&ip.to_bytes())?; + } else if tcp.header.flags.get() & TCP_FIN == TCP_FIN { + handle.state = State::CloseWait; + + handle.ack += 1; + + let tcp = handle.create_tcp(TCP_ACK, Vec::new()); + let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); + self.tcp_file.write(&ip.to_bytes())?; + } + }, + //TODO: Time wait + State::FinWait1 => if tcp.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_ACK && tcp.header.ack_num.get() == handle.seq { + handle.ack = tcp.header.sequence.get() + 1; + + if tcp.header.flags.get() & TCP_FIN == TCP_FIN { + handle.state = State::TimeWait; + + let tcp = handle.create_tcp(TCP_ACK, Vec::new()); + let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); + self.tcp_file.write(&ip.to_bytes())?; + + closing.push(*id); + } else { + handle.state = State::FinWait2; + } + }, + State::FinWait2 => if tcp.header.flags.get() & (TCP_SYN | TCP_ACK | TCP_FIN) == TCP_ACK | TCP_FIN && tcp.header.ack_num.get() == handle.seq { + handle.ack = tcp.header.sequence.get() + 1; - if tcp.header.flags.get() & TCP_FIN == TCP_FIN { handle.state = State::TimeWait; let tcp = handle.create_tcp(TCP_ACK, Vec::new()); @@ -229,89 +262,76 @@ impl Tcpd { self.tcp_file.write(&ip.to_bytes())?; closing.push(*id); + }, + State::LastAck => if tcp.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_ACK && tcp.header.ack_num.get() == handle.seq { + handle.state = State::Closed; + closing.push(*id); + }, + _ => () + } + + while ! handle.todo_read.is_empty() && (! handle.data.is_empty() || handle.read_closed()) { + let mut packet = handle.todo_read.pop_front().unwrap(); + let buf = unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }; + if let Some((_ip, tcp)) = handle.data.pop_front() { + let mut i = 0; + while i < buf.len() && i < tcp.data.len() { + buf[i] = tcp.data[i]; + i += 1; + } + packet.a = i; } else { - handle.state = State::FinWait2; + packet.a = 0; } - }, - State::FinWait2 => if tcp.header.flags.get() & (TCP_SYN | TCP_ACK | TCP_FIN) == TCP_ACK | TCP_FIN && tcp.header.ack_num.get() == handle.seq { - handle.ack = tcp.header.sequence.get() + 1; - handle.state = State::TimeWait; + self.scheme_file.write(&packet)?; + } - let tcp = handle.create_tcp(TCP_ACK, Vec::new()); + if ! handle.todo_write.is_empty() && handle.state == State::Established { + let mut packet = handle.todo_write.pop_front().unwrap(); + let buf = unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }; + + let tcp = handle.create_tcp(TCP_ACK | TCP_PSH, buf.to_vec()); let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes())?; - - closing.push(*id); - }, - State::LastAck => if tcp.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_ACK && tcp.header.ack_num.get() == handle.seq { - handle.state = State::Closed; - closing.push(*id); - }, - _ => () - } - - while ! handle.todo_read.is_empty() && (! handle.data.is_empty() || handle.read_closed()) { - let mut packet = handle.todo_read.pop_front().unwrap(); - let buf = unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }; - if let Some((_ip, tcp)) = handle.data.pop_front() { - let mut i = 0; - while i < buf.len() && i < tcp.data.len() { - buf[i] = tcp.data[i]; - i += 1; + let result = self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO))); + if result.is_ok() { + handle.seq += buf.len() as u32; } - packet.a = i; - } else { - packet.a = 0; + packet.a = Error::mux(result.and(Ok(buf.len()))); + + self.scheme_file.write(&packet)?; } - self.scheme_file.write(&packet)?; - } - - if ! handle.todo_write.is_empty() && handle.state == State::Established { - let mut packet = handle.todo_write.pop_front().unwrap(); - let buf = unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }; - - let tcp = handle.create_tcp(TCP_ACK | TCP_PSH, buf.to_vec()); - let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); - let result = self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO))); - if result.is_ok() { - handle.seq += buf.len() as u32; - } - packet.a = Error::mux(result.and(Ok(buf.len()))); - - self.scheme_file.write(&packet)?; - } - - if handle.events & EVENT_READ == EVENT_READ { - if let Some(&(ref _ip, ref tcp)) = handle.data.get(0) { - self.scheme_file.write(&Packet { - id: 0, - pid: 0, - uid: 0, - gid: 0, - a: syscall::number::SYS_FEVENT, - b: *id, - c: EVENT_READ, - d: tcp.data.len() - })?; + if handle.events & EVENT_READ == EVENT_READ { + if let Some(&(ref _ip, ref tcp)) = handle.data.get(0) { + self.scheme_file.write(&Packet { + id: 0, + pid: 0, + uid: 0, + gid: 0, + a: syscall::number::SYS_FEVENT, + b: *id, + c: EVENT_READ, + d: tcp.data.len() + })?; + } } } } } for file in closing { - let handle = self.handles.remove(&file).unwrap(); + if let Handle::Tcp(handle) = self.handles.remove(&file).unwrap() { + let remove = if let Some(mut port) = self.ports.get_mut(&handle.local.1) { + *port = *port + 1; + *port == 0 + } else { + false + }; - let remove = if let Some(mut port) = self.ports.get_mut(&handle.local.1) { - *port = *port + 1; - *port == 0 - } else { - false - }; - - if remove { - self.ports.remove(&handle.local.1); + if remove { + self.ports.remove(&handle.local.1); + } } } @@ -319,51 +339,56 @@ impl Tcpd { let mut new_handles = Vec::new(); for (_id, handle) in self.handles.iter_mut() { - if handle.state == State::Listen && handle.matches(&ip, &tcp) { - handle.data.push_back((ip.clone(), tcp.clone())); + if let Handle::Tcp(ref mut handle) = *handle { + if handle.state == State::Listen && handle.matches(&ip, &tcp) { + handle.data.push_back((ip.clone(), tcp.clone())); - while ! handle.todo_dup.is_empty() && ! handle.data.is_empty() { - let mut packet = handle.todo_dup.pop_front().unwrap(); - let (ip, tcp) = handle.data.pop_front().unwrap(); + while ! handle.todo_dup.is_empty() && ! handle.data.is_empty() { + let mut packet = handle.todo_dup.pop_front().unwrap(); + let (ip, tcp) = handle.data.pop_front().unwrap(); - let mut new_handle = Handle { - local: handle.local, - remote: (ip.header.src, tcp.header.src.get()), - flags: handle.flags, - events: 0, - state: State::SynReceived, - seq: self.rng.gen(), - ack: tcp.header.sequence.get() + 1, - data: VecDeque::new(), - todo_dup: VecDeque::new(), - todo_read: VecDeque::new(), - todo_write: VecDeque::new(), - }; + let mut new_handle = TcpHandle { + local: handle.local, + remote: (ip.header.src, tcp.header.src.get()), + flags: handle.flags, + events: 0, + read_timeout: handle.read_timeout, + write_timeout: handle.write_timeout, + ttl: handle.ttl, + state: State::SynReceived, + seq: self.rng.gen(), + ack: tcp.header.sequence.get() + 1, + data: VecDeque::new(), + todo_dup: VecDeque::new(), + todo_read: VecDeque::new(), + todo_write: VecDeque::new(), + }; - let tcp = new_handle.create_tcp(TCP_SYN | TCP_ACK, Vec::new()); - let ip = new_handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes())?; + let tcp = new_handle.create_tcp(TCP_SYN | TCP_ACK, Vec::new()); + let ip = new_handle.create_ip(self.rng.gen(), tcp.to_bytes()); + self.tcp_file.write(&ip.to_bytes())?; - new_handle.seq += 1; + new_handle.seq += 1; - handle.data.retain(|&(ref ip, ref tcp)| { - if new_handle.matches(ip, tcp) { - false - } else { - true + handle.data.retain(|&(ref ip, ref tcp)| { + if new_handle.matches(ip, tcp) { + false + } else { + true + } + }); + + if let Some(mut port) = self.ports.get_mut(&handle.local.1) { + *port = *port + 1; } - }); - if let Some(mut port) = self.ports.get_mut(&handle.local.1) { - *port = *port + 1; + let id = self.next_id; + self.next_id += 1; + + packet.a = id; + + new_handles.push((packet, Handle::Tcp(new_handle))); } - - let id = self.next_id; - self.next_id += 1; - - packet.a = id; - - new_handles.push((packet, new_handle)); } } } @@ -401,11 +426,14 @@ impl SchemeMut for Tcpd { return Err(Error::new(EADDRINUSE)); } - let mut handle = Handle { + let mut handle = TcpHandle { local: local, remote: remote, flags: flags, events: 0, + read_timeout: None, + write_timeout: None, + ttl: 64, state: State::Listen, seq: 0, ack: 0, @@ -432,93 +460,105 @@ impl SchemeMut for Tcpd { let id = self.next_id; self.next_id += 1; - self.handles.insert(id, handle); + self.handles.insert(id, Handle::Tcp(handle)); Ok(id) } fn dup(&mut self, file: usize, buf: &[u8]) -> Result { - let path = str::from_utf8(buf).or(Err(Error::new(EINVAL)))?; + let handle = match *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { + Handle::Tcp(ref mut handle) => { + let mut new_handle = TcpHandle { + local: handle.local, + remote: handle.remote, + flags: handle.flags, + events: 0, + read_timeout: handle.read_timeout, + write_timeout: handle.write_timeout, + ttl: handle.ttl, + state: handle.state, + seq: handle.seq, + ack: handle.ack, + data: VecDeque::new(), + todo_dup: VecDeque::new(), + todo_read: VecDeque::new(), + todo_write: VecDeque::new(), + }; - let handle = { - let mut handle = self.handles.get_mut(&file).ok_or(Error::new(EBADF))?; + let path = str::from_utf8(buf).or(Err(Error::new(EINVAL)))?; - let mut new_handle = Handle { - local: handle.local, - remote: handle.remote, - flags: handle.flags, - events: 0, - state: handle.state, - seq: handle.seq, - ack: handle.ack, - data: VecDeque::new(), - todo_dup: VecDeque::new(), - todo_read: VecDeque::new(), - todo_write: VecDeque::new(), - }; + if path == "ttl" { + Handle::Setting(file, SettingKind::Ttl) + } else if path == "read_timeout" { + Handle::Setting(file, SettingKind::ReadTimeout) + } else if path == "write_timeout" { + Handle::Setting(file, SettingKind::WriteTimeout) + } else if path == "listen" { + if handle.is_connected() { + return Err(Error::new(EISCONN)); + } else if let Some((ip, tcp)) = handle.data.pop_front() { + new_handle.remote = (ip.header.src, tcp.header.src.get()); - if path == "listen" { - if handle.is_connected() { - return Err(Error::new(EISCONN)); - } else if let Some((ip, tcp)) = handle.data.pop_front() { - new_handle.remote = (ip.header.src, tcp.header.src.get()); + new_handle.seq = self.rng.gen(); + new_handle.ack = tcp.header.sequence.get() + 1; + new_handle.state = State::SynReceived; - new_handle.seq = self.rng.gen(); - new_handle.ack = tcp.header.sequence.get() + 1; - new_handle.state = State::SynReceived; + let tcp = new_handle.create_tcp(TCP_SYN | TCP_ACK, Vec::new()); + let ip = new_handle.create_ip(self.rng.gen(), tcp.to_bytes()); + self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO))).and(Ok(buf.len()))?; - let tcp = new_handle.create_tcp(TCP_SYN | TCP_ACK, Vec::new()); - let ip = new_handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO))).and(Ok(buf.len()))?; - - new_handle.seq += 1; - } else { - return Err(Error::new(EWOULDBLOCK)); - } - - handle.data.retain(|&(ref ip, ref tcp)| { - if new_handle.matches(ip, tcp) { - false + new_handle.seq += 1; } else { - true + return Err(Error::new(EWOULDBLOCK)); } - }); - } else if path.is_empty() { - new_handle.data = handle.data.clone(); - } else if handle.is_connected() { - return Err(Error::new(EISCONN)); - } else { - new_handle.remote = parse_socket(path); - - if new_handle.is_connected() { - new_handle.seq = self.rng.gen(); - new_handle.ack = 0; - new_handle.state = State::SynSent; handle.data.retain(|&(ref ip, ref tcp)| { if new_handle.matches(ip, tcp) { - new_handle.data.push_back((ip.clone(), tcp.clone())); false } else { true } }); - let tcp = new_handle.create_tcp(TCP_SYN, Vec::new()); - let ip = new_handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO))).and(Ok(buf.len()))?; + Handle::Tcp(new_handle) + } else if path.is_empty() { + new_handle.data = handle.data.clone(); + + Handle::Tcp(new_handle) + } else if handle.is_connected() { + return Err(Error::new(EISCONN)); } else { - return Err(Error::new(EINVAL)); + new_handle.remote = parse_socket(path); + + if new_handle.is_connected() { + new_handle.seq = self.rng.gen(); + new_handle.ack = 0; + new_handle.state = State::SynSent; + + handle.data.retain(|&(ref ip, ref tcp)| { + if new_handle.matches(ip, tcp) { + new_handle.data.push_back((ip.clone(), tcp.clone())); + false + } else { + true + } + }); + + let tcp = new_handle.create_tcp(TCP_SYN, Vec::new()); + let ip = new_handle.create_ip(self.rng.gen(), tcp.to_bytes()); + self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO))).and(Ok(buf.len()))?; + + Handle::Tcp(new_handle) + } else { + return Err(Error::new(EINVAL)); + } } + }, + Handle::Setting(file, kind) => { + Handle::Setting(file, kind) } - - new_handle }; - if let Some(mut port) = self.ports.get_mut(&handle.local.1) { - *port = *port + 1; - } - let id = self.next_id; self.next_id += 1; @@ -528,82 +568,159 @@ impl SchemeMut for Tcpd { } fn read(&mut self, file: usize, buf: &mut [u8]) -> Result { - let mut handle = self.handles.get_mut(&file).ok_or(Error::new(EBADF))?; + let (file, kind) = match *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { + Handle::Tcp(ref mut handle) => { + if ! handle.is_connected() { + return Err(Error::new(ENOTCONN)); + } else if let Some((_ip, tcp)) = handle.data.pop_front() { + let mut i = 0; + while i < buf.len() && i < tcp.data.len() { + buf[i] = tcp.data[i]; + i += 1; + } - if ! handle.is_connected() { - Err(Error::new(ENOTCONN)) - } else if let Some((_ip, tcp)) = handle.data.pop_front() { - let mut i = 0; - while i < buf.len() && i < tcp.data.len() { - buf[i] = tcp.data[i]; - i += 1; + return Ok(i); + } else if handle.flags & O_NONBLOCK == O_NONBLOCK || handle.read_closed() { + return Ok(0); + } else { + return Err(Error::new(EWOULDBLOCK)); + } + }, + Handle::Setting(file, kind) => { + (file, kind) } + }; - Ok(i) - } else if handle.flags & O_NONBLOCK == O_NONBLOCK || handle.read_closed() { - Ok(0) + if let Handle::Tcp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { + let read_timeout = |timeout: &Option, buf: &mut [u8]| -> Result { + if let Some(ref timespec) = *timeout { + timespec.deref().read(buf).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO))) + } else { + Ok(0) + } + }; + + match kind { + SettingKind::Ttl => { + if let Some(mut ttl) = buf.get_mut(0) { + *ttl = handle.ttl; + Ok(1) + } else { + Ok(0) + } + }, + SettingKind::ReadTimeout => { + read_timeout(&handle.read_timeout, buf) + }, + SettingKind::WriteTimeout => { + read_timeout(&handle.write_timeout, buf) + } + } } else { - Err(Error::new(EWOULDBLOCK)) + Err(Error::new(EBADF)) } } fn write(&mut self, file: usize, buf: &[u8]) -> Result { - let mut handle = self.handles.get_mut(&file).ok_or(Error::new(EBADF))?; + let (file, kind) = match *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { + Handle::Tcp(ref mut handle) => { + if ! handle.is_connected() { + return Err(Error::new(ENOTCONN)); + } else if buf.len() >= 65507 { + return Err(Error::new(EMSGSIZE)); + } else { + match handle.state { + State::Established => { + let tcp = handle.create_tcp(TCP_ACK | TCP_PSH, buf.to_vec()); + let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); + self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?; + handle.seq += buf.len() as u32; + return Ok(buf.len()); + }, + _ => { + return Err(Error::new(EWOULDBLOCK)); + } + } + } + }, + Handle::Setting(file, kind) => { + (file, kind) + } + }; - if ! handle.is_connected() { - Err(Error::new(ENOTCONN)) - } else if buf.len() >= 65507 { - Err(Error::new(EMSGSIZE)) - } else { - match handle.state { - State::Established => { - let tcp = handle.create_tcp(TCP_ACK | TCP_PSH, buf.to_vec()); - let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?; - handle.seq += buf.len() as u32; - Ok(buf.len()) + if let Handle::Tcp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { + let write_timeout = |timeout: &mut Option, buf: &[u8]| -> Result { + if buf.len() >= mem::size_of::() { + let mut timespec = TimeSpec::default(); + let count = timespec.deref_mut().write(buf).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?; + *timeout = Some(timespec); + Ok(count) + } else { + *timeout = None; + Ok(0) + } + }; + + match kind { + SettingKind::Ttl => { + if let Some(ttl) = buf.get(0) { + handle.ttl = *ttl; + Ok(1) + } else { + Ok(0) + } }, - _ => { - Err(Error::new(EWOULDBLOCK)) + SettingKind::ReadTimeout => { + write_timeout(&mut handle.read_timeout, buf) + }, + SettingKind::WriteTimeout => { + write_timeout(&mut handle.write_timeout, buf) } } + } else { + Err(Error::new(EBADF)) } } fn fcntl(&mut self, file: usize, cmd: usize, arg: usize) -> Result { - let mut handle = self.handles.get_mut(&file).ok_or(Error::new(EBADF))?; - - match cmd { - F_GETFL => Ok(handle.flags), - F_SETFL => { - handle.flags = arg & ! O_ACCMODE; - Ok(0) - }, - _ => Err(Error::new(EINVAL)) + if let Handle::Tcp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { + match cmd { + F_GETFL => Ok(handle.flags), + F_SETFL => { + handle.flags = arg & ! O_ACCMODE; + Ok(0) + }, + _ => Err(Error::new(EINVAL)) + } + } else { + Err(Error::new(EBADF)) } } fn fevent(&mut self, file: usize, flags: usize) -> Result { - let mut handle = self.handles.get_mut(&file).ok_or(Error::new(EBADF))?; - - handle.events = flags; - - Ok(file) + if let Handle::Tcp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { + handle.events = flags; + Ok(file) + } else { + Err(Error::new(EBADF)) + } } - fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result { - let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; + fn fpath(&mut self, file: usize, buf: &mut [u8]) -> Result { + if let Handle::Tcp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { + let path_string = format!("udp:{}:{}/{}:{}", handle.remote.0.to_string(), handle.remote.1, handle.local.0.to_string(), handle.local.1); + let path = path_string.as_bytes(); - let path_string = format!("tcp:{}:{}/{}:{}", handle.remote.0.to_string(), handle.remote.1, handle.local.0.to_string(), handle.local.1); - let path = path_string.as_bytes(); + let mut i = 0; + while i < buf.len() && i < path.len() { + buf[i] = path[i]; + i += 1; + } - let mut i = 0; - while i < buf.len() && i < path.len() { - buf[i] = path[i]; - i += 1; + Ok(i) + } else { + Err(Error::new(EBADF)) } - - Ok(i) } fn fsync(&mut self, file: usize) -> Result { @@ -614,49 +731,51 @@ impl SchemeMut for Tcpd { fn close(&mut self, file: usize) -> Result { let closed = { - let mut handle = self.handles.get_mut(&file).ok_or(Error::new(EBADF))?; + if let Handle::Tcp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { + handle.data.clear(); - handle.data.clear(); + match handle.state { + State::SynReceived | State::Established => { + handle.state = State::FinWait1; - match handle.state { - State::SynReceived | State::Established => { - handle.state = State::FinWait1; + let tcp = handle.create_tcp(TCP_FIN | TCP_ACK, Vec::new()); + let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); + self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?; - let tcp = handle.create_tcp(TCP_FIN | TCP_ACK, Vec::new()); - let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?; + handle.seq += 1; - handle.seq += 1; + false + }, + State::CloseWait => { + handle.state = State::LastAck; - false - }, - State::CloseWait => { - handle.state = State::LastAck; + let tcp = handle.create_tcp(TCP_FIN | TCP_ACK, Vec::new()); + let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); + self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?; - let tcp = handle.create_tcp(TCP_FIN | TCP_ACK, Vec::new()); - let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?; + handle.seq += 1; - handle.seq += 1; - - false - }, - _ => true + false + }, + _ => true + } + } else { + true } }; if closed { - let handle = self.handles.remove(&file).ok_or(Error::new(EBADF))?; + if let Handle::Tcp(handle) = self.handles.remove(&file).ok_or(Error::new(EBADF))? { + let remove = if let Some(mut port) = self.ports.get_mut(&handle.local.1) { + *port = *port + 1; + *port == 0 + } else { + false + }; - let remove = if let Some(mut port) = self.ports.get_mut(&handle.local.1) { - *port = *port + 1; - *port == 0 - } else { - false - }; - - if remove { - self.ports.remove(&handle.local.1); + if remove { + self.ports.remove(&handle.local.1); + } } } From a627cb7fefb011cef7a73ca13aef1e31cb22ef0e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 3 Jan 2017 14:09:15 -0700 Subject: [PATCH 025/522] Force flush of tables --- arch/x86_64/src/acpi/dmar/mod.rs | 3 +- arch/x86_64/src/acpi/mod.rs | 24 ++-- arch/x86_64/src/device/local_apic.rs | 3 +- arch/x86_64/src/lib.rs | 1 + arch/x86_64/src/paging/mapper.rs | 89 +++++++++++++-- arch/x86_64/src/paging/mod.rs | 88 ++++++++------- arch/x86_64/src/paging/temporary_page.rs | 6 +- arch/x86_64/src/start.rs | 8 +- kernel/context/memory.rs | 137 +++++++++-------------- kernel/syscall/process.rs | 36 +++--- 10 files changed, 223 insertions(+), 172 deletions(-) diff --git a/arch/x86_64/src/acpi/dmar/mod.rs b/arch/x86_64/src/acpi/dmar/mod.rs index d13184f..02aac83 100644 --- a/arch/x86_64/src/acpi/dmar/mod.rs +++ b/arch/x86_64/src/acpi/dmar/mod.rs @@ -59,7 +59,8 @@ pub struct DmarDrhd { impl DmarDrhd { pub fn get(&self, active_table: &mut ActivePageTable) -> &'static mut Drhd { - active_table.identity_map(Frame::containing_address(PhysicalAddress::new(self.base as usize)), entry::PRESENT | entry::WRITABLE | entry::NO_EXECUTE); + let result = active_table.identity_map(Frame::containing_address(PhysicalAddress::new(self.base as usize)), entry::PRESENT | entry::WRITABLE | entry::NO_EXECUTE); + result.flush(active_table); unsafe { &mut *(self.base as *mut Drhd) } } } diff --git a/arch/x86_64/src/acpi/mod.rs b/arch/x86_64/src/acpi/mod.rs index 87f4416..092f609 100644 --- a/arch/x86_64/src/acpi/mod.rs +++ b/arch/x86_64/src/acpi/mod.rs @@ -52,8 +52,8 @@ pub fn init_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) { let trampoline_page = Page::containing_address(VirtualAddress::new(TRAMPOLINE)); // Map trampoline - active_table.map_to(trampoline_page, trampoline_frame, entry::PRESENT | entry::WRITABLE); - active_table.flush(trampoline_page); + let result = active_table.map_to(trampoline_page, trampoline_frame, entry::PRESENT | entry::WRITABLE); + result.flush(active_table); for madt_entry in madt.iter() { println!(" {:?}", madt_entry); @@ -136,8 +136,8 @@ pub fn init_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) { } // Unmap trampoline - active_table.unmap(trampoline_page); - active_table.flush(trampoline_page); + let result = active_table.unmap(trampoline_page); + result.flush(active_table); } else if let Some(dmar) = Dmar::new(sdt) { println!(": {}: {}", dmar.addr_width, dmar.flags); @@ -173,8 +173,8 @@ pub unsafe fn init(active_table: &mut ActivePageTable) -> Option { let end_frame = Frame::containing_address(PhysicalAddress::new(end_addr)); for frame in Frame::range_inclusive(start_frame, end_frame) { let page = Page::containing_address(VirtualAddress::new(frame.start_address().get())); - active_table.map_to(page, frame, entry::PRESENT | entry::NO_EXECUTE); - active_table.flush(page); + let result = active_table.map_to(page, frame, entry::PRESENT | entry::NO_EXECUTE); + result.flush(active_table); } } @@ -184,8 +184,8 @@ pub unsafe fn init(active_table: &mut ActivePageTable) -> Option { let mapped = if active_table.translate_page(Page::containing_address(VirtualAddress::new(sdt_address))).is_none() { let sdt_frame = Frame::containing_address(PhysicalAddress::new(sdt_address)); let sdt_page = Page::containing_address(VirtualAddress::new(sdt_address)); - active_table.map_to(sdt_page, sdt_frame, entry::PRESENT | entry::NO_EXECUTE); - active_table.flush(sdt_page); + let result = active_table.map_to(sdt_page, sdt_frame, entry::PRESENT | entry::NO_EXECUTE); + result.flush(active_table); true } else { false @@ -198,8 +198,8 @@ pub unsafe fn init(active_table: &mut ActivePageTable) -> Option { drop(sdt); if mapped { let sdt_page = Page::containing_address(VirtualAddress::new(sdt_address)); - active_table.unmap(sdt_page); - active_table.flush(sdt_page); + let result = active_table.unmap(sdt_page); + result.flush(active_table); } }; @@ -236,8 +236,8 @@ pub unsafe fn init(active_table: &mut ActivePageTable) -> Option { let end_frame = Frame::containing_address(PhysicalAddress::new(end_addr)); for frame in Frame::range_inclusive(start_frame, end_frame) { let page = Page::containing_address(VirtualAddress::new(frame.start_address().get())); - active_table.unmap(page); - active_table.flush(page); + let result = active_table.unmap(page); + result.flush(active_table); } } diff --git a/arch/x86_64/src/device/local_apic.rs b/arch/x86_64/src/device/local_apic.rs index d352c2c..d55bc3b 100644 --- a/arch/x86_64/src/device/local_apic.rs +++ b/arch/x86_64/src/device/local_apic.rs @@ -32,7 +32,8 @@ impl LocalApic { if ! self.x2 { let page = Page::containing_address(VirtualAddress::new(self.address)); let frame = Frame::containing_address(PhysicalAddress::new(self.address - ::KERNEL_OFFSET)); - active_table.map_to(page, frame, entry::PRESENT | entry::WRITABLE | entry::NO_EXECUTE); + let result = active_table.map_to(page, frame, entry::PRESENT | entry::WRITABLE | entry::NO_EXECUTE); + result.flush(active_table); } self.init_ap(); diff --git a/arch/x86_64/src/lib.rs b/arch/x86_64/src/lib.rs index 609596b..954535f 100644 --- a/arch/x86_64/src/lib.rs +++ b/arch/x86_64/src/lib.rs @@ -1,5 +1,6 @@ //! Architecture support for x86_64 +#![deny(unused_must_use)] #![feature(asm)] #![feature(concat_idents)] #![feature(const_fn)] diff --git a/arch/x86_64/src/paging/mapper.rs b/arch/x86_64/src/paging/mapper.rs index faa5ec6..b18e7a5 100644 --- a/arch/x86_64/src/paging/mapper.rs +++ b/arch/x86_64/src/paging/mapper.rs @@ -1,11 +1,81 @@ +use core::mem; use core::ptr::Unique; use memory::{allocate_frame, deallocate_frame, Frame}; -use super::{Page, PAGE_SIZE, PhysicalAddress, VirtualAddress}; +use super::{ActivePageTable, Page, PAGE_SIZE, PhysicalAddress, VirtualAddress}; use super::entry::{self, EntryFlags}; use super::table::{self, Table, Level4}; +/// In order to enforce correct paging operations in the kernel, these types +/// are returned on any mapping operation to get the code involved to specify +/// how it intends to flush changes to a page table +#[must_use = "The page table must be flushed, or the changes unsafely ignored"] +pub struct MapperFlush(Page); + +impl MapperFlush { + /// Create a new page flush promise + pub fn new(page: Page) -> MapperFlush { + MapperFlush(page) + } + + /// Flush this page in the active table + pub fn flush(self, table: &mut ActivePageTable) { + table.flush(self.0); + mem::forget(self); + } + + /// Ignore the flush. This is unsafe, and a reason should be provided for use + pub unsafe fn ignore(self) { + mem::forget(self); + } +} + +/// A flush cannot be dropped, it must be consumed +impl Drop for MapperFlush { + fn drop(&mut self) { + panic!("Mapper flush was not utilized"); + } +} + +/// To allow for combining multiple flushes into one, we have a way of flushing +/// the active table, which can consume MapperFlush structs +#[must_use = "The page table must be flushed, or the changes unsafely ignored"] +pub struct MapperFlushAll(bool); + +impl MapperFlushAll { + /// Create a new promise to flush all mappings + pub fn new() -> MapperFlushAll { + MapperFlushAll(false) + } + + /// Consume a single page flush + pub fn consume(&mut self, flush: MapperFlush) { + self.0 = true; + mem::forget(flush); + } + + /// Flush the active page table + pub fn flush(self, table: &mut ActivePageTable) { + if self.0 { + table.flush_all(); + } + mem::forget(self); + } + + /// Ignore the flush. This is unsafe, and a reason should be provided for use + pub unsafe fn ignore(self) { + mem::forget(self); + } +} + +/// A flush cannot be dropped, it must be consumed +impl Drop for MapperFlushAll { + fn drop(&mut self) { + panic!("Mapper flush all was not utilized"); + } +} + pub struct Mapper { p4: Unique>, } @@ -27,7 +97,7 @@ impl Mapper { } /// Map a page to a frame - pub fn map_to(&mut self, page: Page, frame: Frame, flags: EntryFlags) { + pub fn map_to(&mut self, page: Page, frame: Frame, flags: EntryFlags) -> MapperFlush { let mut p3 = self.p4_mut().next_table_create(page.p4_index()); let mut p2 = p3.next_table_create(page.p3_index()); let mut p1 = p2.next_table_create(page.p2_index()); @@ -38,31 +108,33 @@ impl Mapper { p1[page.p1_index()].address().get(), p1[page.p1_index()].flags(), frame.start_address().get(), flags); p1[page.p1_index()].set(frame, flags | entry::PRESENT); + MapperFlush::new(page) } /// Map a page to the next free frame - pub fn map(&mut self, page: Page, flags: EntryFlags) { + pub fn map(&mut self, page: Page, flags: EntryFlags) -> MapperFlush { let frame = allocate_frame().expect("out of frames"); self.map_to(page, frame, flags) } /// Update flags for a page - pub fn remap(&mut self, page: Page, flags: EntryFlags) { + pub fn remap(&mut self, page: Page, flags: EntryFlags) -> MapperFlush { let mut p3 = self.p4_mut().next_table_mut(page.p4_index()).expect("failed to remap: no p3"); let mut p2 = p3.next_table_mut(page.p3_index()).expect("failed to remap: no p2"); let mut p1 = p2.next_table_mut(page.p2_index()).expect("failed to remap: no p1"); let frame = p1[page.p1_index()].pointed_frame().expect("failed to remap: not mapped"); p1[page.p1_index()].set(frame, flags | entry::PRESENT); + MapperFlush::new(page) } /// Identity map a frame - pub fn identity_map(&mut self, frame: Frame, flags: EntryFlags) { + pub fn identity_map(&mut self, frame: Frame, flags: EntryFlags) -> MapperFlush { let page = Page::containing_address(VirtualAddress::new(frame.start_address().get())); self.map_to(page, frame, flags) } /// Unmap a page - pub fn unmap(&mut self, page: Page) { + pub fn unmap(&mut self, page: Page) -> MapperFlush { let p1 = self.p4_mut() .next_table_mut(page.p4_index()) .and_then(|p3| p3.next_table_mut(page.p3_index())) @@ -72,10 +144,11 @@ impl Mapper { p1[page.p1_index()].set_unused(); // TODO free p(1,2,3) table if empty deallocate_frame(frame); + MapperFlush::new(page) } /// Unmap a page, return frame without free - pub fn unmap_return(&mut self, page: Page) -> Frame { + pub fn unmap_return(&mut self, page: Page) -> (MapperFlush, Frame) { let p1 = self.p4_mut() .next_table_mut(page.p4_index()) .and_then(|p3| p3.next_table_mut(page.p3_index())) @@ -83,7 +156,7 @@ impl Mapper { .expect("unmap_return does not support huge pages"); let frame = p1[page.p1_index()].pointed_frame().unwrap(); p1[page.p1_index()].set_unused(); - frame + (MapperFlush::new(page), frame) } pub fn translate_page(&self, page: Page) -> Option { diff --git a/arch/x86_64/src/paging/mod.rs b/arch/x86_64/src/paging/mod.rs index fd289ce..6c133e1 100644 --- a/arch/x86_64/src/paging/mod.rs +++ b/arch/x86_64/src/paging/mod.rs @@ -118,52 +118,56 @@ pub unsafe fn init(cpu_id: usize, stack_start: usize, stack_end: usize) -> (Acti }; active_table.with(&mut new_table, &mut temporary_page, |mapper| { + // Map tdata and tbss { - // Map tdata and tbss - { - let size = & __tbss_end as *const _ as usize - & __tdata_start as *const _ as usize; + let size = & __tbss_end as *const _ as usize - & __tdata_start as *const _ as usize; - let start = ::KERNEL_PERCPU_OFFSET + ::KERNEL_PERCPU_SIZE * cpu_id; - let end = start + size; + let start = ::KERNEL_PERCPU_OFFSET + ::KERNEL_PERCPU_SIZE * cpu_id; + let end = start + size; - let start_page = Page::containing_address(VirtualAddress::new(start)); - let end_page = Page::containing_address(VirtualAddress::new(end - 1)); - for page in Page::range_inclusive(start_page, end_page) { - mapper.map(page, PRESENT | GLOBAL | NO_EXECUTE | WRITABLE); + let start_page = Page::containing_address(VirtualAddress::new(start)); + let end_page = Page::containing_address(VirtualAddress::new(end - 1)); + for page in Page::range_inclusive(start_page, end_page) { + let result = mapper.map(page, PRESENT | GLOBAL | NO_EXECUTE | WRITABLE); + // The flush can be ignored as this is not the active table. See later active_table.switch + unsafe { result.ignore(); } + } + } + + let mut remap = |start: usize, end: usize, flags: EntryFlags| { + if end > start { + let start_frame = Frame::containing_address(PhysicalAddress::new(start)); + let end_frame = Frame::containing_address(PhysicalAddress::new(end - 1)); + for frame in Frame::range_inclusive(start_frame, end_frame) { + let page = Page::containing_address(VirtualAddress::new(frame.start_address().get() + ::KERNEL_OFFSET)); + let result = mapper.map_to(page, frame, flags); + // The flush can be ignored as this is not the active table. See later active_table.switch + unsafe { result.ignore(); } } } + }; - let mut remap = |start: usize, end: usize, flags: EntryFlags| { - if end > start { - let start_frame = Frame::containing_address(PhysicalAddress::new(start)); - let end_frame = Frame::containing_address(PhysicalAddress::new(end - 1)); - for frame in Frame::range_inclusive(start_frame, end_frame) { - let page = Page::containing_address(VirtualAddress::new(frame.start_address().get() + ::KERNEL_OFFSET)); - mapper.map_to(page, frame, flags); - } - } - }; + // Remap stack writable, no execute + remap(stack_start - ::KERNEL_OFFSET, stack_end - ::KERNEL_OFFSET, PRESENT | GLOBAL | NO_EXECUTE | WRITABLE); - // Remap stack writable, no execute - remap(stack_start - ::KERNEL_OFFSET, stack_end - ::KERNEL_OFFSET, PRESENT | GLOBAL | NO_EXECUTE | WRITABLE); - - // Remap a section with `flags` - let mut remap_section = |start: &u8, end: &u8, flags: EntryFlags| { - remap(start as *const _ as usize - ::KERNEL_OFFSET, end as *const _ as usize - ::KERNEL_OFFSET, flags); - }; - // Remap text read-only - remap_section(& __text_start, & __text_end, PRESENT | GLOBAL); - // Remap rodata read-only, no execute - remap_section(& __rodata_start, & __rodata_end, PRESENT | GLOBAL | NO_EXECUTE); - // Remap data writable, no execute - remap_section(& __data_start, & __data_end, PRESENT | GLOBAL | NO_EXECUTE | WRITABLE); - // Remap tdata master writable, no execute - remap_section(& __tdata_start, & __tdata_end, PRESENT | GLOBAL | NO_EXECUTE); - // Remap bss writable, no execute - remap_section(& __bss_start, & __bss_end, PRESENT | GLOBAL | NO_EXECUTE | WRITABLE); - } + // Remap a section with `flags` + let mut remap_section = |start: &u8, end: &u8, flags: EntryFlags| { + remap(start as *const _ as usize - ::KERNEL_OFFSET, end as *const _ as usize - ::KERNEL_OFFSET, flags); + }; + // Remap text read-only + remap_section(& __text_start, & __text_end, PRESENT | GLOBAL); + // Remap rodata read-only, no execute + remap_section(& __rodata_start, & __rodata_end, PRESENT | GLOBAL | NO_EXECUTE); + // Remap data writable, no execute + remap_section(& __data_start, & __data_end, PRESENT | GLOBAL | NO_EXECUTE | WRITABLE); + // Remap tdata master writable, no execute + remap_section(& __tdata_start, & __tdata_end, PRESENT | GLOBAL | NO_EXECUTE); + // Remap bss writable, no execute + remap_section(& __bss_start, & __bss_end, PRESENT | GLOBAL | NO_EXECUTE | WRITABLE); }); + // This switches the active table, which is setup by the bootloader, to a correct table + // setup by the lambda above. This will also flush the TLB active_table.switch(new_table); (active_table, init_tcb(cpu_id)) @@ -200,7 +204,9 @@ pub unsafe fn init_ap(cpu_id: usize, bsp_table: usize, stack_start: usize, stack let start_page = Page::containing_address(VirtualAddress::new(start)); let end_page = Page::containing_address(VirtualAddress::new(end - 1)); for page in Page::range_inclusive(start_page, end_page) { - mapper.map(page, PRESENT | GLOBAL | NO_EXECUTE | WRITABLE); + let result = mapper.map(page, PRESENT | GLOBAL | NO_EXECUTE | WRITABLE); + // The flush can be ignored as this is not the active table. See later active_table.switch + unsafe { result.ignore(); } } } @@ -210,7 +216,9 @@ pub unsafe fn init_ap(cpu_id: usize, bsp_table: usize, stack_start: usize, stack let end_frame = Frame::containing_address(PhysicalAddress::new(end - 1)); for frame in Frame::range_inclusive(start_frame, end_frame) { let page = Page::containing_address(VirtualAddress::new(frame.start_address().get() + ::KERNEL_OFFSET)); - mapper.map_to(page, frame, flags); + let result = mapper.map_to(page, frame, flags); + // The flush can be ignored as this is not the active table. See later active_table.switch + unsafe { result.ignore(); } } } }; @@ -219,6 +227,8 @@ pub unsafe fn init_ap(cpu_id: usize, bsp_table: usize, stack_start: usize, stack remap(stack_start - ::KERNEL_OFFSET, stack_end - ::KERNEL_OFFSET, PRESENT | GLOBAL | NO_EXECUTE | WRITABLE); }); + // This switches the active table, which is setup by the bootloader, to a correct table + // setup by the lambda above. This will also flush the TLB active_table.switch(new_table); init_tcb(cpu_id) diff --git a/arch/x86_64/src/paging/temporary_page.rs b/arch/x86_64/src/paging/temporary_page.rs index 4afa6c5..aba6703 100644 --- a/arch/x86_64/src/paging/temporary_page.rs +++ b/arch/x86_64/src/paging/temporary_page.rs @@ -26,7 +26,8 @@ impl TemporaryPage { /// Returns the start address of the temporary page. pub fn map(&mut self, frame: Frame, flags: EntryFlags, active_table: &mut ActivePageTable) -> VirtualAddress { assert!(active_table.translate_page(self.page).is_none(), "temporary page is already mapped"); - active_table.map_to(self.page, frame, flags); + let result = active_table.map_to(self.page, frame, flags); + result.flush(active_table); self.page.start_address() } @@ -38,6 +39,7 @@ impl TemporaryPage { /// Unmaps the temporary page in the active table. pub fn unmap(&mut self, active_table: &mut ActivePageTable) { - active_table.unmap(self.page) + let result = active_table.unmap(self.page); + result.flush(active_table); } } diff --git a/arch/x86_64/src/start.rs b/arch/x86_64/src/start.rs index c39edf4..4488009 100644 --- a/arch/x86_64/src/start.rs +++ b/arch/x86_64/src/start.rs @@ -14,6 +14,7 @@ use idt; use interrupt; use memory; use paging::{self, entry, Page, VirtualAddress}; +use paging::mapper::MapperFlushAll; /// Test of zero values in BSS. static BSS_TEST_ZERO: usize = 0; @@ -97,13 +98,18 @@ pub unsafe extern fn kstart() -> ! { // Setup kernel heap { + let mut flush_all = MapperFlushAll::new(); + // Map heap pages let heap_start_page = Page::containing_address(VirtualAddress::new(::KERNEL_HEAP_OFFSET)); let heap_end_page = Page::containing_address(VirtualAddress::new(::KERNEL_HEAP_OFFSET + ::KERNEL_HEAP_SIZE-1)); for page in Page::range_inclusive(heap_start_page, heap_end_page) { - active_table.map(page, entry::PRESENT | entry::GLOBAL | entry::WRITABLE | entry::NO_EXECUTE); + let result = active_table.map(page, entry::PRESENT | entry::GLOBAL | entry::WRITABLE | entry::NO_EXECUTE); + flush_all.consume(result); } + flush_all.flush(&mut active_table); + // Init the allocator allocator::init(::KERNEL_HEAP_OFFSET, ::KERNEL_HEAP_SIZE); } diff --git a/kernel/context/memory.rs b/kernel/context/memory.rs index 73f808c..e12fbda 100644 --- a/kernel/context/memory.rs +++ b/kernel/context/memory.rs @@ -6,6 +6,7 @@ use spin::Mutex; use arch::memory::Frame; use arch::paging::{ActivePageTable, InactivePageTable, Page, PageIter, PhysicalAddress, VirtualAddress}; use arch::paging::entry::{self, EntryFlags}; +use arch::paging::mapper::MapperFlushAll; use arch::paging::temporary_page::TemporaryPage; #[derive(Debug)] @@ -20,19 +21,17 @@ impl Grant { pub fn physmap(from: PhysicalAddress, to: VirtualAddress, size: usize, flags: EntryFlags) -> Grant { let mut active_table = unsafe { ActivePageTable::new() }; - let mut flush_all = false; + let mut flush_all = MapperFlushAll::new(); let start_page = Page::containing_address(to); let end_page = Page::containing_address(VirtualAddress::new(to.get() + size - 1)); for page in Page::range_inclusive(start_page, end_page) { let frame = Frame::containing_address(PhysicalAddress::new(page.start_address().get() - to.get() + from.get())); - active_table.map_to(page, frame, flags); - flush_all = true; + let result = active_table.map_to(page, frame, flags); + flush_all.consume(result); } - if flush_all { - active_table.flush_all(); - } + flush_all.flush(&mut active_table); Grant { start: to, @@ -59,7 +58,9 @@ impl Grant { let end_page = Page::containing_address(VirtualAddress::new(to.get() + size - 1)); for page in Page::range_inclusive(start_page, end_page) { let frame = frames.pop_front().expect("grant did not find enough frames"); - mapper.map_to(page, frame, flags); + let result = mapper.map_to(page, frame, flags); + // Ignore result due to mapping on inactive table + unsafe { result.ignore(); } } }); @@ -88,18 +89,16 @@ impl Grant { let mut active_table = unsafe { ActivePageTable::new() }; - let mut flush_all = false; + let mut flush_all = MapperFlushAll::new(); let start_page = Page::containing_address(self.start); let end_page = Page::containing_address(VirtualAddress::new(self.start.get() + self.size - 1)); for page in Page::range_inclusive(start_page, end_page) { - active_table.unmap_return(page); - flush_all = true; + let (result, _frame) = active_table.unmap_return(page); + flush_all.consume(result); } - if flush_all { - active_table.flush_all(); - } + flush_all.flush(&mut active_table); self.mapped = false; } @@ -113,7 +112,9 @@ impl Grant { let start_page = Page::containing_address(self.start); let end_page = Page::containing_address(VirtualAddress::new(self.start.get() + self.size - 1)); for page in Page::range_inclusive(start_page, end_page) { - mapper.unmap_return(page); + let (result, _frame) = mapper.unmap_return(page); + // This is not the active table, so the flush can be ignored + unsafe { result.ignore(); } } }); @@ -164,14 +165,14 @@ pub struct Memory { } impl Memory { - pub fn new(start: VirtualAddress, size: usize, flags: EntryFlags, flush: bool, clear: bool) -> Self { + pub fn new(start: VirtualAddress, size: usize, flags: EntryFlags, clear: bool) -> Self { let mut memory = Memory { start: start, size: size, flags: flags }; - memory.map(flush, clear); + memory.map(clear); memory } @@ -198,150 +199,114 @@ impl Memory { Page::range_inclusive(start_page, end_page) } - fn map(&mut self, flush: bool, clear: bool) { + fn map(&mut self, clear: bool) { let mut active_table = unsafe { ActivePageTable::new() }; - let mut flush_all = false; + let mut flush_all = MapperFlushAll::new(); - //TODO: Clear pages? for page in self.pages() { - active_table.map(page, self.flags); - - if flush { - //active_table.flush(page); - flush_all = true; - } + let result = active_table.map(page, self.flags); + flush_all.consume(result); } - if flush_all { - active_table.flush_all(); - } + flush_all.flush(&mut active_table); if clear { - assert!(flush && self.flags.contains(entry::WRITABLE)); + assert!(self.flags.contains(entry::WRITABLE)); unsafe { intrinsics::write_bytes(self.start_address().get() as *mut u8, 0, self.size); } } } - fn unmap(&mut self, flush: bool) { + fn unmap(&mut self) { let mut active_table = unsafe { ActivePageTable::new() }; - let mut flush_all = false; + let mut flush_all = MapperFlushAll::new(); for page in self.pages() { - active_table.unmap(page); - - if flush { - //active_table.flush(page); - flush_all = true; - } + let result = active_table.unmap(page); + flush_all.consume(result); } - if flush_all { - active_table.flush_all(); - } + flush_all.flush(&mut active_table); } /// A complicated operation to move a piece of memory to a new page table /// It also allows for changing the address at the same time - pub fn move_to(&mut self, new_start: VirtualAddress, new_table: &mut InactivePageTable, temporary_page: &mut TemporaryPage, flush: bool) { + pub fn move_to(&mut self, new_start: VirtualAddress, new_table: &mut InactivePageTable, temporary_page: &mut TemporaryPage) { let mut active_table = unsafe { ActivePageTable::new() }; - let mut flush_all = false; + let mut flush_all = MapperFlushAll::new(); for page in self.pages() { - let frame = active_table.unmap_return(page); + let (result, frame) = active_table.unmap_return(page); + flush_all.consume(result); active_table.with(new_table, temporary_page, |mapper| { let new_page = Page::containing_address(VirtualAddress::new(page.start_address().get() - self.start.get() + new_start.get())); - mapper.map_to(new_page, frame, self.flags); + let result = mapper.map_to(new_page, frame, self.flags); + // This is not the active table, so the flush can be ignored + unsafe { result.ignore(); } }); - - if flush { - //active_table.flush(page); - flush_all = true; - } } - if flush_all { - active_table.flush_all(); - } + flush_all.flush(&mut active_table); self.start = new_start; } - pub fn remap(&mut self, new_flags: EntryFlags, flush: bool) { + pub fn remap(&mut self, new_flags: EntryFlags) { let mut active_table = unsafe { ActivePageTable::new() }; - let mut flush_all = false; + let mut flush_all = MapperFlushAll::new(); for page in self.pages() { - active_table.remap(page, new_flags); - - if flush { - //active_table.flush(page); - flush_all = true; - } + let result = active_table.remap(page, new_flags); + flush_all.consume(result); } - if flush_all { - active_table.flush_all(); - } + flush_all.flush(&mut active_table); self.flags = new_flags; } - pub fn resize(&mut self, new_size: usize, flush: bool, clear: bool) { + pub fn resize(&mut self, new_size: usize, clear: bool) { let mut active_table = unsafe { ActivePageTable::new() }; //TODO: Calculate page changes to minimize operations if new_size > self.size { - let mut flush_all = false; + let mut flush_all = MapperFlushAll::new(); let start_page = Page::containing_address(VirtualAddress::new(self.start.get() + self.size)); let end_page = Page::containing_address(VirtualAddress::new(self.start.get() + new_size - 1)); for page in Page::range_inclusive(start_page, end_page) { if active_table.translate_page(page).is_none() { - active_table.map(page, self.flags); - - if flush { - //active_table.flush(page); - flush_all = true; - } + let result = active_table.map(page, self.flags); + flush_all.consume(result); } } - if flush_all { - active_table.flush_all(); - } + flush_all.flush(&mut active_table); if clear { - assert!(flush); unsafe { intrinsics::write_bytes((self.start.get() + self.size) as *mut u8, 0, new_size - self.size); } } } else if new_size < self.size { - let mut flush_all = false; + let mut flush_all = MapperFlushAll::new(); let start_page = Page::containing_address(VirtualAddress::new(self.start.get() + new_size)); let end_page = Page::containing_address(VirtualAddress::new(self.start.get() + self.size - 1)); for page in Page::range_inclusive(start_page, end_page) { if active_table.translate_page(page).is_some() { - active_table.unmap(page); - - if flush { - //active_table.flush(page); - flush_all = true; - } + let result = active_table.unmap(page); + flush_all.consume(result); } } - if flush_all { - active_table.flush_all(); - } + flush_all.flush(&mut active_table); } self.size = new_size; @@ -350,7 +315,7 @@ impl Memory { impl Drop for Memory { fn drop(&mut self) { - self.unmap(true); + self.unmap(); } } diff --git a/kernel/syscall/process.rs b/kernel/syscall/process.rs index aeb7b7d..f8bc6c3 100644 --- a/kernel/syscall/process.rs +++ b/kernel/syscall/process.rs @@ -44,7 +44,7 @@ pub fn brk(address: usize) -> Result { //TODO: out of memory errors if let Some(ref heap_shared) = context.heap { heap_shared.with(|heap| { - heap.resize(address - arch::USER_HEAP_OFFSET, true, true); + heap.resize(address - arch::USER_HEAP_OFFSET, true); }); } else { panic!("user heap not initialized"); @@ -139,7 +139,6 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { VirtualAddress::new(memory.start_address().get() + arch::USER_TMP_OFFSET), memory.size(), entry::PRESENT | entry::NO_EXECUTE | entry::WRITABLE, - true, false ); @@ -149,7 +148,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { memory.size()); } - new_memory.remap(memory.flags(), true); + new_memory.remap(memory.flags()); image.push(new_memory.to_shared()); }); } @@ -160,7 +159,6 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { VirtualAddress::new(arch::USER_TMP_HEAP_OFFSET), heap.size(), entry::PRESENT | entry::NO_EXECUTE | entry::WRITABLE, - true, false ); @@ -170,7 +168,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { heap.size()); } - new_heap.remap(heap.flags(), true); + new_heap.remap(heap.flags()); heap_option = Some(new_heap.to_shared()); }); } @@ -181,7 +179,6 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { VirtualAddress::new(arch::USER_TMP_STACK_OFFSET), stack.size(), entry::PRESENT | entry::NO_EXECUTE | entry::WRITABLE, - true, false ); @@ -191,7 +188,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { stack.size()); } - new_stack.remap(stack.flags(), true); + new_stack.remap(stack.flags()); stack_option = Some(new_stack); } @@ -203,7 +200,6 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { VirtualAddress::new(arch::USER_TMP_TLS_OFFSET), tls.mem.size(), entry::PRESENT | entry::NO_EXECUTE | entry::WRITABLE, - true, true ) }; @@ -214,7 +210,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { tls.file_size); } - new_tls.mem.remap(tls.mem.flags(), true); + new_tls.mem.remap(tls.mem.flags()); tls_option = Some(new_tls); } @@ -405,7 +401,9 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { for page in Page::range_inclusive(start_page, end_page) { let frame = active_table.translate_page(page).expect("kernel percpu not mapped"); active_table.with(&mut new_table, &mut temporary_page, |mapper| { - mapper.map_to(page, frame, entry::PRESENT | entry::NO_EXECUTE | entry::WRITABLE); + let result = mapper.map_to(page, frame, entry::PRESENT | entry::NO_EXECUTE | entry::WRITABLE); + // Ignore result due to operating on inactive table + unsafe { result.ignore(); } }); } } @@ -414,7 +412,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { for memory_shared in image.iter_mut() { memory_shared.with(|memory| { let start = VirtualAddress::new(memory.start_address().get() - arch::USER_TMP_OFFSET + arch::USER_OFFSET); - memory.move_to(start, &mut new_table, &mut temporary_page, true); + memory.move_to(start, &mut new_table, &mut temporary_page); }); } context.image = image; @@ -422,7 +420,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { // Move copy of heap if let Some(heap_shared) = heap_option { heap_shared.with(|heap| { - heap.move_to(VirtualAddress::new(arch::USER_HEAP_OFFSET), &mut new_table, &mut temporary_page, true); + heap.move_to(VirtualAddress::new(arch::USER_HEAP_OFFSET), &mut new_table, &mut temporary_page); }); context.heap = Some(heap_shared); } @@ -430,13 +428,13 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { // Setup user stack if let Some(mut stack) = stack_option { - stack.move_to(VirtualAddress::new(arch::USER_STACK_OFFSET), &mut new_table, &mut temporary_page, true); + stack.move_to(VirtualAddress::new(arch::USER_STACK_OFFSET), &mut new_table, &mut temporary_page); context.stack = Some(stack); } // Setup user TLS if let Some(mut tls) = tls_option { - tls.mem.move_to(VirtualAddress::new(arch::USER_TLS_OFFSET), &mut new_table, &mut temporary_page, true); + tls.mem.move_to(VirtualAddress::new(arch::USER_TLS_OFFSET), &mut new_table, &mut temporary_page); context.tls = Some(tls); } @@ -566,7 +564,6 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result { VirtualAddress::new(segment.p_vaddr as usize), segment.p_memsz as usize, entry::NO_EXECUTE | entry::WRITABLE, - true, true ); @@ -590,7 +587,7 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result { flags.insert(entry::WRITABLE); } - memory.remap(flags, true); + memory.remap(flags); context.image.push(memory.to_shared()); } else if segment.p_type == program_header::PT_TLS { @@ -598,7 +595,6 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result { VirtualAddress::new(arch::USER_TCB_OFFSET), 4096, entry::NO_EXECUTE | entry::WRITABLE | entry::USER_ACCESSIBLE, - true, true ); @@ -619,7 +615,6 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result { VirtualAddress::new(arch::USER_HEAP_OFFSET), 0, entry::NO_EXECUTE | entry::WRITABLE | entry::USER_ACCESSIBLE, - true, true ).to_shared()); @@ -628,7 +623,6 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result { VirtualAddress::new(arch::USER_STACK_OFFSET), arch::USER_STACK_SIZE, entry::NO_EXECUTE | entry::WRITABLE | entry::USER_ACCESSIBLE, - true, true )); @@ -641,7 +635,6 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result { VirtualAddress::new(arch::USER_TLS_OFFSET), size, entry::NO_EXECUTE | entry::WRITABLE | entry::USER_ACCESSIBLE, - true, true ) }; @@ -675,7 +668,6 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result { VirtualAddress::new(arch::USER_ARG_OFFSET), arg_size, entry::NO_EXECUTE | entry::WRITABLE, - true, true ); @@ -690,7 +682,7 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result { arg_offset += arg.len(); } - memory.remap(entry::NO_EXECUTE | entry::USER_ACCESSIBLE, true); + memory.remap(entry::NO_EXECUTE | entry::USER_ACCESSIBLE); context.image.push(memory.to_shared()); } From da88d5298f9835b80598818754fe8fa566aee779 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 3 Jan 2017 14:22:55 -0700 Subject: [PATCH 026/522] Update travis OSX --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f2c97b2..6b35065 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,9 @@ before_install: sudo chown root:$USER /etc/fuse.conf; fi - if [ `uname` = "Darwin" ]; then brew update && - brew install nasm gcc49 pkg-config Caskroom/cask/osxfuse djphoenix/gcc_cross_compilers/x86_64-elf-gcc; + brew install nasm gcc49 pkg-config Caskroom/cask/osxfuse && + brew tap glendc/gcc_cross_compilers && + brew install glendc/gcc_cross_compilers/x64-elf-binutils glendc/gcc_cross_compilers/x64-elf-gcc; fi script: - make clean && From e31bf23c01e6a6afcc667001c9a9b9677122a401 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 3 Jan 2017 14:49:59 -0700 Subject: [PATCH 027/522] Update conditions --- .travis.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6b35065..1485101 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,15 +6,20 @@ cache: cargo os: - linux - osx +matrix: + allow_failures: + - os: osx dist: trusty before_install: -- if [ `uname` = "Linux" ]; then +- if [ "$TRAVIS_OS_NAME" == "linux" ]; then + sudo apt-get update -qq sudo apt-get install -qq nasm pkg-config fuse libfuse-dev genisoimage syslinux && sudo modprobe fuse && sudo chmod 666 /dev/fuse && sudo chown root:$USER /etc/fuse.conf; fi -- if [ `uname` = "Darwin" ]; then brew update && +- if [ "$TRAVIS_OS_NAME" == "osx" ]; then + brew update && brew install nasm gcc49 pkg-config Caskroom/cask/osxfuse && brew tap glendc/gcc_cross_compilers && brew install glendc/gcc_cross_compilers/x64-elf-binutils glendc/gcc_cross_compilers/x64-elf-gcc; @@ -37,4 +42,5 @@ deploy: on: repo: redox-os/redox tags: true + condition: $TRAVIS_OS_NAME = linux skip_cleanup: true From 98c76d36fd40603b46b04000d09115bb83baa1e1 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 3 Jan 2017 15:16:26 -0700 Subject: [PATCH 028/522] Fix Linux syntax --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1485101..cec207d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,7 @@ matrix: dist: trusty before_install: - if [ "$TRAVIS_OS_NAME" == "linux" ]; then - sudo apt-get update -qq + sudo apt-get update -qq && sudo apt-get install -qq nasm pkg-config fuse libfuse-dev genisoimage syslinux && sudo modprobe fuse && sudo chmod 666 /dev/fuse && From 7cd2eff74c4e5b78a58e87b3294b55405e40b888 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 3 Jan 2017 15:55:00 -0700 Subject: [PATCH 029/522] Cleanup Redox repo, update Rust, remove old target --- Makefile | 30 +++++++++---------- arm-unknown-redox.json | 26 ---------------- Cargo.toml => kernel/Cargo.toml | 4 +-- {arch => kernel/arch}/arm/Cargo.toml | 2 +- {arch => kernel/arch}/arm/src/context.rs | 0 {arch => kernel/arch}/arm/src/externs.rs | 0 {arch => kernel/arch}/arm/src/interrupt.rs | 0 {arch => kernel/arch}/arm/src/lib.rs | 0 {arch => kernel/arch}/arm/src/linker.ld | 0 {arch => kernel/arch}/arm/src/panic.rs | 0 {arch => kernel/arch}/arm/src/start.rs | 0 {arch => kernel/arch}/test/Cargo.toml | 0 {arch => kernel/arch}/test/src/interrupt.rs | 0 {arch => kernel/arch}/test/src/lib.rs | 0 {arch => kernel/arch}/test/src/main.rs | 0 {arch => kernel/arch}/test/src/time.rs | 0 {arch => kernel/arch}/x86_64/Cargo.toml | 6 ++-- .../arch}/x86_64/src/acpi/dmar/drhd.rs | 0 .../arch}/x86_64/src/acpi/dmar/mod.rs | 0 {arch => kernel/arch}/x86_64/src/acpi/fadt.rs | 0 {arch => kernel/arch}/x86_64/src/acpi/madt.rs | 0 {arch => kernel/arch}/x86_64/src/acpi/mod.rs | 0 {arch => kernel/arch}/x86_64/src/acpi/rsdt.rs | 0 {arch => kernel/arch}/x86_64/src/acpi/sdt.rs | 0 {arch => kernel/arch}/x86_64/src/acpi/xsdt.rs | 0 {arch => kernel/arch}/x86_64/src/console.rs | 0 {arch => kernel/arch}/x86_64/src/context.rs | 0 .../arch}/x86_64/src/device/cpu.rs | 0 .../arch}/x86_64/src/device/local_apic.rs | 0 .../arch}/x86_64/src/device/mod.rs | 0 .../arch}/x86_64/src/device/rtc.rs | 0 .../arch}/x86_64/src/device/serial.rs | 0 {arch => kernel/arch}/x86_64/src/externs.rs | 0 {arch => kernel/arch}/x86_64/src/gdt.rs | 0 {arch => kernel/arch}/x86_64/src/idt.rs | 0 .../arch}/x86_64/src/interrupt/exception.rs | 0 .../arch}/x86_64/src/interrupt/ipi.rs | 0 .../arch}/x86_64/src/interrupt/irq.rs | 0 .../arch}/x86_64/src/interrupt/mod.rs | 0 .../arch}/x86_64/src/interrupt/syscall.rs | 0 {arch => kernel/arch}/x86_64/src/lib.rs | 0 {arch => kernel/arch}/x86_64/src/linker.ld | 0 .../x86_64/src/memory/area_frame_allocator.rs | 0 .../arch}/x86_64/src/memory/mod.rs | 0 .../arch}/x86_64/src/paging/entry.rs | 0 .../arch}/x86_64/src/paging/mapper.rs | 0 .../arch}/x86_64/src/paging/mod.rs | 0 .../arch}/x86_64/src/paging/table.rs | 0 .../arch}/x86_64/src/paging/temporary_page.rs | 0 {arch => kernel/arch}/x86_64/src/panic.rs | 0 {arch => kernel/arch}/x86_64/src/start.rs | 0 {arch => kernel/arch}/x86_64/src/stop.rs | 0 {arch => kernel/arch}/x86_64/src/time.rs | 0 kernel/{ => src}/common/int_like.rs | 0 kernel/{ => src}/common/mod.rs | 0 kernel/{ => src}/context/context.rs | 0 kernel/{ => src}/context/event.rs | 0 kernel/{ => src}/context/file.rs | 0 kernel/{ => src}/context/list.rs | 0 kernel/{ => src}/context/memory.rs | 0 kernel/{ => src}/context/mod.rs | 0 kernel/{ => src}/context/switch.rs | 0 kernel/{ => src}/elf.rs | 0 kernel/{ => src}/lib.rs | 0 kernel/{ => src}/scheme/debug.rs | 0 kernel/{ => src}/scheme/env.rs | 0 kernel/{ => src}/scheme/event.rs | 0 kernel/{ => src}/scheme/initfs.rs | 2 +- kernel/{ => src}/scheme/irq.rs | 0 kernel/{ => src}/scheme/live.rs | 2 +- kernel/{ => src}/scheme/memory.rs | 0 kernel/{ => src}/scheme/mod.rs | 0 kernel/{ => src}/scheme/null.rs | 0 kernel/{ => src}/scheme/pipe.rs | 0 kernel/{ => src}/scheme/root.rs | 0 kernel/{ => src}/scheme/sys/context.rs | 0 kernel/{ => src}/scheme/sys/cpu.rs | 0 kernel/{ => src}/scheme/sys/exe.rs | 0 kernel/{ => src}/scheme/sys/mod.rs | 0 kernel/{ => src}/scheme/sys/scheme.rs | 0 kernel/{ => src}/scheme/user.rs | 0 kernel/{ => src}/scheme/zero.rs | 0 kernel/{ => src}/sync/mod.rs | 0 kernel/{ => src}/sync/wait_condition.rs | 0 kernel/{ => src}/sync/wait_map.rs | 0 kernel/{ => src}/sync/wait_queue.rs | 0 kernel/{ => src}/syscall/driver.rs | 0 kernel/{ => src}/syscall/fs.rs | 0 kernel/{ => src}/syscall/futex.rs | 0 kernel/{ => src}/syscall/mod.rs | 0 kernel/{ => src}/syscall/privilege.rs | 0 kernel/{ => src}/syscall/process.rs | 0 kernel/{ => src}/syscall/time.rs | 0 kernel/{ => src}/syscall/validate.rs | 0 kernel/{ => src}/tests/mod.rs | 0 rust | 2 +- x86_64-unknown-redox.json | 29 ------------------ 97 files changed, 24 insertions(+), 79 deletions(-) delete mode 100644 arm-unknown-redox.json rename Cargo.toml => kernel/Cargo.toml (90%) rename {arch => kernel/arch}/arm/Cargo.toml (55%) rename {arch => kernel/arch}/arm/src/context.rs (100%) rename {arch => kernel/arch}/arm/src/externs.rs (100%) rename {arch => kernel/arch}/arm/src/interrupt.rs (100%) rename {arch => kernel/arch}/arm/src/lib.rs (100%) rename {arch => kernel/arch}/arm/src/linker.ld (100%) rename {arch => kernel/arch}/arm/src/panic.rs (100%) rename {arch => kernel/arch}/arm/src/start.rs (100%) rename {arch => kernel/arch}/test/Cargo.toml (100%) rename {arch => kernel/arch}/test/src/interrupt.rs (100%) rename {arch => kernel/arch}/test/src/lib.rs (100%) rename {arch => kernel/arch}/test/src/main.rs (100%) rename {arch => kernel/arch}/test/src/time.rs (100%) rename {arch => kernel/arch}/x86_64/Cargo.toml (57%) rename {arch => kernel/arch}/x86_64/src/acpi/dmar/drhd.rs (100%) rename {arch => kernel/arch}/x86_64/src/acpi/dmar/mod.rs (100%) rename {arch => kernel/arch}/x86_64/src/acpi/fadt.rs (100%) rename {arch => kernel/arch}/x86_64/src/acpi/madt.rs (100%) rename {arch => kernel/arch}/x86_64/src/acpi/mod.rs (100%) rename {arch => kernel/arch}/x86_64/src/acpi/rsdt.rs (100%) rename {arch => kernel/arch}/x86_64/src/acpi/sdt.rs (100%) rename {arch => kernel/arch}/x86_64/src/acpi/xsdt.rs (100%) rename {arch => kernel/arch}/x86_64/src/console.rs (100%) rename {arch => kernel/arch}/x86_64/src/context.rs (100%) rename {arch => kernel/arch}/x86_64/src/device/cpu.rs (100%) rename {arch => kernel/arch}/x86_64/src/device/local_apic.rs (100%) rename {arch => kernel/arch}/x86_64/src/device/mod.rs (100%) rename {arch => kernel/arch}/x86_64/src/device/rtc.rs (100%) rename {arch => kernel/arch}/x86_64/src/device/serial.rs (100%) rename {arch => kernel/arch}/x86_64/src/externs.rs (100%) rename {arch => kernel/arch}/x86_64/src/gdt.rs (100%) rename {arch => kernel/arch}/x86_64/src/idt.rs (100%) rename {arch => kernel/arch}/x86_64/src/interrupt/exception.rs (100%) rename {arch => kernel/arch}/x86_64/src/interrupt/ipi.rs (100%) rename {arch => kernel/arch}/x86_64/src/interrupt/irq.rs (100%) rename {arch => kernel/arch}/x86_64/src/interrupt/mod.rs (100%) rename {arch => kernel/arch}/x86_64/src/interrupt/syscall.rs (100%) rename {arch => kernel/arch}/x86_64/src/lib.rs (100%) rename {arch => kernel/arch}/x86_64/src/linker.ld (100%) rename {arch => kernel/arch}/x86_64/src/memory/area_frame_allocator.rs (100%) rename {arch => kernel/arch}/x86_64/src/memory/mod.rs (100%) rename {arch => kernel/arch}/x86_64/src/paging/entry.rs (100%) rename {arch => kernel/arch}/x86_64/src/paging/mapper.rs (100%) rename {arch => kernel/arch}/x86_64/src/paging/mod.rs (100%) rename {arch => kernel/arch}/x86_64/src/paging/table.rs (100%) rename {arch => kernel/arch}/x86_64/src/paging/temporary_page.rs (100%) rename {arch => kernel/arch}/x86_64/src/panic.rs (100%) rename {arch => kernel/arch}/x86_64/src/start.rs (100%) rename {arch => kernel/arch}/x86_64/src/stop.rs (100%) rename {arch => kernel/arch}/x86_64/src/time.rs (100%) rename kernel/{ => src}/common/int_like.rs (100%) rename kernel/{ => src}/common/mod.rs (100%) rename kernel/{ => src}/context/context.rs (100%) rename kernel/{ => src}/context/event.rs (100%) rename kernel/{ => src}/context/file.rs (100%) rename kernel/{ => src}/context/list.rs (100%) rename kernel/{ => src}/context/memory.rs (100%) rename kernel/{ => src}/context/mod.rs (100%) rename kernel/{ => src}/context/switch.rs (100%) rename kernel/{ => src}/elf.rs (100%) rename kernel/{ => src}/lib.rs (100%) rename kernel/{ => src}/scheme/debug.rs (100%) rename kernel/{ => src}/scheme/env.rs (100%) rename kernel/{ => src}/scheme/event.rs (100%) rename kernel/{ => src}/scheme/initfs.rs (99%) rename kernel/{ => src}/scheme/irq.rs (100%) rename kernel/{ => src}/scheme/live.rs (98%) rename kernel/{ => src}/scheme/memory.rs (100%) rename kernel/{ => src}/scheme/mod.rs (100%) rename kernel/{ => src}/scheme/null.rs (100%) rename kernel/{ => src}/scheme/pipe.rs (100%) rename kernel/{ => src}/scheme/root.rs (100%) rename kernel/{ => src}/scheme/sys/context.rs (100%) rename kernel/{ => src}/scheme/sys/cpu.rs (100%) rename kernel/{ => src}/scheme/sys/exe.rs (100%) rename kernel/{ => src}/scheme/sys/mod.rs (100%) rename kernel/{ => src}/scheme/sys/scheme.rs (100%) rename kernel/{ => src}/scheme/user.rs (100%) rename kernel/{ => src}/scheme/zero.rs (100%) rename kernel/{ => src}/sync/mod.rs (100%) rename kernel/{ => src}/sync/wait_condition.rs (100%) rename kernel/{ => src}/sync/wait_map.rs (100%) rename kernel/{ => src}/sync/wait_queue.rs (100%) rename kernel/{ => src}/syscall/driver.rs (100%) rename kernel/{ => src}/syscall/fs.rs (100%) rename kernel/{ => src}/syscall/futex.rs (100%) rename kernel/{ => src}/syscall/mod.rs (100%) rename kernel/{ => src}/syscall/privilege.rs (100%) rename kernel/{ => src}/syscall/process.rs (100%) rename kernel/{ => src}/syscall/time.rs (100%) rename kernel/{ => src}/syscall/validate.rs (100%) rename kernel/{ => src}/tests/mod.rs (100%) delete mode 100644 x86_64-unknown-redox.json diff --git a/Makefile b/Makefile index 30d36b1..fedb4af 100644 --- a/Makefile +++ b/Makefile @@ -3,11 +3,11 @@ ARCH?=x86_64 ROOT=$(PWD) export RUST_TARGET_PATH=$(ROOT)/targets -#TODO: Use libssp -export CFLAGS=-nostartfiles -nostdlib -nodefaultlibs \ +export CFLAGS=-static -nostartfiles -nostdlib -nodefaultlibs \ -undef -imacros $(ROOT)/libc-artifacts/define.h \ -isystem $(ROOT)/libc-artifacts/usr/include \ -L $(ROOT)/libc-artifacts/usr/lib \ + $(ROOT)/libc-artifacts/usr/lib/crt0.o -lm -lc -lgcc \ -fno-stack-protector -U_FORTIFY_SOURCE # Kernel variables @@ -23,10 +23,10 @@ KCARGOFLAGS=--target $(KTARGET) --release -- -C soft-float export TARGET=$(ARCH)-unknown-redox BUILD=build/userspace RUSTC=./rustc.sh -RUSTCFLAGS=--target $(TARGET).json -C opt-level=2 -C debuginfo=0 +RUSTCFLAGS=--target $(TARGET) -C opt-level=2 -C debuginfo=0 RUSTDOC=./rustdoc.sh CARGO=RUSTC="$(RUSTC)" RUSTDOC="$(RUSTDOC)" cargo -CARGOFLAGS=--target $(TARGET).json --release -- +CARGOFLAGS=--target $(TARGET) --release -- # Default targets .PHONY: all live iso clean doc ref test update pull qemu bochs drivers schemes binutils coreutils extrautils netutils userutils wireshark FORCE @@ -40,8 +40,8 @@ iso: build/livedisk.iso FORCE: clean: - cargo clean cargo clean --manifest-path rust/src/libstd/Cargo.toml + cargo clean --manifest-path kernel/Cargo.toml cargo clean --manifest-path drivers/ahcid/Cargo.toml cargo clean --manifest-path drivers/e1000d/Cargo.toml cargo clean --manifest-path drivers/ps2d/Cargo.toml @@ -82,7 +82,7 @@ doc: \ #FORCE to let cargo decide if docs need updating doc-kernel: $(KBUILD)/libkernel.a FORCE - $(KCARGO) doc --target $(KTARGET).json + $(KCARGO) doc --target $(KTARGET).json --manifest-path kernel/Cargo.toml doc-std: $(BUILD)/libstd.rlib FORCE $(CARGO) doc --target $(TARGET).json --manifest-path rust/src/libstd/Cargo.toml @@ -96,8 +96,8 @@ ref: FORCE cargo run --manifest-path crates/docgen/Cargo.toml -- programs/netutils/src/ filesystem/ref/ test: - cargo test cargo test --manifest-path rust/src/libstd/Cargo.toml + cargo test --manifest-path kernel/Cargo.toml cargo test --manifest-path drivers/ahcid/Cargo.toml cargo test --manifest-path drivers/e1000d/Cargo.toml cargo test --manifest-path drivers/ps2d/Cargo.toml @@ -129,8 +129,8 @@ test: cargo test --manifest-path schemes/udpd/Cargo.toml update: - cargo update - cargo update --manifest-path rust/src/libstd/Cargo.toml + #cargo update --manifest-path rust/src/libstd/Cargo.toml + cargo update --manifest-path kernel/Cargo.toml cargo update --manifest-path drivers/ahcid/Cargo.toml cargo update --manifest-path drivers/e1000d/Cargo.toml cargo update --manifest-path drivers/ps2d/Cargo.toml @@ -350,17 +350,17 @@ $(KBUILD)/libstd_unicode.rlib: rust/src/libstd_unicode/lib.rs $(KBUILD)/libcore. $(KBUILD)/libcollections.rlib: rust/src/libcollections/lib.rs $(KBUILD)/libcore.rlib $(KBUILD)/liballoc.rlib $(KBUILD)/libstd_unicode.rlib $(KRUSTC) $(KRUSTCFLAGS) -o $@ $< -$(KBUILD)/libkernel.a: kernel/** $(KBUILD)/libcore.rlib $(KBUILD)/liballoc.rlib $(KBUILD)/libcollections.rlib $(BUILD)/initfs.rs - $(KCARGO) rustc $(KCARGOFLAGS) -C lto -o $@ +$(KBUILD)/libkernel.a: kernel/Cargo.toml kernel/arch/** kernel/src/** $(KBUILD)/libcore.rlib $(KBUILD)/liballoc.rlib $(KBUILD)/libcollections.rlib $(BUILD)/initfs.rs + $(KCARGO) rustc --manifest-path $< --lib $(KCARGOFLAGS) -C lto --emit obj=$@ -$(KBUILD)/libkernel_live.a: kernel/** $(KBUILD)/libcore.rlib $(KBUILD)/liballoc.rlib $(KBUILD)/libcollections.rlib $(BUILD)/initfs.rs build/filesystem.bin - $(KCARGO) rustc --lib $(KCARGOFLAGS) --cfg 'feature="live"' -C lto --emit obj=$@ +$(KBUILD)/libkernel_live.a: kernel/Cargo.toml kernel/arch/** kernel/src/** $(KBUILD)/libcore.rlib $(KBUILD)/liballoc.rlib $(KBUILD)/libcollections.rlib $(BUILD)/initfs.rs build/filesystem.bin + $(KCARGO) rustc --manifest-path $< --lib $(KCARGOFLAGS) --cfg 'feature="live"' -C lto --emit obj=$@ $(KBUILD)/kernel: $(KBUILD)/libkernel.a - $(LD) $(LDFLAGS) -z max-page-size=0x1000 -T arch/$(ARCH)/src/linker.ld -o $@ $< + $(LD) $(LDFLAGS) -z max-page-size=0x1000 -T kernel/arch/$(ARCH)/src/linker.ld -o $@ $< $(KBUILD)/kernel_live: $(KBUILD)/libkernel_live.a - $(LD) $(LDFLAGS) -z max-page-size=0x1000 -T arch/$(ARCH)/src/linker.ld -o $@ $< + $(LD) $(LDFLAGS) -z max-page-size=0x1000 -T kernel/arch/$(ARCH)/src/linker.ld -o $@ $< # Userspace recipes $(BUILD)/libstd.rlib: rust/src/libstd/Cargo.toml rust/src/libstd/** diff --git a/arm-unknown-redox.json b/arm-unknown-redox.json deleted file mode 100644 index 6089ab1..0000000 --- a/arm-unknown-redox.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "llvm-target": "arm-unknown-redox", - "target-endian": "little", - "target-pointer-width": "32", - "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64", - "arch": "arm", - "os": "redox", - "env": "", - "vendor": "unknown", - "target-family": "redox", - "pre-link-args": ["-nostdlib", "-static"], - "features": "+soft-float", - "dynamic-linking": false, - "executables": true, - "relocation-model": "static", - "code-model": "default", - "disable-redzone": true, - "eliminate-frame-pointer": false, - "exe-suffix": "", - "has-rpath": false, - "no-compiler-rt": true, - "no-default-libraries": true, - "position-independent-executables": false, - "has-elf-tls": true, - "panic-strategy": "abort" -} diff --git a/Cargo.toml b/kernel/Cargo.toml similarity index 90% rename from Cargo.toml rename to kernel/Cargo.toml index 5c3c138..8fd747e 100644 --- a/Cargo.toml +++ b/kernel/Cargo.toml @@ -4,13 +4,13 @@ version = "0.1.0" [lib] name = "kernel" -path = "kernel/lib.rs" +path = "src/lib.rs" crate-type = ["staticlib"] [dependencies] bitflags = "*" spin = "*" -redox_syscall = { path = "syscall/" } +redox_syscall = { path = "../syscall/" } [dependencies.goblin] git = "https://github.com/m4b/goblin.git" diff --git a/arch/arm/Cargo.toml b/kernel/arch/arm/Cargo.toml similarity index 55% rename from arch/arm/Cargo.toml rename to kernel/arch/arm/Cargo.toml index deadc75..d477d18 100644 --- a/arch/arm/Cargo.toml +++ b/kernel/arch/arm/Cargo.toml @@ -4,5 +4,5 @@ version = "0.1.0" [dependencies] bitflags = "*" -hole_list_allocator = { path = "../../crates/hole_list_allocator"} +hole_list_allocator = { path = "../../../crates/hole_list_allocator"} spin = "*" diff --git a/arch/arm/src/context.rs b/kernel/arch/arm/src/context.rs similarity index 100% rename from arch/arm/src/context.rs rename to kernel/arch/arm/src/context.rs diff --git a/arch/arm/src/externs.rs b/kernel/arch/arm/src/externs.rs similarity index 100% rename from arch/arm/src/externs.rs rename to kernel/arch/arm/src/externs.rs diff --git a/arch/arm/src/interrupt.rs b/kernel/arch/arm/src/interrupt.rs similarity index 100% rename from arch/arm/src/interrupt.rs rename to kernel/arch/arm/src/interrupt.rs diff --git a/arch/arm/src/lib.rs b/kernel/arch/arm/src/lib.rs similarity index 100% rename from arch/arm/src/lib.rs rename to kernel/arch/arm/src/lib.rs diff --git a/arch/arm/src/linker.ld b/kernel/arch/arm/src/linker.ld similarity index 100% rename from arch/arm/src/linker.ld rename to kernel/arch/arm/src/linker.ld diff --git a/arch/arm/src/panic.rs b/kernel/arch/arm/src/panic.rs similarity index 100% rename from arch/arm/src/panic.rs rename to kernel/arch/arm/src/panic.rs diff --git a/arch/arm/src/start.rs b/kernel/arch/arm/src/start.rs similarity index 100% rename from arch/arm/src/start.rs rename to kernel/arch/arm/src/start.rs diff --git a/arch/test/Cargo.toml b/kernel/arch/test/Cargo.toml similarity index 100% rename from arch/test/Cargo.toml rename to kernel/arch/test/Cargo.toml diff --git a/arch/test/src/interrupt.rs b/kernel/arch/test/src/interrupt.rs similarity index 100% rename from arch/test/src/interrupt.rs rename to kernel/arch/test/src/interrupt.rs diff --git a/arch/test/src/lib.rs b/kernel/arch/test/src/lib.rs similarity index 100% rename from arch/test/src/lib.rs rename to kernel/arch/test/src/lib.rs diff --git a/arch/test/src/main.rs b/kernel/arch/test/src/main.rs similarity index 100% rename from arch/test/src/main.rs rename to kernel/arch/test/src/main.rs diff --git a/arch/test/src/time.rs b/kernel/arch/test/src/time.rs similarity index 100% rename from arch/test/src/time.rs rename to kernel/arch/test/src/time.rs diff --git a/arch/x86_64/Cargo.toml b/kernel/arch/x86_64/Cargo.toml similarity index 57% rename from arch/x86_64/Cargo.toml rename to kernel/arch/x86_64/Cargo.toml index 695a907..a255e4d 100644 --- a/arch/x86_64/Cargo.toml +++ b/kernel/arch/x86_64/Cargo.toml @@ -4,11 +4,11 @@ version = "0.1.0" [dependencies] bitflags = "*" -hole_list_allocator = { path = "../../crates/hole_list_allocator/" } -io = { path = "../../crates/io/" } +hole_list_allocator = { path = "../../../crates/hole_list_allocator/" } +io = { path = "../../../crates/io/" } raw-cpuid = { git = "https://github.com/gz/rust-cpuid" } spin = "*" -redox_syscall = { path = "../../syscall/" } +redox_syscall = { path = "../../../syscall/" } [dependencies.x86] version = "0.7" diff --git a/arch/x86_64/src/acpi/dmar/drhd.rs b/kernel/arch/x86_64/src/acpi/dmar/drhd.rs similarity index 100% rename from arch/x86_64/src/acpi/dmar/drhd.rs rename to kernel/arch/x86_64/src/acpi/dmar/drhd.rs diff --git a/arch/x86_64/src/acpi/dmar/mod.rs b/kernel/arch/x86_64/src/acpi/dmar/mod.rs similarity index 100% rename from arch/x86_64/src/acpi/dmar/mod.rs rename to kernel/arch/x86_64/src/acpi/dmar/mod.rs diff --git a/arch/x86_64/src/acpi/fadt.rs b/kernel/arch/x86_64/src/acpi/fadt.rs similarity index 100% rename from arch/x86_64/src/acpi/fadt.rs rename to kernel/arch/x86_64/src/acpi/fadt.rs diff --git a/arch/x86_64/src/acpi/madt.rs b/kernel/arch/x86_64/src/acpi/madt.rs similarity index 100% rename from arch/x86_64/src/acpi/madt.rs rename to kernel/arch/x86_64/src/acpi/madt.rs diff --git a/arch/x86_64/src/acpi/mod.rs b/kernel/arch/x86_64/src/acpi/mod.rs similarity index 100% rename from arch/x86_64/src/acpi/mod.rs rename to kernel/arch/x86_64/src/acpi/mod.rs diff --git a/arch/x86_64/src/acpi/rsdt.rs b/kernel/arch/x86_64/src/acpi/rsdt.rs similarity index 100% rename from arch/x86_64/src/acpi/rsdt.rs rename to kernel/arch/x86_64/src/acpi/rsdt.rs diff --git a/arch/x86_64/src/acpi/sdt.rs b/kernel/arch/x86_64/src/acpi/sdt.rs similarity index 100% rename from arch/x86_64/src/acpi/sdt.rs rename to kernel/arch/x86_64/src/acpi/sdt.rs diff --git a/arch/x86_64/src/acpi/xsdt.rs b/kernel/arch/x86_64/src/acpi/xsdt.rs similarity index 100% rename from arch/x86_64/src/acpi/xsdt.rs rename to kernel/arch/x86_64/src/acpi/xsdt.rs diff --git a/arch/x86_64/src/console.rs b/kernel/arch/x86_64/src/console.rs similarity index 100% rename from arch/x86_64/src/console.rs rename to kernel/arch/x86_64/src/console.rs diff --git a/arch/x86_64/src/context.rs b/kernel/arch/x86_64/src/context.rs similarity index 100% rename from arch/x86_64/src/context.rs rename to kernel/arch/x86_64/src/context.rs diff --git a/arch/x86_64/src/device/cpu.rs b/kernel/arch/x86_64/src/device/cpu.rs similarity index 100% rename from arch/x86_64/src/device/cpu.rs rename to kernel/arch/x86_64/src/device/cpu.rs diff --git a/arch/x86_64/src/device/local_apic.rs b/kernel/arch/x86_64/src/device/local_apic.rs similarity index 100% rename from arch/x86_64/src/device/local_apic.rs rename to kernel/arch/x86_64/src/device/local_apic.rs diff --git a/arch/x86_64/src/device/mod.rs b/kernel/arch/x86_64/src/device/mod.rs similarity index 100% rename from arch/x86_64/src/device/mod.rs rename to kernel/arch/x86_64/src/device/mod.rs diff --git a/arch/x86_64/src/device/rtc.rs b/kernel/arch/x86_64/src/device/rtc.rs similarity index 100% rename from arch/x86_64/src/device/rtc.rs rename to kernel/arch/x86_64/src/device/rtc.rs diff --git a/arch/x86_64/src/device/serial.rs b/kernel/arch/x86_64/src/device/serial.rs similarity index 100% rename from arch/x86_64/src/device/serial.rs rename to kernel/arch/x86_64/src/device/serial.rs diff --git a/arch/x86_64/src/externs.rs b/kernel/arch/x86_64/src/externs.rs similarity index 100% rename from arch/x86_64/src/externs.rs rename to kernel/arch/x86_64/src/externs.rs diff --git a/arch/x86_64/src/gdt.rs b/kernel/arch/x86_64/src/gdt.rs similarity index 100% rename from arch/x86_64/src/gdt.rs rename to kernel/arch/x86_64/src/gdt.rs diff --git a/arch/x86_64/src/idt.rs b/kernel/arch/x86_64/src/idt.rs similarity index 100% rename from arch/x86_64/src/idt.rs rename to kernel/arch/x86_64/src/idt.rs diff --git a/arch/x86_64/src/interrupt/exception.rs b/kernel/arch/x86_64/src/interrupt/exception.rs similarity index 100% rename from arch/x86_64/src/interrupt/exception.rs rename to kernel/arch/x86_64/src/interrupt/exception.rs diff --git a/arch/x86_64/src/interrupt/ipi.rs b/kernel/arch/x86_64/src/interrupt/ipi.rs similarity index 100% rename from arch/x86_64/src/interrupt/ipi.rs rename to kernel/arch/x86_64/src/interrupt/ipi.rs diff --git a/arch/x86_64/src/interrupt/irq.rs b/kernel/arch/x86_64/src/interrupt/irq.rs similarity index 100% rename from arch/x86_64/src/interrupt/irq.rs rename to kernel/arch/x86_64/src/interrupt/irq.rs diff --git a/arch/x86_64/src/interrupt/mod.rs b/kernel/arch/x86_64/src/interrupt/mod.rs similarity index 100% rename from arch/x86_64/src/interrupt/mod.rs rename to kernel/arch/x86_64/src/interrupt/mod.rs diff --git a/arch/x86_64/src/interrupt/syscall.rs b/kernel/arch/x86_64/src/interrupt/syscall.rs similarity index 100% rename from arch/x86_64/src/interrupt/syscall.rs rename to kernel/arch/x86_64/src/interrupt/syscall.rs diff --git a/arch/x86_64/src/lib.rs b/kernel/arch/x86_64/src/lib.rs similarity index 100% rename from arch/x86_64/src/lib.rs rename to kernel/arch/x86_64/src/lib.rs diff --git a/arch/x86_64/src/linker.ld b/kernel/arch/x86_64/src/linker.ld similarity index 100% rename from arch/x86_64/src/linker.ld rename to kernel/arch/x86_64/src/linker.ld diff --git a/arch/x86_64/src/memory/area_frame_allocator.rs b/kernel/arch/x86_64/src/memory/area_frame_allocator.rs similarity index 100% rename from arch/x86_64/src/memory/area_frame_allocator.rs rename to kernel/arch/x86_64/src/memory/area_frame_allocator.rs diff --git a/arch/x86_64/src/memory/mod.rs b/kernel/arch/x86_64/src/memory/mod.rs similarity index 100% rename from arch/x86_64/src/memory/mod.rs rename to kernel/arch/x86_64/src/memory/mod.rs diff --git a/arch/x86_64/src/paging/entry.rs b/kernel/arch/x86_64/src/paging/entry.rs similarity index 100% rename from arch/x86_64/src/paging/entry.rs rename to kernel/arch/x86_64/src/paging/entry.rs diff --git a/arch/x86_64/src/paging/mapper.rs b/kernel/arch/x86_64/src/paging/mapper.rs similarity index 100% rename from arch/x86_64/src/paging/mapper.rs rename to kernel/arch/x86_64/src/paging/mapper.rs diff --git a/arch/x86_64/src/paging/mod.rs b/kernel/arch/x86_64/src/paging/mod.rs similarity index 100% rename from arch/x86_64/src/paging/mod.rs rename to kernel/arch/x86_64/src/paging/mod.rs diff --git a/arch/x86_64/src/paging/table.rs b/kernel/arch/x86_64/src/paging/table.rs similarity index 100% rename from arch/x86_64/src/paging/table.rs rename to kernel/arch/x86_64/src/paging/table.rs diff --git a/arch/x86_64/src/paging/temporary_page.rs b/kernel/arch/x86_64/src/paging/temporary_page.rs similarity index 100% rename from arch/x86_64/src/paging/temporary_page.rs rename to kernel/arch/x86_64/src/paging/temporary_page.rs diff --git a/arch/x86_64/src/panic.rs b/kernel/arch/x86_64/src/panic.rs similarity index 100% rename from arch/x86_64/src/panic.rs rename to kernel/arch/x86_64/src/panic.rs diff --git a/arch/x86_64/src/start.rs b/kernel/arch/x86_64/src/start.rs similarity index 100% rename from arch/x86_64/src/start.rs rename to kernel/arch/x86_64/src/start.rs diff --git a/arch/x86_64/src/stop.rs b/kernel/arch/x86_64/src/stop.rs similarity index 100% rename from arch/x86_64/src/stop.rs rename to kernel/arch/x86_64/src/stop.rs diff --git a/arch/x86_64/src/time.rs b/kernel/arch/x86_64/src/time.rs similarity index 100% rename from arch/x86_64/src/time.rs rename to kernel/arch/x86_64/src/time.rs diff --git a/kernel/common/int_like.rs b/kernel/src/common/int_like.rs similarity index 100% rename from kernel/common/int_like.rs rename to kernel/src/common/int_like.rs diff --git a/kernel/common/mod.rs b/kernel/src/common/mod.rs similarity index 100% rename from kernel/common/mod.rs rename to kernel/src/common/mod.rs diff --git a/kernel/context/context.rs b/kernel/src/context/context.rs similarity index 100% rename from kernel/context/context.rs rename to kernel/src/context/context.rs diff --git a/kernel/context/event.rs b/kernel/src/context/event.rs similarity index 100% rename from kernel/context/event.rs rename to kernel/src/context/event.rs diff --git a/kernel/context/file.rs b/kernel/src/context/file.rs similarity index 100% rename from kernel/context/file.rs rename to kernel/src/context/file.rs diff --git a/kernel/context/list.rs b/kernel/src/context/list.rs similarity index 100% rename from kernel/context/list.rs rename to kernel/src/context/list.rs diff --git a/kernel/context/memory.rs b/kernel/src/context/memory.rs similarity index 100% rename from kernel/context/memory.rs rename to kernel/src/context/memory.rs diff --git a/kernel/context/mod.rs b/kernel/src/context/mod.rs similarity index 100% rename from kernel/context/mod.rs rename to kernel/src/context/mod.rs diff --git a/kernel/context/switch.rs b/kernel/src/context/switch.rs similarity index 100% rename from kernel/context/switch.rs rename to kernel/src/context/switch.rs diff --git a/kernel/elf.rs b/kernel/src/elf.rs similarity index 100% rename from kernel/elf.rs rename to kernel/src/elf.rs diff --git a/kernel/lib.rs b/kernel/src/lib.rs similarity index 100% rename from kernel/lib.rs rename to kernel/src/lib.rs diff --git a/kernel/scheme/debug.rs b/kernel/src/scheme/debug.rs similarity index 100% rename from kernel/scheme/debug.rs rename to kernel/src/scheme/debug.rs diff --git a/kernel/scheme/env.rs b/kernel/src/scheme/env.rs similarity index 100% rename from kernel/scheme/env.rs rename to kernel/src/scheme/env.rs diff --git a/kernel/scheme/event.rs b/kernel/src/scheme/event.rs similarity index 100% rename from kernel/scheme/event.rs rename to kernel/src/scheme/event.rs diff --git a/kernel/scheme/initfs.rs b/kernel/src/scheme/initfs.rs similarity index 99% rename from kernel/scheme/initfs.rs rename to kernel/src/scheme/initfs.rs index 6355928..0bd3790 100644 --- a/kernel/scheme/initfs.rs +++ b/kernel/src/scheme/initfs.rs @@ -15,7 +15,7 @@ mod gen { } #[cfg(not(test))] -#[path="../../build/userspace/initfs.rs"] +#[path="../../../build/userspace/initfs.rs"] mod gen; struct Handle { diff --git a/kernel/scheme/irq.rs b/kernel/src/scheme/irq.rs similarity index 100% rename from kernel/scheme/irq.rs rename to kernel/src/scheme/irq.rs diff --git a/kernel/scheme/live.rs b/kernel/src/scheme/live.rs similarity index 98% rename from kernel/scheme/live.rs rename to kernel/src/scheme/live.rs index e9ac3b8..c3f77ff 100644 --- a/kernel/scheme/live.rs +++ b/kernel/src/scheme/live.rs @@ -11,7 +11,7 @@ use syscall::error::*; use syscall::flag::{MODE_FILE, SEEK_SET, SEEK_CUR, SEEK_END}; use syscall::scheme::Scheme; -static FILESYSTEM: &'static [u8] = include_bytes!("../../build/filesystem.bin"); +static FILESYSTEM: &'static [u8] = include_bytes!("../../../build/filesystem.bin"); struct Handle { path: &'static [u8], diff --git a/kernel/scheme/memory.rs b/kernel/src/scheme/memory.rs similarity index 100% rename from kernel/scheme/memory.rs rename to kernel/src/scheme/memory.rs diff --git a/kernel/scheme/mod.rs b/kernel/src/scheme/mod.rs similarity index 100% rename from kernel/scheme/mod.rs rename to kernel/src/scheme/mod.rs diff --git a/kernel/scheme/null.rs b/kernel/src/scheme/null.rs similarity index 100% rename from kernel/scheme/null.rs rename to kernel/src/scheme/null.rs diff --git a/kernel/scheme/pipe.rs b/kernel/src/scheme/pipe.rs similarity index 100% rename from kernel/scheme/pipe.rs rename to kernel/src/scheme/pipe.rs diff --git a/kernel/scheme/root.rs b/kernel/src/scheme/root.rs similarity index 100% rename from kernel/scheme/root.rs rename to kernel/src/scheme/root.rs diff --git a/kernel/scheme/sys/context.rs b/kernel/src/scheme/sys/context.rs similarity index 100% rename from kernel/scheme/sys/context.rs rename to kernel/src/scheme/sys/context.rs diff --git a/kernel/scheme/sys/cpu.rs b/kernel/src/scheme/sys/cpu.rs similarity index 100% rename from kernel/scheme/sys/cpu.rs rename to kernel/src/scheme/sys/cpu.rs diff --git a/kernel/scheme/sys/exe.rs b/kernel/src/scheme/sys/exe.rs similarity index 100% rename from kernel/scheme/sys/exe.rs rename to kernel/src/scheme/sys/exe.rs diff --git a/kernel/scheme/sys/mod.rs b/kernel/src/scheme/sys/mod.rs similarity index 100% rename from kernel/scheme/sys/mod.rs rename to kernel/src/scheme/sys/mod.rs diff --git a/kernel/scheme/sys/scheme.rs b/kernel/src/scheme/sys/scheme.rs similarity index 100% rename from kernel/scheme/sys/scheme.rs rename to kernel/src/scheme/sys/scheme.rs diff --git a/kernel/scheme/user.rs b/kernel/src/scheme/user.rs similarity index 100% rename from kernel/scheme/user.rs rename to kernel/src/scheme/user.rs diff --git a/kernel/scheme/zero.rs b/kernel/src/scheme/zero.rs similarity index 100% rename from kernel/scheme/zero.rs rename to kernel/src/scheme/zero.rs diff --git a/kernel/sync/mod.rs b/kernel/src/sync/mod.rs similarity index 100% rename from kernel/sync/mod.rs rename to kernel/src/sync/mod.rs diff --git a/kernel/sync/wait_condition.rs b/kernel/src/sync/wait_condition.rs similarity index 100% rename from kernel/sync/wait_condition.rs rename to kernel/src/sync/wait_condition.rs diff --git a/kernel/sync/wait_map.rs b/kernel/src/sync/wait_map.rs similarity index 100% rename from kernel/sync/wait_map.rs rename to kernel/src/sync/wait_map.rs diff --git a/kernel/sync/wait_queue.rs b/kernel/src/sync/wait_queue.rs similarity index 100% rename from kernel/sync/wait_queue.rs rename to kernel/src/sync/wait_queue.rs diff --git a/kernel/syscall/driver.rs b/kernel/src/syscall/driver.rs similarity index 100% rename from kernel/syscall/driver.rs rename to kernel/src/syscall/driver.rs diff --git a/kernel/syscall/fs.rs b/kernel/src/syscall/fs.rs similarity index 100% rename from kernel/syscall/fs.rs rename to kernel/src/syscall/fs.rs diff --git a/kernel/syscall/futex.rs b/kernel/src/syscall/futex.rs similarity index 100% rename from kernel/syscall/futex.rs rename to kernel/src/syscall/futex.rs diff --git a/kernel/syscall/mod.rs b/kernel/src/syscall/mod.rs similarity index 100% rename from kernel/syscall/mod.rs rename to kernel/src/syscall/mod.rs diff --git a/kernel/syscall/privilege.rs b/kernel/src/syscall/privilege.rs similarity index 100% rename from kernel/syscall/privilege.rs rename to kernel/src/syscall/privilege.rs diff --git a/kernel/syscall/process.rs b/kernel/src/syscall/process.rs similarity index 100% rename from kernel/syscall/process.rs rename to kernel/src/syscall/process.rs diff --git a/kernel/syscall/time.rs b/kernel/src/syscall/time.rs similarity index 100% rename from kernel/syscall/time.rs rename to kernel/src/syscall/time.rs diff --git a/kernel/syscall/validate.rs b/kernel/src/syscall/validate.rs similarity index 100% rename from kernel/syscall/validate.rs rename to kernel/src/syscall/validate.rs diff --git a/kernel/tests/mod.rs b/kernel/src/tests/mod.rs similarity index 100% rename from kernel/tests/mod.rs rename to kernel/src/tests/mod.rs diff --git a/rust b/rust index 57950fa..c6858a1 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 57950faeb68754451f94062c11e3fcf830392025 +Subproject commit c6858a1429895f27b4daafde9295deb494e2e29c diff --git a/x86_64-unknown-redox.json b/x86_64-unknown-redox.json deleted file mode 100644 index d9df631..0000000 --- a/x86_64-unknown-redox.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "llvm-target": "x86_64-unknown-redox", - "target-endian": "little", - "target-pointer-width": "64", - "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128", - "arch": "x86_64", - "os": "redox", - "env": "", - "vendor": "unknown", - "target-family": "redox", - "pre-link-args": ["-m64", "-Wl,--as-needed", "-Wl,-z,noexecstack", "-nostartfiles", "-nostdlib", "-static"], - "late-link-args": ["libc-artifacts/usr/lib/crt0.o", "libc-artifacts/usr/lib/libm.a", "libc-artifacts/usr/lib/libc.a", "libc-artifacts/usr/lib/libgcc.a"], - "features": "", - "dynamic-linking": false, - "executables": true, - "relocation-model": "static", - "code-model": "default", - "disable-redzone": true, - "eliminate-frame-pointer": false, - "exe-suffix": "", - "has-rpath": false, - "no-compiler-rt": true, - "no-default-libraries": true, - "position-independent-executables": false, - "lib-allocation-crate": "alloc_system", - "exe-allocation-crate": "alloc_system", - "has-elf-tls": true, - "panic-strategy": "abort" -} From 6b7e6956f404ea25579d3014aa16c187300d2f2c Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 3 Jan 2017 15:57:54 -0700 Subject: [PATCH 030/522] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f4ada3d..dbacc4b 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Please make sure you use the **latest nightly** of `rustc` before building (for [![Travis Build Status](https://travis-ci.org/redox-os/redox.svg?branch=master)](https://travis-ci.org/redox-os/redox) [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE.md) -![Rust Version](https://img.shields.io/badge/rust-1.15.0--nightly%20(71c06a56a%202016--12--18)-lightgrey.svg) +![Rust Version](https://img.shields.io/badge/rust-1.16.0--nightly%20(4ecc85beb%202016--12--28)-lightgrey.svg) ## Contents From e99488f9168c5c3f33a7a333dac7ba9d7df6a8ca Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 3 Jan 2017 19:50:57 -0700 Subject: [PATCH 031/522] Go back to referencing libs directly --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index fedb4af..0df0610 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,10 @@ export CFLAGS=-static -nostartfiles -nostdlib -nodefaultlibs \ -undef -imacros $(ROOT)/libc-artifacts/define.h \ -isystem $(ROOT)/libc-artifacts/usr/include \ -L $(ROOT)/libc-artifacts/usr/lib \ - $(ROOT)/libc-artifacts/usr/lib/crt0.o -lm -lc -lgcc \ + $(ROOT)/libc-artifacts/usr/lib/crt0.o \ + $(ROOT)/libc-artifacts/usr/lib/libm.a \ + $(ROOT)/libc-artifacts/usr/lib/libc.a \ + $(ROOT)/libc-artifacts/usr/lib/libgcc.a \ -fno-stack-protector -U_FORTIFY_SOURCE # Kernel variables From a3e79e56234376d89c116368d840418a9688e337 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 4 Jan 2017 09:39:16 -0700 Subject: [PATCH 032/522] Potential fix for issue with gcc49 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cec207d..02afecc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,7 +20,7 @@ before_install: fi - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew update && - brew install nasm gcc49 pkg-config Caskroom/cask/osxfuse && + brew install nasm pkg-config Caskroom/cask/osxfuse && brew tap glendc/gcc_cross_compilers && brew install glendc/gcc_cross_compilers/x64-elf-binutils glendc/gcc_cross_compilers/x64-elf-gcc; fi From 53144d1c93e6ac1d6a98cfefad79d2dcfa65aa86 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 4 Jan 2017 10:31:05 -0700 Subject: [PATCH 033/522] Update libc-artifacts --- libc-artifacts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libc-artifacts b/libc-artifacts index 4bff613..72fa53f 160000 --- a/libc-artifacts +++ b/libc-artifacts @@ -1 +1 @@ -Subproject commit 4bff613d3c4214ef4081427ab0a74d8f6f724935 +Subproject commit 72fa53f638f25d7c03cbb4b413b59862f7298dae From c7aaa41ac545a357f89e2095e694e5d679d3f6b0 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 4 Jan 2017 10:39:03 -0700 Subject: [PATCH 034/522] Move linker config into libc-artifacts script. Use cargo config --- .cargo/config | 6 ++++++ Makefile | 37 ++++++++++++++++--------------------- 2 files changed, 22 insertions(+), 21 deletions(-) create mode 100644 .cargo/config diff --git a/.cargo/config b/.cargo/config new file mode 100644 index 0000000..4336324 --- /dev/null +++ b/.cargo/config @@ -0,0 +1,6 @@ +[target.x86_64-unknown-redox] +linker = "libc-artifacts/gcc.sh" +rustflags = [ + "--verbose", + "-Z", "print-link-args" +] diff --git a/Makefile b/Makefile index 0df0610..9ebe069 100644 --- a/Makefile +++ b/Makefile @@ -1,17 +1,11 @@ +# Configuration ARCH?=x86_64 +# Automatic variables ROOT=$(PWD) export RUST_TARGET_PATH=$(ROOT)/targets - -export CFLAGS=-static -nostartfiles -nostdlib -nodefaultlibs \ - -undef -imacros $(ROOT)/libc-artifacts/define.h \ - -isystem $(ROOT)/libc-artifacts/usr/include \ - -L $(ROOT)/libc-artifacts/usr/lib \ - $(ROOT)/libc-artifacts/usr/lib/crt0.o \ - $(ROOT)/libc-artifacts/usr/lib/libm.a \ - $(ROOT)/libc-artifacts/usr/lib/libc.a \ - $(ROOT)/libc-artifacts/usr/lib/libgcc.a \ - -fno-stack-protector -U_FORTIFY_SOURCE +export CC=$(ROOT)/libc-artifacts/gcc.sh +export CFLAGS=-fno-stack-protector -U_FORTIFY_SOURCE # Kernel variables KTARGET=$(ARCH)-unknown-none @@ -182,11 +176,6 @@ ifeq ($(ARCH),arm) export CC=$(ARCH)-none-eabi-gcc export LD=$(ARCH)-none-eabi-ld - KRUSTCFLAGS+=-C linker=$(CC) - KCARGOFLAGS+=-C linker=$(CC) - RUSTCFLAGS+=-C linker=$(CC) - CARGOFLAGS+=-C linker=$(CC) - %.list: % $(ARCH)-none-eabi-objdump -C -D $< > $@ @@ -240,11 +229,6 @@ else VBM=VBoxManage endif - KRUSTCFLAGS+=-C linker=$(CC) -C link-args="$(CFLAGS)" - KCARGOFLAGS+=-C linker=$(CC) -C link-args="$(CFLAGS)" - RUSTCFLAGS+=-C linker=$(CC) -C link-args="$(CFLAGS)" - CARGOFLAGS+=-C linker=$(CC) -C link-args="$(CFLAGS)" - %.list: % objdump -C -M intel -D $< > $@ @@ -357,7 +341,7 @@ $(KBUILD)/libkernel.a: kernel/Cargo.toml kernel/arch/** kernel/src/** $(KBUILD)/ $(KCARGO) rustc --manifest-path $< --lib $(KCARGOFLAGS) -C lto --emit obj=$@ $(KBUILD)/libkernel_live.a: kernel/Cargo.toml kernel/arch/** kernel/src/** $(KBUILD)/libcore.rlib $(KBUILD)/liballoc.rlib $(KBUILD)/libcollections.rlib $(BUILD)/initfs.rs build/filesystem.bin - $(KCARGO) rustc --manifest-path $< --lib $(KCARGOFLAGS) --cfg 'feature="live"' -C lto --emit obj=$@ + $(KCARGO) rustc --manifest-path $< --lib --features live $(KCARGOFLAGS) -C lto --emit obj=$@ $(KBUILD)/kernel: $(KBUILD)/libkernel.a $(LD) $(LDFLAGS) -z max-page-size=0x1000 -T kernel/arch/$(ARCH)/src/linker.ld -o $@ $< @@ -367,6 +351,11 @@ $(KBUILD)/kernel_live: $(KBUILD)/libkernel_live.a # Userspace recipes $(BUILD)/libstd.rlib: rust/src/libstd/Cargo.toml rust/src/libstd/** + mkdir -p $(BUILD) + $(CARGO) rustc --verbose --manifest-path $< --features "panic-unwind" $(CARGOFLAGS) -L native=libc-artifacts/usr/lib -o $@ + cp rust/src/target/$(TARGET)/release/deps/*.rlib $(BUILD) + +$(BUILD)/libtest.rlib: rust/src/libtest/Cargo.toml rust/src/libtest/** $(BUILD)/libstd.rlib mkdir -p $(BUILD) $(CARGO) rustc --verbose --manifest-path $< $(CARGOFLAGS) -L native=libc-artifacts/usr/lib -o $@ cp rust/src/target/$(TARGET)/release/deps/*.rlib $(BUILD) @@ -418,6 +407,12 @@ filesystem/bin/%: programs/%/Cargo.toml programs/%/src/** $(BUILD)/libstd.rlib $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ $(STRIP) $@ +# Example of compiling tests - still TODO +filesystem/test/%: programs/%/Cargo.toml programs/%/src/** $(BUILD)/libstd.rlib $(BUILD)/libtest.rlib + mkdir -p filesystem/test + $(CARGO) test --no-run --manifest-path $< $(CARGOFLAGS) + cp programs/$*/target/$(TARGET)/release/deps/$*-* $@ + filesystem/bin/sh: filesystem/bin/ion cp $< $@ From c80d3d35dc1d34251e40eb40cd2a585e9a39e381 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 4 Jan 2017 10:40:26 -0700 Subject: [PATCH 035/522] Update Rust --- rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust b/rust index c6858a1..d40d01b 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit c6858a1429895f27b4daafde9295deb494e2e29c +Subproject commit d40d01bd0e7d9d20bb3454a3d0870f00b805a01c From 237fa73e80fe665ba4b536ec6690876449b9b971 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 4 Jan 2017 10:56:57 -0700 Subject: [PATCH 036/522] Do not export CC, as it is exported above. Add OS X to gcc.sh --- Makefile | 2 -- libc-artifacts | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 9ebe069..f467b2a 100644 --- a/Makefile +++ b/Makefile @@ -207,7 +207,6 @@ else UNAME := $(shell uname) ifeq ($(UNAME),Darwin) - export CC=$(ARCH)-elf-gcc ECHO=/bin/echo FUMOUNT=sudo umount export LD=$(ARCH)-elf-ld @@ -216,7 +215,6 @@ else VB_AUDIO=coreaudio VBM="/Applications/VirtualBox.app/Contents/MacOS/VBoxManage" else - export CC=gcc ECHO=echo FUMOUNT=fusermount -u export LD=ld diff --git a/libc-artifacts b/libc-artifacts index 72fa53f..8d6a16b 160000 --- a/libc-artifacts +++ b/libc-artifacts @@ -1 +1 @@ -Subproject commit 72fa53f638f25d7c03cbb4b413b59862f7298dae +Subproject commit 8d6a16bbca95f3308a77378e018aa852d179dd6e From 38360911e5b3f4ac97e369cdcdcaa663d83964bb Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 4 Jan 2017 11:10:32 -0700 Subject: [PATCH 037/522] Update libc artifacts --- libc-artifacts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libc-artifacts b/libc-artifacts index 8d6a16b..92eb10e 160000 --- a/libc-artifacts +++ b/libc-artifacts @@ -1 +1 @@ -Subproject commit 8d6a16bbca95f3308a77378e018aa852d179dd6e +Subproject commit 92eb10e3a30a2a422d46bd16651071f8d2d0f1fd From 11dfb73c533aa41b9762d0134244e330092c2298 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 4 Jan 2017 11:11:45 -0700 Subject: [PATCH 038/522] Wait for gcc install on OS X --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 02afecc..01fbb25 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,7 +22,8 @@ before_install: brew update && brew install nasm pkg-config Caskroom/cask/osxfuse && brew tap glendc/gcc_cross_compilers && - brew install glendc/gcc_cross_compilers/x64-elf-binutils glendc/gcc_cross_compilers/x64-elf-gcc; + brew install glendc/gcc_cross_compilers/x64-elf-binutils && + travis_wait brew install glendc/gcc_cross_compilers/x64-elf-gcc; fi script: - make clean && From 437bc3280057d1191098d9ebefb352509f35b26b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 4 Jan 2017 13:25:56 -0700 Subject: [PATCH 039/522] Use redox-os brew --- .travis.yml | 4 +--- bootstrap.sh | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 01fbb25..efb4c03 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,9 +21,7 @@ before_install: - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew update && brew install nasm pkg-config Caskroom/cask/osxfuse && - brew tap glendc/gcc_cross_compilers && - brew install glendc/gcc_cross_compilers/x64-elf-binutils && - travis_wait brew install glendc/gcc_cross_compilers/x64-elf-gcc; + travis_wait 30 brew install redox-os/gcc_cross_compilers/x86_64-elf-gcc; fi script: - make clean && diff --git a/bootstrap.sh b/bootstrap.sh index b2e808e..dc24ee0 100644 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -129,7 +129,7 @@ osx_homebrew() install_brew_pkg "pkg-config" install_brew_cask_pkg "osxfuse" - install_brew_pkg "djphoenix/gcc_cross_compilers/x86_64-elf-gcc" + install_brew_pkg "redox-os/gcc_cross_compilers/x86_64-elf-gcc" } ############################################################################### From 0c8dc7c50dd1d7c3f342568b7f51ed5f3fb5152e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 4 Jan 2017 14:45:02 -0700 Subject: [PATCH 040/522] Add telnet --- Makefile | 3 ++- programs/netutils | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index f467b2a..4cbd23c 100644 --- a/Makefile +++ b/Makefile @@ -196,7 +196,7 @@ else else QEMUFLAGS+=-net nic,model=e1000 -net user -net dump,file=build/network.pcap ifeq ($(net),redir) - QEMUFLAGS+=-redir tcp:8080::8080 + QEMUFLAGS+=-redir tcp:8023::8023 -redir tcp:8080::8080 endif endif ifeq ($(vga),no) @@ -539,6 +539,7 @@ netutils: \ filesystem/bin/irc \ filesystem/bin/nc \ filesystem/bin/ntp \ + filesystem/bin/telnetd \ filesystem/bin/wget orbutils: \ diff --git a/programs/netutils b/programs/netutils index 88a9230..d098d98 160000 --- a/programs/netutils +++ b/programs/netutils @@ -1 +1 @@ -Subproject commit 88a923087a3a9cbbad0bf8faea9cb56332269c57 +Subproject commit d098d9857177e06762bd1a42bc8d15842822cd37 From 2998dc5bdace23ca188d01670be5792890ca40f0 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 4 Jan 2017 15:27:21 -0700 Subject: [PATCH 041/522] Update orbutils --- programs/orbutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/orbutils b/programs/orbutils index 196fc91..abd1fe5 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 196fc91bb03e5cfa1bb46fb8e59a720caf995ef8 +Subproject commit abd1fe55e92143668a973b99dc5031b2d8c7ab92 From db61470278fa2f1db2629b466a2d0d8e3e6b4215 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 4 Jan 2017 15:42:07 -0700 Subject: [PATCH 042/522] Move kernel to submodule --- .gitmodules | 3 + kernel | 1 + kernel/Cargo.toml | 37 - kernel/README.md | 69 -- kernel/arch/arm/Cargo.toml | 8 - kernel/arch/arm/src/context.rs | 9 - kernel/arch/arm/src/externs.rs | 70 -- kernel/arch/arm/src/interrupt.rs | 30 - kernel/arch/arm/src/lib.rs | 39 - kernel/arch/arm/src/linker.ld | 60 -- kernel/arch/arm/src/panic.rs | 38 - kernel/arch/arm/src/start.rs | 27 - kernel/arch/test/Cargo.toml | 3 - kernel/arch/test/src/interrupt.rs | 43 - kernel/arch/test/src/lib.rs | 43 - kernel/arch/test/src/main.rs | 11 - kernel/arch/test/src/time.rs | 7 - kernel/arch/x86_64/Cargo.toml | 15 - kernel/arch/x86_64/src/acpi/dmar/drhd.rs | 77 -- kernel/arch/x86_64/src/acpi/dmar/mod.rs | 183 ---- kernel/arch/x86_64/src/acpi/fadt.rs | 96 -- kernel/arch/x86_64/src/acpi/madt.rs | 133 --- kernel/arch/x86_64/src/acpi/mod.rs | 284 ------ kernel/arch/x86_64/src/acpi/rsdt.rs | 41 - kernel/arch/x86_64/src/acpi/sdt.rs | 33 - kernel/arch/x86_64/src/acpi/xsdt.rs | 41 - kernel/arch/x86_64/src/console.rs | 14 - kernel/arch/x86_64/src/context.rs | 184 ---- kernel/arch/x86_64/src/device/cpu.rs | 126 --- kernel/arch/x86_64/src/device/local_apic.rs | 115 --- kernel/arch/x86_64/src/device/mod.rs | 16 - kernel/arch/x86_64/src/device/rtc.rs | 109 -- kernel/arch/x86_64/src/device/serial.rs | 115 --- kernel/arch/x86_64/src/externs.rs | 70 -- kernel/arch/x86_64/src/gdt.rs | 177 ---- kernel/arch/x86_64/src/idt.rs | 142 --- kernel/arch/x86_64/src/interrupt/exception.rs | 123 --- kernel/arch/x86_64/src/interrupt/ipi.rs | 5 - kernel/arch/x86_64/src/interrupt/irq.rs | 115 --- kernel/arch/x86_64/src/interrupt/mod.rs | 85 -- kernel/arch/x86_64/src/interrupt/syscall.rs | 61 -- kernel/arch/x86_64/src/lib.rs | 327 ------ kernel/arch/x86_64/src/linker.ld | 63 -- .../x86_64/src/memory/area_frame_allocator.rs | 127 --- kernel/arch/x86_64/src/memory/mod.rs | 189 ---- kernel/arch/x86_64/src/paging/entry.rs | 62 -- kernel/arch/x86_64/src/paging/mapper.rs | 182 ---- kernel/arch/x86_64/src/paging/mod.rs | 429 -------- kernel/arch/x86_64/src/paging/table.rs | 98 -- .../arch/x86_64/src/paging/temporary_page.rs | 45 - kernel/arch/x86_64/src/panic.rs | 32 - kernel/arch/x86_64/src/start.rs | 189 ---- kernel/arch/x86_64/src/stop.rs | 23 - kernel/arch/x86_64/src/time.rs | 15 - kernel/src/common/int_like.rs | 108 -- kernel/src/common/mod.rs | 2 - kernel/src/context/context.rs | 252 ----- kernel/src/context/event.rs | 112 -- kernel/src/context/file.rs | 15 - kernel/src/context/list.rs | 91 -- kernel/src/context/memory.rs | 327 ------ kernel/src/context/mod.rs | 75 -- kernel/src/context/switch.rs | 115 --- kernel/src/elf.rs | 73 -- kernel/src/lib.rs | 180 ---- kernel/src/scheme/debug.rs | 75 -- kernel/src/scheme/env.rs | 193 ---- kernel/src/scheme/event.rs | 74 -- kernel/src/scheme/initfs.rs | 154 --- kernel/src/scheme/irq.rs | 101 -- kernel/src/scheme/live.rs | 160 --- kernel/src/scheme/memory.rs | 30 - kernel/src/scheme/mod.rs | 246 ----- kernel/src/scheme/null.rs | 37 - kernel/src/scheme/pipe.rs | 272 ----- kernel/src/scheme/root.rs | 116 --- kernel/src/scheme/sys/context.rs | 106 -- kernel/src/scheme/sys/cpu.rs | 13 - kernel/src/scheme/sys/exe.rs | 16 - kernel/src/scheme/sys/mod.rs | 183 ---- kernel/src/scheme/sys/scheme.rs | 24 - kernel/src/scheme/user.rs | 354 ------- kernel/src/scheme/zero.rs | 42 - kernel/src/sync/mod.rs | 7 - kernel/src/sync/wait_condition.rs | 48 - kernel/src/sync/wait_map.rs | 62 -- kernel/src/sync/wait_queue.rs | 82 -- kernel/src/syscall/driver.rs | 130 --- kernel/src/syscall/fs.rs | 356 ------- kernel/src/syscall/futex.rs | 110 -- kernel/src/syscall/mod.rs | 121 --- kernel/src/syscall/privilege.rs | 147 --- kernel/src/syscall/process.rs | 965 ------------------ kernel/src/syscall/time.rs | 53 - kernel/src/syscall/validate.rs | 44 - kernel/src/tests/mod.rs | 29 - 96 files changed, 4 insertions(+), 10335 deletions(-) create mode 160000 kernel delete mode 100644 kernel/Cargo.toml delete mode 100644 kernel/README.md delete mode 100644 kernel/arch/arm/Cargo.toml delete mode 100644 kernel/arch/arm/src/context.rs delete mode 100644 kernel/arch/arm/src/externs.rs delete mode 100644 kernel/arch/arm/src/interrupt.rs delete mode 100644 kernel/arch/arm/src/lib.rs delete mode 100644 kernel/arch/arm/src/linker.ld delete mode 100644 kernel/arch/arm/src/panic.rs delete mode 100644 kernel/arch/arm/src/start.rs delete mode 100644 kernel/arch/test/Cargo.toml delete mode 100644 kernel/arch/test/src/interrupt.rs delete mode 100644 kernel/arch/test/src/lib.rs delete mode 100644 kernel/arch/test/src/main.rs delete mode 100644 kernel/arch/test/src/time.rs delete mode 100644 kernel/arch/x86_64/Cargo.toml delete mode 100644 kernel/arch/x86_64/src/acpi/dmar/drhd.rs delete mode 100644 kernel/arch/x86_64/src/acpi/dmar/mod.rs delete mode 100644 kernel/arch/x86_64/src/acpi/fadt.rs delete mode 100644 kernel/arch/x86_64/src/acpi/madt.rs delete mode 100644 kernel/arch/x86_64/src/acpi/mod.rs delete mode 100644 kernel/arch/x86_64/src/acpi/rsdt.rs delete mode 100644 kernel/arch/x86_64/src/acpi/sdt.rs delete mode 100644 kernel/arch/x86_64/src/acpi/xsdt.rs delete mode 100644 kernel/arch/x86_64/src/console.rs delete mode 100644 kernel/arch/x86_64/src/context.rs delete mode 100644 kernel/arch/x86_64/src/device/cpu.rs delete mode 100644 kernel/arch/x86_64/src/device/local_apic.rs delete mode 100644 kernel/arch/x86_64/src/device/mod.rs delete mode 100644 kernel/arch/x86_64/src/device/rtc.rs delete mode 100644 kernel/arch/x86_64/src/device/serial.rs delete mode 100644 kernel/arch/x86_64/src/externs.rs delete mode 100644 kernel/arch/x86_64/src/gdt.rs delete mode 100644 kernel/arch/x86_64/src/idt.rs delete mode 100644 kernel/arch/x86_64/src/interrupt/exception.rs delete mode 100644 kernel/arch/x86_64/src/interrupt/ipi.rs delete mode 100644 kernel/arch/x86_64/src/interrupt/irq.rs delete mode 100644 kernel/arch/x86_64/src/interrupt/mod.rs delete mode 100644 kernel/arch/x86_64/src/interrupt/syscall.rs delete mode 100644 kernel/arch/x86_64/src/lib.rs delete mode 100644 kernel/arch/x86_64/src/linker.ld delete mode 100644 kernel/arch/x86_64/src/memory/area_frame_allocator.rs delete mode 100644 kernel/arch/x86_64/src/memory/mod.rs delete mode 100644 kernel/arch/x86_64/src/paging/entry.rs delete mode 100644 kernel/arch/x86_64/src/paging/mapper.rs delete mode 100644 kernel/arch/x86_64/src/paging/mod.rs delete mode 100644 kernel/arch/x86_64/src/paging/table.rs delete mode 100644 kernel/arch/x86_64/src/paging/temporary_page.rs delete mode 100644 kernel/arch/x86_64/src/panic.rs delete mode 100644 kernel/arch/x86_64/src/start.rs delete mode 100644 kernel/arch/x86_64/src/stop.rs delete mode 100644 kernel/arch/x86_64/src/time.rs delete mode 100644 kernel/src/common/int_like.rs delete mode 100644 kernel/src/common/mod.rs delete mode 100644 kernel/src/context/context.rs delete mode 100644 kernel/src/context/event.rs delete mode 100644 kernel/src/context/file.rs delete mode 100644 kernel/src/context/list.rs delete mode 100644 kernel/src/context/memory.rs delete mode 100644 kernel/src/context/mod.rs delete mode 100644 kernel/src/context/switch.rs delete mode 100644 kernel/src/elf.rs delete mode 100644 kernel/src/lib.rs delete mode 100644 kernel/src/scheme/debug.rs delete mode 100644 kernel/src/scheme/env.rs delete mode 100644 kernel/src/scheme/event.rs delete mode 100644 kernel/src/scheme/initfs.rs delete mode 100644 kernel/src/scheme/irq.rs delete mode 100644 kernel/src/scheme/live.rs delete mode 100644 kernel/src/scheme/memory.rs delete mode 100644 kernel/src/scheme/mod.rs delete mode 100644 kernel/src/scheme/null.rs delete mode 100644 kernel/src/scheme/pipe.rs delete mode 100644 kernel/src/scheme/root.rs delete mode 100644 kernel/src/scheme/sys/context.rs delete mode 100644 kernel/src/scheme/sys/cpu.rs delete mode 100644 kernel/src/scheme/sys/exe.rs delete mode 100644 kernel/src/scheme/sys/mod.rs delete mode 100644 kernel/src/scheme/sys/scheme.rs delete mode 100644 kernel/src/scheme/user.rs delete mode 100644 kernel/src/scheme/zero.rs delete mode 100644 kernel/src/sync/mod.rs delete mode 100644 kernel/src/sync/wait_condition.rs delete mode 100644 kernel/src/sync/wait_map.rs delete mode 100644 kernel/src/sync/wait_queue.rs delete mode 100644 kernel/src/syscall/driver.rs delete mode 100644 kernel/src/syscall/fs.rs delete mode 100644 kernel/src/syscall/futex.rs delete mode 100644 kernel/src/syscall/mod.rs delete mode 100644 kernel/src/syscall/privilege.rs delete mode 100644 kernel/src/syscall/process.rs delete mode 100644 kernel/src/syscall/time.rs delete mode 100644 kernel/src/syscall/validate.rs delete mode 100644 kernel/src/tests/mod.rs diff --git a/.gitmodules b/.gitmodules index 7c83399..02f5947 100644 --- a/.gitmodules +++ b/.gitmodules @@ -58,3 +58,6 @@ [submodule "programs/games"] path = programs/games url = https://github.com/redox-os/games.git +[submodule "kernel"] + path = kernel + url = https://github.com/redox-os/kernel.git diff --git a/kernel b/kernel new file mode 160000 index 0000000..0c8ba63 --- /dev/null +++ b/kernel @@ -0,0 +1 @@ +Subproject commit 0c8ba636f4263665dae1b0fdd0a040e4e0c724f5 diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml deleted file mode 100644 index 8fd747e..0000000 --- a/kernel/Cargo.toml +++ /dev/null @@ -1,37 +0,0 @@ -[package] -name = "kernel" -version = "0.1.0" - -[lib] -name = "kernel" -path = "src/lib.rs" -crate-type = ["staticlib"] - -[dependencies] -bitflags = "*" -spin = "*" -redox_syscall = { path = "../syscall/" } - -[dependencies.goblin] -git = "https://github.com/m4b/goblin.git" -default-features = false -features = ["elf32", "elf64"] - -[dev-dependencies] -arch_test = { path = "arch/test" } - -[target.'cfg(target_arch = "arm")'.dependencies] -arch_arm = { path = "arch/arm" } - -[target.'cfg(target_arch = "x86_64")'.dependencies] -arch_x86_64 = { path = "arch/x86_64" } - -[features] -default = [] -live = [] - -[profile.dev] -panic = "unwind" - -[profile.release] -panic = "abort" diff --git a/kernel/README.md b/kernel/README.md deleted file mode 100644 index e9c8a98..0000000 --- a/kernel/README.md +++ /dev/null @@ -1,69 +0,0 @@ -# kernel - -A collaborative effort to rewrite the kernel with focus on correctness and code -quality. - -## Why? - -The kernel code was getting increasingly messy to the point where only the -original writer would be able to find and fix bugs. Fortunately, the kernel of -Redox is relatively small and such a project is estimated to take only a few -months. - -## What? - -The aims of the new kernel should be clear in their order: - -1. **Correctness**: Above anything else, the kernel should be correct. No hacks, -despite how the tiny cool shortcuts might seem, it gives severe backslash later -on. Keep it correct and well-written. - -2. **Readability and documentation**: The code quality should be high, with that -follows a detailed documentation, including both API docs (on every item!) and -careful comments for anything non-trivial. - -3. **Performance**: If you can, go for it. - -## Guidelines - -### A rotten house is built on a rotten fundament. - -Don't fool yourself. You are likely not getting back to the ugly code. Write it -the right way **first time**, and make sure you only move on when it's -**done right**. - -### Comments - -Do not hesitate to put comments all over the place. - -### Documentation - -Every public item should contain API documentation. - -### Debug assertions - -Abusing debug assertions is a wonderful way to catch bugs, and it is very much -encouraged. - -### Statical checking - -Rust provides a lot of type-system features which can be used to create -wonderful safe abstractions, and you should use them whenever you get the chance. - -Unsafety should be avoided, and if it is triggered only under some addition -**insert an assertion**. Despite this being a kernel, we prefer kernel panics -over security vulnerabilities. - -If the condition is (or should be) unreachable, but if not upheld, leading to -UB, put an assertion in the start of the function. - -### Be gentle - -Don't just write as much code as you can as quick as possible. Take your time -and be careful. - -### Commits - -Use descriptive commits. One way to force yourself to do that is to not pass the -`-m` flag, which will make your editor pop up, so that you can conviniently -write long commit messages. diff --git a/kernel/arch/arm/Cargo.toml b/kernel/arch/arm/Cargo.toml deleted file mode 100644 index d477d18..0000000 --- a/kernel/arch/arm/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "arch_arm" -version = "0.1.0" - -[dependencies] -bitflags = "*" -hole_list_allocator = { path = "../../../crates/hole_list_allocator"} -spin = "*" diff --git a/kernel/arch/arm/src/context.rs b/kernel/arch/arm/src/context.rs deleted file mode 100644 index db711c3..0000000 --- a/kernel/arch/arm/src/context.rs +++ /dev/null @@ -1,9 +0,0 @@ -#[derive(Debug)] -pub struct Context; - -impl Context { - pub fn new() -> Self { - Context - } -} - diff --git a/kernel/arch/arm/src/externs.rs b/kernel/arch/arm/src/externs.rs deleted file mode 100644 index 3b87427..0000000 --- a/kernel/arch/arm/src/externs.rs +++ /dev/null @@ -1,70 +0,0 @@ -/// 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/arch/arm/src/interrupt.rs b/kernel/arch/arm/src/interrupt.rs deleted file mode 100644 index 6d7d460..0000000 --- a/kernel/arch/arm/src/interrupt.rs +++ /dev/null @@ -1,30 +0,0 @@ -//! Interrupt instructions - -/// Clear interrupts -#[inline(always)] -pub unsafe fn disable() { -} - -/// Set interrupts -#[inline(always)] -pub unsafe fn enable() { -} - -/// Set interrupts and halt -#[inline(always)] -pub unsafe fn enable_and_halt() { - halt(); -} - -/// Halt instruction -#[inline(always)] -pub unsafe fn halt() { - //asm!("wfi" : : : : "volatile"); - asm!("nop" : : : : "volatile"); -} - -/// Get a stack trace -//TODO: Check for stack being mapped before dereferencing -#[inline(never)] -pub unsafe fn stack_trace() { -} diff --git a/kernel/arch/arm/src/lib.rs b/kernel/arch/arm/src/lib.rs deleted file mode 100644 index 77b0e9c..0000000 --- a/kernel/arch/arm/src/lib.rs +++ /dev/null @@ -1,39 +0,0 @@ -//! Architecture support for ARM - -#![feature(asm)] -#![feature(lang_items)] -#![feature(naked_functions)] -#![no_std] - -extern crate hole_list_allocator as allocator; -#[macro_use] -extern crate bitflags; -extern crate spin; - -/// Print to console -#[macro_export] -macro_rules! print { - ($($arg:tt)*) => ({}); -} - -/// Print with new line to console -#[macro_export] -macro_rules! println { - ($fmt:expr) => (print!(concat!($fmt, "\n"))); - ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); -} - -/// Context switching -pub mod context; - -/// Memset, memcpy, etc. -pub mod externs; - -/// Interrupt handling -pub mod interrupt; - -/// Panic support -pub mod panic; - -/// Initialization function -pub mod start; diff --git a/kernel/arch/arm/src/linker.ld b/kernel/arch/arm/src/linker.ld deleted file mode 100644 index 71fd23e..0000000 --- a/kernel/arch/arm/src/linker.ld +++ /dev/null @@ -1,60 +0,0 @@ -ENTRY(kstart) -OUTPUT_ARCH(arm) -OUTPUT_FORMAT(elf32-littlearm) - -KERNEL_OFFSET = 0; - -SECTIONS { - . = KERNEL_OFFSET; - - .text : AT(ADDR(.text) - KERNEL_OFFSET) { - __text_start = .; - *(.text*) - . = ALIGN(4096); - __text_end = .; - } - - .rodata : AT(ADDR(.rodata) - KERNEL_OFFSET) { - __rodata_start = .; - *(.rodata*) - . = ALIGN(4096); - __rodata_end = .; - } - - .data : AT(ADDR(.data) - KERNEL_OFFSET) { - __data_start = .; - *(.data*) - . = ALIGN(4096); - __data_end = .; - } - - .tdata : AT(ADDR(.tdata) - KERNEL_OFFSET) { - __tdata_start = .; - *(.tdata*) - . = ALIGN(4096); - __tdata_end = .; - __tbss_start = .; - *(.tbss*) - . += 8; - . = ALIGN(4096); - __tbss_end = .; - } - - .bss : AT(ADDR(.bss) - KERNEL_OFFSET) { - __bss_start = .; - *(.bss*) - . = ALIGN(4096); - __bss_end = .; - } - - __end = .; - - /DISCARD/ : { - *(.comment*) - *(.debug*) - *(.eh_frame*) - *(.gcc_except_table*) - *(.note*) - *(.rel.eh_frame*) - } -} diff --git a/kernel/arch/arm/src/panic.rs b/kernel/arch/arm/src/panic.rs deleted file mode 100644 index 2acb38e..0000000 --- a/kernel/arch/arm/src/panic.rs +++ /dev/null @@ -1,38 +0,0 @@ -//! Intrinsics for panic handling - -use interrupt; - -#[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) -> ! { - println!("PANIC: {}", fmt); - println!("FILE: {}", file); - println!("LINE: {}", line); - - unsafe { interrupt::stack_trace(); } - - println!("HALT"); - loop { - unsafe { interrupt::halt(); } - } -} - -#[allow(non_snake_case)] -#[no_mangle] -/// Required to handle panics -pub extern "C" fn _Unwind_Resume() -> ! { - loop { - unsafe { interrupt::halt(); } - } -} - -/// Required for linker -#[no_mangle] -pub extern "C" fn __aeabi_unwind_cpp_pr0() { - loop {} -} diff --git a/kernel/arch/arm/src/start.rs b/kernel/arch/arm/src/start.rs deleted file mode 100644 index b9abbe6..0000000 --- a/kernel/arch/arm/src/start.rs +++ /dev/null @@ -1,27 +0,0 @@ -const SERIAL_BASE: *mut u8 = 0x16000000 as *mut u8; -const SERIAL_FLAG_REGISTER: *const u8 = 0x16000018 as *const u8; -const SERIAL_BUFFER_FULL: u8 = (1 << 5); - -unsafe fn putc (c: u8) -{ - /* Wait until the serial buffer is empty */ - while *SERIAL_FLAG_REGISTER & SERIAL_BUFFER_FULL == SERIAL_BUFFER_FULL {} - - /* Put our character, c, into the serial buffer */ - *SERIAL_BASE = c; -} - -unsafe fn puts(string: &str) -{ - for b in string.bytes() { - putc(b); - } -} - -#[no_mangle] -#[naked] -pub unsafe extern fn kstart() -> ! { - asm!("mov sp, 0x18000" : : : : "volatile"); - puts("TEST\r\n"); - loop {} -} diff --git a/kernel/arch/test/Cargo.toml b/kernel/arch/test/Cargo.toml deleted file mode 100644 index 1900c7d..0000000 --- a/kernel/arch/test/Cargo.toml +++ /dev/null @@ -1,3 +0,0 @@ -[package] -name = "arch_test" -version = "0.1.0" diff --git a/kernel/arch/test/src/interrupt.rs b/kernel/arch/test/src/interrupt.rs deleted file mode 100644 index 9e49020..0000000 --- a/kernel/arch/test/src/interrupt.rs +++ /dev/null @@ -1,43 +0,0 @@ -//! Interrupt instructions - -static mut INTERRUPTS_ENABLED: bool = false; - -/// Clear interrupts -#[inline(always)] -pub unsafe fn disable() { - println!("CLEAR INTERRUPTS"); - INTERRUPTS_ENABLED = false; -} - -/// Set interrupts -#[inline(always)] -pub unsafe fn enable() { - println!("SET INTERRUPTS"); - INTERRUPTS_ENABLED = true; -} - -/// Halt instruction -#[inline(always)] -pub unsafe fn halt() { - assert!(INTERRUPTS_ENABLED); - ::std::thread::yield_now(); -} - -/// Pause instruction -#[inline(always)] -pub unsafe fn pause() { - -} - -/// Set interrupts and nop -#[inline(always)] -pub unsafe fn enable_and_nop() { - enable(); -} - -/// Set interrupts and halt -#[inline(always)] -pub unsafe fn enable_and_halt() { - enable(); - halt(); -} diff --git a/kernel/arch/test/src/lib.rs b/kernel/arch/test/src/lib.rs deleted file mode 100644 index 8a155cd..0000000 --- a/kernel/arch/test/src/lib.rs +++ /dev/null @@ -1,43 +0,0 @@ -//! Architecture support for testing - -pub use std::io; - -/// Print to console -#[macro_export] -macro_rules! print { - ($($arg:tt)*) => ({ - use $crate::io::Write; - let _ = write!($crate::io::stdout(), $($arg)*); - }); -} - -/// Print with new line to console -#[macro_export] -macro_rules! println { - ($fmt:expr) => (print!(concat!($fmt, "\n"))); - ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); -} - -/// Create an interrupt function that can safely run rust code -#[macro_export] -macro_rules! interrupt { - ($name:ident, $func:block) => { - pub unsafe extern fn $name () { - unsafe fn inner() { - $func - } - - // Call inner rust function - inner(); - } - }; -} - -/// Interrupt instructions -pub mod interrupt; - -/// Initialization and main function -pub mod main; - -/// Time functions -pub mod time; diff --git a/kernel/arch/test/src/main.rs b/kernel/arch/test/src/main.rs deleted file mode 100644 index 3f93ffb..0000000 --- a/kernel/arch/test/src/main.rs +++ /dev/null @@ -1,11 +0,0 @@ -/// This function is where the kernel sets up IRQ handlers -/// It is increcibly unsafe, and should be minimal in nature - -extern { - fn kmain() -> !; -} - -#[no_mangle] -pub unsafe extern fn kstart() -> ! { - kmain(); -} diff --git a/kernel/arch/test/src/time.rs b/kernel/arch/test/src/time.rs deleted file mode 100644 index 6f7889d..0000000 --- a/kernel/arch/test/src/time.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub fn monotonic() -> (u64, u64) { - (0, 0) -} - -pub fn realtime() -> (u64, u64) { - (0, 0) -} diff --git a/kernel/arch/x86_64/Cargo.toml b/kernel/arch/x86_64/Cargo.toml deleted file mode 100644 index a255e4d..0000000 --- a/kernel/arch/x86_64/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "arch_x86_64" -version = "0.1.0" - -[dependencies] -bitflags = "*" -hole_list_allocator = { path = "../../../crates/hole_list_allocator/" } -io = { path = "../../../crates/io/" } -raw-cpuid = { git = "https://github.com/gz/rust-cpuid" } -spin = "*" -redox_syscall = { path = "../../../syscall/" } - -[dependencies.x86] -version = "0.7" -default-features = false diff --git a/kernel/arch/x86_64/src/acpi/dmar/drhd.rs b/kernel/arch/x86_64/src/acpi/dmar/drhd.rs deleted file mode 100644 index 494917e..0000000 --- a/kernel/arch/x86_64/src/acpi/dmar/drhd.rs +++ /dev/null @@ -1,77 +0,0 @@ -#[repr(packed)] -pub struct DrhdFault { - pub sts: u32, - pub ctrl: u32, - pub data: u32, - pub addr: [u32; 2], - _rsv: [u64; 2], - pub log: u64, -} - -#[repr(packed)] -pub struct DrhdProtectedMemory { - pub en: u32, - pub low_base: u32, - pub low_limit: u32, - pub high_base: u64, - pub high_limit: u64, -} - -#[repr(packed)] -pub struct DrhdInvalidation { - pub queue_head: u64, - pub queue_tail: u64, - pub queue_addr: u64, - _rsv: u32, - pub cmpl_sts: u32, - pub cmpl_ctrl: u32, - pub cmpl_data: u32, - pub cmpl_addr: [u32; 2], -} - -#[repr(packed)] -pub struct DrhdPageRequest { - pub queue_head: u64, - pub queue_tail: u64, - pub queue_addr: u64, - _rsv: u32, - pub sts: u32, - pub ctrl: u32, - pub data: u32, - pub addr: [u32; 2], -} - -#[repr(packed)] -pub struct DrhdMtrrVariable { - pub base: u64, - pub mask: u64, -} - -#[repr(packed)] -pub struct DrhdMtrr { - pub cap: u64, - pub def_type: u64, - pub fixed: [u64; 11], - pub variable: [DrhdMtrrVariable; 10], -} - -#[repr(packed)] -pub struct Drhd { - pub version: u32, - _rsv: u32, - pub cap: u64, - pub ext_cap: u64, - pub gl_cmd: u32, - pub gl_sts: u32, - pub root_table: u64, - pub ctx_cmd: u64, - _rsv1: u32, - pub fault: DrhdFault, - _rsv2: u32, - pub pm: DrhdProtectedMemory, - pub invl: DrhdInvalidation, - _rsv3: u64, - pub intr_table: u64, - pub page_req: DrhdPageRequest, - pub mtrr: DrhdMtrr, -} diff --git a/kernel/arch/x86_64/src/acpi/dmar/mod.rs b/kernel/arch/x86_64/src/acpi/dmar/mod.rs deleted file mode 100644 index 02aac83..0000000 --- a/kernel/arch/x86_64/src/acpi/dmar/mod.rs +++ /dev/null @@ -1,183 +0,0 @@ -use core::mem; - -use super::sdt::Sdt; -use self::drhd::Drhd; -use memory::Frame; -use paging::{entry, ActivePageTable, PhysicalAddress}; - -pub mod drhd; - -/// The DMA Remapping Table -#[derive(Debug)] -pub struct Dmar { - sdt: &'static Sdt, - pub addr_width: u8, - pub flags: u8, - _rsv: [u8; 10], -} - -impl Dmar { - pub fn new(sdt: &'static Sdt) -> Option { - if &sdt.signature == b"DMAR" && sdt.data_len() >= 12 { //Not valid if no local address and flags - let addr_width = unsafe { *(sdt.data_address() as *const u8) }; - let flags = unsafe { *(sdt.data_address() as *const u8).offset(1) }; - let rsv: [u8; 10] = unsafe { *((sdt.data_address() as *const u8).offset(2) as *const [u8; 10]) }; - - Some(Dmar { - sdt: sdt, - addr_width: addr_width, - flags: flags, - _rsv: rsv, - }) - } else { - None - } - } - - pub fn iter(&self) -> DmarIter { - DmarIter { - sdt: self.sdt, - i: 12 // Skip address width and flags - } - } -} - -/// - -/// DMAR DMA Remapping Hardware Unit Definition -// TODO: Implement iterator on DmarDrhd scope -#[derive(Debug)] -#[repr(packed)] -pub struct DmarDrhd { - kind: u16, - length: u16, - flags: u8, - _rsv: u8, - segment: u16, - base: u64, -} - -impl DmarDrhd { - pub fn get(&self, active_table: &mut ActivePageTable) -> &'static mut Drhd { - let result = active_table.identity_map(Frame::containing_address(PhysicalAddress::new(self.base as usize)), entry::PRESENT | entry::WRITABLE | entry::NO_EXECUTE); - result.flush(active_table); - unsafe { &mut *(self.base as *mut Drhd) } - } -} - -/// DMAR Reserved Memory Region Reporting -// TODO: Implement iterator on DmarRmrr scope -#[derive(Debug)] -#[repr(packed)] -pub struct DmarRmrr { - kind: u16, - length: u16, - _rsv: u16, - segment: u16, - base: u64, - limit: u64, -} - -/// DMAR Root Port ATS Capability Reporting -// TODO: Implement iterator on DmarAtsr scope -#[derive(Debug)] -#[repr(packed)] -pub struct DmarAtsr { - kind: u16, - length: u16, - flags: u8, - _rsv: u8, - segment: u16, -} - -/// DMAR Remapping Hardware Static Affinity -#[derive(Debug)] -#[repr(packed)] -pub struct DmarRhsa { - kind: u16, - length: u16, - _rsv: u32, - base: u64, - domain: u32, -} - -/// DMAR ACPI Name-space Device Declaration -// TODO: Implement iterator on DmarAndd object name -#[derive(Debug)] -#[repr(packed)] -pub struct DmarAndd { - kind: u16, - length: u16, - _rsv: [u8; 3], - acpi_dev: u8, -} - -/// DMAR Entries -#[derive(Debug)] -pub enum DmarEntry { - Drhd(&'static DmarDrhd), - InvalidDrhd(usize), - Rmrr(&'static DmarRmrr), - InvalidRmrr(usize), - Atsr(&'static DmarAtsr), - InvalidAtsr(usize), - Rhsa(&'static DmarRhsa), - InvalidRhsa(usize), - Andd(&'static DmarAndd), - InvalidAndd(usize), - Unknown(u16) -} - -pub struct DmarIter { - sdt: &'static Sdt, - i: usize -} - -impl Iterator for DmarIter { - type Item = DmarEntry; - fn next(&mut self) -> Option { - if self.i + 4 <= self.sdt.data_len() { - let entry_type = unsafe { *((self.sdt.data_address() as *const u8).offset(self.i as isize) as *const u16) }; - let entry_len = unsafe { *((self.sdt.data_address() as *const u8).offset(self.i as isize + 2) as *const u16) } as usize; - - if self.i + entry_len <= self.sdt.data_len() { - let item = match entry_type { - 0 => if entry_len >= mem::size_of::() { - DmarEntry::Drhd(unsafe { &*((self.sdt.data_address() + self.i) as *const DmarDrhd) }) - } else { - DmarEntry::InvalidDrhd(entry_len) - }, - 1 => if entry_len >= mem::size_of::() { - DmarEntry::Rmrr(unsafe { &*((self.sdt.data_address() + self.i) as *const DmarRmrr) }) - } else { - DmarEntry::InvalidRmrr(entry_len) - }, - 2 => if entry_len >= mem::size_of::() { - DmarEntry::Atsr(unsafe { &*((self.sdt.data_address() + self.i) as *const DmarAtsr) }) - } else { - DmarEntry::InvalidAtsr(entry_len) - }, - 3 => if entry_len == mem::size_of::() { - DmarEntry::Rhsa(unsafe { &*((self.sdt.data_address() + self.i) as *const DmarRhsa) }) - } else { - DmarEntry::InvalidRhsa(entry_len) - }, - 4 => if entry_len >= mem::size_of::() { - DmarEntry::Andd(unsafe { &*((self.sdt.data_address() + self.i) as *const DmarAndd) }) - } else { - DmarEntry::InvalidAndd(entry_len) - }, - _ => DmarEntry::Unknown(entry_type) - }; - - self.i += entry_len; - - Some(item) - } else { - None - } - } else { - None - } - } -} diff --git a/kernel/arch/x86_64/src/acpi/fadt.rs b/kernel/arch/x86_64/src/acpi/fadt.rs deleted file mode 100644 index d40d5a1..0000000 --- a/kernel/arch/x86_64/src/acpi/fadt.rs +++ /dev/null @@ -1,96 +0,0 @@ -use core::{mem, ptr}; - -use super::sdt::Sdt; - -#[repr(packed)] -#[derive(Debug)] -pub struct Fadt { - pub header: Sdt, - pub firmware_ctrl: u32, - pub dsdt: u32, - - // field used in ACPI 1.0; no longer in use, for compatibility only - reserved: u8, - - pub preferred_power_managament: u8, - pub sci_interrupt: u16, - pub smi_command_port: u32, - pub acpi_enable: u8, - pub acpi_disable: u8, - pub s4_bios_req: u8, - pub pstate_control: u8, - pub pm1a_event_block: u32, - pub pm1b_event_block: u32, - pub pm1a_control_block: u32, - pub pm1b_control_block: u32, - pub pm2_control_block: u32, - pub pm_timer_block: u32, - pub gpe0_block: u32, - pub gpe1_block: u32, - pub pm1_event_length: u8, - pub pm1_control_length: u8, - pub pm2_control_length: u8, - pub pm_timer_length: u8, - pub gpe0_ength: u8, - pub gpe1_length: u8, - pub gpe1_base: u8, - pub c_state_control: u8, - pub worst_c2_latency: u16, - pub worst_c3_latency: u16, - pub flush_size: u16, - pub flush_stride: u16, - pub duty_offset: u8, - pub duty_width: u8, - pub day_alarm: u8, - pub month_alarm: u8, - pub century: u8, - - // reserved in ACPI 1.0; used since ACPI 2.0+ - pub boot_architecture_flags: u16, - - reserved2: u8, - pub flags: u32, -} - -/* ACPI 2 structure -#[repr(packed)] -#[derive(Clone, Copy, Debug, Default)] -pub struct GenericAddressStructure { - address_space: u8, - bit_width: u8, - bit_offset: u8, - access_size: u8, - address: u64, -} - -{ - // 12 byte structure; see below for details - pub reset_reg: GenericAddressStructure, - - pub reset_value: u8, - reserved3: [u8; 3], - - // 64bit pointers - Available on ACPI 2.0+ - pub x_firmware_control: u64, - pub x_dsdt: u64, - - pub x_pm1a_event_block: GenericAddressStructure, - pub x_pm1b_event_block: GenericAddressStructure, - pub x_pm1a_control_block: GenericAddressStructure, - pub x_pm1b_control_block: GenericAddressStructure, - pub x_pm2_control_block: GenericAddressStructure, - pub x_pm_timer_block: GenericAddressStructure, - pub x_gpe0_block: GenericAddressStructure, - pub x_gpe1_block: GenericAddressStructure, -} -*/ - -impl Fadt { - pub fn new(sdt: &'static Sdt) -> Option { - if &sdt.signature == b"FACP" && sdt.length as usize >= mem::size_of::() { - Some(unsafe { ptr::read((sdt as *const Sdt) as *const Fadt) }) - } else { - None - } - } -} diff --git a/kernel/arch/x86_64/src/acpi/madt.rs b/kernel/arch/x86_64/src/acpi/madt.rs deleted file mode 100644 index dac16dc..0000000 --- a/kernel/arch/x86_64/src/acpi/madt.rs +++ /dev/null @@ -1,133 +0,0 @@ -use core::mem; - -use super::sdt::Sdt; - -/// The Multiple APIC Descriptor Table -#[derive(Debug)] -pub struct Madt { - sdt: &'static Sdt, - pub local_address: u32, - pub flags: u32 -} - -impl Madt { - pub fn new(sdt: &'static Sdt) -> Option { - if &sdt.signature == b"APIC" && sdt.data_len() >= 8 { //Not valid if no local address and flags - let local_address = unsafe { *(sdt.data_address() as *const u32) }; - let flags = unsafe { *(sdt.data_address() as *const u32).offset(1) }; - - Some(Madt { - sdt: sdt, - local_address: local_address, - flags: flags - }) - } else { - None - } - } - - pub fn iter(&self) -> MadtIter { - MadtIter { - sdt: self.sdt, - i: 8 // Skip local controller address and flags - } - } -} - -/// - -/// MADT Local APIC -#[derive(Debug)] -#[repr(packed)] -pub struct MadtLocalApic { - /// Processor ID - pub processor: u8, - /// Local APIC ID - pub id: u8, - /// Flags. 1 means that the processor is enabled - pub flags: u32 -} - -/// MADT I/O APIC -#[derive(Debug)] -#[repr(packed)] -pub struct MadtIoApic { - /// I/O APIC ID - pub id: u8, - /// reserved - reserved: u8, - /// I/O APIC address - pub address: u32, - /// Global system interrupt base - pub gsi_base: u32 -} - -/// MADT Interrupt Source Override -#[derive(Debug)] -#[repr(packed)] -pub struct MadtIntSrcOverride { - /// Bus Source - pub bus_source: u8, - /// IRQ Source - pub irq_source: u8, - /// Global system interrupt base - pub gsi_base: u32, - /// Flags - pub flags: u16 -} - -/// MADT Entries -#[derive(Debug)] -pub enum MadtEntry { - LocalApic(&'static MadtLocalApic), - InvalidLocalApic(usize), - IoApic(&'static MadtIoApic), - InvalidIoApic(usize), - IntSrcOverride(&'static MadtIntSrcOverride), - InvalidIntSrcOverride(usize), - Unknown(u8) -} - -pub struct MadtIter { - sdt: &'static Sdt, - i: usize -} - -impl Iterator for MadtIter { - type Item = MadtEntry; - fn next(&mut self) -> Option { - if self.i + 1 < self.sdt.data_len() { - let entry_type = unsafe { *(self.sdt.data_address() as *const u8).offset(self.i as isize) }; - let entry_len = unsafe { *(self.sdt.data_address() as *const u8).offset(self.i as isize + 1) } as usize; - - if self.i + entry_len <= self.sdt.data_len() { - let item = match entry_type { - 0 => if entry_len == mem::size_of::() + 2 { - MadtEntry::LocalApic(unsafe { &*((self.sdt.data_address() + self.i + 2) as *const MadtLocalApic) }) - } else { - MadtEntry::InvalidLocalApic(entry_len) - }, - 1 => if entry_len == mem::size_of::() + 2 { - MadtEntry::IoApic(unsafe { &*((self.sdt.data_address() + self.i + 2) as *const MadtIoApic) }) - } else { - MadtEntry::InvalidIoApic(entry_len) - }, - 2 => if entry_len == mem::size_of::() + 2 { - MadtEntry::IntSrcOverride(unsafe { &*((self.sdt.data_address() + self.i + 2) as *const MadtIntSrcOverride) }) - } else { - MadtEntry::InvalidIntSrcOverride(entry_len) - }, - _ => MadtEntry::Unknown(entry_type) - }; - - self.i += entry_len; - - Some(item) - } else { - None - } - } else { - None - } - } -} diff --git a/kernel/arch/x86_64/src/acpi/mod.rs b/kernel/arch/x86_64/src/acpi/mod.rs deleted file mode 100644 index 092f609..0000000 --- a/kernel/arch/x86_64/src/acpi/mod.rs +++ /dev/null @@ -1,284 +0,0 @@ -//! # ACPI -//! Code to parse the ACPI tables - -use core::intrinsics::{atomic_load, atomic_store}; -use core::sync::atomic::Ordering; - -use device::local_apic::LOCAL_APIC; -use interrupt; -use memory::{allocate_frames, Frame}; -use paging::{entry, ActivePageTable, Page, PhysicalAddress, VirtualAddress}; -use start::{kstart_ap, CPU_COUNT, AP_READY}; - -use self::dmar::{Dmar, DmarEntry}; -use self::fadt::Fadt; -use self::madt::{Madt, MadtEntry}; -use self::rsdt::Rsdt; -use self::sdt::Sdt; -use self::xsdt::Xsdt; - -pub mod dmar; -pub mod fadt; -pub mod madt; -pub mod rsdt; -pub mod sdt; -pub mod xsdt; - -const TRAMPOLINE: usize = 0x7E00; -const AP_STARTUP: usize = TRAMPOLINE + 512; - -pub fn init_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) { - print!(" "); - for &c in sdt.signature.iter() { - print!("{}", c as char); - } - - if let Some(fadt) = Fadt::new(sdt) { - println!(": {:#?}", fadt); - } else if let Some(madt) = Madt::new(sdt) { - println!(": {:>08X}: {}", madt.local_address, madt.flags); - - let mut local_apic = unsafe { &mut LOCAL_APIC }; - - let me = local_apic.id() as u8; - - if local_apic.x2 { - println!(" X2APIC {}", me); - } else { - println!(" XAPIC {}: {:>08X}", me, local_apic.address); - } - - let trampoline_frame = Frame::containing_address(PhysicalAddress::new(TRAMPOLINE)); - let trampoline_page = Page::containing_address(VirtualAddress::new(TRAMPOLINE)); - - // Map trampoline - let result = active_table.map_to(trampoline_page, trampoline_frame, entry::PRESENT | entry::WRITABLE); - result.flush(active_table); - - for madt_entry in madt.iter() { - println!(" {:?}", madt_entry); - match madt_entry { - MadtEntry::LocalApic(ap_local_apic) => if ap_local_apic.id == me { - println!(" This is my local APIC"); - } else { - if ap_local_apic.flags & 1 == 1 { - // Increase CPU ID - CPU_COUNT.fetch_add(1, Ordering::SeqCst); - - // Allocate a stack - let stack_start = allocate_frames(64).expect("no more frames in acpi stack_start").start_address().get() + ::KERNEL_OFFSET; - let stack_end = stack_start + 64 * 4096; - - let ap_ready = TRAMPOLINE as *mut u64; - let ap_cpu_id = unsafe { ap_ready.offset(1) }; - let ap_page_table = unsafe { ap_ready.offset(2) }; - let ap_stack_start = unsafe { ap_ready.offset(3) }; - let ap_stack_end = unsafe { ap_ready.offset(4) }; - let ap_code = unsafe { ap_ready.offset(5) }; - - // Set the ap_ready to 0, volatile - unsafe { atomic_store(ap_ready, 0) }; - unsafe { atomic_store(ap_cpu_id, ap_local_apic.id as u64) }; - unsafe { atomic_store(ap_page_table, active_table.address() as u64) }; - unsafe { atomic_store(ap_stack_start, stack_start as u64) }; - unsafe { atomic_store(ap_stack_end, stack_end as u64) }; - unsafe { atomic_store(ap_code, kstart_ap as u64) }; - AP_READY.store(false, Ordering::SeqCst); - - print!(" AP {}:", ap_local_apic.id); - - // Send INIT IPI - { - let mut icr = 0x4500; - if local_apic.x2 { - icr |= (ap_local_apic.id as u64) << 32; - } else { - icr |= (ap_local_apic.id as u64) << 56; - } - print!(" IPI..."); - local_apic.set_icr(icr); - } - - // Send START IPI - { - //Start at 0x0800:0000 => 0x8000. Hopefully the bootloader code is still there - let ap_segment = (AP_STARTUP >> 12) & 0xFF; - let mut icr = 0x4600 | ap_segment as u64; - - if local_apic.x2 { - icr |= (ap_local_apic.id as u64) << 32; - } else { - icr |= (ap_local_apic.id as u64) << 56; - } - - print!(" SIPI..."); - local_apic.set_icr(icr); - } - - // Wait for trampoline ready - print!(" Wait..."); - while unsafe { atomic_load(ap_ready) } == 0 { - interrupt::pause(); - } - print!(" Trampoline..."); - while ! AP_READY.load(Ordering::SeqCst) { - interrupt::pause(); - } - println!(" Ready"); - - active_table.flush_all(); - } else { - println!(" CPU Disabled"); - } - }, - _ => () - } - } - - // Unmap trampoline - let result = active_table.unmap(trampoline_page); - result.flush(active_table); - } else if let Some(dmar) = Dmar::new(sdt) { - println!(": {}: {}", dmar.addr_width, dmar.flags); - - for dmar_entry in dmar.iter() { - println!(" {:?}", dmar_entry); - match dmar_entry { - DmarEntry::Drhd(dmar_drhd) => { - let drhd = dmar_drhd.get(active_table); - - println!("VER: {:X}", drhd.version); - println!("CAP: {:X}", drhd.cap); - println!("EXT_CAP: {:X}", drhd.ext_cap); - println!("GCMD: {:X}", drhd.gl_cmd); - println!("GSTS: {:X}", drhd.gl_sts); - println!("RT: {:X}", drhd.root_table); - }, - _ => () - } - } - } else { - println!(": Unknown"); - } -} - -/// Parse the ACPI tables to gather CPU, interrupt, and timer information -pub unsafe fn init(active_table: &mut ActivePageTable) -> Option { - let start_addr = 0xE0000; - let end_addr = 0xFFFFF; - - // Map all of the ACPI RSDP space - { - let start_frame = Frame::containing_address(PhysicalAddress::new(start_addr)); - let end_frame = Frame::containing_address(PhysicalAddress::new(end_addr)); - for frame in Frame::range_inclusive(start_frame, end_frame) { - let page = Page::containing_address(VirtualAddress::new(frame.start_address().get())); - let result = active_table.map_to(page, frame, entry::PRESENT | entry::NO_EXECUTE); - result.flush(active_table); - } - } - - // Search for RSDP - if let Some(rsdp) = RSDP::search(start_addr, end_addr) { - let get_sdt = |sdt_address: usize, active_table: &mut ActivePageTable| -> (&'static Sdt, bool) { - let mapped = if active_table.translate_page(Page::containing_address(VirtualAddress::new(sdt_address))).is_none() { - let sdt_frame = Frame::containing_address(PhysicalAddress::new(sdt_address)); - let sdt_page = Page::containing_address(VirtualAddress::new(sdt_address)); - let result = active_table.map_to(sdt_page, sdt_frame, entry::PRESENT | entry::NO_EXECUTE); - result.flush(active_table); - true - } else { - false - }; - (&*(sdt_address as *const Sdt), mapped) - }; - - let drop_sdt = |sdt: &'static Sdt, mapped: bool, active_table: &mut ActivePageTable| { - let sdt_address = sdt as *const Sdt as usize; - drop(sdt); - if mapped { - let sdt_page = Page::containing_address(VirtualAddress::new(sdt_address)); - let result = active_table.unmap(sdt_page); - result.flush(active_table); - } - }; - - let (rxsdt, rxmapped) = get_sdt(rsdp.sdt_address(), active_table); - - for &c in rxsdt.signature.iter() { - print!("{}", c as char); - } - println!(":"); - if let Some(rsdt) = Rsdt::new(rxsdt) { - for sdt_address in rsdt.iter() { - let (sdt, mapped) = get_sdt(sdt_address, active_table); - init_sdt(sdt, active_table); - drop_sdt(sdt, mapped, active_table); - } - } else if let Some(xsdt) = Xsdt::new(rxsdt) { - for sdt_address in xsdt.iter() { - let (sdt, mapped) = get_sdt(sdt_address, active_table); - init_sdt(sdt, active_table); - drop_sdt(sdt, mapped, active_table); - } - } else { - println!("UNKNOWN RSDT OR XSDT SIGNATURE"); - } - - drop_sdt(rxsdt, rxmapped, active_table); - } else { - println!("NO RSDP FOUND"); - } - - // Unmap all of the ACPI RSDP space - { - let start_frame = Frame::containing_address(PhysicalAddress::new(start_addr)); - let end_frame = Frame::containing_address(PhysicalAddress::new(end_addr)); - for frame in Frame::range_inclusive(start_frame, end_frame) { - let page = Page::containing_address(VirtualAddress::new(frame.start_address().get())); - let result = active_table.unmap(page); - result.flush(active_table); - } - } - - None -} - -pub struct Acpi; - -/// RSDP -#[derive(Copy, Clone, Debug)] -#[repr(packed)] -pub struct RSDP { - signature: [u8; 8], - checksum: u8, - oemid: [u8; 6], - revision: u8, - rsdt_address: u32, - length: u32, - xsdt_address: u64, - extended_checksum: u8, - reserved: [u8; 3] -} - -impl RSDP { - /// Search for the RSDP - pub fn search(start_addr: usize, end_addr: usize) -> Option { - for i in 0 .. (end_addr + 1 - start_addr)/16 { - let rsdp = unsafe { &*((start_addr + i * 16) as *const RSDP) }; - if &rsdp.signature == b"RSD PTR " { - return Some(*rsdp); - } - } - None - } - - /// Get the RSDT or XSDT address - pub fn sdt_address(&self) -> usize { - if self.revision >= 2 { - self.xsdt_address as usize - } else { - self.rsdt_address as usize - } - } -} diff --git a/kernel/arch/x86_64/src/acpi/rsdt.rs b/kernel/arch/x86_64/src/acpi/rsdt.rs deleted file mode 100644 index fa391c0..0000000 --- a/kernel/arch/x86_64/src/acpi/rsdt.rs +++ /dev/null @@ -1,41 +0,0 @@ -use core::mem; - -use super::sdt::Sdt; - -#[derive(Debug)] -pub struct Rsdt(&'static Sdt); - -impl Rsdt { - pub fn new(sdt: &'static Sdt) -> Option { - if &sdt.signature == b"RSDT" { - Some(Rsdt(sdt)) - } else { - None - } - } - - pub fn iter(&self) -> RsdtIter { - RsdtIter { - sdt: self.0, - i: 0 - } - } -} - -pub struct RsdtIter { - sdt: &'static Sdt, - i: usize -} - -impl Iterator for RsdtIter { - type Item = usize; - fn next(&mut self) -> Option { - if self.i < self.sdt.data_len()/mem::size_of::() { - let item = unsafe { *(self.sdt.data_address() as *const u32).offset(self.i as isize) }; - self.i += 1; - Some(item as usize) - } else { - None - } - } -} diff --git a/kernel/arch/x86_64/src/acpi/sdt.rs b/kernel/arch/x86_64/src/acpi/sdt.rs deleted file mode 100644 index 0d8cedd..0000000 --- a/kernel/arch/x86_64/src/acpi/sdt.rs +++ /dev/null @@ -1,33 +0,0 @@ -use core::mem; - -#[derive(Copy, Clone, Debug)] -#[repr(packed)] -pub struct Sdt { - pub signature: [u8; 4], - pub length: u32, - pub revision: u8, - pub checksum: u8, - pub oem_id: [u8; 6], - pub oem_table_id: [u8; 8], - pub oem_revision: u32, - pub creator_id: u32, - pub creator_revision: u32 -} - -impl Sdt { - /// Get the address of this tables data - pub fn data_address(&'static self) -> usize { - self as *const _ as usize + mem::size_of::() - } - - /// Get the length of this tables data - pub fn data_len(&'static self) -> usize { - let total_size = self.length as usize; - let header_size = mem::size_of::(); - if total_size >= header_size { - total_size - header_size - } else { - 0 - } - } -} diff --git a/kernel/arch/x86_64/src/acpi/xsdt.rs b/kernel/arch/x86_64/src/acpi/xsdt.rs deleted file mode 100644 index 5ec6036..0000000 --- a/kernel/arch/x86_64/src/acpi/xsdt.rs +++ /dev/null @@ -1,41 +0,0 @@ -use core::mem; - -use super::sdt::Sdt; - -#[derive(Debug)] -pub struct Xsdt(&'static Sdt); - -impl Xsdt { - pub fn new(sdt: &'static Sdt) -> Option { - if &sdt.signature == b"XSDT" { - Some(Xsdt(sdt)) - } else { - None - } - } - - pub fn iter(&self) -> XsdtIter { - XsdtIter { - sdt: self.0, - i: 0 - } - } -} - -pub struct XsdtIter { - sdt: &'static Sdt, - i: usize -} - -impl Iterator for XsdtIter { - type Item = usize; - fn next(&mut self) -> Option { - if self.i < self.sdt.data_len()/mem::size_of::() { - let item = unsafe { *(self.sdt.data_address() as *const u64).offset(self.i as isize) }; - self.i += 1; - Some(item as usize) - } else { - None - } - } -} diff --git a/kernel/arch/x86_64/src/console.rs b/kernel/arch/x86_64/src/console.rs deleted file mode 100644 index 92f28d8..0000000 --- a/kernel/arch/x86_64/src/console.rs +++ /dev/null @@ -1,14 +0,0 @@ -use core::fmt::{self, Write}; -use spin::Mutex; - -use device::serial::COM1; - -pub static CONSOLE: Mutex = Mutex::new(Console); - -pub struct Console; - -impl Write for Console { - fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> { - COM1.lock().write_str(s) - } -} diff --git a/kernel/arch/x86_64/src/context.rs b/kernel/arch/x86_64/src/context.rs deleted file mode 100644 index 2a8242d..0000000 --- a/kernel/arch/x86_64/src/context.rs +++ /dev/null @@ -1,184 +0,0 @@ -use core::mem; -use core::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT}; - -/// This must be used by the kernel to ensure that context switches are done atomically -/// Compare and exchange this to true when beginning a context switch on any CPU -/// The Context::switch_to function will set it back to false, allowing other CPU's to switch -/// This must be done, as no locks can be held on the stack during switch -pub static CONTEXT_SWITCH_LOCK: AtomicBool = ATOMIC_BOOL_INIT; - -#[derive(Clone, Debug)] -pub struct Context { - /// FX valid? - loadable: bool, - /// FX location - fx: usize, - /// Page table pointer - cr3: usize, - /// RFLAGS register - rflags: usize, - /// RBX register - rbx: usize, - /// R12 register - r12: usize, - /// R13 register - r13: usize, - /// R14 register - r14: usize, - /// R15 register - r15: usize, - /// Base pointer - rbp: usize, - /// Stack pointer - rsp: usize -} - -impl Context { - pub fn new() -> Context { - Context { - loadable: false, - fx: 0, - cr3: 0, - rflags: 0, - rbx: 0, - r12: 0, - r13: 0, - r14: 0, - r15: 0, - rbp: 0, - rsp: 0 - } - } - - pub fn get_page_table(&self) -> usize { - self.cr3 - } - - pub fn set_fx(&mut self, address: usize) { - self.fx = address; - } - - pub fn set_page_table(&mut self, address: usize) { - self.cr3 = address; - } - - pub fn set_stack(&mut self, address: usize) { - self.rsp = address; - } - - pub unsafe fn signal_stack(&mut self, handler: extern fn(usize), sig: u8) { - self.push_stack(sig as usize); - self.push_stack(handler as usize); - self.push_stack(signal_handler_wrapper as usize); - } - - pub unsafe fn push_stack(&mut self, value: usize) { - self.rsp -= mem::size_of::(); - *(self.rsp as *mut usize) = value; - } - - pub unsafe fn pop_stack(&mut self) -> usize { - let value = *(self.rsp as *const usize); - self.rsp += mem::size_of::(); - value - } - - /// Switch to the next context by restoring its stack and registers - #[cold] - #[inline(never)] - #[naked] - pub unsafe fn switch_to(&mut self, next: &mut Context) { - asm!("fxsave [$0]" : : "r"(self.fx) : "memory" : "intel", "volatile"); - self.loadable = true; - if next.loadable { - asm!("fxrstor [$0]" : : "r"(next.fx) : "memory" : "intel", "volatile"); - }else{ - asm!("fninit" : : : "memory" : "intel", "volatile"); - } - - asm!("mov $0, cr3" : "=r"(self.cr3) : : "memory" : "intel", "volatile"); - if next.cr3 != self.cr3 { - asm!("mov cr3, $0" : : "r"(next.cr3) : "memory" : "intel", "volatile"); - } - - asm!("pushfq ; pop $0" : "=r"(self.rflags) : : "memory" : "intel", "volatile"); - asm!("push $0 ; popfq" : : "r"(next.rflags) : "memory" : "intel", "volatile"); - - asm!("mov $0, rbx" : "=r"(self.rbx) : : "memory" : "intel", "volatile"); - asm!("mov rbx, $0" : : "r"(next.rbx) : "memory" : "intel", "volatile"); - - asm!("mov $0, r12" : "=r"(self.r12) : : "memory" : "intel", "volatile"); - asm!("mov r12, $0" : : "r"(next.r12) : "memory" : "intel", "volatile"); - - asm!("mov $0, r13" : "=r"(self.r13) : : "memory" : "intel", "volatile"); - asm!("mov r13, $0" : : "r"(next.r13) : "memory" : "intel", "volatile"); - - asm!("mov $0, r14" : "=r"(self.r14) : : "memory" : "intel", "volatile"); - asm!("mov r14, $0" : : "r"(next.r14) : "memory" : "intel", "volatile"); - - asm!("mov $0, r15" : "=r"(self.r15) : : "memory" : "intel", "volatile"); - asm!("mov r15, $0" : : "r"(next.r15) : "memory" : "intel", "volatile"); - - asm!("mov $0, rsp" : "=r"(self.rsp) : : "memory" : "intel", "volatile"); - asm!("mov rsp, $0" : : "r"(next.rsp) : "memory" : "intel", "volatile"); - - asm!("mov $0, rbp" : "=r"(self.rbp) : : "memory" : "intel", "volatile"); - asm!("mov rbp, $0" : : "r"(next.rbp) : "memory" : "intel", "volatile"); - } -} - -#[repr(packed)] -pub struct SignalHandlerStack { - r11: usize, - r10: usize, - r9: usize, - r8: usize, - rsi: usize, - rdi: usize, - rdx: usize, - rcx: usize, - rax: usize, - handler: extern fn(usize), - sig: usize, - rip: usize, -} - -#[naked] -unsafe extern fn signal_handler_wrapper() { - #[inline(never)] - unsafe fn inner(stack: &SignalHandlerStack) { - (stack.handler)(stack.sig); - } - - // Push scratch registers - asm!("push rax - push rcx - push rdx - push rdi - push rsi - push r8 - push r9 - push r10 - push r11" - : : : : "intel", "volatile"); - - // Get reference to stack variables - let rsp: usize; - asm!("" : "={rsp}"(rsp) : : : "intel", "volatile"); - - // Call inner rust function - inner(&*(rsp as *const SignalHandlerStack)); - - // Pop scratch registers, error code, and return - asm!("pop r11 - pop r10 - pop r9 - pop r8 - pop rsi - pop rdi - pop rdx - pop rcx - pop rax - add rsp, 16" - : : : : "intel", "volatile"); -} diff --git a/kernel/arch/x86_64/src/device/cpu.rs b/kernel/arch/x86_64/src/device/cpu.rs deleted file mode 100644 index e48547b..0000000 --- a/kernel/arch/x86_64/src/device/cpu.rs +++ /dev/null @@ -1,126 +0,0 @@ -extern crate raw_cpuid; - -use core::fmt::{Result, Write}; - -use self::raw_cpuid::CpuId; - -pub fn cpu_info(w: &mut W) -> Result { - let cpuid = CpuId::new(); - - if let Some(info) = cpuid.get_vendor_info() { - write!(w, "Vendor: {}\n", info.as_string())?; - } - - if let Some(info) = cpuid.get_extended_function_info() { - if let Some(brand) = info.processor_brand_string() { - write!(w, "Model: {}\n", brand)?; - } - } - - if let Some(info) = cpuid.get_processor_frequency_info() { - write!(w, "CPU Base MHz: {}\n", info.processor_base_frequency())?; - write!(w, "CPU Max MHz: {}\n", info.processor_max_frequency())?; - write!(w, "Bus MHz: {}\n", info.bus_frequency())?; - } - - write!(w, "Features:")?; - - if let Some(info) = cpuid.get_feature_info() { - if info.has_fpu() { write!(w, " fpu")? }; - if info.has_vme() { write!(w, " vme")? }; - if info.has_de() { write!(w, " de")? }; - if info.has_pse() { write!(w, " pse")? }; - if info.has_tsc() { write!(w, " tsc")? }; - if info.has_msr() { write!(w, " msr")? }; - if info.has_pae() { write!(w, " pae")? }; - if info.has_mce() { write!(w, " mce")? }; - - if info.has_cmpxchg8b() { write!(w, " cx8")? }; - if info.has_apic() { write!(w, " apic")? }; - if info.has_sysenter_sysexit() { write!(w, " sep")? }; - if info.has_mtrr() { write!(w, " mtrr")? }; - if info.has_pge() { write!(w, " pge")? }; - if info.has_mca() { write!(w, " mca")? }; - if info.has_cmov() { write!(w, " cmov")? }; - if info.has_pat() { write!(w, " pat")? }; - - if info.has_pse36() { write!(w, " pse36")? }; - if info.has_psn() { write!(w, " psn")? }; - if info.has_clflush() { write!(w, " clflush")? }; - if info.has_ds() { write!(w, " ds")? }; - if info.has_acpi() { write!(w, " acpi")? }; - if info.has_mmx() { write!(w, " mmx")? }; - if info.has_fxsave_fxstor() { write!(w, " fxsr")? }; - if info.has_sse() { write!(w, " sse")? }; - - if info.has_sse2() { write!(w, " sse2")? }; - if info.has_ss() { write!(w, " ss")? }; - if info.has_htt() { write!(w, " ht")? }; - if info.has_tm() { write!(w, " tm")? }; - if info.has_pbe() { write!(w, " pbe")? }; - - if info.has_sse3() { write!(w, " sse3")? }; - if info.has_pclmulqdq() { write!(w, " pclmulqdq")? }; - if info.has_ds_area() { write!(w, " dtes64")? }; - if info.has_monitor_mwait() { write!(w, " monitor")? }; - if info.has_cpl() { write!(w, " ds_cpl")? }; - if info.has_vmx() { write!(w, " vmx")? }; - if info.has_smx() { write!(w, " smx")? }; - if info.has_eist() { write!(w, " est")? }; - - if info.has_tm2() { write!(w, " tm2")? }; - if info.has_ssse3() { write!(w, " ssse3")? }; - if info.has_cnxtid() { write!(w, " cnxtid")? }; - if info.has_fma() { write!(w, " fma")? }; - if info.has_cmpxchg16b() { write!(w, " cx16")? }; - if info.has_pdcm() { write!(w, " pdcm")? }; - if info.has_pcid() { write!(w, " pcid")? }; - if info.has_dca() { write!(w, " dca")? }; - - if info.has_sse41() { write!(w, " sse4_1")? }; - if info.has_sse42() { write!(w, " sse4_2")? }; - if info.has_x2apic() { write!(w, " x2apic")? }; - if info.has_movbe() { write!(w, " movbe")? }; - if info.has_popcnt() { write!(w, " popcnt")? }; - if info.has_tsc_deadline() { write!(w, " tsc_deadline_timer")? }; - if info.has_aesni() { write!(w, " aes")? }; - if info.has_xsave() { write!(w, " xsave")? }; - - if info.has_oxsave() { write!(w, " xsaveopt")? }; - if info.has_avx() { write!(w, " avx")? }; - if info.has_f16c() { write!(w, " f16c")? }; - if info.has_rdrand() { write!(w, " rdrand")? }; - } - - if let Some(info) = cpuid.get_extended_function_info() { - if info.has_64bit_mode() { write!(w, " lm")? }; - if info.has_rdtscp() { write!(w, " rdtscp")? }; - if info.has_1gib_pages() { write!(w, " pdpe1gb")? }; - if info.has_execute_disable() { write!(w, " nx")? }; - if info.has_syscall_sysret() { write!(w, " syscall")? }; - if info.has_prefetchw() { write!(w, " prefetchw")? }; - if info.has_lzcnt() { write!(w, " lzcnt")? }; - if info.has_lahf_sahf() { write!(w, " lahf_lm")? }; - if info.has_invariant_tsc() { write!(w, " constant_tsc")? }; - } - - if let Some(info) = cpuid.get_extended_feature_info() { - if info.has_fsgsbase() { write!(w, " fsgsbase")? }; - if info.has_tsc_adjust_msr() { write!(w, " tsc_adjust")? }; - if info.has_bmi1() { write!(w, " bmi1")? }; - if info.has_hle() { write!(w, " hle")? }; - if info.has_avx2() { write!(w, " avx2")? }; - if info.has_smep() { write!(w, " smep")? }; - if info.has_bmi2() { write!(w, " bmi2")? }; - if info.has_rep_movsb_stosb() { write!(w, " erms")? }; - if info.has_invpcid() { write!(w, " invpcid")? }; - if info.has_rtm() { write!(w, " rtm")? }; - if info.has_qm() { write!(w, " qm")? }; - if info.has_fpu_cs_ds_deprecated() { write!(w, " fpu_seg")? }; - if info.has_mpx() { write!(w, " mpx")? }; - } - - write!(w, "\n")?; - - Ok(()) -} diff --git a/kernel/arch/x86_64/src/device/local_apic.rs b/kernel/arch/x86_64/src/device/local_apic.rs deleted file mode 100644 index d55bc3b..0000000 --- a/kernel/arch/x86_64/src/device/local_apic.rs +++ /dev/null @@ -1,115 +0,0 @@ -use core::intrinsics::{volatile_load, volatile_store}; -use x86::cpuid::CpuId; -use x86::msr::*; - -use memory::Frame; -use paging::{entry, ActivePageTable, PhysicalAddress, Page, VirtualAddress}; - -pub static mut LOCAL_APIC: LocalApic = LocalApic { - address: 0, - x2: false -}; - -pub unsafe fn init(active_table: &mut ActivePageTable) { - LOCAL_APIC.init(active_table); -} - -pub unsafe fn init_ap() { - LOCAL_APIC.init_ap(); -} - -/// Local APIC -pub struct LocalApic { - pub address: usize, - pub x2: bool -} - -impl LocalApic { - unsafe fn init(&mut self, active_table: &mut ActivePageTable) { - self.address = (rdmsr(IA32_APIC_BASE) as usize & 0xFFFF0000) + ::KERNEL_OFFSET; - self.x2 = CpuId::new().get_feature_info().unwrap().has_x2apic(); - - if ! self.x2 { - let page = Page::containing_address(VirtualAddress::new(self.address)); - let frame = Frame::containing_address(PhysicalAddress::new(self.address - ::KERNEL_OFFSET)); - let result = active_table.map_to(page, frame, entry::PRESENT | entry::WRITABLE | entry::NO_EXECUTE); - result.flush(active_table); - } - - self.init_ap(); - } - - unsafe fn init_ap(&mut self) { - if self.x2 { - wrmsr(IA32_APIC_BASE, rdmsr(IA32_APIC_BASE) | 1 << 10); - wrmsr(IA32_X2APIC_SIVR, 0x100); - } else { - self.write(0xF0, 0x100); - } - } - - unsafe fn read(&self, reg: u32) -> u32 { - volatile_load((self.address + reg as usize) as *const u32) - } - - unsafe fn write(&mut self, reg: u32, value: u32) { - volatile_store((self.address + reg as usize) as *mut u32, value); - } - - pub fn id(&self) -> u32 { - if self.x2 { - unsafe { rdmsr(IA32_X2APIC_APICID) as u32 } - } else { - unsafe { self.read(0x20) } - } - } - - pub fn version(&self) -> u32 { - if self.x2 { - unsafe { rdmsr(IA32_X2APIC_VERSION) as u32 } - } else { - unsafe { self.read(0x30) } - } - } - - pub fn icr(&self) -> u64 { - if self.x2 { - unsafe { rdmsr(IA32_X2APIC_ICR) } - } else { - unsafe { - (self.read(0x310) as u64) << 32 | self.read(0x300) as u64 - } - } - } - - pub fn set_icr(&mut self, value: u64) { - if self.x2 { - unsafe { wrmsr(IA32_X2APIC_ICR, value); } - } else { - unsafe { - while self.read(0x300) & 1 << 12 == 1 << 12 {} - self.write(0x310, (value >> 32) as u32); - self.write(0x300, value as u32); - while self.read(0x300) & 1 << 12 == 1 << 12 {} - } - } - } - - pub fn ipi(&mut self, apic_id: usize) { - let mut icr = 0x4040; - if self.x2 { - icr |= (apic_id as u64) << 32; - } else { - icr |= (apic_id as u64) << 56; - } - self.set_icr(icr); - } - - pub unsafe fn eoi(&mut self) { - if self.x2 { - wrmsr(IA32_X2APIC_EOI, 0); - } else { - self.write(0xB0, 0); - } - } -} diff --git a/kernel/arch/x86_64/src/device/mod.rs b/kernel/arch/x86_64/src/device/mod.rs deleted file mode 100644 index d4d56e6..0000000 --- a/kernel/arch/x86_64/src/device/mod.rs +++ /dev/null @@ -1,16 +0,0 @@ -use paging::ActivePageTable; - -pub mod cpu; -pub mod local_apic; -pub mod rtc; -pub mod serial; - -pub unsafe fn init(active_table: &mut ActivePageTable){ - local_apic::init(active_table); - rtc::init(); - serial::init(); -} - -pub unsafe fn init_ap() { - local_apic::init_ap(); -} diff --git a/kernel/arch/x86_64/src/device/rtc.rs b/kernel/arch/x86_64/src/device/rtc.rs deleted file mode 100644 index ef6de05..0000000 --- a/kernel/arch/x86_64/src/device/rtc.rs +++ /dev/null @@ -1,109 +0,0 @@ -use io::{Io, Pio}; -use time; - -pub fn init() { - let mut rtc = Rtc::new(); - time::START.lock().0 = rtc.time(); -} - -fn cvt_bcd(value: usize) -> usize { - (value & 0xF) + ((value / 16) * 10) -} - -/// RTC -pub struct Rtc { - addr: Pio, - data: Pio, -} - -impl Rtc { - /// Create new empty RTC - pub fn new() -> Self { - return Rtc { - addr: Pio::::new(0x70), - data: Pio::::new(0x71), - }; - } - - /// Read - unsafe fn read(&mut self, reg: u8) -> u8 { - self.addr.write(reg); - return self.data.read(); - } - - /// Wait - unsafe fn wait(&mut self) { - while self.read(0xA) & 0x80 != 0x80 {} - while self.read(0xA) & 0x80 == 0x80 {} - } - - /// Get time - pub fn time(&mut self) -> u64 { - let mut second; - let mut minute; - let mut hour; - let mut day; - let mut month; - let mut year; - let register_b; - unsafe { - self.wait(); - second = self.read(0) as usize; - minute = self.read(2) as usize; - hour = self.read(4) as usize; - day = self.read(7) as usize; - month = self.read(8) as usize; - year = self.read(9) as usize; - register_b = self.read(0xB); - } - - if register_b & 4 != 4 { - second = cvt_bcd(second); - minute = cvt_bcd(minute); - hour = cvt_bcd(hour & 0x7F) | (hour & 0x80); - day = cvt_bcd(day); - month = cvt_bcd(month); - year = cvt_bcd(year); - } - - if register_b & 2 != 2 || hour & 0x80 == 0x80 { - hour = ((hour & 0x7F) + 12) % 24; - } - - // TODO: Century Register - year += 2000; - - // Unix time from clock - let mut secs: u64 = (year as u64 - 1970) * 31536000; - - let mut leap_days = (year as u64 - 1972) / 4 + 1; - if year % 4 == 0 { - if month <= 2 { - leap_days -= 1; - } - } - secs += leap_days * 86400; - - match month { - 2 => secs += 2678400, - 3 => secs += 5097600, - 4 => secs += 7776000, - 5 => secs += 10368000, - 6 => secs += 13046400, - 7 => secs += 15638400, - 8 => secs += 18316800, - 9 => secs += 20995200, - 10 => secs += 23587200, - 11 => secs += 26265600, - 12 => secs += 28857600, - _ => (), - } - - secs += (day as u64 - 1) * 86400; - secs += hour as u64 * 3600; - secs += minute as u64 * 60; - secs += second as u64; - - secs - } -} diff --git a/kernel/arch/x86_64/src/device/serial.rs b/kernel/arch/x86_64/src/device/serial.rs deleted file mode 100644 index 521c04e..0000000 --- a/kernel/arch/x86_64/src/device/serial.rs +++ /dev/null @@ -1,115 +0,0 @@ -use core::fmt::{self, Write}; -use spin::Mutex; - -use io::{Io, Pio, ReadOnly}; - -pub static COM1: Mutex = Mutex::new(SerialPort::new(0x3F8)); -pub static COM2: Mutex = Mutex::new(SerialPort::new(0x2F8)); - -pub unsafe fn init() { - COM1.lock().init(); - COM2.lock().init(); -} - -bitflags! { - /// Interrupt enable flags - flags IntEnFlags: u8 { - const RECEIVED = 1, - const SENT = 1 << 1, - const ERRORED = 1 << 2, - const STATUS_CHANGE = 1 << 3, - // 4 to 7 are unused - } -} - -bitflags! { - /// Line status flags - flags LineStsFlags: u8 { - const INPUT_FULL = 1, - // 1 to 4 unknown - const OUTPUT_EMPTY = 1 << 5, - // 6 and 7 unknown - } -} - -#[allow(dead_code)] -pub struct SerialPort { - /// Data register, read to receive, write to send - data: Pio, - /// Interrupt enable - int_en: Pio, - /// FIFO control - fifo_ctrl: Pio, - /// Line control - line_ctrl: Pio, - /// Modem control - modem_ctrl: Pio, - /// Line status - line_sts: ReadOnly>, - /// Modem status - modem_sts: ReadOnly>, -} - -impl SerialPort { - const fn new(base: u16) -> SerialPort { - SerialPort { - data: Pio::new(base), - int_en: Pio::new(base + 1), - fifo_ctrl: Pio::new(base + 2), - line_ctrl: Pio::new(base + 3), - modem_ctrl: Pio::new(base + 4), - line_sts: ReadOnly::new(Pio::new(base + 5)), - modem_sts: ReadOnly::new(Pio::new(base + 6)) - } - } - - fn line_sts(&self) -> LineStsFlags { - LineStsFlags::from_bits_truncate(self.line_sts.read()) - } - - fn write(&mut self, data: u8) { - while ! self.line_sts().contains(OUTPUT_EMPTY) {} - self.data.write(data) - } - - fn init(&mut self) { - //TODO: Cleanup - self.int_en.write(0x00); - self.line_ctrl.write(0x80); - self.data.write(0x03); - self.int_en.write(0x00); - self.line_ctrl.write(0x03); - self.fifo_ctrl.write(0xC7); - self.modem_ctrl.write(0x0B); - self.int_en.write(0x01); - } - - pub fn on_receive(&mut self) { - let data = self.data.read(); - - extern { - fn debug_input(byte: u8); - } - - unsafe { debug_input(data) }; - } -} - -impl Write for SerialPort { - fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> { - for byte in s.bytes() { - match byte { - 8 | 0x7F => { - self.write(8); - self.write(b' '); - self.write(8); - }, - _ => { - self.write(byte); - } - } - } - - Ok(()) - } -} diff --git a/kernel/arch/x86_64/src/externs.rs b/kernel/arch/x86_64/src/externs.rs deleted file mode 100644 index d92f8c4..0000000 --- a/kernel/arch/x86_64/src/externs.rs +++ /dev/null @@ -1,70 +0,0 @@ -/// 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 as usize + i) as *mut u8) = *((src as usize + i) as *const u8); - 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 as usize + i) as *mut u8) = *((src as usize + i) as *const u8); - } - } else { - let mut i = 0; - while i < n { - *((dest as usize + i) as *mut u8) = *((src as usize + i) as *const u8); - i += 1; - } - } - - dest -} - -/// Memset -/// -/// Fill a block of memory with a specified value. -#[no_mangle] -pub unsafe extern fn memset(dest: *mut u8, c: i32, n: usize) -> *mut u8 { - let mut i = 0; - while i < n { - *((dest as usize + i) as *mut u8) = c as u8; - i += 1; - } - - dest -} - -/// 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 as usize + i) as *const u8); - let b = *((s2 as usize + i) as *const u8); - if a != b { - return a as i32 - b as i32 - } - i += 1; - } - - 0 -} diff --git a/kernel/arch/x86_64/src/gdt.rs b/kernel/arch/x86_64/src/gdt.rs deleted file mode 100644 index 96e1b99..0000000 --- a/kernel/arch/x86_64/src/gdt.rs +++ /dev/null @@ -1,177 +0,0 @@ -//! Global descriptor table - -use core::mem; -use x86::dtables::{self, DescriptorTablePointer}; -use x86::segmentation::{self, SegmentSelector}; -use x86::task::{self, TaskStateSegment}; - -pub const GDT_NULL: usize = 0; -pub const GDT_KERNEL_CODE: usize = 1; -pub const GDT_KERNEL_DATA: usize = 2; -pub const GDT_KERNEL_TLS: usize = 3; -pub const GDT_USER_CODE: usize = 4; -pub const GDT_USER_DATA: usize = 5; -pub const GDT_USER_TLS: usize = 6; -pub const GDT_TSS: usize = 7; -pub const GDT_TSS_HIGH: usize = 8; - -pub const GDT_A_PRESENT: u8 = 1 << 7; -pub const GDT_A_RING_0: u8 = 0 << 5; -pub const GDT_A_RING_1: u8 = 1 << 5; -pub const GDT_A_RING_2: u8 = 2 << 5; -pub const GDT_A_RING_3: u8 = 3 << 5; -pub const GDT_A_SYSTEM: u8 = 1 << 4; -pub const GDT_A_EXECUTABLE: u8 = 1 << 3; -pub const GDT_A_CONFORMING: u8 = 1 << 2; -pub const GDT_A_PRIVILEGE: u8 = 1 << 1; -pub const GDT_A_DIRTY: u8 = 1; - -pub const GDT_A_TSS_AVAIL: u8 = 0x9; -pub const GDT_A_TSS_BUSY: u8 = 0xB; - -pub const GDT_F_PAGE_SIZE: u8 = 1 << 7; -pub const GDT_F_PROTECTED_MODE: u8 = 1 << 6; -pub const GDT_F_LONG_MODE: u8 = 1 << 5; - -static mut INIT_GDTR: DescriptorTablePointer = DescriptorTablePointer { - limit: 0, - base: 0 -}; - -static mut INIT_GDT: [GdtEntry; 4] = [ - // Null - GdtEntry::new(0, 0, 0, 0), - // Kernel code - GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE, GDT_F_LONG_MODE), - // Kernel data - GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_LONG_MODE), - // Kernel TLS - GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_LONG_MODE) -]; - -#[thread_local] -pub static mut GDTR: DescriptorTablePointer = DescriptorTablePointer { - limit: 0, - base: 0 -}; - -#[thread_local] -pub static mut GDT: [GdtEntry; 9] = [ - // Null - GdtEntry::new(0, 0, 0, 0), - // Kernel code - GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE, GDT_F_LONG_MODE), - // Kernel data - GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_LONG_MODE), - // Kernel TLS - GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_LONG_MODE), - // User code - GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE, GDT_F_LONG_MODE), - // User data - GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_LONG_MODE), - // User TLS - GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_LONG_MODE), - // TSS - GdtEntry::new(0, 0, GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_TSS_AVAIL, 0), - // TSS must be 16 bytes long, twice the normal size - GdtEntry::new(0, 0, 0, 0), -]; - -#[thread_local] -pub static mut TSS: TaskStateSegment = TaskStateSegment { - reserved: 0, - rsp: [0; 3], - reserved2: 0, - ist: [0; 7], - reserved3: 0, - reserved4: 0, - iomap_base: 0xFFFF -}; - -/// Initialize GDT -pub unsafe fn init(tcb_offset: usize, stack_offset: usize) { - // Setup the initial GDT with TLS, so we can setup the TLS GDT (a little confusing) - // This means that each CPU will have its own GDT, but we only need to define it once as a thread local - INIT_GDTR.limit = (INIT_GDT.len() * mem::size_of::() - 1) as u16; - INIT_GDTR.base = INIT_GDT.as_ptr() as u64; - - // Set the TLS segment to the offset of the Thread Control Block - INIT_GDT[GDT_KERNEL_TLS].set_offset(tcb_offset as u32); - - // Load the initial GDT, before we have access to thread locals - dtables::lgdt(&INIT_GDTR); - - // Load the segment descriptors - segmentation::load_cs(SegmentSelector::new(GDT_KERNEL_CODE as u16)); - segmentation::load_ds(SegmentSelector::new(GDT_KERNEL_DATA as u16)); - segmentation::load_es(SegmentSelector::new(GDT_KERNEL_DATA as u16)); - segmentation::load_fs(SegmentSelector::new(GDT_KERNEL_TLS as u16)); - segmentation::load_gs(SegmentSelector::new(GDT_KERNEL_DATA as u16)); - segmentation::load_ss(SegmentSelector::new(GDT_KERNEL_DATA as u16)); - - // Now that we have access to thread locals, setup the AP's individual GDT - GDTR.limit = (GDT.len() * mem::size_of::() - 1) as u16; - GDTR.base = GDT.as_ptr() as u64; - - // Set the TLS segment to the offset of the Thread Control Block - GDT[GDT_KERNEL_TLS].set_offset(tcb_offset as u32); - - // Set the User TLS segment to the offset of the user TCB - GDT[GDT_USER_TLS].set_offset(::USER_TCB_OFFSET as u32); - - // We can now access our TSS, which is a thread local - GDT[GDT_TSS].set_offset(&TSS as *const _ as u32); - GDT[GDT_TSS].set_limit(mem::size_of::() as u32); - - // Set the stack pointer when coming back from userspace - TSS.rsp[0] = stack_offset as u64; - - // Load the new GDT, which is correctly located in thread local storage - dtables::lgdt(&GDTR); - - // Reload the segment descriptors - segmentation::load_cs(SegmentSelector::new(GDT_KERNEL_CODE as u16)); - segmentation::load_ds(SegmentSelector::new(GDT_KERNEL_DATA as u16)); - segmentation::load_es(SegmentSelector::new(GDT_KERNEL_DATA as u16)); - segmentation::load_fs(SegmentSelector::new(GDT_KERNEL_TLS as u16)); - segmentation::load_gs(SegmentSelector::new(GDT_KERNEL_DATA as u16)); - segmentation::load_ss(SegmentSelector::new(GDT_KERNEL_DATA as u16)); - - // Load the task register - task::load_ltr(SegmentSelector::new(GDT_TSS as u16)); -} - -#[derive(Copy, Clone, Debug)] -#[repr(packed)] -pub struct GdtEntry { - pub limitl: u16, - pub offsetl: u16, - pub offsetm: u8, - pub access: u8, - pub flags_limith: u8, - pub offseth: u8 -} - -impl GdtEntry { - pub const fn new(offset: u32, limit: u32, access: u8, flags: u8) -> Self { - GdtEntry { - limitl: limit as u16, - offsetl: offset as u16, - offsetm: (offset >> 16) as u8, - access: access, - flags_limith: flags & 0xF0 | ((limit >> 16) as u8) & 0x0F, - offseth: (offset >> 24) as u8 - } - } - - pub fn set_offset(&mut self, offset: u32) { - self.offsetl = offset as u16; - self.offsetm = (offset >> 16) as u8; - self.offseth = (offset >> 24) as u8; - } - - pub fn set_limit(&mut self, limit: u32) { - self.limitl = limit as u16; - self.flags_limith = self.flags_limith & 0xF0 | ((limit >> 16) as u8) & 0x0F; - } -} diff --git a/kernel/arch/x86_64/src/idt.rs b/kernel/arch/x86_64/src/idt.rs deleted file mode 100644 index 0d0d95e..0000000 --- a/kernel/arch/x86_64/src/idt.rs +++ /dev/null @@ -1,142 +0,0 @@ -use core::mem; -use x86::dtables::{self, DescriptorTablePointer}; - -use interrupt::*; - -pub static mut IDTR: DescriptorTablePointer = DescriptorTablePointer { - limit: 0, - base: 0 -}; - -pub static mut IDT: [IdtEntry; 256] = [IdtEntry::new(); 256]; - -pub unsafe fn init() { - IDTR.limit = (IDT.len() * mem::size_of::() - 1) as u16; - IDTR.base = IDT.as_ptr() as u64; - - // Set up exceptions - IDT[0].set_func(exception::divide_by_zero); - IDT[1].set_func(exception::debug); - IDT[2].set_func(exception::non_maskable); - IDT[3].set_func(exception::breakpoint); - IDT[4].set_func(exception::overflow); - IDT[5].set_func(exception::bound_range); - IDT[6].set_func(exception::invalid_opcode); - IDT[7].set_func(exception::device_not_available); - IDT[8].set_func(exception::double_fault); - // 9 no longer available - IDT[10].set_func(exception::invalid_tss); - IDT[11].set_func(exception::segment_not_present); - IDT[12].set_func(exception::stack_segment); - IDT[13].set_func(exception::protection); - IDT[14].set_func(exception::page); - // 15 reserved - IDT[16].set_func(exception::fpu); - IDT[17].set_func(exception::alignment_check); - IDT[18].set_func(exception::machine_check); - IDT[19].set_func(exception::simd); - IDT[20].set_func(exception::virtualization); - // 21 through 29 reserved - IDT[30].set_func(exception::security); - // 31 reserved - - // Set up IRQs - IDT[32].set_func(irq::pit); - IDT[33].set_func(irq::keyboard); - IDT[34].set_func(irq::cascade); - IDT[35].set_func(irq::com2); - IDT[36].set_func(irq::com1); - IDT[37].set_func(irq::lpt2); - IDT[38].set_func(irq::floppy); - IDT[39].set_func(irq::lpt1); - IDT[40].set_func(irq::rtc); - IDT[41].set_func(irq::pci1); - IDT[42].set_func(irq::pci2); - IDT[43].set_func(irq::pci3); - IDT[44].set_func(irq::mouse); - IDT[45].set_func(irq::fpu); - IDT[46].set_func(irq::ata1); - IDT[47].set_func(irq::ata2); - - // Set IPI handler (null) - IDT[0x40].set_func(ipi::ipi); - - // Set syscall function - IDT[0x80].set_func(syscall::syscall); - IDT[0x80].set_flags(IDT_PRESENT | IDT_RING_3 | IDT_INTERRUPT); - - dtables::lidt(&IDTR); -} - -bitflags! { - pub flags IdtFlags: u8 { - const IDT_PRESENT = 1 << 7, - const IDT_RING_0 = 0 << 5, - const IDT_RING_1 = 1 << 5, - const IDT_RING_2 = 2 << 5, - const IDT_RING_3 = 3 << 5, - const IDT_SS = 1 << 4, - const IDT_INTERRUPT = 0xE, - const IDT_TRAP = 0xF, - } -} - -#[repr(packed)] -pub struct IdtDescriptor { - size: u16, - offset: u64 -} - -impl IdtDescriptor { - pub fn set_slice(&mut self, slice: &'static [IdtEntry]) { - self.size = (slice.len() * mem::size_of::() - 1) as u16; - self.offset = slice.as_ptr() as u64; - } - - pub unsafe fn load(&self) { - asm!("lidt [rax]" : : "{rax}"(self as *const _ as usize) : : "intel", "volatile"); - } -} - -#[derive(Copy, Clone, Debug)] -#[repr(packed)] -pub struct IdtEntry { - offsetl: u16, - selector: u16, - zero: u8, - attribute: u8, - offsetm: u16, - offseth: u32, - zero2: u32 -} - -impl IdtEntry { - pub const fn new() -> IdtEntry { - IdtEntry { - offsetl: 0, - selector: 0, - zero: 0, - attribute: 0, - offsetm: 0, - offseth: 0, - zero2: 0 - } - } - - pub fn set_flags(&mut self, flags: IdtFlags) { - self.attribute = flags.bits; - } - - pub fn set_offset(&mut self, selector: u16, base: usize) { - self.selector = selector; - self.offsetl = base as u16; - self.offsetm = (base >> 16) as u16; - self.offseth = (base >> 32) as u32; - } - - // A function to set the offset more easily - pub fn set_func(&mut self, func: unsafe extern fn()) { - self.set_flags(IDT_PRESENT | IDT_RING_0 | IDT_INTERRUPT); - self.set_offset(8, func as usize); - } -} diff --git a/kernel/arch/x86_64/src/interrupt/exception.rs b/kernel/arch/x86_64/src/interrupt/exception.rs deleted file mode 100644 index 3822779..0000000 --- a/kernel/arch/x86_64/src/interrupt/exception.rs +++ /dev/null @@ -1,123 +0,0 @@ -use interrupt::stack_trace; -use syscall::flag::*; - -extern { - fn ksignal(signal: usize); -} - -interrupt_stack!(divide_by_zero, stack, { - println!("Divide by zero fault at {:>02X}:{:>016X}", stack.cs, stack.rip); - stack_trace(); - ksignal(SIGFPE); -}); - -interrupt_stack!(debug, stack, { - println!("Debug trap at {:>02X}:{:>016X}", stack.cs, stack.rip); - ksignal(SIGTRAP); -}); - -interrupt_stack!(non_maskable, stack, { - println!("Non-maskable interrupt at {:>02X}:{:>016X}", stack.cs, stack.rip); -}); - -interrupt_stack!(breakpoint, stack, { - println!("Breakpoint trap at {:>02X}:{:>016X}", stack.cs, stack.rip); - ksignal(SIGTRAP); -}); - -interrupt_stack!(overflow, stack, { - println!("Overflow trap at {:>02X}:{:>016X}", stack.cs, stack.rip); - ksignal(SIGFPE); -}); - -interrupt_stack!(bound_range, stack, { - println!("Bound range exceeded fault at {:>02X}:{:>016X}", stack.cs, stack.rip); - stack_trace(); - ksignal(SIGSEGV); -}); - -interrupt_stack!(invalid_opcode, stack, { - println!("Invalid opcode fault at {:>02X}:{:>016X}", stack.cs, stack.rip); - stack_trace(); - ksignal(SIGILL); -}); - -interrupt_stack!(device_not_available, stack, { - println!("Device not available fault at {:>02X}:{:>016X}", stack.cs, stack.rip); - stack_trace(); - ksignal(SIGILL); -}); - -interrupt_error!(double_fault, stack, { - println!("Double fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip); - stack_trace(); - ksignal(SIGSEGV); -}); - -interrupt_error!(invalid_tss, stack, { - println!("Invalid TSS fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip); - stack_trace(); - ksignal(SIGSEGV); -}); - -interrupt_error!(segment_not_present, stack, { - println!("Segment not present fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip); - stack_trace(); - ksignal(SIGSEGV); -}); - -interrupt_error!(stack_segment, stack, { - println!("Stack segment fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip); - stack_trace(); - ksignal(SIGSEGV); -}); - -interrupt_error!(protection, stack, { - println!("Protection fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip); - stack_trace(); - ksignal(SIGSEGV); -}); - -interrupt_error!(page, stack, { - let cr2: usize; - asm!("mov rax, cr2" : "={rax}"(cr2) : : : "intel", "volatile"); - println!("Page fault: {:>02X}:{:>016X} at {:>02X}:{:>016X}", stack.code, cr2, stack.cs, stack.rip); - stack_trace(); - ksignal(SIGSEGV); -}); - -interrupt_stack!(fpu, stack, { - println!("FPU floating point fault at {:>02X}:{:>016X}", stack.cs, stack.rip); - stack_trace(); - ksignal(SIGFPE); -}); - -interrupt_error!(alignment_check, stack, { - println!("Alignment check fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip); - stack_trace(); - ksignal(SIGBUS); -}); - -interrupt_stack!(machine_check, stack, { - println!("Machine check fault at {:>02X}:{:>016X}", stack.cs, stack.rip); - stack_trace(); - ksignal(SIGBUS); -}); - -interrupt_stack!(simd, stack, { - println!("SIMD floating point fault at {:>02X}:{:>016X}", stack.cs, stack.rip); - stack_trace(); - ksignal(SIGFPE); -}); - -interrupt_stack!(virtualization, stack, { - println!("Virtualization fault at {:>02X}:{:>016X}", stack.cs, stack.rip); - stack_trace(); - ksignal(SIGBUS); -}); - -interrupt_error!(security, stack, { - println!("Security exception: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip); - stack_trace(); - ksignal(SIGBUS); -}); diff --git a/kernel/arch/x86_64/src/interrupt/ipi.rs b/kernel/arch/x86_64/src/interrupt/ipi.rs deleted file mode 100644 index 325d9d8..0000000 --- a/kernel/arch/x86_64/src/interrupt/ipi.rs +++ /dev/null @@ -1,5 +0,0 @@ -use device::local_apic::LOCAL_APIC; - -interrupt!(ipi, { - LOCAL_APIC.eoi(); -}); diff --git a/kernel/arch/x86_64/src/interrupt/irq.rs b/kernel/arch/x86_64/src/interrupt/irq.rs deleted file mode 100644 index c6a8733..0000000 --- a/kernel/arch/x86_64/src/interrupt/irq.rs +++ /dev/null @@ -1,115 +0,0 @@ -use x86::io; - -use device::serial::{COM1, COM2}; -use time; - -extern { - fn irq_trigger(irq: u8); -} - -#[inline(always)] -unsafe fn master_ack() { - io::outb(0x20, 0x20); -} - -#[inline(always)] -unsafe fn slave_ack() { - io::outb(0xA0, 0x20); - master_ack(); -} - -pub unsafe fn acknowledge(irq: usize) { - if irq >= 8 { - slave_ack(); - } else { - master_ack(); - } -} - -interrupt!(pit, { - // Saves CPU time by not sending IRQ event irq_trigger(0); - - { - const PIT_RATE: u64 = 2250286; - - let mut offset = time::OFFSET.lock(); - let sum = offset.1 + PIT_RATE; - offset.1 = sum % 1000000000; - offset.0 += sum / 1000000000; - } - - master_ack(); -}); - -interrupt!(keyboard, { - irq_trigger(1); -}); - -interrupt!(cascade, { - irq_trigger(2); - master_ack(); -}); - -interrupt!(com2, { - irq_trigger(3); - COM2.lock().on_receive(); - master_ack(); -}); - -interrupt!(com1, { - irq_trigger(4); - COM1.lock().on_receive(); - master_ack(); -}); - -interrupt!(lpt2, { - irq_trigger(5); - master_ack(); -}); - -interrupt!(floppy, { - irq_trigger(6); - master_ack(); -}); - -interrupt!(lpt1, { - irq_trigger(7); - master_ack(); -}); - -interrupt!(rtc, { - irq_trigger(8); - slave_ack(); -}); - -interrupt!(pci1, { - irq_trigger(9); - slave_ack(); -}); - -interrupt!(pci2, { - irq_trigger(10); -}); - -interrupt!(pci3, { - irq_trigger(11); -}); - -interrupt!(mouse, { - irq_trigger(12); -}); - -interrupt!(fpu, { - irq_trigger(13); - slave_ack(); -}); - -interrupt!(ata1, { - irq_trigger(14); - slave_ack(); -}); - -interrupt!(ata2, { - irq_trigger(15); - slave_ack(); -}); diff --git a/kernel/arch/x86_64/src/interrupt/mod.rs b/kernel/arch/x86_64/src/interrupt/mod.rs deleted file mode 100644 index 3cc5caa..0000000 --- a/kernel/arch/x86_64/src/interrupt/mod.rs +++ /dev/null @@ -1,85 +0,0 @@ -//! Interrupt instructions - -use core::mem; - -use paging::{ActivePageTable, VirtualAddress}; - -pub mod exception; -pub mod ipi; -pub mod irq; -pub mod syscall; - -/// Clear interrupts -#[inline(always)] -pub unsafe fn disable() { - asm!("cli" : : : : "intel", "volatile"); -} - -/// Set interrupts -#[inline(always)] -pub unsafe fn enable() { - asm!("sti" : : : : "intel", "volatile"); -} - -/// Set interrupts and halt -/// This will atomically wait for the next interrupt -/// Performing enable followed by halt is not guaranteed to be atomic, use this instead! -#[inline(always)] -pub unsafe fn enable_and_halt() { - asm!("sti - hlt" - : : : : "intel", "volatile"); -} - -/// Set interrupts and nop -/// This will enable interrupts and allow the IF flag to be processed -/// Simply enabling interrupts does not gurantee that they will trigger, use this instead! -#[inline(always)] -pub unsafe fn enable_and_nop() { - asm!("sti - nop" - : : : : "intel", "volatile"); -} - -/// Halt instruction -#[inline(always)] -pub unsafe fn halt() { - asm!("hlt" : : : : "intel", "volatile"); -} - -/// Pause instruction -/// Safe because it is similar to a NOP, and has no memory effects -#[inline(always)] -pub fn pause() { - unsafe { asm!("pause" : : : : "intel", "volatile"); } -} - -/// Get a stack trace -//TODO: Check for stack being mapped before dereferencing -#[inline(never)] -pub unsafe fn stack_trace() { - let mut rbp: usize; - asm!("" : "={rbp}"(rbp) : : : "intel", "volatile"); - - println!("TRACE: {:>016X}", rbp); - //Maximum 64 frames - let active_table = ActivePageTable::new(); - for _frame in 0..64 { - if let Some(rip_rbp) = rbp.checked_add(mem::size_of::()) { - if active_table.translate(VirtualAddress::new(rbp)).is_some() && active_table.translate(VirtualAddress::new(rip_rbp)).is_some() { - let rip = *(rip_rbp as *const usize); - if rip == 0 { - println!(" {:>016X}: EMPTY RETURN", rbp); - break; - } - println!(" {:>016X}: {:>016X}", rbp, rip); - rbp = *(rbp as *const usize); - } else { - println!(" {:>016X}: GUARD PAGE", rbp); - break; - } - } else { - println!(" {:>016X}: RBP OVERFLOW", rbp); - } - } -} diff --git a/kernel/arch/x86_64/src/interrupt/syscall.rs b/kernel/arch/x86_64/src/interrupt/syscall.rs deleted file mode 100644 index d1527da..0000000 --- a/kernel/arch/x86_64/src/interrupt/syscall.rs +++ /dev/null @@ -1,61 +0,0 @@ -#[naked] -pub unsafe extern fn syscall() { - #[inline(never)] - unsafe fn inner() { - extern { - fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, stack: usize) -> usize; - } - - let mut a; - { - let b; - let c; - let d; - let e; - let f; - let stack; - asm!("" : "={rax}"(a), "={rbx}"(b), "={rcx}"(c), "={rdx}"(d), "={rsi}"(e), "={rdi}"(f), "={rbp}"(stack) - : : : "intel", "volatile"); - - a = syscall(a, b, c, d, e, f, stack); - } - - asm!("" : : "{rax}"(a) : : "intel", "volatile"); - } - - // Push scratch registers, minus rax for the return value - asm!("push rcx - push rdx - push rdi - push rsi - push r8 - push r9 - push r10 - push r11 - push fs - mov r11, 0x18 - mov fs, r11" - : : : : "intel", "volatile"); - - inner(); - - // Interrupt return - asm!("pop fs - pop r11 - pop r10 - pop r9 - pop r8 - pop rsi - pop rdi - pop rdx - pop rcx - iretq" - : : : : "intel", "volatile"); -} - -#[naked] -pub unsafe extern fn clone_ret() -> usize { - asm!("pop rbp" - : : : : "intel", "volatile"); - 0 -} diff --git a/kernel/arch/x86_64/src/lib.rs b/kernel/arch/x86_64/src/lib.rs deleted file mode 100644 index 954535f..0000000 --- a/kernel/arch/x86_64/src/lib.rs +++ /dev/null @@ -1,327 +0,0 @@ -//! Architecture support for x86_64 - -#![deny(unused_must_use)] -#![feature(asm)] -#![feature(concat_idents)] -#![feature(const_fn)] -#![feature(core_intrinsics)] -#![feature(drop_types_in_const)] -#![feature(lang_items)] -#![feature(naked_functions)] -#![feature(thread_local)] -#![feature(unique)] -#![no_std] - -extern crate hole_list_allocator as allocator; - -#[macro_use] -extern crate bitflags; -extern crate io; -extern crate spin; -extern crate syscall; -pub extern crate x86; - -// Because the memory map is so important to not be aliased, it is defined here, in one place -// The lower 256 PML4 entries are reserved for userspace -// Each PML4 entry references up to 512 GB of memory -// The top (511) PML4 is reserved for recursive mapping -// The second from the top (510) PML4 is reserved for the kernel - /// The size of a single PML4 - pub const PML4_SIZE: usize = 0x0000_0080_0000_0000; - - /// Offset of recursive paging - pub const RECURSIVE_PAGE_OFFSET: usize = (-(PML4_SIZE as isize)) as usize; - - /// Offset of kernel - pub const KERNEL_OFFSET: usize = RECURSIVE_PAGE_OFFSET - PML4_SIZE; - - /// Offset to kernel heap - pub const KERNEL_HEAP_OFFSET: usize = KERNEL_OFFSET + PML4_SIZE/2; - /// Size of kernel heap - pub const KERNEL_HEAP_SIZE: usize = 128 * 1024 * 1024; // 128 MB - - /// Offset to kernel percpu variables - //TODO: Use 64-bit fs offset to enable this pub const KERNEL_PERCPU_OFFSET: usize = KERNEL_HEAP_OFFSET - PML4_SIZE; - pub const KERNEL_PERCPU_OFFSET: usize = 0xC000_0000; - /// Size of kernel percpu variables - pub const KERNEL_PERCPU_SIZE: usize = 64 * 1024; // 64 KB - - /// Offset to user image - pub const USER_OFFSET: usize = 0; - - /// Offset to user TCB - pub const USER_TCB_OFFSET: usize = 0xB000_0000; - - /// Offset to user arguments - pub const USER_ARG_OFFSET: usize = USER_OFFSET + PML4_SIZE/2; - - /// Offset to user heap - pub const USER_HEAP_OFFSET: usize = USER_OFFSET + PML4_SIZE; - - /// Offset to user grants - pub const USER_GRANT_OFFSET: usize = USER_HEAP_OFFSET + PML4_SIZE; - - /// Offset to user stack - pub const USER_STACK_OFFSET: usize = USER_GRANT_OFFSET + PML4_SIZE; - /// Size of user stack - pub const USER_STACK_SIZE: usize = 1024 * 1024; // 1 MB - - /// Offset to user TLS - pub const USER_TLS_OFFSET: usize = USER_STACK_OFFSET + PML4_SIZE; - - /// Offset to user temporary image (used when cloning) - pub const USER_TMP_OFFSET: usize = USER_TLS_OFFSET + PML4_SIZE; - - /// Offset to user temporary heap (used when cloning) - pub const USER_TMP_HEAP_OFFSET: usize = USER_TMP_OFFSET + PML4_SIZE; - - /// Offset to user temporary page for grants - pub const USER_TMP_GRANT_OFFSET: usize = USER_TMP_HEAP_OFFSET + PML4_SIZE; - - /// Offset to user temporary stack (used when cloning) - pub const USER_TMP_STACK_OFFSET: usize = USER_TMP_GRANT_OFFSET + PML4_SIZE; - - /// Offset to user temporary tls (used when cloning) - pub const USER_TMP_TLS_OFFSET: usize = USER_TMP_STACK_OFFSET + PML4_SIZE; - - /// Offset for usage in other temporary pages - pub const USER_TMP_MISC_OFFSET: usize = USER_TMP_TLS_OFFSET + PML4_SIZE; - - -/// Print to console -#[macro_export] -macro_rules! print { - ($($arg:tt)*) => ({ - use core::fmt::Write; - let _ = write!($crate::console::CONSOLE.lock(), $($arg)*); - }); -} - -/// Print with new line to console -#[macro_export] -macro_rules! println { - ($fmt:expr) => (print!(concat!($fmt, "\n"))); - ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); -} - -/// Create an interrupt function that can safely run rust code -#[macro_export] -macro_rules! interrupt { - ($name:ident, $func:block) => { - #[naked] - pub unsafe extern fn $name () { - #[inline(never)] - unsafe fn inner() { - $func - } - - // Push scratch registers - asm!("push rax - push rcx - push rdx - push rdi - push rsi - push r8 - push r9 - push r10 - push r11 - push fs - mov rax, 0x18 - mov fs, ax" - : : : : "intel", "volatile"); - - // Call inner rust function - inner(); - - // Pop scratch registers and return - asm!("pop fs - pop r11 - pop r10 - pop r9 - pop r8 - pop rsi - pop rdi - pop rdx - pop rcx - pop rax - iretq" - : : : : "intel", "volatile"); - } - }; -} - -#[repr(packed)] -pub struct InterruptStack { - fs: usize, - r11: usize, - r10: usize, - r9: usize, - r8: usize, - rsi: usize, - rdi: usize, - rdx: usize, - rcx: usize, - rax: usize, - rip: usize, - cs: usize, - rflags: usize, -} - -#[macro_export] -macro_rules! interrupt_stack { - ($name:ident, $stack: ident, $func:block) => { - #[naked] - pub unsafe extern fn $name () { - #[inline(never)] - unsafe fn inner($stack: &$crate::InterruptStack) { - $func - } - - // Push scratch registers - asm!("push rax - push rcx - push rdx - push rdi - push rsi - push r8 - push r9 - push r10 - push r11 - push fs - mov rax, 0x18 - mov fs, ax" - : : : : "intel", "volatile"); - - // Get reference to stack variables - let rsp: usize; - asm!("" : "={rsp}"(rsp) : : : "intel", "volatile"); - - // Call inner rust function - inner(&*(rsp as *const $crate::InterruptStack)); - - // Pop scratch registers and return - asm!("pop fs - pop r11 - pop r10 - pop r9 - pop r8 - pop rsi - pop rdi - pop rdx - pop rcx - pop rax - iretq" - : : : : "intel", "volatile"); - } - }; -} - -#[repr(packed)] -pub struct InterruptErrorStack { - fs: usize, - r11: usize, - r10: usize, - r9: usize, - r8: usize, - rsi: usize, - rdi: usize, - rdx: usize, - rcx: usize, - rax: usize, - code: usize, - rip: usize, - cs: usize, - rflags: usize, -} - -#[macro_export] -macro_rules! interrupt_error { - ($name:ident, $stack:ident, $func:block) => { - #[naked] - pub unsafe extern fn $name () { - #[inline(never)] - unsafe fn inner($stack: &$crate::InterruptErrorStack) { - $func - } - - // Push scratch registers - asm!("push rax - push rcx - push rdx - push rdi - push rsi - push r8 - push r9 - push r10 - push r11 - push fs - mov rax, 0x18 - mov fs, ax" - : : : : "intel", "volatile"); - - // Get reference to stack variables - let rsp: usize; - asm!("" : "={rsp}"(rsp) : : : "intel", "volatile"); - - // Call inner rust function - inner(&*(rsp as *const $crate::InterruptErrorStack)); - - // Pop scratch registers, error code, and return - asm!("pop fs - pop r11 - pop r10 - pop r9 - pop r8 - pop rsi - pop rdi - pop rdx - pop rcx - pop rax - add rsp, 8 - iretq" - : : : : "intel", "volatile"); - } - }; -} - -/// ACPI table parsing -pub mod acpi; - -/// Console handling -pub mod console; - -/// Context switching -pub mod context; - -/// Devices -pub mod device; - -/// Memcpy, memmove, etc. -pub mod externs; - -/// Global descriptor table -pub mod gdt; - -/// Interrupt descriptor table -pub mod idt; - -/// Interrupt instructions -pub mod interrupt; - -/// Memory management -pub mod memory; - -/// Paging -pub mod paging; - -/// Panic -pub mod panic; - -/// Initialization and start function -pub mod start; - -/// Shutdown function -pub mod stop; - -/// Time -pub mod time; diff --git a/kernel/arch/x86_64/src/linker.ld b/kernel/arch/x86_64/src/linker.ld deleted file mode 100644 index 546adaa..0000000 --- a/kernel/arch/x86_64/src/linker.ld +++ /dev/null @@ -1,63 +0,0 @@ -ENTRY(kstart) -OUTPUT_FORMAT(elf64-x86-64) - -KERNEL_OFFSET = 0xffffff0000100000; -/* KERNEL_OFFSET = 0x100000; */ - -SECTIONS { - . = KERNEL_OFFSET; - - . += SIZEOF_HEADERS; - . = ALIGN(4096); - - .text : AT(ADDR(.text) - KERNEL_OFFSET) { - __text_start = .; - *(.text*) - . = ALIGN(4096); - __text_end = .; - } - - .rodata : AT(ADDR(.rodata) - KERNEL_OFFSET) { - __rodata_start = .; - *(.rodata*) - . = ALIGN(4096); - __rodata_end = .; - } - - .data : AT(ADDR(.data) - KERNEL_OFFSET) { - __data_start = .; - *(.data*) - . = ALIGN(4096); - __data_end = .; - } - - .tdata : AT(ADDR(.tdata) - KERNEL_OFFSET) { - __tdata_start = .; - *(.tdata*) - . = ALIGN(4096); - __tdata_end = .; - __tbss_start = .; - *(.tbss*) - . += 8; - . = ALIGN(4096); - __tbss_end = .; - } - - .bss : AT(ADDR(.bss) - KERNEL_OFFSET) { - __bss_start = .; - *(.bss*) - . = ALIGN(4096); - __bss_end = .; - } - - __end = .; - - /DISCARD/ : { - *(.comment*) - *(.debug*) - *(.eh_frame*) - *(.gcc_except_table*) - *(.note*) - *(.rel.eh_frame*) - } -} diff --git a/kernel/arch/x86_64/src/memory/area_frame_allocator.rs b/kernel/arch/x86_64/src/memory/area_frame_allocator.rs deleted file mode 100644 index e25f22a..0000000 --- a/kernel/arch/x86_64/src/memory/area_frame_allocator.rs +++ /dev/null @@ -1,127 +0,0 @@ -//! # Area frame allocator -//! Some code was borrowed from [Phil Opp's Blog](http://os.phil-opp.com/allocating-frames.html) - -use paging::PhysicalAddress; - -use super::{Frame, FrameAllocator, MemoryArea, MemoryAreaIter}; - - -pub struct AreaFrameAllocator { - next_free_frame: Frame, - current_area: Option<&'static MemoryArea>, - areas: MemoryAreaIter, - kernel_start: Frame, - kernel_end: Frame -} - -impl AreaFrameAllocator { - pub fn new(kernel_start: usize, kernel_end: usize, memory_areas: MemoryAreaIter) -> AreaFrameAllocator { - let mut allocator = AreaFrameAllocator { - next_free_frame: Frame::containing_address(PhysicalAddress::new(0)), - current_area: None, - areas: memory_areas, - kernel_start: Frame::containing_address(PhysicalAddress::new(kernel_start)), - kernel_end: Frame::containing_address(PhysicalAddress::new(kernel_end)) - }; - allocator.choose_next_area(); - allocator - } - - fn choose_next_area(&mut self) { - self.current_area = self.areas.clone().filter(|area| { - let address = area.base_addr + area.length - 1; - Frame::containing_address(PhysicalAddress::new(address as usize)) >= self.next_free_frame - }).min_by_key(|area| area.base_addr); - - if let Some(area) = self.current_area { - let start_frame = Frame::containing_address(PhysicalAddress::new(area.base_addr as usize)); - if self.next_free_frame < start_frame { - self.next_free_frame = start_frame; - } - } - } -} - -impl FrameAllocator for AreaFrameAllocator { - fn free_frames(&self) -> usize { - let mut count = 0; - - for area in self.areas.clone() { - let start_frame = Frame::containing_address(PhysicalAddress::new(area.base_addr as usize)); - let end_frame = Frame::containing_address(PhysicalAddress::new((area.base_addr + area.length - 1) as usize)); - for frame in Frame::range_inclusive(start_frame, end_frame) { - if frame >= self.kernel_start && frame <= self.kernel_end { - // Inside of kernel range - } else if frame >= self.next_free_frame { - // Frame is in free range - count += 1; - } else { - // Inside of used range - } - } - } - - count - } - - fn used_frames(&self) -> usize { - let mut count = 0; - - for area in self.areas.clone() { - let start_frame = Frame::containing_address(PhysicalAddress::new(area.base_addr as usize)); - let end_frame = Frame::containing_address(PhysicalAddress::new((area.base_addr + area.length - 1) as usize)); - for frame in Frame::range_inclusive(start_frame, end_frame) { - if frame >= self.kernel_start && frame <= self.kernel_end { - // Inside of kernel range - count += 1 - } else if frame >= self.next_free_frame { - // Frame is in free range - } else { - count += 1; - } - } - } - - count - } - - fn allocate_frames(&mut self, count: usize) -> Option { - if count == 0 { - None - } else if let Some(area) = self.current_area { - // "Clone" the frame to return it if it's free. Frame doesn't - // implement Clone, but we can construct an identical frame. - let start_frame = Frame{ number: self.next_free_frame.number }; - let end_frame = Frame { number: self.next_free_frame.number + (count - 1) }; - - // the last frame of the current area - let current_area_last_frame = { - let address = area.base_addr + area.length - 1; - Frame::containing_address(PhysicalAddress::new(address as usize)) - }; - - if end_frame > current_area_last_frame { - // all frames of current area are used, switch to next area - self.choose_next_area(); - } else if (start_frame >= self.kernel_start && start_frame <= self.kernel_end) - || (end_frame >= self.kernel_start && end_frame <= self.kernel_end) { - // `frame` is used by the kernel - self.next_free_frame = Frame { - number: self.kernel_end.number + 1 - }; - } else { - // frame is unused, increment `next_free_frame` and return it - self.next_free_frame.number += count; - return Some(start_frame); - } - // `frame` was not valid, try it again with the updated `next_free_frame` - self.allocate_frames(count) - } else { - None // no free frames left - } - } - - fn deallocate_frames(&mut self, frame: Frame, count: usize) { - //panic!("AreaFrameAllocator::deallocate_frame: not supported: {:?}", frame); - } -} diff --git a/kernel/arch/x86_64/src/memory/mod.rs b/kernel/arch/x86_64/src/memory/mod.rs deleted file mode 100644 index 17b2200..0000000 --- a/kernel/arch/x86_64/src/memory/mod.rs +++ /dev/null @@ -1,189 +0,0 @@ -//! # Memory management -//! Some code was borrowed from [Phil Opp's Blog](http://os.phil-opp.com/allocating-frames.html) - -pub use paging::{PAGE_SIZE, PhysicalAddress}; - -use self::area_frame_allocator::AreaFrameAllocator; - -use spin::Mutex; - -pub mod area_frame_allocator; - -/// The current memory map. It's size is maxed out to 512 entries, due to it being -/// from 0x500 to 0x5000 (800 is the absolute total) -static mut MEMORY_MAP: [MemoryArea; 512] = [MemoryArea { base_addr: 0, length: 0, _type: 0, acpi: 0 }; 512]; - -/// Memory does not exist -pub const MEMORY_AREA_NULL: u32 = 0; - -/// Memory is free to use -pub const MEMORY_AREA_FREE: u32 = 1; - -/// Memory is reserved -pub const MEMORY_AREA_RESERVED: u32 = 2; - -/// Memory is used by ACPI, and can be reclaimed -pub const MEMORY_AREA_ACPI: u32 = 3; - -/// A memory map area -#[derive(Copy, Clone, Debug, Default)] -#[repr(packed)] -pub struct MemoryArea { - pub base_addr: u64, - pub length: u64, - pub _type: u32, - pub acpi: u32 -} - -#[derive(Clone)] -pub struct MemoryAreaIter { - _type: u32, - i: usize -} - -impl MemoryAreaIter { - fn new(_type: u32) -> Self { - MemoryAreaIter { - _type: _type, - i: 0 - } - } -} - -impl Iterator for MemoryAreaIter { - type Item = &'static MemoryArea; - fn next(&mut self) -> Option { - while self.i < unsafe { MEMORY_MAP.len() } { - let entry = unsafe { &MEMORY_MAP[self.i] }; - self.i += 1; - if entry._type == self._type { - return Some(entry); - } - } - None - } -} - -static ALLOCATOR: Mutex> = Mutex::new(None); - -/// Init memory module -/// Must be called once, and only once, -pub unsafe fn init(kernel_start: usize, kernel_end: usize) { - // Copy memory map from bootloader location - for (i, mut entry) in MEMORY_MAP.iter_mut().enumerate() { - *entry = *(0x500 as *const MemoryArea).offset(i as isize); - if entry._type != MEMORY_AREA_NULL { - println!("{:?}", entry); - } - } - - *ALLOCATOR.lock() = Some(AreaFrameAllocator::new(kernel_start, kernel_end, MemoryAreaIter::new(MEMORY_AREA_FREE))); -} - -/// Allocate a frame -pub fn allocate_frame() -> Option { - allocate_frames(1) -} - -/// Deallocate a frame -pub fn deallocate_frame(frame: Frame) { - deallocate_frames(frame, 1) -} - -/// Get the number of frames available -pub fn free_frames() -> usize { - if let Some(ref allocator) = *ALLOCATOR.lock() { - allocator.free_frames() - } else { - panic!("frame allocator not initialized"); - } -} - -/// Get the number of frames used -pub fn used_frames() -> usize { - if let Some(ref allocator) = *ALLOCATOR.lock() { - allocator.used_frames() - } else { - panic!("frame allocator not initialized"); - } -} - -/// Allocate a range of frames -pub fn allocate_frames(count: usize) -> Option { - if let Some(ref mut allocator) = *ALLOCATOR.lock() { - allocator.allocate_frames(count) - } else { - panic!("frame allocator not initialized"); - } -} - -/// Deallocate a range of frames frame -pub fn deallocate_frames(frame: Frame, count: usize) { - if let Some(ref mut allocator) = *ALLOCATOR.lock() { - allocator.deallocate_frames(frame, count) - } else { - panic!("frame allocator not initialized"); - } -} - -/// A frame, allocated by the frame allocator. -/// Do not add more derives, or make anything `pub`! -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] -pub struct Frame { - number: usize -} - -impl Frame { - /// Get the address of this frame - pub fn start_address(&self) -> PhysicalAddress { - PhysicalAddress::new(self.number * PAGE_SIZE) - } - - //TODO: Set private - pub fn clone(&self) -> Frame { - Frame { - number: self.number - } - } - - /// Create a frame containing `address` - pub fn containing_address(address: PhysicalAddress) -> Frame { - Frame { - number: address.get() / PAGE_SIZE - } - } - - //TODO: Set private - pub fn range_inclusive(start: Frame, end: Frame) -> FrameIter { - FrameIter { - start: start, - end: end, - } - } -} - -pub struct FrameIter { - start: Frame, - end: Frame, -} - -impl Iterator for FrameIter { - type Item = Frame; - - fn next(&mut self) -> Option { - if self.start <= self.end { - let frame = self.start.clone(); - self.start.number += 1; - Some(frame) - } else { - None - } - } -} - -pub trait FrameAllocator { - fn free_frames(&self) -> usize; - fn used_frames(&self) -> usize; - fn allocate_frames(&mut self, size: usize) -> Option; - fn deallocate_frames(&mut self, frame: Frame, size: usize); -} diff --git a/kernel/arch/x86_64/src/paging/entry.rs b/kernel/arch/x86_64/src/paging/entry.rs deleted file mode 100644 index aecf647..0000000 --- a/kernel/arch/x86_64/src/paging/entry.rs +++ /dev/null @@ -1,62 +0,0 @@ -//! # Page table entry -//! Some code borrowed from [Phil Opp's Blog](http://os.phil-opp.com/modifying-page-tables.html) - -use memory::Frame; - -use super::PhysicalAddress; - -/// A page table entry -pub struct Entry(u64); - -bitflags! { - pub flags EntryFlags: u64 { - const PRESENT = 1 << 0, - const WRITABLE = 1 << 1, - const USER_ACCESSIBLE = 1 << 2, - const WRITE_THROUGH = 1 << 3, - const NO_CACHE = 1 << 4, - const ACCESSED = 1 << 5, - const DIRTY = 1 << 6, - const HUGE_PAGE = 1 << 7, - const GLOBAL = 1 << 8, - const NO_EXECUTE = 1 << 63, - } -} - -pub const ADDRESS_MASK: usize = 0x000f_ffff_ffff_f000; - -impl Entry { - /// Is the entry unused? - pub fn is_unused(&self) -> bool { - self.0 == 0 - } - - /// Make the entry unused - pub fn set_unused(&mut self) { - self.0 = 0; - } - - /// Get the address this page references - pub fn address(&self) -> PhysicalAddress { - PhysicalAddress::new(self.0 as usize & ADDRESS_MASK) - } - - /// Get the current entry flags - pub fn flags(&self) -> EntryFlags { - EntryFlags::from_bits_truncate(self.0) - } - - /// Get the associated frame, if available - pub fn pointed_frame(&self) -> Option { - if self.flags().contains(PRESENT) { - Some(Frame::containing_address(self.address())) - } else { - None - } - } - - pub fn set(&mut self, frame: Frame, flags: EntryFlags) { - debug_assert!(frame.start_address().get() & !ADDRESS_MASK == 0); - self.0 = (frame.start_address().get() as u64) | flags.bits(); - } -} diff --git a/kernel/arch/x86_64/src/paging/mapper.rs b/kernel/arch/x86_64/src/paging/mapper.rs deleted file mode 100644 index b18e7a5..0000000 --- a/kernel/arch/x86_64/src/paging/mapper.rs +++ /dev/null @@ -1,182 +0,0 @@ -use core::mem; -use core::ptr::Unique; - -use memory::{allocate_frame, deallocate_frame, Frame}; - -use super::{ActivePageTable, Page, PAGE_SIZE, PhysicalAddress, VirtualAddress}; -use super::entry::{self, EntryFlags}; -use super::table::{self, Table, Level4}; - -/// In order to enforce correct paging operations in the kernel, these types -/// are returned on any mapping operation to get the code involved to specify -/// how it intends to flush changes to a page table -#[must_use = "The page table must be flushed, or the changes unsafely ignored"] -pub struct MapperFlush(Page); - -impl MapperFlush { - /// Create a new page flush promise - pub fn new(page: Page) -> MapperFlush { - MapperFlush(page) - } - - /// Flush this page in the active table - pub fn flush(self, table: &mut ActivePageTable) { - table.flush(self.0); - mem::forget(self); - } - - /// Ignore the flush. This is unsafe, and a reason should be provided for use - pub unsafe fn ignore(self) { - mem::forget(self); - } -} - -/// A flush cannot be dropped, it must be consumed -impl Drop for MapperFlush { - fn drop(&mut self) { - panic!("Mapper flush was not utilized"); - } -} - -/// To allow for combining multiple flushes into one, we have a way of flushing -/// the active table, which can consume MapperFlush structs -#[must_use = "The page table must be flushed, or the changes unsafely ignored"] -pub struct MapperFlushAll(bool); - -impl MapperFlushAll { - /// Create a new promise to flush all mappings - pub fn new() -> MapperFlushAll { - MapperFlushAll(false) - } - - /// Consume a single page flush - pub fn consume(&mut self, flush: MapperFlush) { - self.0 = true; - mem::forget(flush); - } - - /// Flush the active page table - pub fn flush(self, table: &mut ActivePageTable) { - if self.0 { - table.flush_all(); - } - mem::forget(self); - } - - /// Ignore the flush. This is unsafe, and a reason should be provided for use - pub unsafe fn ignore(self) { - mem::forget(self); - } -} - -/// A flush cannot be dropped, it must be consumed -impl Drop for MapperFlushAll { - fn drop(&mut self) { - panic!("Mapper flush all was not utilized"); - } -} - -pub struct Mapper { - p4: Unique>, -} - -impl Mapper { - /// Create a new page table - pub unsafe fn new() -> Mapper { - Mapper { - p4: Unique::new(table::P4), - } - } - - pub fn p4(&self) -> &Table { - unsafe { self.p4.get() } - } - - pub fn p4_mut(&mut self) -> &mut Table { - unsafe { self.p4.get_mut() } - } - - /// Map a page to a frame - pub fn map_to(&mut self, page: Page, frame: Frame, flags: EntryFlags) -> MapperFlush { - let mut p3 = self.p4_mut().next_table_create(page.p4_index()); - let mut p2 = p3.next_table_create(page.p3_index()); - let mut p1 = p2.next_table_create(page.p2_index()); - - assert!(p1[page.p1_index()].is_unused(), - "{:X}: Set to {:X}: {:?}, requesting {:X}: {:?}", - page.start_address().get(), - p1[page.p1_index()].address().get(), p1[page.p1_index()].flags(), - frame.start_address().get(), flags); - p1[page.p1_index()].set(frame, flags | entry::PRESENT); - MapperFlush::new(page) - } - - /// Map a page to the next free frame - pub fn map(&mut self, page: Page, flags: EntryFlags) -> MapperFlush { - let frame = allocate_frame().expect("out of frames"); - self.map_to(page, frame, flags) - } - - /// Update flags for a page - pub fn remap(&mut self, page: Page, flags: EntryFlags) -> MapperFlush { - let mut p3 = self.p4_mut().next_table_mut(page.p4_index()).expect("failed to remap: no p3"); - let mut p2 = p3.next_table_mut(page.p3_index()).expect("failed to remap: no p2"); - let mut p1 = p2.next_table_mut(page.p2_index()).expect("failed to remap: no p1"); - let frame = p1[page.p1_index()].pointed_frame().expect("failed to remap: not mapped"); - p1[page.p1_index()].set(frame, flags | entry::PRESENT); - MapperFlush::new(page) - } - - /// Identity map a frame - pub fn identity_map(&mut self, frame: Frame, flags: EntryFlags) -> MapperFlush { - let page = Page::containing_address(VirtualAddress::new(frame.start_address().get())); - self.map_to(page, frame, flags) - } - - /// Unmap a page - pub fn unmap(&mut self, page: Page) -> MapperFlush { - let p1 = self.p4_mut() - .next_table_mut(page.p4_index()) - .and_then(|p3| p3.next_table_mut(page.p3_index())) - .and_then(|p2| p2.next_table_mut(page.p2_index())) - .expect("unmap does not support huge pages"); - let frame = p1[page.p1_index()].pointed_frame().unwrap(); - p1[page.p1_index()].set_unused(); - // TODO free p(1,2,3) table if empty - deallocate_frame(frame); - MapperFlush::new(page) - } - - /// Unmap a page, return frame without free - pub fn unmap_return(&mut self, page: Page) -> (MapperFlush, Frame) { - let p1 = self.p4_mut() - .next_table_mut(page.p4_index()) - .and_then(|p3| p3.next_table_mut(page.p3_index())) - .and_then(|p2| p2.next_table_mut(page.p2_index())) - .expect("unmap_return does not support huge pages"); - let frame = p1[page.p1_index()].pointed_frame().unwrap(); - p1[page.p1_index()].set_unused(); - (MapperFlush::new(page), frame) - } - - pub fn translate_page(&self, page: Page) -> Option { - self.p4().next_table(page.p4_index()) - .and_then(|p3| p3.next_table(page.p3_index())) - .and_then(|p2| p2.next_table(page.p2_index())) - .and_then(|p1| p1[page.p1_index()].pointed_frame()) - } - - pub fn translate_page_flags(&self, page: Page) -> Option { - self.p4().next_table(page.p4_index()) - .and_then(|p3| p3.next_table(page.p3_index())) - .and_then(|p2| p2.next_table(page.p2_index())) - .and_then(|p1| Some(p1[page.p1_index()].flags())) - } - - /// Translate a virtual address to a physical one - pub fn translate(&self, virtual_address: VirtualAddress) -> Option { - let offset = virtual_address.get() % PAGE_SIZE; - self.translate_page(Page::containing_address(virtual_address)) - .map(|frame| PhysicalAddress::new(frame.start_address().get() + offset)) - } -} diff --git a/kernel/arch/x86_64/src/paging/mod.rs b/kernel/arch/x86_64/src/paging/mod.rs deleted file mode 100644 index 6c133e1..0000000 --- a/kernel/arch/x86_64/src/paging/mod.rs +++ /dev/null @@ -1,429 +0,0 @@ -//! # Paging -//! Some code was borrowed from [Phil Opp's Blog](http://os.phil-opp.com/modifying-page-tables.html) - -use core::mem; -use core::ops::{Deref, DerefMut}; -use x86::{msr, tlb}; - -use memory::{allocate_frame, Frame}; - -use self::entry::{EntryFlags, PRESENT, GLOBAL, WRITABLE, NO_EXECUTE}; -use self::mapper::Mapper; -use self::temporary_page::TemporaryPage; - -pub mod entry; -pub mod mapper; -pub mod table; -pub mod temporary_page; - -/// Number of entries per page table -pub const ENTRY_COUNT: usize = 512; - -/// Size of pages -pub const PAGE_SIZE: usize = 4096; - -/// Setup page attribute table -unsafe fn init_pat() { - let uncacheable = 0; - let write_combining = 1; - let write_through = 4; - //let write_protected = 5; - let write_back = 6; - let uncached = 7; - - let pat0 = write_back; - let pat1 = write_through; - let pat2 = uncached; - let pat3 = uncacheable; - - let pat4 = write_combining; - let pat5 = pat1; - let pat6 = pat2; - let pat7 = pat3; - - msr::wrmsr(msr::IA32_PAT, pat7 << 56 | pat6 << 48 | pat5 << 40 | pat4 << 32 - | pat3 << 24 | pat2 << 16 | pat1 << 8 | pat0); -} - -/// Copy tdata, clear tbss, set TCB self pointer -unsafe fn init_tcb(cpu_id: usize) -> usize { - extern { - /// The starting byte of the thread data segment - static mut __tdata_start: u8; - /// The ending byte of the thread data segment - static mut __tdata_end: u8; - /// The starting byte of the thread BSS segment - static mut __tbss_start: u8; - /// The ending byte of the thread BSS segment - static mut __tbss_end: u8; - } - - let tcb_offset; - { - let size = & __tbss_end as *const _ as usize - & __tdata_start as *const _ as usize; - let tbss_offset = & __tbss_start as *const _ as usize - & __tdata_start as *const _ as usize; - - let start = ::KERNEL_PERCPU_OFFSET + ::KERNEL_PERCPU_SIZE * cpu_id; - let end = start + size; - tcb_offset = end - mem::size_of::(); - - ::externs::memcpy(start as *mut u8, & __tdata_start as *const u8, tbss_offset); - ::externs::memset((start + tbss_offset) as *mut u8, 0, size - tbss_offset); - - *(tcb_offset as *mut usize) = end; - } - tcb_offset -} - -/// Initialize paging -/// -/// Returns page table and thread control block offset -pub unsafe fn init(cpu_id: usize, stack_start: usize, stack_end: usize) -> (ActivePageTable, usize) { - extern { - /// The starting byte of the text (code) data segment. - static mut __text_start: u8; - /// The ending byte of the text (code) data segment. - static mut __text_end: u8; - /// The starting byte of the _.rodata_ (read-only data) segment. - static mut __rodata_start: u8; - /// The ending byte of the _.rodata_ (read-only data) segment. - static mut __rodata_end: u8; - /// The starting byte of the _.data_ segment. - static mut __data_start: u8; - /// The ending byte of the _.data_ segment. - static mut __data_end: u8; - /// The starting byte of the thread data segment - static mut __tdata_start: u8; - /// The ending byte of the thread data segment - static mut __tdata_end: u8; - /// The starting byte of the thread BSS segment - static mut __tbss_start: u8; - /// The ending byte of the thread BSS segment - static mut __tbss_end: u8; - /// The starting byte of the _.bss_ (uninitialized data) segment. - static mut __bss_start: u8; - /// The ending byte of the _.bss_ (uninitialized data) segment. - static mut __bss_end: u8; - } - - init_pat(); - - let mut active_table = ActivePageTable::new(); - - let mut temporary_page = TemporaryPage::new(Page::containing_address(VirtualAddress::new(::USER_TMP_MISC_OFFSET))); - - let mut new_table = { - let frame = allocate_frame().expect("no more frames in paging::init new_table"); - InactivePageTable::new(frame, &mut active_table, &mut temporary_page) - }; - - active_table.with(&mut new_table, &mut temporary_page, |mapper| { - // Map tdata and tbss - { - let size = & __tbss_end as *const _ as usize - & __tdata_start as *const _ as usize; - - let start = ::KERNEL_PERCPU_OFFSET + ::KERNEL_PERCPU_SIZE * cpu_id; - let end = start + size; - - let start_page = Page::containing_address(VirtualAddress::new(start)); - let end_page = Page::containing_address(VirtualAddress::new(end - 1)); - for page in Page::range_inclusive(start_page, end_page) { - let result = mapper.map(page, PRESENT | GLOBAL | NO_EXECUTE | WRITABLE); - // The flush can be ignored as this is not the active table. See later active_table.switch - unsafe { result.ignore(); } - } - } - - let mut remap = |start: usize, end: usize, flags: EntryFlags| { - if end > start { - let start_frame = Frame::containing_address(PhysicalAddress::new(start)); - let end_frame = Frame::containing_address(PhysicalAddress::new(end - 1)); - for frame in Frame::range_inclusive(start_frame, end_frame) { - let page = Page::containing_address(VirtualAddress::new(frame.start_address().get() + ::KERNEL_OFFSET)); - let result = mapper.map_to(page, frame, flags); - // The flush can be ignored as this is not the active table. See later active_table.switch - unsafe { result.ignore(); } - } - } - }; - - // Remap stack writable, no execute - remap(stack_start - ::KERNEL_OFFSET, stack_end - ::KERNEL_OFFSET, PRESENT | GLOBAL | NO_EXECUTE | WRITABLE); - - // Remap a section with `flags` - let mut remap_section = |start: &u8, end: &u8, flags: EntryFlags| { - remap(start as *const _ as usize - ::KERNEL_OFFSET, end as *const _ as usize - ::KERNEL_OFFSET, flags); - }; - // Remap text read-only - remap_section(& __text_start, & __text_end, PRESENT | GLOBAL); - // Remap rodata read-only, no execute - remap_section(& __rodata_start, & __rodata_end, PRESENT | GLOBAL | NO_EXECUTE); - // Remap data writable, no execute - remap_section(& __data_start, & __data_end, PRESENT | GLOBAL | NO_EXECUTE | WRITABLE); - // Remap tdata master writable, no execute - remap_section(& __tdata_start, & __tdata_end, PRESENT | GLOBAL | NO_EXECUTE); - // Remap bss writable, no execute - remap_section(& __bss_start, & __bss_end, PRESENT | GLOBAL | NO_EXECUTE | WRITABLE); - }); - - // This switches the active table, which is setup by the bootloader, to a correct table - // setup by the lambda above. This will also flush the TLB - active_table.switch(new_table); - - (active_table, init_tcb(cpu_id)) -} - -pub unsafe fn init_ap(cpu_id: usize, bsp_table: usize, stack_start: usize, stack_end: usize) -> usize { - extern { - /// The starting byte of the thread data segment - static mut __tdata_start: u8; - /// The ending byte of the thread data segment - static mut __tdata_end: u8; - /// The starting byte of the thread BSS segment - static mut __tbss_start: u8; - /// The ending byte of the thread BSS segment - static mut __tbss_end: u8; - } - - init_pat(); - - let mut active_table = ActivePageTable::new(); - - let mut new_table = InactivePageTable::from_address(bsp_table); - - let mut temporary_page = TemporaryPage::new(Page::containing_address(VirtualAddress::new(::USER_TMP_MISC_OFFSET))); - - active_table.with(&mut new_table, &mut temporary_page, |mapper| { - // Map tdata and tbss - { - let size = & __tbss_end as *const _ as usize - & __tdata_start as *const _ as usize; - - let start = ::KERNEL_PERCPU_OFFSET + ::KERNEL_PERCPU_SIZE * cpu_id; - let end = start + size; - - let start_page = Page::containing_address(VirtualAddress::new(start)); - let end_page = Page::containing_address(VirtualAddress::new(end - 1)); - for page in Page::range_inclusive(start_page, end_page) { - let result = mapper.map(page, PRESENT | GLOBAL | NO_EXECUTE | WRITABLE); - // The flush can be ignored as this is not the active table. See later active_table.switch - unsafe { result.ignore(); } - } - } - - let mut remap = |start: usize, end: usize, flags: EntryFlags| { - if end > start { - let start_frame = Frame::containing_address(PhysicalAddress::new(start)); - let end_frame = Frame::containing_address(PhysicalAddress::new(end - 1)); - for frame in Frame::range_inclusive(start_frame, end_frame) { - let page = Page::containing_address(VirtualAddress::new(frame.start_address().get() + ::KERNEL_OFFSET)); - let result = mapper.map_to(page, frame, flags); - // The flush can be ignored as this is not the active table. See later active_table.switch - unsafe { result.ignore(); } - } - } - }; - - // Remap stack writable, no execute - remap(stack_start - ::KERNEL_OFFSET, stack_end - ::KERNEL_OFFSET, PRESENT | GLOBAL | NO_EXECUTE | WRITABLE); - }); - - // This switches the active table, which is setup by the bootloader, to a correct table - // setup by the lambda above. This will also flush the TLB - active_table.switch(new_table); - - init_tcb(cpu_id) -} - -pub struct ActivePageTable { - mapper: Mapper, -} - -impl Deref for ActivePageTable { - type Target = Mapper; - - fn deref(&self) -> &Mapper { - &self.mapper - } -} - -impl DerefMut for ActivePageTable { - fn deref_mut(&mut self) -> &mut Mapper { - &mut self.mapper - } -} - -impl ActivePageTable { - pub unsafe fn new() -> ActivePageTable { - ActivePageTable { - mapper: Mapper::new(), - } - } - - pub fn switch(&mut self, new_table: InactivePageTable) -> InactivePageTable { - use x86::controlregs; - - let old_table = InactivePageTable { - p4_frame: Frame::containing_address( - PhysicalAddress::new(unsafe { controlregs::cr3() } as usize) - ), - }; - unsafe { - controlregs::cr3_write(new_table.p4_frame.start_address().get() as u64); - } - old_table - } - - pub fn flush(&mut self, page: Page) { - unsafe { tlb::flush(page.start_address().get()); } - } - - pub fn flush_all(&mut self) { - unsafe { tlb::flush_all(); } - } - - pub fn with(&mut self, table: &mut InactivePageTable, temporary_page: &mut temporary_page::TemporaryPage, f: F) - where F: FnOnce(&mut Mapper) - { - use x86::controlregs; - - { - let backup = Frame::containing_address(PhysicalAddress::new(unsafe { controlregs::cr3() as usize })); - - // map temporary_page to current p4 table - let p4_table = temporary_page.map_table_frame(backup.clone(), PRESENT | WRITABLE | NO_EXECUTE, self); - - // overwrite recursive mapping - self.p4_mut()[511].set(table.p4_frame.clone(), PRESENT | WRITABLE | NO_EXECUTE); - self.flush_all(); - - // execute f in the new context - f(self); - - // restore recursive mapping to original p4 table - p4_table[511].set(backup, PRESENT | WRITABLE | NO_EXECUTE); - self.flush_all(); - } - - temporary_page.unmap(self); - } - - pub unsafe fn address(&self) -> usize { - use x86::controlregs; - controlregs::cr3() as usize - } -} - -pub struct InactivePageTable { - p4_frame: Frame, -} - -impl InactivePageTable { - pub fn new(frame: Frame, active_table: &mut ActivePageTable, temporary_page: &mut TemporaryPage) -> InactivePageTable { - { - let table = temporary_page.map_table_frame(frame.clone(), PRESENT | WRITABLE | NO_EXECUTE, active_table); - // now we are able to zero the table - table.zero(); - // set up recursive mapping for the table - table[511].set(frame.clone(), PRESENT | WRITABLE | NO_EXECUTE); - } - temporary_page.unmap(active_table); - - InactivePageTable { p4_frame: frame } - } - - pub unsafe fn from_address(cr3: usize) -> InactivePageTable { - InactivePageTable { p4_frame: Frame::containing_address(PhysicalAddress::new(cr3)) } - } - - pub unsafe fn address(&self) -> usize { - self.p4_frame.start_address().get() - } -} - -/// A physical address. -#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] -pub struct PhysicalAddress(usize); - -impl PhysicalAddress { - pub fn new(address: usize) -> Self { - PhysicalAddress(address) - } - - pub fn get(&self) -> usize { - self.0 - } -} - -/// A virtual address. -#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] -pub struct VirtualAddress(usize); - -impl VirtualAddress { - pub fn new(address: usize) -> Self { - VirtualAddress(address) - } - - pub fn get(&self) -> usize { - self.0 - } -} - -/// Page -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -pub struct Page { - number: usize -} - -impl Page { - pub fn start_address(&self) -> VirtualAddress { - VirtualAddress::new(self.number * PAGE_SIZE) - } - - pub fn p4_index(&self) -> usize { - (self.number >> 27) & 0o777 - } - - pub fn p3_index(&self) -> usize { - (self.number >> 18) & 0o777 - } - - pub fn p2_index(&self) -> usize { - (self.number >> 9) & 0o777 - } - - pub fn p1_index(&self) -> usize { - (self.number >> 0) & 0o777 - } - - pub fn containing_address(address: VirtualAddress) -> Page { - //TODO assert!(address.get() < 0x0000_8000_0000_0000 || address.get() >= 0xffff_8000_0000_0000, - // "invalid address: 0x{:x}", address.get()); - Page { number: address.get() / PAGE_SIZE } - } - - pub fn range_inclusive(start: Page, end: Page) -> PageIter { - PageIter { - start: start, - end: end, - } - } -} - -pub struct PageIter { - start: Page, - end: Page, -} - -impl Iterator for PageIter { - type Item = Page; - - fn next(&mut self) -> Option { - if self.start <= self.end { - let page = self.start; - self.start.number += 1; - Some(page) - } else { - None - } - } -} diff --git a/kernel/arch/x86_64/src/paging/table.rs b/kernel/arch/x86_64/src/paging/table.rs deleted file mode 100644 index c28db79..0000000 --- a/kernel/arch/x86_64/src/paging/table.rs +++ /dev/null @@ -1,98 +0,0 @@ -//! # Page table -//! Code borrowed from [Phil Opp's Blog](http://os.phil-opp.com/modifying-page-tables.html) - -use core::marker::PhantomData; -use core::ops::{Index, IndexMut}; - -use memory::allocate_frame; - -use super::entry::*; -use super::ENTRY_COUNT; - -pub const P4: *mut Table = 0xffff_ffff_ffff_f000 as *mut _; - -pub trait TableLevel {} - -pub enum Level4 {} -pub enum Level3 {} -pub enum Level2 {} -pub enum Level1 {} - -impl TableLevel for Level4 {} -impl TableLevel for Level3 {} -impl TableLevel for Level2 {} -impl TableLevel for Level1 {} - -pub trait HierarchicalLevel: TableLevel { - type NextLevel: TableLevel; -} - -impl HierarchicalLevel for Level4 { - type NextLevel = Level3; -} - -impl HierarchicalLevel for Level3 { - type NextLevel = Level2; -} - -impl HierarchicalLevel for Level2 { - type NextLevel = Level1; -} - -pub struct Table { - entries: [Entry; ENTRY_COUNT], - level: PhantomData, -} - -impl Table where L: TableLevel { - pub fn zero(&mut self) { - for entry in self.entries.iter_mut() { - entry.set_unused(); - } - } -} - -impl Table where L: HierarchicalLevel { - pub fn next_table(&self, index: usize) -> Option<&Table> { - self.next_table_address(index).map(|address| unsafe { &*(address as *const _) }) - } - - pub fn next_table_mut(&mut self, index: usize) -> Option<&mut Table> { - self.next_table_address(index).map(|address| unsafe { &mut *(address as *mut _) }) - } - - pub fn next_table_create(&mut self, index: usize) -> &mut Table { - if self.next_table(index).is_none() { - assert!(!self[index].flags().contains(HUGE_PAGE), - "next_table_create does not support huge pages"); - let frame = allocate_frame().expect("no frames available"); - self[index].set(frame, PRESENT | WRITABLE | USER_ACCESSIBLE /* Allow users to go down the page table, implement permissions at the page level */); - self.next_table_mut(index).unwrap().zero(); - } - self.next_table_mut(index).unwrap() - } - - fn next_table_address(&self, index: usize) -> Option { - let entry_flags = self[index].flags(); - if entry_flags.contains(PRESENT) && !entry_flags.contains(HUGE_PAGE) { - let table_address = self as *const _ as usize; - Some((table_address << 9) | (index << 12)) - } else { - None - } - } -} - -impl Index for Table where L: TableLevel { - type Output = Entry; - - fn index(&self, index: usize) -> &Entry { - &self.entries[index] - } -} - -impl IndexMut for Table where L: TableLevel { - fn index_mut(&mut self, index: usize) -> &mut Entry { - &mut self.entries[index] - } -} diff --git a/kernel/arch/x86_64/src/paging/temporary_page.rs b/kernel/arch/x86_64/src/paging/temporary_page.rs deleted file mode 100644 index aba6703..0000000 --- a/kernel/arch/x86_64/src/paging/temporary_page.rs +++ /dev/null @@ -1,45 +0,0 @@ -//! Temporarily map a page -//! From [Phil Opp's Blog](http://os.phil-opp.com/remap-the-kernel.html) - -use memory::Frame; - -use super::{ActivePageTable, Page, VirtualAddress}; -use super::entry::EntryFlags; -use super::table::{Table, Level1}; - -pub struct TemporaryPage { - page: Page, -} - -impl TemporaryPage { - pub fn new(page: Page) -> TemporaryPage { - TemporaryPage { - page: page, - } - } - - pub fn start_address (&self) -> VirtualAddress { - self.page.start_address() - } - - /// Maps the temporary page to the given frame in the active table. - /// Returns the start address of the temporary page. - pub fn map(&mut self, frame: Frame, flags: EntryFlags, active_table: &mut ActivePageTable) -> VirtualAddress { - assert!(active_table.translate_page(self.page).is_none(), "temporary page is already mapped"); - let result = active_table.map_to(self.page, frame, flags); - result.flush(active_table); - self.page.start_address() - } - - /// Maps the temporary page to the given page table frame in the active - /// table. Returns a reference to the now mapped table. - pub fn map_table_frame(&mut self, frame: Frame, flags: EntryFlags, active_table: &mut ActivePageTable) -> &mut Table { - unsafe { &mut *(self.map(frame, flags, active_table).get() as *mut Table) } - } - - /// Unmaps the temporary page in the active table. - pub fn unmap(&mut self, active_table: &mut ActivePageTable) { - let result = active_table.unmap(self.page); - result.flush(active_table); - } -} diff --git a/kernel/arch/x86_64/src/panic.rs b/kernel/arch/x86_64/src/panic.rs deleted file mode 100644 index 27d361d..0000000 --- a/kernel/arch/x86_64/src/panic.rs +++ /dev/null @@ -1,32 +0,0 @@ -//! Intrinsics for panic handling - -use interrupt; - -#[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) -> ! { - println!("PANIC: {}", fmt); - println!("FILE: {}", file); - println!("LINE: {}", line); - - unsafe { interrupt::stack_trace(); } - - println!("HALT"); - loop { - unsafe { interrupt::halt(); } - } -} - -#[allow(non_snake_case)] -#[no_mangle] -/// Required to handle panics -pub extern "C" fn _Unwind_Resume() -> ! { - loop { - unsafe { interrupt::halt(); } - } -} diff --git a/kernel/arch/x86_64/src/start.rs b/kernel/arch/x86_64/src/start.rs deleted file mode 100644 index 4488009..0000000 --- a/kernel/arch/x86_64/src/start.rs +++ /dev/null @@ -1,189 +0,0 @@ -/// This function is where the kernel sets up IRQ handlers -/// It is increcibly unsafe, and should be minimal in nature -/// It must create the IDT with the correct entries, those entries are -/// defined in other files inside of the `arch` module - -use core::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; - -use acpi; -use allocator; -use device; -use externs::memset; -use gdt; -use idt; -use interrupt; -use memory; -use paging::{self, entry, Page, VirtualAddress}; -use paging::mapper::MapperFlushAll; - -/// Test of zero values in BSS. -static BSS_TEST_ZERO: usize = 0; -/// Test of non-zero values in data. -static DATA_TEST_NONZERO: usize = 0xFFFFFFFFFFFFFFFF; -/// Test of zero values in thread BSS -#[thread_local] -static mut TBSS_TEST_ZERO: usize = 0; -/// Test of non-zero values in thread data. -#[thread_local] -static mut TDATA_TEST_NONZERO: usize = 0xFFFFFFFFFFFFFFFF; - -pub static CPU_COUNT: AtomicUsize = ATOMIC_USIZE_INIT; -pub static AP_READY: AtomicBool = ATOMIC_BOOL_INIT; -static BSP_READY: AtomicBool = ATOMIC_BOOL_INIT; - -extern { - /// Kernel main function - fn kmain(cpus: usize) -> !; - /// Kernel main for APs - fn kmain_ap(id: usize) -> !; -} - -/// The entry to Rust, all things must be initialized -#[no_mangle] -pub unsafe extern fn kstart() -> ! { - { - extern { - /// The starting byte of the _.bss_ (uninitialized data) segment. - static mut __bss_start: u8; - /// The ending byte of the _.bss_ (uninitialized data) segment. - static mut __bss_end: u8; - /// The end of the kernel - static mut __end: u8; - } - - // Zero BSS, this initializes statics that are set to 0 - { - let start_ptr = &mut __bss_start as *mut u8; - let end_ptr = & __bss_end as *const u8 as usize; - - if start_ptr as usize <= end_ptr { - let size = end_ptr - start_ptr as usize; - memset(start_ptr, 0, size); - } - - assert_eq!(BSS_TEST_ZERO, 0); - assert_eq!(DATA_TEST_NONZERO, 0xFFFFFFFFFFFFFFFF); - } - - // Initialize memory management - memory::init(0, &__end as *const u8 as usize - ::KERNEL_OFFSET); - - // TODO: allocate a stack - let stack_start = 0x00080000 + ::KERNEL_OFFSET; - let stack_end = 0x0009F000 + ::KERNEL_OFFSET; - - // Initialize paging - let (mut active_table, tcb_offset) = paging::init(0, stack_start, stack_end); - - // Set up GDT - gdt::init(tcb_offset, stack_end); - - // Set up IDT - idt::init(); - - // Test tdata and tbss - { - assert_eq!(TBSS_TEST_ZERO, 0); - TBSS_TEST_ZERO += 1; - assert_eq!(TBSS_TEST_ZERO, 1); - assert_eq!(TDATA_TEST_NONZERO, 0xFFFFFFFFFFFFFFFF); - TDATA_TEST_NONZERO -= 1; - assert_eq!(TDATA_TEST_NONZERO, 0xFFFFFFFFFFFFFFFE); - } - - // Reset AP variables - CPU_COUNT.store(1, Ordering::SeqCst); - AP_READY.store(false, Ordering::SeqCst); - BSP_READY.store(false, Ordering::SeqCst); - - // Setup kernel heap - { - let mut flush_all = MapperFlushAll::new(); - - // Map heap pages - let heap_start_page = Page::containing_address(VirtualAddress::new(::KERNEL_HEAP_OFFSET)); - let heap_end_page = Page::containing_address(VirtualAddress::new(::KERNEL_HEAP_OFFSET + ::KERNEL_HEAP_SIZE-1)); - for page in Page::range_inclusive(heap_start_page, heap_end_page) { - let result = active_table.map(page, entry::PRESENT | entry::GLOBAL | entry::WRITABLE | entry::NO_EXECUTE); - flush_all.consume(result); - } - - flush_all.flush(&mut active_table); - - // Init the allocator - allocator::init(::KERNEL_HEAP_OFFSET, ::KERNEL_HEAP_SIZE); - } - - // Initialize devices - device::init(&mut active_table); - - // Read ACPI tables, starts APs - acpi::init(&mut active_table); - - BSP_READY.store(true, Ordering::SeqCst); - } - - kmain(CPU_COUNT.load(Ordering::SeqCst)); -} - -/// Entry to rust for an AP -pub unsafe extern fn kstart_ap(cpu_id: usize, bsp_table: usize, stack_start: usize, stack_end: usize) -> ! { - { - assert_eq!(BSS_TEST_ZERO, 0); - assert_eq!(DATA_TEST_NONZERO, 0xFFFFFFFFFFFFFFFF); - - // Initialize paging - let tcb_offset = paging::init_ap(cpu_id, bsp_table, stack_start, stack_end); - - // Set up GDT for AP - gdt::init(tcb_offset, stack_end); - - // Set up IDT for AP - idt::init(); - - // Test tdata and tbss - { - assert_eq!(TBSS_TEST_ZERO, 0); - TBSS_TEST_ZERO += 1; - assert_eq!(TBSS_TEST_ZERO, 1); - assert_eq!(TDATA_TEST_NONZERO, 0xFFFFFFFFFFFFFFFF); - TDATA_TEST_NONZERO -= 1; - assert_eq!(TDATA_TEST_NONZERO, 0xFFFFFFFFFFFFFFFE); - } - - // Initialize devices (for AP) - device::init_ap(); - - AP_READY.store(true, Ordering::SeqCst); - } - - while ! BSP_READY.load(Ordering::SeqCst) { - interrupt::pause(); - } - - kmain_ap(cpu_id); -} - -pub unsafe fn usermode(ip: usize, sp: usize) -> ! { - // Go to usermode - asm!("mov ds, ax - mov es, ax - mov fs, bx - mov gs, ax - push rax - push rcx - push rdx - push rsi - push rdi - iretq" - : // No output because it never returns - : "{rax}"(gdt::GDT_USER_DATA << 3 | 3), // Data segment - "{rbx}"(gdt::GDT_USER_TLS << 3 | 3), // TLS segment - "{rcx}"(sp), // Stack pointer - "{rdx}"(3 << 12 | 1 << 9), // Flags - Set IOPL and interrupt enable flag - "{rsi}"(gdt::GDT_USER_CODE << 3 | 3), // Code segment - "{rdi}"(ip) // IP - : // No clobers because it never returns - : "intel", "volatile"); - unreachable!(); -} diff --git a/kernel/arch/x86_64/src/stop.rs b/kernel/arch/x86_64/src/stop.rs deleted file mode 100644 index 5af92ae..0000000 --- a/kernel/arch/x86_64/src/stop.rs +++ /dev/null @@ -1,23 +0,0 @@ -use io::{Io, Pio}; - -#[no_mangle] -pub unsafe extern fn kstop() -> ! { - // (phony) ACPI shutdown (http://forum.osdev.org/viewtopic.php?t=16990) - // Works for qemu and bochs. - for &port in [0x604, 0xB004].iter() { - println!("Shutdown with outw(0x{:X}, 0x{:X})", port, 0x2000); - Pio::::new(port).write(0x2000); - } - - // Magic shutdown code for bochs and qemu (older versions). - for c in "Shutdown".bytes() { - println!("Shutdown with outb(0x{:X}, '{}')", 0x8900, c as char); - Pio::::new(0x8900).write(c); - } - - // Magic code for VMWare. Also a hard lock. - println!("Shutdown with cli hlt"); - asm!("cli; hlt" : : : : "intel", "volatile"); - - unreachable!(); -} diff --git a/kernel/arch/x86_64/src/time.rs b/kernel/arch/x86_64/src/time.rs deleted file mode 100644 index 7af3ef7..0000000 --- a/kernel/arch/x86_64/src/time.rs +++ /dev/null @@ -1,15 +0,0 @@ -use spin::Mutex; - -pub static START: Mutex<(u64, u64)> = Mutex::new((0, 0)); -pub static OFFSET: Mutex<(u64, u64)> = Mutex::new((0, 0)); - -pub fn monotonic() -> (u64, u64) { - *OFFSET.lock() -} - -pub fn realtime() -> (u64, u64) { - let offset = monotonic(); - let start = *START.lock(); - let sum = start.1 + offset.1; - (start.0 + offset.0 + sum / 1000000000, sum % 1000000000) -} diff --git a/kernel/src/common/int_like.rs b/kernel/src/common/int_like.rs deleted file mode 100644 index 10f8423..0000000 --- a/kernel/src/common/int_like.rs +++ /dev/null @@ -1,108 +0,0 @@ -//! Helpers used to define types that are backed by integers (typically `usize`), -//! without compromising safety. -//! -//! # Example -//! -//! ``` -//! /// Define an opaque type `Pid` backed by a `usize`. -//! int_like!(Pid, usize); -//! -//! const ZERO: Pid = Pid::from(0); -//! ``` -//! -//! # Example -//! -//! ``` -//! /// Define opaque types `Pid` and `AtomicPid`, backed respectively by a `usize` -//! /// and a `AtomicUsize`. -//! -//! int_like!(Pid, AtomicPid, usize, AtomicUsize); -//! -//! const ZERO: Pid = Pid::from(0); -//! let ATOMIC_PID: AtomicPid = AtomicPid::default(); -//! ``` - -#[macro_export] -macro_rules! int_like { - ($new_type_name:ident, $backing_type: ident) => { - #[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)] - pub struct $new_type_name($backing_type); - - impl $new_type_name { - pub const fn into(self) -> $backing_type { - self.0 - } - pub const fn from(x: $backing_type) -> Self { - $new_type_name(x) - } - } - }; - - ($new_type_name:ident, $new_atomic_type_name: ident, $backing_type:ident, $backing_atomic_type:ident) => { - int_like!($new_type_name, $backing_type); - - /// A mutable holder for T that can safely be shared among threads. - /// Runtime equivalent to using `AtomicUsize`, just type-safer. - pub struct $new_atomic_type_name { - container: $backing_atomic_type, - } - - impl $new_atomic_type_name { - pub const fn new(x: $new_type_name) -> Self { - $new_atomic_type_name { - container: $backing_atomic_type::new(x.into()) - } - } - pub const fn default() -> Self { - Self::new($new_type_name::from(0)) - } - pub fn load(&self, order: ::core::sync::atomic::Ordering) -> $new_type_name { - $new_type_name::from(self.container.load(order)) - } - pub fn store(&self, val: $new_type_name, order: ::core::sync::atomic::Ordering) { - self.container.store(val.into(), order) - } - #[allow(dead_code)] - pub fn swap(&self, val: $new_type_name, order: ::core::sync::atomic::Ordering) -> $new_type_name { - $new_type_name::from(self.container.swap(val.into(), order)) - } - #[allow(dead_code)] - pub fn compare_and_swap(&self, current: $new_type_name, new: $new_type_name, order: ::core::sync::atomic::Ordering) -> $new_type_name { - $new_type_name::from(self.container.compare_and_swap(current.into(), new.into(), order)) - } - #[allow(dead_code)] - pub fn compare_exchange(&self, current: $new_type_name, new: $new_type_name, success: ::core::sync::atomic::Ordering, failure: ::core::sync::atomic::Ordering) -> ::core::result::Result<$new_type_name, $new_type_name> { - match self.container.compare_exchange(current.into(), new.into(), success, failure) { - Ok(result) => Ok($new_type_name::from(result)), - Err(result) => Err($new_type_name::from(result)) - } - } - #[allow(dead_code)] - pub fn compare_exchange_weak(&self, current: $new_type_name, new: $new_type_name, success: ::core::sync::atomic::Ordering, failure: ::core::sync::atomic::Ordering) -> ::core::result::Result<$new_type_name, $new_type_name> { - match self.container.compare_exchange_weak(current.into(), new.into(), success, failure) { - Ok(result) => Ok($new_type_name::from(result)), - Err(result) => Err($new_type_name::from(result)) - } - } - } - } -} - -#[cfg(test)] -fn test() { - use core::mem::size_of; - use ::core::sync::atomic::AtomicUsize; - - // Generate type `usize_like`. - int_like!(UsizeLike, usize); - const ZERO: UsizeLike = UsizeLike::from(0); - assert_eq!(size_of::(), size_of::()); - - - // Generate types `usize_like` and `AtomicUsize`. - int_like!(UsizeLike2, AtomicUsizeLike, usize, AtomicUsize); - assert_eq!(size_of::(), size_of::()); - assert_eq!(size_of::(), size_of::()); -} - - diff --git a/kernel/src/common/mod.rs b/kernel/src/common/mod.rs deleted file mode 100644 index 29f6412..0000000 --- a/kernel/src/common/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -#[macro_use] -pub mod int_like; diff --git a/kernel/src/context/context.rs b/kernel/src/context/context.rs deleted file mode 100644 index 607653c..0000000 --- a/kernel/src/context/context.rs +++ /dev/null @@ -1,252 +0,0 @@ -use alloc::arc::Arc; -use alloc::boxed::Box; -use collections::{BTreeMap, Vec, VecDeque}; -use spin::Mutex; - -use arch; -use context::file::File; -use context::memory::{Grant, Memory, SharedMemory, Tls}; -use scheme::{SchemeNamespace, FileHandle}; -use syscall::data::Event; -use sync::{WaitMap, WaitQueue}; - -/// Unique identifier for a context (i.e. `pid`). -use ::core::sync::atomic::AtomicUsize; -int_like!(ContextId, AtomicContextId, usize, AtomicUsize); - -/// The status of a context - used for scheduling -/// See syscall::process::waitpid and the sync module for examples of usage -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub enum Status { - Runnable, - Blocked, - Exited(usize) -} - -/// A context, which identifies either a process or a thread -#[derive(Debug)] -pub struct Context { - /// The ID of this context - pub id: ContextId, - /// The ID of the parent context - pub ppid: ContextId, - /// The real user id - pub ruid: u32, - /// The real group id - pub rgid: u32, - /// The real namespace id - pub rns: SchemeNamespace, - /// The effective user id - pub euid: u32, - /// The effective group id - pub egid: u32, - /// The effective namespace id - pub ens: SchemeNamespace, - /// Status of context - pub status: Status, - /// Context running or not - pub running: bool, - /// CPU ID, if locked - pub cpu_id: Option, - /// Context is halting parent - pub vfork: bool, - /// Context is being waited on - pub waitpid: Arc>, - /// Context should handle pending signals - pub pending: VecDeque, - /// Context should wake up at specified time - pub wake: Option<(u64, u64)>, - /// The architecture specific context - pub arch: arch::context::Context, - /// Kernel FX - used to store SIMD and FPU registers on context switch - pub kfx: Option>, - /// Kernel stack - pub kstack: Option>, - /// Executable image - pub image: Vec, - /// User heap - pub heap: Option, - /// User stack - pub stack: Option, - /// User Thread local storage - pub tls: Option, - /// User grants - pub grants: Arc>>, - /// The name of the context - pub name: Arc>>, - /// The current working directory - pub cwd: Arc>>, - /// Kernel events - pub events: Arc>, - /// The process environment - pub env: Arc, Arc>>>>>, - /// The open files in the scheme - pub files: Arc>>> -} - -impl Context { - pub fn new(id: ContextId) -> Context { - Context { - id: id, - ppid: ContextId::from(0), - ruid: 0, - rgid: 0, - rns: SchemeNamespace::from(0), - euid: 0, - egid: 0, - ens: SchemeNamespace::from(0), - status: Status::Blocked, - running: false, - cpu_id: None, - vfork: false, - waitpid: Arc::new(WaitMap::new()), - pending: VecDeque::new(), - wake: None, - arch: arch::context::Context::new(), - kfx: None, - kstack: None, - image: Vec::new(), - heap: None, - stack: None, - tls: None, - grants: Arc::new(Mutex::new(Vec::new())), - name: Arc::new(Mutex::new(Vec::new())), - cwd: Arc::new(Mutex::new(Vec::new())), - events: Arc::new(WaitQueue::new()), - env: Arc::new(Mutex::new(BTreeMap::new())), - files: Arc::new(Mutex::new(Vec::new())) - } - } - - /// Make a relative path absolute - /// Given a cwd of "scheme:/path" - /// This function will turn "foo" into "scheme:/path/foo" - /// "/foo" will turn into "scheme:/foo" - /// "bar:/foo" will be used directly, as it is already absolute - pub fn canonicalize(&self, path: &[u8]) -> Vec { - if path.iter().position(|&b| b == b':').is_none() { - let cwd = self.cwd.lock(); - if path == b"." { - cwd.clone() - } else if path == b".." { - cwd[..cwd[..cwd.len() - 1] - .iter().rposition(|&b| b == b'/' || b == b':') - .map_or(cwd.len(), |i| i + 1)] - .to_vec() - } else if path.starts_with(b"./") { - let mut canon = cwd.clone(); - if ! canon.ends_with(b"/") { - canon.push(b'/'); - } - canon.extend_from_slice(&path[2..]); - canon - } else if path.starts_with(b"../") { - let mut canon = cwd[..cwd[..cwd.len() - 1] - .iter().rposition(|&b| b == b'/' || b == b':') - .map_or(cwd.len(), |i| i + 1)] - .to_vec(); - canon.extend_from_slice(&path[3..]); - canon - } else if path.starts_with(b"/") { - let mut canon = cwd[..cwd.iter().position(|&b| b == b':').map_or(1, |i| i + 1)].to_vec(); - canon.extend_from_slice(&path); - canon - } else { - let mut canon = cwd.clone(); - if ! canon.ends_with(b"/") { - canon.push(b'/'); - } - canon.extend_from_slice(&path); - canon - } - } else { - path.to_vec() - } - } - - /// Block the context, and return true if it was runnable before being blocked - pub fn block(&mut self) -> bool { - if self.status == Status::Runnable { - self.status = Status::Blocked; - true - } else { - false - } - } - - /// Unblock context, and return true if it was blocked before being marked runnable - pub fn unblock(&mut self) -> bool { - if self.status == Status::Blocked { - self.status = Status::Runnable; - if let Some(cpu_id) = self.cpu_id { - if cpu_id != ::cpu_id() { - // Send IPI if not on current CPU - // TODO: Make this more architecture independent - unsafe { arch::device::local_apic::LOCAL_APIC.ipi(cpu_id) }; - } - } - true - } else { - false - } - } - - /// Add a file to the lowest available slot. - /// Return the file descriptor number or None if no slot was found - pub fn add_file(&self, file: File) -> Option { - let mut files = self.files.lock(); - for (i, mut file_option) in files.iter_mut().enumerate() { - if file_option.is_none() { - *file_option = Some(file); - return Some(FileHandle::from(i)); - } - } - let len = files.len(); - if len < super::CONTEXT_MAX_FILES { - files.push(Some(file)); - Some(FileHandle::from(len)) - } else { - None - } - } - - /// Get a file - pub fn get_file(&self, i: FileHandle) -> Option { - let files = self.files.lock(); - if i.into() < files.len() { - files[i.into()] - } else { - None - } - } - - /// Insert a file with a specific handle number. This is used by dup2 - /// Return the file descriptor number or None if the slot was not empty, or i was invalid - pub fn insert_file(&self, i: FileHandle, file: File) -> Option { - let mut files = self.files.lock(); - if i.into() < super::CONTEXT_MAX_FILES { - while i.into() >= files.len() { - files.push(None); - } - if files[i.into()].is_none() { - files[i.into()] = Some(file); - Some(i) - } else { - None - } - } else { - None - } - } - - /// Remove a file - // TODO: adjust files vector to smaller size if possible - pub fn remove_file(&self, i: FileHandle) -> Option { - let mut files = self.files.lock(); - if i.into() < files.len() { - files[i.into()].take() - } else { - None - } - } -} diff --git a/kernel/src/context/event.rs b/kernel/src/context/event.rs deleted file mode 100644 index c6c9431..0000000 --- a/kernel/src/context/event.rs +++ /dev/null @@ -1,112 +0,0 @@ -use alloc::arc::{Arc, Weak}; -use collections::BTreeMap; -use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard}; - -use context; -use scheme::{FileHandle, SchemeId}; -use sync::WaitQueue; -use syscall::data::Event; - -type EventList = Weak>; - -#[derive(PartialEq, Eq, PartialOrd, Ord)] -pub struct RegKey { - scheme_id: SchemeId, - event_id: usize, -} - -#[derive(PartialEq, Eq, PartialOrd, Ord)] -pub struct ProcessKey { - context_id: context::context::ContextId, - fd: FileHandle, -} - -type Registry = BTreeMap>; - -static REGISTRY: Once> = Once::new(); - -/// Initialize registry, called if needed -fn init_registry() -> RwLock { - RwLock::new(Registry::new()) -} - -/// Get the global schemes list, const -fn registry() -> RwLockReadGuard<'static, Registry> { - REGISTRY.call_once(init_registry).read() -} - -/// Get the global schemes list, mutable -pub fn registry_mut() -> RwLockWriteGuard<'static, Registry> { - REGISTRY.call_once(init_registry).write() -} - -pub fn register(fd: FileHandle, scheme_id: SchemeId, event_id: usize) -> bool { - let (context_id, events) = { - let contexts = context::contexts(); - let context_lock = contexts.current().expect("event::register: No context"); - let context = context_lock.read(); - (context.id, Arc::downgrade(&context.events)) - }; - - let mut registry = registry_mut(); - let entry = registry.entry(RegKey { - scheme_id: scheme_id, - event_id: event_id - }).or_insert_with(|| { - BTreeMap::new() - }); - let process_key = ProcessKey { - context_id: context_id, - fd: fd - }; - if entry.contains_key(&process_key) { - false - } else { - entry.insert(process_key, events); - true - } -} - -pub fn unregister(fd: FileHandle, scheme_id: SchemeId, event_id: usize) { - let mut registry = registry_mut(); - - let mut remove = false; - let key = RegKey { - scheme_id: scheme_id, - event_id: event_id - }; - if let Some(entry) = registry.get_mut(&key) { - let process_key = ProcessKey { - context_id: context::context_id(), - fd: fd, - }; - entry.remove(&process_key); - - if entry.is_empty() { - remove = true; - } - } - - if remove { - registry.remove(&key); - } -} - -pub fn trigger(scheme_id: SchemeId, event_id: usize, flags: usize, data: usize) { - let registry = registry(); - let key = RegKey { - scheme_id: scheme_id, - event_id: event_id - }; - if let Some(event_lists) = registry.get(&key) { - for entry in event_lists.iter() { - if let Some(event_list) = entry.1.upgrade() { - event_list.send(Event { - id: (entry.0).fd.into(), - flags: flags, - data: data - }); - } - } - } -} diff --git a/kernel/src/context/file.rs b/kernel/src/context/file.rs deleted file mode 100644 index 26e0863..0000000 --- a/kernel/src/context/file.rs +++ /dev/null @@ -1,15 +0,0 @@ -//! File struct - -use scheme::SchemeId; - -/// A file -//TODO: Close on exec -#[derive(Copy, Clone, Debug)] -pub struct File { - /// The scheme that this file refers to - pub scheme: SchemeId, - /// The number the scheme uses to refer to this file - pub number: usize, - /// If events are on, this is the event ID - pub event: Option, -} diff --git a/kernel/src/context/list.rs b/kernel/src/context/list.rs deleted file mode 100644 index 11c25c2..0000000 --- a/kernel/src/context/list.rs +++ /dev/null @@ -1,91 +0,0 @@ -use alloc::arc::Arc; -use alloc::boxed::Box; -use collections::BTreeMap; -use core::mem; -use core::sync::atomic::Ordering; -use spin::RwLock; - -use arch; -use syscall::error::{Result, Error, EAGAIN}; -use super::context::{Context, ContextId}; - -/// Context list type -pub struct ContextList { - map: BTreeMap>>, - next_id: usize -} - -impl ContextList { - /// Create a new context list. - pub fn new() -> Self { - ContextList { - map: BTreeMap::new(), - next_id: 1 - } - } - - /// Get the nth context. - pub fn get(&self, id: ContextId) -> Option<&Arc>> { - self.map.get(&id) - } - - /// Get the current context. - pub fn current(&self) -> Option<&Arc>> { - self.map.get(&super::CONTEXT_ID.load(Ordering::SeqCst)) - } - - pub fn iter(&self) -> ::collections::btree_map::Iter>> { - self.map.iter() - } - - /// Create a new context. - pub fn new_context(&mut self) -> Result<&Arc>> { - if self.next_id >= super::CONTEXT_MAX_CONTEXTS { - self.next_id = 1; - } - - while self.map.contains_key(&ContextId::from(self.next_id)) { - self.next_id += 1; - } - - if self.next_id >= super::CONTEXT_MAX_CONTEXTS { - return Err(Error::new(EAGAIN)); - } - - let id = ContextId::from(self.next_id); - self.next_id += 1; - - assert!(self.map.insert(id, Arc::new(RwLock::new(Context::new(id)))).is_none()); - - Ok(self.map.get(&id).expect("Failed to insert new context. ID is out of bounds.")) - } - - /// Spawn a context from a function. - pub fn spawn(&mut self, func: extern fn()) -> Result<&Arc>> { - let context_lock = self.new_context()?; - { - let mut context = context_lock.write(); - let mut fx = unsafe { Box::from_raw(::alloc::heap::allocate(512, 16) as *mut [u8; 512]) }; - for b in fx.iter_mut() { - *b = 0; - } - let mut stack = vec![0; 65536].into_boxed_slice(); - let offset = stack.len() - mem::size_of::(); - unsafe { - let offset = stack.len() - mem::size_of::(); - let func_ptr = stack.as_mut_ptr().offset(offset as isize); - *(func_ptr as *mut usize) = func as usize; - } - context.arch.set_page_table(unsafe { arch::paging::ActivePageTable::new().address() }); - context.arch.set_fx(fx.as_ptr() as usize); - context.arch.set_stack(stack.as_ptr() as usize + offset); - context.kfx = Some(fx); - context.kstack = Some(stack); - } - Ok(context_lock) - } - - pub fn remove(&mut self, id: ContextId) -> Option>> { - self.map.remove(&id) - } -} diff --git a/kernel/src/context/memory.rs b/kernel/src/context/memory.rs deleted file mode 100644 index e12fbda..0000000 --- a/kernel/src/context/memory.rs +++ /dev/null @@ -1,327 +0,0 @@ -use alloc::arc::{Arc, Weak}; -use collections::VecDeque; -use core::intrinsics; -use spin::Mutex; - -use arch::memory::Frame; -use arch::paging::{ActivePageTable, InactivePageTable, Page, PageIter, PhysicalAddress, VirtualAddress}; -use arch::paging::entry::{self, EntryFlags}; -use arch::paging::mapper::MapperFlushAll; -use arch::paging::temporary_page::TemporaryPage; - -#[derive(Debug)] -pub struct Grant { - start: VirtualAddress, - size: usize, - flags: EntryFlags, - mapped: bool -} - -impl Grant { - pub fn physmap(from: PhysicalAddress, to: VirtualAddress, size: usize, flags: EntryFlags) -> Grant { - let mut active_table = unsafe { ActivePageTable::new() }; - - let mut flush_all = MapperFlushAll::new(); - - let start_page = Page::containing_address(to); - let end_page = Page::containing_address(VirtualAddress::new(to.get() + size - 1)); - for page in Page::range_inclusive(start_page, end_page) { - let frame = Frame::containing_address(PhysicalAddress::new(page.start_address().get() - to.get() + from.get())); - let result = active_table.map_to(page, frame, flags); - flush_all.consume(result); - } - - flush_all.flush(&mut active_table); - - Grant { - start: to, - size: size, - flags: flags, - mapped: true - } - } - - pub fn map_inactive(from: VirtualAddress, to: VirtualAddress, size: usize, flags: EntryFlags, new_table: &mut InactivePageTable, temporary_page: &mut TemporaryPage) -> Grant { - let mut active_table = unsafe { ActivePageTable::new() }; - - let mut frames = VecDeque::new(); - - let start_page = Page::containing_address(from); - let end_page = Page::containing_address(VirtualAddress::new(from.get() + size - 1)); - for page in Page::range_inclusive(start_page, end_page) { - let frame = active_table.translate_page(page).expect("grant references unmapped memory"); - frames.push_back(frame); - } - - active_table.with(new_table, temporary_page, |mapper| { - let start_page = Page::containing_address(to); - let end_page = Page::containing_address(VirtualAddress::new(to.get() + size - 1)); - for page in Page::range_inclusive(start_page, end_page) { - let frame = frames.pop_front().expect("grant did not find enough frames"); - let result = mapper.map_to(page, frame, flags); - // Ignore result due to mapping on inactive table - unsafe { result.ignore(); } - } - }); - - Grant { - start: to, - size: size, - flags: flags, - mapped: true - } - } - - pub fn start_address(&self) -> VirtualAddress { - self.start - } - - pub fn size(&self) -> usize { - self.size - } - - pub fn flags(&self) -> EntryFlags { - self.flags - } - - pub fn unmap(mut self) { - assert!(self.mapped); - - let mut active_table = unsafe { ActivePageTable::new() }; - - let mut flush_all = MapperFlushAll::new(); - - let start_page = Page::containing_address(self.start); - let end_page = Page::containing_address(VirtualAddress::new(self.start.get() + self.size - 1)); - for page in Page::range_inclusive(start_page, end_page) { - let (result, _frame) = active_table.unmap_return(page); - flush_all.consume(result); - } - - flush_all.flush(&mut active_table); - - self.mapped = false; - } - - pub fn unmap_inactive(mut self, new_table: &mut InactivePageTable, temporary_page: &mut TemporaryPage) { - assert!(self.mapped); - - let mut active_table = unsafe { ActivePageTable::new() }; - - active_table.with(new_table, temporary_page, |mapper| { - let start_page = Page::containing_address(self.start); - let end_page = Page::containing_address(VirtualAddress::new(self.start.get() + self.size - 1)); - for page in Page::range_inclusive(start_page, end_page) { - let (result, _frame) = mapper.unmap_return(page); - // This is not the active table, so the flush can be ignored - unsafe { result.ignore(); } - } - }); - - self.mapped = false; - } -} - -impl Drop for Grant { - fn drop(&mut self) { - assert!(!self.mapped); - } -} - -#[derive(Clone, Debug)] -pub enum SharedMemory { - Owned(Arc>), - Borrowed(Weak>) -} - -impl SharedMemory { - pub fn with(&self, f: F) -> T where F: FnOnce(&mut Memory) -> T { - match *self { - SharedMemory::Owned(ref memory_lock) => { - let mut memory = memory_lock.lock(); - f(&mut *memory) - }, - SharedMemory::Borrowed(ref memory_weak) => { - let memory_lock = memory_weak.upgrade().expect("SharedMemory::Borrowed no longer valid"); - let mut memory = memory_lock.lock(); - f(&mut *memory) - } - } - } - - pub fn borrow(&self) -> SharedMemory { - match *self { - SharedMemory::Owned(ref memory_lock) => SharedMemory::Borrowed(Arc::downgrade(memory_lock)), - SharedMemory::Borrowed(ref memory_lock) => SharedMemory::Borrowed(memory_lock.clone()) - } - } -} - -#[derive(Debug)] -pub struct Memory { - start: VirtualAddress, - size: usize, - flags: EntryFlags -} - -impl Memory { - pub fn new(start: VirtualAddress, size: usize, flags: EntryFlags, clear: bool) -> Self { - let mut memory = Memory { - start: start, - size: size, - flags: flags - }; - - memory.map(clear); - - memory - } - - pub fn to_shared(self) -> SharedMemory { - SharedMemory::Owned(Arc::new(Mutex::new(self))) - } - - pub fn start_address(&self) -> VirtualAddress { - self.start - } - - pub fn size(&self) -> usize { - self.size - } - - pub fn flags(&self) -> EntryFlags { - self.flags - } - - pub fn pages(&self) -> PageIter { - let start_page = Page::containing_address(self.start); - let end_page = Page::containing_address(VirtualAddress::new(self.start.get() + self.size - 1)); - Page::range_inclusive(start_page, end_page) - } - - fn map(&mut self, clear: bool) { - let mut active_table = unsafe { ActivePageTable::new() }; - - let mut flush_all = MapperFlushAll::new(); - - for page in self.pages() { - let result = active_table.map(page, self.flags); - flush_all.consume(result); - } - - flush_all.flush(&mut active_table); - - if clear { - assert!(self.flags.contains(entry::WRITABLE)); - unsafe { - intrinsics::write_bytes(self.start_address().get() as *mut u8, 0, self.size); - } - } - } - - fn unmap(&mut self) { - let mut active_table = unsafe { ActivePageTable::new() }; - - let mut flush_all = MapperFlushAll::new(); - - for page in self.pages() { - let result = active_table.unmap(page); - flush_all.consume(result); - } - - flush_all.flush(&mut active_table); - } - - /// A complicated operation to move a piece of memory to a new page table - /// It also allows for changing the address at the same time - pub fn move_to(&mut self, new_start: VirtualAddress, new_table: &mut InactivePageTable, temporary_page: &mut TemporaryPage) { - let mut active_table = unsafe { ActivePageTable::new() }; - - let mut flush_all = MapperFlushAll::new(); - - for page in self.pages() { - let (result, frame) = active_table.unmap_return(page); - flush_all.consume(result); - - active_table.with(new_table, temporary_page, |mapper| { - let new_page = Page::containing_address(VirtualAddress::new(page.start_address().get() - self.start.get() + new_start.get())); - let result = mapper.map_to(new_page, frame, self.flags); - // This is not the active table, so the flush can be ignored - unsafe { result.ignore(); } - }); - } - - flush_all.flush(&mut active_table); - - self.start = new_start; - } - - pub fn remap(&mut self, new_flags: EntryFlags) { - let mut active_table = unsafe { ActivePageTable::new() }; - - let mut flush_all = MapperFlushAll::new(); - - for page in self.pages() { - let result = active_table.remap(page, new_flags); - flush_all.consume(result); - } - - flush_all.flush(&mut active_table); - - self.flags = new_flags; - } - - pub fn resize(&mut self, new_size: usize, clear: bool) { - let mut active_table = unsafe { ActivePageTable::new() }; - - //TODO: Calculate page changes to minimize operations - if new_size > self.size { - let mut flush_all = MapperFlushAll::new(); - - let start_page = Page::containing_address(VirtualAddress::new(self.start.get() + self.size)); - let end_page = Page::containing_address(VirtualAddress::new(self.start.get() + new_size - 1)); - for page in Page::range_inclusive(start_page, end_page) { - if active_table.translate_page(page).is_none() { - let result = active_table.map(page, self.flags); - flush_all.consume(result); - } - } - - flush_all.flush(&mut active_table); - - if clear { - unsafe { - intrinsics::write_bytes((self.start.get() + self.size) as *mut u8, 0, new_size - self.size); - } - } - } else if new_size < self.size { - let mut flush_all = MapperFlushAll::new(); - - let start_page = Page::containing_address(VirtualAddress::new(self.start.get() + new_size)); - let end_page = Page::containing_address(VirtualAddress::new(self.start.get() + self.size - 1)); - for page in Page::range_inclusive(start_page, end_page) { - if active_table.translate_page(page).is_some() { - let result = active_table.unmap(page); - flush_all.consume(result); - } - } - - flush_all.flush(&mut active_table); - } - - self.size = new_size; - } -} - -impl Drop for Memory { - fn drop(&mut self) { - self.unmap(); - } -} - -#[derive(Debug)] -pub struct Tls { - pub master: VirtualAddress, - pub file_size: usize, - pub mem: Memory -} diff --git a/kernel/src/context/mod.rs b/kernel/src/context/mod.rs deleted file mode 100644 index 2b1214c..0000000 --- a/kernel/src/context/mod.rs +++ /dev/null @@ -1,75 +0,0 @@ -//! Context management -use alloc::boxed::Box; -use core::sync::atomic::Ordering; -use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard}; - -pub use self::context::{Context, Status}; -pub use self::list::ContextList; -pub use self::switch::switch; -pub use context::context::ContextId; - -/// Context struct -mod context; - -/// Context list -mod list; - -/// Context switch function -mod switch; - -/// Event handling -pub mod event; - -/// File struct - defines a scheme and a file number -pub mod file; - -/// Memory struct - contains a set of pages for a context -pub mod memory; - -/// Limit on number of contexts -pub const CONTEXT_MAX_CONTEXTS: usize = usize::max_value() - 1; - -/// Maximum context files -pub const CONTEXT_MAX_FILES: usize = 65536; - -/// Contexts list -static CONTEXTS: Once> = Once::new(); - -#[thread_local] -static CONTEXT_ID: context::AtomicContextId = context::AtomicContextId::default(); - -pub fn init() { - let mut contexts = contexts_mut(); - let context_lock = contexts.new_context().expect("could not initialize first context"); - let mut context = context_lock.write(); - let mut fx = unsafe { Box::from_raw(::alloc::heap::allocate(512, 16) as *mut [u8; 512]) }; - for b in fx.iter_mut() { - *b = 0; - } - - context.arch.set_fx(fx.as_ptr() as usize); - context.kfx = Some(fx); - context.status = Status::Runnable; - context.running = true; - context.cpu_id = Some(::cpu_id()); - CONTEXT_ID.store(context.id, Ordering::SeqCst); -} - -/// Initialize contexts, called if needed -fn init_contexts() -> RwLock { - RwLock::new(ContextList::new()) -} - -/// Get the global schemes list, const -pub fn contexts() -> RwLockReadGuard<'static, ContextList> { - CONTEXTS.call_once(init_contexts).read() -} - -/// Get the global schemes list, mutable -pub fn contexts_mut() -> RwLockWriteGuard<'static, ContextList> { - CONTEXTS.call_once(init_contexts).write() -} - -pub fn context_id() -> context::ContextId { - CONTEXT_ID.load(Ordering::SeqCst) -} diff --git a/kernel/src/context/switch.rs b/kernel/src/context/switch.rs deleted file mode 100644 index bbdc8ad..0000000 --- a/kernel/src/context/switch.rs +++ /dev/null @@ -1,115 +0,0 @@ -use core::sync::atomic::Ordering; - -use arch; -use context::{contexts, Context, Status, CONTEXT_ID}; -use syscall; - -/// Switch to the next context -/// -/// # Safety -/// -/// Do not call this while holding locks! -pub unsafe fn switch() -> bool { - use core::ops::DerefMut; - - // Set the global lock to avoid the unsafe operations below from causing issues - while arch::context::CONTEXT_SWITCH_LOCK.compare_and_swap(false, true, Ordering::SeqCst) { - arch::interrupt::pause(); - } - - let cpu_id = ::cpu_id(); - - let from_ptr; - let mut to_ptr = 0 as *mut Context; - let mut to_sig = None; - { - let contexts = contexts(); - { - let context_lock = contexts.current().expect("context::switch: not inside of context"); - let mut context = context_lock.write(); - from_ptr = context.deref_mut() as *mut Context; - } - - let check_context = |context: &mut Context| -> bool { - if context.cpu_id == None && cpu_id == 0 { - context.cpu_id = Some(cpu_id); - // println!("{}: take {} {}", cpu_id, context.id, ::core::str::from_utf8_unchecked(&context.name.lock())); - } - - if context.status == Status::Blocked && ! context.pending.is_empty() { - context.unblock(); - } - - if context.status == Status::Blocked && context.wake.is_some() { - let wake = context.wake.expect("context::switch: wake not set"); - - let current = arch::time::monotonic(); - if current.0 > wake.0 || (current.0 == wake.0 && current.1 >= wake.1) { - context.unblock(); - } - } - - if context.cpu_id == Some(cpu_id) { - if context.status == Status::Runnable && ! context.running { - return true; - } - } - - false - }; - - for (pid, context_lock) in contexts.iter() { - if *pid > (*from_ptr).id { - let mut context = context_lock.write(); - if check_context(&mut context) { - to_ptr = context.deref_mut() as *mut Context; - to_sig = context.pending.pop_front(); - break; - } - } - } - - if to_ptr as usize == 0 { - for (pid, context_lock) in contexts.iter() { - if *pid < (*from_ptr).id { - let mut context = context_lock.write(); - if check_context(&mut context) { - to_ptr = context.deref_mut() as *mut Context; - to_sig = context.pending.pop_front(); - break; - } - } - } - } - }; - - if to_ptr as usize == 0 { - // Unset global lock if no context found - arch::context::CONTEXT_SWITCH_LOCK.store(false, Ordering::SeqCst); - return false; - } - - (&mut *from_ptr).running = false; - (&mut *to_ptr).running = true; - if let Some(ref stack) = (*to_ptr).kstack { - arch::gdt::TSS.rsp[0] = (stack.as_ptr() as usize + stack.len() - 256) as u64; - } - CONTEXT_ID.store((&mut *to_ptr).id, Ordering::SeqCst); - - // Unset global lock before switch, as arch is only usable by the current CPU at this time - arch::context::CONTEXT_SWITCH_LOCK.store(false, Ordering::SeqCst); - - if let Some(sig) = to_sig { - println!("Handle {}", sig); - (&mut *to_ptr).arch.signal_stack(signal_handler, sig); - } - - (&mut *from_ptr).arch.switch_to(&mut (&mut *to_ptr).arch); - - true -} - -extern fn signal_handler(signal: usize) { - println!("Signal handler: {}", signal); - syscall::exit(signal); -} diff --git a/kernel/src/elf.rs b/kernel/src/elf.rs deleted file mode 100644 index bf484fe..0000000 --- a/kernel/src/elf.rs +++ /dev/null @@ -1,73 +0,0 @@ -//! ELF executables - -use collections::String; - -use core::str; - -#[cfg(target_arch = "x86")] -pub use goblin::elf32::{header, program_header}; - -#[cfg(target_arch = "x86_64")] -pub use goblin::elf64::{header, program_header}; - -/// An ELF executable -pub struct Elf<'a> { - pub data: &'a [u8], - header: &'a header::Header -} - -impl<'a> Elf<'a> { - /// Create a ELF executable from data - pub fn from(data: &'a [u8]) -> Result, String> { - if data.len() < header::SIZEOF_EHDR { - Err(format!("Elf: Not enough data: {} < {}", data.len(), header::SIZEOF_EHDR)) - } else if &data[..header::SELFMAG] != header::ELFMAG { - Err(format!("Elf: Invalid magic: {:?} != {:?}", &data[..4], header::ELFMAG)) - } else if data.get(header::EI_CLASS) != Some(&header::ELFCLASS) { - Err(format!("Elf: Invalid architecture: {:?} != {:?}", data.get(header::EI_CLASS), header::ELFCLASS)) - } else { - Ok(Elf { - data: data, - header: unsafe { &*(data.as_ptr() as usize as *const header::Header) } - }) - } - } - - pub fn segments(&'a self) -> ElfSegments<'a> { - ElfSegments { - data: self.data, - header: self.header, - i: 0 - } - } - - /// Get the entry field of the header - pub fn entry(&self) -> usize { - self.header.e_entry as usize - } -} - -pub struct ElfSegments<'a> { - data: &'a [u8], - header: &'a header::Header, - i: usize -} - -impl<'a> Iterator for ElfSegments<'a> { - type Item = &'a program_header::ProgramHeader; - fn next(&mut self) -> Option { - if self.i < self.header.e_phnum as usize { - let item = unsafe { - &* (( - self.data.as_ptr() as usize - + self.header.e_phoff as usize - + self.i * self.header.e_phentsize as usize - ) as *const program_header::ProgramHeader) - }; - self.i += 1; - Some(item) - } else { - None - } - } -} diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs deleted file mode 100644 index 5502278..0000000 --- a/kernel/src/lib.rs +++ /dev/null @@ -1,180 +0,0 @@ -//! # The Redox OS Kernel, version 2 -//! -//! The Redox OS Kernel is a hybrid kernel that supports X86_64 systems and -//! provides Unix-like syscalls for primarily Rust applications - -#![deny(warnings)] -#![feature(alloc)] -#![feature(asm)] -#![feature(collections)] -#![feature(const_fn)] -#![feature(core_intrinsics)] -#![feature(drop_types_in_const)] -#![feature(heap_api)] -#![feature(integer_atomics)] -#![feature(never_type)] -#![feature(thread_local)] -#![no_std] - -use arch::interrupt; - -/// Architecture specific items (test) -#[cfg(test)] -#[macro_use] -extern crate arch_test as arch; - -/// Architecture specific items (ARM) -#[cfg(all(not(test), target_arch = "arm"))] -#[macro_use] -extern crate arch_arm as arch; - -/// Architecture specific items (x86_64) -#[cfg(all(not(test), target_arch = "x86_64"))] -#[macro_use] -extern crate arch_x86_64 as arch; - -extern crate alloc; -#[macro_use] -extern crate collections; - -#[macro_use] -extern crate bitflags; -extern crate goblin; -extern crate spin; - -use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; -use scheme::FileHandle; - -#[macro_use] -/// Shared data structures -pub mod common; - -/// Context management -pub mod context; - -/// ELF file parsing -pub mod elf; - -/// Schemes, filesystem handlers -pub mod scheme; - -/// Synchronization primitives -pub mod sync; - -/// Syscall handlers -pub mod syscall; - -/// Tests -#[cfg(test)] -pub mod tests; - -/// A unique number that identifies the current CPU - used for scheduling -#[thread_local] -static CPU_ID: AtomicUsize = ATOMIC_USIZE_INIT; - -/// Get the current CPU's scheduling ID -#[inline(always)] -pub fn cpu_id() -> usize { - CPU_ID.load(Ordering::Relaxed) -} - -/// The count of all CPUs that can have work scheduled -static CPU_COUNT : AtomicUsize = ATOMIC_USIZE_INIT; - -/// Get the number of CPUs currently active -#[inline(always)] -pub fn cpu_count() -> usize { - CPU_COUNT.load(Ordering::Relaxed) -} - -/// Initialize userspace by running the initfs:bin/init process -/// This function will also set the CWD to initfs:bin and open debug: as stdio -pub extern fn userspace_init() { - assert_eq!(syscall::chdir(b"initfs:"), Ok(0)); - - assert_eq!(syscall::open(b"debug:", syscall::flag::O_RDONLY).map(FileHandle::into), Ok(0)); - assert_eq!(syscall::open(b"debug:", syscall::flag::O_WRONLY).map(FileHandle::into), Ok(1)); - assert_eq!(syscall::open(b"debug:", syscall::flag::O_WRONLY).map(FileHandle::into), Ok(2)); - - syscall::exec(b"/bin/init", &[]).expect("failed to execute init"); - - panic!("init returned"); -} - -/// Allow exception handlers to send signal to arch-independant kernel -#[no_mangle] -pub extern fn ksignal(signal: usize) { - println!("SIGNAL {}, CPU {}, PID {:?}", signal, cpu_id(), context::context_id()); - { - let contexts = context::contexts(); - if let Some(context_lock) = contexts.current() { - let context = context_lock.read(); - println!("NAME {}", unsafe { ::core::str::from_utf8_unchecked(&context.name.lock()) }); - } - } - syscall::exit(signal & 0x7F); -} - -/// This is the kernel entry point for the primary CPU. The arch crate is responsible for calling this -#[no_mangle] -pub extern fn kmain(cpus: usize) { - CPU_ID.store(0, Ordering::SeqCst); - CPU_COUNT.store(cpus, Ordering::SeqCst); - - context::init(); - - let pid = syscall::getpid(); - println!("BSP: {:?} {}", pid, cpus); - - match context::contexts_mut().spawn(userspace_init) { - Ok(context_lock) => { - let mut context = context_lock.write(); - context.status = context::Status::Runnable; - }, - Err(err) => { - panic!("failed to spawn userspace_init: {:?}", err); - } - } - - loop { - unsafe { - interrupt::disable(); - if context::switch() { - interrupt::enable_and_nop(); - } else { - // Enable interrupts, then halt CPU (to save power) until the next interrupt is actually fired. - interrupt::enable_and_halt(); - } - } - } -} - -/// This is the main kernel entry point for secondary CPUs -#[no_mangle] -pub extern fn kmain_ap(_id: usize) { - // Disable APs for now - loop { - unsafe { interrupt::enable_and_halt(); } - } - - /* - CPU_ID.store(id, Ordering::SeqCst); - - context::init(); - - let pid = syscall::getpid(); - println!("AP {}: {:?}", id, pid); - - loop { - unsafe { - interrupt::disable(); - if context::switch() { - interrupt::enable_and_nop(); - } else { - // Enable interrupts, then halt CPU (to save power) until the next interrupt is actually fired. - interrupt::enable_and_halt(); - } - } - } -*/ -} diff --git a/kernel/src/scheme/debug.rs b/kernel/src/scheme/debug.rs deleted file mode 100644 index 4d929a8..0000000 --- a/kernel/src/scheme/debug.rs +++ /dev/null @@ -1,75 +0,0 @@ -use core::str; -use core::sync::atomic::Ordering; -use spin::Once; - -use context; -use scheme::*; -use sync::WaitQueue; -use syscall::flag::EVENT_READ; -use syscall::scheme::Scheme; - -pub static DEBUG_SCHEME_ID: AtomicSchemeId = ATOMIC_SCHEMEID_INIT; - -/// Input queue -static INPUT: Once> = Once::new(); - -/// Initialize input queue, called if needed -fn init_input() -> WaitQueue { - WaitQueue::new() -} - -/// Add to the input queue -#[no_mangle] -pub extern fn debug_input(b: u8) { - let len = INPUT.call_once(init_input).send(b); - - context::event::trigger(DEBUG_SCHEME_ID.load(Ordering::SeqCst), 0, EVENT_READ, len); -} - -pub struct DebugScheme; - -impl DebugScheme { - pub fn new(scheme_id: SchemeId) -> DebugScheme { - DEBUG_SCHEME_ID.store(scheme_id, Ordering::SeqCst); - DebugScheme - } -} - -impl Scheme for DebugScheme { - fn open(&self, _path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result { - Ok(0) - } - - fn dup(&self, _file: usize, _buf: &[u8]) -> Result { - Ok(0) - } - - /// Read the file `number` into the `buffer` - /// - /// Returns the number of bytes read - fn read(&self, _file: usize, buf: &mut [u8]) -> Result { - Ok(INPUT.call_once(init_input).receive_into(buf, true)) - } - - /// Write the `buffer` to the `file` - /// - /// Returns the number of bytes written - fn write(&self, _file: usize, buffer: &[u8]) -> Result { - //TODO: Write bytes, do not convert to str - print!("{}", unsafe { str::from_utf8_unchecked(buffer) }); - Ok(buffer.len()) - } - - fn fevent(&self, _file: usize, _flags: usize) -> Result { - Ok(0) - } - - fn fsync(&self, _file: usize) -> Result { - Ok(0) - } - - /// Close the file `number` - fn close(&self, _file: usize) -> Result { - Ok(0) - } -} diff --git a/kernel/src/scheme/env.rs b/kernel/src/scheme/env.rs deleted file mode 100644 index 3c88b1e..0000000 --- a/kernel/src/scheme/env.rs +++ /dev/null @@ -1,193 +0,0 @@ -use alloc::arc::Arc; -use collections::{BTreeMap, Vec}; -use core::{cmp, str}; -use core::sync::atomic::{AtomicUsize, Ordering}; -use spin::{Mutex, RwLock}; - -use context; -use syscall::data::Stat; -use syscall::error::*; -use syscall::flag::{MODE_FILE, SEEK_SET, SEEK_CUR, SEEK_END}; -use syscall::scheme::Scheme; - -#[derive(Clone)] -struct Handle { - data: Arc>>, - mode: u16, - seek: usize -} - -pub struct EnvScheme { - next_id: AtomicUsize, - handles: RwLock> -} - -impl EnvScheme { - pub fn new() -> EnvScheme { - EnvScheme { - next_id: AtomicUsize::new(0), - handles: RwLock::new(BTreeMap::new()) - } - } -} - -impl Scheme for EnvScheme { - fn open(&self, path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result { - let path = str::from_utf8(path).map_err(|_err| Error::new(ENOENT))?.trim_matches('/'); - - let env_lock = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - context.env.clone() - }; - - if path.is_empty() { - let mut list = Vec::new(); - { - let env = env_lock.lock(); - for entry in env.iter() { - if ! list.is_empty() { - list.push(b'\n'); - } - list.extend_from_slice(&entry.0); - list.push(b'='); - list.extend_from_slice(&entry.1.lock()); - } - } - - let id = self.next_id.fetch_add(1, Ordering::SeqCst); - self.handles.write().insert(id, Handle { - data: Arc::new(Mutex::new(list)), - mode: MODE_FILE, - seek: 0 - }); - - Ok(id) - } else { - let data = { - let mut env = env_lock.lock(); - if env.contains_key(path.as_bytes()) { - env[path.as_bytes()].clone() - } else /*if flags & O_CREAT == O_CREAT*/ { - let name = path.as_bytes().to_vec().into_boxed_slice(); - let data = Arc::new(Mutex::new(Vec::new())); - env.insert(name, data.clone()); - data - } - }; - - let id = self.next_id.fetch_add(1, Ordering::SeqCst); - self.handles.write().insert(id, Handle { - data: data, - mode: MODE_FILE, - seek: 0 - }); - - Ok(id) - } - } - - fn dup(&self, id: usize, _buf: &[u8]) -> Result { - let new_handle = { - let handles = self.handles.read(); - let handle = handles.get(&id).ok_or(Error::new(EBADF))?; - handle.clone() - }; - - let id = self.next_id.fetch_add(1, Ordering::SeqCst); - self.handles.write().insert(id, new_handle); - - Ok(id) - } - - fn read(&self, id: usize, buffer: &mut [u8]) -> Result { - let mut handles = self.handles.write(); - let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; - - let data = handle.data.lock(); - - let mut i = 0; - while i < buffer.len() && handle.seek < data.len() { - buffer[i] = data[handle.seek]; - i += 1; - handle.seek += 1; - } - - Ok(i) - } - - fn write(&self, id: usize, buffer: &[u8]) -> Result { - let mut handles = self.handles.write(); - let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; - - let mut data = handle.data.lock(); - - let mut i = 0; - while i < buffer.len() && handle.seek < data.len() { - data[handle.seek] = buffer[i]; - i += 1; - handle.seek += 1; - } - - while i < buffer.len() { - data.push(buffer[i]); - i += 1; - handle.seek += 1; - } - - Ok(i) - } - - fn seek(&self, id: usize, pos: usize, whence: usize) -> Result { - let mut handles = self.handles.write(); - let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; - - let len = handle.data.lock().len(); - handle.seek = match whence { - SEEK_SET => cmp::min(len, pos), - SEEK_CUR => cmp::max(0, cmp::min(len as isize, handle.seek as isize + pos as isize)) as usize, - SEEK_END => cmp::max(0, cmp::min(len as isize, len as isize + pos as isize)) as usize, - _ => return Err(Error::new(EINVAL)) - }; - - Ok(handle.seek) - } - - fn fstat(&self, id: usize, stat: &mut Stat) -> Result { - let handles = self.handles.read(); - let handle = handles.get(&id).ok_or(Error::new(EBADF))?; - - stat.st_mode = handle.mode; - stat.st_size = handle.data.lock().len() as u64; - - Ok(0) - } - - fn fsync(&self, id: usize) -> Result { - let handles = self.handles.read(); - let _handle = handles.get(&id).ok_or(Error::new(EBADF))?; - - Ok(0) - } - - fn ftruncate(&self, id: usize, len: usize) -> Result { - let handles = self.handles.read(); - let handle = handles.get(&id).ok_or(Error::new(EBADF))?; - - let mut data = handle.data.lock(); - if len < data.len() { - data.truncate(len) - } else { - while len > data.len() { - data.push(0); - } - } - - Ok(0) - } - - fn close(&self, id: usize) -> Result { - self.handles.write().remove(&id).ok_or(Error::new(EBADF)).and(Ok(0)) - } -} diff --git a/kernel/src/scheme/event.rs b/kernel/src/scheme/event.rs deleted file mode 100644 index 2266141..0000000 --- a/kernel/src/scheme/event.rs +++ /dev/null @@ -1,74 +0,0 @@ -use alloc::arc::{Arc, Weak}; -use collections::BTreeMap; -use core::{mem, slice}; -use core::sync::atomic::{AtomicUsize, Ordering}; -use spin::RwLock; - -use context; -use sync::WaitQueue; -use syscall::data::Event; -use syscall::error::*; -use syscall::scheme::Scheme; - -pub struct EventScheme { - next_id: AtomicUsize, - handles: RwLock>>> -} - -impl EventScheme { - pub fn new() -> EventScheme { - EventScheme { - next_id: AtomicUsize::new(0), - handles: RwLock::new(BTreeMap::new()) - } - } -} - -impl Scheme for EventScheme { - fn open(&self, _path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result { - let handle = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - context.events.clone() - }; - - let id = self.next_id.fetch_add(1, Ordering::SeqCst); - self.handles.write().insert(id, Arc::downgrade(&handle)); - - Ok(id) - } - - fn dup(&self, id: usize, _buf: &[u8]) -> Result { - let handle = { - let handles = self.handles.read(); - let handle_weak = handles.get(&id).ok_or(Error::new(EBADF))?; - handle_weak.upgrade().ok_or(Error::new(EBADF))? - }; - - let new_id = self.next_id.fetch_add(1, Ordering::SeqCst); - self.handles.write().insert(new_id, Arc::downgrade(&handle)); - Ok(new_id) - } - - fn read(&self, id: usize, buf: &mut [u8]) -> Result { - let handle = { - let handles = self.handles.read(); - let handle_weak = handles.get(&id).ok_or(Error::new(EBADF))?; - handle_weak.upgrade().ok_or(Error::new(EBADF))? - }; - - let event_buf = unsafe { slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut Event, buf.len()/mem::size_of::()) }; - Ok(handle.receive_into(event_buf, true) * mem::size_of::()) - } - - fn fsync(&self, id: usize) -> Result { - let handles = self.handles.read(); - let handle_weak = handles.get(&id).ok_or(Error::new(EBADF))?; - handle_weak.upgrade().ok_or(Error::new(EBADF)).and(Ok(0)) - } - - fn close(&self, id: usize) -> Result { - self.handles.write().remove(&id).ok_or(Error::new(EBADF)).and(Ok(0)) - } -} diff --git a/kernel/src/scheme/initfs.rs b/kernel/src/scheme/initfs.rs deleted file mode 100644 index 0bd3790..0000000 --- a/kernel/src/scheme/initfs.rs +++ /dev/null @@ -1,154 +0,0 @@ -use collections::BTreeMap; -use core::{cmp, str}; -use core::sync::atomic::{AtomicUsize, Ordering}; -use spin::RwLock; - -use syscall::data::Stat; -use syscall::error::*; -use syscall::flag::{MODE_DIR, MODE_FILE, SEEK_SET, SEEK_CUR, SEEK_END}; -use syscall::scheme::Scheme; - -#[cfg(test)] -mod gen { - use collections::BTreeMap; - pub fn gen() -> BTreeMap<&'static [u8], (&'static [u8], bool)> { BTreeMap::new() } -} - -#[cfg(not(test))] -#[path="../../../build/userspace/initfs.rs"] -mod gen; - -struct Handle { - path: &'static [u8], - data: &'static [u8], - mode: u16, - seek: usize -} - -pub struct InitFsScheme { - next_id: AtomicUsize, - files: BTreeMap<&'static [u8], (&'static [u8], bool)>, - handles: RwLock> -} - -impl InitFsScheme { - pub fn new() -> InitFsScheme { - InitFsScheme { - next_id: AtomicUsize::new(0), - files: gen::gen(), - handles: RwLock::new(BTreeMap::new()) - } - } -} - -impl Scheme for InitFsScheme { - fn open(&self, path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result { - let path_utf8 = str::from_utf8(path).map_err(|_err| Error::new(ENOENT))?; - let path_trimmed = path_utf8.trim_matches('/'); - - //Have to iterate to get the path without allocation - for entry in self.files.iter() { - if entry.0 == &path_trimmed.as_bytes() { - let id = self.next_id.fetch_add(1, Ordering::SeqCst); - self.handles.write().insert(id, Handle { - path: entry.0, - data: (entry.1).0, - mode: if (entry.1).1 { MODE_DIR | 0o755 } else { MODE_FILE | 0o744 }, - seek: 0 - }); - - return Ok(id); - } - } - - Err(Error::new(ENOENT)) - } - - fn dup(&self, id: usize, _buf: &[u8]) -> Result { - let (path, data, mode, seek) = { - let handles = self.handles.read(); - let handle = handles.get(&id).ok_or(Error::new(EBADF))?; - (handle.path, handle.data, handle.mode, handle.seek) - }; - - let id = self.next_id.fetch_add(1, Ordering::SeqCst); - self.handles.write().insert(id, Handle { - path: path, - data: data, - mode: mode, - seek: seek - }); - - Ok(id) - } - - fn read(&self, id: usize, buffer: &mut [u8]) -> Result { - let mut handles = self.handles.write(); - let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; - - let mut i = 0; - while i < buffer.len() && handle.seek < handle.data.len() { - buffer[i] = handle.data[handle.seek]; - i += 1; - handle.seek += 1; - } - - Ok(i) - } - - fn seek(&self, id: usize, pos: usize, whence: usize) -> Result { - let mut handles = self.handles.write(); - let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; - - handle.seek = match whence { - SEEK_SET => cmp::min(handle.data.len(), pos), - SEEK_CUR => cmp::max(0, cmp::min(handle.data.len() as isize, handle.seek as isize + pos as isize)) as usize, - SEEK_END => cmp::max(0, cmp::min(handle.data.len() as isize, handle.data.len() as isize + pos as isize)) as usize, - _ => return Err(Error::new(EINVAL)) - }; - - Ok(handle.seek) - } - - fn fpath(&self, id: usize, buf: &mut [u8]) -> Result { - let handles = self.handles.read(); - let handle = handles.get(&id).ok_or(Error::new(EBADF))?; - - //TODO: Copy scheme part in kernel - let mut i = 0; - let scheme_path = b"initfs:"; - while i < buf.len() && i < scheme_path.len() { - buf[i] = scheme_path[i]; - i += 1; - } - - let mut j = 0; - while i < buf.len() && j < handle.path.len() { - buf[i] = handle.path[j]; - i += 1; - j += 1; - } - - Ok(i) - } - - fn fstat(&self, id: usize, stat: &mut Stat) -> Result { - let handles = self.handles.read(); - let handle = handles.get(&id).ok_or(Error::new(EBADF))?; - - stat.st_mode = handle.mode; - stat.st_uid = 0; - stat.st_gid = 0; - stat.st_size = handle.data.len() as u64; - - Ok(0) - } - - fn fsync(&self, _id: usize) -> Result { - Ok(0) - } - - fn close(&self, id: usize) -> Result { - self.handles.write().remove(&id).ok_or(Error::new(EBADF)).and(Ok(0)) - } -} diff --git a/kernel/src/scheme/irq.rs b/kernel/src/scheme/irq.rs deleted file mode 100644 index 4817df0..0000000 --- a/kernel/src/scheme/irq.rs +++ /dev/null @@ -1,101 +0,0 @@ -use core::{mem, str}; -use core::sync::atomic::Ordering; -use spin::Mutex; - -use arch::interrupt::irq::acknowledge; -use context; -use scheme::{AtomicSchemeId, ATOMIC_SCHEMEID_INIT, SchemeId}; -use syscall::error::*; -use syscall::flag::EVENT_READ; -use syscall::scheme::Scheme; - -pub static IRQ_SCHEME_ID: AtomicSchemeId = ATOMIC_SCHEMEID_INIT; - -/// IRQ queues -static ACKS: Mutex<[usize; 16]> = Mutex::new([0; 16]); -static COUNTS: Mutex<[usize; 16]> = Mutex::new([0; 16]); - -/// Add to the input queue -#[no_mangle] -pub extern fn irq_trigger(irq: u8) { - COUNTS.lock()[irq as usize] += 1; - context::event::trigger(IRQ_SCHEME_ID.load(Ordering::SeqCst), irq as usize, EVENT_READ, mem::size_of::()); -} - -pub struct IrqScheme; - -impl IrqScheme { - pub fn new(scheme_id: SchemeId) -> IrqScheme { - IRQ_SCHEME_ID.store(scheme_id, Ordering::SeqCst); - IrqScheme - } -} - -impl Scheme for IrqScheme { - fn open(&self, path: &[u8], _flags: usize, uid: u32, _gid: u32) -> Result { - if uid == 0 { - let path_str = str::from_utf8(path).or(Err(Error::new(ENOENT)))?; - - let id = path_str.parse::().or(Err(Error::new(ENOENT)))?; - - if id < COUNTS.lock().len() { - Ok(id) - } else { - Err(Error::new(ENOENT)) - } - } else { - Err(Error::new(EACCES)) - } - } - - fn dup(&self, file: usize, _buf: &[u8]) -> Result { - Ok(file) - } - - fn read(&self, file: usize, buffer: &mut [u8]) -> Result { - // Ensures that the length of the buffer is larger than the size of a usize - if buffer.len() >= mem::size_of::() { - let ack = ACKS.lock()[file]; - let current = COUNTS.lock()[file]; - if ack != current { - // Safe if the length of the buffer is larger than the size of a usize - assert!(buffer.len() >= mem::size_of::()); - unsafe { *(buffer.as_mut_ptr() as *mut usize) = current; } - Ok(mem::size_of::()) - } else { - Ok(0) - } - } else { - Err(Error::new(EINVAL)) - } - } - - fn write(&self, file: usize, buffer: &[u8]) -> Result { - if buffer.len() >= mem::size_of::() { - assert!(buffer.len() >= mem::size_of::()); - let ack = unsafe { *(buffer.as_ptr() as *const usize) }; - let current = COUNTS.lock()[file]; - if ack == current { - ACKS.lock()[file] = ack; - unsafe { acknowledge(file); } - Ok(mem::size_of::()) - } else { - Ok(0) - } - } else { - Err(Error::new(EINVAL)) - } - } - - fn fevent(&self, file: usize, _flags: usize) -> Result { - Ok(file) - } - - fn fsync(&self, _file: usize) -> Result { - Ok(0) - } - - fn close(&self, _file: usize) -> Result { - Ok(0) - } -} diff --git a/kernel/src/scheme/live.rs b/kernel/src/scheme/live.rs deleted file mode 100644 index c3f77ff..0000000 --- a/kernel/src/scheme/live.rs +++ /dev/null @@ -1,160 +0,0 @@ -/// Disk scheme replacement when making live disk - -use alloc::arc::Arc; -use collections::{BTreeMap, Vec}; -use core::cmp; -use core::sync::atomic::{AtomicUsize, Ordering}; -use spin::RwLock; - -use syscall::data::Stat; -use syscall::error::*; -use syscall::flag::{MODE_FILE, SEEK_SET, SEEK_CUR, SEEK_END}; -use syscall::scheme::Scheme; - -static FILESYSTEM: &'static [u8] = include_bytes!("../../../build/filesystem.bin"); - -struct Handle { - path: &'static [u8], - data: Arc>>, - mode: u16, - seek: usize -} - -pub struct DiskScheme { - next_id: AtomicUsize, - data: Arc>>, - handles: RwLock> -} - -impl DiskScheme { - pub fn new() -> DiskScheme { - DiskScheme { - next_id: AtomicUsize::new(0), - data: Arc::new(RwLock::new(FILESYSTEM.to_vec())), - handles: RwLock::new(BTreeMap::new()) - } - } -} - -impl Scheme for DiskScheme { - fn open(&self, _path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result { - let id = self.next_id.fetch_add(1, Ordering::SeqCst); - self.handles.write().insert(id, Handle { - path: b"0", - data: self.data.clone(), - mode: MODE_FILE | 0o744, - seek: 0 - }); - - Ok(id) - } - - fn dup(&self, id: usize, _buf: &[u8]) -> Result { - let (path, data, mode, seek) = { - let handles = self.handles.read(); - let handle = handles.get(&id).ok_or(Error::new(EBADF))?; - (handle.path, handle.data.clone(), handle.mode, handle.seek) - }; - - let id = self.next_id.fetch_add(1, Ordering::SeqCst); - self.handles.write().insert(id, Handle { - path: path, - data: data, - mode: mode, - seek: seek - }); - - Ok(id) - } - - fn read(&self, id: usize, buffer: &mut [u8]) -> Result { - let mut handles = self.handles.write(); - let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; - let data = handle.data.read(); - - let mut i = 0; - while i < buffer.len() && handle.seek < data.len() { - buffer[i] = data[handle.seek]; - i += 1; - handle.seek += 1; - } - - Ok(i) - } - - fn write(&self, id: usize, buffer: &[u8]) -> Result { - let mut handles = self.handles.write(); - let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; - let mut data = handle.data.write(); - - let mut i = 0; - while i < buffer.len() && handle.seek < data.len() { - data[handle.seek] = buffer[i]; - i += 1; - handle.seek += 1; - } - - Ok(i) - } - - fn seek(&self, id: usize, pos: usize, whence: usize) -> Result { - let mut handles = self.handles.write(); - let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; - let data = handle.data.read(); - - handle.seek = match whence { - SEEK_SET => cmp::min(data.len(), pos), - SEEK_CUR => cmp::max(0, cmp::min(data.len() as isize, handle.seek as isize + pos as isize)) as usize, - SEEK_END => cmp::max(0, cmp::min(data.len() as isize, data.len() as isize + pos as isize)) as usize, - _ => return Err(Error::new(EINVAL)) - }; - - Ok(handle.seek) - } - - fn fpath(&self, id: usize, buf: &mut [u8]) -> Result { - let handles = self.handles.read(); - let handle = handles.get(&id).ok_or(Error::new(EBADF))?; - - //TODO: Copy scheme part in kernel - let mut i = 0; - let scheme_path = b"disk:"; - while i < buf.len() && i < scheme_path.len() { - buf[i] = scheme_path[i]; - i += 1; - } - - let mut j = 0; - while i < buf.len() && j < handle.path.len() { - buf[i] = handle.path[j]; - i += 1; - j += 1; - } - - Ok(i) - } - - fn fstat(&self, id: usize, stat: &mut Stat) -> Result { - let handles = self.handles.read(); - let handle = handles.get(&id).ok_or(Error::new(EBADF))?; - let data = handle.data.read(); - - stat.st_mode = handle.mode; - stat.st_uid = 0; - stat.st_gid = 0; - stat.st_size = data.len() as u64; - - Ok(0) - } - - fn fsync(&self, id: usize) -> Result { - let handles = self.handles.read(); - let _handle = handles.get(&id).ok_or(Error::new(EBADF))?; - - Ok(0) - } - - fn close(&self, id: usize) -> Result { - self.handles.write().remove(&id).ok_or(Error::new(EBADF)).and(Ok(0)) - } -} diff --git a/kernel/src/scheme/memory.rs b/kernel/src/scheme/memory.rs deleted file mode 100644 index 9db0c48..0000000 --- a/kernel/src/scheme/memory.rs +++ /dev/null @@ -1,30 +0,0 @@ -use arch::memory::{free_frames, used_frames}; - -use syscall::data::StatVfs; -use syscall::error::*; -use syscall::scheme::Scheme; - -pub struct MemoryScheme; - -impl Scheme for MemoryScheme { - fn open(&self, _path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result { - Ok(0) - } - - fn fstatvfs(&self, _file: usize, stat: &mut StatVfs) -> Result { - let used = used_frames() as u64; - let free = free_frames() as u64; - - stat.f_bsize = 4096; - stat.f_blocks = used + free; - stat.f_bfree = free; - stat.f_bavail = stat.f_bfree; - - Ok(0) - } - - /// Close the file `number` - fn close(&self, _file: usize) -> Result { - Ok(0) - } -} diff --git a/kernel/src/scheme/mod.rs b/kernel/src/scheme/mod.rs deleted file mode 100644 index 3f0c5a7..0000000 --- a/kernel/src/scheme/mod.rs +++ /dev/null @@ -1,246 +0,0 @@ -//! # Schemes -//! A scheme is a primitive for handling filesystem syscalls in Redox. -//! Schemes accept paths from the kernel for `open`, and file descriptors that they generate -//! are then passed for operations like `close`, `read`, `write`, etc. -//! -//! The kernel validates paths and file descriptors before they are passed to schemes, -//! also stripping the scheme identifier of paths if necessary. - -use alloc::arc::Arc; -use alloc::boxed::Box; -use collections::BTreeMap; -use core::sync::atomic::AtomicUsize; -use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard}; - -use syscall::error::*; -use syscall::scheme::Scheme; - -use self::debug::DebugScheme; -use self::event::EventScheme; -use self::env::EnvScheme; -use self::initfs::InitFsScheme; -use self::irq::IrqScheme; -use self::memory::MemoryScheme; -use self::null::NullScheme; -use self::pipe::PipeScheme; -use self::root::RootScheme; -use self::sys::SysScheme; -use self::zero::ZeroScheme; - -/// `debug:` - provides access to serial console -pub mod debug; - -/// `event:` - allows reading of `Event`s which are registered using `fevent` -pub mod event; - -/// `env:` - access and modify environmental variables -pub mod env; - -/// `initfs:` - a readonly filesystem used for initializing the system -pub mod initfs; - -/// `irq:` - allows userspace handling of IRQs -pub mod irq; - -/// When compiled with "live" feature - `disk:` - embedded filesystem for live disk -#[cfg(feature="live")] -pub mod live; - -/// `memory:` - a scheme for accessing physical memory -pub mod memory; - -/// `null:` - a scheme that will discard all writes, and read no bytes -pub mod null; - -/// `pipe:` - used internally by the kernel to implement `pipe` -pub mod pipe; - -/// `:` - allows the creation of userspace schemes, tightly dependent on `user` -pub mod root; - -/// `sys:` - system information, such as the context list and scheme list -pub mod sys; - -/// A wrapper around userspace schemes, tightly dependent on `root` -pub mod user; - -/// `zero:` - a scheme that will discard all writes, and always fill read buffers with zero -pub mod zero; - -/// Limit on number of schemes -pub const SCHEME_MAX_SCHEMES: usize = 65536; - -/// Unique identifier for a scheme namespace. -int_like!(SchemeNamespace, AtomicSchemeNamespace, usize, AtomicUsize); - -/// Unique identifier for a scheme. -int_like!(SchemeId, AtomicSchemeId, usize, AtomicUsize); - -pub const ATOMIC_SCHEMEID_INIT: AtomicSchemeId = AtomicSchemeId::default(); - -/// Unique identifier for a file descriptor. -int_like!(FileHandle, AtomicFileHandle, usize, AtomicUsize); - -/// Scheme list type -pub struct SchemeList { - map: BTreeMap>>, - names: BTreeMap, SchemeId>>, - next_ns: usize, - next_id: usize -} - -impl SchemeList { - /// Create a new scheme list. - pub fn new() -> Self { - let mut list = SchemeList { - map: BTreeMap::new(), - names: BTreeMap::new(), - next_ns: 0, - next_id: 1 - }; - list.new_root(); - list - } - - /// Initialize a new namespace - fn new_ns(&mut self) -> SchemeNamespace { - let ns = SchemeNamespace(self.next_ns); - self.next_ns += 1; - self.names.insert(ns, BTreeMap::new()); - - self.insert(ns, Box::new(*b""), |scheme_id| Arc::new(Box::new(RootScheme::new(ns, scheme_id)))).unwrap(); - self.insert(ns, Box::new(*b"event"), |_| Arc::new(Box::new(EventScheme::new()))).unwrap(); - self.insert(ns, Box::new(*b"env"), |_| Arc::new(Box::new(EnvScheme::new()))).unwrap(); - self.insert(ns, Box::new(*b"null"), |_| Arc::new(Box::new(NullScheme))).unwrap(); - self.insert(ns, Box::new(*b"sys"), |_| Arc::new(Box::new(SysScheme::new()))).unwrap(); - self.insert(ns, Box::new(*b"zero"), |_| Arc::new(Box::new(ZeroScheme))).unwrap(); - - ns - } - - /// Initialize the root namespace - #[cfg(not(feature="live"))] - fn new_root(&mut self) { - // Do common namespace initialization - let ns = self.new_ns(); - - // Debug, Initfs and IRQ are only available in the root namespace. Pipe is special - self.insert(ns, Box::new(*b"debug"), |scheme_id| Arc::new(Box::new(DebugScheme::new(scheme_id)))).unwrap(); - self.insert(ns, Box::new(*b"initfs"), |_| Arc::new(Box::new(InitFsScheme::new()))).unwrap(); - self.insert(ns, Box::new(*b"irq"), |scheme_id| Arc::new(Box::new(IrqScheme::new(scheme_id)))).unwrap(); - self.insert(ns, Box::new(*b"memory"), |_| Arc::new(Box::new(MemoryScheme))).unwrap(); - self.insert(ns, Box::new(*b"pipe"), |scheme_id| Arc::new(Box::new(PipeScheme::new(scheme_id)))).unwrap(); - } - - /// Initialize the root namespace - with live disk - #[cfg(feature="live")] - fn new_root(&mut self) { - // Do common namespace initialization - let ns = self.new_ns(); - - // Debug, Disk, Initfs and IRQ are only available in the root namespace. Pipe is special - self.insert(ns, Box::new(*b"debug"), |scheme_id| Arc::new(Box::new(DebugScheme::new(scheme_id)))).unwrap(); - self.insert(ns, Box::new(*b"disk"), |_| Arc::new(Box::new(self::live::DiskScheme::new()))).unwrap(); - self.insert(ns, Box::new(*b"initfs"), |_| Arc::new(Box::new(InitFsScheme::new()))).unwrap(); - self.insert(ns, Box::new(*b"irq"), |scheme_id| Arc::new(Box::new(IrqScheme::new(scheme_id)))).unwrap(); - self.insert(ns, Box::new(*b"memory"), |_| Arc::new(Box::new(MemoryScheme))).unwrap(); - self.insert(ns, Box::new(*b"pipe"), |scheme_id| Arc::new(Box::new(PipeScheme::new(scheme_id)))).unwrap(); - } - - pub fn make_ns(&mut self, from: SchemeNamespace, names: &[&[u8]]) -> Result { - // Create an empty namespace - let to = self.new_ns(); - - // Copy requested scheme IDs - for name in names.iter() { - let id = if let Some((id, _scheme)) = self.get_name(from, name) { - id - } else { - return Err(Error::new(ENODEV)); - }; - - if let Some(ref mut names) = self.names.get_mut(&to) { - assert!(names.insert(name.to_vec().into_boxed_slice(), id).is_none()); - } else { - panic!("scheme namespace not found"); - } - } - - Ok(to) - } - - pub fn iter(&self) -> ::collections::btree_map::Iter>> { - self.map.iter() - } - - pub fn iter_name(&self, ns: SchemeNamespace) -> ::collections::btree_map::Iter, SchemeId> { - self.names[&ns].iter() - } - - /// Get the nth scheme. - pub fn get(&self, id: SchemeId) -> Option<&Arc>> { - self.map.get(&id) - } - - pub fn get_name(&self, ns: SchemeNamespace, name: &[u8]) -> Option<(SchemeId, &Arc>)> { - if let Some(&id) = self.names[&ns].get(name) { - self.get(id).map(|scheme| (id, scheme)) - } else { - None - } - } - - /// Create a new scheme. - pub fn insert(&mut self, ns: SchemeNamespace, name: Box<[u8]>, scheme_fn: F) -> Result - where F: Fn(SchemeId) -> Arc> - { - if self.names[&ns].contains_key(&name) { - return Err(Error::new(EEXIST)); - } - - if self.next_id >= SCHEME_MAX_SCHEMES { - self.next_id = 1; - } - - while self.map.contains_key(&SchemeId(self.next_id)) { - self.next_id += 1; - } - - /* Allow scheme list to grow if required - if self.next_id >= SCHEME_MAX_SCHEMES { - return Err(Error::new(EAGAIN)); - } - */ - - let id = SchemeId(self.next_id); - self.next_id += 1; - - let scheme = scheme_fn(id); - - assert!(self.map.insert(id, scheme).is_none()); - if let Some(ref mut names) = self.names.get_mut(&ns) { - assert!(names.insert(name, id).is_none()); - } else { - panic!("scheme namespace not found"); - } - Ok(id) - } -} - -/// Schemes list -static SCHEMES: Once> = Once::new(); - -/// Initialize schemes, called if needed -fn init_schemes() -> RwLock { - RwLock::new(SchemeList::new()) -} - -/// Get the global schemes list, const -pub fn schemes() -> RwLockReadGuard<'static, SchemeList> { - SCHEMES.call_once(init_schemes).read() -} - -/// Get the global schemes list, mutable -pub fn schemes_mut() -> RwLockWriteGuard<'static, SchemeList> { - SCHEMES.call_once(init_schemes).write() -} diff --git a/kernel/src/scheme/null.rs b/kernel/src/scheme/null.rs deleted file mode 100644 index 690c16c..0000000 --- a/kernel/src/scheme/null.rs +++ /dev/null @@ -1,37 +0,0 @@ -use syscall::error::*; -use syscall::scheme::Scheme; - -pub struct NullScheme; - -impl Scheme for NullScheme { - fn open(&self, _path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result { - Ok(0) - } - - fn dup(&self, _file: usize, _buf: &[u8]) -> Result { - Ok(0) - } - - /// Read the file `number` into the `buffer` - /// - /// Returns the number of bytes read - fn read(&self, _file: usize, _buf: &mut [u8]) -> Result { - Ok(0) - } - - /// Write the `buffer` to the `file` - /// - /// Returns the number of bytes written - fn write(&self, _file: usize, buffer: &[u8]) -> Result { - Ok(buffer.len()) - } - - fn fsync(&self, _file: usize) -> Result { - Ok(0) - } - - /// Close the file `number` - fn close(&self, _file: usize) -> Result { - Ok(0) - } -} diff --git a/kernel/src/scheme/pipe.rs b/kernel/src/scheme/pipe.rs deleted file mode 100644 index 5e64350..0000000 --- a/kernel/src/scheme/pipe.rs +++ /dev/null @@ -1,272 +0,0 @@ -use alloc::arc::{Arc, Weak}; -use collections::{BTreeMap, VecDeque}; -use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; -use spin::{Mutex, Once, RwLock, RwLockReadGuard, RwLockWriteGuard}; -use scheme::{AtomicSchemeId, ATOMIC_SCHEMEID_INIT, SchemeId}; - -use sync::WaitCondition; -use syscall::error::{Error, Result, EAGAIN, EBADF, EINVAL, EPIPE}; -use syscall::flag::{F_GETFL, F_SETFL, O_ACCMODE, O_CLOEXEC, O_NONBLOCK}; -use syscall::scheme::Scheme; - -/// Pipes list -pub static PIPE_SCHEME_ID: AtomicSchemeId = ATOMIC_SCHEMEID_INIT; -static PIPE_NEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT; -static PIPES: Once>, BTreeMap>)>> = Once::new(); - -/// Initialize pipes, called if needed -fn init_pipes() -> RwLock<(BTreeMap>, BTreeMap>)> { - RwLock::new((BTreeMap::new(), BTreeMap::new())) -} - -/// Get the global pipes list, const -fn pipes() -> RwLockReadGuard<'static, (BTreeMap>, BTreeMap>)> { - PIPES.call_once(init_pipes).read() -} - -/// Get the global schemes list, mutable -fn pipes_mut() -> RwLockWriteGuard<'static, (BTreeMap>, BTreeMap>)> { - PIPES.call_once(init_pipes).write() -} - -pub fn pipe(flags: usize) -> (usize, usize) { - let mut pipes = pipes_mut(); - let read_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst); - let write_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst); - let read = PipeRead::new(flags); - let write = PipeWrite::new(flags, &read); - pipes.0.insert(read_id, Arc::new(read)); - pipes.1.insert(write_id, Arc::new(write)); - (read_id, write_id) -} - -pub struct PipeScheme; - -impl PipeScheme { - pub fn new(scheme_id: SchemeId) -> PipeScheme { - PIPE_SCHEME_ID.store(scheme_id, Ordering::SeqCst); - PipeScheme - } -} - -impl Scheme for PipeScheme { - fn dup(&self, id: usize, buf: &[u8]) -> Result { - let mut pipes = pipes_mut(); - - let read_option = if let Some(pipe) = pipes.0.get(&id) { - Some(pipe.dup(buf)?) - } else { - None - }; - if let Some(pipe) = read_option { - let pipe_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst); - pipes.0.insert(pipe_id, Arc::new(pipe)); - return Ok(pipe_id); - } - - let write_option = if let Some(pipe) = pipes.1.get(&id) { - Some(pipe.dup(buf)?) - } else { - None - }; - if let Some(pipe) = write_option { - let pipe_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst); - pipes.1.insert(pipe_id, Arc::new(pipe)); - return Ok(pipe_id); - } - - Err(Error::new(EBADF)) - } - - fn read(&self, id: usize, buf: &mut [u8]) -> Result { - // Clone to prevent deadlocks - let pipe = { - let pipes = pipes(); - pipes.0.get(&id).map(|pipe| pipe.clone()).ok_or(Error::new(EBADF))? - }; - - pipe.read(buf) - } - - fn write(&self, id: usize, buf: &[u8]) -> Result { - // Clone to prevent deadlocks - let pipe = { - let pipes = pipes(); - pipes.1.get(&id).map(|pipe| pipe.clone()).ok_or(Error::new(EBADF))? - }; - - pipe.write(buf) - } - - fn fcntl(&self, id: usize, cmd: usize, arg: usize) -> Result { - let pipes = pipes(); - - if let Some(pipe) = pipes.0.get(&id) { - return pipe.fcntl(cmd, arg); - } - - if let Some(pipe) = pipes.1.get(&id) { - return pipe.fcntl(cmd, arg); - } - - Err(Error::new(EBADF)) - } - - fn fsync(&self, _id: usize) -> Result { - Ok(0) - } - - fn close(&self, id: usize) -> Result { - let mut pipes = pipes_mut(); - - drop(pipes.0.remove(&id)); - drop(pipes.1.remove(&id)); - - Ok(0) - } -} - -/// Read side of a pipe -pub struct PipeRead { - flags: AtomicUsize, - condition: Arc, - vec: Arc>> -} - -impl PipeRead { - pub fn new(flags: usize) -> Self { - PipeRead { - flags: AtomicUsize::new(flags), - condition: Arc::new(WaitCondition::new()), - vec: Arc::new(Mutex::new(VecDeque::new())), - } - } - - fn dup(&self, buf: &[u8]) -> Result { - if buf == b"exec" && self.flags.load(Ordering::SeqCst) & O_CLOEXEC == O_CLOEXEC { - Err(Error::new(EBADF)) - } else { - let mut flags = self.flags.load(Ordering::SeqCst); - if buf.is_empty() { - flags &= ! O_CLOEXEC; - } - Ok(PipeRead { - flags: AtomicUsize::new(flags), - condition: self.condition.clone(), - vec: self.vec.clone() - }) - } - } - - fn fcntl(&self, cmd: usize, arg: usize) -> Result { - match cmd { - F_GETFL => Ok(self.flags.load(Ordering::SeqCst)), - F_SETFL => { - self.flags.store(arg & ! O_ACCMODE, Ordering::SeqCst); - Ok(0) - }, - _ => Err(Error::new(EINVAL)) - } - } - - fn read(&self, buf: &mut [u8]) -> Result { - loop { - { - let mut vec = self.vec.lock(); - - let mut i = 0; - while i < buf.len() { - if let Some(b) = vec.pop_front() { - buf[i] = b; - i += 1; - } else { - break; - } - } - - if i > 0 { - return Ok(i); - } - } - - if Arc::weak_count(&self.vec) == 0 { - return Ok(0); - } else if self.flags.load(Ordering::SeqCst) & O_NONBLOCK == O_NONBLOCK { - return Err(Error::new(EAGAIN)); - } else { - self.condition.wait(); - } - } - } -} - -/// Read side of a pipe -pub struct PipeWrite { - flags: AtomicUsize, - condition: Arc, - vec: Option>>> -} - -impl PipeWrite { - pub fn new(flags: usize, read: &PipeRead) -> Self { - PipeWrite { - flags: AtomicUsize::new(flags), - condition: read.condition.clone(), - vec: Some(Arc::downgrade(&read.vec)), - } - } - - fn dup(&self, buf: &[u8]) -> Result { - if buf == b"exec" && self.flags.load(Ordering::SeqCst) & O_CLOEXEC == O_CLOEXEC { - Err(Error::new(EBADF)) - } else { - let mut flags = self.flags.load(Ordering::SeqCst); - if buf.is_empty() { - flags &= ! O_CLOEXEC; - } - Ok(PipeWrite { - flags: AtomicUsize::new(flags), - condition: self.condition.clone(), - vec: self.vec.clone() - }) - } - } - - fn fcntl(&self, cmd: usize, arg: usize) -> Result { - match cmd { - F_GETFL => Ok(self.flags.load(Ordering::SeqCst)), - F_SETFL => { - self.flags.store(arg & ! O_ACCMODE, Ordering::SeqCst); - Ok(0) - }, - _ => Err(Error::new(EINVAL)) - } - } - - fn write(&self, buf: &[u8]) -> Result { - if let Some(ref vec_weak) = self.vec { - if let Some(vec_lock) = vec_weak.upgrade() { - let mut vec = vec_lock.lock(); - - for &b in buf.iter() { - vec.push_back(b); - } - - self.condition.notify(); - - Ok(buf.len()) - } else { - Err(Error::new(EPIPE)) - } - } else { - panic!("PipeWrite dropped before write"); - } - } -} - -impl Drop for PipeWrite { - fn drop(&mut self) { - drop(self.vec.take()); - self.condition.notify(); - } -} diff --git a/kernel/src/scheme/root.rs b/kernel/src/scheme/root.rs deleted file mode 100644 index 1860998..0000000 --- a/kernel/src/scheme/root.rs +++ /dev/null @@ -1,116 +0,0 @@ -use alloc::arc::Arc; -use alloc::boxed::Box; -use collections::BTreeMap; -use core::sync::atomic::{AtomicUsize, Ordering}; -use spin::RwLock; - -use context; -use syscall::error::*; -use syscall::scheme::Scheme; -use scheme::{self, SchemeNamespace, SchemeId}; -use scheme::user::{UserInner, UserScheme}; - -pub struct RootScheme { - scheme_ns: SchemeNamespace, - scheme_id: SchemeId, - next_id: AtomicUsize, - handles: RwLock>> -} - -impl RootScheme { - pub fn new(scheme_ns: SchemeNamespace, scheme_id: SchemeId) -> RootScheme { - RootScheme { - scheme_ns: scheme_ns, - scheme_id: scheme_id, - next_id: AtomicUsize::new(0), - handles: RwLock::new(BTreeMap::new()) - } - } -} - -impl Scheme for RootScheme { - fn open(&self, path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result { - if uid == 0 { - let context = { - let contexts = context::contexts(); - let context = contexts.current().ok_or(Error::new(ESRCH))?; - Arc::downgrade(&context) - }; - - let id = self.next_id.fetch_add(1, Ordering::SeqCst); - - let inner = { - let mut schemes = scheme::schemes_mut(); - let inner = Arc::new(UserInner::new(self.scheme_id, id, flags, context)); - schemes.insert(self.scheme_ns, path.to_vec().into_boxed_slice(), |scheme_id| { - inner.scheme_id.store(scheme_id, Ordering::SeqCst); - Arc::new(Box::new(UserScheme::new(Arc::downgrade(&inner)))) - })?; - inner - }; - - self.handles.write().insert(id, inner); - - Ok(id) - } else { - Err(Error::new(EACCES)) - } - } - - fn dup(&self, file: usize, _buf: &[u8]) -> Result { - let mut handles = self.handles.write(); - let inner = { - let inner = handles.get(&file).ok_or(Error::new(EBADF))?; - inner.clone() - }; - - let id = self.next_id.fetch_add(1, Ordering::SeqCst); - handles.insert(id, inner); - - Ok(id) - } - - fn read(&self, file: usize, buf: &mut [u8]) -> Result { - let inner = { - let handles = self.handles.read(); - let inner = handles.get(&file).ok_or(Error::new(EBADF))?; - inner.clone() - }; - - inner.read(buf) - } - - fn write(&self, file: usize, buf: &[u8]) -> Result { - let inner = { - let handles = self.handles.read(); - let inner = handles.get(&file).ok_or(Error::new(EBADF))?; - inner.clone() - }; - - inner.write(buf) - } - - fn fevent(&self, file: usize, flags: usize) -> Result { - let inner = { - let handles = self.handles.read(); - let inner = handles.get(&file).ok_or(Error::new(EBADF))?; - inner.clone() - }; - - inner.fevent(flags) - } - - fn fsync(&self, file: usize) -> Result { - let inner = { - let handles = self.handles.read(); - let inner = handles.get(&file).ok_or(Error::new(EBADF))?; - inner.clone() - }; - - inner.fsync() - } - - fn close(&self, file: usize) -> Result { - self.handles.write().remove(&file).ok_or(Error::new(EBADF)).and(Ok(0)) - } -} diff --git a/kernel/src/scheme/sys/context.rs b/kernel/src/scheme/sys/context.rs deleted file mode 100644 index a28820d..0000000 --- a/kernel/src/scheme/sys/context.rs +++ /dev/null @@ -1,106 +0,0 @@ -use collections::{String, Vec}; -use core::str; - -use context; -use syscall::error::Result; - -pub fn resource() -> Result> { - let mut string = format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{}\n", - "PID", - "PPID", - "RUID", - "RGID", - "RNS", - "EUID", - "EGID", - "ENS", - "STAT", - "CPU", - "MEM", - "NAME"); - { - let contexts = context::contexts(); - for (_id, context_lock) in contexts.iter() { - let context = context_lock.read(); - - let mut stat_string = String::new(); - if context.stack.is_some() { - stat_string.push('U'); - } else { - stat_string.push('K'); - } - match context.status { - context::Status::Runnable => { - stat_string.push('R'); - }, - context::Status::Blocked => if context.wake.is_some() { - stat_string.push('S'); - } else { - stat_string.push('B'); - }, - context::Status::Exited(_status) => { - stat_string.push('Z'); - } - } - if context.running { - stat_string.push('+'); - } - - let cpu_string = if let Some(cpu_id) = context.cpu_id { - format!("{}", cpu_id) - } else { - format!("?") - }; - - let mut memory = 0; - if let Some(ref kfx) = context.kstack { - memory += kfx.len(); - } - if let Some(ref kstack) = context.kstack { - memory += kstack.len(); - } - for shared_mem in context.image.iter() { - shared_mem.with(|mem| { - memory += mem.size(); - }); - } - if let Some(ref heap) = context.heap { - heap.with(|heap| { - memory += heap.size(); - }); - } - if let Some(ref stack) = context.stack { - memory += stack.size(); - } - - let memory_string = if memory >= 1024 * 1024 * 1024 { - format!("{} GB", memory / 1024 / 1024 / 1024) - } else if memory >= 1024 * 1024 { - format!("{} MB", memory / 1024 / 1024) - } else if memory >= 1024 { - format!("{} KB", memory / 1024) - } else { - format!("{} B", memory) - }; - - let name_bytes = context.name.lock(); - let name = str::from_utf8(&name_bytes).unwrap_or(""); - - string.push_str(&format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{}\n", - context.id.into(), - context.ppid.into(), - context.ruid, - context.rgid, - context.rns.into(), - context.euid, - context.egid, - context.ens.into(), - stat_string, - cpu_string, - memory_string, - name)); - } - } - - Ok(string.into_bytes()) -} diff --git a/kernel/src/scheme/sys/cpu.rs b/kernel/src/scheme/sys/cpu.rs deleted file mode 100644 index 70c1694..0000000 --- a/kernel/src/scheme/sys/cpu.rs +++ /dev/null @@ -1,13 +0,0 @@ -use collections::Vec; - -use arch::device::cpu::cpu_info; -use syscall::error::{Error, EIO, Result}; - -pub fn resource() -> Result> { - let mut string = format!("CPUs: {}\n", ::cpu_count()); - - match cpu_info(&mut string) { - Ok(()) => Ok(string.into_bytes()), - Err(_) => Err(Error::new(EIO)) - } -} diff --git a/kernel/src/scheme/sys/exe.rs b/kernel/src/scheme/sys/exe.rs deleted file mode 100644 index 84eb266..0000000 --- a/kernel/src/scheme/sys/exe.rs +++ /dev/null @@ -1,16 +0,0 @@ -use collections::Vec; - -use context; -use syscall::error::{Error, ESRCH, Result}; - -pub fn resource() -> Result> { - let mut name = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - let name = context.name.lock(); - name.clone() - }; - name.push(b'\n'); - Ok(name) -} diff --git a/kernel/src/scheme/sys/mod.rs b/kernel/src/scheme/sys/mod.rs deleted file mode 100644 index ce5fd23..0000000 --- a/kernel/src/scheme/sys/mod.rs +++ /dev/null @@ -1,183 +0,0 @@ -use alloc::boxed::Box; -use collections::{BTreeMap, Vec}; -use core::{cmp, str}; -use core::sync::atomic::{AtomicUsize, Ordering}; -use spin::RwLock; - -use syscall::data::Stat; -use syscall::error::{Error, EBADF, EINVAL, ENOENT, Result}; -use syscall::flag::{MODE_DIR, MODE_FILE, SEEK_CUR, SEEK_END, SEEK_SET}; -use syscall::scheme::Scheme; - -mod context; -mod cpu; -mod exe; -mod scheme; -//mod interrupt; -//mod log; -//mod test; - -struct Handle { - path: &'static [u8], - data: Vec, - mode: u16, - seek: usize -} - -type SysFn = Fn() -> Result> + Send + Sync; - -/// System information scheme -pub struct SysScheme { - next_id: AtomicUsize, - files: BTreeMap<&'static [u8], Box>, - handles: RwLock> -} - -impl SysScheme { - pub fn new() -> SysScheme { - let mut files: BTreeMap<&'static [u8], Box> = BTreeMap::new(); - - files.insert(b"context", Box::new(move || context::resource())); - files.insert(b"cpu", Box::new(move || cpu::resource())); - files.insert(b"exe", Box::new(move || exe::resource())); - files.insert(b"scheme", Box::new(move || scheme::resource())); - //files.insert(b"interrupt", Box::new(move || interrupt::resource())); - //files.insert(b"log", Box::new(move || log::resource())); - //files.insert(b"test", Box::new(move || test::resource())); - - SysScheme { - next_id: AtomicUsize::new(0), - files: files, - handles: RwLock::new(BTreeMap::new()) - } - } -} - -impl Scheme for SysScheme { - fn open(&self, path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result { - let path_utf8 = str::from_utf8(path).map_err(|_err| Error::new(ENOENT))?; - let path_trimmed = path_utf8.trim_matches('/'); - - if path_trimmed.is_empty() { - let mut data = Vec::new(); - for entry in self.files.iter() { - if ! data.is_empty() { - data.push(b'\n'); - } - data.extend_from_slice(entry.0); - } - - let id = self.next_id.fetch_add(1, Ordering::SeqCst); - self.handles.write().insert(id, Handle { - path: b"", - data: data, - mode: MODE_DIR | 0o444, - seek: 0 - }); - return Ok(id) - } else { - //Have to iterate to get the path without allocation - for entry in self.files.iter() { - if entry.0 == &path_trimmed.as_bytes() { - let id = self.next_id.fetch_add(1, Ordering::SeqCst); - self.handles.write().insert(id, Handle { - path: entry.0, - data: entry.1()?, - mode: MODE_FILE | 0o444, - seek: 0 - }); - return Ok(id) - } - } - } - - Err(Error::new(ENOENT)) - } - - fn dup(&self, id: usize, _buf: &[u8]) -> Result { - let (path, data, mode, seek) = { - let handles = self.handles.read(); - let handle = handles.get(&id).ok_or(Error::new(EBADF))?; - (handle.path, handle.data.clone(), handle.mode, handle.seek) - }; - - let id = self.next_id.fetch_add(1, Ordering::SeqCst); - self.handles.write().insert(id, Handle { - path: path, - data: data, - mode: mode, - seek: seek - }); - - Ok(id) - } - - fn read(&self, id: usize, buffer: &mut [u8]) -> Result { - let mut handles = self.handles.write(); - let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; - - let mut i = 0; - while i < buffer.len() && handle.seek < handle.data.len() { - buffer[i] = handle.data[handle.seek]; - i += 1; - handle.seek += 1; - } - - Ok(i) - } - - fn seek(&self, id: usize, pos: usize, whence: usize) -> Result { - let mut handles = self.handles.write(); - let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; - - handle.seek = match whence { - SEEK_SET => cmp::min(handle.data.len(), pos), - SEEK_CUR => cmp::max(0, cmp::min(handle.data.len() as isize, handle.seek as isize + pos as isize)) as usize, - SEEK_END => cmp::max(0, cmp::min(handle.data.len() as isize, handle.data.len() as isize + pos as isize)) as usize, - _ => return Err(Error::new(EINVAL)) - }; - - Ok(handle.seek) - } - - fn fpath(&self, id: usize, buf: &mut [u8]) -> Result { - let handles = self.handles.read(); - let handle = handles.get(&id).ok_or(Error::new(EBADF))?; - - let mut i = 0; - let scheme_path = b"sys:"; - while i < buf.len() && i < scheme_path.len() { - buf[i] = scheme_path[i]; - i += 1; - } - - let mut j = 0; - while i < buf.len() && j < handle.path.len() { - buf[i] = handle.path[j]; - i += 1; - j += 1; - } - - Ok(i) - } - - fn fstat(&self, id: usize, stat: &mut Stat) -> Result { - let handles = self.handles.read(); - let handle = handles.get(&id).ok_or(Error::new(EBADF))?; - - stat.st_mode = handle.mode; - stat.st_uid = 0; - stat.st_gid = 0; - stat.st_size = handle.data.len() as u64; - - Ok(0) - } - - fn fsync(&self, _id: usize) -> Result { - Ok(0) - } - - fn close(&self, id: usize) -> Result { - self.handles.write().remove(&id).ok_or(Error::new(EBADF)).and(Ok(0)) - } -} diff --git a/kernel/src/scheme/sys/scheme.rs b/kernel/src/scheme/sys/scheme.rs deleted file mode 100644 index b0f0c7d..0000000 --- a/kernel/src/scheme/sys/scheme.rs +++ /dev/null @@ -1,24 +0,0 @@ -use collections::Vec; - -use context; -use scheme; -use syscall::error::{Error, ESRCH, Result}; - -pub fn resource() -> Result> { - let scheme_ns = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - context.ens - }; - - let mut data = Vec::new(); - - let schemes = scheme::schemes(); - for (name, _scheme_lock) in schemes.iter_name(scheme_ns) { - data.extend_from_slice(name); - data.push(b'\n'); - } - - Ok(data) -} diff --git a/kernel/src/scheme/user.rs b/kernel/src/scheme/user.rs deleted file mode 100644 index 589a8c9..0000000 --- a/kernel/src/scheme/user.rs +++ /dev/null @@ -1,354 +0,0 @@ -use alloc::arc::{Arc, Weak}; -use collections::BTreeMap; -use core::sync::atomic::{AtomicU64, Ordering}; -use core::{mem, slice, usize}; -use spin::{Mutex, RwLock}; - -use arch; -use arch::paging::{InactivePageTable, Page, VirtualAddress, entry}; -use arch::paging::temporary_page::TemporaryPage; -use context::{self, Context}; -use context::memory::Grant; -use scheme::{AtomicSchemeId, ATOMIC_SCHEMEID_INIT, SchemeId}; -use sync::{WaitQueue, WaitMap}; -use syscall::data::{Packet, Stat, StatVfs}; -use syscall::error::*; -use syscall::flag::{EVENT_READ, O_NONBLOCK}; -use syscall::number::*; -use syscall::scheme::Scheme; - -pub struct UserInner { - root_id: SchemeId, - handle_id: usize, - flags: usize, - pub scheme_id: AtomicSchemeId, - next_id: AtomicU64, - context: Weak>, - todo: WaitQueue, - fmap: Mutex>, usize)>>, - done: WaitMap -} - -impl UserInner { - pub fn new(root_id: SchemeId, handle_id: usize, flags: usize, context: Weak>) -> UserInner { - UserInner { - root_id: root_id, - handle_id: handle_id, - flags: flags, - scheme_id: ATOMIC_SCHEMEID_INIT, - next_id: AtomicU64::new(1), - context: context, - todo: WaitQueue::new(), - fmap: Mutex::new(BTreeMap::new()), - done: WaitMap::new() - } - } - - pub fn call(&self, a: usize, b: usize, c: usize, d: usize) -> Result { - let (pid, uid, gid) = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - (context.id, context.euid, context.egid) - }; - - self.call_inner(Packet { - id: self.next_id.fetch_add(1, Ordering::SeqCst), - pid: pid.into(), - uid: uid, - gid: gid, - a: a, - b: b, - c: c, - d: d - }) - } - - fn call_inner(&self, packet: Packet) -> Result { - let id = packet.id; - - let len = self.todo.send(packet); - context::event::trigger(self.root_id, self.handle_id, EVENT_READ, mem::size_of::() * len); - - Error::demux(self.done.receive(&id)) - } - - pub fn capture(&self, buf: &[u8]) -> Result { - UserInner::capture_inner(&self.context, buf.as_ptr() as usize, buf.len(), false) - } - - pub fn capture_mut(&self, buf: &mut [u8]) -> Result { - UserInner::capture_inner(&self.context, buf.as_mut_ptr() as usize, buf.len(), true) - } - - fn capture_inner(context_weak: &Weak>, address: usize, size: usize, writable: bool) -> Result { - if size == 0 { - Ok(0) - } else { - let context_lock = context_weak.upgrade().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - - let mut grants = context.grants.lock(); - - let mut new_table = unsafe { InactivePageTable::from_address(context.arch.get_page_table()) }; - let mut temporary_page = TemporaryPage::new(Page::containing_address(VirtualAddress::new(arch::USER_TMP_GRANT_OFFSET))); - - let from_address = (address/4096) * 4096; - let offset = address - from_address; - let full_size = ((offset + size + 4095)/4096) * 4096; - let mut to_address = arch::USER_GRANT_OFFSET; - - let mut flags = entry::PRESENT | entry::NO_EXECUTE | entry::USER_ACCESSIBLE; - if writable { - flags |= entry::WRITABLE; - } - - for i in 0 .. grants.len() { - let start = grants[i].start_address().get(); - if to_address + full_size < start { - grants.insert(i, Grant::map_inactive( - VirtualAddress::new(from_address), - VirtualAddress::new(to_address), - full_size, - flags, - &mut new_table, - &mut temporary_page - )); - - return Ok(to_address + offset); - } else { - let pages = (grants[i].size() + 4095) / 4096; - let end = start + pages * 4096; - to_address = end; - } - } - - grants.push(Grant::map_inactive( - VirtualAddress::new(from_address), - VirtualAddress::new(to_address), - full_size, - flags, - &mut new_table, - &mut temporary_page - )); - - Ok(to_address + offset) - } - } - - pub fn release(&self, address: usize) -> Result<()> { - if address == 0 { - Ok(()) - } else { - let context_lock = self.context.upgrade().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - - let mut grants = context.grants.lock(); - - let mut new_table = unsafe { InactivePageTable::from_address(context.arch.get_page_table()) }; - let mut temporary_page = TemporaryPage::new(Page::containing_address(VirtualAddress::new(arch::USER_TMP_GRANT_OFFSET))); - - for i in 0 .. grants.len() { - let start = grants[i].start_address().get(); - let end = start + grants[i].size(); - if address >= start && address < end { - grants.remove(i).unmap_inactive(&mut new_table, &mut temporary_page); - - return Ok(()); - } - } - - Err(Error::new(EFAULT)) - } - } - - pub fn read(&self, buf: &mut [u8]) -> Result { - let packet_buf = unsafe { slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut Packet, buf.len()/mem::size_of::()) }; - Ok(self.todo.receive_into(packet_buf, self.flags & O_NONBLOCK != O_NONBLOCK) * mem::size_of::()) - } - - pub fn write(&self, buf: &[u8]) -> Result { - let packet_size = mem::size_of::(); - let len = buf.len()/packet_size; - let mut i = 0; - while i < len { - let mut packet = unsafe { *(buf.as_ptr() as *const Packet).offset(i as isize) }; - if packet.id == 0 { - match packet.a { - SYS_FEVENT => context::event::trigger(self.scheme_id.load(Ordering::SeqCst), packet.b, packet.c, packet.d), - _ => println!("Unknown scheme -> kernel message {}", packet.a) - } - } else { - if let Some((context_weak, size)) = self.fmap.lock().remove(&packet.id) { - if let Ok(address) = Error::demux(packet.a) { - packet.a = Error::mux(UserInner::capture_inner(&context_weak, address, size, true)); - } - } - - self.done.send(packet.id, packet.a); - } - i += 1; - } - - Ok(i * packet_size) - } - - pub fn fevent(&self, _flags: usize) -> Result { - Ok(self.handle_id) - } - - pub fn fsync(&self) -> Result { - Ok(0) - } -} - -/// UserInner has to be wrapped -pub struct UserScheme { - inner: Weak -} - -impl UserScheme { - pub fn new(inner: Weak) -> UserScheme { - UserScheme { - inner: inner - } - } -} - -impl Scheme for UserScheme { - fn open(&self, path: &[u8], flags: usize, _uid: u32, _gid: u32) -> Result { - let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - let address = inner.capture(path)?; - let result = inner.call(SYS_OPEN, address, path.len(), flags); - let _ = inner.release(address); - result - } - - fn chmod(&self, path: &[u8], mode: u16, _uid: u32, _gid: u32) -> Result { - let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - let address = inner.capture(path)?; - let result = inner.call(SYS_CHMOD, address, path.len(), mode as usize); - let _ = inner.release(address); - result - } - - fn rmdir(&self, path: &[u8], _uid: u32, _gid: u32) -> Result { - let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - let address = inner.capture(path)?; - let result = inner.call(SYS_RMDIR, address, path.len(), 0); - let _ = inner.release(address); - result - } - - fn unlink(&self, path: &[u8], _uid: u32, _gid: u32) -> Result { - let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - let address = inner.capture(path)?; - let result = inner.call(SYS_UNLINK, address, path.len(), 0); - let _ = inner.release(address); - result - } - - fn dup(&self, file: usize, buf: &[u8]) -> Result { - let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - let address = inner.capture(buf)?; - let result = inner.call(SYS_DUP, file, address, buf.len()); - let _ = inner.release(address); - result - } - - fn read(&self, file: usize, buf: &mut [u8]) -> Result { - let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - let address = inner.capture_mut(buf)?; - let result = inner.call(SYS_READ, file, address, buf.len()); - let _ = inner.release(address); - result - } - - fn write(&self, file: usize, buf: &[u8]) -> Result { - let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - let address = inner.capture(buf)?; - let result = inner.call(SYS_WRITE, file, address, buf.len()); - let _ = inner.release(address); - result - } - - fn seek(&self, file: usize, position: usize, whence: usize) -> Result { - let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - inner.call(SYS_LSEEK, file, position, whence) - } - - fn fcntl(&self, file: usize, cmd: usize, arg: usize) -> Result { - let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - inner.call(SYS_FCNTL, file, cmd, arg) - } - - fn fevent(&self, file: usize, flags: usize) -> Result { - let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - inner.call(SYS_FEVENT, file, flags, 0) - } - - fn fmap(&self, file: usize, offset: usize, size: usize) -> Result { - let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - - let (pid, uid, gid, context_lock) = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - (context.id, context.euid, context.egid, Arc::downgrade(&context_lock)) - }; - - let id = inner.next_id.fetch_add(1, Ordering::SeqCst); - - inner.fmap.lock().insert(id, (context_lock, size)); - - inner.call_inner(Packet { - id: id, - pid: pid.into(), - uid: uid, - gid: gid, - a: SYS_FMAP, - b: file, - c: offset, - d: size - }) - } - - fn fpath(&self, file: usize, buf: &mut [u8]) -> Result { - let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - let address = inner.capture_mut(buf)?; - let result = inner.call(SYS_FPATH, file, address, buf.len()); - let _ = inner.release(address); - result - } - - fn fstat(&self, file: usize, stat: &mut Stat) -> Result { - let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - let address = inner.capture_mut(stat)?; - let result = inner.call(SYS_FSTAT, file, address, mem::size_of::()); - let _ = inner.release(address); - result - } - - fn fstatvfs(&self, file: usize, stat: &mut StatVfs) -> Result { - let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - let address = inner.capture_mut(stat)?; - let result = inner.call(SYS_FSTATVFS, file, address, mem::size_of::()); - let _ = inner.release(address); - result - } - - fn fsync(&self, file: usize) -> Result { - let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - inner.call(SYS_FSYNC, file, 0, 0) - } - - fn ftruncate(&self, file: usize, len: usize) -> Result { - let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - inner.call(SYS_FTRUNCATE, file, len, 0) - } - - fn close(&self, file: usize) -> Result { - let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; - inner.call(SYS_CLOSE, file, 0, 0) - } -} diff --git a/kernel/src/scheme/zero.rs b/kernel/src/scheme/zero.rs deleted file mode 100644 index 90175cb..0000000 --- a/kernel/src/scheme/zero.rs +++ /dev/null @@ -1,42 +0,0 @@ -use syscall::error::*; -use syscall::scheme::Scheme; - -pub struct ZeroScheme; - -impl Scheme for ZeroScheme { - fn open(&self, _path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result { - Ok(0) - } - - fn dup(&self, _file: usize, _buf: &[u8]) -> Result { - Ok(0) - } - - /// Read the file `number` into the `buffer` - /// - /// Returns the number of bytes read - fn read(&self, _file: usize, buf: &mut [u8]) -> Result { - let mut i = 0; - while i < buf.len() { - buf[i] = 0; - i += 1; - } - Ok(i) - } - - /// Write the `buffer` to the `file` - /// - /// Returns the number of bytes written - fn write(&self, _file: usize, buffer: &[u8]) -> Result { - Ok(buffer.len()) - } - - fn fsync(&self, _file: usize) -> Result { - Ok(0) - } - - /// Close the file `number` - fn close(&self, _file: usize) -> Result { - Ok(0) - } -} diff --git a/kernel/src/sync/mod.rs b/kernel/src/sync/mod.rs deleted file mode 100644 index 833925b..0000000 --- a/kernel/src/sync/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub use self::wait_condition::WaitCondition; -pub use self::wait_queue::WaitQueue; -pub use self::wait_map::WaitMap; - -pub mod wait_condition; -pub mod wait_queue; -pub mod wait_map; diff --git a/kernel/src/sync/wait_condition.rs b/kernel/src/sync/wait_condition.rs deleted file mode 100644 index cb17026..0000000 --- a/kernel/src/sync/wait_condition.rs +++ /dev/null @@ -1,48 +0,0 @@ -use alloc::arc::Arc; -use collections::Vec; -use spin::{Mutex, RwLock}; - -use context::{self, Context}; - -#[derive(Debug)] -pub struct WaitCondition { - contexts: Mutex>>> -} - -impl WaitCondition { - pub fn new() -> WaitCondition { - WaitCondition { - contexts: Mutex::new(Vec::with_capacity(16)) - } - } - - pub fn notify(&self) -> usize { - let mut contexts = self.contexts.lock(); - let len = contexts.len(); - while let Some(context_lock) = contexts.pop() { - context_lock.write().unblock(); - } - len - } - - pub fn wait(&self) { - { - let context_lock = { - let contexts = context::contexts(); - let context_lock = contexts.current().expect("WaitCondition::wait: no context"); - context_lock.clone() - }; - - context_lock.write().block(); - - self.contexts.lock().push(context_lock); - } - unsafe { context::switch(); } - } -} - -impl Drop for WaitCondition { - fn drop(&mut self){ - self.notify(); - } -} diff --git a/kernel/src/sync/wait_map.rs b/kernel/src/sync/wait_map.rs deleted file mode 100644 index c0198a1..0000000 --- a/kernel/src/sync/wait_map.rs +++ /dev/null @@ -1,62 +0,0 @@ -use collections::BTreeMap; -use core::mem; -use spin::Mutex; - -use sync::WaitCondition; - -#[derive(Debug)] -pub struct WaitMap { - inner: Mutex>, - condition: WaitCondition -} - -impl WaitMap where K: Clone + Ord { - pub fn new() -> WaitMap { - WaitMap { - inner: Mutex::new(BTreeMap::new()), - condition: WaitCondition::new() - } - } - - pub fn receive_nonblock(&self, key: &K) -> Option { - self.inner.lock().remove(key) - } - - pub fn receive(&self, key: &K) -> V { - loop { - if let Some(value) = self.receive_nonblock(key) { - return value; - } - self.condition.wait(); - } - } - - pub fn receive_any_nonblock(&self) -> Option<(K, V)> { - let mut inner = self.inner.lock(); - if let Some(key) = inner.keys().next().map(|key| key.clone()) { - inner.remove(&key).map(|value| (key, value)) - } else { - None - } - } - - pub fn receive_any(&self) -> (K, V) { - loop { - if let Some(entry) = self.receive_any_nonblock() { - return entry; - } - self.condition.wait(); - } - } - - pub fn receive_all(&self) -> BTreeMap { - let mut ret = BTreeMap::new(); - mem::swap(&mut ret, &mut *self.inner.lock()); - ret - } - - pub fn send(&self, key: K, value: V) { - self.inner.lock().insert(key, value); - self.condition.notify(); - } -} diff --git a/kernel/src/sync/wait_queue.rs b/kernel/src/sync/wait_queue.rs deleted file mode 100644 index fdf81b5..0000000 --- a/kernel/src/sync/wait_queue.rs +++ /dev/null @@ -1,82 +0,0 @@ -use collections::vec_deque::VecDeque; -use spin::Mutex; - -use sync::WaitCondition; - -#[derive(Debug)] -pub struct WaitQueue { - pub inner: Mutex>, - pub condition: WaitCondition, -} - -impl WaitQueue { - pub fn new() -> WaitQueue { - WaitQueue { - inner: Mutex::new(VecDeque::new()), - condition: WaitCondition::new() - } - } - - pub fn clone(&self) -> WaitQueue where T: Clone { - WaitQueue { - inner: Mutex::new(self.inner.lock().clone()), - condition: WaitCondition::new() - } - } - - pub fn is_empty(&self) -> bool { - self.inner.lock().is_empty() - } - - pub fn receive(&self) -> T { - loop { - if let Some(value) = self.inner.lock().pop_front() { - return value; - } - self.condition.wait(); - } - } - - pub fn receive_into(&self, buf: &mut [T], block: bool) -> usize { - let mut i = 0; - - if i < buf.len() && block { - buf[i] = self.receive(); - i += 1; - } - - { - let mut inner = self.inner.lock(); - while i < buf.len() { - if let Some(value) = inner.pop_front() { - buf[i] = value; - i += 1; - } else { - break; - } - } - } - - i - } - - pub fn send(&self, value: T) -> usize { - let len = { - let mut inner = self.inner.lock(); - inner.push_back(value); - inner.len() - }; - self.condition.notify(); - len - } - - pub fn send_from(&self, buf: &[T]) -> usize where T: Copy { - let len = { - let mut inner = self.inner.lock(); - inner.extend(buf.iter()); - inner.len() - }; - self.condition.notify(); - len - } -} diff --git a/kernel/src/syscall/driver.rs b/kernel/src/syscall/driver.rs deleted file mode 100644 index 9c3f3cd..0000000 --- a/kernel/src/syscall/driver.rs +++ /dev/null @@ -1,130 +0,0 @@ -use arch; -use arch::memory::{allocate_frames, deallocate_frames, Frame}; -use arch::paging::{entry, ActivePageTable, PhysicalAddress, VirtualAddress}; -use context; -use context::memory::Grant; -use syscall::error::{Error, EFAULT, ENOMEM, EPERM, ESRCH, Result}; -use syscall::flag::{MAP_WRITE, MAP_WRITE_COMBINE}; - -fn enforce_root() -> Result<()> { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - if context.euid == 0 { - Ok(()) - } else { - Err(Error::new(EPERM)) - } -} - -pub fn iopl(_level: usize, _stack_base: usize) -> Result { - enforce_root()?; - - //TODO - Ok(0) -} - -pub fn physalloc(size: usize) -> Result { - enforce_root()?; - - allocate_frames((size + 4095)/4096).ok_or(Error::new(ENOMEM)).map(|frame| frame.start_address().get()) -} - -pub fn physfree(physical_address: usize, size: usize) -> Result { - enforce_root()?; - - deallocate_frames(Frame::containing_address(PhysicalAddress::new(physical_address)), (size + 4095)/4096); - //TODO: Check that no double free occured - Ok(0) -} - -//TODO: verify exlusive access to physical memory -pub fn physmap(physical_address: usize, size: usize, flags: usize) -> Result { - enforce_root()?; - - if size == 0 { - Ok(0) - } else { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - - let mut grants = context.grants.lock(); - - let from_address = (physical_address/4096) * 4096; - let offset = physical_address - from_address; - let full_size = ((offset + size + 4095)/4096) * 4096; - let mut to_address = arch::USER_GRANT_OFFSET; - - let mut entry_flags = entry::PRESENT | entry::NO_EXECUTE | entry::USER_ACCESSIBLE; - if flags & MAP_WRITE == MAP_WRITE { - entry_flags |= entry::WRITABLE; - } - if flags & MAP_WRITE_COMBINE == MAP_WRITE_COMBINE { - entry_flags |= entry::HUGE_PAGE; - } - - for i in 0 .. grants.len() { - let start = grants[i].start_address().get(); - if to_address + full_size < start { - grants.insert(i, Grant::physmap( - PhysicalAddress::new(from_address), - VirtualAddress::new(to_address), - full_size, - entry_flags - )); - - return Ok(to_address + offset); - } else { - let pages = (grants[i].size() + 4095) / 4096; - let end = start + pages * 4096; - to_address = end; - } - } - - grants.push(Grant::physmap( - PhysicalAddress::new(from_address), - VirtualAddress::new(to_address), - full_size, - entry_flags - )); - - Ok(to_address + offset) - } -} - -pub fn physunmap(virtual_address: usize) -> Result { - enforce_root()?; - - if virtual_address == 0 { - Ok(0) - } else { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - - let mut grants = context.grants.lock(); - - for i in 0 .. grants.len() { - let start = grants[i].start_address().get(); - let end = start + grants[i].size(); - if virtual_address >= start && virtual_address < end { - grants.remove(i).unmap(); - - return Ok(0); - } - } - - Err(Error::new(EFAULT)) - } -} - -pub fn virttophys(virtual_address: usize) -> Result { - enforce_root()?; - - let active_table = unsafe { ActivePageTable::new() }; - match active_table.translate(VirtualAddress::new(virtual_address)) { - Some(physical_address) => Ok(physical_address.get()), - None => Err(Error::new(EFAULT)) - } -} diff --git a/kernel/src/syscall/fs.rs b/kernel/src/syscall/fs.rs deleted file mode 100644 index bd02c52..0000000 --- a/kernel/src/syscall/fs.rs +++ /dev/null @@ -1,356 +0,0 @@ -//! Filesystem syscalls -use core::sync::atomic::Ordering; - -use context; -use scheme::{self, FileHandle}; -use syscall; -use syscall::data::{Packet, Stat}; -use syscall::error::*; -use syscall::flag::{MODE_DIR, MODE_FILE}; - -pub fn file_op(a: usize, fd: FileHandle, c: usize, d: usize) -> Result { - let (file, pid, uid, gid) = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - let file = context.get_file(fd).ok_or(Error::new(EBADF))?; - (file, context.id, context.euid, context.egid) - }; - - let scheme = { - let schemes = scheme::schemes(); - let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?; - scheme.clone() - }; - - let mut packet = Packet { - id: 0, - pid: pid.into(), - uid: uid, - gid: gid, - a: a, - b: file.number, - c: c, - d: d - }; - - scheme.handle(&mut packet); - - Error::demux(packet.a) -} - -pub fn file_op_slice(a: usize, fd: FileHandle, slice: &[u8]) -> Result { - file_op(a, fd, slice.as_ptr() as usize, slice.len()) -} - -pub fn file_op_mut_slice(a: usize, fd: FileHandle, slice: &mut [u8]) -> Result { - file_op(a, fd, slice.as_mut_ptr() as usize, slice.len()) -} - -/// Change the current working directory -pub fn chdir(path: &[u8]) -> Result { - let fd = open(path, syscall::flag::O_RDONLY | syscall::flag::O_DIRECTORY)?; - let mut stat = Stat::default(); - let stat_res = file_op_mut_slice(syscall::number::SYS_FSTAT, fd, &mut stat); - let _ = close(fd); - stat_res?; - if stat.st_mode & (MODE_FILE | MODE_DIR) == MODE_DIR { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - let canonical = context.canonicalize(path); - *context.cwd.lock() = canonical; - Ok(0) - } else { - Err(Error::new(ENOTDIR)) - } -} - -/// Get the current working directory -pub fn getcwd(buf: &mut [u8]) -> Result { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - let cwd = context.cwd.lock(); - let mut i = 0; - while i < buf.len() && i < cwd.len() { - buf[i] = cwd[i]; - i += 1; - } - Ok(i) -} - -/// Open syscall -pub fn open(path: &[u8], flags: usize) -> Result { - let (path_canon, uid, gid, scheme_ns) = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - (context.canonicalize(path), context.euid, context.egid, context.ens) - }; - - //println!("open {}", unsafe { ::core::str::from_utf8_unchecked(&path_canon) }); - - let mut parts = path_canon.splitn(2, |&b| b == b':'); - let scheme_name_opt = parts.next(); - let reference_opt = parts.next(); - - let (scheme_id, file_id) = { - let scheme_name = scheme_name_opt.ok_or(Error::new(ENODEV))?; - let (scheme_id, scheme) = { - let schemes = scheme::schemes(); - let (scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?; - (scheme_id, scheme.clone()) - }; - let file_id = scheme.open(reference_opt.unwrap_or(b""), flags, uid, gid)?; - (scheme_id, file_id) - }; - - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - context.add_file(::context::file::File { - scheme: scheme_id, - number: file_id, - event: None, - }).ok_or(Error::new(EMFILE)) -} - -pub fn pipe2(fds: &mut [usize], flags: usize) -> Result { - if fds.len() >= 2 { - let scheme_id = ::scheme::pipe::PIPE_SCHEME_ID.load(Ordering::SeqCst); - let (read_id, write_id) = ::scheme::pipe::pipe(flags); - - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - - let read_fd = context.add_file(::context::file::File { - scheme: scheme_id, - number: read_id, - event: None, - }).ok_or(Error::new(EMFILE))?; - - let write_fd = context.add_file(::context::file::File { - scheme: scheme_id, - number: write_id, - event: None, - }).ok_or(Error::new(EMFILE))?; - - fds[0] = read_fd.into(); - fds[1] = write_fd.into(); - - Ok(0) - } else { - Err(Error::new(EFAULT)) - } -} - -/// chmod syscall -pub fn chmod(path: &[u8], mode: u16) -> Result { - let (path_canon, uid, gid, scheme_ns) = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - (context.canonicalize(path), context.euid, context.egid, context.ens) - }; - - let mut parts = path_canon.splitn(2, |&b| b == b':'); - let scheme_name_opt = parts.next(); - let reference_opt = parts.next(); - - let scheme_name = scheme_name_opt.ok_or(Error::new(ENODEV))?; - let scheme = { - let schemes = scheme::schemes(); - let (_scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?; - scheme.clone() - }; - scheme.chmod(reference_opt.unwrap_or(b""), mode, uid, gid) -} - -/// rmdir syscall -pub fn rmdir(path: &[u8]) -> Result { - let (path_canon, uid, gid, scheme_ns) = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - (context.canonicalize(path), context.euid, context.egid, context.ens) - }; - - let mut parts = path_canon.splitn(2, |&b| b == b':'); - let scheme_name_opt = parts.next(); - let reference_opt = parts.next(); - - let scheme_name = scheme_name_opt.ok_or(Error::new(ENODEV))?; - let scheme = { - let schemes = scheme::schemes(); - let (_scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?; - scheme.clone() - }; - scheme.rmdir(reference_opt.unwrap_or(b""), uid, gid) -} - -/// Unlink syscall -pub fn unlink(path: &[u8]) -> Result { - let (path_canon, uid, gid, scheme_ns) = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - (context.canonicalize(path), context.euid, context.egid, context.ens) - }; - - let mut parts = path_canon.splitn(2, |&b| b == b':'); - let scheme_name_opt = parts.next(); - let reference_opt = parts.next(); - - let scheme_name = scheme_name_opt.ok_or(Error::new(ENODEV))?; - let scheme = { - let schemes = scheme::schemes(); - let (_scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?; - scheme.clone() - }; - scheme.unlink(reference_opt.unwrap_or(b""), uid, gid) -} - -/// Close syscall -pub fn close(fd: FileHandle) -> Result { - let file = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - let file = context.remove_file(fd).ok_or(Error::new(EBADF))?; - file - }; - - if let Some(event_id) = file.event { - context::event::unregister(fd, file.scheme, event_id); - } - - let scheme = { - let schemes = scheme::schemes(); - let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?; - scheme.clone() - }; - scheme.close(file.number) -} - -/// Duplicate file descriptor -pub fn dup(fd: FileHandle, buf: &[u8]) -> Result { - let file = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - let file = context.get_file(fd).ok_or(Error::new(EBADF))?; - file - }; - - let new_id = { - let scheme = { - let schemes = scheme::schemes(); - let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?; - scheme.clone() - }; - scheme.dup(file.number, buf)? - }; - - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - context.add_file(::context::file::File { - scheme: file.scheme, - number: new_id, - event: None, - }).ok_or(Error::new(EMFILE)) -} - -/// Duplicate file descriptor, replacing another -pub fn dup2(fd: FileHandle, new_fd: FileHandle, buf: &[u8]) -> Result { - if fd == new_fd { - Ok(new_fd) - } else { - let _ = close(new_fd)?; - - let file = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - let file = context.get_file(fd).ok_or(Error::new(EBADF))?; - file - }; - - let new_id = { - let scheme = { - let schemes = scheme::schemes(); - let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?; - scheme.clone() - }; - scheme.dup(file.number, buf)? - }; - - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - context.insert_file(new_fd, ::context::file::File { - scheme: file.scheme, - number: new_id, - event: None, - }).ok_or(Error::new(EBADF)) - } -} - -/// Register events for file -pub fn fevent(fd: FileHandle, flags: usize) -> Result { - let file = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - let mut files = context.files.lock(); - let mut file = files.get_mut(fd.into()).ok_or(Error::new(EBADF))?.ok_or(Error::new(EBADF))?; - if let Some(event_id) = file.event.take() { - println!("{:?}: {:?}:{}: events already registered: {}", fd, file.scheme, file.number, event_id); - context::event::unregister(fd, file.scheme, event_id); - } - file.clone() - }; - - let scheme = { - let schemes = scheme::schemes(); - let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?; - scheme.clone() - }; - let event_id = scheme.fevent(file.number, flags)?; - { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - let mut files = context.files.lock(); - let mut file = files.get_mut(fd.into()).ok_or(Error::new(EBADF))?.ok_or(Error::new(EBADF))?; - file.event = Some(event_id); - } - context::event::register(fd, file.scheme, event_id); - Ok(0) -} - -pub fn funmap(virtual_address: usize) -> Result { - if virtual_address == 0 { - Ok(0) - } else { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - - let mut grants = context.grants.lock(); - - for i in 0 .. grants.len() { - let start = grants[i].start_address().get(); - let end = start + grants[i].size(); - if virtual_address >= start && virtual_address < end { - grants.remove(i).unmap(); - - return Ok(0); - } - } - - Err(Error::new(EFAULT)) - } -} diff --git a/kernel/src/syscall/futex.rs b/kernel/src/syscall/futex.rs deleted file mode 100644 index 4b9c30c..0000000 --- a/kernel/src/syscall/futex.rs +++ /dev/null @@ -1,110 +0,0 @@ -use alloc::arc::Arc; -use collections::VecDeque; -use core::intrinsics; -use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard}; - -use context::{self, Context}; -use syscall::error::{Error, Result, ESRCH, EAGAIN, EINVAL}; -use syscall::flag::{FUTEX_WAIT, FUTEX_WAKE, FUTEX_REQUEUE}; -use syscall::validate::validate_slice_mut; - -type FutexList = VecDeque<(usize, Arc>)>; - -/// Fast userspace mutex list -static FUTEXES: Once> = Once::new(); - -/// Initialize futexes, called if needed -fn init_futexes() -> RwLock { - RwLock::new(VecDeque::new()) -} - -/// Get the global futexes list, const -pub fn futexes() -> RwLockReadGuard<'static, FutexList> { - FUTEXES.call_once(init_futexes).read() -} - -/// Get the global futexes list, mutable -pub fn futexes_mut() -> RwLockWriteGuard<'static, FutexList> { - FUTEXES.call_once(init_futexes).write() -} - -pub fn futex(addr: &mut i32, op: usize, val: i32, val2: usize, addr2: *mut i32) -> Result { - match op { - FUTEX_WAIT => { - { - let mut futexes = futexes_mut(); - - let context_lock = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - context_lock.clone() - }; - - if unsafe { intrinsics::atomic_load(addr) != val } { - return Err(Error::new(EAGAIN)); - } - - context_lock.write().block(); - - futexes.push_back((addr as *mut i32 as usize, context_lock)); - } - - unsafe { context::switch(); } - - Ok(0) - }, - FUTEX_WAKE => { - let mut woken = 0; - - { - let mut futexes = futexes_mut(); - - let mut i = 0; - while i < futexes.len() && (woken as i32) < val { - if futexes[i].0 == addr as *mut i32 as usize { - if let Some(futex) = futexes.swap_remove_back(i) { - futex.1.write().unblock(); - woken += 1; - } - } else { - i += 1; - } - } - } - - Ok(woken) - }, - FUTEX_REQUEUE => { - let addr2_safe = validate_slice_mut(addr2, 1).map(|addr2_safe| &mut addr2_safe[0])?; - - let mut woken = 0; - let mut requeued = 0; - - { - let mut futexes = futexes_mut(); - - let mut i = 0; - while i < futexes.len() && (woken as i32) < val { - if futexes[i].0 == addr as *mut i32 as usize { - if let Some(futex) = futexes.swap_remove_back(i) { - futex.1.write().unblock(); - woken += 1; - } - } else { - i += 1; - } - } - while i < futexes.len() && requeued < val2 { - if futexes[i].0 == addr as *mut i32 as usize { - futexes[i].0 = addr2_safe as *mut i32 as usize; - requeued += 1; - } - i += 1; - } - } - - Ok(woken) - }, - _ => Err(Error::new(EINVAL)) - } -} diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs deleted file mode 100644 index d303007..0000000 --- a/kernel/src/syscall/mod.rs +++ /dev/null @@ -1,121 +0,0 @@ -///! Syscall handlers - -extern crate syscall; - -pub use self::syscall::{data, error, flag, number, scheme}; - -pub use self::driver::*; -pub use self::fs::*; -pub use self::futex::futex; -pub use self::privilege::*; -pub use self::process::*; -pub use self::time::*; -pub use self::validate::*; - -use self::data::TimeSpec; -use self::error::{Error, Result, ENOSYS}; -use self::number::*; - -use context::ContextId; -use scheme::{FileHandle, SchemeNamespace}; - -/// Driver syscalls -pub mod driver; - -/// Filesystem syscalls -pub mod fs; - -/// Fast userspace mutex -pub mod futex; - -/// Privilege syscalls -pub mod privilege; - -/// Process syscalls -pub mod process; - -/// Time syscalls -pub mod time; - -/// Validate input -pub mod validate; - -#[no_mangle] -pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, stack: usize) -> usize { - #[inline(always)] - fn inner(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, stack: usize) -> Result { - match a & SYS_CLASS { - SYS_CLASS_FILE => { - let fd = FileHandle::from(b); - match a & SYS_ARG { - SYS_ARG_SLICE => file_op_slice(a, fd, validate_slice(c as *const u8, d)?), - SYS_ARG_MSLICE => file_op_mut_slice(a, fd, validate_slice_mut(c as *mut u8, d)?), - _ => match a { - SYS_CLOSE => close(fd), - SYS_DUP => dup(fd, validate_slice(c as *const u8, d)?).map(FileHandle::into), - SYS_DUP2 => dup2(fd, FileHandle::from(c), validate_slice(d as *const u8, e)?).map(FileHandle::into), - SYS_FEVENT => fevent(fd, c), - SYS_FUNMAP => funmap(b), - _ => file_op(a, fd, c, d) - } - } - }, - SYS_CLASS_PATH => match a { - SYS_OPEN => open(validate_slice(b as *const u8, c)?, d).map(FileHandle::into), - SYS_CHMOD => chmod(validate_slice(b as *const u8, c)?, d as u16), - SYS_RMDIR => rmdir(validate_slice(b as *const u8, c)?), - SYS_UNLINK => unlink(validate_slice(b as *const u8, c)?), - _ => unreachable!() - }, - _ => match a { - SYS_YIELD => sched_yield(), - SYS_NANOSLEEP => nanosleep(validate_slice(b as *const TimeSpec, 1).map(|req| &req[0])?, validate_slice_mut(c as *mut TimeSpec, 1).ok().map(|rem| &mut rem[0])), - SYS_CLOCK_GETTIME => clock_gettime(b, validate_slice_mut(c as *mut TimeSpec, 1).map(|time| &mut time[0])?), - SYS_FUTEX => futex(validate_slice_mut(b as *mut i32, 1).map(|uaddr| &mut uaddr[0])?, c, d as i32, e, f as *mut i32), - SYS_BRK => brk(b), - SYS_GETPID => getpid().map(ContextId::into), - SYS_CLONE => clone(b, stack).map(ContextId::into), - SYS_EXIT => exit((b & 0xFF) << 8), - SYS_KILL => kill(ContextId::from(b), c), - SYS_WAITPID => waitpid(ContextId::from(b), c, d).map(ContextId::into), - SYS_CHDIR => chdir(validate_slice(b as *const u8, c)?), - SYS_EXECVE => exec(validate_slice(b as *const u8, c)?, validate_slice(d as *const [usize; 2], e)?), - SYS_IOPL => iopl(b, stack), - SYS_GETCWD => getcwd(validate_slice_mut(b as *mut u8, c)?), - SYS_GETEGID => getegid(), - SYS_GETENS => getens(), - SYS_GETEUID => geteuid(), - SYS_GETGID => getgid(), - SYS_GETNS => getns(), - SYS_GETUID => getuid(), - SYS_MKNS => mkns(validate_slice(b as *const [usize; 2], c)?), - SYS_SETREUID => setreuid(b as u32, c as u32), - SYS_SETRENS => setrens(SchemeNamespace::from(b), SchemeNamespace::from(c)), - SYS_SETREGID => setregid(b as u32, c as u32), - SYS_PIPE2 => pipe2(validate_slice_mut(b as *mut usize, 2)?, c), - SYS_PHYSALLOC => physalloc(b), - SYS_PHYSFREE => physfree(b, c), - SYS_PHYSMAP => physmap(b, c, d), - SYS_PHYSUNMAP => physunmap(b), - SYS_VIRTTOPHYS => virttophys(b), - _ => Err(Error::new(ENOSYS)) - } - } - } - - let result = inner(a, b, c, d, e, f, stack); - - /* - if let Err(ref err) = result { - let contexts = ::context::contexts(); - if let Some(context_lock) = contexts.current() { - let context = context_lock.read(); - print!("{}: {}: ", unsafe { ::core::str::from_utf8_unchecked(&context.name.lock()) }, context.id.into()); - } - - println!("{:X}, {:X}, {:X}, {:X}: {}", a, b, c, d, err); - } - */ - - Error::mux(result) -} diff --git a/kernel/src/syscall/privilege.rs b/kernel/src/syscall/privilege.rs deleted file mode 100644 index e718196..0000000 --- a/kernel/src/syscall/privilege.rs +++ /dev/null @@ -1,147 +0,0 @@ -use collections::Vec; - -use context; -use scheme::{self, SchemeNamespace}; -use syscall::error::*; -use syscall::validate::validate_slice; - -pub fn getegid() -> Result { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - Ok(context.egid as usize) -} - -pub fn getens() -> Result { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - Ok(context.ens.into()) -} - -pub fn geteuid() -> Result { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - Ok(context.euid as usize) -} - -pub fn getgid() -> Result { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - Ok(context.rgid as usize) -} - -pub fn getns() -> Result { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - Ok(context.rns.into()) -} - -pub fn getuid() -> Result { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - Ok(context.ruid as usize) -} - -pub fn mkns(name_ptrs: &[[usize; 2]]) -> Result { - let mut names = Vec::new(); - for name_ptr in name_ptrs { - names.push(validate_slice(name_ptr[0] as *const u8, name_ptr[1])?); - } - - let (uid, from) = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - (context.euid, context.ens) - }; - - if uid == 0 { - let to = scheme::schemes_mut().make_ns(from, &names)?; - Ok(to.into()) - } else { - Err(Error::new(EACCES)) - } -} - -pub fn setregid(rgid: u32, egid: u32) -> Result { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let mut context = context_lock.write(); - - if (context.euid == 0 - || rgid as i32 == -1 - || rgid == context.egid - || rgid == context.rgid) - && (context.euid == 0 - || egid as i32 == -1 - || egid == context.egid - || egid == context.rgid) - { - if rgid as i32 != -1 { - context.rgid = rgid; - } - if egid as i32 != -1 { - context.egid = egid; - } - Ok(0) - } else { - Err(Error::new(EPERM)) - } -} - -pub fn setrens(rns: SchemeNamespace, ens: SchemeNamespace) -> Result { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let mut context = context_lock.write(); - - if (context.euid == 0 - || rns.into() as isize == -1 - || rns == context.ens - || rns == context.rns) - && (context.euid == 0 - || ens.into() as isize == -1 - || ens == context.ens - || ens == context.rns) - { - if rns.into() as isize != -1 { - context.rns = rns; - } - if ens.into() as isize != -1 { - context.ens = ens; - } - Ok(0) - } else { - Err(Error::new(EPERM)) - } -} - -pub fn setreuid(ruid: u32, euid: u32) -> Result { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let mut context = context_lock.write(); - - if (context.euid == 0 - || ruid as i32 == -1 - || ruid == context.euid - || ruid == context.ruid) - && (context.euid == 0 - || euid as i32 == -1 - || euid == context.euid - || euid == context.ruid) - { - if ruid as i32 != -1 { - context.ruid = ruid; - } - if euid as i32 != -1 { - context.euid = euid; - } - Ok(0) - } else { - Err(Error::new(EPERM)) - } -} diff --git a/kernel/src/syscall/process.rs b/kernel/src/syscall/process.rs deleted file mode 100644 index f8bc6c3..0000000 --- a/kernel/src/syscall/process.rs +++ /dev/null @@ -1,965 +0,0 @@ -///! Process syscalls -use alloc::arc::Arc; -use alloc::boxed::Box; -use collections::{BTreeMap, Vec}; -use core::{intrinsics, mem, str}; -use core::ops::DerefMut; -use spin::Mutex; - -use arch; -use arch::memory::allocate_frame; -use arch::paging::{ActivePageTable, InactivePageTable, Page, VirtualAddress, entry}; -use arch::paging::temporary_page::TemporaryPage; -use arch::start::usermode; -use context; -use context::ContextId; -use elf::{self, program_header}; -use scheme::{self, FileHandle}; -use syscall; -use syscall::data::Stat; -use syscall::error::*; -use syscall::flag::{CLONE_VFORK, CLONE_VM, CLONE_FS, CLONE_FILES, WNOHANG}; -use syscall::validate::{validate_slice, validate_slice_mut}; - -pub fn brk(address: usize) -> Result { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - - //println!("{}: {}: BRK {:X}", unsafe { ::core::str::from_utf8_unchecked(&context.name.lock()) }, - // context.id.into(), address); - - let current = if let Some(ref heap_shared) = context.heap { - heap_shared.with(|heap| { - heap.start_address().get() + heap.size() - }) - } else { - panic!("user heap not initialized"); - }; - - if address == 0 { - //println!("Brk query {:X}", current); - Ok(current) - } else if address >= arch::USER_HEAP_OFFSET { - //TODO: out of memory errors - if let Some(ref heap_shared) = context.heap { - heap_shared.with(|heap| { - heap.resize(address - arch::USER_HEAP_OFFSET, true); - }); - } else { - panic!("user heap not initialized"); - } - - //println!("Brk resize {:X}", address); - Ok(address) - } else { - //println!("Brk no mem"); - Err(Error::new(ENOMEM)) - } -} - -pub fn clone(flags: usize, stack_base: usize) -> Result { - let ppid; - let pid; - { - let ruid; - let rgid; - let rns; - let euid; - let egid; - let ens; - let mut cpu_id = None; - let arch; - let vfork; - let mut kfx_option = None; - let mut kstack_option = None; - let mut offset = 0; - let mut image = vec![]; - let mut heap_option = None; - let mut stack_option = None; - let mut tls_option = None; - let grants; - let name; - let cwd; - let env; - let files; - - // Copy from old process - { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - - ppid = context.id; - ruid = context.ruid; - rgid = context.rgid; - rns = context.rns; - euid = context.euid; - egid = context.egid; - ens = context.ens; - - if flags & CLONE_VM == CLONE_VM { - cpu_id = context.cpu_id; - } - - arch = context.arch.clone(); - - if let Some(ref fx) = context.kfx { - let mut new_fx = unsafe { Box::from_raw(::alloc::heap::allocate(512, 16) as *mut [u8; 512]) }; - for (new_b, b) in new_fx.iter_mut().zip(fx.iter()) { - *new_b = *b; - } - kfx_option = Some(new_fx); - } - - if let Some(ref stack) = context.kstack { - offset = stack_base - stack.as_ptr() as usize - mem::size_of::(); // Add clone ret - let mut new_stack = stack.clone(); - - unsafe { - let func_ptr = new_stack.as_mut_ptr().offset(offset as isize); - *(func_ptr as *mut usize) = arch::interrupt::syscall::clone_ret as usize; - } - - kstack_option = Some(new_stack); - } - - if flags & CLONE_VM == CLONE_VM { - for memory_shared in context.image.iter() { - image.push(memory_shared.clone()); - } - - if let Some(ref heap_shared) = context.heap { - heap_option = Some(heap_shared.clone()); - } - } else { - for memory_shared in context.image.iter() { - memory_shared.with(|memory| { - let mut new_memory = context::memory::Memory::new( - VirtualAddress::new(memory.start_address().get() + arch::USER_TMP_OFFSET), - memory.size(), - entry::PRESENT | entry::NO_EXECUTE | entry::WRITABLE, - false - ); - - unsafe { - intrinsics::copy(memory.start_address().get() as *const u8, - new_memory.start_address().get() as *mut u8, - memory.size()); - } - - new_memory.remap(memory.flags()); - image.push(new_memory.to_shared()); - }); - } - - if let Some(ref heap_shared) = context.heap { - heap_shared.with(|heap| { - let mut new_heap = context::memory::Memory::new( - VirtualAddress::new(arch::USER_TMP_HEAP_OFFSET), - heap.size(), - entry::PRESENT | entry::NO_EXECUTE | entry::WRITABLE, - false - ); - - unsafe { - intrinsics::copy(heap.start_address().get() as *const u8, - new_heap.start_address().get() as *mut u8, - heap.size()); - } - - new_heap.remap(heap.flags()); - heap_option = Some(new_heap.to_shared()); - }); - } - } - - if let Some(ref stack) = context.stack { - let mut new_stack = context::memory::Memory::new( - VirtualAddress::new(arch::USER_TMP_STACK_OFFSET), - stack.size(), - entry::PRESENT | entry::NO_EXECUTE | entry::WRITABLE, - false - ); - - unsafe { - intrinsics::copy(stack.start_address().get() as *const u8, - new_stack.start_address().get() as *mut u8, - stack.size()); - } - - new_stack.remap(stack.flags()); - stack_option = Some(new_stack); - } - - if let Some(ref tls) = context.tls { - let mut new_tls = context::memory::Tls { - master: tls.master, - file_size: tls.file_size, - mem: context::memory::Memory::new( - VirtualAddress::new(arch::USER_TMP_TLS_OFFSET), - tls.mem.size(), - entry::PRESENT | entry::NO_EXECUTE | entry::WRITABLE, - true - ) - }; - - unsafe { - intrinsics::copy(tls.master.get() as *const u8, - new_tls.mem.start_address().get() as *mut u8, - tls.file_size); - } - - new_tls.mem.remap(tls.mem.flags()); - tls_option = Some(new_tls); - } - - if flags & CLONE_VM == CLONE_VM { - grants = context.grants.clone(); - } else { - grants = Arc::new(Mutex::new(Vec::new())); - } - - if flags & CLONE_VM == CLONE_VM { - name = context.name.clone(); - } else { - name = Arc::new(Mutex::new(context.name.lock().clone())); - } - - if flags & CLONE_FS == CLONE_FS { - cwd = context.cwd.clone(); - } else { - cwd = Arc::new(Mutex::new(context.cwd.lock().clone())); - } - - if flags & CLONE_VM == CLONE_VM { - env = context.env.clone(); - } else { - let mut new_env = BTreeMap::new(); - for item in context.env.lock().iter() { - new_env.insert(item.0.clone(), Arc::new(Mutex::new(item.1.lock().clone()))); - } - env = Arc::new(Mutex::new(new_env)); - } - - if flags & CLONE_FILES == CLONE_FILES { - files = context.files.clone(); - } else { - files = Arc::new(Mutex::new(context.files.lock().clone())); - } - } - - // If not cloning files, dup to get a new number from scheme - // This has to be done outside the context lock to prevent deadlocks - if flags & CLONE_FILES == 0 { - for (_fd, mut file_option) in files.lock().iter_mut().enumerate() { - let new_file_option = if let Some(file) = *file_option { - let result = { - let scheme = { - let schemes = scheme::schemes(); - let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?; - scheme.clone() - }; - let result = scheme.dup(file.number, b"clone"); - result - }; - match result { - Ok(new_number) => { - Some(context::file::File { - scheme: file.scheme, - number: new_number, - event: None, - }) - }, - Err(_err) => { - None - } - } - } else { - None - }; - - *file_option = new_file_option; - } - } - - // If vfork, block the current process - // This has to be done after the operations that may require context switches - if flags & CLONE_VFORK == CLONE_VFORK { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let mut context = context_lock.write(); - context.block(); - vfork = true; - } else { - vfork = false; - } - - // Set up new process - { - let mut contexts = context::contexts_mut(); - let context_lock = contexts.new_context()?; - let mut context = context_lock.write(); - - pid = context.id; - - context.ppid = ppid; - context.ruid = ruid; - context.rgid = rgid; - context.rns = rns; - context.euid = euid; - context.egid = egid; - context.ens = ens; - - context.cpu_id = cpu_id; - - context.status = context::Status::Runnable; - - context.vfork = vfork; - - context.arch = arch; - - let mut active_table = unsafe { ActivePageTable::new() }; - - let mut temporary_page = TemporaryPage::new(Page::containing_address(VirtualAddress::new(arch::USER_TMP_MISC_OFFSET))); - - let mut new_table = { - let frame = allocate_frame().expect("no more frames in syscall::clone new_table"); - InactivePageTable::new(frame, &mut active_table, &mut temporary_page) - }; - - context.arch.set_page_table(unsafe { new_table.address() }); - - // Copy kernel mapping - { - let frame = active_table.p4()[510].pointed_frame().expect("kernel table not mapped"); - let flags = active_table.p4()[510].flags(); - active_table.with(&mut new_table, &mut temporary_page, |mapper| { - mapper.p4_mut()[510].set(frame, flags); - }); - } - - if let Some(fx) = kfx_option.take() { - context.arch.set_fx(fx.as_ptr() as usize); - context.kfx = Some(fx); - } - - // Set kernel stack - if let Some(stack) = kstack_option.take() { - context.arch.set_stack(stack.as_ptr() as usize + offset); - context.kstack = Some(stack); - } - - // Setup heap - if flags & CLONE_VM == CLONE_VM { - // Copy user image mapping, if found - if ! image.is_empty() { - let frame = active_table.p4()[0].pointed_frame().expect("user image not mapped"); - let flags = active_table.p4()[0].flags(); - active_table.with(&mut new_table, &mut temporary_page, |mapper| { - mapper.p4_mut()[0].set(frame, flags); - }); - } - context.image = image; - - // Copy user heap mapping, if found - if let Some(heap_shared) = heap_option { - let frame = active_table.p4()[1].pointed_frame().expect("user heap not mapped"); - let flags = active_table.p4()[1].flags(); - active_table.with(&mut new_table, &mut temporary_page, |mapper| { - mapper.p4_mut()[1].set(frame, flags); - }); - context.heap = Some(heap_shared); - } - - // Copy grant mapping - if ! grants.lock().is_empty() { - let frame = active_table.p4()[2].pointed_frame().expect("user grants not mapped"); - let flags = active_table.p4()[2].flags(); - active_table.with(&mut new_table, &mut temporary_page, |mapper| { - mapper.p4_mut()[2].set(frame, flags); - }); - } - context.grants = grants; - } else { - // Copy percpu mapping - for cpu_id in 0..::cpu_count() { - extern { - /// The starting byte of the thread data segment - static mut __tdata_start: u8; - /// The ending byte of the thread BSS segment - static mut __tbss_end: u8; - } - - let size = unsafe { & __tbss_end as *const _ as usize - & __tdata_start as *const _ as usize }; - - let start = arch::KERNEL_PERCPU_OFFSET + arch::KERNEL_PERCPU_SIZE * cpu_id; - let end = start + size; - - let start_page = Page::containing_address(VirtualAddress::new(start)); - let end_page = Page::containing_address(VirtualAddress::new(end - 1)); - for page in Page::range_inclusive(start_page, end_page) { - let frame = active_table.translate_page(page).expect("kernel percpu not mapped"); - active_table.with(&mut new_table, &mut temporary_page, |mapper| { - let result = mapper.map_to(page, frame, entry::PRESENT | entry::NO_EXECUTE | entry::WRITABLE); - // Ignore result due to operating on inactive table - unsafe { result.ignore(); } - }); - } - } - - // Move copy of image - for memory_shared in image.iter_mut() { - memory_shared.with(|memory| { - let start = VirtualAddress::new(memory.start_address().get() - arch::USER_TMP_OFFSET + arch::USER_OFFSET); - memory.move_to(start, &mut new_table, &mut temporary_page); - }); - } - context.image = image; - - // Move copy of heap - if let Some(heap_shared) = heap_option { - heap_shared.with(|heap| { - heap.move_to(VirtualAddress::new(arch::USER_HEAP_OFFSET), &mut new_table, &mut temporary_page); - }); - context.heap = Some(heap_shared); - } - } - - // Setup user stack - if let Some(mut stack) = stack_option { - stack.move_to(VirtualAddress::new(arch::USER_STACK_OFFSET), &mut new_table, &mut temporary_page); - context.stack = Some(stack); - } - - // Setup user TLS - if let Some(mut tls) = tls_option { - tls.mem.move_to(VirtualAddress::new(arch::USER_TLS_OFFSET), &mut new_table, &mut temporary_page); - context.tls = Some(tls); - } - - context.name = name; - - context.cwd = cwd; - - context.env = env; - - context.files = files; - } - } - - unsafe { context::switch(); } - - Ok(pid) -} - -fn empty(context: &mut context::Context, reaping: bool) { - if reaping { - // Memory should already be unmapped - assert!(context.image.is_empty()); - assert!(context.heap.is_none()); - assert!(context.stack.is_none()); - assert!(context.tls.is_none()); - } else { - // Unmap previous image, heap, grants, stack, and tls - context.image.clear(); - drop(context.heap.take()); - drop(context.stack.take()); - drop(context.tls.take()); - } - - // FIXME: Looks like a race condition. - // Is it possible for Arc::strong_count to return 1 to two contexts that exit at the - // same time, or return 2 to both, thus either double freeing or leaking the grants? - if Arc::strong_count(&context.grants) == 1 { - let mut grants = context.grants.lock(); - for grant in grants.drain(..) { - if reaping { - println!("{}: {}: Grant should not exist: {:?}", context.id.into(), unsafe { ::core::str::from_utf8_unchecked(&context.name.lock()) }, grant); - - let mut new_table = unsafe { InactivePageTable::from_address(context.arch.get_page_table()) }; - let mut temporary_page = TemporaryPage::new(Page::containing_address(VirtualAddress::new(arch::USER_TMP_GRANT_OFFSET))); - - grant.unmap_inactive(&mut new_table, &mut temporary_page); - } else { - grant.unmap(); - } - } - } -} - -pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result { - let entry; - let mut sp = arch::USER_STACK_OFFSET + arch::USER_STACK_SIZE - 256; - - { - let mut args = Vec::new(); - for arg_ptr in arg_ptrs { - let arg = validate_slice(arg_ptr[0] as *const u8, arg_ptr[1])?; - args.push(arg.to_vec()); // Must be moved into kernel space before exec unmaps all memory - } - - let (uid, gid, canonical) = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - (context.euid, context.egid, context.canonicalize(path)) - }; - - let file = syscall::open(&canonical, syscall::flag::O_RDONLY)?; - let mut stat = Stat::default(); - syscall::file_op_mut_slice(syscall::number::SYS_FSTAT, file, &mut stat)?; - - let mut perm = stat.st_mode & 0o7; - if stat.st_uid == uid { - perm |= (stat.st_mode >> 6) & 0o7; - } - if stat.st_gid == gid { - perm |= (stat.st_mode >> 3) & 0o7; - } - if uid == 0 { - perm |= 0o7; - } - - if perm & 0o1 != 0o1 { - let _ = syscall::close(file); - return Err(Error::new(EACCES)); - } - - //TODO: Only read elf header, not entire file. Then read required segments - let mut data = vec![0; stat.st_size as usize]; - syscall::file_op_mut_slice(syscall::number::SYS_READ, file, &mut data)?; - let _ = syscall::close(file); - - match elf::Elf::from(&data) { - Ok(elf) => { - entry = elf.entry(); - - drop(path); // Drop so that usage is not allowed after unmapping context - drop(arg_ptrs); // Drop so that usage is not allowed after unmapping context - - let contexts = context::contexts(); - let (vfork, ppid, files) = { - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let mut context = context_lock.write(); - - // Set name - context.name = Arc::new(Mutex::new(canonical)); - - empty(&mut context, false); - - if stat.st_mode & syscall::flag::MODE_SETUID == syscall::flag::MODE_SETUID { - context.euid = stat.st_uid; - } - - if stat.st_mode & syscall::flag::MODE_SETGID == syscall::flag::MODE_SETGID { - context.egid = stat.st_gid; - } - - // Map and copy new segments - let mut tls_option = None; - for segment in elf.segments() { - if segment.p_type == program_header::PT_LOAD { - let mut memory = context::memory::Memory::new( - VirtualAddress::new(segment.p_vaddr as usize), - segment.p_memsz as usize, - entry::NO_EXECUTE | entry::WRITABLE, - true - ); - - unsafe { - // Copy file data - intrinsics::copy((elf.data.as_ptr() as usize + segment.p_offset as usize) as *const u8, - segment.p_vaddr as *mut u8, - segment.p_filesz as usize); - } - - let mut flags = entry::NO_EXECUTE | entry::USER_ACCESSIBLE; - - if segment.p_flags & program_header::PF_R == program_header::PF_R { - flags.insert(entry::PRESENT); - } - - // W ^ X. If it is executable, do not allow it to be writable, even if requested - if segment.p_flags & program_header::PF_X == program_header::PF_X { - flags.remove(entry::NO_EXECUTE); - } else if segment.p_flags & program_header::PF_W == program_header::PF_W { - flags.insert(entry::WRITABLE); - } - - memory.remap(flags); - - context.image.push(memory.to_shared()); - } else if segment.p_type == program_header::PT_TLS { - let memory = context::memory::Memory::new( - VirtualAddress::new(arch::USER_TCB_OFFSET), - 4096, - entry::NO_EXECUTE | entry::WRITABLE | entry::USER_ACCESSIBLE, - true - ); - - unsafe { *(arch::USER_TCB_OFFSET as *mut usize) = arch::USER_TLS_OFFSET + segment.p_memsz as usize; } - - context.image.push(memory.to_shared()); - - tls_option = Some(( - VirtualAddress::new(segment.p_vaddr as usize), - segment.p_filesz as usize, - segment.p_memsz as usize - )); - } - } - - // Map heap - context.heap = Some(context::memory::Memory::new( - VirtualAddress::new(arch::USER_HEAP_OFFSET), - 0, - entry::NO_EXECUTE | entry::WRITABLE | entry::USER_ACCESSIBLE, - true - ).to_shared()); - - // Map stack - context.stack = Some(context::memory::Memory::new( - VirtualAddress::new(arch::USER_STACK_OFFSET), - arch::USER_STACK_SIZE, - entry::NO_EXECUTE | entry::WRITABLE | entry::USER_ACCESSIBLE, - true - )); - - // Map TLS - if let Some((master, file_size, size)) = tls_option { - let tls = context::memory::Tls { - master: master, - file_size: file_size, - mem: context::memory::Memory::new( - VirtualAddress::new(arch::USER_TLS_OFFSET), - size, - entry::NO_EXECUTE | entry::WRITABLE | entry::USER_ACCESSIBLE, - true - ) - }; - - unsafe { - // Copy file data - intrinsics::copy(master.get() as *const u8, - tls.mem.start_address().get() as *mut u8, - file_size); - } - - context.tls = Some(tls); - } - - // Push arguments - let mut arg_size = 0; - for arg in args.iter().rev() { - sp -= mem::size_of::(); - unsafe { *(sp as *mut usize) = arch::USER_ARG_OFFSET + arg_size; } - sp -= mem::size_of::(); - unsafe { *(sp as *mut usize) = arg.len(); } - - arg_size += arg.len(); - } - - sp -= mem::size_of::(); - unsafe { *(sp as *mut usize) = args.len(); } - - if arg_size > 0 { - let mut memory = context::memory::Memory::new( - VirtualAddress::new(arch::USER_ARG_OFFSET), - arg_size, - entry::NO_EXECUTE | entry::WRITABLE, - true - ); - - let mut arg_offset = 0; - for arg in args.iter().rev() { - unsafe { - intrinsics::copy(arg.as_ptr(), - (arch::USER_ARG_OFFSET + arg_offset) as *mut u8, - arg.len()); - } - - arg_offset += arg.len(); - } - - memory.remap(entry::NO_EXECUTE | entry::USER_ACCESSIBLE); - - context.image.push(memory.to_shared()); - } - - let files = Arc::new(Mutex::new(context.files.lock().clone())); - context.files = files.clone(); - - let vfork = context.vfork; - context.vfork = false; - (vfork, context.ppid, files) - }; - - // Duplicate current files using b"exec", close previous - for (fd, mut file_option) in files.lock().iter_mut().enumerate() { - let new_file_option = if let Some(file) = *file_option { - // Duplicate - let result = { - let scheme_option = { - let schemes = scheme::schemes(); - schemes.get(file.scheme).map(|scheme| scheme.clone()) - }; - if let Some(scheme) = scheme_option { - let result = scheme.dup(file.number, b"exec"); - result - } else { - Err(Error::new(EBADF)) - } - }; - - // Close - { - if let Some(event_id) = file.event { - context::event::unregister(FileHandle::from(fd), file.scheme, event_id); - } - - let scheme_option = { - let schemes = scheme::schemes(); - schemes.get(file.scheme).map(|scheme| scheme.clone()) - }; - if let Some(scheme) = scheme_option { - let _ = scheme.close(file.number); - } - } - - // Return new descriptor - match result { - Ok(new_number) => { - Some(context::file::File { - scheme: file.scheme, - number: new_number, - event: None, - }) - }, - Err(_err) => { - None - } - } - } else { - None - }; - - *file_option = new_file_option; - } - - if vfork { - if let Some(context_lock) = contexts.get(ppid) { - let mut context = context_lock.write(); - if ! context.unblock() { - println!("{:?} not blocked for exec vfork unblock", ppid); - } - } else { - println!("{:?} not found for exec vfork unblock", ppid); - } - } - }, - Err(err) => { - println!("failed to execute {}: {}", unsafe { str::from_utf8_unchecked(path) }, err); - return Err(Error::new(ENOEXEC)); - } - } - } - - // Go to usermode - unsafe { usermode(entry, sp); } -} - -pub fn exit(status: usize) -> ! { - { - let context_lock = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH)).expect("exit failed to find context"); - context_lock.clone() - }; - - let mut close_files = Vec::new(); - let (pid, ppid) = { - let mut context = context_lock.write(); - // FIXME: Looks like a race condition. - // Is it possible for Arc::strong_count to return 1 to two contexts that exit at the - // same time, or return 2 to both, thus either double closing or leaking the files? - if Arc::strong_count(&context.files) == 1 { - mem::swap(context.files.lock().deref_mut(), &mut close_files); - } - context.files = Arc::new(Mutex::new(Vec::new())); - (context.id, context.ppid) - }; - - /// Files must be closed while context is valid so that messages can be passed - for (fd, file_option) in close_files.drain(..).enumerate() { - if let Some(file) = file_option { - if let Some(event_id) = file.event { - context::event::unregister(FileHandle::from(fd), file.scheme, event_id); - } - - let scheme_option = { - let schemes = scheme::schemes(); - schemes.get(file.scheme).map(|scheme| scheme.clone()) - }; - if let Some(scheme) = scheme_option { - let _ = scheme.close(file.number); - } - } - } - - /// Transfer child processes to parent - { - let contexts = context::contexts(); - for (_id, context_lock) in contexts.iter() { - let mut context = context_lock.write(); - if context.ppid == pid { - context.ppid = ppid; - context.vfork = false; - } - } - } - - let (vfork, children) = { - let mut context = context_lock.write(); - - empty(&mut context, false); - - let vfork = context.vfork; - context.vfork = false; - - context.status = context::Status::Exited(status); - - let children = context.waitpid.receive_all(); - - (vfork, children) - }; - - { - let contexts = context::contexts(); - if let Some(parent_lock) = contexts.get(ppid) { - let waitpid = { - let mut parent = parent_lock.write(); - if vfork { - if ! parent.unblock() { - println!("{:?} not blocked for exit vfork unblock", ppid); - } - } - parent.waitpid.clone() - }; - - for (c_pid, c_status) in children { - waitpid.send(c_pid, c_status); - } - waitpid.send(pid, status); - } else { - println!("{:?} not found for exit vfork unblock", ppid); - } - } - } - - unsafe { context::switch(); } - - unreachable!(); -} - -pub fn getpid() -> Result { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - Ok(context.id) -} - -pub fn kill(pid: ContextId, sig: usize) -> Result { - let (ruid, euid) = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - (context.ruid, context.euid) - }; - - if sig > 0 && sig <= 0x7F { - let contexts = context::contexts(); - let context_lock = contexts.get(pid).ok_or(Error::new(ESRCH))?; - let mut context = context_lock.write(); - if euid == 0 - || euid == context.ruid - || ruid == context.ruid - { - context.pending.push_back(sig as u8); - Ok(0) - } else { - Err(Error::new(EPERM)) - } - } else { - Err(Error::new(EINVAL)) - } -} - -fn reap(pid: ContextId) -> Result { - // Spin until not running - let mut running = false; - while running { - { - let contexts = context::contexts(); - let context_lock = contexts.get(pid).ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - running = context.running; - } - - arch::interrupt::pause(); - } - - let mut contexts = context::contexts_mut(); - let context_lock = contexts.remove(pid).ok_or(Error::new(ESRCH))?; - { - let mut context = context_lock.write(); - empty(&mut context, true); - } - drop(context_lock); - - Ok(pid) -} - -pub fn waitpid(pid: ContextId, status_ptr: usize, flags: usize) -> Result { - let waitpid = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - context.waitpid.clone() - }; - - let mut tmp = [0]; - let status_slice = if status_ptr != 0 { - validate_slice_mut(status_ptr as *mut usize, 1)? - } else { - &mut tmp - }; - - if pid.into() == 0 { - if flags & WNOHANG == WNOHANG { - if let Some((w_pid, status)) = waitpid.receive_any_nonblock() { - status_slice[0] = status; - reap(w_pid) - } else { - Ok(ContextId::from(0)) - } - } else { - let (w_pid, status) = waitpid.receive_any(); - status_slice[0] = status; - reap(w_pid) - } - } else { - if flags & WNOHANG == WNOHANG { - if let Some(status) = waitpid.receive_nonblock(&pid) { - status_slice[0] = status; - reap(pid) - } else { - Ok(ContextId::from(0)) - } - } else { - let status = waitpid.receive(&pid); - status_slice[0] = status; - reap(pid) - } - } -} diff --git a/kernel/src/syscall/time.rs b/kernel/src/syscall/time.rs deleted file mode 100644 index 448f311..0000000 --- a/kernel/src/syscall/time.rs +++ /dev/null @@ -1,53 +0,0 @@ -use arch; -use context; -use syscall::data::TimeSpec; -use syscall::error::*; -use syscall::flag::{CLOCK_REALTIME, CLOCK_MONOTONIC}; - -pub fn clock_gettime(clock: usize, time: &mut TimeSpec) -> Result { - match clock { - CLOCK_REALTIME => { - let arch_time = arch::time::realtime(); - time.tv_sec = arch_time.0 as i64; - time.tv_nsec = arch_time.1 as i32; - Ok(0) - }, - CLOCK_MONOTONIC => { - let arch_time = arch::time::monotonic(); - time.tv_sec = arch_time.0 as i64; - time.tv_nsec = arch_time.1 as i32; - Ok(0) - }, - _ => Err(Error::new(EINVAL)) - } -} - -pub fn nanosleep(req: &TimeSpec, rem_opt: Option<&mut TimeSpec>) -> Result { - let start = arch::time::monotonic(); - let sum = start.1 + req.tv_nsec as u64; - let end = (start.0 + req.tv_sec as u64 + sum / 1000000000, sum % 1000000000); - - { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let mut context = context_lock.write(); - - context.wake = Some(end); - context.block(); - } - - unsafe { context::switch(); } - - if let Some(mut rem) = rem_opt { - //TODO let current = arch::time::monotonic(); - rem.tv_sec = 0; - rem.tv_nsec = 0; - } - - Ok(0) -} - -pub fn sched_yield() -> Result { - unsafe { context::switch(); } - Ok(0) -} diff --git a/kernel/src/syscall/validate.rs b/kernel/src/syscall/validate.rs deleted file mode 100644 index 0f5b03b..0000000 --- a/kernel/src/syscall/validate.rs +++ /dev/null @@ -1,44 +0,0 @@ -use core::{mem, slice}; - -use arch::paging::{ActivePageTable, Page, VirtualAddress, entry}; -use syscall::error::*; - -fn validate(address: usize, size: usize, flags: entry::EntryFlags) -> Result<()> { - let active_table = unsafe { ActivePageTable::new() }; - - let start_page = Page::containing_address(VirtualAddress::new(address)); - let end_page = Page::containing_address(VirtualAddress::new(address + size - 1)); - for page in Page::range_inclusive(start_page, end_page) { - if let Some(page_flags) = active_table.translate_page_flags(page) { - if ! page_flags.contains(flags) { - //println!("{:X}: Not {:?}", page.start_address().get(), flags); - return Err(Error::new(EFAULT)); - } - } else { - //println!("{:X}: Not found", page.start_address().get()); - return Err(Error::new(EFAULT)); - } - } - - Ok(()) -} - -/// Convert a pointer and length to slice, if valid -pub fn validate_slice(ptr: *const T, len: usize) -> Result<&'static [T]> { - if len == 0 { - Ok(&[]) - } else { - validate(ptr as usize, len * mem::size_of::(), entry::PRESENT /* TODO | entry::USER_ACCESSIBLE */)?; - Ok(unsafe { slice::from_raw_parts(ptr, len) }) - } -} - -/// Convert a pointer and length to slice, if valid -pub fn validate_slice_mut(ptr: *mut T, len: usize) -> Result<&'static mut [T]> { - if len == 0 { - Ok(&mut []) - } else { - validate(ptr as usize, len * mem::size_of::(), entry::PRESENT | entry::WRITABLE /* TODO | entry::USER_ACCESSIBLE */)?; - Ok(unsafe { slice::from_raw_parts_mut(ptr, len) }) - } -} diff --git a/kernel/src/tests/mod.rs b/kernel/src/tests/mod.rs deleted file mode 100644 index 0ad27af..0000000 --- a/kernel/src/tests/mod.rs +++ /dev/null @@ -1,29 +0,0 @@ -use syscall::{self, Error}; - -/// Test stdio -#[test] -fn stdio() { - // Test opening stdin - assert_eq!(syscall::open(b"debug:", 0), Ok(0)); - - // Test opening stdout - assert_eq!(syscall::open(b"debug:", 0), Ok(1)); - - // Test opening stderr - assert_eq!(syscall::open(b"debug:", 0), Ok(2)); - - // Test writing stdout - let stdout_str = b"STDOUT"; - assert_eq!(syscall::write(1, stdout_str), Ok(stdout_str.len())); - - // Test writing stderr - let stderr_str = b"STDERR"; - assert_eq!(syscall::write(2, stderr_str), Ok(stderr_str.len())); -} - -/// Test that invalid reads/writes cause errors -#[test] -fn invalid_path() { - assert_eq!(syscall::read(999, &mut []), Err(Error::new(EBADF))); - assert_eq!(syscall::write(999, &[]), Err(Error::new(EBADF))); -} From 67496b67dfe92e1bdb3af1fac0f0a9d1ea2ef7d7 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 4 Jan 2017 15:52:54 -0700 Subject: [PATCH 043/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index 0c8ba63..882e64b 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 0c8ba636f4263665dae1b0fdd0a040e4e0c724f5 +Subproject commit 882e64bdb976b365f055d3b0e225ced06dec8b49 From cd366c21652468a893806675291c35debba65f55 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 4 Jan 2017 16:25:55 -0700 Subject: [PATCH 044/522] Fix name of bgad --- drivers/bgad/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/bgad/Cargo.toml b/drivers/bgad/Cargo.toml index cc9ce26..c763e32 100644 --- a/drivers/bgad/Cargo.toml +++ b/drivers/bgad/Cargo.toml @@ -1,3 +1,3 @@ [package] -name = "rtl8168d" +name = "bgad" version = "0.1.0" From ff06f2d19f0363702ef7f282bcf5cef0ca2a82ce Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 4 Jan 2017 16:34:43 -0700 Subject: [PATCH 045/522] Use cargo workspace (which will potentially improve build times --- Cargo.toml | 34 +++++++++++++++++ Makefile | 108 ++++------------------------------------------------- kernel | 2 +- 3 files changed, 43 insertions(+), 101 deletions(-) create mode 100644 Cargo.toml diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..d6329de --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,34 @@ +[workspace] +members = [ + "drivers/ahcid", + "drivers/bgad", + "drivers/e1000d", + "drivers/pcid", + "drivers/ps2d", + "drivers/rtl8168d", + "drivers/vesad", + "kernel", + "programs/acid", + "programs/binutils", + "programs/contain", + "programs/coreutils", + "programs/extrautils", + "programs/games", + "programs/init", + "programs/ion", + "programs/netutils", + "programs/orbutils", + "programs/pkgutils", + "programs/smith", + "programs/tar", + "programs/userutils", + "schemes/ethernetd", + "schemes/example", + "schemes/ipd", + "schemes/orbital", + "schemes/ptyd", + "schemes/randd", + "schemes/redoxfs", + "schemes/tcpd", + "schemes/udpd" +] diff --git a/Makefile b/Makefile index 4cbd23c..9592719 100644 --- a/Makefile +++ b/Makefile @@ -37,38 +37,9 @@ iso: build/livedisk.iso FORCE: clean: + cargo clean cargo clean --manifest-path rust/src/libstd/Cargo.toml - cargo clean --manifest-path kernel/Cargo.toml - cargo clean --manifest-path drivers/ahcid/Cargo.toml - cargo clean --manifest-path drivers/e1000d/Cargo.toml - cargo clean --manifest-path drivers/ps2d/Cargo.toml - cargo clean --manifest-path drivers/pcid/Cargo.toml - cargo clean --manifest-path drivers/rtl8168d/Cargo.toml - cargo clean --manifest-path drivers/vesad/Cargo.toml - cargo clean --manifest-path programs/acid/Cargo.toml - cargo clean --manifest-path programs/contain/Cargo.toml - cargo clean --manifest-path programs/init/Cargo.toml - cargo clean --manifest-path programs/ion/Cargo.toml - cargo clean --manifest-path programs/binutils/Cargo.toml - cargo clean --manifest-path programs/coreutils/Cargo.toml - cargo clean --manifest-path programs/extrautils/Cargo.toml - cargo clean --manifest-path programs/games/Cargo.toml - cargo clean --manifest-path programs/netutils/Cargo.toml - cargo clean --manifest-path programs/orbutils/Cargo.toml - cargo clean --manifest-path programs/pkgutils/Cargo.toml - cargo clean --manifest-path programs/userutils/Cargo.toml - cargo clean --manifest-path programs/smith/Cargo.toml - cargo clean --manifest-path programs/tar/Cargo.toml - cargo clean --manifest-path schemes/ethernetd/Cargo.toml - cargo clean --manifest-path schemes/example/Cargo.toml - cargo clean --manifest-path schemes/ipd/Cargo.toml - cargo clean --manifest-path schemes/orbital/Cargo.toml - cargo clean --manifest-path schemes/ptyd/Cargo.toml - cargo clean --manifest-path schemes/randd/Cargo.toml - cargo clean --manifest-path schemes/redoxfs/Cargo.toml - cargo clean --manifest-path schemes/tcpd/Cargo.toml - cargo clean --manifest-path schemes/udpd/Cargo.toml - -$(FUMOUNT) build/filesystem/ + -$(FUMOUNT) build/filesystem/ || true rm -rf initfs/bin rm -rf filesystem/bin filesystem/sbin filesystem/ui/bin rm -rf build @@ -92,71 +63,8 @@ ref: FORCE cargo run --manifest-path crates/docgen/Cargo.toml -- programs/extrautils/src/bin/ filesystem/ref/ cargo run --manifest-path crates/docgen/Cargo.toml -- programs/netutils/src/ filesystem/ref/ -test: - cargo test --manifest-path rust/src/libstd/Cargo.toml - cargo test --manifest-path kernel/Cargo.toml - cargo test --manifest-path drivers/ahcid/Cargo.toml - cargo test --manifest-path drivers/e1000d/Cargo.toml - cargo test --manifest-path drivers/ps2d/Cargo.toml - cargo test --manifest-path drivers/pcid/Cargo.toml - cargo test --manifest-path drivers/rtl8168d/Cargo.toml - cargo test --manifest-path drivers/vesad/Cargo.toml - cargo test --manifest-path programs/acid/Cargo.toml - cargo test --manifest-path programs/contain/Cargo.toml - cargo test --manifest-path programs/init/Cargo.toml - cargo test --manifest-path programs/ion/Cargo.toml - cargo test --manifest-path programs/binutils/Cargo.toml - cargo test --manifest-path programs/coreutils/Cargo.toml - cargo test --manifest-path programs/extrautils/Cargo.toml - cargo test --manifest-path programs/games/Cargo.toml - cargo test --manifest-path programs/netutils/Cargo.toml - cargo test --manifest-path programs/orbutils/Cargo.toml - cargo test --manifest-path programs/pkgutils/Cargo.toml - cargo test --manifest-path programs/userutils/Cargo.toml - cargo test --manifest-path programs/smith/Cargo.toml - cargo test --manifest-path programs/tar/Cargo.toml - cargo test --manifest-path schemes/ethernetd/Cargo.toml - cargo test --manifest-path schemes/example/Cargo.toml - cargo test --manifest-path schemes/ipd/Cargo.toml - cargo test --manifest-path schemes/orbital/Cargo.toml - cargo test --manifest-path schemes/ptyd/Cargo.toml - cargo test --manifest-path schemes/randd/Cargo.toml - cargo test --manifest-path schemes/redoxfs/Cargo.toml - cargo test --manifest-path schemes/tcpd/Cargo.toml - cargo test --manifest-path schemes/udpd/Cargo.toml - update: - #cargo update --manifest-path rust/src/libstd/Cargo.toml - cargo update --manifest-path kernel/Cargo.toml - cargo update --manifest-path drivers/ahcid/Cargo.toml - cargo update --manifest-path drivers/e1000d/Cargo.toml - cargo update --manifest-path drivers/ps2d/Cargo.toml - cargo update --manifest-path drivers/pcid/Cargo.toml - cargo update --manifest-path drivers/rtl8168d/Cargo.toml - cargo update --manifest-path drivers/vesad/Cargo.toml - cargo update --manifest-path programs/acid/Cargo.toml - cargo update --manifest-path programs/contain/Cargo.toml - cargo update --manifest-path programs/init/Cargo.toml - cargo update --manifest-path programs/ion/Cargo.toml - cargo update --manifest-path programs/binutils/Cargo.toml - cargo update --manifest-path programs/coreutils/Cargo.toml - cargo update --manifest-path programs/extrautils/Cargo.toml - cargo update --manifest-path programs/games/Cargo.toml - cargo update --manifest-path programs/netutils/Cargo.toml - cargo update --manifest-path programs/orbutils/Cargo.toml - cargo update --manifest-path programs/pkgutils/Cargo.toml - cargo update --manifest-path programs/userutils/Cargo.toml - cargo update --manifest-path programs/smith/Cargo.toml - cargo update --manifest-path programs/tar/Cargo.toml - cargo update --manifest-path schemes/ethernetd/Cargo.toml - cargo update --manifest-path schemes/example/Cargo.toml - cargo update --manifest-path schemes/ipd/Cargo.toml - cargo update --manifest-path schemes/orbital/Cargo.toml - cargo update --manifest-path schemes/ptyd/Cargo.toml - cargo update --manifest-path schemes/randd/Cargo.toml - cargo update --manifest-path schemes/redoxfs/Cargo.toml - cargo update --manifest-path schemes/tcpd/Cargo.toml - cargo update --manifest-path schemes/udpd/Cargo.toml + cargo update pull: git pull --rebase --recurse-submodules @@ -591,13 +499,13 @@ build/filesystem.bin: \ filesystem/bin/sh \ filesystem/bin/smith \ filesystem/bin/tar - -$(FUMOUNT) build/filesystem/ + -$(FUMOUNT) build/filesystem/ || true rm -rf $@ build/filesystem/ dd if=/dev/zero of=$@ bs=1048576 count=64 cargo run --manifest-path schemes/redoxfs/Cargo.toml --release --bin redoxfs-mkfs $@ mkdir -p build/filesystem/ cargo build --manifest-path schemes/redoxfs/Cargo.toml --release --bin redoxfs - schemes/redoxfs/target/release/redoxfs $@ build/filesystem/ + cargo run --manifest-path schemes/redoxfs/Cargo.toml --release --bin redoxfs -- $@ build/filesystem/ sleep 2 pgrep redoxfs cp -RL filesystem/* build/filesystem/ @@ -617,19 +525,19 @@ build/filesystem.bin: \ mkdir build/filesystem/tmp chmod 1777 build/filesystem/tmp sync - -$(FUMOUNT) build/filesystem/ + -$(FUMOUNT) build/filesystem/ || true rm -rf build/filesystem/ mount: FORCE mkdir -p build/filesystem/ cargo build --manifest-path schemes/redoxfs/Cargo.toml --release --bin redoxfs - schemes/redoxfs/target/release/redoxfs build/harddrive.bin build/filesystem/ + cargo run --manifest-path schemes/redoxfs/Cargo.toml --release --bin redoxfs -- build/harddrive.bin build/filesystem/ sleep 2 pgrep redoxfs unmount: FORCE sync - -$(FUMOUNT) build/filesystem/ + -$(FUMOUNT) build/filesystem/ || true rm -rf build/filesystem/ wireshark: FORCE diff --git a/kernel b/kernel index 882e64b..06118a2 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 882e64bdb976b365f055d3b0e225ced06dec8b49 +Subproject commit 06118a23ddf578424c35c2a0f9b704acbc5648f0 From 477c7379ead024f779cd5d21bdac2d960652bd52 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 4 Jan 2017 16:46:18 -0700 Subject: [PATCH 046/522] Cleanup dependencies --- drivers/ps2d/Cargo.toml | 2 +- drivers/vesad/Cargo.toml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/ps2d/Cargo.toml b/drivers/ps2d/Cargo.toml index 98ebbf2..22863b9 100644 --- a/drivers/ps2d/Cargo.toml +++ b/drivers/ps2d/Cargo.toml @@ -6,5 +6,5 @@ version = "0.1.0" bitflags = "*" event = { path = "../../crates/event/" } io = { path = "../../crates/io/" } -orbclient = "0.1" +orbclient = "0.2" redox_syscall = { path = "../../syscall/" } diff --git a/drivers/vesad/Cargo.toml b/drivers/vesad/Cargo.toml index 9041edb..a70dbf0 100644 --- a/drivers/vesad/Cargo.toml +++ b/drivers/vesad/Cargo.toml @@ -3,9 +3,9 @@ name = "vesad" version = "0.1.0" [dependencies] -orbclient = "0.1" +orbclient = "0.2" ransid = "0.2" -rusttype = { git = "https://github.com/dylanede/rusttype.git", optional = true } +rusttype = { version = "0.2", optional = true } redox_syscall = { path = "../../syscall" } [features] From 2eda65945f05daacff449927659c6fdac5d412e6 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 4 Jan 2017 17:11:22 -0700 Subject: [PATCH 047/522] Simplify travis build --- .travis.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index efb4c03..d8e9d69 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,10 +5,10 @@ rust: cache: cargo os: - linux -- osx -matrix: - allow_failures: - - os: osx +#- osx +#matrix: +# allow_failures: +# - os: osx dist: trusty before_install: - if [ "$TRAVIS_OS_NAME" == "linux" ]; then @@ -26,7 +26,7 @@ before_install: script: - make clean && make update && - make build/harddrive.bin.gz build/livedisk.bin.gz build/livedisk.iso -j 2 + make build/harddrive.bin.gz build/livedisk.bin.gz build/livedisk.iso notifications: email: false webhooks: http://37.139.9.28:54863/travis From 7ae998ce3b592953fbca69e264998bc5b861d3db Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 5 Jan 2017 11:22:36 -0700 Subject: [PATCH 048/522] Move drivers to submodule --- .gitmodules | 3 + drivers | 1 + drivers/ahcid/Cargo.toml | 10 - drivers/ahcid/src/ahci/disk.rs | 108 ------- drivers/ahcid/src/ahci/fis.rs | 155 ----------- drivers/ahcid/src/ahci/hba.rs | 417 ---------------------------- drivers/ahcid/src/ahci/mod.rs | 35 --- drivers/ahcid/src/main.rs | 86 ------ drivers/ahcid/src/scheme.rs | 166 ----------- drivers/bgad/Cargo.toml | 3 - drivers/bgad/src/main.rs | 13 - drivers/e1000d/Cargo.toml | 11 - drivers/e1000d/src/device.rs | 346 ----------------------- drivers/e1000d/src/main.rs | 136 --------- drivers/pcid/Cargo.toml | 8 - drivers/pcid/src/config.rs | 14 - drivers/pcid/src/main.rs | 160 ----------- drivers/pcid/src/pci/bar.rs | 18 -- drivers/pcid/src/pci/bus.rs | 46 --- drivers/pcid/src/pci/class.rs | 50 ---- drivers/pcid/src/pci/dev.rs | 46 --- drivers/pcid/src/pci/func.rs | 30 -- drivers/pcid/src/pci/header.rs | 43 --- drivers/pcid/src/pci/mod.rs | 78 ------ drivers/ps2d/Cargo.toml | 10 - drivers/ps2d/src/controller.rs | 233 ---------------- drivers/ps2d/src/keymap.rs | 148 ---------- drivers/ps2d/src/main.rs | 193 ------------- drivers/rtl8168d/Cargo.toml | 11 - drivers/rtl8168d/src/device.rs | 300 -------------------- drivers/rtl8168d/src/main.rs | 141 ---------- drivers/vesad/Cargo.toml | 12 - drivers/vesad/src/display.rs | 246 ---------------- drivers/vesad/src/main.rs | 109 -------- drivers/vesad/src/mode_info.rs | 37 --- drivers/vesad/src/primitive.rs | 47 ---- drivers/vesad/src/scheme.rs | 190 ------------- drivers/vesad/src/screen/graphic.rs | 126 --------- drivers/vesad/src/screen/mod.rs | 32 --- drivers/vesad/src/screen/text.rs | 233 ---------------- 40 files changed, 4 insertions(+), 4047 deletions(-) create mode 160000 drivers delete mode 100644 drivers/ahcid/Cargo.toml delete mode 100644 drivers/ahcid/src/ahci/disk.rs delete mode 100644 drivers/ahcid/src/ahci/fis.rs delete mode 100644 drivers/ahcid/src/ahci/hba.rs delete mode 100644 drivers/ahcid/src/ahci/mod.rs delete mode 100644 drivers/ahcid/src/main.rs delete mode 100644 drivers/ahcid/src/scheme.rs delete mode 100644 drivers/bgad/Cargo.toml delete mode 100644 drivers/bgad/src/main.rs delete mode 100644 drivers/e1000d/Cargo.toml delete mode 100644 drivers/e1000d/src/device.rs delete mode 100644 drivers/e1000d/src/main.rs delete mode 100644 drivers/pcid/Cargo.toml delete mode 100644 drivers/pcid/src/config.rs delete mode 100644 drivers/pcid/src/main.rs delete mode 100644 drivers/pcid/src/pci/bar.rs delete mode 100644 drivers/pcid/src/pci/bus.rs delete mode 100644 drivers/pcid/src/pci/class.rs delete mode 100644 drivers/pcid/src/pci/dev.rs delete mode 100644 drivers/pcid/src/pci/func.rs delete mode 100644 drivers/pcid/src/pci/header.rs delete mode 100644 drivers/pcid/src/pci/mod.rs delete mode 100644 drivers/ps2d/Cargo.toml delete mode 100644 drivers/ps2d/src/controller.rs delete mode 100644 drivers/ps2d/src/keymap.rs delete mode 100644 drivers/ps2d/src/main.rs delete mode 100644 drivers/rtl8168d/Cargo.toml delete mode 100644 drivers/rtl8168d/src/device.rs delete mode 100644 drivers/rtl8168d/src/main.rs delete mode 100644 drivers/vesad/Cargo.toml delete mode 100644 drivers/vesad/src/display.rs delete mode 100644 drivers/vesad/src/main.rs delete mode 100644 drivers/vesad/src/mode_info.rs delete mode 100644 drivers/vesad/src/primitive.rs delete mode 100644 drivers/vesad/src/scheme.rs delete mode 100644 drivers/vesad/src/screen/graphic.rs delete mode 100644 drivers/vesad/src/screen/mod.rs delete mode 100644 drivers/vesad/src/screen/text.rs diff --git a/.gitmodules b/.gitmodules index 02f5947..c5a24df 100644 --- a/.gitmodules +++ b/.gitmodules @@ -61,3 +61,6 @@ [submodule "kernel"] path = kernel url = https://github.com/redox-os/kernel.git +[submodule "drivers"] + path = drivers + url = https://github.com/redox-os/drivers.git diff --git a/drivers b/drivers new file mode 160000 index 0000000..9eeade8 --- /dev/null +++ b/drivers @@ -0,0 +1 @@ +Subproject commit 9eeade88606095a03ee3c285972b45d1c499a971 diff --git a/drivers/ahcid/Cargo.toml b/drivers/ahcid/Cargo.toml deleted file mode 100644 index f718331..0000000 --- a/drivers/ahcid/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "ahcid" -version = "0.1.0" - -[dependencies] -bitflags = "*" -dma = { path = "../../crates/dma/" } -io = { path = "../../crates/io/" } -spin = "*" -redox_syscall = { path = "../../syscall/" } diff --git a/drivers/ahcid/src/ahci/disk.rs b/drivers/ahcid/src/ahci/disk.rs deleted file mode 100644 index 4389425..0000000 --- a/drivers/ahcid/src/ahci/disk.rs +++ /dev/null @@ -1,108 +0,0 @@ -use std::ptr; - -use dma::Dma; -use syscall::error::Result; - -use super::hba::{HbaPort, HbaCmdTable, HbaCmdHeader}; - -pub struct Disk { - id: usize, - port: &'static mut HbaPort, - size: u64, - clb: Dma<[HbaCmdHeader; 32]>, - ctbas: [Dma; 32], - _fb: Dma<[u8; 256]>, - buf: Dma<[u8; 256 * 512]> -} - -impl Disk { - pub fn new(id: usize, port: &'static mut HbaPort) -> Result { - let mut clb = Dma::zeroed()?; - let mut ctbas = [ - Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, - Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, - Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, - Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, - Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, - Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, - Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, - Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, - ]; - let mut fb = Dma::zeroed()?; - let buf = Dma::zeroed()?; - - port.init(&mut clb, &mut ctbas, &mut fb); - - let size = unsafe { port.identify(&mut clb, &mut ctbas).unwrap_or(0) }; - - Ok(Disk { - id: id, - port: port, - size: size, - clb: clb, - ctbas: ctbas, - _fb: fb, - buf: buf - }) - } - - pub fn id(&self) -> usize { - self.id - } - - pub fn size(&self) -> u64 { - self.size - } - - pub fn read(&mut self, block: u64, buffer: &mut [u8]) -> Result { - let sectors = buffer.len()/512; - - let mut sector: usize = 0; - while sectors - sector >= 255 { - if let Err(err) = self.port.ata_dma(block + sector as u64, 255, false, &mut self.clb, &mut self.ctbas, &mut self.buf) { - return Err(err); - } - - unsafe { ptr::copy(self.buf.as_ptr(), buffer.as_mut_ptr().offset(sector as isize * 512), 255 * 512); } - - sector += 255; - } - if sector < sectors { - if let Err(err) = self.port.ata_dma(block + sector as u64, sectors - sector, false, &mut self.clb, &mut self.ctbas, &mut self.buf) { - return Err(err); - } - - unsafe { ptr::copy(self.buf.as_ptr(), buffer.as_mut_ptr().offset(sector as isize * 512), (sectors - sector) * 512); } - - sector += sectors - sector; - } - - Ok(sector * 512) - } - - pub fn write(&mut self, block: u64, buffer: &[u8]) -> Result { - let sectors = buffer.len()/512; - - let mut sector: usize = 0; - while sectors - sector >= 255 { - unsafe { ptr::copy(buffer.as_ptr().offset(sector as isize * 512), self.buf.as_mut_ptr(), 255 * 512); } - - if let Err(err) = self.port.ata_dma(block + sector as u64, 255, true, &mut self.clb, &mut self.ctbas, &mut self.buf) { - return Err(err); - } - - sector += 255; - } - if sector < sectors { - unsafe { ptr::copy(buffer.as_ptr().offset(sector as isize * 512), self.buf.as_mut_ptr(), (sectors - sector) * 512); } - - if let Err(err) = self.port.ata_dma(block + sector as u64, sectors - sector, true, &mut self.clb, &mut self.ctbas, &mut self.buf) { - return Err(err); - } - - sector += sectors - sector; - } - - Ok(sector * 512) - } -} diff --git a/drivers/ahcid/src/ahci/fis.rs b/drivers/ahcid/src/ahci/fis.rs deleted file mode 100644 index 7dbe33c..0000000 --- a/drivers/ahcid/src/ahci/fis.rs +++ /dev/null @@ -1,155 +0,0 @@ -use io::Mmio; - -#[repr(u8)] -pub enum FisType { - /// Register FIS - host to device - RegH2D = 0x27, - /// Register FIS - device to host - RegD2H = 0x34, - /// DMA activate FIS - device to host - DmaAct = 0x39, - /// DMA setup FIS - bidirectional - DmaSetup = 0x41, - /// Data FIS - bidirectional - Data = 0x46, - /// BIST activate FIS - bidirectional - Bist = 0x58, - /// PIO setup FIS - device to host - PioSetup = 0x5F, - /// Set device bits FIS - device to host - DevBits = 0xA1 -} - -#[repr(packed)] -pub struct FisRegH2D { - // DWORD 0 - pub fis_type: Mmio, // FIS_TYPE_REG_H2D - - pub pm: Mmio, // Port multiplier, 1: Command, 0: Control - - pub command: Mmio, // Command register - pub featurel: Mmio, // Feature register, 7:0 - - // DWORD 1 - pub lba0: Mmio, // LBA low register, 7:0 - pub lba1: Mmio, // LBA mid register, 15:8 - pub lba2: Mmio, // LBA high register, 23:16 - pub device: Mmio, // Device register - - // DWORD 2 - pub lba3: Mmio, // LBA register, 31:24 - pub lba4: Mmio, // LBA register, 39:32 - pub lba5: Mmio, // LBA register, 47:40 - pub featureh: Mmio, // Feature register, 15:8 - - // DWORD 3 - pub countl: Mmio, // Count register, 7:0 - pub counth: Mmio, // Count register, 15:8 - pub icc: Mmio, // Isochronous command completion - pub control: Mmio, // Control register - - // DWORD 4 - pub rsv1: [Mmio; 4], // Reserved -} - -#[repr(packed)] -pub struct FisRegD2H { - // DWORD 0 - pub fis_type: Mmio, // FIS_TYPE_REG_D2H - - pub pm: Mmio, // Port multiplier, Interrupt bit: 2 - - pub status: Mmio, // Status register - pub error: Mmio, // Error register - - // DWORD 1 - pub lba0: Mmio, // LBA low register, 7:0 - pub lba1: Mmio, // LBA mid register, 15:8 - pub lba2: Mmio, // LBA high register, 23:16 - pub device: Mmio, // Device register - - // DWORD 2 - pub lba3: Mmio, // LBA register, 31:24 - pub lba4: Mmio, // LBA register, 39:32 - pub lba5: Mmio, // LBA register, 47:40 - pub rsv2: Mmio, // Reserved - - // DWORD 3 - pub countl: Mmio, // Count register, 7:0 - pub counth: Mmio, // Count register, 15:8 - pub rsv3: [Mmio; 2], // Reserved - - // DWORD 4 - pub rsv4: [Mmio; 4], // Reserved -} - -#[repr(packed)] -pub struct FisData { - // DWORD 0 - pub fis_type: Mmio, // FIS_TYPE_DATA - - pub pm: Mmio, // Port multiplier - - pub rsv1: [Mmio; 2], // Reserved - - // DWORD 1 ~ N - pub data: [Mmio; 252], // Payload -} - -#[repr(packed)] -pub struct FisPioSetup { - // DWORD 0 - pub fis_type: Mmio, // FIS_TYPE_PIO_SETUP - - pub pm: Mmio, // Port multiplier, direction: 4 - device to host, interrupt: 2 - - pub status: Mmio, // Status register - pub error: Mmio, // Error register - - // DWORD 1 - pub lba0: Mmio, // LBA low register, 7:0 - pub lba1: Mmio, // LBA mid register, 15:8 - pub lba2: Mmio, // LBA high register, 23:16 - pub device: Mmio, // Device register - - // DWORD 2 - pub lba3: Mmio, // LBA register, 31:24 - pub lba4: Mmio, // LBA register, 39:32 - pub lba5: Mmio, // LBA register, 47:40 - pub rsv2: Mmio, // Reserved - - // DWORD 3 - pub countl: Mmio, // Count register, 7:0 - pub counth: Mmio, // Count register, 15:8 - pub rsv3: Mmio, // Reserved - pub e_status: Mmio, // New value of status register - - // DWORD 4 - pub tc: Mmio, // Transfer count - pub rsv4: [Mmio; 2], // Reserved -} - -#[repr(packed)] -pub struct FisDmaSetup { - // DWORD 0 - pub fis_type: Mmio, // FIS_TYPE_DMA_SETUP - - pub pm: Mmio, // Port multiplier, direction: 4 - device to host, interrupt: 2, auto-activate: 1 - - pub rsv1: [Mmio; 2], // Reserved - - // DWORD 1&2 - pub dma_buffer_id: Mmio, /* DMA Buffer Identifier. Used to Identify DMA buffer in host memory. SATA Spec says host specific and not in Spec. Trying AHCI spec might work. */ - - // DWORD 3 - pub rsv3: Mmio, // More reserved - - // DWORD 4 - pub dma_buffer_offset: Mmio, // Byte offset into buffer. First 2 bits must be 0 - - // DWORD 5 - pub transfer_count: Mmio, // Number of bytes to transfer. Bit 0 must be 0 - - // DWORD 6 - pub rsv6: Mmio, // Reserved -} diff --git a/drivers/ahcid/src/ahci/hba.rs b/drivers/ahcid/src/ahci/hba.rs deleted file mode 100644 index d22b706..0000000 --- a/drivers/ahcid/src/ahci/hba.rs +++ /dev/null @@ -1,417 +0,0 @@ -use std::mem::size_of; -use std::ops::DerefMut; -use std::{ptr, u32}; - -use dma::Dma; -use io::{Io, Mmio}; -use syscall::error::{Error, Result, EIO}; - -use super::fis::{FisType, FisRegH2D}; - -const ATA_CMD_READ_DMA_EXT: u8 = 0x25; -const ATA_CMD_WRITE_DMA_EXT: u8 = 0x35; -const ATA_CMD_IDENTIFY: u8 = 0xEC; -const ATA_DEV_BUSY: u8 = 0x80; -const ATA_DEV_DRQ: u8 = 0x08; - -const HBA_PORT_CMD_CR: u32 = 1 << 15; -const HBA_PORT_CMD_FR: u32 = 1 << 14; -const HBA_PORT_CMD_FRE: u32 = 1 << 4; -const HBA_PORT_CMD_ST: u32 = 1; -const HBA_PORT_IS_ERR: u32 = 1 << 30 | 1 << 29 | 1 << 28 | 1 << 27; -const HBA_SSTS_PRESENT: u32 = 0x3; -const HBA_SIG_ATA: u32 = 0x00000101; -const HBA_SIG_ATAPI: u32 = 0xEB140101; -const HBA_SIG_PM: u32 = 0x96690101; -const HBA_SIG_SEMB: u32 = 0xC33C0101; - -fn pause() { - unsafe { asm!("pause" : : : "memory" : "intel", "volatile"); } -} - -#[derive(Debug)] -pub enum HbaPortType { - None, - Unknown(u32), - SATA, - SATAPI, - PM, - SEMB, -} - -#[repr(packed)] -pub struct HbaPort { - pub clb: [Mmio; 2], // 0x00, command list base address, 1K-byte aligned - pub fb: [Mmio; 2], // 0x08, FIS base address, 256-byte aligned - pub is: Mmio, // 0x10, interrupt status - pub ie: Mmio, // 0x14, interrupt enable - pub cmd: Mmio, // 0x18, command and status - pub _rsv0: Mmio, // 0x1C, Reserved - pub tfd: Mmio, // 0x20, task file data - pub sig: Mmio, // 0x24, signature - pub ssts: Mmio, // 0x28, SATA status (SCR0:SStatus) - pub sctl: Mmio, // 0x2C, SATA control (SCR2:SControl) - pub serr: Mmio, // 0x30, SATA error (SCR1:SError) - pub sact: Mmio, // 0x34, SATA active (SCR3:SActive) - pub ci: Mmio, // 0x38, command issue - pub sntf: Mmio, // 0x3C, SATA notification (SCR4:SNotification) - pub fbs: Mmio, // 0x40, FIS-based switch control - pub _rsv1: [Mmio; 11], // 0x44 ~ 0x6F, Reserved - pub vendor: [Mmio; 4], // 0x70 ~ 0x7F, vendor specific -} - -impl HbaPort { - pub fn probe(&self) -> HbaPortType { - if self.ssts.readf(HBA_SSTS_PRESENT) { - let sig = self.sig.read(); - match sig { - HBA_SIG_ATA => HbaPortType::SATA, - HBA_SIG_ATAPI => HbaPortType::SATAPI, - HBA_SIG_PM => HbaPortType::PM, - HBA_SIG_SEMB => HbaPortType::SEMB, - _ => HbaPortType::Unknown(sig), - } - } else { - HbaPortType::None - } - } - - pub fn start(&mut self) { - while self.cmd.readf(HBA_PORT_CMD_CR) { - pause(); - } - - self.cmd.writef(HBA_PORT_CMD_FRE | HBA_PORT_CMD_ST, true); - } - - pub fn stop(&mut self) { - self.cmd.writef(HBA_PORT_CMD_ST, false); - - while self.cmd.readf(HBA_PORT_CMD_FR | HBA_PORT_CMD_CR) { - pause(); - } - - self.cmd.writef(HBA_PORT_CMD_FRE, false); - } - - pub fn slot(&self) -> Option { - let slots = self.sact.read() | self.ci.read(); - for i in 0..32 { - if slots & 1 << i == 0 { - return Some(i); - } - } - None - } - - pub fn init(&mut self, clb: &mut Dma<[HbaCmdHeader; 32]>, ctbas: &mut [Dma; 32], fb: &mut Dma<[u8; 256]>) { - self.stop(); - - for i in 0..32 { - let cmdheader = &mut clb[i]; - cmdheader.ctba.write(ctbas[i].physical() as u64); - cmdheader.prdtl.write(0); - } - - self.clb[0].write(clb.physical() as u32); - self.clb[1].write((clb.physical() >> 32) as u32); - self.fb[0].write(fb.physical() as u32); - self.fb[1].write((fb.physical() >> 32) as u32); - let is = self.is.read(); - self.is.write(is); - self.ie.write(0); - let serr = self.serr.read(); - self.serr.write(serr); - - // Disable power management - let sctl = self.sctl.read() ; - self.sctl.write(sctl | 7 << 8); - - // Power on and spin up device - self.cmd.writef(1 << 2 | 1 << 1, true); - - print!("{}", format!(" - AHCI init {:X}\n", self.cmd.read())); - } - - pub unsafe fn identify(&mut self, clb: &mut Dma<[HbaCmdHeader; 32]>, ctbas: &mut [Dma; 32]) -> Option { - self.is.write(u32::MAX); - - let dest: Dma<[u16; 256]> = Dma::new([0; 256]).unwrap(); - - if let Some(slot) = self.slot() { - let cmdheader = &mut clb[slot as usize]; - cmdheader.cfl.write(((size_of::() / size_of::()) as u8)); - cmdheader.prdtl.write(1); - - { - let cmdtbl = &mut ctbas[slot as usize]; - ptr::write_bytes(cmdtbl.deref_mut() as *mut HbaCmdTable as *mut u8, 0, size_of::()); - - let prdt_entry = &mut cmdtbl.prdt_entry[0]; - prdt_entry.dba.write(dest.physical() as u64); - prdt_entry.dbc.write(512 | 1); - } - - { - let cmdfis = &mut *(ctbas[slot as usize].cfis.as_mut_ptr() as *mut FisRegH2D); - - cmdfis.fis_type.write(FisType::RegH2D as u8); - cmdfis.pm.write(1 << 7); - cmdfis.command.write(ATA_CMD_IDENTIFY); - cmdfis.device.write(0); - cmdfis.countl.write(1); - cmdfis.counth.write(0); - } - - while self.tfd.readf((ATA_DEV_BUSY | ATA_DEV_DRQ) as u32) { - pause(); - } - - self.ci.writef(1 << slot, true); - - self.start(); - - while (self.ci.readf(1 << slot) || self.tfd.readf(0x80)) && self.is.read() & HBA_PORT_IS_ERR == 0 { - pause(); - } - - self.stop(); - - if self.is.read() & HBA_PORT_IS_ERR != 0 { - print!("{}", format!("ERROR IS {:X} TFD {:X} SERR {:X}\n", self.is.read(), self.tfd.read(), self.serr.read())); - return None; - } - - let mut serial = String::new(); - for word in 10..20 { - let d = dest[word]; - let a = ((d >> 8) as u8) as char; - if a != '\0' { - serial.push(a); - } - let b = (d as u8) as char; - if b != '\0' { - serial.push(b); - } - } - - let mut firmware = String::new(); - for word in 23..27 { - let d = dest[word]; - let a = ((d >> 8) as u8) as char; - if a != '\0' { - firmware.push(a); - } - let b = (d as u8) as char; - if b != '\0' { - firmware.push(b); - } - } - - let mut model = String::new(); - for word in 27..47 { - let d = dest[word]; - let a = ((d >> 8) as u8) as char; - if a != '\0' { - model.push(a); - } - let b = (d as u8) as char; - if b != '\0' { - model.push(b); - } - } - - let mut sectors = (dest[100] as u64) | - ((dest[101] as u64) << 16) | - ((dest[102] as u64) << 32) | - ((dest[103] as u64) << 48); - - let lba_bits = if sectors == 0 { - sectors = (dest[60] as u64) | ((dest[61] as u64) << 16); - 28 - } else { - 48 - }; - - print!("{}", format!(" + Serial: {} Firmware: {} Model: {} {}-bit LBA Size: {} MB\n", - serial.trim(), firmware.trim(), model.trim(), lba_bits, sectors / 2048)); - - Some(sectors * 512) - } else { - None - } - } - - pub fn ata_dma(&mut self, block: u64, sectors: usize, write: bool, clb: &mut Dma<[HbaCmdHeader; 32]>, ctbas: &mut [Dma; 32], buf: &mut Dma<[u8; 256 * 512]>) -> Result { - if write { - //print!("{}", format!("AHCI {:X} DMA BLOCK: {:X} SECTORS: {} WRITE: {}\n", (self as *mut HbaPort) as usize, block, sectors, write)); - } - - assert!(sectors > 0 && sectors < 256); - - self.is.write(u32::MAX); - - if let Some(slot) = self.slot() { - if write { - //print!("{}", format!("SLOT {}\n", slot)); - } - - let cmdheader = &mut clb[slot as usize]; - - cmdheader.cfl.write(((size_of::() / size_of::()) as u8) | if write { 1 << 7 | 1 << 6 } else { 0 }); - - cmdheader.prdtl.write(1); - - { - let cmdtbl = &mut ctbas[slot as usize]; - unsafe { ptr::write_bytes(cmdtbl.deref_mut() as *mut HbaCmdTable as *mut u8, 0, size_of::()) }; - - let prdt_entry = &mut cmdtbl.prdt_entry[0]; - prdt_entry.dba.write(buf.physical() as u64); - prdt_entry.dbc.write(((sectors * 512) as u32) | 1); - } - - { - let cmdfis = unsafe { &mut *(ctbas[slot as usize].cfis.as_mut_ptr() as *mut FisRegH2D) }; - - cmdfis.fis_type.write(FisType::RegH2D as u8); - cmdfis.pm.write(1 << 7); - if write { - cmdfis.command.write(ATA_CMD_WRITE_DMA_EXT); - } else { - cmdfis.command.write(ATA_CMD_READ_DMA_EXT); - } - - cmdfis.lba0.write(block as u8); - cmdfis.lba1.write((block >> 8) as u8); - cmdfis.lba2.write((block >> 16) as u8); - - cmdfis.device.write(1 << 6); - - cmdfis.lba3.write((block >> 24) as u8); - cmdfis.lba4.write((block >> 32) as u8); - cmdfis.lba5.write((block >> 40) as u8); - - cmdfis.countl.write(sectors as u8); - cmdfis.counth.write((sectors >> 8) as u8); - } - - if write { - //print!("WAIT ATA_DEV_BUSY | ATA_DEV_DRQ\n"); - } - while self.tfd.readf((ATA_DEV_BUSY | ATA_DEV_DRQ) as u32) { - pause(); - } - - if write { - //print!("{}", format!("WRITE CI {:X} in {:X}\n", 1 << slot, self.ci.read())); - } - self.ci.writef(1 << slot, true); - - self.start(); - - if write { - //print!("{}", format!("WAIT CI {:X} in {:X}\n", 1 << slot, self.ci.read())); - } - while (self.ci.readf(1 << slot) || self.tfd.readf(0x80)) && self.is.read() & HBA_PORT_IS_ERR == 0 { - pause(); - if write { - //print!("{}", format!("WAIT CI {:X} TFD {:X} IS {:X} CMD {:X} SERR {:X}\n", self.ci.read(), self.tfd.read(), self.is.read(), self.cmd.read(), self.serr.read())); - } - } - - self.stop(); - - if self.is.read() & HBA_PORT_IS_ERR != 0 { - print!("{}", format!("ERROR IS {:X} IE {:X} CMD {:X} TFD {:X}\nSSTS {:X} SCTL {:X} SERR {:X} SACT {:X}\nCI {:X} SNTF {:X} FBS {:X}\n", - self.is.read(), self.ie.read(), self.cmd.read(), self.tfd.read(), - self.ssts.read(), self.sctl.read(), self.serr.read(), self.sact.read(), - self.ci.read(), self.sntf.read(), self.fbs.read())); - self.is.write(u32::MAX); - return Err(Error::new(EIO)); - } - - if write { - //print!("{}", format!("SUCCESS {}\n", sectors)); - } - Ok(sectors * 512) - } else { - print!("No Command Slots\n"); - Err(Error::new(EIO)) - } - } -} - -#[repr(packed)] -pub struct HbaMem { - pub cap: Mmio, // 0x00, Host capability - pub ghc: Mmio, // 0x04, Global host control - pub is: Mmio, // 0x08, Interrupt status - pub pi: Mmio, // 0x0C, Port implemented - pub vs: Mmio, // 0x10, Version - pub ccc_ctl: Mmio, // 0x14, Command completion coalescing control - pub ccc_pts: Mmio, // 0x18, Command completion coalescing ports - pub em_loc: Mmio, // 0x1C, Enclosure management location - pub em_ctl: Mmio, // 0x20, Enclosure management control - pub cap2: Mmio, // 0x24, Host capabilities extended - pub bohc: Mmio, // 0x28, BIOS/OS handoff control and status - pub _rsv: [Mmio; 116], // 0x2C - 0x9F, Reserved - pub vendor: [Mmio; 96], // 0xA0 - 0xFF, Vendor specific registers - pub ports: [HbaPort; 32], // 0x100 - 0x10FF, Port control registers -} - -impl HbaMem { - pub fn init(&mut self) { - /* - self.ghc.writef(1, true); - while self.ghc.readf(1) { - pause(); - } - */ - self.ghc.write(1 << 31 | 1 << 1); - - print!("{}", format!(" - AHCI CAP {:X} GHC {:X} IS {:X} PI {:X} VS {:X} CAP2 {:X} BOHC {:X}", - self.cap.read(), self.ghc.read(), self.is.read(), self.pi.read(), - self.vs.read(), self.cap2.read(), self.bohc.read())); - } -} - -#[repr(packed)] -pub struct HbaPrdtEntry { - dba: Mmio, // Data base address - _rsv0: Mmio, // Reserved - dbc: Mmio, // Byte count, 4M max, interrupt = 1 -} - -#[repr(packed)] -pub struct HbaCmdTable { - // 0x00 - cfis: [Mmio; 64], // Command FIS - - // 0x40 - _acmd: [Mmio; 16], // ATAPI command, 12 or 16 bytes - - // 0x50 - _rsv: [Mmio; 48], // Reserved - - // 0x80 - prdt_entry: [HbaPrdtEntry; 65536], // Physical region descriptor table entries, 0 ~ 65535 -} - -#[repr(packed)] -pub struct HbaCmdHeader { - // DW0 - cfl: Mmio, /* Command FIS length in DWORDS, 2 ~ 16, atapi: 4, write - host to device: 2, prefetchable: 1 */ - _pm: Mmio, // Reset - 0x80, bist: 0x40, clear busy on ok: 0x20, port multiplier - - prdtl: Mmio, // Physical region descriptor table length in entries - - // DW1 - _prdbc: Mmio, // Physical region descriptor byte count transferred - - // DW2, 3 - ctba: Mmio, // Command table descriptor base address - - // DW4 - 7 - _rsv1: [Mmio; 4], // Reserved -} diff --git a/drivers/ahcid/src/ahci/mod.rs b/drivers/ahcid/src/ahci/mod.rs deleted file mode 100644 index fec9e00..0000000 --- a/drivers/ahcid/src/ahci/mod.rs +++ /dev/null @@ -1,35 +0,0 @@ -use io::Io; - -use self::disk::Disk; -use self::hba::{HbaMem, HbaPortType}; - -pub mod disk; -pub mod fis; -pub mod hba; - -pub fn disks(base: usize, name: &str) -> Vec { - unsafe { &mut *(base as *mut HbaMem) }.init(); - let pi = unsafe { &mut *(base as *mut HbaMem) }.pi.read(); - let ret: Vec = (0..32) - .filter(|&i| pi & 1 << i as i32 == 1 << i as i32) - .filter_map(|i| { - let port = &mut unsafe { &mut *(base as *mut HbaMem) }.ports[i]; - let port_type = port.probe(); - print!("{}", format!("{}-{}: {:?}\n", name, i, port_type)); - match port_type { - HbaPortType::SATA => { - match Disk::new(i, port) { - Ok(disk) => Some(disk), - Err(err) => { - print!("{}", format!("{}: {}\n", i, err)); - None - } - } - } - _ => None, - } - }) - .collect(); - - ret -} diff --git a/drivers/ahcid/src/main.rs b/drivers/ahcid/src/main.rs deleted file mode 100644 index 4e8cbc9..0000000 --- a/drivers/ahcid/src/main.rs +++ /dev/null @@ -1,86 +0,0 @@ -#![feature(asm)] - -#[macro_use] -extern crate bitflags; -extern crate dma; -extern crate io; -extern crate spin; -extern crate syscall; - -use std::{env, usize}; -use std::fs::File; -use std::io::{Read, Write}; -use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; -use syscall::{EVENT_READ, MAP_WRITE, Event, Packet, Result, Scheme}; - -use scheme::DiskScheme; - -pub mod ahci; -pub mod scheme; - -fn create_scheme_fallback<'a>(name: &'a str, fallback: &'a str) -> Result<(&'a str, RawFd)> { - if let Ok(fd) = syscall::open(&format!(":{}", name), syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK) { - Ok((name, fd)) - } else { - syscall::open(&format!(":{}", fallback), syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK) - .map(|fd| (fallback, fd)) - } -} - -fn main() { - let mut args = env::args().skip(1); - - let mut name = args.next().expect("ahcid: no name provided"); - name.push_str("_ahci"); - - let bar_str = args.next().expect("ahcid: no address provided"); - let bar = usize::from_str_radix(&bar_str, 16).expect("ahcid: failed to parse address"); - - let irq_str = args.next().expect("ahcid: no irq provided"); - let irq = irq_str.parse::().expect("ahcid: failed to parse irq"); - - print!("{}", format!(" + AHCI {} on: {:X} IRQ: {}\n", name, bar, irq)); - - // Daemonize - if unsafe { syscall::clone(0).unwrap() } == 0 { - let address = unsafe { syscall::physmap(bar, 4096, MAP_WRITE).expect("ahcid: failed to map address") }; - { - let (_scheme_name, socket_fd) = create_scheme_fallback("disk", &name).expect("ahcid: failed to create disk scheme"); - let mut socket = unsafe { File::from_raw_fd(socket_fd) }; - syscall::fevent(socket_fd, EVENT_READ).expect("ahcid: failed to fevent disk scheme"); - - let mut irq_file = File::open(&format!("irq:{}", irq)).expect("ahcid: failed to open irq file"); - let irq_fd = irq_file.as_raw_fd(); - syscall::fevent(irq_fd, EVENT_READ).expect("ahcid: failed to fevent irq file"); - - let mut event_file = File::open("event:").expect("ahcid: failed to open event file"); - - let scheme = DiskScheme::new(ahci::disks(address, &name)); - loop { - let mut event = Event::default(); - if event_file.read(&mut event).expect("ahcid: failed to read event file") == 0 { - break; - } - if event.id == socket_fd { - loop { - let mut packet = Packet::default(); - if socket.read(&mut packet).expect("ahcid: failed to read disk scheme") == 0 { - break; - } - scheme.handle(&mut packet); - socket.write(&mut packet).expect("ahcid: failed to write disk scheme"); - } - } else if event.id == irq_fd { - let mut irq = [0; 8]; - if irq_file.read(&mut irq).expect("ahcid: failed to read irq file") >= irq.len() { - //TODO : Test for IRQ - //irq_file.write(&irq).expect("ahcid: failed to write irq file"); - } - } else { - println!("Unknown event {}", event.id); - } - } - } - unsafe { let _ = syscall::physunmap(address); } - } -} diff --git a/drivers/ahcid/src/scheme.rs b/drivers/ahcid/src/scheme.rs deleted file mode 100644 index cd35d76..0000000 --- a/drivers/ahcid/src/scheme.rs +++ /dev/null @@ -1,166 +0,0 @@ -use std::collections::BTreeMap; -use std::{cmp, str}; -use std::fmt::Write; -use std::io::Read; -use std::sync::Arc; -use std::sync::atomic::{AtomicUsize, Ordering}; -use spin::Mutex; -use syscall::{Error, EACCES, EBADF, EINVAL, EISDIR, ENOENT, Result, Scheme, Stat, MODE_DIR, MODE_FILE, O_DIRECTORY, O_STAT, SEEK_CUR, SEEK_END, SEEK_SET}; - -use ahci::disk::Disk; - -#[derive(Clone)] -enum Handle { - //TODO: Make these enum variants normal tuples (), not nested tuples (()) - List((Vec, usize)), - Disk((Arc>, usize)) -} - -pub struct DiskScheme { - disks: Box<[Arc>]>, - handles: Mutex>, - next_id: AtomicUsize -} - -impl DiskScheme { - pub fn new(disks: Vec) -> DiskScheme { - let mut disk_arcs = vec![]; - for disk in disks { - disk_arcs.push(Arc::new(Mutex::new(disk))); - } - - DiskScheme { - disks: disk_arcs.into_boxed_slice(), - handles: Mutex::new(BTreeMap::new()), - next_id: AtomicUsize::new(0) - } - } -} - -impl Scheme for DiskScheme { - fn open(&self, path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result { - if uid == 0 { - let path_str = str::from_utf8(path).or(Err(Error::new(ENOENT)))?.trim_matches('/'); - if path_str.is_empty() { - if flags & O_DIRECTORY == O_DIRECTORY || flags & O_STAT == O_STAT { - let mut list = String::new(); - - for i in 0..self.disks.len() { - write!(list, "{}\n", i).unwrap(); - } - - let id = self.next_id.fetch_add(1, Ordering::SeqCst); - self.handles.lock().insert(id, Handle::List((list.into_bytes(), 0))); - Ok(id) - } else { - Err(Error::new(EISDIR)) - } - } else { - let i = path_str.parse::().or(Err(Error::new(ENOENT)))?; - - if let Some(disk) = self.disks.get(i) { - let id = self.next_id.fetch_add(1, Ordering::SeqCst); - self.handles.lock().insert(id, Handle::Disk((disk.clone(), 0))); - Ok(id) - } else { - Err(Error::new(ENOENT)) - } - } - } else { - Err(Error::new(EACCES)) - } - } - - fn dup(&self, id: usize, _buf: &[u8]) -> Result { - let mut handles = self.handles.lock(); - let new_handle = { - let handle = handles.get(&id).ok_or(Error::new(EBADF))?; - handle.clone() - }; - - let new_id = self.next_id.fetch_add(1, Ordering::SeqCst); - handles.insert(new_id, new_handle); - Ok(new_id) - } - - fn fstat(&self, id: usize, stat: &mut Stat) -> Result { - let handles = self.handles.lock(); - match *handles.get(&id).ok_or(Error::new(EBADF))? { - Handle::List(ref handle) => { - stat.st_mode = MODE_DIR; - stat.st_size = handle.0.len() as u64; - Ok(0) - }, - Handle::Disk(ref handle) => { - stat.st_mode = MODE_FILE; - stat.st_size = handle.0.lock().size(); - Ok(0) - } - } - } - - fn read(&self, id: usize, buf: &mut [u8]) -> Result { - let mut handles = self.handles.lock(); - match *handles.get_mut(&id).ok_or(Error::new(EBADF))? { - Handle::List(ref mut handle) => { - let count = (&handle.0[handle.1..]).read(buf).unwrap(); - handle.1 += count; - Ok(count) - }, - Handle::Disk(ref mut handle) => { - let mut disk = handle.0.lock(); - let count = disk.read((handle.1 as u64)/512, buf)?; - handle.1 += count; - Ok(count) - } - } - } - - fn write(&self, id: usize, buf: &[u8]) -> Result { - let mut handles = self.handles.lock(); - match *handles.get_mut(&id).ok_or(Error::new(EBADF))? { - Handle::List(_) => { - Err(Error::new(EBADF)) - }, - Handle::Disk(ref mut handle) => { - let mut disk = handle.0.lock(); - let count = disk.write((handle.1 as u64)/512, buf)?; - handle.1 += count; - Ok(count) - } - } - } - - fn seek(&self, id: usize, pos: usize, whence: usize) -> Result { - let mut handles = self.handles.lock(); - match *handles.get_mut(&id).ok_or(Error::new(EBADF))? { - Handle::List(ref mut handle) => { - let len = handle.0.len() as usize; - handle.1 = match whence { - SEEK_SET => cmp::min(len, pos), - SEEK_CUR => cmp::max(0, cmp::min(len as isize, handle.1 as isize + pos as isize)) as usize, - SEEK_END => cmp::max(0, cmp::min(len as isize, len as isize + pos as isize)) as usize, - _ => return Err(Error::new(EINVAL)) - }; - - Ok(handle.1) - }, - Handle::Disk(ref mut handle) => { - let len = handle.0.lock().size() as usize; - handle.1 = match whence { - SEEK_SET => cmp::min(len, pos), - SEEK_CUR => cmp::max(0, cmp::min(len as isize, handle.1 as isize + pos as isize)) as usize, - SEEK_END => cmp::max(0, cmp::min(len as isize, len as isize + pos as isize)) as usize, - _ => return Err(Error::new(EINVAL)) - }; - - Ok(handle.1) - } - } - } - - fn close(&self, id: usize) -> Result { - let mut handles = self.handles.lock(); - handles.remove(&id).ok_or(Error::new(EBADF)).and(Ok(0)) - } -} diff --git a/drivers/bgad/Cargo.toml b/drivers/bgad/Cargo.toml deleted file mode 100644 index c763e32..0000000 --- a/drivers/bgad/Cargo.toml +++ /dev/null @@ -1,3 +0,0 @@ -[package] -name = "bgad" -version = "0.1.0" diff --git a/drivers/bgad/src/main.rs b/drivers/bgad/src/main.rs deleted file mode 100644 index 48d75d7..0000000 --- a/drivers/bgad/src/main.rs +++ /dev/null @@ -1,13 +0,0 @@ -use std::env; - -fn main() { - let mut args = env::args().skip(1); - - let mut name = args.next().expect("bgad: no name provided"); - name.push_str("_bga"); - - let bar_str = args.next().expect("bgad: no address provided"); - let bar = usize::from_str_radix(&bar_str, 16).expect("bgad: failed to parse address"); - - print!("{}", format!(" + BGA {} on: {:X}\n", name, bar)); -} diff --git a/drivers/e1000d/Cargo.toml b/drivers/e1000d/Cargo.toml deleted file mode 100644 index ec8c45e..0000000 --- a/drivers/e1000d/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "e1000d" -version = "0.1.0" - -[dependencies] -bitflags = "*" -dma = { path = "../../crates/dma/" } -event = { path = "../../crates/event/" } -io = { path = "../../crates/io/" } -netutils = { path = "../../programs/netutils/" } -redox_syscall = { path = "../../syscall/" } diff --git a/drivers/e1000d/src/device.rs b/drivers/e1000d/src/device.rs deleted file mode 100644 index 8cb46f3..0000000 --- a/drivers/e1000d/src/device.rs +++ /dev/null @@ -1,346 +0,0 @@ -use std::{cmp, mem, ptr, slice}; - -use dma::Dma; -use netutils::setcfg; -use syscall::error::{Error, EACCES, EWOULDBLOCK, Result}; -use syscall::flag::O_NONBLOCK; -use syscall::scheme::Scheme; - -const CTRL: u32 = 0x00; -const CTRL_LRST: u32 = 1 << 3; -const CTRL_ASDE: u32 = 1 << 5; -const CTRL_SLU: u32 = 1 << 6; -const CTRL_ILOS: u32 = 1 << 7; -const CTRL_VME: u32 = 1 << 30; -const CTRL_PHY_RST: u32 = 1 << 31; - -const STATUS: u32 = 0x08; - -const FCAL: u32 = 0x28; -const FCAH: u32 = 0x2C; -const FCT: u32 = 0x30; -const FCTTV: u32 = 0x170; - -const ICR: u32 = 0xC0; - -const IMS: u32 = 0xD0; -const IMS_TXDW: u32 = 1; -const IMS_TXQE: u32 = 1 << 1; -const IMS_LSC: u32 = 1 << 2; -const IMS_RXSEQ: u32 = 1 << 3; -const IMS_RXDMT: u32 = 1 << 4; -const IMS_RX: u32 = 1 << 6; -const IMS_RXT: u32 = 1 << 7; - -const RCTL: u32 = 0x100; -const RCTL_EN: u32 = 1 << 1; -const RCTL_UPE: u32 = 1 << 3; -const RCTL_MPE: u32 = 1 << 4; -const RCTL_LPE: u32 = 1 << 5; -const RCTL_LBM: u32 = 1 << 6 | 1 << 7; -const RCTL_BAM: u32 = 1 << 15; -const RCTL_BSIZE1: u32 = 1 << 16; -const RCTL_BSIZE2: u32 = 1 << 17; -const RCTL_BSEX: u32 = 1 << 25; -const RCTL_SECRC: u32 = 1 << 26; - -const RDBAL: u32 = 0x2800; -const RDBAH: u32 = 0x2804; -const RDLEN: u32 = 0x2808; -const RDH: u32 = 0x2810; -const RDT: u32 = 0x2818; - -const RAL0: u32 = 0x5400; -const RAH0: u32 = 0x5404; - -#[derive(Debug)] -#[repr(packed)] -struct Rd { - buffer: u64, - length: u16, - checksum: u16, - status: u8, - error: u8, - special: u16, -} -const RD_DD: u8 = 1; -const RD_EOP: u8 = 1 << 1; - -const TCTL: u32 = 0x400; -const TCTL_EN: u32 = 1 << 1; -const TCTL_PSP: u32 = 1 << 3; - -const TDBAL: u32 = 0x3800; -const TDBAH: u32 = 0x3804; -const TDLEN: u32 = 0x3808; -const TDH: u32 = 0x3810; -const TDT: u32 = 0x3818; - -#[derive(Debug)] -#[repr(packed)] -struct Td { - buffer: u64, - length: u16, - cso: u8, - command: u8, - status: u8, - css: u8, - special: u16, -} -const TD_CMD_EOP: u8 = 1; -const TD_CMD_IFCS: u8 = 1 << 1; -const TD_CMD_RS: u8 = 1 << 3; -const TD_DD: u8 = 1; - -pub struct Intel8254x { - base: usize, - receive_buffer: [Dma<[u8; 16384]>; 16], - receive_ring: Dma<[Rd; 16]>, - transmit_buffer: [Dma<[u8; 16384]>; 16], - transmit_ring: Dma<[Td; 16]> -} - -impl Scheme for Intel8254x { - fn open(&self, _path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result { - if uid == 0 { - Ok(flags) - } else { - Err(Error::new(EACCES)) - } - } - - fn dup(&self, id: usize, _buf: &[u8]) -> Result { - Ok(id) - } - - fn read(&self, id: usize, buf: &mut [u8]) -> Result { - let head = unsafe { self.read(RDH) }; - let mut tail = unsafe { self.read(RDT) }; - - tail += 1; - if tail >= self.receive_ring.len() as u32 { - tail = 0; - } - - if tail != head { - let rd = unsafe { &mut * (self.receive_ring.as_ptr().offset(tail as isize) as *mut Rd) }; - if rd.status & RD_DD == RD_DD { - rd.status = 0; - - let data = &self.receive_buffer[tail as usize][.. rd.length as usize]; - - let mut i = 0; - while i < buf.len() && i < data.len() { - buf[i] = data[i]; - i += 1; - } - - unsafe { self.write(RDT, tail) }; - - return Ok(i); - } - } - - if id & O_NONBLOCK == O_NONBLOCK { - Ok(0) - } else { - Err(Error::new(EWOULDBLOCK)) - } - } - - fn write(&self, _id: usize, buf: &[u8]) -> Result { - loop { - let head = unsafe { self.read(TDH) }; - let mut tail = unsafe { self.read(TDT) }; - let old_tail = tail; - - tail += 1; - if tail >= self.transmit_ring.len() as u32 { - tail = 0; - } - - if tail != head { - let td = unsafe { &mut * (self.transmit_ring.as_ptr().offset(old_tail as isize) as *mut Td) }; - - td.cso = 0; - td.command = TD_CMD_EOP | TD_CMD_IFCS | TD_CMD_RS; - td.status = 0; - td.css = 0; - td.special = 0; - - td.length = (cmp::min(buf.len(), 0x3FFF)) as u16; - - let mut data = unsafe { slice::from_raw_parts_mut(self.transmit_buffer[old_tail as usize].as_ptr() as *mut u8, td.length as usize) }; - - let mut i = 0; - while i < buf.len() && i < data.len() { - data[i] = buf[i]; - i += 1; - } - - unsafe { self.write(TDT, tail) }; - - while td.status == 0 { - unsafe { asm!("pause" : : : "memory" : "intel", "volatile"); } - } - - return Ok(i); - } - - unsafe { asm!("pause" : : : "memory" : "intel", "volatile"); } - } - } - - fn fevent(&self, _id: usize, _flags: usize) -> Result { - Ok(0) - } - - fn fsync(&self, _id: usize) -> Result { - Ok(0) - } - - fn close(&self, _id: usize) -> Result { - Ok(0) - } -} - -impl Intel8254x { - pub unsafe fn new(base: usize) -> Result { - let mut module = Intel8254x { - base: base, - receive_buffer: [Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, - Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, - Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, - Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?], - receive_ring: Dma::zeroed()?, - transmit_buffer: [Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, - Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, - Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, - Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?], - transmit_ring: Dma::zeroed()? - }; - - module.init(); - - Ok(module) - } - - pub unsafe fn irq(&self) -> bool { - let icr = self.read(ICR); - icr != 0 - } - - pub fn next_read(&self) -> usize { - let head = unsafe { self.read(RDH) }; - let mut tail = unsafe { self.read(RDT) }; - - tail += 1; - if tail >= self.receive_ring.len() as u32 { - tail = 0; - } - - if tail != head { - let rd = unsafe { &* (self.receive_ring.as_ptr().offset(tail as isize) as *const Rd) }; - if rd.status & RD_DD == RD_DD { - return rd.length as usize; - } - } - - 0 - } - - pub unsafe fn read(&self, register: u32) -> u32 { - ptr::read_volatile((self.base + register as usize) as *mut u32) - } - - pub unsafe fn write(&self, register: u32, data: u32) -> u32 { - ptr::write_volatile((self.base + register as usize) as *mut u32, data); - ptr::read_volatile((self.base + register as usize) as *mut u32) - } - - pub unsafe fn flag(&self, register: u32, flag: u32, value: bool) { - if value { - self.write(register, self.read(register) | flag); - } else { - self.write(register, self.read(register) & (0xFFFFFFFF - flag)); - } - } - - pub unsafe fn init(&mut self) { - // Enable auto negotiate, link, clear reset, do not Invert Loss-Of Signal - self.flag(CTRL, CTRL_ASDE | CTRL_SLU, true); - self.flag(CTRL, CTRL_LRST, false); - self.flag(CTRL, CTRL_PHY_RST, false); - self.flag(CTRL, CTRL_ILOS, false); - - // No flow control - self.write(FCAH, 0); - self.write(FCAL, 0); - self.write(FCT, 0); - self.write(FCTTV, 0); - - // Do not use VLANs - self.flag(CTRL, CTRL_VME, false); - - // TODO: Clear statistical counters - - let mac_low = self.read(RAL0); - let mac_high = self.read(RAH0); - let mac = [mac_low as u8, - (mac_low >> 8) as u8, - (mac_low >> 16) as u8, - (mac_low >> 24) as u8, - mac_high as u8, - (mac_high >> 8) as u8]; - print!("{}", format!(" - MAC: {:>02X}:{:>02X}:{:>02X}:{:>02X}:{:>02X}:{:>02X}\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])); - let _ = setcfg("mac", &format!("{:>02X}.{:>02X}.{:>02X}.{:>02X}.{:>02X}.{:>02X}", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])); - - // - // MTA => 0; - // - - // Receive Buffer - for i in 0..self.receive_ring.len() { - self.receive_ring[i].buffer = self.receive_buffer[i].physical() as u64; - } - - self.write(RDBAH, (self.receive_ring.physical() >> 32) as u32); - self.write(RDBAL, self.receive_ring.physical() as u32); - self.write(RDLEN, (self.receive_ring.len() * mem::size_of::()) as u32); - self.write(RDH, 0); - self.write(RDT, self.receive_ring.len() as u32 - 1); - - // Transmit Buffer - for i in 0..self.transmit_ring.len() { - self.transmit_ring[i].buffer = self.transmit_buffer[i].physical() as u64; - } - - self.write(TDBAH, (self.transmit_ring.physical() >> 32) as u32); - self.write(TDBAL, self.transmit_ring.physical() as u32); - self.write(TDLEN, (self.transmit_ring.len() * mem::size_of::()) as u32); - self.write(TDH, 0); - self.write(TDT, 0); - - self.write(IMS, IMS_RXT | IMS_RX | IMS_RXDMT | IMS_RXSEQ); // | IMS_LSC | IMS_TXQE | IMS_TXDW - - self.flag(RCTL, RCTL_EN, true); - self.flag(RCTL, RCTL_UPE, true); - // self.flag(RCTL, RCTL_MPE, true); - self.flag(RCTL, RCTL_LPE, true); - self.flag(RCTL, RCTL_LBM, false); - // RCTL.RDMTS = Minimum threshold size ??? - // RCTL.MO = Multicast offset - self.flag(RCTL, RCTL_BAM, true); - self.flag(RCTL, RCTL_BSIZE1, true); - self.flag(RCTL, RCTL_BSIZE2, false); - self.flag(RCTL, RCTL_BSEX, true); - self.flag(RCTL, RCTL_SECRC, true); - - self.flag(TCTL, TCTL_EN, true); - self.flag(TCTL, TCTL_PSP, true); - // TCTL.CT = Collision threshold - // TCTL.COLD = Collision distance - // TIPG Packet Gap - // TODO ... - } -} diff --git a/drivers/e1000d/src/main.rs b/drivers/e1000d/src/main.rs deleted file mode 100644 index b690029..0000000 --- a/drivers/e1000d/src/main.rs +++ /dev/null @@ -1,136 +0,0 @@ -#![feature(asm)] - -extern crate dma; -extern crate event; -extern crate netutils; -extern crate syscall; - -use std::cell::RefCell; -use std::env; -use std::fs::File; -use std::io::{Read, Write, Result}; -use std::os::unix::io::{AsRawFd, FromRawFd}; -use std::sync::Arc; - -use event::EventQueue; -use syscall::{Packet, Scheme, MAP_WRITE}; -use syscall::error::EWOULDBLOCK; - -pub mod device; - -fn main() { - let mut args = env::args().skip(1); - - let mut name = args.next().expect("e1000d: no name provided"); - name.push_str("_e1000"); - - let bar_str = args.next().expect("e1000d: no address provided"); - let bar = usize::from_str_radix(&bar_str, 16).expect("e1000d: failed to parse address"); - - let irq_str = args.next().expect("e1000d: no irq provided"); - let irq = irq_str.parse::().expect("e1000d: failed to parse irq"); - - print!("{}", format!(" + E1000 {} on: {:X}, IRQ: {}\n", name, bar, irq)); - - // Daemonize - if unsafe { syscall::clone(0).unwrap() } == 0 { - let socket_fd = syscall::open(":network", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK).expect("e1000d: failed to create network scheme"); - let socket = Arc::new(RefCell::new(unsafe { File::from_raw_fd(socket_fd) })); - - let address = unsafe { syscall::physmap(bar, 128*1024, MAP_WRITE).expect("e1000d: failed to map address") }; - { - let device = Arc::new(unsafe { device::Intel8254x::new(address).expect("e1000d: failed to allocate device") }); - - let mut event_queue = EventQueue::::new().expect("e1000d: failed to create event queue"); - - let todo = Arc::new(RefCell::new(Vec::::new())); - - let device_irq = device.clone(); - let socket_irq = socket.clone(); - let todo_irq = todo.clone(); - let mut irq_file = File::open(format!("irq:{}", irq)).expect("e1000d: failed to open IRQ file"); - event_queue.add(irq_file.as_raw_fd(), move |_count: usize| -> Result> { - let mut irq = [0; 8]; - irq_file.read(&mut irq)?; - if unsafe { device_irq.irq() } { - irq_file.write(&mut irq)?; - - let mut todo = todo_irq.borrow_mut(); - let mut i = 0; - while i < todo.len() { - let a = todo[i].a; - device_irq.handle(&mut todo[i]); - if todo[i].a == (-EWOULDBLOCK) as usize { - todo[i].a = a; - i += 1; - } else { - socket_irq.borrow_mut().write(&mut todo[i])?; - todo.remove(i); - } - } - - let next_read = device_irq.next_read(); - if next_read > 0 { - return Ok(Some(next_read)); - } - } - Ok(None) - }).expect("e1000d: failed to catch events on IRQ file"); - - let socket_packet = socket.clone(); - event_queue.add(socket_fd, move |_count: usize| -> Result> { - loop { - let mut packet = Packet::default(); - if socket_packet.borrow_mut().read(&mut packet)? == 0 { - break; - } - - let a = packet.a; - device.handle(&mut packet); - if packet.a == (-EWOULDBLOCK) as usize { - packet.a = a; - todo.borrow_mut().push(packet); - } else { - socket_packet.borrow_mut().write(&mut packet)?; - } - } - - let next_read = device.next_read(); - if next_read > 0 { - return Ok(Some(next_read)); - } - - Ok(None) - }).expect("e1000d: failed to catch events on IRQ file"); - - for event_count in event_queue.trigger_all(0).expect("e1000d: failed to trigger events") { - socket.borrow_mut().write(&Packet { - id: 0, - pid: 0, - uid: 0, - gid: 0, - a: syscall::number::SYS_FEVENT, - b: 0, - c: syscall::flag::EVENT_READ, - d: event_count - }).expect("e1000d: failed to write event"); - } - - loop { - let event_count = event_queue.run().expect("e1000d: failed to handle events"); - - socket.borrow_mut().write(&Packet { - id: 0, - pid: 0, - uid: 0, - gid: 0, - a: syscall::number::SYS_FEVENT, - b: 0, - c: syscall::flag::EVENT_READ, - d: event_count - }).expect("e1000d: failed to write event"); - } - } - unsafe { let _ = syscall::physunmap(address); } - } -} diff --git a/drivers/pcid/Cargo.toml b/drivers/pcid/Cargo.toml deleted file mode 100644 index f09b85a..0000000 --- a/drivers/pcid/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "pcid" -version = "0.1.0" - -[dependencies] -redox_syscall = { path = "../../syscall/" } -rustc-serialize = "0.3" -toml = "0.2" diff --git a/drivers/pcid/src/config.rs b/drivers/pcid/src/config.rs deleted file mode 100644 index 3bc4dba..0000000 --- a/drivers/pcid/src/config.rs +++ /dev/null @@ -1,14 +0,0 @@ -#[derive(Debug, Default, RustcDecodable)] -pub struct Config { - pub drivers: Vec -} - -#[derive(Debug, Default, RustcDecodable)] -pub struct DriverConfig { - pub name: Option, - pub class: Option, - pub subclass: Option, - pub vendor: Option, - pub device: Option, - pub command: Option> -} diff --git a/drivers/pcid/src/main.rs b/drivers/pcid/src/main.rs deleted file mode 100644 index 8202d6f..0000000 --- a/drivers/pcid/src/main.rs +++ /dev/null @@ -1,160 +0,0 @@ -#![feature(asm)] - -extern crate rustc_serialize; -extern crate syscall; -extern crate toml; - -use std::env; -use std::fs::File; -use std::io::Read; -use std::process::Command; -use syscall::iopl; - -use config::Config; -use pci::{Pci, PciBar, PciClass}; - -mod config; -mod pci; - -fn main() { - let mut config = Config::default(); - - let mut args = env::args().skip(1); - if let Some(config_path) = args.next() { - if let Ok(mut config_file) = File::open(&config_path) { - let mut config_data = String::new(); - if let Ok(_) = config_file.read_to_string(&mut config_data) { - config = toml::decode_str(&config_data).unwrap_or(Config::default()); - } - } - } - - unsafe { iopl(3).unwrap() }; - - print!("PCI BS/DV/FN VEND:DEVI CL.SC.IN.RV\n"); - - let pci = Pci::new(); - for bus in pci.buses() { - for dev in bus.devs() { - for func in dev.funcs() { - if let Some(header) = func.header() { - let pci_class = PciClass::from(header.class); - - let mut string = format!("PCI {:>02X}/{:>02X}/{:>02X} {:>04X}:{:>04X} {:>02X}.{:>02X}.{:>02X}.{:>02X} {:?}", - bus.num, dev.num, func.num, - header.vendor_id, header.device_id, - header.class, header.subclass, header.interface, header.revision, - pci_class); - - match pci_class { - PciClass::Storage => match header.subclass { - 0x01 => { - string.push_str(" IDE"); - }, - 0x06 => { - string.push_str(" SATA"); - }, - _ => () - }, - PciClass::SerialBus => match header.subclass { - 0x03 => match header.interface { - 0x00 => { - string.push_str(" UHCI"); - }, - 0x10 => { - string.push_str(" OHCI"); - }, - 0x20 => { - string.push_str(" EHCI"); - }, - 0x30 => { - string.push_str(" XHCI"); - }, - _ => () - }, - _ => () - }, - _ => () - } - - for i in 0..header.bars.len() { - match PciBar::from(header.bars[i]) { - PciBar::None => (), - PciBar::Memory(address) => string.push_str(&format!(" {}={:>08X}", i, address)), - PciBar::Port(address) => string.push_str(&format!(" {}={:>04X}", i, address)) - } - } - - string.push('\n'); - - print!("{}", string); - - for driver in config.drivers.iter() { - if let Some(class) = driver.class { - if class != header.class { continue; } - } - - if let Some(subclass) = driver.subclass { - if subclass != header.subclass { continue; } - } - - if let Some(vendor) = driver.vendor { - if vendor != header.vendor_id { continue; } - } - - if let Some(device) = driver.device { - if device != header.device_id { continue; } - } - - if let Some(ref args) = driver.command { - // Enable bus mastering - unsafe { - let cmd = pci.read(bus.num, dev.num, func.num, 0x04); - pci.write(bus.num, dev.num, func.num, 0x04, cmd | 4); - } - - let mut args = args.iter(); - if let Some(program) = args.next() { - let mut command = Command::new(program); - for arg in args { - let bar_arg = |i| -> String { - match PciBar::from(header.bars[i]) { - PciBar::None => String::new(), - PciBar::Memory(address) => format!("{:>08X}", address), - PciBar::Port(address) => format!("{:>04X}", address) - } - }; - let arg = match arg.as_str() { - "$BUS" => format!("{:>02X}", bus.num), - "$DEV" => format!("{:>02X}", dev.num), - "$FUNC" => format!("{:>02X}", func.num), - "$NAME" => format!("pci-{:>02X}.{:>02X}.{:>02X}", bus.num, dev.num, func.num), - "$BAR0" => bar_arg(0), - "$BAR1" => bar_arg(1), - "$BAR2" => bar_arg(2), - "$BAR3" => bar_arg(3), - "$BAR4" => bar_arg(4), - "$BAR5" => bar_arg(5), - "$IRQ" => format!("{}", header.interrupt_line), - _ => arg.clone() - }; - command.arg(&arg); - } - - println!("PCID SPAWN {:?}", command); - - match command.spawn() { - Ok(mut child) => match child.wait() { - Ok(_status) => (), //println!("pcid: waited for {}: {:?}", line, status.code()), - Err(err) => println!("pcid: failed to wait for {:?}: {}", command, err) - }, - Err(err) => println!("pcid: failed to execute {:?}: {}", command, err) - } - } - } - } - } - } - } - } -} diff --git a/drivers/pcid/src/pci/bar.rs b/drivers/pcid/src/pci/bar.rs deleted file mode 100644 index 190fa05..0000000 --- a/drivers/pcid/src/pci/bar.rs +++ /dev/null @@ -1,18 +0,0 @@ -#[derive(Debug)] -pub enum PciBar { - None, - Memory(u32), - Port(u16) -} - -impl From for PciBar { - fn from(bar: u32) -> Self { - if bar & 0xFFFFFFFC == 0 { - PciBar::None - } else if bar & 1 == 0 { - PciBar::Memory(bar & 0xFFFFFFF0) - } else { - PciBar::Port((bar & 0xFFFC) as u16) - } - } -} diff --git a/drivers/pcid/src/pci/bus.rs b/drivers/pcid/src/pci/bus.rs deleted file mode 100644 index 120fa45..0000000 --- a/drivers/pcid/src/pci/bus.rs +++ /dev/null @@ -1,46 +0,0 @@ -use super::{Pci, PciDev}; - -pub struct PciBus<'pci> { - pub pci: &'pci Pci, - pub num: u8 -} - -impl<'pci> PciBus<'pci> { - pub fn devs(&'pci self) -> PciBusIter<'pci> { - PciBusIter::new(self) - } - - pub unsafe fn read(&self, dev: u8, func: u8, offset: u8) -> u32 { - self.pci.read(self.num, dev, func, offset) - } -} - -pub struct PciBusIter<'pci> { - bus: &'pci PciBus<'pci>, - num: u32 -} - -impl<'pci> PciBusIter<'pci> { - pub fn new(bus: &'pci PciBus<'pci>) -> Self { - PciBusIter { - bus: bus, - num: 0 - } - } -} - -impl<'pci> Iterator for PciBusIter<'pci> { - type Item = PciDev<'pci>; - fn next(&mut self) -> Option { - if self.num < 32 { - let dev = PciDev { - bus: self.bus, - num: self.num as u8 - }; - self.num += 1; - Some(dev) - } else { - None - } - } -} diff --git a/drivers/pcid/src/pci/class.rs b/drivers/pcid/src/pci/class.rs deleted file mode 100644 index 21f7f69..0000000 --- a/drivers/pcid/src/pci/class.rs +++ /dev/null @@ -1,50 +0,0 @@ -#[derive(Debug)] -pub enum PciClass { - Legacy, - Storage, - Network, - Display, - Multimedia, - Memory, - Bridge, - SimpleComms, - Peripheral, - Input, - Docking, - Processor, - SerialBus, - Wireless, - IntelligentIo, - SatelliteComms, - Cryptography, - SignalProc, - Reserved(u8), - Unknown -} - -impl From for PciClass { - fn from(class: u8) -> PciClass { - match class { - 0x00 => PciClass::Legacy, - 0x01 => PciClass::Storage, - 0x02 => PciClass::Network, - 0x03 => PciClass::Display, - 0x04 => PciClass::Multimedia, - 0x05 => PciClass::Memory, - 0x06 => PciClass::Bridge, - 0x07 => PciClass::SimpleComms, - 0x08 => PciClass::Peripheral, - 0x09 => PciClass::Input, - 0x0A => PciClass::Docking, - 0x0B => PciClass::Processor, - 0x0C => PciClass::SerialBus, - 0x0D => PciClass::Wireless, - 0x0E => PciClass::IntelligentIo, - 0x0F => PciClass::SatelliteComms, - 0x10 => PciClass::Cryptography, - 0x11 => PciClass::SignalProc, - 0xFF => PciClass::Unknown, - reserved => PciClass::Reserved(reserved) - } - } -} diff --git a/drivers/pcid/src/pci/dev.rs b/drivers/pcid/src/pci/dev.rs deleted file mode 100644 index 0508888..0000000 --- a/drivers/pcid/src/pci/dev.rs +++ /dev/null @@ -1,46 +0,0 @@ -use super::{PciBus, PciFunc}; - -pub struct PciDev<'pci> { - pub bus: &'pci PciBus<'pci>, - pub num: u8 -} - -impl<'pci> PciDev<'pci> { - pub fn funcs(&'pci self) -> PciDevIter<'pci> { - PciDevIter::new(self) - } - - pub unsafe fn read(&self, func: u8, offset: u8) -> u32 { - self.bus.read(self.num, func, offset) - } -} - -pub struct PciDevIter<'pci> { - dev: &'pci PciDev<'pci>, - num: u32 -} - -impl<'pci> PciDevIter<'pci> { - pub fn new(dev: &'pci PciDev<'pci>) -> Self { - PciDevIter { - dev: dev, - num: 0 - } - } -} - -impl<'pci> Iterator for PciDevIter<'pci> { - type Item = PciFunc<'pci>; - fn next(&mut self) -> Option { - if self.num < 8 { - let func = PciFunc { - dev: self.dev, - num: self.num as u8 - }; - self.num += 1; - Some(func) - } else { - None - } - } -} diff --git a/drivers/pcid/src/pci/func.rs b/drivers/pcid/src/pci/func.rs deleted file mode 100644 index 578e5c6..0000000 --- a/drivers/pcid/src/pci/func.rs +++ /dev/null @@ -1,30 +0,0 @@ -use std::ops::DerefMut; - -use super::{PciDev, PciHeader}; - -pub struct PciFunc<'pci> { - pub dev: &'pci PciDev<'pci>, - pub num: u8 -} - -impl<'pci> PciFunc<'pci> { - pub fn header(&self) -> Option { - if unsafe { self.read(0) } != 0xFFFFFFFF { - let mut header = PciHeader::default(); - { - let dwords = header.deref_mut(); - dwords.iter_mut().fold(0usize, |offset, dword| { - *dword = unsafe { self.read(offset as u8) }; - offset + 4 - }); - } - Some(header) - } else { - None - } - } - - pub unsafe fn read(&self, offset: u8) -> u32 { - self.dev.read(self.num, offset) - } -} diff --git a/drivers/pcid/src/pci/header.rs b/drivers/pcid/src/pci/header.rs deleted file mode 100644 index 2cc335e..0000000 --- a/drivers/pcid/src/pci/header.rs +++ /dev/null @@ -1,43 +0,0 @@ -use std::ops::{Deref, DerefMut}; -use std::{slice, mem}; - -#[derive(Debug, Default)] -#[repr(packed)] -pub struct PciHeader { - pub vendor_id: u16, - pub device_id: u16, - pub command: u16, - pub status: u16, - pub revision: u8, - pub interface: u8, - pub subclass: u8, - pub class: u8, - pub cache_line_size: u8, - pub latency_timer: u8, - pub header_type: u8, - pub bist: u8, - pub bars: [u32; 6], - pub cardbus_cis_ptr: u32, - pub subsystem_vendor_id: u16, - pub subsystem_id: u16, - pub expansion_rom_bar: u32, - pub capabilities: u8, - pub reserved: [u8; 7], - pub interrupt_line: u8, - pub interrupt_pin: u8, - pub min_grant: u8, - pub max_latency: u8 -} - -impl Deref for PciHeader { - type Target = [u32]; - fn deref(&self) -> &[u32] { - unsafe { slice::from_raw_parts(self as *const PciHeader as *const u32, mem::size_of::()/4) as &[u32] } - } -} - -impl DerefMut for PciHeader { - fn deref_mut(&mut self) -> &mut [u32] { - unsafe { slice::from_raw_parts_mut(self as *mut PciHeader as *mut u32, mem::size_of::()/4) as &mut [u32] } - } -} diff --git a/drivers/pcid/src/pci/mod.rs b/drivers/pcid/src/pci/mod.rs deleted file mode 100644 index d2a8e89..0000000 --- a/drivers/pcid/src/pci/mod.rs +++ /dev/null @@ -1,78 +0,0 @@ -pub use self::bar::PciBar; -pub use self::bus::{PciBus, PciBusIter}; -pub use self::class::PciClass; -pub use self::dev::{PciDev, PciDevIter}; -pub use self::func::PciFunc; -pub use self::header::PciHeader; - -mod bar; -mod bus; -mod class; -mod dev; -mod func; -mod header; - -pub struct Pci; - -impl Pci { - pub fn new() -> Self { - Pci - } - - pub fn buses<'pci>(&'pci self) -> PciIter<'pci> { - PciIter::new(self) - } - - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - pub unsafe fn read(&self, bus: u8, dev: u8, func: u8, offset: u8) -> u32 { - let address = 0x80000000 | ((bus as u32) << 16) | ((dev as u32) << 11) | ((func as u32) << 8) | ((offset as u32) & 0xFC); - let value: u32; - asm!("mov dx, 0xCF8 - out dx, eax - mov dx, 0xCFC - in eax, dx" - : "={eax}"(value) : "{eax}"(address) : "dx" : "intel", "volatile"); - value - } - - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - pub unsafe fn write(&self, bus: u8, dev: u8, func: u8, offset: u8, value: u32) { - let address = 0x80000000 | ((bus as u32) << 16) | ((dev as u32) << 11) | ((func as u32) << 8) | ((offset as u32) & 0xFC); - asm!("mov dx, 0xCF8 - out dx, eax" - : : "{eax}"(address) : "dx" : "intel", "volatile"); - asm!("mov dx, 0xCFC - out dx, eax" - : : "{eax}"(value) : "dx" : "intel", "volatile"); - } -} - -pub struct PciIter<'pci> { - pci: &'pci Pci, - num: u32 -} - -impl<'pci> PciIter<'pci> { - pub fn new(pci: &'pci Pci) -> Self { - PciIter { - pci: pci, - num: 0 - } - } -} - -impl<'pci> Iterator for PciIter<'pci> { - type Item = PciBus<'pci>; - fn next(&mut self) -> Option { - if self.num < 256 { - let bus = PciBus { - pci: self.pci, - num: self.num as u8 - }; - self.num += 1; - Some(bus) - } else { - None - } - } -} diff --git a/drivers/ps2d/Cargo.toml b/drivers/ps2d/Cargo.toml deleted file mode 100644 index 22863b9..0000000 --- a/drivers/ps2d/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "ps2d" -version = "0.1.0" - -[dependencies] -bitflags = "*" -event = { path = "../../crates/event/" } -io = { path = "../../crates/io/" } -orbclient = "0.2" -redox_syscall = { path = "../../syscall/" } diff --git a/drivers/ps2d/src/controller.rs b/drivers/ps2d/src/controller.rs deleted file mode 100644 index e68d4f1..0000000 --- a/drivers/ps2d/src/controller.rs +++ /dev/null @@ -1,233 +0,0 @@ -use io::{Io, Pio, ReadOnly, WriteOnly}; - -bitflags! { - flags StatusFlags: u8 { - const OUTPUT_FULL = 1, - const INPUT_FULL = 1 << 1, - const SYSTEM = 1 << 2, - const COMMAND = 1 << 3, - // Chipset specific - const KEYBOARD_LOCK = 1 << 4, - // Chipset specific - const SECOND_OUTPUT_FULL = 1 << 5, - const TIME_OUT = 1 << 6, - const PARITY = 1 << 7 - } -} - -bitflags! { - flags ConfigFlags: u8 { - const FIRST_INTERRUPT = 1, - const SECOND_INTERRUPT = 1 << 1, - const POST_PASSED = 1 << 2, - // 1 << 3 should be zero - const CONFIG_RESERVED_3 = 1 << 3, - const FIRST_DISABLED = 1 << 4, - const SECOND_DISABLED = 1 << 5, - const FIRST_TRANSLATE = 1 << 6, - // 1 << 7 should be zero - const CONFIG_RESERVED_7 = 1 << 7, - } -} - -#[repr(u8)] -#[allow(dead_code)] -enum Command { - ReadConfig = 0x20, - WriteConfig = 0x60, - DisableSecond = 0xA7, - EnableSecond = 0xA8, - TestSecond = 0xA9, - TestController = 0xAA, - TestFirst = 0xAB, - Diagnostic = 0xAC, - DisableFirst = 0xAD, - EnableFirst = 0xAE, - WriteSecond = 0xD4 -} - -#[repr(u8)] -#[allow(dead_code)] -enum KeyboardCommand { - EnableReporting = 0xF4, - SetDefaults = 0xF6, - Reset = 0xFF -} - -#[repr(u8)] -enum KeyboardCommandData { - ScancodeSet = 0xF0 -} - -#[repr(u8)] -#[allow(dead_code)] -enum MouseCommand { - GetDeviceId = 0xF2, - EnableReporting = 0xF4, - SetDefaults = 0xF6, - Reset = 0xFF -} - -#[repr(u8)] -enum MouseCommandData { - SetSampleRate = 0xF3, -} - -pub struct Ps2 { - data: Pio, - status: ReadOnly>, - command: WriteOnly> -} - -impl Ps2 { - pub fn new() -> Self { - Ps2 { - data: Pio::new(0x60), - status: ReadOnly::new(Pio::new(0x64)), - command: WriteOnly::new(Pio::new(0x64)), - } - } - - fn status(&mut self) -> StatusFlags { - StatusFlags::from_bits_truncate(self.status.read()) - } - - fn wait_write(&mut self) { - while self.status().contains(INPUT_FULL) {} - } - - fn wait_read(&mut self) { - while ! self.status().contains(OUTPUT_FULL) {} - } - - fn flush_read(&mut self) { - while self.status().contains(OUTPUT_FULL) { - print!("FLUSH: {:X}\n", self.data.read()); - } - } - - fn command(&mut self, command: Command) { - self.wait_write(); - self.command.write(command as u8); - } - - fn read(&mut self) -> u8 { - self.wait_read(); - self.data.read() - } - - fn write(&mut self, data: u8) { - self.wait_write(); - self.data.write(data); - } - - fn config(&mut self) -> ConfigFlags { - self.command(Command::ReadConfig); - ConfigFlags::from_bits_truncate(self.read()) - } - - fn set_config(&mut self, config: ConfigFlags) { - self.command(Command::WriteConfig); - self.write(config.bits()); - } - - fn keyboard_command(&mut self, command: KeyboardCommand) -> u8 { - self.write(command as u8); - self.read() - } - - fn keyboard_command_data(&mut self, command: KeyboardCommandData, data: u8) -> u8 { - self.write(command as u8); - assert_eq!(self.read(), 0xFA); - self.write(data as u8); - self.read() - } - - fn mouse_command(&mut self, command: MouseCommand) -> u8 { - self.command(Command::WriteSecond); - self.write(command as u8); - self.read() - } - - fn mouse_command_data(&mut self, command: MouseCommandData, data: u8) -> u8 { - self.command(Command::WriteSecond); - self.write(command as u8); - assert_eq!(self.read(), 0xFA); - self.command(Command::WriteSecond); - self.write(data as u8); - self.read() - } - - pub fn init(&mut self) -> bool { - // Disable devices - self.command(Command::DisableFirst); - self.command(Command::DisableSecond); - - // Clear remaining data - self.flush_read(); - - // Disable clocks, disable interrupts, and disable translate - { - let mut config = self.config(); - config.insert(FIRST_DISABLED); - config.insert(SECOND_DISABLED); - config.remove(FIRST_TRANSLATE); - config.remove(FIRST_INTERRUPT); - config.remove(SECOND_INTERRUPT); - self.set_config(config); - } - - // Perform the self test - self.command(Command::TestController); - assert_eq!(self.read(), 0x55); - - // Enable devices - self.command(Command::EnableFirst); - self.command(Command::EnableSecond); - - // Reset keyboard - assert_eq!(self.keyboard_command(KeyboardCommand::Reset), 0xFA); - assert_eq!(self.read(), 0xAA); - self.flush_read(); - - // Set scancode set to 2 - assert_eq!(self.keyboard_command_data(KeyboardCommandData::ScancodeSet, 2), 0xFA); - - // Reset mouse and set up scroll - // TODO: Check for ack - assert_eq!(self.mouse_command(MouseCommand::Reset), 0xFA); - assert_eq!(self.read(), 0xAA); - assert_eq!(self.read(), 0x00); - self.flush_read(); - - // Enable extra packet on mouse - assert_eq!(self.mouse_command_data(MouseCommandData::SetSampleRate, 200), 0xFA); - assert_eq!(self.mouse_command_data(MouseCommandData::SetSampleRate, 100), 0xFA); - assert_eq!(self.mouse_command_data(MouseCommandData::SetSampleRate, 80), 0xFA); - assert_eq!(self.mouse_command(MouseCommand::GetDeviceId), 0xFA); - let mouse_id = self.read(); - let mouse_extra = mouse_id == 3; - - // Set sample rate to maximum - assert_eq!(self.mouse_command_data(MouseCommandData::SetSampleRate, 200), 0xFA); - - // Enable data reporting - assert_eq!(self.keyboard_command(KeyboardCommand::EnableReporting), 0xFA); - assert_eq!(self.mouse_command(MouseCommand::EnableReporting), 0xFA); - - // Enable clocks and interrupts - { - let mut config = self.config(); - config.remove(FIRST_DISABLED); - config.remove(SECOND_DISABLED); - config.insert(FIRST_TRANSLATE); - config.insert(FIRST_INTERRUPT); - config.insert(SECOND_INTERRUPT); - self.set_config(config); - } - - self.flush_read(); - - mouse_extra - } -} diff --git a/drivers/ps2d/src/keymap.rs b/drivers/ps2d/src/keymap.rs deleted file mode 100644 index 5697e52..0000000 --- a/drivers/ps2d/src/keymap.rs +++ /dev/null @@ -1,148 +0,0 @@ -pub mod english { - static ENGLISH: [[char; 2]; 58] = [ - ['\0', '\0'], - ['\x1B', '\x1B'], - ['1', '!'], - ['2', '@'], - ['3', '#'], - ['4', '$'], - ['5', '%'], - ['6', '^'], - ['7', '&'], - ['8', '*'], - ['9', '('], - ['0', ')'], - ['-', '_'], - ['=', '+'], - ['\x7F', '\x7F'], - ['\t', '\t'], - ['q', 'Q'], - ['w', 'W'], - ['e', 'E'], - ['r', 'R'], - ['t', 'T'], - ['y', 'Y'], - ['u', 'U'], - ['i', 'I'], - ['o', 'O'], - ['p', 'P'], - ['[', '{'], - [']', '}'], - ['\n', '\n'], - ['\0', '\0'], - ['a', 'A'], - ['s', 'S'], - ['d', 'D'], - ['f', 'F'], - ['g', 'G'], - ['h', 'H'], - ['j', 'J'], - ['k', 'K'], - ['l', 'L'], - [';', ':'], - ['\'', '"'], - ['`', '~'], - ['\0', '\0'], - ['\\', '|'], - ['z', 'Z'], - ['x', 'X'], - ['c', 'C'], - ['v', 'V'], - ['b', 'B'], - ['n', 'N'], - ['m', 'M'], - [',', '<'], - ['.', '>'], - ['/', '?'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - [' ', ' '] - ]; - - pub fn get_char(scancode: u8, shift: bool) -> char { - if let Some(c) = ENGLISH.get(scancode as usize) { - if shift { - c[1] - } else { - c[0] - } - } else { - '\0' - } - } -} -pub mod dvorak { - static DVORAK: [[char; 2]; 58] = [ - ['\0', '\0'], - ['\x1B', '\x1B'], - ['1', '!'], - ['2', '@'], - ['3', '#'], - ['4', '$'], - ['5', '%'], - ['6', '^'], - ['7', '&'], - ['8', '*'], - ['9', '('], - ['0', ')'], - ['[', '{'], - [']', '}'], - ['\x7F', '\x7F'], - ['\t', '\t'], - ['\'', '"'], - [',', '<'], - ['.', '>'], - ['p', 'P'], - ['y', 'Y'], - ['f', 'F'], - ['g', 'G'], - ['c', 'C'], - ['r', 'R'], - ['l', 'L'], - ['/', '?'], - ['=', '+'], - ['\n', '\n'], - ['\0', '\0'], - ['a', 'A'], - ['o', 'O'], - ['e', 'E'], - ['u', 'U'], - ['i', 'I'], - ['d', 'D'], - ['h', 'H'], - ['t', 'T'], - ['n', 'N'], - ['s', 'S'], - ['-', '_'], - ['`', '~'], - ['\0', '\0'], - ['\\', '|'], - [';', ':'], - ['q', 'Q'], - ['j', 'J'], - ['k', 'K'], - ['x', 'X'], - ['b', 'B'], - ['m', 'M'], - ['w', 'W'], - ['v', 'V'], - ['z', 'Z'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - [' ', ' '] - ]; - - pub fn get_char(scancode: u8, shift: bool) -> char { - if let Some(c) = DVORAK.get(scancode as usize) { - if shift { - c[1] - } else { - c[0] - } - } else { - '\0' - } - } -} diff --git a/drivers/ps2d/src/main.rs b/drivers/ps2d/src/main.rs deleted file mode 100644 index 7c67bd3..0000000 --- a/drivers/ps2d/src/main.rs +++ /dev/null @@ -1,193 +0,0 @@ -#![feature(asm)] - -#[macro_use] -extern crate bitflags; -extern crate event; -extern crate io; -extern crate orbclient; -extern crate syscall; - -use std::env; -use std::fs::File; -use std::io::{Read, Write, Result}; -use std::os::unix::io::AsRawFd; -use std::mem; - -use event::EventQueue; -use orbclient::{KeyEvent, MouseEvent}; -use syscall::iopl; - -mod controller; -mod keymap; - -bitflags! { - flags MousePacketFlags: u8 { - const LEFT_BUTTON = 1, - const RIGHT_BUTTON = 1 << 1, - const MIDDLE_BUTTON = 1 << 2, - const ALWAYS_ON = 1 << 3, - const X_SIGN = 1 << 4, - const Y_SIGN = 1 << 5, - const X_OVERFLOW = 1 << 6, - const Y_OVERFLOW = 1 << 7 - } -} - -struct Ps2d<'a> { - input: File, - lshift: bool, - rshift: bool, - packets: [u8; 4], - packet_i: usize, - extra_packet: bool, - //Keymap function - get_char: &'a Fn(u8,bool) -> char -} - -impl<'a> Ps2d<'a> { - fn new(input: File, extra_packet: bool, keymap: &'a Fn(u8,bool) -> char) -> Self { - Ps2d { - input: input, - lshift: false, - rshift: false, - packets: [0; 4], - packet_i: 0, - extra_packet: extra_packet, - get_char: keymap - } - } - - fn handle(&mut self, keyboard: bool, data: u8) { - if keyboard { - let (scancode, pressed) = if data >= 0x80 { - (data - 0x80, false) - } else { - (data, true) - }; - - if scancode == 0x2A { - self.lshift = pressed; - } else if scancode == 0x36 { - self.rshift = pressed; - } - - self.input.write(&KeyEvent { - character: (self.get_char)(scancode, self.lshift || self.rshift), - scancode: scancode, - pressed: pressed - }.to_event()).expect("ps2d: failed to write key event"); - } else { - self.packets[self.packet_i] = data; - self.packet_i += 1; - - let flags = MousePacketFlags::from_bits_truncate(self.packets[0]); - if ! flags.contains(ALWAYS_ON) { - println!("MOUSE MISALIGN {:X}", self.packets[0]); - - self.packets = [0; 4]; - self.packet_i = 0; - } else if self.packet_i >= self.packets.len() || (!self.extra_packet && self.packet_i >= 3) { - if ! flags.contains(X_OVERFLOW) && ! flags.contains(Y_OVERFLOW) { - let mut dx = self.packets[1] as i32; - if flags.contains(X_SIGN) { - dx -= 0x100; - } - - let mut dy = -(self.packets[2] as i32); - if flags.contains(Y_SIGN) { - dy += 0x100; - } - - let _extra = if self.extra_packet { - self.packets[3] - } else { - 0 - }; - - self.input.write(&MouseEvent { - x: dx, - y: dy, - left_button: flags.contains(LEFT_BUTTON), - middle_button: flags.contains(MIDDLE_BUTTON), - right_button: flags.contains(RIGHT_BUTTON) - }.to_event()).expect("ps2d: failed to write mouse event"); - } else { - println!("ps2d: overflow {:X} {:X} {:X} {:X}", self.packets[0], self.packets[1], self.packets[2], self.packets[3]); - } - - self.packets = [0; 4]; - self.packet_i = 0; - } - } - } -} - -fn main() { - // Daemonize - if unsafe { syscall::clone(0).unwrap() } == 0 { - unsafe { - iopl(3).expect("ps2d: failed to get I/O permission"); - asm!("cli" : : : : "intel", "volatile"); - } - - let input = File::open("display:input").expect("ps2d: failed to open display:input"); - - let extra_packet = controller::Ps2::new().init(); - let keymap = match env::args().skip(1).next() { - Some(k) => match k.to_lowercase().as_ref() { - "dvorak" => (keymap::dvorak::get_char), - "english" => (keymap::english::get_char), - &_ => (keymap::english::get_char) - }, - None => (keymap::english::get_char) - }; - let mut ps2d = Ps2d::new(input, extra_packet,&keymap); - - let mut event_queue = EventQueue::<(bool, u8)>::new().expect("ps2d: failed to create event queue"); - - let mut key_irq = File::open("irq:1").expect("ps2d: failed to open irq:1"); - - event_queue.add(key_irq.as_raw_fd(), move |_count: usize| -> Result> { - let mut irq = [0; 8]; - if key_irq.read(&mut irq)? >= mem::size_of::() { - let data: u8; - unsafe { - asm!("in al, dx" : "={al}"(data) : "{dx}"(0x60) : : "intel", "volatile"); - } - - key_irq.write(&irq)?; - - Ok(Some((true, data))) - } else { - Ok(None) - } - }).expect("ps2d: failed to poll irq:1"); - - let mut mouse_irq = File::open("irq:12").expect("ps2d: failed to open irq:12"); - - event_queue.add(mouse_irq.as_raw_fd(), move |_count: usize| -> Result> { - let mut irq = [0; 8]; - if mouse_irq.read(&mut irq)? >= mem::size_of::() { - let data: u8; - unsafe { - asm!("in al, dx" : "={al}"(data) : "{dx}"(0x60) : : "intel", "volatile"); - } - - mouse_irq.write(&irq)?; - - Ok(Some((false, data))) - } else { - Ok(None) - } - }).expect("ps2d: failed to poll irq:12"); - - for (keyboard, data) in event_queue.trigger_all(0).expect("ps2d: failed to trigger events") { - ps2d.handle(keyboard, data); - } - - loop { - let (keyboard, data) = event_queue.run().expect("ps2d: failed to handle events"); - ps2d.handle(keyboard, data); - } - } -} diff --git a/drivers/rtl8168d/Cargo.toml b/drivers/rtl8168d/Cargo.toml deleted file mode 100644 index e72a130..0000000 --- a/drivers/rtl8168d/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "rtl8168d" -version = "0.1.0" - -[dependencies] -bitflags = "*" -dma = { path = "../../crates/dma/" } -event = { path = "../../crates/event/" } -io = { path = "../../crates/io/" } -netutils = { path = "../../programs/netutils/" } -redox_syscall = { path = "../../syscall/" } diff --git a/drivers/rtl8168d/src/device.rs b/drivers/rtl8168d/src/device.rs deleted file mode 100644 index 7ed7d59..0000000 --- a/drivers/rtl8168d/src/device.rs +++ /dev/null @@ -1,300 +0,0 @@ -use std::mem; - -use dma::Dma; -use io::{Mmio, Io, ReadOnly}; -use netutils::setcfg; -use syscall::error::{Error, EACCES, EWOULDBLOCK, Result}; -use syscall::flag::O_NONBLOCK; -use syscall::scheme::SchemeMut; - -#[repr(packed)] -struct Regs { - mac: [Mmio; 2], - _mar: [Mmio; 2], - _dtccr: [Mmio; 2], - _rsv0: [Mmio; 2], - tnpds: [Mmio; 2], - thpds: [Mmio; 2], - _rsv1: [Mmio; 7], - cmd: Mmio, - tppoll: Mmio, - _rsv2: [Mmio; 3], - imr: Mmio, - isr: Mmio, - tcr: Mmio, - rcr: Mmio, - _tctr: Mmio, - _rsv3: Mmio, - cmd_9346: Mmio, - _config: [Mmio; 6], - _rsv4: Mmio, - timer_int: Mmio, - _rsv5: Mmio, - _phys_ar: Mmio, - _rsv6: [Mmio; 2], - phys_sts: ReadOnly>, - _rsv7: [Mmio; 23], - _wakeup: [Mmio; 16], - _crc: [Mmio; 5], - _rsv8: [Mmio; 12], - rms: Mmio, - _rsv9: Mmio, - _c_plus_cr: Mmio, - _rsv10: Mmio, - rdsar: [Mmio; 2], - mtps: Mmio, - _rsv11: [Mmio; 19], -} - -const OWN: u32 = 1 << 31; -const EOR: u32 = 1 << 30; -const FS: u32 = 1 << 29; -const LS: u32 = 1 << 28; - -#[repr(packed)] -struct Rd { - ctrl: Mmio, - _vlan: Mmio, - buffer: Mmio -} - -#[repr(packed)] -struct Td { - ctrl: Mmio, - _vlan: Mmio, - buffer: Mmio -} - -pub struct Rtl8168 { - regs: &'static mut Regs, - receive_buffer: [Dma<[Mmio; 0x1FF8]>; 16], - receive_ring: Dma<[Rd; 16]>, - transmit_buffer: [Dma<[Mmio; 7552]>; 16], - transmit_ring: Dma<[Td; 16]>, - transmit_buffer_h: [Dma<[Mmio; 7552]>; 1], - transmit_ring_h: Dma<[Td; 1]> -} - -impl SchemeMut for Rtl8168 { - fn open(&mut self, _path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result { - if uid == 0 { - Ok(flags) - } else { - Err(Error::new(EACCES)) - } - } - - fn dup(&mut self, id: usize, _buf: &[u8]) -> Result { - Ok(id) - } - - fn read(&mut self, id: usize, buf: &mut [u8]) -> Result { - for (rd_i, rd) in self.receive_ring.iter_mut().enumerate() { - if ! rd.ctrl.readf(OWN) { - let rd_len = rd.ctrl.read() & 0x3FFF; - - let data = &self.receive_buffer[rd_i as usize]; - - let mut i = 0; - while i < buf.len() && i < rd_len as usize { - buf[i] = data[i].read(); - i += 1; - } - - let eor = rd.ctrl.read() & EOR; - rd.ctrl.write(OWN | eor | data.len() as u32); - - return Ok(i); - } - } - - if id & O_NONBLOCK == O_NONBLOCK { - Ok(0) - } else { - Err(Error::new(EWOULDBLOCK)) - } - } - - fn write(&mut self, _id: usize, buf: &[u8]) -> Result { - loop { - for (td_i, td) in self.transmit_ring.iter_mut().enumerate() { - if ! td.ctrl.readf(OWN) { - - let mut data = &mut self.transmit_buffer[td_i as usize]; - - let mut i = 0; - while i < buf.len() && i < data.len() { - data[i].write(buf[i]); - i += 1; - } - - let eor = td.ctrl.read() & EOR; - td.ctrl.write(OWN | eor | FS | LS | i as u32); - - self.regs.tppoll.writef(1 << 6, true); //Notify of normal priority packet - - while self.regs.tppoll.readf(1 << 6) { - unsafe { asm!("pause" : : : "memory" : "intel", "volatile"); } - } - - return Ok(i); - } - } - - unsafe { asm!("pause" : : : "memory" : "intel", "volatile"); } - } - } - - fn fevent(&mut self, _id: usize, _flags: usize) -> Result { - Ok(0) - } - - fn fsync(&mut self, _id: usize) -> Result { - Ok(0) - } - - fn close(&mut self, _id: usize) -> Result { - Ok(0) - } -} - -impl Rtl8168 { - pub unsafe fn new(base: usize) -> Result { - assert_eq!(mem::size_of::(), 256); - - let regs = &mut *(base as *mut Regs); - assert_eq!(®s.tnpds as *const _ as usize - base, 0x20); - assert_eq!(®s.cmd as *const _ as usize - base, 0x37); - assert_eq!(®s.tcr as *const _ as usize - base, 0x40); - assert_eq!(®s.rcr as *const _ as usize - base, 0x44); - assert_eq!(®s.cmd_9346 as *const _ as usize - base, 0x50); - assert_eq!(®s.phys_sts as *const _ as usize - base, 0x6C); - assert_eq!(®s.rms as *const _ as usize - base, 0xDA); - assert_eq!(®s.rdsar as *const _ as usize - base, 0xE4); - assert_eq!(®s.mtps as *const _ as usize - base, 0xEC); - - let mut module = Rtl8168 { - regs: regs, - receive_buffer: [Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, - Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, - Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, - Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?], - receive_ring: Dma::zeroed()?, - transmit_buffer: [Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, - Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, - Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, - Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?, Dma::zeroed()?], - transmit_ring: Dma::zeroed()?, - transmit_buffer_h: [Dma::zeroed()?], - transmit_ring_h: Dma::zeroed()? - }; - - module.init(); - - Ok(module) - } - - pub unsafe fn irq(&mut self) -> u16 { - // Read and then clear the ISR - let isr = self.regs.isr.read(); - self.regs.isr.write(isr); - let imr = self.regs.imr.read(); - isr & imr - } - - pub fn next_read(&self) -> usize { - for rd in self.receive_ring.iter() { - if ! rd.ctrl.readf(OWN) { - return rd.ctrl.read() as usize & 0x3FFF; - } - } - 0 - } - - pub unsafe fn init(&mut self) { - let mac_low = self.regs.mac[0].read(); - let mac_high = self.regs.mac[1].read(); - let mac = [mac_low as u8, - (mac_low >> 8) as u8, - (mac_low >> 16) as u8, - (mac_low >> 24) as u8, - mac_high as u8, - (mac_high >> 8) as u8]; - print!("{}", format!(" - MAC: {:>02X}:{:>02X}:{:>02X}:{:>02X}:{:>02X}:{:>02X}\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])); - let _ = setcfg("mac", &format!("{:>02X}.{:>02X}.{:>02X}.{:>02X}.{:>02X}.{:>02X}", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])); - - // Reset - this will disable tx and rx, reinitialize FIFOs, and set the system buffer pointer to the initial value - self.regs.cmd.writef(1 << 4, true); - while self.regs.cmd.readf(1 << 4) {} - - // Set up rx buffers - for i in 0..self.receive_ring.len() { - let rd = &mut self.receive_ring[i]; - let data = &mut self.receive_buffer[i]; - rd.buffer.write(data.physical() as u64); - rd.ctrl.write(OWN | data.len() as u32); - } - if let Some(mut rd) = self.receive_ring.last_mut() { - rd.ctrl.writef(EOR, true); - } - - // Set up normal priority tx buffers - for i in 0..self.transmit_ring.len() { - self.transmit_ring[i].buffer.write(self.transmit_buffer[i].physical() as u64); - } - if let Some(mut td) = self.transmit_ring.last_mut() { - td.ctrl.writef(EOR, true); - } - - // Set up high priority tx buffers - for i in 0..self.transmit_ring_h.len() { - self.transmit_ring_h[i].buffer.write(self.transmit_buffer_h[i].physical() as u64); - } - if let Some(mut td) = self.transmit_ring_h.last_mut() { - td.ctrl.writef(EOR, true); - } - - // Unlock config - self.regs.cmd_9346.write(1 << 7 | 1 << 6); - - // Enable rx (bit 3) and tx (bit 2) - self.regs.cmd.writef(1 << 3 | 1 << 2, true); - - // Max RX packet size - self.regs.rms.write(0x1FF8); - - // Max TX packet size - self.regs.mtps.write(0x3B); - - // Set tx low priority buffer address - self.regs.tnpds[0].write(self.transmit_ring.physical() as u32); - self.regs.tnpds[1].write((self.transmit_ring.physical() >> 32) as u32); - - // Set tx high priority buffer address - self.regs.thpds[0].write(self.transmit_ring_h.physical() as u32); - self.regs.thpds[1].write((self.transmit_ring_h.physical() >> 32) as u32); - - // Set rx buffer address - self.regs.rdsar[0].write(self.receive_ring.physical() as u32); - self.regs.rdsar[1].write((self.receive_ring.physical() >> 32) as u32); - - // Disable timer interrupt - self.regs.timer_int.write(0); - - //Clear ISR - let isr = self.regs.isr.read(); - self.regs.isr.write(isr); - - // Interrupt on tx error (bit 3), tx ok (bit 2), rx error(bit 1), and rx ok (bit 0) - self.regs.imr.write(1 << 15 | 1 << 14 | 1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2 | 1 << 1 | 1); - - // Set TX config - self.regs.tcr.write(0b11 << 24 | 0b111 << 8); - - // Set RX config - Accept broadcast (bit 3), multicast (bit 2), and unicast (bit 1) - self.regs.rcr.write(0xE70E); - - // Lock config - self.regs.cmd_9346.write(0); - } -} diff --git a/drivers/rtl8168d/src/main.rs b/drivers/rtl8168d/src/main.rs deleted file mode 100644 index 46a1b86..0000000 --- a/drivers/rtl8168d/src/main.rs +++ /dev/null @@ -1,141 +0,0 @@ -#![feature(asm)] - -extern crate dma; -extern crate event; -extern crate io; -extern crate netutils; -extern crate syscall; - -use std::cell::RefCell; -use std::env; -use std::fs::File; -use std::io::{Read, Write, Result}; -use std::os::unix::io::{AsRawFd, FromRawFd}; -use std::sync::Arc; - -use event::EventQueue; -use syscall::{Packet, SchemeMut, MAP_WRITE}; -use syscall::error::EWOULDBLOCK; - -pub mod device; - -fn main() { - let mut args = env::args().skip(1); - - let mut name = args.next().expect("rtl8168d: no name provided"); - name.push_str("_rtl8168"); - - let bar_str = args.next().expect("rtl8168d: no address provided"); - let bar = usize::from_str_radix(&bar_str, 16).expect("rtl8168d: failed to parse address"); - - let irq_str = args.next().expect("rtl8168d: no irq provided"); - let irq = irq_str.parse::().expect("rtl8168d: failed to parse irq"); - - print!("{}", format!(" + RTL8168 {} on: {:X}, IRQ: {}\n", name, bar, irq)); - - // Daemonize - if unsafe { syscall::clone(0).unwrap() } == 0 { - let socket_fd = syscall::open(":network", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK).expect("rtl8168d: failed to create network scheme"); - let socket = Arc::new(RefCell::new(unsafe { File::from_raw_fd(socket_fd) })); - - let mut irq_file = File::open(format!("irq:{}", irq)).expect("rtl8168d: failed to open IRQ file"); - - let address = unsafe { syscall::physmap(bar, 256, MAP_WRITE).expect("rtl8168d: failed to map address") }; - { - let device = Arc::new(RefCell::new(unsafe { device::Rtl8168::new(address).expect("rtl8168d: failed to allocate device") })); - - let mut event_queue = EventQueue::::new().expect("rtl8168d: failed to create event queue"); - - let todo = Arc::new(RefCell::new(Vec::::new())); - - let device_irq = device.clone(); - let socket_irq = socket.clone(); - let todo_irq = todo.clone(); - event_queue.add(irq_file.as_raw_fd(), move |_count: usize| -> Result> { - let mut irq = [0; 8]; - irq_file.read(&mut irq)?; - - let isr = unsafe { device_irq.borrow_mut().irq() }; - if isr != 0 { - irq_file.write(&mut irq)?; - - let mut todo = todo_irq.borrow_mut(); - let mut i = 0; - while i < todo.len() { - let a = todo[i].a; - device_irq.borrow_mut().handle(&mut todo[i]); - if todo[i].a == (-EWOULDBLOCK) as usize { - todo[i].a = a; - i += 1; - } else { - socket_irq.borrow_mut().write(&mut todo[i])?; - todo.remove(i); - } - } - - let next_read = device_irq.borrow().next_read(); - if next_read > 0 { - return Ok(Some(next_read)); - } - } - Ok(None) - }).expect("rtl8168d: failed to catch events on IRQ file"); - - let socket_fd = socket.borrow().as_raw_fd(); - let socket_packet = socket.clone(); - event_queue.add(socket_fd, move |_count: usize| -> Result> { - loop { - let mut packet = Packet::default(); - if socket_packet.borrow_mut().read(&mut packet)? == 0 { - break; - } - - let a = packet.a; - device.borrow_mut().handle(&mut packet); - if packet.a == (-EWOULDBLOCK) as usize { - packet.a = a; - todo.borrow_mut().push(packet); - } else { - socket_packet.borrow_mut().write(&mut packet)?; - } - } - - let next_read = device.borrow().next_read(); - if next_read > 0 { - return Ok(Some(next_read)); - } - - Ok(None) - }).expect("rtl8168d: failed to catch events on IRQ file"); - - for event_count in event_queue.trigger_all(0).expect("rtl8168d: failed to trigger events") { - socket.borrow_mut().write(&Packet { - id: 0, - pid: 0, - uid: 0, - gid: 0, - a: syscall::number::SYS_FEVENT, - b: 0, - c: syscall::flag::EVENT_READ, - d: event_count - }).expect("rtl8168d: failed to write event"); - } - - loop { - let event_count = event_queue.run().expect("rtl8168d: failed to handle events"); - - socket.borrow_mut().write(&Packet { - id: 0, - pid: 0, - uid: 0, - gid: 0, - a: syscall::number::SYS_FEVENT, - b: 0, - c: syscall::flag::EVENT_READ, - d: event_count - }).expect("rtl8168d: failed to write event"); - } - } - unsafe { let _ = syscall::physunmap(address); } - } -} diff --git a/drivers/vesad/Cargo.toml b/drivers/vesad/Cargo.toml deleted file mode 100644 index a70dbf0..0000000 --- a/drivers/vesad/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "vesad" -version = "0.1.0" - -[dependencies] -orbclient = "0.2" -ransid = "0.2" -rusttype = { version = "0.2", optional = true } -redox_syscall = { path = "../../syscall" } - -[features] -default = [] diff --git a/drivers/vesad/src/display.rs b/drivers/vesad/src/display.rs deleted file mode 100644 index 829d6ba..0000000 --- a/drivers/vesad/src/display.rs +++ /dev/null @@ -1,246 +0,0 @@ -#[cfg(feature="rusttype")] -extern crate rusttype; - -use alloc::heap; -use std::{cmp, slice}; - -use primitive::{fast_set32, fast_set64, fast_copy, fast_copy64}; - -#[cfg(feature="rusttype")] -use self::rusttype::{Font, FontCollection, Scale, point}; - -#[cfg(not(feature="rusttype"))] -static FONT: &'static [u8] = include_bytes!("../../../res/fonts/unifont.font"); - -#[cfg(feature="rusttype")] -static FONT: &'static [u8] = include_bytes!("../../../res/fonts/DejaVuSansMono.ttf"); -#[cfg(feature="rusttype")] -static FONT_BOLD: &'static [u8] = include_bytes!("../../../res/fonts/DejaVuSansMono-Bold.ttf"); -#[cfg(feature="rusttype")] -static FONT_BOLD_ITALIC: &'static [u8] = include_bytes!("../../../res/fonts/DejaVuSansMono-BoldOblique.ttf"); -#[cfg(feature="rusttype")] -static FONT_ITALIC: &'static [u8] = include_bytes!("../../../res/fonts/DejaVuSansMono-Oblique.ttf"); - -/// A display -pub struct Display { - pub width: usize, - pub height: usize, - pub onscreen: &'static mut [u32], - pub offscreen: &'static mut [u32], - #[cfg(feature="rusttype")] - pub font: Font<'static>, - #[cfg(feature="rusttype")] - pub font_bold: Font<'static>, - #[cfg(feature="rusttype")] - pub font_bold_italic: Font<'static>, - #[cfg(feature="rusttype")] - pub font_italic: Font<'static> -} - -impl Display { - #[cfg(not(feature="rusttype"))] - pub fn new(width: usize, height: usize, onscreen: usize) -> Display { - let size = width * height; - let offscreen = unsafe { heap::allocate(size * 4, 4096) }; - unsafe { fast_set64(offscreen as *mut u64, 0, size/2) }; - Display { - width: width, - height: height, - onscreen: unsafe { slice::from_raw_parts_mut(onscreen as *mut u32, size) }, - offscreen: unsafe { slice::from_raw_parts_mut(offscreen as *mut u32, size) } - } - } - - #[cfg(feature="rusttype")] - pub fn new(width: usize, height: usize, onscreen: usize) -> Display { - let size = width * height; - let offscreen = unsafe { heap::allocate(size * 4, 4096) }; - unsafe { fast_set64(offscreen as *mut u64, 0, size/2) }; - Display { - width: width, - height: height, - onscreen: unsafe { slice::from_raw_parts_mut(onscreen as *mut u32, size) }, - offscreen: unsafe { slice::from_raw_parts_mut(offscreen as *mut u32, size) }, - font: FontCollection::from_bytes(FONT).into_font().unwrap(), - font_bold: FontCollection::from_bytes(FONT_BOLD).into_font().unwrap(), - font_bold_italic: FontCollection::from_bytes(FONT_BOLD_ITALIC).into_font().unwrap(), - font_italic: FontCollection::from_bytes(FONT_ITALIC).into_font().unwrap() - } - } - - /// Draw a rectangle - pub fn rect(&mut self, x: usize, y: usize, w: usize, h: usize, color: u32) { - let start_y = cmp::min(self.height - 1, y); - let end_y = cmp::min(self.height, y + h); - - let start_x = cmp::min(self.width - 1, x); - let len = cmp::min(self.width, x + w) - start_x; - - let mut offscreen_ptr = self.offscreen.as_mut_ptr() as usize; - - let stride = self.width * 4; - - let offset = y * stride + start_x * 4; - offscreen_ptr += offset; - - let mut rows = end_y - start_y; - while rows > 0 { - unsafe { - fast_set32(offscreen_ptr as *mut u32, color, len); - } - offscreen_ptr += stride; - rows -= 1; - } - } - - /// Invert a rectangle - pub fn invert(&mut self, x: usize, y: usize, w: usize, h: usize) { - let start_y = cmp::min(self.height - 1, y); - let end_y = cmp::min(self.height, y + h); - - let start_x = cmp::min(self.width - 1, x); - let len = cmp::min(self.width, x + w) - start_x; - - let mut offscreen_ptr = self.offscreen.as_mut_ptr() as usize; - - let stride = self.width * 4; - - let offset = y * stride + start_x * 4; - offscreen_ptr += offset; - - let mut rows = end_y - start_y; - while rows > 0 { - let mut row_ptr = offscreen_ptr; - let mut cols = len; - while cols > 0 { - unsafe { - let color = *(row_ptr as *mut u32); - *(row_ptr as *mut u32) = !color; - } - row_ptr += 4; - cols -= 1; - } - offscreen_ptr += stride; - rows -= 1; - } - } - - /// Draw a character - #[cfg(not(feature="rusttype"))] - pub fn char(&mut self, x: usize, y: usize, character: char, color: u32, _bold: bool, _italic: bool) { - if x + 8 <= self.width && y + 16 <= self.height { - let mut dst = self.offscreen.as_mut_ptr() as usize + (y * self.width + x) * 4; - - let font_i = 16 * (character as usize); - if font_i + 16 <= FONT.len() { - for row in 0..16 { - let row_data = FONT[font_i + row]; - for col in 0..8 { - if (row_data >> (7 - col)) & 1 == 1 { - unsafe { *((dst + col * 4) as *mut u32) = color; } - } - } - dst += self.width * 4; - } - } - } - } - - /// Draw a character - #[cfg(feature="rusttype")] - pub fn char(&mut self, x: usize, y: usize, character: char, color: u32, bold: bool, italic: bool) { - let width = self.width; - let height = self.height; - let offscreen = self.offscreen.as_mut_ptr() as usize; - - let font = if bold && italic { - &self.font_bold_italic - } else if bold { - &self.font_bold - } else if italic { - &self.font_italic - } else { - &self.font - }; - - if let Some(glyph) = font.glyph(character){ - let scale = Scale::uniform(16.0); - let v_metrics = font.v_metrics(scale); - let point = point(0.0, v_metrics.ascent); - let glyph = glyph.scaled(scale).positioned(point); - if let Some(bb) = glyph.pixel_bounding_box() { - glyph.draw(|off_x, off_y, v| { - let off_x = x + (off_x as i32 + bb.min.x) as usize; - let off_y = y + (off_y as i32 + bb.min.y) as usize; - // There's still a possibility that the glyph clips the boundaries of the bitmap - if off_x < width && off_y < height { - if v > 0.0 { - let f_a = (v * 255.0) as u32; - let f_r = (((color >> 16) & 0xFF) * f_a)/255; - let f_g = (((color >> 8) & 0xFF) * f_a)/255; - let f_b = ((color & 0xFF) * f_a)/255; - - let offscreen_ptr = (offscreen + (off_y * width + off_x) * 4) as *mut u32; - - let bg = unsafe { *offscreen_ptr }; - - let b_a = 255 - f_a; - let b_r = (((bg >> 16) & 0xFF) * b_a)/255; - let b_g = (((bg >> 8) & 0xFF) * b_a)/255; - let b_b = ((bg & 0xFF) * b_a)/255; - - let c = ((f_r + b_r) << 16) | ((f_g + b_g) << 8) | (f_b + b_b); - - unsafe { *offscreen_ptr = c; } - } - } - }); - } - } - } - - /// Scroll display - pub fn scroll(&mut self, rows: usize, color: u32) { - let data = (color as u64) << 32 | color as u64; - - let width = self.width/2; - let height = self.height; - if rows > 0 && rows < height { - let off1 = rows * width; - let off2 = height * width - off1; - unsafe { - let data_ptr = self.offscreen.as_mut_ptr() as *mut u64; - fast_copy64(data_ptr, data_ptr.offset(off1 as isize), off2); - fast_set64(data_ptr.offset(off2 as isize), data, off1); - } - } - } - - /// Copy from offscreen to onscreen - pub fn sync(&mut self, x: usize, y: usize, w: usize, h: usize) { - let start_y = cmp::min(self.height - 1, y); - let end_y = cmp::min(self.height, y + h); - - let start_x = cmp::min(self.width - 1, x); - let len = (cmp::min(self.width, x + w) - start_x) * 4; - - let mut offscreen_ptr = self.offscreen.as_mut_ptr() as usize; - let mut onscreen_ptr = self.onscreen.as_mut_ptr() as usize; - - let stride = self.width * 4; - - let offset = y * stride + start_x * 4; - offscreen_ptr += offset; - onscreen_ptr += offset; - - let mut rows = end_y - start_y; - while rows > 0 { - unsafe { - fast_copy(onscreen_ptr as *mut u8, offscreen_ptr as *const u8, len); - } - offscreen_ptr += stride; - onscreen_ptr += stride; - rows -= 1; - } - } -} diff --git a/drivers/vesad/src/main.rs b/drivers/vesad/src/main.rs deleted file mode 100644 index 7f4347a..0000000 --- a/drivers/vesad/src/main.rs +++ /dev/null @@ -1,109 +0,0 @@ -#![feature(alloc)] -#![feature(asm)] -#![feature(heap_api)] - -extern crate alloc; -extern crate orbclient; -extern crate syscall; - -use std::{env, mem}; -use std::fs::File; -use std::io::{Read, Write}; -use syscall::{physmap, physunmap, Packet, SchemeMut, EVENT_READ, MAP_WRITE, MAP_WRITE_COMBINE}; - -use mode_info::VBEModeInfo; -use primitive::fast_set64; -use scheme::DisplayScheme; - -pub mod display; -pub mod mode_info; -pub mod primitive; -pub mod scheme; -pub mod screen; - -fn main() { - let mut spec = Vec::new(); - - for arg in env::args().skip(1) { - if arg == "T" { - spec.push(false); - } else if arg == "G" { - spec.push(true); - } else { - println!("vesad: unknown screen type: {}", arg); - } - } - - let width; - let height; - let physbaseptr; - - { - let mode_info = unsafe { &*(physmap(0x5200, 4096, 0).expect("vesad: failed to map VBE info") as *const VBEModeInfo) }; - - width = mode_info.xresolution as usize; - height = mode_info.yresolution as usize; - physbaseptr = mode_info.physbaseptr as usize; - - unsafe { let _ = physunmap(mode_info as *const _ as usize); } - } - - if physbaseptr > 0 { - // Daemonize - if unsafe { syscall::clone(0).unwrap() } == 0 { - let mut socket = File::create(":display").expect("vesad: failed to create display scheme"); - - let size = width * height; - - let onscreen = unsafe { physmap(physbaseptr, size * 4, MAP_WRITE | MAP_WRITE_COMBINE).expect("vesad: failed to map VBE LFB") }; - unsafe { fast_set64(onscreen as *mut u64, 0, size/2) }; - - let mut scheme = DisplayScheme::new(width, height, onscreen, &spec); - - let mut blocked = Vec::new(); - loop { - let mut packet = Packet::default(); - socket.read(&mut packet).expect("vesad: failed to read display scheme"); - - // If it is a read packet, and there is no data, block it. Otherwise, handle packet - if packet.a == syscall::number::SYS_READ && packet.d > 0 && scheme.will_block(packet.b) { - blocked.push(packet); - } else { - scheme.handle(&mut packet); - socket.write(&packet).expect("vesad: failed to write display scheme"); - } - - // If there are blocked readers, and data is available, handle them - { - let mut i = 0; - while i < blocked.len() { - if ! scheme.will_block(blocked[i].b) { - let mut packet = blocked.remove(i); - scheme.handle(&mut packet); - socket.write(&packet).expect("vesad: failed to write display scheme"); - } else { - i += 1; - } - } - } - - for (screen_id, screen) in scheme.screens.iter() { - if ! screen.will_block() { - let event_packet = Packet { - id: 0, - pid: 0, - uid: 0, - gid: 0, - a: syscall::number::SYS_FEVENT, - b: *screen_id, - c: EVENT_READ, - d: mem::size_of::() - }; - - socket.write(&event_packet).expect("vesad: failed to write display event"); - } - } - } - } - } -} diff --git a/drivers/vesad/src/mode_info.rs b/drivers/vesad/src/mode_info.rs deleted file mode 100644 index 7d59af6..0000000 --- a/drivers/vesad/src/mode_info.rs +++ /dev/null @@ -1,37 +0,0 @@ -/// The info of the VBE mode -#[derive(Copy, Clone, Default, Debug)] -#[repr(packed)] -pub struct VBEModeInfo { - attributes: u16, - win_a: u8, - win_b: u8, - granularity: u16, - winsize: u16, - segment_a: u16, - segment_b: u16, - winfuncptr: u32, - bytesperscanline: u16, - pub xresolution: u16, - pub yresolution: u16, - xcharsize: u8, - ycharsize: u8, - numberofplanes: u8, - bitsperpixel: u8, - numberofbanks: u8, - memorymodel: u8, - banksize: u8, - numberofimagepages: u8, - unused: u8, - redmasksize: u8, - redfieldposition: u8, - greenmasksize: u8, - greenfieldposition: u8, - bluemasksize: u8, - bluefieldposition: u8, - rsvdmasksize: u8, - rsvdfieldposition: u8, - directcolormodeinfo: u8, - pub physbaseptr: u32, - offscreenmemoryoffset: u32, - offscreenmemsize: u16, -} diff --git a/drivers/vesad/src/primitive.rs b/drivers/vesad/src/primitive.rs deleted file mode 100644 index 16c2536..0000000 --- a/drivers/vesad/src/primitive.rs +++ /dev/null @@ -1,47 +0,0 @@ -#[cfg(target_arch = "x86_64")] -#[inline(always)] -#[cold] -pub unsafe fn fast_copy(dst: *mut u8, src: *const u8, len: usize) { - asm!("cld - rep movsb" - : - : "{rdi}"(dst as usize), "{rsi}"(src as usize), "{rcx}"(len) - : "cc", "memory", "rdi", "rsi", "rcx" - : "intel", "volatile"); -} - -#[cfg(target_arch = "x86_64")] -#[inline(always)] -#[cold] -pub unsafe fn fast_copy64(dst: *mut u64, src: *const u64, len: usize) { - asm!("cld - rep movsq" - : - : "{rdi}"(dst as usize), "{rsi}"(src as usize), "{rcx}"(len) - : "cc", "memory", "rdi", "rsi", "rcx" - : "intel", "volatile"); -} - -#[cfg(target_arch = "x86_64")] -#[inline(always)] -#[cold] -pub unsafe fn fast_set32(dst: *mut u32, src: u32, len: usize) { - asm!("cld - rep stosd" - : - : "{rdi}"(dst as usize), "{eax}"(src), "{rcx}"(len) - : "cc", "memory", "rdi", "rcx" - : "intel", "volatile"); -} - -#[cfg(target_arch = "x86_64")] -#[inline(always)] -#[cold] -pub unsafe fn fast_set64(dst: *mut u64, src: u64, len: usize) { - asm!("cld - rep stosq" - : - : "{rdi}"(dst as usize), "{rax}"(src), "{rcx}"(len) - : "cc", "memory", "rdi", "rcx" - : "intel", "volatile"); -} diff --git a/drivers/vesad/src/scheme.rs b/drivers/vesad/src/scheme.rs deleted file mode 100644 index e376bf7..0000000 --- a/drivers/vesad/src/scheme.rs +++ /dev/null @@ -1,190 +0,0 @@ -use std::collections::BTreeMap; -use std::{mem, slice, str}; - -use orbclient::{Event, EventOption}; -use syscall::{Result, Error, EACCES, EBADF, ENOENT, SchemeMut}; - -use display::Display; -use screen::{Screen, GraphicScreen, TextScreen}; - -pub struct DisplayScheme { - active: usize, - pub screens: BTreeMap> -} - -impl DisplayScheme { - pub fn new(width: usize, height: usize, onscreen: usize, spec: &[bool]) -> DisplayScheme { - let mut screens: BTreeMap> = BTreeMap::new(); - - let mut screen_i = 1; - for &screen_type in spec.iter() { - if screen_type { - screens.insert(screen_i, Box::new(GraphicScreen::new(Display::new(width, height, onscreen)))); - } else { - screens.insert(screen_i, Box::new(TextScreen::new(Display::new(width, height, onscreen)))); - } - screen_i += 1; - } - - DisplayScheme { - active: 1, - screens: screens - } - } - - pub fn will_block(&self, id: usize) -> bool { - if let Some(screen) = self.screens.get(&id) { - screen.will_block() - } else { - false - } - } -} - -impl SchemeMut for DisplayScheme { - fn open(&mut self, path: &[u8], _flags: usize, uid: u32, _gid: u32) -> Result { - if path == b"input" { - if uid == 0 { - Ok(0) - } else { - Err(Error::new(EACCES)) - } - } else { - let path_str = str::from_utf8(path).unwrap_or("").trim_matches('/'); - let mut parts = path_str.split('/'); - let id = parts.next().unwrap_or("").parse::().unwrap_or(0); - if self.screens.contains_key(&id) { - for cmd in parts { - if cmd == "activate" { - self.active = id; - } - } - Ok(id) - } else { - Err(Error::new(ENOENT)) - } - } - } - - fn dup(&mut self, id: usize, _buf: &[u8]) -> Result { - Ok(id) - } - - fn fevent(&mut self, id: usize, flags: usize) -> Result { - if let Some(mut screen) = self.screens.get_mut(&id) { - screen.event(flags).and(Ok(id)) - } else { - Err(Error::new(EBADF)) - } - } - - fn fmap(&mut self, id: usize, offset: usize, size: usize) -> Result { - if let Some(screen) = self.screens.get(&id) { - screen.map(offset, size) - } else { - Err(Error::new(EBADF)) - } - } - - fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result { - let path_str = if id == 0 { - format!("display:input") - } else if let Some(screen) = self.screens.get(&id) { - format!("display:{}/{}/{}", id, screen.width(), screen.height()) - } else { - return Err(Error::new(EBADF)); - }; - - let path = path_str.as_bytes(); - - let mut i = 0; - while i < buf.len() && i < path.len() { - buf[i] = path[i]; - i += 1; - } - - Ok(i) - } - - fn fsync(&mut self, id: usize) -> Result { - if let Some(mut screen) = self.screens.get_mut(&id) { - if id == self.active { - screen.sync(); - } - Ok(0) - } else { - Err(Error::new(EBADF)) - } - } - - fn read(&mut self, id: usize, buf: &mut [u8]) -> Result { - if let Some(mut screen) = self.screens.get_mut(&id) { - screen.read(buf) - } else { - Err(Error::new(EBADF)) - } - } - - fn write(&mut self, id: usize, buf: &[u8]) -> Result { - if id == 0 { - if buf.len() == 1 && buf[0] >= 0xF4 { - let new_active = (buf[0] - 0xF4) as usize + 1; - if let Some(mut screen) = self.screens.get_mut(&new_active) { - self.active = new_active; - screen.redraw(); - } - Ok(1) - } else { - let events = unsafe { slice::from_raw_parts(buf.as_ptr() as *const Event, buf.len()/mem::size_of::()) }; - - for event in events.iter() { - let new_active_opt = if let EventOption::Key(key_event) = event.to_option() { - match key_event.scancode { - f @ 0x3B ... 0x44 => { // F1 through F10 - Some((f - 0x3A) as usize) - }, - 0x57 => { // F11 - Some(11) - }, - 0x58 => { // F12 - Some(12) - }, - _ => None - } - } else { - None - }; - - if let Some(new_active) = new_active_opt { - if let Some(mut screen) = self.screens.get_mut(&new_active) { - self.active = new_active; - screen.redraw(); - } - } else { - if let Some(mut screen) = self.screens.get_mut(&self.active) { - screen.input(event); - } - } - } - - Ok(events.len() * mem::size_of::()) - } - } else if let Some(mut screen) = self.screens.get_mut(&id) { - screen.write(buf, id == self.active) - } else { - Err(Error::new(EBADF)) - } - } - - fn seek(&mut self, id: usize, pos: usize, whence: usize) -> Result { - if let Some(mut screen) = self.screens.get_mut(&id) { - screen.seek(pos, whence) - } else { - Err(Error::new(EBADF)) - } - } - - fn close(&mut self, _id: usize) -> Result { - Ok(0) - } -} diff --git a/drivers/vesad/src/screen/graphic.rs b/drivers/vesad/src/screen/graphic.rs deleted file mode 100644 index b911922..0000000 --- a/drivers/vesad/src/screen/graphic.rs +++ /dev/null @@ -1,126 +0,0 @@ -use std::collections::VecDeque; -use std::{cmp, mem, slice}; - -use orbclient::{Event, EventOption}; -use syscall::error::*; -use syscall::flag::{SEEK_SET, SEEK_CUR, SEEK_END}; - -use display::Display; -use primitive::fast_copy; -use screen::Screen; - -pub struct GraphicScreen { - pub display: Display, - pub seek: usize, - pub mouse_x: i32, - pub mouse_y: i32, - pub input: VecDeque, - pub requested: usize -} - -impl GraphicScreen { - pub fn new(display: Display) -> GraphicScreen { - GraphicScreen { - display: display, - seek: 0, - mouse_x: 0, - mouse_y: 0, - input: VecDeque::new(), - requested: 0 - } - } -} - -impl Screen for GraphicScreen { - fn width(&self) -> usize { - self.display.width - } - - fn height(&self) -> usize { - self.display.height - } - - fn event(&mut self, flags: usize) -> Result { - self.requested = flags; - Ok(0) - } - - fn map(&self, offset: usize, size: usize) -> Result { - if offset + size <= self.display.offscreen.len() * 4 { - Ok(self.display.offscreen.as_ptr() as usize + offset) - } else { - Err(Error::new(EINVAL)) - } - } - - fn input(&mut self, event: &Event) { - if let EventOption::Mouse(mut mouse_event) = event.to_option() { - let x = cmp::max(0, cmp::min(self.display.width as i32, self.mouse_x + mouse_event.x)); - let y = cmp::max(0, cmp::min(self.display.height as i32, self.mouse_y + mouse_event.y)); - - mouse_event.x = x; - self.mouse_x = x; - mouse_event.y = y; - self.mouse_y = y; - - self.input.push_back(mouse_event.to_event()); - } else { - self.input.push_back(*event); - } - } - - fn read(&mut self, buf: &mut [u8]) -> Result { - let mut i = 0; - - let event_buf = unsafe { slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut Event, buf.len()/mem::size_of::()) }; - - while i < event_buf.len() && ! self.input.is_empty() { - event_buf[i] = self.input.pop_front().unwrap(); - i += 1; - } - - Ok(i * mem::size_of::()) - } - - fn will_block(&self) -> bool { - self.input.is_empty() - } - - fn write(&mut self, buf: &[u8], sync: bool) -> Result { - let size = cmp::max(0, cmp::min(self.display.offscreen.len() as isize - self.seek as isize, (buf.len()/4) as isize)) as usize; - - if size > 0 { - unsafe { - fast_copy(self.display.offscreen.as_mut_ptr().offset(self.seek as isize) as *mut u8, buf.as_ptr(), size * 4); - if sync { - fast_copy(self.display.onscreen.as_mut_ptr().offset(self.seek as isize) as *mut u8, buf.as_ptr(), size * 4); - } - } - } - - Ok(size * 4) - } - - fn seek(&mut self, pos: usize, whence: usize) -> Result { - let size = self.display.offscreen.len(); - - self.seek = match whence { - SEEK_SET => cmp::min(size, (pos/4)), - SEEK_CUR => cmp::max(0, cmp::min(size as isize, self.seek as isize + (pos/4) as isize)) as usize, - SEEK_END => cmp::max(0, cmp::min(size as isize, size as isize + (pos/4) as isize)) as usize, - _ => return Err(Error::new(EINVAL)) - }; - - Ok(self.seek * 4) - } - - fn sync(&mut self) { - self.redraw(); - } - - fn redraw(&mut self) { - let width = self.display.width; - let height = self.display.height; - self.display.sync(0, 0, width, height); - } -} diff --git a/drivers/vesad/src/screen/mod.rs b/drivers/vesad/src/screen/mod.rs deleted file mode 100644 index 9909694..0000000 --- a/drivers/vesad/src/screen/mod.rs +++ /dev/null @@ -1,32 +0,0 @@ -pub use self::graphic::GraphicScreen; -pub use self::text::TextScreen; - -use orbclient::Event; -use syscall::Result; - -mod graphic; -mod text; - -pub trait Screen { - fn width(&self) -> usize; - - fn height(&self) -> usize; - - fn event(&mut self, flags: usize) -> Result; - - fn map(&self, offset: usize, size: usize) -> Result; - - fn input(&mut self, event: &Event); - - fn read(&mut self, buf: &mut [u8]) -> Result; - - fn will_block(&self) -> bool; - - fn write(&mut self, buf: &[u8], sync: bool) -> Result; - - fn seek(&mut self, pos: usize, whence: usize) -> Result; - - fn sync(&mut self); - - fn redraw(&mut self); -} diff --git a/drivers/vesad/src/screen/text.rs b/drivers/vesad/src/screen/text.rs deleted file mode 100644 index ccc259d..0000000 --- a/drivers/vesad/src/screen/text.rs +++ /dev/null @@ -1,233 +0,0 @@ -extern crate ransid; - -use std::collections::{BTreeSet, VecDeque}; - -use orbclient::{Event, EventOption}; -use syscall::error::*; - -use display::Display; -use screen::Screen; - -pub struct TextScreen { - pub console: ransid::Console, - pub display: Display, - pub changed: BTreeSet, - pub ctrl: bool, - pub input: VecDeque, - pub end_of_input: bool, - pub cooked: VecDeque, - pub requested: usize -} - -impl TextScreen { - pub fn new(display: Display) -> TextScreen { - TextScreen { - console: ransid::Console::new(display.width/8, display.height/16), - display: display, - changed: BTreeSet::new(), - ctrl: false, - input: VecDeque::new(), - end_of_input: false, - cooked: VecDeque::new(), - requested: 0 - } - } -} - -impl Screen for TextScreen { - fn width(&self) -> usize { - self.console.w - } - - fn height(&self) -> usize { - self.console.h - } - - fn event(&mut self, flags: usize) -> Result { - self.requested = flags; - Ok(0) - } - - fn map(&self, offset: usize, size: usize) -> Result { - Err(Error::new(EBADF)) - } - - fn input(&mut self, event: &Event) { - let mut buf = vec![]; - - match event.to_option() { - EventOption::Key(key_event) => { - if key_event.scancode == 0x1D { - self.ctrl = key_event.pressed; - } else if key_event.pressed { - match key_event.scancode { - 0x0E => { // Backspace - buf.extend_from_slice(b"\x7F"); - }, - 0x47 => { // Home - buf.extend_from_slice(b"\x1B[H"); - }, - 0x48 => { // Up - buf.extend_from_slice(b"\x1B[A"); - }, - 0x49 => { // Page up - buf.extend_from_slice(b"\x1B[5~"); - }, - 0x4B => { // Left - buf.extend_from_slice(b"\x1B[D"); - }, - 0x4D => { // Right - buf.extend_from_slice(b"\x1B[C"); - }, - 0x4F => { // End - buf.extend_from_slice(b"\x1B[F"); - }, - 0x50 => { // Down - buf.extend_from_slice(b"\x1B[B"); - }, - 0x51 => { // Page down - buf.extend_from_slice(b"\x1B[6~"); - }, - 0x52 => { // Insert - buf.extend_from_slice(b"\x1B[2~"); - }, - 0x53 => { // Delete - buf.extend_from_slice(b"\x1B[3~"); - }, - _ => { - let c = match key_event.character { - c @ 'A' ... 'Z' if self.ctrl => ((c as u8 - b'A') + b'\x01') as char, - c @ 'a' ... 'z' if self.ctrl => ((c as u8 - b'a') + b'\x01') as char, - c => c - }; - - if c != '\0' { - buf.extend_from_slice(&[c as u8]); - } - } - } - } - }, - _ => () //TODO: Mouse in terminal - } - - if self.console.raw_mode { - for &b in buf.iter() { - self.input.push_back(b); - } - } else { - for &b in buf.iter() { - match b { - b'\x03' => { - self.end_of_input = true; - let _ = self.write(b"^C\n", true); - }, - b'\x08' | b'\x7F' => { - if let Some(_c) = self.cooked.pop_back() { - let _ = self.write(b"\x08", true); - } - }, - b'\x1B' => { - let _ = self.write(b"^[", true); - }, - b'\n' | b'\r' => { - self.cooked.push_back(b); - while let Some(c) = self.cooked.pop_front() { - self.input.push_back(c); - } - let _ = self.write(b"\n", true); - }, - _ => { - self.cooked.push_back(b); - let _ = self.write(&[b], true); - } - } - } - } - } - - fn read(&mut self, buf: &mut [u8]) -> Result { - let mut i = 0; - - while i < buf.len() && ! self.input.is_empty() { - buf[i] = self.input.pop_front().unwrap(); - i += 1; - } - - if i == 0 { - self.end_of_input = false; - } - - Ok(i) - } - - fn will_block(&self) -> bool { - self.input.is_empty() && ! self.end_of_input - } - - fn write(&mut self, buf: &[u8], sync: bool) -> Result { - if self.console.cursor && self.console.x < self.console.w && self.console.y < self.console.h { - let x = self.console.x; - let y = self.console.y; - self.display.invert(x * 8, y * 16, 8, 16); - self.changed.insert(y); - } - - { - let display = &mut self.display; - let changed = &mut self.changed; - self.console.write(buf, |event| { - match event { - ransid::Event::Char { x, y, c, color, bold, .. } => { - display.char(x * 8, y * 16, c, color.data, bold, false); - changed.insert(y); - }, - ransid::Event::Rect { x, y, w, h, color } => { - display.rect(x * 8, y * 16, w * 8, h * 16, color.data); - for y2 in y..y + h { - changed.insert(y2); - } - }, - ransid::Event::Scroll { rows, color } => { - display.scroll(rows * 16, color.data); - for y in 0..display.height/16 { - changed.insert(y); - } - } - } - }); - } - - if self.console.cursor && self.console.x < self.console.w && self.console.y < self.console.h { - let x = self.console.x; - let y = self.console.y; - self.display.invert(x * 8, y * 16, 8, 16); - self.changed.insert(y); - } - - if ! self.console.raw_mode && sync { - self.sync(); - } - - Ok(buf.len()) - } - - fn seek(&mut self, _pos: usize, _whence: usize) -> Result { - Ok(0) - } - - fn sync(&mut self) { - let width = self.display.width; - for change in self.changed.iter() { - self.display.sync(0, change * 16, width, 16); - } - self.changed.clear(); - } - - fn redraw(&mut self) { - let width = self.display.width; - let height = self.display.height; - self.display.sync(0, 0, width, height); - self.changed.clear(); - } -} From 5776b0b452be65bb4cff1d7b73b2a27d7aefebbf Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 5 Jan 2017 11:26:32 -0700 Subject: [PATCH 049/522] Move bootloader to submodule --- .gitmodules | 3 + bootloader | 1 + bootloader/arm/start.s | 17 -- bootloader/x86_64/bootsector.asm | 188 ---------------------- bootloader/x86_64/config.asm | 18 --- bootloader/x86_64/descriptor_flags.inc | 46 ------ bootloader/x86_64/gdt_entry.inc | 8 - bootloader/x86_64/harddrive.asm | 21 --- bootloader/x86_64/initialize.asm | 78 ---------- bootloader/x86_64/livedisk.asm | 19 --- bootloader/x86_64/memory_map.asm | 32 ---- bootloader/x86_64/print16.asm | 65 -------- bootloader/x86_64/startup-common.asm | 110 ------------- bootloader/x86_64/startup-i386.asm | 148 ------------------ bootloader/x86_64/startup-x86_64.asm | 179 --------------------- bootloader/x86_64/unreal.asm | 54 ------- bootloader/x86_64/vesa.asm | 207 ------------------------- bootloader/x86_64/vesa.inc | 90 ----------- 18 files changed, 4 insertions(+), 1280 deletions(-) create mode 160000 bootloader delete mode 100644 bootloader/arm/start.s delete mode 100644 bootloader/x86_64/bootsector.asm delete mode 100644 bootloader/x86_64/config.asm delete mode 100644 bootloader/x86_64/descriptor_flags.inc delete mode 100644 bootloader/x86_64/gdt_entry.inc delete mode 100644 bootloader/x86_64/harddrive.asm delete mode 100644 bootloader/x86_64/initialize.asm delete mode 100644 bootloader/x86_64/livedisk.asm delete mode 100644 bootloader/x86_64/memory_map.asm delete mode 100644 bootloader/x86_64/print16.asm delete mode 100644 bootloader/x86_64/startup-common.asm delete mode 100644 bootloader/x86_64/startup-i386.asm delete mode 100644 bootloader/x86_64/startup-x86_64.asm delete mode 100644 bootloader/x86_64/unreal.asm delete mode 100644 bootloader/x86_64/vesa.asm delete mode 100644 bootloader/x86_64/vesa.inc diff --git a/.gitmodules b/.gitmodules index c5a24df..98d2765 100644 --- a/.gitmodules +++ b/.gitmodules @@ -64,3 +64,6 @@ [submodule "drivers"] path = drivers url = https://github.com/redox-os/drivers.git +[submodule "bootloader"] + path = bootloader + url = https://github.com/redox-os/bootloader.git diff --git a/bootloader b/bootloader new file mode 160000 index 0000000..7639aef --- /dev/null +++ b/bootloader @@ -0,0 +1 @@ +Subproject commit 7639aef32ed5ffd272701d955147b8b50aad53e0 diff --git a/bootloader/arm/start.s b/bootloader/arm/start.s deleted file mode 100644 index 8495600..0000000 --- a/bootloader/arm/start.s +++ /dev/null @@ -1,17 +0,0 @@ -interrupt_vector_table: - b . @ Reset - b . - b . @ SWI instruction - b . - b . - b . - b . - b . - -.comm stack, 0x10000 @ Reserve 64k stack in the BSS -_start: - .globl _start - ldr sp, =stack+0x10000 @ Set up the stack - bl kstart @ Jump to the main function -1: - b 1b @ Halt diff --git a/bootloader/x86_64/bootsector.asm b/bootloader/x86_64/bootsector.asm deleted file mode 100644 index b66184e..0000000 --- a/bootloader/x86_64/bootsector.asm +++ /dev/null @@ -1,188 +0,0 @@ -ORG 0x7C00 -SECTION .text -USE16 - -boot: ; dl comes with disk - ; initialize segment registers - xor ax, ax - mov ds, ax - mov es, ax - mov ss, ax - - ; initialize stack - mov sp, 0x7C00 - - ; initialize CS - push ax - push word .set_cs - retf - -.set_cs: - - ; save disk number - mov [disk], dl - - mov si, name - call print - call print_line - - mov bx, (startup_start - boot) / 512 - call print_num - call print_line - - mov bx, startup_start - call print_num - call print_line - - mov eax, (startup_start - boot) / 512 - mov bx, startup_start - mov cx, (startup_end - startup_start) / 512 - xor dx, dx - call load - - mov si, finished - call print - call print_line - - jmp startup - -; load some sectors from disk to a buffer in memory -; buffer has to be below 1MiB -; IN -; ax: start sector -; bx: offset of buffer -; cx: number of sectors (512 Bytes each) -; dx: segment of buffer -; CLOBBER -; ax, bx, cx, dx, si -; TODO rewrite to (eventually) move larger parts at once -; if that is done increase buffer_size_sectors in startup-common to that (max 0x80000 - startup_end) -load: - cmp cx, 127 - jbe .good_size - - pusha - mov cx, 127 - call load - popa - add ax, 127 - add dx, 127 * 512 / 16 - sub cx, 127 - - jmp load -.good_size: - mov [DAPACK.addr], eax - mov [DAPACK.buf], bx - mov [DAPACK.count], cx - mov [DAPACK.seg], dx - - call print_dapack - - mov dl, [disk] - mov si, DAPACK - mov ah, 0x42 - int 0x13 - jc error - ret - - ; store some sectors to disk from a buffer in memory - ; buffer has to be below 1MiB - ; IN - ; ax: start sector - ; bx: offset of buffer - ; cx: number of sectors (512 Bytes each) - ; dx: segment of buffer - ; CLOBBER - ; ax, bx, cx, dx, si - ; TODO rewrite to (eventually) move larger parts at once - ; if that is done increase buffer_size_sectors in startup-common to that (max 0x80000 - startup_end) - store: - cmp cx, 127 - jbe .good_size - - pusha - mov cx, 127 - call store - popa - add ax, 127 - add dx, 127 * 512 / 16 - sub cx, 127 - - jmp store - .good_size: - mov [DAPACK.addr], eax - mov [DAPACK.buf], bx - mov [DAPACK.count], cx - mov [DAPACK.seg], dx - - call print_dapack - - mov dl, [disk] - mov si, DAPACK - mov ah, 0x43 - int 0x13 - jc error - ret - -print_dapack: - mov bx, [DAPACK.addr + 2] - call print_num - - mov bx, [DAPACK.addr] - call print_num - - mov al, '#' - call print_char - - mov bx, [DAPACK.count] - call print_num - - mov al, ' ' - call print_char - - mov bx, [DAPACK.seg] - call print_num - - mov al, ':' - call print_char - - mov bx, [DAPACK.buf] - call print_num - - jmp print_line - -error: - mov bh, 0 - mov bl, ah - call print_num - - mov al, ' ' - call print_char - - mov si, errored - call print - call print_line -.halt: - cli - hlt - jmp .halt - -%include "print16.asm" - -name: db "Redox Loader - Stage One",0 -errored: db "Could not read disk",0 -finished: db "Redox Loader - Stage Two",0 - -disk: db 0 - -DAPACK: - db 0x10 - db 0 -.count: dw 0 ; int 13 resets this to # of blocks actually read/written -.buf: dw 0 ; memory buffer destination address (0:7c00) -.seg: dw 0 ; in memory page zero -.addr: dq 0 ; put the lba to read in this spot - -times 510-($-$$) db 0 -db 0x55 -db 0xaa diff --git a/bootloader/x86_64/config.asm b/bootloader/x86_64/config.asm deleted file mode 100644 index 8e3b220..0000000 --- a/bootloader/x86_64/config.asm +++ /dev/null @@ -1,18 +0,0 @@ -SECTION .text -USE16 - -align 512, db 0 - -config: - .xres: dw 0 - .yres: dw 0 - -times 512 - ($ - config) db 0 - -save_config: - mov eax, (config - boot) / 512 - mov bx, config - mov cx, 1 - xor dx, dx - call store - ret diff --git a/bootloader/x86_64/descriptor_flags.inc b/bootloader/x86_64/descriptor_flags.inc deleted file mode 100644 index 210c98d..0000000 --- a/bootloader/x86_64/descriptor_flags.inc +++ /dev/null @@ -1,46 +0,0 @@ -attrib: - .present equ 1 << 7 - .ring1 equ 1 << 5 - .ring2 equ 1 << 6 - .ring3 equ 1 << 5 | 1 << 6 - .user equ 1 << 4 -;user - .code equ 1 << 3 -; code - .conforming equ 1 << 2 - .readable equ 1 << 1 -; data - .expand_down equ 1 << 2 - .writable equ 1 << 1 - .accessed equ 1 << 0 -;system -; legacy - .tssAvailabe16 equ 0x1 - .ldt equ 0x2 - .tssBusy16 equ 0x3 - .call16 equ 0x4 - .task equ 0x5 - .interrupt16 equ 0x6 - .trap16 equ 0x7 - .tssAvailabe32 equ 0x9 - .tssBusy32 equ 0xB - .call32 equ 0xC - .interrupt32 equ 0xE - .trap32 equ 0xF -; long mode - .ldt32 equ 0x2 - .tssAvailabe64 equ 0x9 - .tssBusy64 equ 0xB - .call64 equ 0xC - .interrupt64 equ 0xE - .trap64 equ 0xF - -flags: - .granularity equ 1 << 7 - .available equ 1 << 4 -;user - .default_operand_size equ 1 << 6 -; code - .long_mode equ 1 << 5 -; data - .reserved equ 1 << 5 diff --git a/bootloader/x86_64/gdt_entry.inc b/bootloader/x86_64/gdt_entry.inc deleted file mode 100644 index 861a78b..0000000 --- a/bootloader/x86_64/gdt_entry.inc +++ /dev/null @@ -1,8 +0,0 @@ -struc GDTEntry - .limitl resw 1 - .basel resw 1 - .basem resb 1 - .attribute resb 1 - .flags__limith resb 1 - .baseh resb 1 -endstruc diff --git a/bootloader/x86_64/harddrive.asm b/bootloader/x86_64/harddrive.asm deleted file mode 100644 index 052dfe8..0000000 --- a/bootloader/x86_64/harddrive.asm +++ /dev/null @@ -1,21 +0,0 @@ -%include "bootsector.asm" - -startup_start: -%ifdef ARCH_i386 - %include "startup-i386.asm" -%endif - -%ifdef ARCH_x86_64 - %include "startup-x86_64.asm" -%endif -align 512, db 0 -startup_end: - -kernel_file: - incbin "build/kernel/kernel" - align 512, db 0 -.end: -.length equ kernel_file.end - kernel_file -.length_sectors equ .length / 512 - -incbin "build/filesystem.bin" diff --git a/bootloader/x86_64/initialize.asm b/bootloader/x86_64/initialize.asm deleted file mode 100644 index e723d37..0000000 --- a/bootloader/x86_64/initialize.asm +++ /dev/null @@ -1,78 +0,0 @@ -SECTION .text -USE16 - -initialize: -.fpu: ;enable fpu - mov eax, cr0 - and al, 11110011b - or al, 00100010b - mov cr0, eax - mov eax, cr4 - or eax, 0x200 - mov cr4, eax - fninit - ret - -.sse: ;enable sse - mov eax, cr4 - or ax, 0000011000000000b - mov cr4, eax - ret - -;PIT Frequency -;If using nanoseconds, to minimize drift, one should find a frequency as close to an integer nanosecond value in wavelength -;Divider Hz Nanoseconds Properties -;2685 444.38795779019242706393 2250286.00003631746492922946 Best For Context Switching -;5370 222.19397889509621353196 4500572.00007263492985856020 -;21029 56.73981961418358774390 17624306.99991199998882825455 -;23714 50.31549576902532962244 19874592.99994831745375667118 -;26399 45.19798729749864262535 22124878.99998463491868476373 -;29084 41.02536331545408701233 24375165.00002095238361424615 -;31769 37.55804925136663623868 26625451.00005726984854313455 -;34454 34.63115071302799868423 28875737.00009358731347639618 -;50113 23.80982313305263437963 41999471.99993295237244784676 -;52798 22.59899364874932131267 44249757.99996926983737931766 -;55483 21.50535599492937776736 46500044.00000558730230583335 Lowest Drift -;58168 20.51268165772704350616 48750330.00004190476724037528 -;60853 19.60760630809765610021 51000616.00007822223218031738 - -.pit: - ;initialize the PIT - mov ax, 2685 ;this is the divider for the PIT - out 0x40, al - rol ax, 8 - out 0x40, al - ;DISABLED ;enable rtc interrupt - ;mov al, 0xB - ;out 0x70, al - ;rol ax, 8 - ;in al, 0x71 - ;rol ax, 8 - ;out 0x70, al - ;rol ax, 8 - ;or al, 0x40 - ;out 0x71, al - ret - -.pic: ;sets up IRQs at int 20-2F - mov al, 0x11 - out 0x20, al - out 0xA0, al - mov al, 0x20 ;IRQ0 vector - out 0x21, al - mov al, 0x28 ;IRQ8 vector - out 0xA1, al - mov al, 4 - out 0x21, al - mov al, 2 - out 0xA1, al - mov al, 1 - out 0x21, al - out 0xA1, al - xor al, al ;no IRQ masks - out 0x21, al - out 0xA1, al - mov al, 0x20 ;reset PIC's - out 0xA0, al - out 0x20, al - ret diff --git a/bootloader/x86_64/livedisk.asm b/bootloader/x86_64/livedisk.asm deleted file mode 100644 index e1cd643..0000000 --- a/bootloader/x86_64/livedisk.asm +++ /dev/null @@ -1,19 +0,0 @@ -%include "bootsector.asm" - -startup_start: -%ifdef ARCH_i386 - %include "startup-i386.asm" -%endif - -%ifdef ARCH_x86_64 - %include "startup-x86_64.asm" -%endif -align 512, db 0 -startup_end: - -kernel_file: - incbin "build/kernel/kernel_live" - align 512, db 0 -.end: -.length equ kernel_file.end - kernel_file -.length_sectors equ .length / 512 diff --git a/bootloader/x86_64/memory_map.asm b/bootloader/x86_64/memory_map.asm deleted file mode 100644 index a5cdc70..0000000 --- a/bootloader/x86_64/memory_map.asm +++ /dev/null @@ -1,32 +0,0 @@ -SECTION .text -USE16 -;Generate a memory map at 0x500 to 0x5000 (available memory not used for kernel or bootloader) -memory_map: -.start equ 0x0500 -.end equ 0x5000 -.length equ .end - .start - - xor eax, eax - mov di, .start - mov ecx, .length / 4 ; moving 4 Bytes at once - cld - rep stosd - - mov di, .start - mov edx, 0x534D4150 - xor ebx, ebx -.lp: - mov eax, 0xE820 - mov ecx, 24 - - int 0x15 - jc .done ; Error or finished - - cmp ebx, 0 - je .done ; Finished - - add di, 24 - cmp di, .end - jb .lp ; Still have buffer space -.done: - ret diff --git a/bootloader/x86_64/print16.asm b/bootloader/x86_64/print16.asm deleted file mode 100644 index dada0fd..0000000 --- a/bootloader/x86_64/print16.asm +++ /dev/null @@ -1,65 +0,0 @@ -SECTION .text -USE16 -; provide function for printing in x86 real mode - -; print a string and a newline -; IN -; si: points at zero-terminated String -; CLOBBER -; ax -print_line: - mov al, 13 - call print_char - mov al, 10 - jmp print_char - -; print a string -; IN -; si: points at zero-terminated String -; CLOBBER -; ax -print: - cld -.loop: - lodsb - test al, al - jz .done - call print_char - jmp .loop -.done: - ret - -; print a character -; IN -; al: character to print -; CLOBBER -; ah -print_char: - mov ah, 0x0e - int 0x10 - ret - -; print a number in hex -; IN -; bx: the number -; CLOBBER -; cx, ax -print_num: - mov cx, 4 -.lp: - mov al, bh - shr al, 4 - - cmp al, 0xA - jb .below_0xA - - add al, 'A' - 0xA - '0' -.below_0xA: - add al, '0' - - call print_char - - shl bx, 4 - loop .lp - - ret diff --git a/bootloader/x86_64/startup-common.asm b/bootloader/x86_64/startup-common.asm deleted file mode 100644 index 9677bbc..0000000 --- a/bootloader/x86_64/startup-common.asm +++ /dev/null @@ -1,110 +0,0 @@ -SECTION .text -USE16 - -startup: - ; enable A20-Line via IO-Port 92, might not work on all motherboards - in al, 0x92 - or al, 2 - out 0x92, al - -; loading kernel to 1MiB -; move part of kernel to startup_end via bootsector#load and then copy it up -; repeat until all of the kernel is loaded - -; buffersize in multiple of sectors (512 Bytes) -; min 1 -; max (0x70000 - startup_end) / 512 -buffer_size_sectors equ 127 -; buffer size in Bytes -buffer_size_bytes equ buffer_size_sectors * 512 - -kernel_base equ 0x100000 - - ; how often do we need to call load and move memory - mov ecx, kernel_file.length_sectors / buffer_size_sectors - - mov eax, (kernel_file - boot) / 512 - mov edi, kernel_base - cld -.lp: - ; saving counter - push cx - - ; populating buffer - mov cx, buffer_size_sectors - mov bx, kernel_file - mov dx, 0x0 - - push edi - push eax - call load - - ; moving buffer - call unreal - pop eax - pop edi - - mov esi, kernel_file - mov ecx, buffer_size_bytes / 4 - a32 rep movsd - - ; preparing next iteration - add eax, buffer_size_sectors - - pop cx - loop .lp - - ; load the part of the kernel that does not fill the buffer completely - mov cx, kernel_file.length_sectors % buffer_size_sectors - test cx, cx - jz finished_loading ; if cx = 0 => skip - - mov bx, kernel_file - mov dx, 0x0 - call load - - ; moving remnants of kernel - call unreal - - mov esi, kernel_file - mov ecx, (kernel_file.length_sectors % buffer_size_bytes) / 4 - a32 rep movsd -finished_loading: - call memory_map - - call vesa - - mov si, init_fpu_msg - call printrm - call initialize.fpu - - mov si, init_sse_msg - call printrm - call initialize.sse - - mov si, init_pit_msg - call printrm - call initialize.pit - - mov si, init_pic_msg - call printrm - call initialize.pic - - mov si, startup_arch_msg - call printrm - - jmp startup_arch - -%include "config.asm" -%include "descriptor_flags.inc" -%include "gdt_entry.inc" -%include "unreal.asm" -%include "memory_map.asm" -%include "vesa.asm" -%include "initialize.asm" - -init_fpu_msg: db "Init FPU",13,10,0 -init_sse_msg: db "Init SSE",13,10,0 -init_pit_msg: db "Init PIT",13,10,0 -init_pic_msg: db "Init PIC",13,10,0 -startup_arch_msg: db "Startup Arch",13,10,0 diff --git a/bootloader/x86_64/startup-i386.asm b/bootloader/x86_64/startup-i386.asm deleted file mode 100644 index c38a09e..0000000 --- a/bootloader/x86_64/startup-i386.asm +++ /dev/null @@ -1,148 +0,0 @@ -%include "startup-common.asm" - -startup_arch: - ; load protected mode GDT and IDT - cli - lgdt [gdtr] - lidt [idtr] - ; set protected mode bit of cr0 - mov eax, cr0 - or eax, 1 - mov cr0, eax - - ; far jump to load CS with 32 bit segment - jmp gdt.kernel_code:protected_mode - -USE32 -protected_mode: - ; load all the other segments with 32 bit data segments - mov eax, gdt.kernel_data - mov ds, eax - mov es, eax - mov fs, eax - mov gs, eax - mov ss, eax - - mov esp, 0x800000 - 128 - - mov eax, gdt.tss - ltr ax - - ;rust init - mov eax, [kernel_base + 0x18] - mov [interrupts.handler], eax - mov eax, gdtr - mov ebx, idtr - mov ecx, tss - int 255 -.lp: - sti - hlt - jmp .lp - -gdtr: - dw gdt.end + 1 ; size - dd gdt ; offset - -gdt: -.null equ $ - gdt - dq 0 - -.kernel_code equ $ - gdt - istruc GDTEntry - at GDTEntry.limitl, dw 0xFFFF - at GDTEntry.basel, dw 0 - at GDTEntry.basem, db 0 - at GDTEntry.attribute, db attrib.present | attrib.user | attrib.code | attrib.readable - at GDTEntry.flags__limith, db 0xFF | flags.granularity | flags.default_operand_size - at GDTEntry.baseh, db 0 - iend - -.kernel_data equ $ - gdt - istruc GDTEntry - at GDTEntry.limitl, dw 0xFFFF - at GDTEntry.basel, dw 0 - at GDTEntry.basem, db 0 - at GDTEntry.attribute, db attrib.present | attrib.user | attrib.writable - at GDTEntry.flags__limith, db 0xFF | flags.granularity | flags.default_operand_size - at GDTEntry.baseh, db 0 - iend - -.user_code equ $ - gdt - istruc GDTEntry - at GDTEntry.limitl, dw 0xFFFF - at GDTEntry.basel, dw 0 - at GDTEntry.basem, db 0 - at GDTEntry.attribute, db attrib.present | attrib.ring3 | attrib.user | attrib.code | attrib.readable - at GDTEntry.flags__limith, db 0xFF | flags.granularity | flags.default_operand_size - at GDTEntry.baseh, db 0 - iend - -.user_data equ $ - gdt - istruc GDTEntry - at GDTEntry.limitl, dw 0xFFFF - at GDTEntry.basel, dw 0 - at GDTEntry.basem, db 0 - at GDTEntry.attribute, db attrib.present | attrib.ring3 | attrib.user | attrib.writable - at GDTEntry.flags__limith, db 0xFF | flags.granularity | flags.default_operand_size - at GDTEntry.baseh, db 0 - iend - -.user_tls equ $ - gdt - istruc GDTEntry - at GDTEntry.limitl, dw 0xFFFF - at GDTEntry.basel, dw 0 - at GDTEntry.basem, db 0 - at GDTEntry.attribute, db attrib.present | attrib.ring3 | attrib.user | attrib.writable - at GDTEntry.flags__limith, db 0xFF | flags.granularity | flags.default_operand_size - at GDTEntry.baseh, db 0 - iend - -.tss equ $ - gdt - istruc GDTEntry - at GDTEntry.limitl, dw (tss.end - tss) & 0xFFFF - at GDTEntry.basel, dw (tss-$$+0x7C00) & 0xFFFF - at GDTEntry.basem, db ((tss-$$+0x7C00) >> 16) & 0xFF - at GDTEntry.attribute, db attrib.present | attrib.ring3 | attrib.tssAvailabe32 - at GDTEntry.flags__limith, db ((tss.end - tss) >> 16) & 0xF - at GDTEntry.baseh, db ((tss-$$+0x7C00) >> 24) & 0xFF - iend -.end equ $ - gdt - -struc TSS - .prev_tss resd 1 ;The previous TSS - if we used hardware task switching this would form a linked list. - .esp0 resd 1 ;The stack pointer to load when we change to kernel mode. - .ss0 resd 1 ;The stack segment to load when we change to kernel mode. - .esp1 resd 1 ;everything below here is unused now.. - .ss1 resd 1 - .esp2 resd 1 - .ss2 resd 1 - .cr3 resd 1 - .eip resd 1 - .eflags resd 1 - .eax resd 1 - .ecx resd 1 - .edx resd 1 - .ebx resd 1 - .esp resd 1 - .ebp resd 1 - .esi resd 1 - .edi resd 1 - .es resd 1 - .cs resd 1 - .ss resd 1 - .ds resd 1 - .fs resd 1 - .gs resd 1 - .ldt resd 1 - .trap resw 1 - .iomap_base resw 1 -endstruc - -tss: - istruc TSS - at TSS.esp0, dd 0x800000 - 128 - at TSS.ss0, dd gdt.kernel_data - at TSS.iomap_base, dw 0xFFFF - iend -.end: diff --git a/bootloader/x86_64/startup-x86_64.asm b/bootloader/x86_64/startup-x86_64.asm deleted file mode 100644 index 6059331..0000000 --- a/bootloader/x86_64/startup-x86_64.asm +++ /dev/null @@ -1,179 +0,0 @@ -trampoline: - .ready: dq 0 - .cpu_id: dq 0 - .page_table: dq 0 - .stack_start: dq 0 - .stack_end: dq 0 - .code: dq 0 - - times 512 - ($ - trampoline) db 0 - -startup_ap: - cli - - xor ax, ax - mov ds, ax - mov es, ax - mov ss, ax - - ; initialize stack - mov sp, 0x7C00 - - call initialize.fpu - call initialize.sse - - ;cr3 holds pointer to PML4 - mov edi, 0x70000 - mov cr3, edi - - ;enable FXSAVE/FXRSTOR, Page Global, Page Address Extension, and Page Size Extension - mov eax, cr4 - or eax, 1 << 9 | 1 << 7 | 1 << 5 | 1 << 4 - mov cr4, eax - - ; load protected mode GDT - lgdt [gdtr] - - mov ecx, 0xC0000080 ; Read from the EFER MSR. - rdmsr - or eax, 1 << 11 | 1 << 8 ; Set the Long-Mode-Enable and NXE bit. - wrmsr - - ;enabling paging and protection simultaneously - mov ebx, cr0 - or ebx, 1 << 31 | 1 << 16 | 1 ;Bit 31: Paging, Bit 16: write protect kernel, Bit 0: Protected Mode - mov cr0, ebx - - ; far jump to enable Long Mode and load CS with 64 bit segment - jmp gdt.kernel_code:long_mode_ap - -%include "startup-common.asm" - -startup_arch: - cli - ; setting up Page Tables - ; Identity Mapping first GB - mov ax, 0x7000 - mov es, ax - - xor edi, edi - xor eax, eax - mov ecx, 6 * 4096 / 4 ;PML4, PDP, 4 PD / moves 4 Bytes at once - cld - rep stosd - - xor edi, edi - ;Link first PML4 and second to last PML4 to PDP - mov DWORD [es:edi], 0x71000 | 1 << 1 | 1 - mov DWORD [es:edi + 510*8], 0x71000 | 1 << 1 | 1 - add edi, 0x1000 - ;Link last PML4 to PML4 - mov DWORD [es:edi - 8], 0x70000 | 1 << 1 | 1 - ;Link first four PDP to PD - mov DWORD [es:edi], 0x72000 | 1 << 1 | 1 - mov DWORD [es:edi + 8], 0x73000 | 1 << 1 | 1 - mov DWORD [es:edi + 16], 0x74000 | 1 << 1 | 1 - mov DWORD [es:edi + 24], 0x75000 | 1 << 1 | 1 - add edi, 0x1000 - ;Link all PD's (512 per PDP, 2MB each)y - mov ebx, 1 << 7 | 1 << 1 | 1 - mov ecx, 4*512 -.setpd: - mov [es:edi], ebx - add ebx, 0x200000 - add edi, 8 - loop .setpd - - xor ax, ax - mov es, ax - - ;cr3 holds pointer to PML4 - mov edi, 0x70000 - mov cr3, edi - - ;enable FXSAVE/FXRSTOR, Page Global, Page Address Extension, and Page Size Extension - mov eax, cr4 - or eax, 1 << 9 | 1 << 7 | 1 << 5 | 1 << 4 - mov cr4, eax - - ; load protected mode GDT - lgdt [gdtr] - - mov ecx, 0xC0000080 ; Read from the EFER MSR. - rdmsr - or eax, 1 << 11 | 1 << 8 ; Set the Long-Mode-Enable and NXE bit. - wrmsr - - ;enabling paging and protection simultaneously - mov ebx, cr0 - or ebx, 1 << 31 | 1 << 16 | 1 ;Bit 31: Paging, Bit 16: write protect kernel, Bit 0: Protected Mode - mov cr0, ebx - - ; far jump to enable Long Mode and load CS with 64 bit segment - jmp gdt.kernel_code:long_mode - -USE64 -long_mode: - ; load all the other segments with 64 bit data segments - mov rax, gdt.kernel_data - mov ds, rax - mov es, rax - mov fs, rax - mov gs, rax - mov ss, rax - - mov rsp, 0xFFFFFF000009F000 - - ;rust init - mov rax, [kernel_base + 0x18] - jmp rax - -long_mode_ap: - mov rax, gdt.kernel_data - mov ds, rax - mov es, rax - mov fs, rax - mov gs, rax - mov ss, rax - - mov rdi, [trampoline.cpu_id] - mov rsi, [trampoline.page_table] - mov rdx, [trampoline.stack_start] - mov rcx, [trampoline.stack_end] - - lea rsp, [rcx - 256] - - mov rax, [trampoline.code] - mov qword [trampoline.ready], 1 - jmp rax - -gdtr: - dw gdt.end + 1 ; size - dq gdt ; offset - -gdt: -.null equ $ - gdt - dq 0 - -.kernel_code equ $ - gdt -istruc GDTEntry - at GDTEntry.limitl, dw 0 - at GDTEntry.basel, dw 0 - at GDTEntry.basem, db 0 - at GDTEntry.attribute, db attrib.present | attrib.user | attrib.code - at GDTEntry.flags__limith, db flags.long_mode - at GDTEntry.baseh, db 0 -iend - -.kernel_data equ $ - gdt -istruc GDTEntry - at GDTEntry.limitl, dw 0 - at GDTEntry.basel, dw 0 - at GDTEntry.basem, db 0 -; AMD System Programming Manual states that the writeable bit is ignored in long mode, but ss can not be set to this descriptor without it - at GDTEntry.attribute, db attrib.present | attrib.user | attrib.writable - at GDTEntry.flags__limith, db 0 - at GDTEntry.baseh, db 0 -iend - -.end equ $ - gdt diff --git a/bootloader/x86_64/unreal.asm b/bootloader/x86_64/unreal.asm deleted file mode 100644 index 691a892..0000000 --- a/bootloader/x86_64/unreal.asm +++ /dev/null @@ -1,54 +0,0 @@ -SECTION .text -USE16 - -; switch to unreal mode; ds and es can address up to 4GiB -unreal: - cli - - lgdt [unreal_gdtr] - - push es - push ds - - mov eax, cr0 ; switch to pmode by - or al,1 ; set pmode bit - mov cr0, eax - - jmp $+2 - -; http://wiki.osdev.org/Babystep7 -; When this register given a "selector", a "segment descriptor cache register" -; is filled with the descriptor values, including the size (or limit). After -; the switch back to real mode, these values are not modified, regardless of -; what value is in the 16-bit segment register. So the 64k limit is no longer -; valid and 32-bit offsets can be used with the real-mode addressing rules - mov bx, unreal_gdt.data - mov es, bx - mov ds, bx - - and al,0xFE ; back to realmode - mov cr0, eax ; by toggling bit again - - pop ds - pop es - sti - ret - - -unreal_gdtr: - dw unreal_gdt.end + 1 ; size - dd unreal_gdt ; offset - -unreal_gdt: -.null equ $ - unreal_gdt - dq 0 -.data equ $ - unreal_gdt - istruc GDTEntry - at GDTEntry.limitl, dw 0xFFFF - at GDTEntry.basel, dw 0x0 - at GDTEntry.basem, db 0x0 - at GDTEntry.attribute, db attrib.present | attrib.user | attrib.writable - at GDTEntry.flags__limith, db 0xFF | flags.granularity | flags.default_operand_size - at GDTEntry.baseh, db 0x0 - iend -.end equ $ - unreal_gdt diff --git a/bootloader/x86_64/vesa.asm b/bootloader/x86_64/vesa.asm deleted file mode 100644 index b649e4b..0000000 --- a/bootloader/x86_64/vesa.asm +++ /dev/null @@ -1,207 +0,0 @@ -%include "vesa.inc" -SECTION .text -USE16 -vesa: -.getcardinfo: - mov ax, 0x4F00 - mov di, VBECardInfo - int 0x10 - cmp ax, 0x4F - je .findmode - mov eax, 1 - ret - .resetlist: - ;if needed, reset mins/maxes/stuff - xor cx, cx - mov [.minx], cx - mov [.miny], cx - mov [config.xres], cx - mov [config.yres], cx -.findmode: - mov si, [VBECardInfo.videomodeptr] - mov ax, [VBECardInfo.videomodeptr+2] - mov fs, ax - sub si, 2 -.searchmodes: - add si, 2 - mov cx, [fs:si] - cmp cx, 0xFFFF - jne .getmodeinfo - cmp word [.goodmode], 0 - je .resetlist - jmp .findmode -.getmodeinfo: - push esi - mov [.currentmode], cx - mov ax, 0x4F01 - mov di, VBEModeInfo - int 0x10 - pop esi - cmp ax, 0x4F - je .foundmode - mov eax, 1 - ret -.foundmode: - ;check minimum values, really not minimums from an OS perspective but ugly for users - cmp byte [VBEModeInfo.bitsperpixel], 32 - jb .searchmodes -.testx: - mov cx, [VBEModeInfo.xresolution] - cmp word [config.xres], 0 - je .notrequiredx - cmp cx, [config.xres] - je .testy - jmp .searchmodes -.notrequiredx: - cmp cx, [.minx] - jb .searchmodes -.testy: - mov cx, [VBEModeInfo.yresolution] - cmp word [config.yres], 0 - je .notrequiredy - cmp cx, [config.yres] - jne .searchmodes ;as if there weren't enough warnings, USE WITH CAUTION - cmp word [config.xres], 0 - jnz .setmode - jmp .testgood -.notrequiredy: - cmp cx, [.miny] - jb .searchmodes -.testgood: - mov cx, [.currentmode] - mov [.goodmode], cx - push esi - ; call decshowrm - ; mov al, ':' - ; call charrm - mov cx, [VBEModeInfo.xresolution] - call decshowrm - mov al, 'x' - call charrm - mov cx, [VBEModeInfo.yresolution] - call decshowrm - mov al, '@' - call charrm - xor ch, ch - mov cl, [VBEModeInfo.bitsperpixel] - call decshowrm - mov si, .modeok - call printrm - xor ax, ax - int 0x16 - pop esi - cmp al, 'y' - je .setmode - cmp al, 's' - je .savemode - jmp .searchmodes -.savemode: - mov cx, [VBEModeInfo.xresolution] - mov [config.xres], cx - mov cx, [VBEModeInfo.yresolution] - mov [config.yres], cx - call save_config -.setmode: - mov bx, [.currentmode] - cmp bx, 0 - je .nomode - or bx, 0x4000 - mov ax, 0x4F02 - int 0x10 -.nomode: - cmp ax, 0x4F - je .returngood - mov eax, 1 - ret -.returngood: - xor eax, eax - ret - -.minx dw 640 -.miny dw 480 - -.modeok db ": Is this OK? (s)ave/(y)es/(n)o",10,13,0 - -.goodmode dw 0 -.currentmode dw 0 -;useful functions - -decshowrm: - mov si, .number -.clear: - mov al, "0" - mov [si], al - inc si - cmp si, .numberend - jb .clear - dec si - call convertrm - mov si, .number -.lp: - lodsb - cmp si, .numberend - jae .end - cmp al, "0" - jbe .lp -.end: - dec si - call printrm - ret - -.number times 7 db 0 -.numberend db 0 - -convertrm: - dec si - mov bx, si ;place to convert into must be in si, number to convert must be in cx -.cnvrt: - mov si, bx - sub si, 4 -.ten4: inc si - cmp cx, 10000 - jb .ten3 - sub cx, 10000 - inc byte [si] - jmp .cnvrt -.ten3: inc si - cmp cx, 1000 - jb .ten2 - sub cx, 1000 - inc byte [si] - jmp .cnvrt -.ten2: inc si - cmp cx, 100 - jb .ten1 - sub cx, 100 - inc byte [si] - jmp .cnvrt -.ten1: inc si - cmp cx, 10 - jb .ten0 - sub cx, 10 - inc byte [si] - jmp .cnvrt -.ten0: inc si - cmp cx, 1 - jb .return - sub cx, 1 - inc byte [si] - jmp .cnvrt -.return: - ret - -printrm: - mov al, [si] - test al, al - jz .return - call charrm - inc si - jmp printrm -.return: - ret - -charrm: ;char must be in al - mov bx, 7 - mov ah, 0xE - int 10h - ret diff --git a/bootloader/x86_64/vesa.inc b/bootloader/x86_64/vesa.inc deleted file mode 100644 index 7f85476..0000000 --- a/bootloader/x86_64/vesa.inc +++ /dev/null @@ -1,90 +0,0 @@ -ABSOLUTE 0x5000 -VBECardInfo: - .signature resb 4 - .version resw 1 - .oemstring resd 1 - .capabilities resd 1 - .videomodeptr resd 1 - .totalmemory resw 1 - .oemsoftwarerev resw 1 - .oemvendornameptr resd 1 - .oemproductnameptr resd 1 - .oemproductrevptr resd 1 - .reserved resb 222 - .oemdata resb 256 - -ABSOLUTE 0x5200 -VBEModeInfo: - .attributes resw 1 - .winA resb 1 - .winB resb 1 - .granularity resw 1 - .winsize resw 1 - .segmentA resw 1 - .segmentB resw 1 - .winfuncptr resd 1 - .bytesperscanline resw 1 - .xresolution resw 1 - .yresolution resw 1 - .xcharsize resb 1 - .ycharsize resb 1 - .numberofplanes resb 1 - .bitsperpixel resb 1 - .numberofbanks resb 1 - .memorymodel resb 1 - .banksize resb 1 - .numberofimagepages resb 1 - .unused resb 1 - .redmasksize resb 1 - .redfieldposition resb 1 - .greenmasksize resb 1 - .greenfieldposition resb 1 - .bluemasksize resb 1 - .bluefieldposition resb 1 - .rsvdmasksize resb 1 - .rsvdfieldposition resb 1 - .directcolormodeinfo resb 1 - .physbaseptr resd 1 - .offscreenmemoryoffset resd 1 - .offscreenmemsize resw 1 - .reserved resb 206 - -VBE.ModeAttributes: - .available equ 1 << 0 - .bios equ 1 << 2 - .color equ 1 << 3 - .graphics equ 1 << 4 - .vgacompatible equ 1 << 5 - .notbankable equ 1 << 6 - .linearframebuffer equ 1 << 7 - -ABSOLUTE 0x5400 -VBEEDID: - .header resb 8 - .manufacturer resw 1 - .productid resw 1 - .serial resd 1 - .manufactureweek resb 1 - .manufactureyear resb 1 - .version resb 1 - .revision resb 1 - .input resb 1 - .horizontalsize resb 1 - .verticalsize resb 1 - .gamma resb 1 - .displaytype resb 1 - .chromaticity resb 10 - .timingI resb 1 - .timingII resb 1 - .timingreserved resb 1 - .standardtiming: resw 8 ;format: db (horizontal-248)/8, aspectratio | verticalfrequency - 60 - .aspect.16.10 equ 0 ;mul horizontal by 10, shr 4 to get vertical resolution - .aspect.4.3 equ 1 << 6 ;mul horizontal by 3, shr 2 to get vertical resolution - .aspect.5.4 equ 2 << 6 ;shl horizontal by 2, div by 5 to get vertical resolution - .aspect.16.9 equ 3 << 6 ;mul horizontal by 9, shr by 4 to get vertical resolution - .descriptorblock1 resb 18 - .descriptorblock2 resb 18 - .descriptorblock3 resb 18 - .descriptorblock4 resb 18 - .extensionflag resb 1 - .checksum resb 1 \ No newline at end of file From df80a0bc56c25664cc1e97b53360b61315e6569d Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 5 Jan 2017 11:28:34 -0700 Subject: [PATCH 050/522] Move isolinux to submodule --- .gitmodules | 3 + isolinux | 1 + isolinux/COPYING | 340 ------------------------------------------ isolinux/isolinux.bin | Bin 40960 -> 0 bytes isolinux/isolinux.cfg | 6 - isolinux/ldlinux.c32 | Bin 116492 -> 0 bytes isolinux/memdisk | Bin 25628 -> 0 bytes 7 files changed, 4 insertions(+), 346 deletions(-) create mode 160000 isolinux delete mode 100644 isolinux/COPYING delete mode 100644 isolinux/isolinux.bin delete mode 100644 isolinux/isolinux.cfg delete mode 100644 isolinux/ldlinux.c32 delete mode 100644 isolinux/memdisk diff --git a/.gitmodules b/.gitmodules index 98d2765..f706dda2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -67,3 +67,6 @@ [submodule "bootloader"] path = bootloader url = https://github.com/redox-os/bootloader.git +[submodule "isolinux"] + path = isolinux + url = https://github.com/redox-os/isolinux.git diff --git a/isolinux b/isolinux new file mode 160000 index 0000000..3cf79d3 --- /dev/null +++ b/isolinux @@ -0,0 +1 @@ +Subproject commit 3cf79d335400af8fc3a87a13f0ae12777a766b3b diff --git a/isolinux/COPYING b/isolinux/COPYING deleted file mode 100644 index 60549be..0000000 --- a/isolinux/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) 19yy - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) 19yy name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/isolinux/isolinux.bin b/isolinux/isolinux.bin deleted file mode 100644 index e099c90fa014ba2aef5d5f032ef42ae441282c73..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40960 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 diff --git a/isolinux/isolinux.cfg b/isolinux/isolinux.cfg deleted file mode 100644 index 20e6848..0000000 --- a/isolinux/isolinux.cfg +++ /dev/null @@ -1,6 +0,0 @@ -prompt 0 -default 1 - -label 1 - kernel /isolinux/memdisk - append initrd=/livedisk.gz diff --git a/isolinux/ldlinux.c32 b/isolinux/ldlinux.c32 deleted file mode 100644 index e4330130d0d4debabd6517b70de8492bc09159d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 116492 zcmb<-^>JflWMqH=W(H;kFwcj9!GwW<;mu(%kHLgNfq|JpgF%Er7$OhTz`(#@aF~%n z<_#kQJ4j4`fq{vEfx%)QBOK3QU|;}YHU}UjEpP}N~>d-7!ELUSO_pU zF*+zI2&OSGFfcW8FmVQThBI;=GH@_p=wfhSP`JR&m~watLq`ygqXI_*(+Nfu1|~;F z1{Y2?#~Q^6N(?3qix}@JEfi>BU|@Q|!p|VUz{qiC@exS{FLeQi76lFl0mnwp3XUv> zNzxk(cpVrR)EK#38CX^r@oZ3FP~4zW#KEz^mp3Af(ScEbfkA+wg@IFrkwYO-g@KW! zF~~w#vB41(79bDhGB7aYF)%O`GB7X{F)%O`GcYiefFz)}l!1Yv49W&k6(E9vfuWj# zfuWv(fuRA)Z)9L#XkuVsXom7zpfreTWnf@v12GsF7lqjrHbBjQQJWbU7`8GnFl=LBVA#&U zz_0@*!N9<pfH?0b4|vdq6XEg~!>i;@K{H1isNV3QGbuo?@g8gVd3wgaXXLS*t8^1d*+6>DdO|4o|Z2wyrg^W%?s_HTFvsR%u|z= zTszLk+(n7F0+_oRR&i?3dK!GC6H ztor8zN-OR7lQ~k_WD8x)IG5$j(=48V=57lM5vfYlK^T*Ag zq$bamM_qikPI`Y~Z$n8FFK4)n--W8Sr&Y&8E=_O_h|!$FubE>g_s#rL!qQ)52D_!_ zb#N~*KT#KUd$LTM^0tlp?Hsa?{NvwfpK_^V%Es6Se>+vv=I{OZOy$^zmy?)krDa#Y z*In_Vv?%B3@1nQ^Ssk+N)>{9T2I}#5ncC~uUQ%M*R=Vnml()vFMc;)!i#_`)RKvDj zq|4OaRZ^|++s4p8Yh(*P1b$<0e5juErSY^he|Ky6nOPj&98!XcF01tqJXW8Qs&(^0 zL%?O#4f2)U?f?CF-)UwoP88=@^Rs_Tv6yWj#~H(a$87|-Q+d`$Pv!V=r_Ik$D|_-{ z<~{MJxbA%y;tyyHG%$PSaI!x{&+G1|OO>lOy<=N)j{{^!~VUhe@xAXVS$jfu}l`7p=IgqZ(RL8eBWOGsDE}QS_kzd%o^JqId6q z-}qj8&dE3KT5~v#Iycu_wp>4VYqHGsiLZ3-th;q2GDd%&I@c}Ro%x~P1z9sS3)dyP zeskBFQ*1M(ro?7Sjc?kU2{&EXHnQuN@CWN1ewcfxeHz&)SSu%t7{QD`pDyJQ2>#%vWGwV8}(&zX!>EAo&)MrBDMvObs;iQ@Eg#Q2(DpGmjt1 zJdl1+`3}#Um;rf-$!%rL^S9VIP5m4+ z^A@4W7b3YA zNAr&YC)9FidK5x%!SSVw#-E7hpByyzO+z!k7>zHB=AM;k?k_>}pC+37#L&Wj2AX@^ z(A;|;&AcaQ?&U%=F9yv#OYDGDt8mFbFaTFl+?*?+qikuMKivJU0Wwlv@b%CNMHERNrP`sDYaIhLeGT@iYU& zO(uVKE^0@F&k9ZkhM9*M7?wlb@6FA?kaG(ZHjwbG zWnf@fv4@dC1gxKjfs3Dk!B32l!47J^1}6i9emNt!pAB-~ZC(b3Q-2v45~1>W91IMK zs~H$(vq8)|$A*y zF=At2I5UNTK?!QU6CVS^A4W!S-x_4UHX8%OsmYK&D2TtCgMoo#AHqIR_TcnkUqzH%@y2q2}`3~mO7@3$di4Iumfa4|4c-eh0^jfg$A< z0|Tg-1gY=f1H~mH!v?7PtN0iguCXw}^G7j11B0&n#IADpdbmHU{LU4dp*)XJELq7m?rp^D{7fh+$+}}xPp|wLE~`>Ncm5Mje((KG9vzD*ccd=PeznibNCn-Hn2m+M?vmSRsjZv2T103voSD4Pe+tTj2sLM zZ;xjco-O>-ZQ|{BMT=3L&jDHhB#(O{sD~#E@)$5xCHfI zm;eLAjci5+GbsNiD+9x^NsuvKkojjA85rL6BGN|}0|P_n9R~22F-Sg=kAa~@oRJ}d z8)E))b_Rx`Weg0UX#kM?XYlqv8fCU`=S27&cwj5X&Rz^qtC^_V0nvyK@%#!gr9+- z&V`WyG|mmuug%K9P}Pg5Pkyj5FdUu$E_cRX!!=yKe z`ZS%5f#JbUMurnipgh3CFrA-);esh8@uGILpewuy_IkgEBO{ zUNSK-EI9;AKLQNlYzzzr(-7s!5=I6F_dZ1X=qDQkL&;1A27jpkjvNurV-n&On&Q!^6NJ|Bitn8Y6_9xckpDB-85sDMLdNbvd^HXR1`(w8^IbLu z2Kku?`(*?e7&PJ#_4hYU28NAiAY=6){o-5<3|i+A@!`(Tz%WULk-;Bo|57#v289`r zxh9bM=Ufa7zi%)w)It3l%Fe(rXE6gq5i~wrIT#o|Amv9TUIqq(_Y4eLQ1u3U3=Cfx z5#_fW3j@Rdw}|$BA|C_80cA#b{^a3eV2C`&z;F?&|2QK9!BkDs-9tH-^*9;8WQ1uFY3=Hp(!e5zqX&d0nVXoN8edXbkjhY8Qk0jRTL7Yy3o03M@)J|yvr~)mQgc8;c_6XW ziqz!Nl2nGY%)FF>#F7k#wB(%p;#7u|)U?FXoRawD+!O}q{JgZxbic&hREGHM#H9TE zT!xg?viQWj;>_aIqRhmc_;Rp7aY;&YeqMYLLw-SOUUGh3aehuJLwtO3WpPesUTH;q zacW6CR0C8tJ~J;Zp8>8QJ+&k;r3}F@M&l=@l*N}9WtOBeWGAJ>7iVOqm89h)rWZ5B z$LAKumt^Lq7BQr!mc(bLRx+d&l$I2Oc*V&@si}FznN_I_PM-e3U~eSn7gQEyre~DI z7nc-)l_oRfrsn46mw^KfBnWp@Qes|SY7s+nVopweGAP`VGm03BQXyO<-(?mg78IoB zrGSjg%mX_rC9^Cg)0iQ+ve*$URm_lBaGhc`5Or9K=wX2cqJ0^HWN5Qj6n@GxL&D!3hEs z9t^pOdFeT+@p+)!Qe2W)R1%+)0#5!Q|D+Zb}IEiETCJ}E!HB)%vYA(2*;nu;(0 zo}MAXsktD#GV?M^iV}0visL~n1`q+^f_<1+l$?W~fRn%8xHfO)m!LBSSNWcyKWT35C$&%)In4cSl(2 z_Dw9#MwpV8UzD60Uy@o;0t)g}hA?+Wx6GVWP#8d&0VPE!i4&&87o?^vJuwB6X}}>4 z%7DqpDF9SnU}W9m%3??gK+4SU00ikkPv)SKwj{qaH?abobs4H4#RE9~FqEZ16K;GO zI1hnJrTl^thWvt(%)As3l~|MxqM(AQMc`sAzn~;OCqFNpA*(1cFU7=yAs0%6f*T|d zU!0nn!jK0Q&4JSK@x`Dt0!jV3skzCZVje_i6oKNa0Lslx%>{9b%M%M23LxpSuozS( zfDARUU?_$fS5{n{oR|krZ}E8`mlanQ$EOw*fm0>O+sTO~proCbQVObQ3c$4rNW3IJ z6BHc9B}K)lAeo|qq@rw)%Ho1N5S0w25$a0v!SW^f;OYrn0v4APfyzgy062Whpn+Ld z3}Yn1SjibhMX3cjpn|n5sT3CKnR%%t@p&cri3}+j$p!HRiOJdVX_=`xDM);fU}_0O zpfnG}LskM60STvqJqxoXr?{jDY&QOq_larj02u=}T8YBzLZs2Mc z%7N6ud8Iiy@kL;9FtZ$#*1-inwB|%A53$w7Ak(4ZAgvWJHn`S}2iN(KvI5F3C@lfI z3c>}I0pN_yfZ!*krWPP^LBW8;1$!FoTu^fYq#tB0jGbRl%utY=32r$+>jzLB#}FT% znO6d;ks0FSLGsCI>5vu=C~ravW^f4{pH`Hg3sM0p?21c@azKf{Dh=!gkkaIw#NuL9 zmGPM=;AR6BQBWHRWLSJkYFTD-Dnoi=Nk(cBs0Pd|$;{77%mGV6+zEDeQEFmJ5(Buv z1-UXMKQ}Qm4=e-9Q(y*2Ne-w$02OYf(24`%?8KbRL{QTPq!pwL5`pnanfZ`F0g07^ z4FLyY5`u{&n!`|GVFr$|__TsjhJyTZP~I!a2UXgo(Dq4ud}(fe3aF)$l3AP$3R*+s z_#$wl0xSRuse;6!#N1+r9FS)iz@i}QPC2Xa=`*Kvg}$ zloF6tB`|~FenV+`6d*M{pe_Vw7;uJ#Ye~xlc0xrIii;`hY@uFm7 zBZg!U3AYP{XJ*1sng_FsAu}%xVHK1E69ie6k_wg&PAzfCOa_;;MU^n81f>>(YHhd* z4{(tHlMN`!%mw#kLFR{)=E2zzS66|WF}cO*aOIF94r(9B>qc@foK!b(r?koy+}ekF3F1^_juFh4P^+MF5LZJvsJ?~@x~G;v zJqi^FuFOk@83tkpY}HF*zILlz3zTWHu-^ zp!$%)0NR9sRr{dC32OAjC*|ZPXERiR>snCXG{2}A)G{q90rylvywp5UEtCSPK;SYE z9!Lh-ZPEiJCh#~IXgL1LCdhaUXr2JXXV?tkb3kbUC@le{6`-^Rl=gtqK2SOUN{2w{ z2q+x`r4yiZ3Y2bu(k)QB14{Qm=?PGJ3Y4A!rRPBD1yFhklwJX)4?yV?Q2GLtz5%5l zKiaD7^uLHxl2r8%H950n;w(jrh=0!qt3X$2^) z0;M&ev<{RufYK&V+5$@3Kxqdk?ED4hbOGoW-1lrDhM zB~ZEoO4mT?1}NPDrF)?C1SmZPO3#4ObD;DBD7^$quYl5Pp!5bPy#-3|fYN)Q^Z_V+ z1WKQQ(ifog6)1fJO5cIf51{lDDE$ITzk$*pp!63g{R2w>fzk}Sq45o+IiNHTloo)} zB2ZcaO3OfL1t_for8S_m4wN>4(k4*a0!rIJX$L6n0;N5mv=5XHfYKpQIs!_^Kkr$Ff$Pzy^pmYV4u7T1GP`U+5 zcR=YLC_Mp6Pl3`ip!6Ily#PutfzlhG^bsh121?(7(qEu7$6koLHK4Q!ly-p9K2SOW zN~b{S0w`Srr8}VX6etZ^rw1zMmO%L{p!6Cjy#Y#Zfzmsm^d2aE07@T$(ifog6)3H- z5902OLl7D??+>zX1(d%AN}qtzpmm)f`72QV4JdsFN|gN5q7N}J zh=6ES1_lWbt;WD01ESR#7!*LXCIf>8h}L0X&;ij485j&ev>pS435YgiV6XtuCJYQV zAli(9!2v{rK(sXjLkNgI!@v*$qB|HEVnDPVBSQj+ zc4S~k0nyG33>hGrmysa{M0+zZ6o6Oc7SLzMut5gnuUSk0Ephfz;FaaS1>S~0MS1f7|wubRtAO( zAo>Oa!xa#Hje+3?i1uYfPvu;hz4yKJiy4n&dtEU0-|{s7&t)mP6h@Z5WS6oK>$QgW?&Ej(bE_h zBtWz zt-!#L0;2ygFl2z}B@7HXAX<@up#VfHF));XXk`Y53J~4Ez)%CCRTvl=Ky(iSLkoy@ zVr1w5(Haa4Js^4=1H%Lmt;N7F1w8ws14QRDFzf-*7a151farG&3`an;7$d_85Iu{5;S7j2 zVqmxcqWu^du7K!e3=B6w^j`*sJ0RMaf#Cs&?qgth0-{YB7+!$rQw$7mK=e@th7TZm zGXujH5N*N0@B>6IXJGgPqCpGL4>B^aw=yuWfM^>A1`ZHy%fP?`qK`2!2!Loi1_luj zZO_0U0isnI8Dv28Mg|525beOgpaP=jGcag?=q3gR9T3gO$Y21XofsHQK=fk<1`80~ z$iQF&qFopm96+=y1A_~Qu47>E0MT<97<@pqKO;i`h@Qm25CWpz7#Jczv^xVs42bq% zU`PPbo(v2rAli$8Ap=BrF)-wS=xzpv0ub%Xz)%9B{TLW3Ky)M{Lk)=bVPt3k(E$t$ zEg(9OfuRFLTQV~Afao9wh6x}#n1Nvmh`!9gFatzeF*3{n(V+|s3qbT#28Jad+Le)E z1&H=!WLN{D!x$JgfM{bzhAkj^A_Kz?5N*TAum?mhWnee}q9qs^j)3S~28I(LI)Z`W z42X_oV7LIHqZk;jfM|P0h8rOIBLl-75FN|F@Bl>bV_0v1V86=1@B_q8U|{$IqE~=6aWgWoe`8=^ImF1op2Wbw0ix$IFz|rrWCjKS z5S_xnAOfO4GcZVi=qN@884w-J$e;kC!xprz6;3&4CGkUZ$Xerps05BhPszV0ofP|M0U_MA|252epO9L?92Bbd$WWEBJ4>BqPX<~oSp&N{{PYd%m?j?$pCHrf2jcGgS?Uf+WP-e z0L%xiBF*>!GLHew2YD?6w6*``hrb~IgHBDz0PXF0`2frZc{PKBk%8gm1u%aK$bF#g z{4WoH`5>=nfR@_6+yLf-PEE)FwR~PK0P{gXkpbGK|8fGDzXYTov=#ql1DFpAnhemk z`N%vS-)8-U~+zXUUei;Dfmw@C!TQFZbfcc=Ln{flA-T=(60m*~5c)wHt^Fc{D z;{`}w0L*Uz$$tRx8Nhr{($4q+;(z!F@;_)-UIqg*1H;P)U_L0RXK;Y{7r^`}ApHU$ z{sAx_l=L$sK>Q70{v43J0*Jo=%m-zK3=I%}0+ z9YFj9FdvjvGCV;105E?GNIn3>cL4K2tI{(fKzsu*AGA9?BLT!$0P_!k)PuGRzZ3xT zkAV0EAbAEbAC$E+DnR@XKS2Hm?LNq80P!Dy`Jk+p(E;LL0Q0Ya^iKfs4}kfgtd}tZ z#NPns-vP;kwgkLf0Oo_TV#W%P`~)!n2}pheh~EI_gR*AE4iLWp%zp!tKLFwJOfaEWL_zqw`DC=h20PzjL{68T12Oz!zm=DUz881M50WhD136%dqdt{%S_#41{8IZgJ zh`#{L2NeYw8X*1zFkb~EZvf&qfcc=JA;SX1F97p(K=KYCegc>eDk?HOK>PqO-vlHd z0OC7<`JkdBBLc)X0P}4?@(Ccm0+uCD4dj0x zkbDD({{YMf6*UQI&B5#18=TOF;4$Kzs)80OC7*{r|tgLZOV=;q{Nhq2Xb{fiFN? z&l?YS7Bez*9(@67ziPhdWKrqeobvhq|8B9?OC@T}C;xX|H$3oZ-S>;0-7G4aCm3J6 zX#e&9f9ru#)^0bJ*X+&5I9^{dJP;Kf7at2YwfT*}i?b{Y42_2kLFOLo3{l}}KKtMB zKEJ~eDRve@Idns0VGFDyZ~j&#=|v5 zj0`VY!KU-KfC}5rV=pvB7#La)@V9g`Ffepyh=7gkd=K$Uuhaid7M0EqFBbm$|G)EC zmsrcC5}t-%3jFP$lG5$NH4|6hVO z#rHOYj)F*QwqW3I0UavU+YGArK>Sj!&JQm@?bl-r44ofdnEn0_a%AfP{#H=)uJgl- zFMt342Zt_8?`m*lyE1@+8ssj}@m*jacGswIApGc}!o%#M!qVxYBH-|%^ef00-99QT zou6LJ`0@WgD0Ucsbo;3Abcd*Lyl9082^?c#XXyO#;u}agC?QoMU}!!f(Cwlk@`CHv|NmeMIuC*QSwH{(e=Q0Q5ODH6 z(aocxdGMvyKTs4&fD=&gi@S`V^zK-|$k5yT3hIhd_3q|5|3O)fp@h4)S!Kun|1WsI zfZPe%&+51M}zZF;EQgsiSP44CW6#=9`9}D+xhQ*=h0&> zD$ERN&GrnXKD{m~%mJZ>CwGAYq_;T)WW{qv28PaKJ3wa~yvY0b|9?bO>$eit20MmQ zm4+G>W`+{6-sUe*Czf#aHiN3ZZid&KFUv_|NsBHoA>T|GjQ3FJd$p7+$>l`2T*y;RE7 zEe5f6^3VVOo9!7&*p7ows{j>SmXH!v^S$NuV%gr+XP6ln3~yVu({3)RLq4gw4eFJi#T4&*X|vavvC zh>Aj|kBUTZjf%rgP=m(sz~|M+T~t700Svv(M?iT4q|liy(g^C+|1VJy=xy!>l~FIIy#N0{KGyK!{?Vb#BRA-2aPWR*)pg;;ykpY!2pbl0yi%O@9iiov~3QsLZw~Go7h}YZvZ^!@t z0WU1x|NsBLL`9^xc{7-=@g7l%%Y0hbdG7nQ-n#$IM|cds9d}Uy4Ye@zHt*X3t}=M6 zOH@Q^jdp-WQLIf=YFYXBxtKVBgYE^Wz2N3uo**<|V%S|341mah~1~6`Nic6^j=uKtIc=^H2+}YZ_#FAV5k>t{_&r`1vF&d{DbkOJR<``^AA@3mP{rPgN?rh)Xr@F z!NT7PZhL^v)NB61&EEn#+^1f=`3EO|3#gIS{DX_Xr3BO(c*p|M$jjf7#>&7@Yw=>@ z-~a!cYg8l{N`%10Uw4R#Lh}hw%_;H!dT;Y;upj2W{r^7>7SAuuKxN<$KK_y@M?%j`@2*rDF3BG5!`%^A+R>A^w(WVE2mhw}8e8UdDhOAU^vFW`0@%114HXu{+7aj|NnQh zsPuX;YQF4sQE})M(daGx&-md*;oJZJ|MRGHetqfp_y2!O9TomQSCCpB6{x}x4MxTn zFT5biUTT8E&qjrTzXeocyae?KLB}gl z^0#P%#)hVVc`xPv{Quv*c?mNELvJ&Pv^>V&!VLfYwd z;IzN+)&KvI(6Y_&KceITS>NfRqSD*^6H*3gz;pL0P$lq#nZE^eWN7mbp;GSV8Wj$P zl6&1|ujP6J9yI@o;%^6S>+JSX;pk}L0hPU-Cmg`>-vTa)LFHoWw-SwRKaTDY6_L&p zojxiCFRs0Vw2r!cR18WLyVHbopDq|N8&m@DeBmG}MSVD3mcfz5etfkb{BY+23>w)gc zppo$sssAM^G66xo%|T#?3PBwAawBL|qC`a|sJA%;Eb;RN$kjYAXZ!@UEFRe2XJBC9 zZ}0l`|9_*6%0G5cAzS+koG(h9dR-YoEy@oaE;9b$_{~u`xsy29Dn*I9!pT7sxDfkcWm_W+~5sltjM#dj63|{{K-w8Il z^Y2S8kZYPv!DfWN`2W8*N5uu4-a-9{?-x7I^*a8KYCTZrume?-B~(!gT!95F9g+u{M?2I8jpaQ1mKqG3(y%qtSeF( z8G0vxRCPj0(D;hsfy3P_Du;tR4|Ykm+%6I5Vrn^1!ew}4#r;wiN2k}X3=cF|F_f}5 z{8lJu>O28ymj=K1{0-Fn2~TBY00rE&&hxvzu)rD&{;&W4?>yRB!P48zqQk(@&Cq(F zg!#Y2pU&1AP&p4S96<-wf+|5*j?Pk^<8GjVE{4uL8N&nJHY(jy+C@O6@}&~y|4x58 zr?i524$VJUOCR;Nf`&x8ZB%-$aw4N+s{_pswv*#*Eq}zi9ApjZ(acVxm(fo_2^xA7@!*AU! zpI3bT|Nn)70s}*5%T`bbxHbP{Eq!iypnJ+;jW7TIcTNF^g+ucXzS1|xz}{wjFO#%FD$=;Vs36SwBhQ+vMUaB$nmLn|Nl4FX)u*2v>qst z>2hFfIZz_n{NO(SwhO%?)0?YA7)seX+;lpNM55#34}%Q)@C9U02*{vg-3=)$3=EcS zpaG;BgVqD3JjdHWBA{NtYYxT(onT%!nCuk+oi@$T?I!SIDJWID3G4z*Rzcd!!l2Az z&^--gP-lQjx1T_76=UZbH^b}8pdLu`8=e=&U@g-@T8?!dZK!2XC}Vbg z{k`*r<_Az6y4wd7x&KT2y4^WIBM{v@DxHTqKfIXo64VwhH3Ic>yG2wQYy=oeRYU)m zi$F`AUKbUSfEWMez};;wc?O1V7Zr)-BLc74yXzHRuj~BKe1r#_BSG$Hd;>c2;sq$4 z8xQkQ$#?jp@1M&_uUAysgH-iQmJKY41x#=);H`{2TBQZUzlEwjL*#N=iAKcbkCxUZQ&3 z4K%#T(Cx zx!p&o1}lb=$ld_PV+;zQjz>332WS|j z^TII~6?Vq|E-C`uJ}LrTp8q?1RM=WhmS}hRsIWD^RBZSeTgKZ^qr%Qmdg~ZdywmIR zy-tiExel(*Lm<5juMZt#VEE6X^0FM%jRx1~%{3|_3?-u7E-E4o7P_T84Hb+Gu-d+N z^2dGP0f|yJNKAHj^MFd`pG>84;Q>MaH-pBldz%A50o3az67WJ#1~f1t@!ACxcyJZ} zw{$=G464h0;0js63T0kPcQ=E~fG0tb*PPwWE}#P0O{RIb4mg&Do9i?fOL@CnL7Cg5 zvlTSh3`xu{E=V&lKumaX6wCz0!;4*DCMXtPtOqke@&958mj~8YTv$?uiR2o31(Ux$648LV~;5Ad{ z2S^FdzwbixD}&}=oMpnzClvVi9cX@$2J`9rBcA?klLh}#KGUi^V zm50NEI}h{kV|eih)c-!lzt5TR#dQ$#yvx7OmElF>e~`~hm|b6g=+y6gp?RY>;BWIUUjBAaFOPZ4v;feE&@=vh z%rB}zW<#t2El%h>&cDx@=|$@Q|NpbU2_AeVkbOX~cM9lql>gbs1rI*p=w)Gg2^x?D z>9q&x1!-V>VFJ={Uhv>UiR=S{2OkLZ+Ax9*k^w0J8PEJe5TpcTCI`q&9`;@qzSoue zKnHgkUi$v6^H}GN7YrcP$9r{*J72u`0xCHV_qv!eymSNH@Sf`7MLht0r zo&W#8Py&yj@wYUyFff3I*c6Zy#DNqrLKT1xc7s+wCFd`B z{}=Pc85lajaxYy$g*ZrgDNnbH3RuThkd9oC4mXzWP@ZmAju(~R z|Nrj>Hv}6j82DQm|NsC0;-NSLL$@nWcL7W12WV*uX_S~g0|i70+kX}nhu3dF9gk98 z!vn3~N{s)z{ptMhS_jf}22Ce`rVzAQR9;LMV_@h!)Wz3wvV^-Wc) z7$D8hm;InIzsV^(|Nrm&@Ph3t*n%*Ki(W*490GOw&xim2zt{*e4eZ)(h(`ne{r}(X zz+&yn!ruxS26&+g(h|x8F#uNHIkCLd09%sODnnne?#~3W%36Wm~k=H)f44QUiggJ}ZbF1uR(N*6YUh zLhS)05A{w41=$NuuoQnwEoh*k71XYO5iW`ds~`9O|9`PT1k|7g$-N8%+cg(r?AcEs z&-1rz0=1pb-3Obi((9t4@?r{TeEE1ch`9|ap2ZmcLJFMgK%?;d9p6BW*bfe!EGqmh zk3sC0Amt4f3?&MX;-Ooh^TmssU%~S!DlaO985lYbb~b~Gk4_&I7Em=b4Kz~WqN37Z z!2qh8_*-T(ftpsJvZY&~^TdleAkC9OI=Y=egG@}F7a#__ECMN3hK$c@E2iV=yg$1cySEW(*TRT3;61o^*&|9JBiW(H6N!0-|@ zyJYykd&=)6pTSC2ftB#L2D30QxHtc2Eq(H`1XKh~=7Jc}1(64j`E~CGwMe0Pzx96! zKR9E9W*d7QL1QzZax3E=IFuE7Co}E(|Nn(IMEg`172#eN6%9};y>~PFuK)kxB`K(p z{zB;%$f5i#Gk$?XljVgX)R@jsFE}7ZwATFk{~ta(`2Aw9y#fQ89|9660&>*Sf-6bk4-99QZ;HgQDP8OAyrT_o`?_z5{pb&rx z0AwGiI4}9i(A@^=I<_7t;eWA4h=Jiam1LcbY=dKpVs` zCs6L}xby%23kN|4hR)-#Y%kUgZh^lz0218|Y6QLnttRQ+3{K~4FIIrW?OyKr0V+DS z?*m(73^CFOWTYv`$hQKZnJ}o4{4M?9sWxycG83eIGl==J5^MyhI_&)L;sa>#|39c+ z1FdT7bz^<;<~G=`pk})WICI*30u5S$0`Nr*XtoO62{XI|7RUw*fZD&un?dbr(1gu# za2E^|A;-a9g0MhVLs+277QzB$1P}| zRR|DSP_+VLyU_SQ?Kk6(6!i%CyNMErdV$tJbz zphg1wi{H2Y|9`QW9~5%EJ3zM-bx#ffwN@@z{^M_TW@lhH#>DVqHE3|+!wV$=28Ndw z-$8KzEs57dORVDtL_|NWq8 zcDM!&kOojitnfk?ssZdp!%H@KC3?F+odlbr5>>-XHi`UG4>`S-22T%y%>di{nhPP& z4Ia!3>ipUH=|vPT14HCXk1wF8ISTR4{#PLXmDoTFCb7;JFQngrdd8?j9pFOZI5^*e z0zck*?JKq6QGRM&#?K1k2yU&jgY<$^26g=QnqKTx%5u^p&80pU7XnkAC)OoZM+_iaW0=Dce#In^8oigx(SM2lu|Hr|D zO`xvdOLnm0PY}g*5XA;?#V6tjXB+ki(CUhL$Cl_4xIqOSe_|2nvL@^^>^=Gd9P_-r%@R5c44oP;4L}tGs1>9F%3>d0EP*Hxd$IEB|Nk$J zfD&TMUQl`c64dr`Z~o6$dg4b3L9kAKh)xTLPKRDM-WOINoku~|9m_lg(z^phe1FDxs`&tC^CgBXhAgfZ zThIUh9~svPp8fBf3|<{s05(ttV&L=VVBhKXx^cdEdFB8A7YjK-)pI9!wFp|F4O&d{ z(g>_u4WfG`M7LtE8_$c?Al=8VgN);!3L2|O>jbY-ddUFRVGPkx4%Pum`Zf@OG_XL4 z{)_A@pmk4%mtHKo`2RmNVoSIowd2b@pedTk;NCRT%k>{XVF~ScsX_Dy^={4p-EP75 zqKp%kgxFt*gWPnUgMp!wEv4bZ>S5^@!PCuz@s!dz4HsmS6t=|3y5=2)37;AO8RE z;%oS+z~8p%$N&FMZXI6#!7E>TCkH~z%?6uW;s{F7xgedYAf1PLH-Ky7Zg6dU-tt;0 z|1n0;+A67Q|Np)C~h1t z}ybEV1Q_-c`+Ge7`WEMG$kBr3S36;MG8pyAyo!`28M$#SYERj z9x%Mr-F@Q!|Nk9~ofi&1;NahOiStle<0I}5-OV7oI|R}WzT)U^23g-B(EQJ$K=LQAun5$6U_Mzx`NR_ZIMB+Yt4gEGlW81}}uq z{Qtk9xi^gY-HY9z;ocvepWeOL2xjqbJJK7*`0mAG76yh5%wQ#;9!75%^BWuH65ehW zl{C<`oiE?L`TxJSj%fp9=dX7!%0OCwy|LL}&S7}q-HUV<28Qn4AcuFc_lB{&dlAOM z!0?ToqlEQE=IQ_c8+IQ7wN&_9R=xTE|5!7a)7=c3HhyvHGHBWqv;gVF{>%UWzw7|n zGI=H>F8@CQ$2do?8_P@3Mv&ggb0HGXAQI7_O!(qFxa#0<@qGgtVFR!5A4>f8t#7GOUIP6(YpUVzpGcZ;ZiDj?9!sl9HDpoMswUNVCnu?S*U z71%ERmUpi~6V}||X6R(l>br(26(j!E>#zU+f01(j|9@}|V0h`pj5DD8Qvqs~Grj1( z`2YXQEwABaBY(?s&@8No3bb~s0|gwoeXMx?|Nj>^L6b}1I<9j!sEhKl5@c!fI#9>D z;Pn6hFEd~N|KE57G>Qoy)O_*(252}l*`1N0^H}SFQqC98PJ}e;93MfS~FdT0Njn;$uRlUu(Kw&f!G-`9u@RH$y7jGW?|KHmUnw$fT&2%#M zHa`NXC`YI`1?mwW>TMPQwGafLEd|grSb^Tv$deWCKd7~| zu&a=UHNd*TEw2}Q9>eA;UK{o{KL^>kNz*7pX-%8)ScI?g*0nJ!jwEiy<>JDe=eDPx1Igni?EZz36Uv<8C;l%`+ zdIN1-WN7_g!qHhL^WRV7^?vB&-0N+<&EQHEG`+9&f(KI5Dt3b=u~@7HOT^*Bn4qOe zodUhh0$~3)>;?@7GL(e$hN$p>Ht;aK_;&`Bp;`}=IDn?bS`U<1yZ|i=>pTh?%IQ4* zdC7})(5ee=IzO7}oiAR@W@KOhc}Sx5c8OJYGiU&{vl%qv)ZGl4-)}uo!u{eeXbb|( z?QRBjOTmIKz=9xdxAf~nu;t)}2c9)NYXHx5vt0uv{45tn2E%WlP6|`!F=#Y=0Y&Zc z&JQm@+W|WdcDlo6T_N(FzoO&fU!J=6|9`iM%Hgo!7kjRPOj2+GB|FfNy2%M}hzlGC z51}1%F<@b6KEMK6l^z`jwz?av;k`2>D3ldCkG)uQ^8f$N!!JPPapxh!1Fe@zcsj3l z-u%3z^8!R${NdIEC3@ju!JWszEi~|I<Tnt@C_f=S6TrKXDvf!LfknWjb9MVnL%#-6ASZ;hi5}tUmt#e_Pzp|eJXrBg(O6}024^LiubIw9~Xx{I$GAAzp8ZUkM}(*W9D(0Lv%E6{lg zLte!2Qm<^v-v9qQV^kzMuOEER(s`}<8GCn(3JY_LibS`Lin7k;&Uc-Eo1e0G%d7@1 zq~rYh?GQ%^8+VBcPv=*|Z>|4JgcVPBm#7GE-fMmil88|e>AcsO!O>a3(;cH?&>11n zd_csh@fRpQOJ_G9kpUNCpnz?D!}DVAWl#txIx#Zr0%fZmpsSriTqE?+j7l=zRBiX}2rO3q{cM1Bma$(tJpy`KX9>jtWcZHPFJv9iSa> zy{kd1E)2i*Hc#IJiLKt|`4ARIXa1kC|0OCMp)cN@0xdjZW$gTP@D)q*Blg~A7tlBd z&xFoT&5zi-MJ6;K;puIjvgiN*@5ewrB-p%hU{JvS5*3l~7jpmp|95LXF4BBNr12lv ztBbmuT|mtp9+ggx?q<*y=i}gutFxGPf;#29KwWuoT95(xz(s`xmd!vx^J3{GP`Ge9 zf|49k$gmy%|G#%`259o(5G*i20pSZ@IpYNl2Fur__rM|DZ39`L{Q`6=QscpG4j?1D z8*@NzGw5#o0-`0Fe>0Y;@o!`6^<(1SR>#=qF0^qsR<~IQ^9$W-@!Ubd_XeBc! zmV8tMKx4n4ek%iHHX1U_%mW(P_H6w5pPhlBOrW>9XYc?2FMb^U|No^R6X>FI4hDu7 zl1D%lYU_a#F3`|6Xd%IC`Tr#DwrjGdsQh3`#i#j80u%|2zEtx120t z>HP5eT|kfg&?Lgzb zphbK;L1LY+UaU9_ww497a-xK<8`P8nHELdLIQ1V?{>b!(s7OHSued{?Ce?xe{{zB$ zn?HhGR(${*Ew61sPT(vR25m&>eDUJRq5uD9ym)u)|Nqy@plY%C1yl16rgC1;nsLye z5$K9}F3^^i7cX={4Tu*nj81_J3IL}W;gpfR4`$2I!pTr4)Y~ku@BjZ7o(KQ`H~jW8nvsFw#oA-g3jAGf zh>FWj(3CYKxq}QZV5sTd4Qj`BxvSV1may2El&W<5>-4&)aAXPWddJSd@S=AA|NoJo zL26z`28QD;aul7nOvxZbp#4oV0F777)XQf18s`r;AF2;eU|7|C^|EzT5@6 ziStF%zW<;FpQU1*Klrzu=yg$X3F!O;Y6iVnap3>|2v8zvJy62>g6kM~K?-~4hZp@I z=GzkX&KEC4PJmKJ1ybrzcoA_HlsfiUGct5u1vk{$y1}C#t#3=&x>ti{P7v*aQ{OLv zcJ_hxu$}mRq1T0p`^Ccj;OYoGjN0tE@BjaopnU+LVZF^cpmGOP1ie^$1T+LtyAPZ} z1YY=o%OC+z2Aa>vzyMm3#MtYj0?r|wA70q+1!r4%@De8emahy93}L;^%^=fW1n&in zK)nRr!3dTv;ugNxu}Trx`9e09>cd?E_#eB?w7FJ=zx~5eC#b{?ELUz2T0ZN)&r#i zz0I>gR)RK%y##Ge0{IbC(S-%Pm<%eiN>pSR-!&f*fVhw+{C|mx#EY4GKxI$oFHj7< z$T8L43T5VF z|NnP4gO2>@W_aPY2Q*~2_djGeR`U@Ba5@R=ZGHmQc6~R<2cXzucvUx>Jn&kr zP7p4~0+uV`Yd!|rk;77YwE4vU*N}yV%||%E&Ix|8{1nJOZcFgyF{Y28#hMVOD7@$a zOMS2aZ53<&#n^oBKVqj9XtxpzI6n!4R?0(s-RYvj14^$9pc2*az>CcvKpX!`cpOR% zL7A%Ag1b}$)Jb5_c2Qwz{a?b>{3ErDxA{L~iHGH}VwTo#rPeS0gA&`{*LGlapvt#5 zpRvnDMYzMoMxxh8MWok7MWXZ73(yP)Xazl}s(UTrQNs6{734cU{%tNQ60g}i--9_cbigYITb9|4V@gsAXzGl3J4gMde;i;6^d^AwP{i;4_r8ut4I&|pk6Xrl>#%Q8?+ z#G(S)70c`{VCkYF!rwHFfq{X4yPE{4@s$QzKW%ujJ48k1h3n4$pq*1JjsHPcT$Zu! z2T`E(qRpbB?4qJzdAy9N6EsC70p2vr(e24|`9IdMMdC$ zs6dqEk20ptAB-$2nl36V4K*t24E(L2Wp$vW{o=4+8_Z&VS8mcDfC9oZ$A0I;WukJd-JRC4gruv^x+rs%nS^Thg?k= z8M>QVKr0{^njbJabWeKm|Nnm_CeZ4{u;8E*y}v0xfCLIsNbdYu;ncARc>fGvk?m|2vy=xEL5BqT>z+2ffGy zn|Rg)W+G@KX6u1ckr!DIgM_+RR5-x8U$bL11>Db82Ak4u!pP7CR@-^7`5}An0-dYdId&Ab@&t_&OgRb)rXR+P47~v# z8h){t^MdT33<}E*rq_<0$9f&U*zlIe@NYZN-P7!H;QxQdoBtp7Hs3r23!RsZpo&rv zydGEuY{84IplT=gMZGcT|G!h;M0+C130WEsKPD+yHD_)mBjD0v*LTdIaPh zO=Cs|8?I8{Zm<>I3~8XjHK?tduYmH~hZn*7LDl{NW~x%H7={H+Ktm&j$IR@i3?XZ+WYjyElrdQ<8t%fwWF0(C`Lm z(}FeFCG(9K8G0v!Y1=>4BgG3cJqtA?Vyp7;1_jZiARQv z3|a6|V5RN<|3^h14t|jcmOP3g$qJDKRWZRY9KZ^epeT3(N{79vKceGf4+p=H1FL8< zWMtr9f9S=I-4I(jz@j;Zj0`~;PD~680WbU@?G4yopy!7`?)5eVts4e4Ih+47)@gQv zk2xsW1@3ip^Qe?^A7f)MJYe~+RP?o|TZh~K<{w-o?7purwZ1K3KE}q-`2&>pL9Unq zHtvrBBSSB!V+bmnT~s(;aP9>=C-6lDSpJRyBSVLa3NvW$d*?-PiT9#x+yDO_rR<;z zm>C=wpnwT{;SScY8cD-W&@2H&j}sO>kjh2i1s_;rkpUw^=UL0{3eXJVZqQg(sgUJl z&~4wPT;2SZ2kTi{Pu9zHt_I0>g2j)sgC^;ZHmgWb`6J_jfotr@xcJBs}z5a}y-5^G%j|va}KJ(^(R*+5OmIsI=z+yRd%3tF5MygEUlMHM7q1dvVz?r zD$R$OIt4mEy!HT%1a=DS0NwW4P|ILdYV_K)^8?7pQeDu|7u}OV26uA3mhWzU0y5eF zEC*_|IzZ)^c7U#)MjjXfjhS^G0HvY#x*$k3D?g}as7>+kLz@ns-p_gSVsFni-AgHA$vH?60 zdE)=exr_`94OY6PpSzquyP)3K=$1OTb(S(TR55|}Y`Ul@bX&Ck=WhW;T5k~(c&)Ku z!%y219yfOj|NkZLUIv3quxH?Jc?~)+&Xo}sao54)KHXqffb7-00E#%L&dDHWb$5fv z-b}{M)gT7{KFj9+R{SlXo-SxZ3b?1i@D79D_9(c{sd_dr3BWSZZ(k80rHyoYE__up7b)GQ1#J}W_z`+Lsod-KF^KW-! zF?`$ks`C)&q&o)2gMyd&x3d{uVmu*u3$$f1M1>`@MujE!*_(UWA}Xwm*LQ-L-7G5K zA2R-GKEU04iJ|jyS|=O-nhOF4UkP*`PwRAJO6!bc>HLA{xxC#AN}GW?pa=l%R(SCR zT2fyDOIYYIGQ4=W{r~@qFF+;qez2f2NRVeML@+EEbZ`yhHOo&Wd=5@sQU5z4{#%?b z{Qw!tKOD@z?NaN>5-v~vZ4#E3OTU1H4~K_=j-2?sr1M8yJaqI?Q%Qa2-_GM*u8g4K zwBw-R0Sl1osRuv_6nrcKL|_U?faSl73X9=4?GP0W(13fli;70`3sAWxU|piZQ|{5_ zqQY$DV$N8?#$2Mp^7>V8h&fZQD-&p6(~BRQKs9YCcQ1>1SBMIel|YF+bBPMa>!Y0q zyJA$BEF?>K9Xl^;o@P8;`X0RHV!et#z4mf{djSHGxR7LS7sZP*N2<` zG4i*9=5bn2^0$Ka*T7~Of?v%3{{MgDp@W)?4BcIz^w=%gIje_@fg!Csk|nKk)&x+w zDbXpJ*6qNO*6GO7+XRw~KKvpXtgjQKZxTpf+Hod6h)1k(EQlj{0cPgdHnN|-pNlutP7A1^kK$Bod+#1mT)v!GL$eo zzW$y;u?$$-3G1SO2j)slZa+pz_zg*V_Ju9lM}a!#Em4!&S+ejwAyqSE|OzVpZB2b~AISyVWESQ%d50Z%FWsIV{^ z9^l_5!rXcB;49YVhw|MaQ&=v)YJS9Mc@54;9qS%1v=mBB4jUnZ{`0^8363+S+O{ua>Y5W|zr|JnH4?LkXadUj7Z3+c?-sPeafmZ|V>y8t@h z;+u;gqd*B?=ZhB!Yd`_?avd`R1GpV;<;uX{%EZFJ;QDeFGXsN-R*5cu4`{%?*8?Icqrv$2@iJ5^RJ4A(ri+|sN zUKb|N=nu8SML_}alaYbJCV;;MG%oWJbgHOLGJlIdNH7JW%qE(@6?8gjHyfzh z?hR3~fRz&0Kd){+2AU!QN8f(X*4vj?m>3vr3QEH2g>3RltoMV;6Px^!@R#dA;-w{? zHWejuHpTp{^FT{t{8%7{{`XN~c?nu4Z}|VU&VJAm@z<)IFSJ34<% zwU6Qd<18xw|NpOl&AK1d-0pnwVhuP^gIC2ngUk$3G5KGj!qWNkMbZlJm@;^PuG>e& zBEs@4e~TIu1H*q%U3>PMi;4szf2$klxFFEEBYySL%{D6kO0=78RQ~g~>Vd*j3^e?e z*2(nRve`z3sYI$qv(W}@e~H3NUa*2L7Zsikrq`0)d?2OWAu0l$jGcijuQ|HGdOMk# zkFmUb#0Xk;ry{{r3L1820hO%1ZY%R|3T}3USI4AWoWrnq772#*IA;%!@uoQca4h9Hy3k8fl?6%*N%Yy zptc`q%o1#J={ai`6%PIu&@o4#-P|DWpL^*G>PgfxsPeah)(W`3v<0p2sZmj2DCMw; zgQSNJ7ZrK_)h;R)ukCDNOWbU9`CHyHFn~J85aE}gqpSJ1g{a8$Z#!WVTgtOT7c^W6 z)*)ees-A;?b%=_E)9WvWC-;L^9K77dz`)R%qhiwe667$3Qt|E_6%)&sCC;D*49sa~ zUmJ7@wp=QC%)jjr|6&&v3;s!xJhuY(Owf@`niE-KgxkJrYXAu1|{CqWsR;kB9}C`*B|>}%=HW3QPy&w=Zt z*T&!y;I)q7$^D>3<)GP-my>^kPp}eUD3$aq6$6!5pfc$-4>&;`GdyYd|Mhjy7;N*A z2yk8ZBJ~}p)zqy3YBhmMEdFf*kkW?P;q~Xk!JrjCoDLQOrQbR@UVnmAe8De1Z3LC_ zVG7`i?|SE1*eaPtOaA|7c4LXMcH<~g?L63c5WJ`NR40#0H`|M?%m4rHJOnD#FO|r3 zih)`vejMFyEZt!onunO#LP7aq$^ZY1ZY+_IW=8OfF0eiCY1R*LS-AtVx@RvB6Qhd?$1YG=sCkG{L`Cy(>7nDU44@bUbv>Goax~Vcuz)Osw0(O6 z8ILi78XecWc~m~H(hgAp9rh&B2_ku3v+e*-kQ|W!M|5~taN`@$czEYI@VQQ%&p$8i zeE8zqKhRP~kT|T7*!V^SwAMOAg{51o@$Y9)ZfWZQ%^93N-T*phJh>@28FYRm#FXou z_dYKLoyN%6xEpkeFX-g>dV%9DDxf2HK@JDWF*NT6oy_J?$KK$h!p!uV`*@2A=!^@H z{P7kQ(8hfbvv(@!wEfNy6@lIjpcBlS_oy6TWME({wK&!Q;+r08_{hM(z}UM1Yd69>MDn*fGh`T1DV(WIqdNmo5?XZM$oAd%pHDA%{eLp%+1G` zLGu;hX$BEc&DiUrA^?gl&>R=|w39oaQ|S(AzGE&?5$H7k=Ay#P*z1}DD(FijkGrS{ zfP4xW7EIbV>h5k(fV7^hU%bft`~UxIjh&#{1=7Op?goWh=Y`gjb%NcSL8mHrzW=-g8ncZ@KoJFwTuAdp z;6>CrP`=zJ!^i+?`G7{hVC@u8VaCYcHW3t^+XPxJm2&nLFoFv9*HsO_{+HDB7BKN| za{wI#)tsZk!UPH%%OB;bpcrnc0;E+F|HsQ2}vWS-L|RjR9IevY8VdCDJGpCUV_%3gUU+O zfiHm<6V`%!@g2%;@kmCi2SWapz)<|$6Y=`8(*Ll!r%s7 znDwIbEGTXpUxAVjD~NdEzX&|Te+;y0q10uP?G6!{1+@W`I$95u7(#5|c=2c+$Oce4X+2OP4yt{d zkL7?Z;y|^in?(gR#6@1ntpSC2lN4m)`x+?myeL`-ZlAEU9w-H!%kiRU(f|LiYoQ&T zZW|TQh+gMeXfFqJmRucZagadgMaa>{;N8TaOr`m?mqqi13&?ec4G*;5F0ll)!nH+I zI`4OzsDPXXY7KzK^*%3Q4pHG?yw%O30-B`m^|mYuYX?Bc>^{q0!s2PvQ~rK zd`=Qn55YUL-!FEa?L6_KYzeqO$<}$i^X2CykZc0#od&-!0qdF}$;i+f`o-|%i!%%V z|L^ww(#6?)Qla@}YQs>dfUZEd z15399_?RWbZ@n%m(x6pjz0D`if&(5tn=jJ&0yI40QNsQr4ipE^yIfSHZMaJA*R$Dh zlnA``v*9f%2es8~L`!5}JG6c)IqLVHM`b5y?yGf9DI(fa?Fty>5)K(V4K|7yDL%LQ6@4k)ioVeZ64j0UZYh2Il4!pmjqQps{}N z!j0n$oS;!8MbHekQFj4Pr(v@dLkSz`+>26v*u=ji=zP!<|KXK5&x=H`;YYqK`lI52>gQLuD=c)>Fpv`19|lw>=@R6qv@ZUK#h@_^G6|29$3;%TSO z01p1`yk4M95FR|uzqsq!k2`RH+IG!9)j@0?(CM*;2f#_;#ikXYun+?|_gd%qUL7vW zcO}vdc3h=gJ3!0FUi_N<|GyjmKDYlbKFt3A|MkPpA7HycX&!WhPcc~gbumVU-Xg|c zM@CQ?2X0RGu3iBeA#ews8UXTciEYE~m7rcoiBMNFNUFo_|FLGU$ZNS5DT}~4M6&b6 z3(fie|980kZ#huP4v}YcbAP=ZTuMNPDnR}B-^)SHju!(hNP#(<2jWf-kUKv>-D!B> zaOVk#Pfvig=zz4G?`{U&&I3O5S+w&S#Me;mFQ@M>7@B`EmN*r$H~(TP z34ML9H{gH6FP3tl@;%!|Nk9T&04LI0&2m|37#m#cO8JT(3LGg-dOe zOXVP%K+W;v&1*n`3reuv%`Xg^e{k0ELu5hq#Y@oiW%gu{5-!FIonW=y-5_f~=@Yd4 zdoqaAdWpZ)3zW%xR5+{|YxnPv2F+dHnD+nwj%X0;9Eb&4toY&xh-D2D+coX~|7@^< zBB0qTX2$Le7SJ(8EeA?CUd)~L|G(?&4?A)}Dkn_)|NkX;a^VN8zz+|5QSb=V=$|IS z$k6S;)4Pe~{Qv(u#X%jP?H_r|hl`c204i^>SW;+)Cc2+jfq2t{>%}=0X84bU9$~_x?aq%~Uy7Udd*h^B& zWqO_d+pzGrgD&bh&IT%___tl^4C8otoRxv0;TK1VSHmw({#H0I1 zwr}{wUy@la-0+LHB(mWbUuoenw_wJX6TsS}OClP6)$_MBu`)2cj`$xc^0ERXZll83 zAfodBWi~4VgJ1K%|NJfMSQ!|0ftqTaKVHn6@&Etp7yn#Tgd6I@8TeaVSs56Pv8XV- zv;i^Pf*D>KvobIo2d%VYcnP|bpy8K1f15nW;JRRj67h};%?}>fB$V>;Z@bjhBHVKB z|Njmb6&cXNUKvowQ<#4ni%Qu4P?mo#DlCyNpRs^Es9CPi@JoZg8FU9j!!Kq2mh)g? zRsL4+Ee;34yyz0GhF{72t!qJJLoO;39s!_%F^>Sya$3U!|3eu-fdxuw3=I6-$JxLs z(hb~1JLcxW&>O}9Ye`=Jy!vGx$PhPB(+hOj4roIKDE?%6t1fi@1TAur>~>@6WogUy z;NarlcBwZ+@Iq$*$4k(mcMZR+OJ%#=SR9&v@Yi#6y0N@eVgc=qVc`eO?}>q(YG2BE z%*})GCFtCThF>21Eub53%3T|NIrFz%Vqjn>7iswA$lo#>)P!pX9VOTBOZ~NU!!K9< zmTMrfCQz@d;g=hK3#et+@XMXQmzy^@(fYhx z4H_ZwV=+ANk{NXJ^fnh2VQm)`nU^O)jso#OW0Z^sJA71xEqzoZ`1=(>TQNa%NT67S zO7f^!`lyKT_p>rHFue8zNr23F?E#vK7lx<-X|8AQ0!89$DUfO46b2fJ0xJTkuVgYj z0LnzKpLkfhsEB}7i+H?dYdrv#VNrRxl!<}Cqq~j=R5ORDh}83d=2m*+|98l!yyk4Z zRLNv`sY67?(nUq0o(pW%OVGVEtq1r!kAND<2VU+4ji3BrECHRUT~Z8MavTKmKWMRN z#ee>7F)G6R+eB1?!#i(we)t~>I=)fCBQnbJFn_NWXxz%1F(CZ47wB{t2L2XMGZw6+ z*ZDtEx&&(s26>9dBcSu9;U%y@^AUlUpfmX)=@&wRQt@l0<{yk8J4;lXe=wDpfSd%X z$UvD#I1r)^Y(PZR%jKYG2OpmbnxclN@Ctgp3&Mh^eZ8jPR|fx-L(M-#O2nFfNR~)~ zPDE@4Z4T)Oi+BmTMyVq#{3YnRrH-&jkjWe`K?8~1A#EJZzYNQ`94t@NeR>JH4yt?4 zcJV}@k-w}FPh*d0N7Uq9aks%|=eyzrm= z|Nn8&a1;Y5BY;z~SeJ{6h(`yDN<&=)LkS0{s0AheE^vCg+*|$MGDJn9o)Z)uJe|K^ zzvkcO7YWk*KU4r51fCsnUXY2f*uyV;SN#9adYhM#;eW>wE>H-7=7~K5!RuKXDnb}a z`FDY;iiV0Hh7uP3Z22xx2xv=F-6M@6FZ zSLcWSmm@%9R)=4R-3HaHHoS}s-IL&Y{s(a!4t}wB9>`opUPcD~Z6~{DgJq?=qXqs4 zLuX%uUs#{{|G)A0KOXRehKNe%X;89$Aq{H49y2`IEuzx-0=z`9^8^333;f#-clU!$ z;q3Ml_#emun&*oJtqKeV+q9jBk>SPtfB*mUZ#&W547y#blSQSAMWr|3KmWE%-OVb@ z44}hZx>!^^Kr88x9mEqEefY)WW&i)P7V>~PGhka7x*Y_%9Yk6Wlra6j01m0wb3s1x z2RZk6^KMXdFqG!OT51(643!GUn?Z*ggBn=J!7c!`+>e881~rFYJ9cjd8_m}3An-px zrkkzXL!fsu$f>{f9nls*W$aK zzrdQ`bRIW6@UHXLn~uYsr`~iN+yz$i;oUB<^pAJH4G(af2ALEWe>k}Ljn0eMIiT1$ z$OW1#EG_GN*gF}tVR{GX^y?Rv6aN4I=Axp(SnAPGqoT@C>eyJLA`{@`sZa_U+EQUG z<^1NNqQX?7^jZMC#j*83$ve=v9K&m!7eSDZLJ4NZ@w@B z%a=X?-IOpHbYW*FQ}YoW$XIdX8_-=)FAmNIxlNS|GPn?;!UNhHW2wMk_^r2j0;tRA zq9R}jx`LqDW&=YhA8h>Q%}Zztu$yHAXb=|E*lD)e!BEQP-uz$THE8Q!H_L`@mL1?h zG@Xvtx24?Rklg9StB!=3D)B@H1e0xudT{Qv*@B4qU>Xl(2S!z6G= zon^;tP(K#3NID!;S-PlL_fDPx+K~0P>;L~=7Zq${9)rd|A&Q${aM?(fbM0beaA4wJe5mML zcZdq;z%H2=aT7q>lMLVXx~OD>`boVmD$$@`QtP*pOr$Xr&*qjSs1pE+cRu&V|DeTerEgxo{0F|XqMK#Map;{Z%{D6-O4(eS|H4wnj&7C}p#D*} zNk{89e(>UT{_Sj*E-EVgt)MgK__w<;S%Qw(Zv|JK+uhi@LsSeD4_RI)tpzQi>JCxS z0Q2&@-9WdqaCA3-HdBL!Xh36@y&a$!0gVNN(k19>0?QB;fm+Z&fdu%JERz?8ec-y% zr1>CM>w!{@|1K&5udijhsEBZZ2D^G&7(ph04o`k@y#sVD0ndN14WRjh<{A|qj+Z*1 zddEeD5m0u54+b>80Uf6EB6$WVcY$i}&ZD4#U!+{cVfeqfW-DloAS_S4 zdtK1&vK2I}3UW14Zn^^!2IVClm2Q!a)=MS!%~d=MB@*3EJglH04p=VWcv0Q^|Nm=6 z(3mD9M|FeB%n%ixPA5>VIuFWKO`u%GqS9=m!tr`OJioBKxX=gAFC05Sw?cuk90Pw# z7!w1iAb`vXbb>Z9fu>bmR6r*Sa==o(z>CmMNU8@7t9C&Y_Xd1x_$65m8hipJ`-??q zZJbNkIzO}=C^-yvZtrAJ=>i&2eQ~Vk|Nn+P;CTm5$RuI!6cup0wnRk^Jd@V>;l;up z@Qn=$klrC^=fR706aN2y@v`Ut|DB+T7x0BxEH5g1z`MU#UTA~PW&7~L4@9}Bh=9lN zKr{Xl&}9ISz=s!TFJFQx08l`~5^Xn+O0!J|Ln-HfaA+yKz66p5t$$+a0F9z{+w5rl zUt-3;&7B+6m@3ujc85j>$T^@fsTXg$|NjSzvNAA$9SKfQ*Si0MZ)gCgqu28r_NZtw zF)(nJRD(OdV6R>72c7TI^Z$SE9u-g@3aq&kbiLZlZqRXsFMRnJ7<#9GHTIUMD8oXj zx*Hrystmm@DsnG^_`unkr}M)LcL-C&@LOk%iUcg_3B!{fc!}6cRZz~wngp+a{m!xj z;{DbGC0hL30=O+hRCr1i__qacS%#>Hl!|pbpoW0Ni&tI$|3ku$gVlCR0J#Wd<|2l@+4GgPdJ(MOz!F1^~Gkde>98jS4vH;D|OBNVIu0*Yhxx zXm-2vfKwxATh!iy)7!BYcs)BNQ;UEXbg@;1ys7iawx}(&8?6e`iYr=p$nqCH{fo=qx&V-Z4~&Y z9JJx$pK^%fV(Cd6PW~3qrE0w;DiDW)LZ3nhqU8u0AL@j}1%|Nj?RAcxhcSRfMU zj}CAGUBeCbEsD?Xc7T10;~`h z;3z!;YP6KDf#rr-FZccX|G%q6#S*megp-zdpo%Ld$9^M;5!9uMsJA*sIP(orgL`>yHJ7~FN zr;CbA=Z6>7P&TAYvjEk@@Fp0zMu8VnD^0yZK1@9(hVc>5~|NH+xtdQe)0cvl(&}>Huyj^WD6)Y+*&UXF(|AGTm z!OS*D==yMi3qUJSi>^im5@?-2UR1S#L)RQsINF2cN>m_$-1*@}97N6t6!I!BOgW*c ztMkVTO(+|*hf?!}G?XXN`QZgWlr0Bt^MJw{v>hFkgBhA@_A)S(3d7nxFF-K*n#iE!3Tg$F_(1}kt<)9Nw@kBkV=A>y z>vmC*OS5)kgT;ayOQ~A78xJfsE4=7z1-DL6W1*xKITl*L?cob;ka8DP(89~z<~QKh zQ|qOYEW?wa6b-uk0kqnp#MkgPX!`-n4A2xt>wyw;!*8I;Dp!Zhhk{mewqe zQmO8I7UL|Q)+~Wi{_c8?&L37zB1NoLPNHS9Zq5HVN>4jC|5hm7>e%=bluSzJbPK(n z1YSjb0r|?2<~I^AEc!uZ|D3;|ll%-1ytvr-|Gxu&%MH*p-M40&?MQu(k1r2_8sQ%f zJ`e!S$uxl4%!Ze`S++OZOkgPGaBBXgQ2O!pMbN=w+}xluFI-eOptVOgXu}H!H|Ufj zP%DOIdpFAjP?ZMipp?XddnGoVpfxAHpe^|VARjj$uzAta0d6b`bTqbr#?W&?CzP@@ zAK-nF-SPi_M{6rcFhoVGl z7`dqMfZB!%{H^C9T!F?K6#-Dx z@V71oHPJ*=UV~@-LGCxa)Oi86J{pvg8sC8Ke17q=8x&K%zrZ6&pu_;`*PCjAn)8T$ zJ*4+WxL=Rfd)ol&z165dno@|G1k|qwwW=`s^{g$hW)rwy-v(NB>Y{?$uMfx3uV2}K z*00xS0;dL!9iY2eq5TvS(CAZ(N)M=5fb`AFLB$p*SYd4-nHTG8AZ?&OObiSSd%%j7 zOYZbeo(nn0MdpQE14u#1$z7tLba((%BX(Z=ysGn5Z;pyNxaHOPzVpK8)x9n%;h@eC zMCdqJs6@pb!u<}GPY0Dr5CMohc)+3a#fz>g&_+_w=tJj+7qwu{N{IbDFY=JN0x#l0 z+z=Jh-WCJB3o7-Z1bQo)_trP$z>T0CLCaF&C3k z2G`yY6;s0lFVyQn!zM4kf=+UFQ89l3nnM7M#DJpZ1?ZYh=tze9iy%-_*hK|2l9B!b zwA~G~=-co=)l)Kbil(D zut5tIFb_It!2=((kO0-t@Iebuu>o4)AOY%Bfd?&Ez=IYBFKTMR^^gH#&_V<}XdwX_ zwBSJuTCluOssJ|&;DZ*B1{rM7g5$-ZI#3`t9s!jV;MPERFlhY@=+u?#pVoDr{(iah zrl;Wn%M-P{4K_?%r7WOjVxXNQ@rQ$7^tOY_mXBW<7$EbQmtHKc0ig%_X`MMLpu;W>zTg12?m;sNpjtXaMdi4QiVmnU==|9E z2{Jq?RsH{e^9j%hsSaZ)=rD4X<|77R2ZJmNe8B{^Dh*`S!S2nVA0-K2NSLX@nW@p&8kiZuqtssx>_>9A2pu0vP9=lwQ z5nG_63=J>s-~xFpr53c>4Ts0z{tAKmD}+LSfegg!t=bllw;p~1HC;O|BFC5oBpHI{ z)gd1HRfgm-YjBK#1~5QpE?n5b4f0z@&Hw+eOL6$E^T#`AN(7}te}u=5!qQ;}iwY>| z5tk4_#=YqL^sb9V1(XsY3(p}LYh^RYPrO+CWQOi1HDo_o!TrR){rV0bkdL-i|NsBG z9H)=c-b1_;0`gJ--`#9H18OE**F4@?`+|R;QRnC8 zcLvS>ILrC(oVI;!e{YmnnXBk*7+gM86^h{^Ca|30hU@(UnGa%JD<>W#6!;Pm=+ zGss95%^R_{+?|(D?f===4M}G#4~pIRF3uYroE82mi@;el|R;`5EG&*4rhb z-wrdDaJ3$&WV!S6HPfAw7k}S4@%s7Q8+RsNIsgCv{Ri{Pc#u5c{+b| zxTnV z)eGN(+Y8saT~tg!&F5|x70`H#0C>p?|9V%R7q%ehf<`C!TfnoAt_p^iK<#|c9_S#@ zQWul%5EY9T*NXoCkBT(B^u1ID)R*r(gw*)x0&Tf+Q|WS15$JGJ?Fdusyr2rY3>|dO z-tqsSEmb8dpqon|Cgl|U{~sOI8^Or=yCY5kv{<6UO}5*Wp~FoEH17op8#f8im;xwp z+(3tDG^6zCbzUUZfg0ctz`LXlW4q?z*K$D{X|G&9uFqXbF zJOHjVL9?{5Y7?}sR2pndJ;)dqmCkF12X=xMUx zJEYSZch_(;Fodou75LWN0un1>Kkf$JezwC2ujD$pG&(&;A9879KN-Bki~v=wuw8&5CT`%niUJkJ5Q9%3rQ#DfKJ&w{V@s$*f` zpK{>)jn3n*tGmD+?qE^rIN1Eqo`2iHPB#VqZOx6`pbgM&G7xFi0}Kod2Olu;Z=2l8 z&A`BU!J*SlqUB@>=W#dCtvd{_MUT6I7xW!>18*}s?j`{$OS;`e4F7Yx36zRh&!H@~rYu?w`0`grXt1_sdCsh!6GzwKA2jf&-uB2Y&ka>#^rm`M5k zB35fRf$|&R^E+ZxczR=01Yp5-|MTi*P((^*If1r9g3cQR;m%u~A70G(4VntcV(NUs zzwJdRNEn2{QigxPso{t~>w%I6!%LkvKnu-ZyeR~Y5VamCRq5tY;a~5^1Kz$4mb#b= zDtcNElyG()?|cW^CAFjzw2B5S>5}{ZKPX{eXg*>CZ|pa}ad@$11!x&g`AcvpaC9E- zyxw`X+eIY;R0?!^Lqp;OXaj!(Xt=(Vqxszbm!MPc`L~s*uvmU5df)lM@Dk$>!B^J7 zBIS>YSgoA}%5QhpsPJ^=s0e_rN$zA(fd)mljmqcM&DAUnB@$WApd*SU!0U=aR0KM2 zyy*S)|Nm?0EM`#Q!~r^f7+F%~H#{)-TR_EKw>J;}`g5J2OW8s`F9D5Js&vPwaJ)EE z0O}>fYUIvi;Pv?&FI;m#hXXVpae(_h_=RK@s356*0V&z9cb*0LNCxCA&{=RCFBay4 z3cc0?rFLPRzdAuT_p!X-%?7yxx?5WfR4#jf-SG-E!2IHWKBynv`Qk-d38*jF`i+0; zf$ujUCG%lWvI~51ck%!KjmJ1ZmWrr=s=z(QESLWO@BGPVqtbG+l>HckZs+mWPTe*t z{QLMDAA**B9{kDDTWQewtKpYrJxhncYu4t2<{ccp6^z{?DqUR75BYmD4LV61@&00sqSc{+IFaZ+GJe;NR}X1v>9n=mO{%X3&91 z%|`-y!z_ABRG2$Iyf{_(|3B!Y&5Iz}+zikNuL0=5x)(dkK`xbj#=rpHocJOToHR>V zI~`a$86Yc$UQ7k6`S}#&8&J-Js8oljl<&;o0L`y;21s;Ph;)l}3V_Bq#X6l>I@zGL z8aO$FLx$spC)ljDFtbkd`lzsUK6|Nqg@dJ(kg;c&xG zg<>}F&Y#1Emo7h;1U{`2e7eP_GLSdIo-#0GG5jxQ`EUNhA`9e69_S$#6DEAW_5DWk zEe5C=YcE{>b@=kH&I>aSPna+PV(!`tmtP&e{L1jaB#>BG=dqyg5Bb-ZsBkcTisN5@ zj`36+*gjB<3G~)-fX=84{m{+c9nR7n&(V3W^D^h*5>D{08^hbLInFYGZaaCM+W zU+}NFz;RBwOkeh zSY``E=Jj(Ze+h&SKQ*%xa@Hsh$ibOl>!&=1Ti;vzrcwlIV(aZntK+UOKo#k0?$+Ct zHqZbJM|OuB#PsIc7mOtu-(%l2hkjuA9{b_7OgPvv>JaJIPa#|h2)EnyO?T)An2SJr zYL=IPLXP_}B()nJc=0ap|9^0_f)k|!IHi_=4_CDVFUWgw7Nh{Q*dMGwJ{@%I+XL|0 zyce5Lq*&5H=g%?03jXN0cyRvbcwr2-bNV9&&>?edy&)=~rCdzVwU}oA!z7?-j)+JgB{1BHj6@x0zS&|Nj@AIUomgv#6A?zlhBNRXkDA zhr@zHI`^yn>7Nol=Z zBHr!I(H+dv&HQ2t=nze|-U6QPXr9+kyIoXLKqrR7R$cU#s6=$@wZ4U%5ZLVsa;r>t zEC=J^Ug!UvE-E(NH7XI7@A+HKf~L*DTayf!-8n$V*;;hFs2EtgsMzo~gC^`it2Hcr zR4n-0W`UHtf|F!-jEaqAjEY6Eo_36iMYk(QcPI6OT4F@x%GP=JDtWCJ&Occ%aUAOF%D)LSj)dEMIW z&eClT+8%59p;)`~BgEQr4$F_lvY=DgIzND|<>++-r6rN$E-EJAvR?yqC<)jVAgit2 zL9TEIF+nrepjDtCm7w$vF0Vn&60p0b{06(rxjTTPTc{f}TWrEmA`DvM#4MuHc~SEq zf9o4228P#4ofou0r=GNa1o1>5JL-5qtNeUT` z>&a4<&dZ$#yB#=Q-)ucus@m(Kk^q`H4gr^Bp!@<3#FV)I|KnN@l!$^i4t0aJnSv(M zV_I*Q2D}DsO#meqh2|O+6NVDdg$^RxE-DEQ-Q_HuB`Q3i1I5APDtGK4Ch)-&!5l9^M_)2t&}LDw zv{5PM>-^X)qVnSBPf$;&TLO{^yP01s{P`brK($@FfcG^UI3N- z2g{f`4?^7|_3QutsBShyMiWl||No^gcqx#IMz=ugr4rU&C!W_|LEE=GEkH%aaTgUA zPyz+z!`1_(oXs^V5e%i0uere))j9S5|JQFoi>Me%PG-hk`~QHcPn zTATL&|LbR9RVDeLb)%p?pfM^eFQ%mZ{|`EC{Pkl?5tWyspz6z;qgRH*@)m!yCuq;g zMa_eqw_e))|Nq~TN2QFplSf5cLf=c3}$ zd?W*2g@We&O0z-L+|8TNRi~hn3P6zxD(gX67qqPtR86UX{M~s0w)!8M9fX>HvG7kh z#J}wlV~7d|CGmH zeCvVI+n}V?`oBb{+n=L598{pbc;S`|zQ&_;f44tJ7IU|F=ZhD{$>18ebWL|X&+7}l zKHxcGod8%a(|ExY4bjux?V_UcVhhL>A71c+C>IqKP_>y43RD*r4pz|0H}KsopxaMD zi;9{XKvE2llq1pWqM`y?=aT88!otAAz`*PSE+aKShb}Q5*F4|+{114DhQIwe0|P@A z6R1fC$|^4=B!QjC-+CUjm<4pYtB(pe8@ynP2bE&{t)K&uKuQhYwjL;9bM1EEdHsz! zM}?!e71>ReE-EawoS*@cm!Q)b!Tx!Y^#A{H7Zq?s^tv);AK-c67y}wB0IyyNQBi2U zRASN1)ydKA#nS1)((T33>A}%_fTuf%=k=53Uo52(p#I%)2k^-r-C-QvLfT@T0bmtn z9Nl4{;;r-s=sv1WgYFO&m(Bo|;|`#`UktqkJcj>Yvm3rO{MLN_KgjXmTSSf|{s(bX zz#Ml_yXAkW2>*5$6%oyMVVy5QVe(=@%>Vxp%_siD=6}P(f`eZ$XM$2(`gL&g@4}0m zMDXgJ&gZQMO0-+Qm8f+4fnr>&^T!LvL~w+bfKK*(@gxz{@O;hDUB>hJMmLKJXwU=P zo@{>O@?w1k$V_37nV@xIpraeRb5tT;=!1j3lmoQ#7d)?g47^gD1G4rBv=ak#u}u~u zXcP&Ok~%-U_!S9Gzn~@9`H7&T$3cE+y;Qo(@IY^fia2ObKySg0&W{~j-6gFIokfhz zhgcn&e{ht(Jm#We5Ar!rx2r<)3tdgnac>U2pxbG5L51dv2NB>pfWH-VaRUE#7L|Z3 z#%>=K5%7V$0xuk6LE}NqM_iC{Xu*ri=^($EUxVgQ$jQasTU0=2alP=11Enj72a7?4 z>v3=+58^?Qa8NSLQ4z=j4U6cO2asgw(}PHE+Teugp|kX8Xm z(-N!|LmSBborhv0S}&FI8(xBG%Db_xIggX(6`KKu+&gUdxlvhz6T zya4I09w~`S|Nnzdg=v22(ZP|{%@dZ^>A~21fZ3_}7hCDA;|%;t2VQj^()`tYhy&C! z0xiSqya=A6@L)?j?!eJ^IqkRuSK6L#KbcMsp0wi*0(}S5jynkT-Az00Akz1&*Fz%h zxPw^Vd&2|GKUhFVVIF+Wk=FQrmU~*KWp_;*PiG}l^FcOnWZi41GhmcF(ENh6gYlRn z({sXPAeK9c_5?=-2_yYAm z)zd(6)qRD50d#^Q|Mmkf-o}BKe+YE`>iqEHLlk&(8|Ya6zo{UViB}jHc7XadFG?do z^%>}7juLx_NOA-?YPmZ+ZRwqE9LGVWG6OVEL$fQ=aa;l~rh{$y zeVKuwJ4Z#O^(24GNzfqkv0fIzP8JnVAuLrD2Fv#)-k=3& zpwVWCYp#ZaTmwqQpvnc3;6VF)It4m2SUTA{Jve#`I9`ht9fcTEve)u`2}frpOK%}Z z=kac_ZYIz^Y?d;??kbjUCyq|G&I>OV#sB~R`bn`SC_`DkFEN5xlmoV?WPZ1dN~Z*< z>j&CK#L^kS@mkP2i=~tYraL7b941^~3tn1+*JeT%K7uYRJPhibLRk-TCA70g%PF zOISK3LF1XA0XMjn-7zW(-Im=TE6qAhRC=@jf4|)sqr%c1!P5Nue~Gc>XoQ7Px?lmsnv2KnVRxRM85y#pS#h>ry&Wus(JQl54Z zHtN9f;zTTHFdRJU5FQpB_(A}zqU0i|$cMHFI-j?GD=~#cd1WXlZIyzH`M=TNXq5w1 zR-l{Q;MGtkdv66tcNxd)iqDcCglJB z<_Et$N|GBur#^z(#4^1R|G(b=od6{SsrX9xy8Sr18NEulJI}R#D}4pJe8B&1ib~Nr%R|MdG%r{lFF(>5$^eV);1{xB zXEk16VCZfJUBJ}M@FFSf|Nqzj!h&Bgg5^>#FfhF6iv)SSgs=113+FIUpuPAL3?9P< z5Afbd1o_PdWC;AivQiFEv7#38|Njfd7|`%T@QaOLWug}t7-qb<8vzmnrCQJ&T`#=pb=|Bs9|Jka_U+!E-t=zIYlSVqoR zGB4I7fWk@uWD8_v8t9%jmhKW21JL<;9xqHn!L>T*qOVra93Q9zS7rFXz+lVJz`(%Y zG6}S@>@B4KB@LR-e(@*>_Hbbd|e zsm>2C9)VnVwDmwKQ|DJu&!AJ|btLG#Oy(SL^ONVr#<2hYHIH`cfYLBar$(FU^ zreMcHw6(r1vF&^hac<|2ZW9&l5)~7WqdGsm@D2U{-||?g7^su4&7;DsqXL=3eJ$Jy zxd)CX3f#`*03Fu`>Y2k1oeB>N4twDq4+`YfXTkLwj|wy@J;T6hMxpaKJSsoE*aEK5 zI)A+24g*DB=LdM4L0fGcFMh^>Op67X20FkCvdr{4WcjGyCPu^m@MC{r=ke%(oc+y( zkx`&jrsYzJ6u2+g`QpX%5a^^OM{kWO!)vBZjIOWGfR2?yq{GHH;09AG*v^+{Kt)k! zhzjUVKhQ#V(9v+9eh#>QcictA15~qu9n`%?Wex)a!>4ti#jm|ipfL>=NCJi2q}5oX zqVpegEO6Tvb_Ryt$#R$e|L<-A>v3wl`aUu;Fm$ie0S%W-106xx8KPp+HO+*HfuSQrMZS9)XbW5Sz68+W z>NP5$d#q&AI`{ozWMF7HS<1ALC9SbWg^7u&jHUH$DIa**cd69g|NsA+zXq+9=U^!1 zY5x1aguS;Gv`vfyteS z&(L|j!$*au`2pzS0TCNU$pfkk3>=`V(iuT}q%9h1R74mhLAMSFG^VHsFfe@l-{=CO z1whggjVYjWV>ucA`>05~&0JYs- z?q+3Ra6I^s6LiWSbT|_BbQze^I@>@85;gRJQep!* zos`IdTAJT)_PVHefcw`xFHC}=eQVIQ9U$L=2C7@%mWFh@sMvt&3g$M@0gl?BlSjcU zkn!OA5I`5_T7bhhiy?!7ffF?Q;gTf)?s|dZDdEKoaJWf;Ryw^09XsS=c%Y$1MV^6w z>VeLeC7=OimEI5)8_-&U|0OD*iB5(8B`PxiOH^DyOPCT~gu@MJ$^HNT|I3x2fn66B z2hi~Af6$H3po7wFK&_}3cf7!zTK?8nh#C*@5ROQ9h>FdNfFP(J=Yod2eNvU5BEBnt_#@Fk^&fom-Lt1B_5EBDK>)R4@P{qOcvDZb# zAr#c~e<2O?z>h!R&5s^g%;4@m&x?tHP>b*V`TxJUMn!~yzeNO8gt(}982<0hU;$-! zlWtHOvRlBn^j+g4h7X{{iU0W-7#bgf*qv83&syiGh!kDY4p9*SU(x;H|NqxVKqKg( zpkihp=%gf2+Usls?OX?^572E%N|xQO zpwl5aS`U=efhsp}`rzqyWofS9U?>6Yh3*XijcV|GzoB>mbbK%)XkSmQ2>4bY5z7!2 zjxwv)GTpucpb0c^uU+H?wjSU~9VzKp_L_ z|ADqof^A=T|36Eh*AF5g@}k=v9RB>R z8KB{7KaSpTf&XO^pfvKLz#SU;z96YGmY3rH|Njp&1l_3U(e0w*@}l1pG_m8N;_%|D zA9y&+wZ#)8OH-LNipjPz@moQMHWyKK&(7s%eZcy6{a_o*-cbP)# zw-UC{@c-9dvxkPi5b_5N4}f(Bzu*OHD?9?dQgH|9Fv}MOUf_lk%7Tq2p&;`;j(`hd z5rz`K?iv+|-tzyA|3KNK3_N#j(^{e;QTny>Z0GgPV-TZEJ-|ji1P>>9aCBA(bY_Tv zR(^Iy@IV%I2tb#0fE@(#O7k0m7iD1EZXJen5UzKggN^X+(g!UV{O<=gRo0S4r9`x$ z;=exlMkdfzT}920{(uI39bR9xEK%X$ZwF5RvZ(ZK)&Q+GDpBEqn6TFm(ugjpwbW55 zDQKwuuV0eY`9hloG{VZ#-RuJ@1p^p6CxaMSpdGdxyV9WrcGu}EfFo0HV zIfTEc@cI9r@dtQqmJMh^1KcWiXg*NX{NRtai;6?9$0Wl8pI0>>vFUYXd|3<{+Xd}i zI|3OWfcRbFMO6qWr0*R953GT14dCcJ2b%B!l@s8mUni(7dg}WnP^*tc1w1yx3u;(_ zN{$!1Km+PFD!t*LkN}O9FoH(=SYE7g19=$K9e)csRKN3m>$ein$#pE9pha99FB(9* zplVndy1{-1U1k9eg)Gn!aV!pCFa9r4aR7P$e~F3*EC4`5P!0h>z0IHi4hVly>w8*m_aXuGJ`AiST&0xGCLB{A~hHkC?^ks z+sBZVdJ5l;d?;l}<7H^z-+lq=Dw&{e9~B+YkuIGdUR1h+)&({n5diu6QmHW5Rte~V zPJ28+Hi8pf@C$aZ>DdQCOMO6ng)9cclf9FZFa7`j!o(fa*bx99W$P5n9`LrIOF*<}1;ND8-@y^SgCw6}P&%gj$sK~$ld*=oI^~d

-Redox +Redox

**Redox** is an operating system written in Rust, a language with focus on safety and high performance. Redox, following the microkernel design, aims to be secure, usable, and free. Redox is inspired by previous kernels and operating systems, such as SeL4, Minix, Plan 9, and BSD. @@ -53,19 +53,19 @@ The ecosystem and software Redox OS provides is listed below. | [libpager](https://github.com/redox-os/libpager) | [**@ticki**](https://github.com/ticki) | [Magnet (future package manager)](https://github.com/redox-os/magnet) | [**@ticki**](https://github.com/ticki) | [netutils](https://github.com/redox-os/netutils) | [**@jackpot51**](https://github.com/jackpot51) -| [orbclient (orbital client)](https://github.com/redox-os/orbclient) | [**@jackpot51**](https://github.com/jackpot51) +| [orbclient (Orbital client)](https://github.com/redox-os/orbclient) | [**@jackpot51**](https://github.com/jackpot51) | [orbdata](https://github.com/redox-os/orbdata) | [**@jackpot51**](https://github.com/jackpot51) -| [Orbital (windowing and compositing system](https://github.com/redox-os/orbital) | [**@jackpot51**](https://github.com/jackpot51) -| [orbtk (orbital toolkit)](https://github.com/redox-os/orbtk) | [**@stratact**](https://github.com/stratact) -| [orbutils (orbital utilities))](https://github.com/redox-os/orbutils) | [**@jackpot51**](https://github.com/jackpot51) +| [Orbital (windowing and compositing system)](https://github.com/redox-os/orbital) | [**@jackpot51**](https://github.com/jackpot51) +| [orbtk (Orbital toolkit)](https://github.com/redox-os/orbtk) | [**@stratact**](https://github.com/stratact) +| [orbutils (Orbital utilities)](https://github.com/redox-os/orbutils) | [**@jackpot51**](https://github.com/jackpot51) | [pkgutils (current package manager)](https://github.com/redox-os/pkgutils) | [**@jackpot51**](https://github.com/jackpot51) | [playbot (internal REPL bot)](https://github.com/redox-os/playbot) | [**@ticki**](https://github.com/ticki) | [ralloc](https://github.com/redox-os/ralloc) | [**@ticki**](https://github.com/ticki) -| [RANSID (rust ANSI driver)](https://github.com/redox-os/ransid) | [**@jackpot51**](https://github.com/jackpot51) +| [RANSID (Rust ANSI driver)](https://github.com/redox-os/ransid) | [**@jackpot51**](https://github.com/jackpot51) | [redoxfs (old filesystem)](https://github.com/redox-os/redoxfs) | [**@jackpot51**](https://github.com/jackpot51) | [syscall](https://github.com/redox-os/syscall) | [**@jackpot51**](https://github.com/jackpot51) -| [Sodium (vim-inspired text editor)](https://github.com/redox-os/sodium) | [**@ticki**](https://github.com/ticki) -| [libstd (Redox standard library](https://github.com/redox-os/libstd) | [**@jackpot51**](https://github.com/jackpot51) +| [Sodium (Vim-inspired text editor)](https://github.com/redox-os/sodium) | [**@ticki**](https://github.com/ticki) +| [libstd (Redox standard library)](https://github.com/redox-os/libstd) | [**@jackpot51**](https://github.com/jackpot51) | [userutils](https://github.com/redox-os/userutils) | [**@jackpot51**](https://github.com/jackpot51) | [TFS (ticki filesystem)](https://github.com/ticki/tfs) | [**@ticki**](https://github.com/ticki) | [The Redox book](https://github.com/redox-os/book) | [**@ticki**](https://github.com/ticki) From 06a2afb28a877b2872056462c969ba3fcee32029 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 16 Mar 2017 18:43:12 -0600 Subject: [PATCH 192/522] Update orbutils --- programs/orbutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/orbutils b/programs/orbutils index e4d585d..65a15a9 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit e4d585dba61513eed760941f07d1475759a86be5 +Subproject commit 65a15a90a2eb12eca91069212384d48feaa00182 From 9d76b7ce0872a0808dca8f6e15b35994f18327af Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 16 Mar 2017 22:45:15 -0600 Subject: [PATCH 193/522] Remove override for rustls --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 7e38736..db3c91b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,4 +39,3 @@ members = [ [replace] "jpeg-decoder:0.1.11" = { git = "https://github.com/redox-os/jpeg-decoder.git", branch = "single_thread" } "liner:0.1.3" = { git = "https://github.com/redox-os/liner.git", branch = "redox" } -"rustls:0.5.7" = { git = "https://github.com/ctz/rustls.git" } From 96189617e5a5167e2d262262f29e1a5355ff2fb7 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 16 Mar 2017 22:50:32 -0600 Subject: [PATCH 194/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index 7dd8de7..1d5c7d6 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 7dd8de777dca78c6608e8215d10d936edf8f5322 +Subproject commit 1d5c7d6a4e6e8b4169e6c21e4c6591151f7e25c9 From dc820b3508ea020d0cc53c8de4d1cf90988235ff Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 16 Mar 2017 22:52:20 -0600 Subject: [PATCH 195/522] Add more e1000 IDs --- filesystem/etc/pcid.toml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/filesystem/etc/pcid.toml b/filesystem/etc/pcid.toml index b68865e..f8a9515 100644 --- a/filesystem/etc/pcid.toml +++ b/filesystem/etc/pcid.toml @@ -1,10 +1,24 @@ [[drivers]] -name = "E1000 NIC" +name = "82543GC NIC" +class = 2 +vendor = 32902 +device = 4100 +command = ["/sbin/e1000d", "$NAME", "$BAR0", "$IRQ"] + +[[drivers]] +name = "82540EM NIC" class = 2 vendor = 32902 device = 4110 command = ["/sbin/e1000d", "$NAME", "$BAR0", "$IRQ"] +[[drivers]] +name = "82545EM NIC" +class = 2 +vendor = 32902 +device = 4111 +command = ["/sbin/e1000d", "$NAME", "$BAR0", "$IRQ"] + [[drivers]] name = "RTL8168 NIC" class = 2 From 9128f8069cca9d3a10ad6b9b1979b797e3906400 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 18 Mar 2017 09:16:16 -0600 Subject: [PATCH 196/522] Update orbital --- schemes/orbital | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schemes/orbital b/schemes/orbital index baa6fda..8ff5cff 160000 --- a/schemes/orbital +++ b/schemes/orbital @@ -1 +1 @@ -Subproject commit baa6fdac85e2df29c22f455ab5406a71b2a6ce97 +Subproject commit 8ff5cff332055907ace5a99460571791b05ec2dd From 70571bc064757441dc716f13e86cba9289e8502c Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 18 Mar 2017 12:11:05 -0600 Subject: [PATCH 197/522] Update ui --- filesystem/ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/filesystem/ui b/filesystem/ui index 638f87f..b14a4f6 160000 --- a/filesystem/ui +++ b/filesystem/ui @@ -1 +1 @@ -Subproject commit 638f87fe766b84d635f19806f52d041fe88e1743 +Subproject commit b14a4f6a1d50c1e284b312bec1a50b2f59465668 From 7e3bb25e7b612b71f688434c419888588d718080 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 19 Mar 2017 09:26:29 -0600 Subject: [PATCH 198/522] Update coreutils and ion --- programs/coreutils | 2 +- programs/ion | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/programs/coreutils b/programs/coreutils index 6637651..0222774 160000 --- a/programs/coreutils +++ b/programs/coreutils @@ -1 +1 @@ -Subproject commit 66376514f0b2ba55657b17549a7b02cffc7786af +Subproject commit 0222774182113f64e8e33e573e00f2f5f93543f7 diff --git a/programs/ion b/programs/ion index 5a6a5b9..78ea6c2 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit 5a6a5b9dde4629844adfee6cbfc970b4c9711046 +Subproject commit 78ea6c299f43b1fd65fa46168a4023ce63ad1f8f From f37f4bb4fd32bda07d8b10114125c192cd2dbeef Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 19 Mar 2017 16:45:51 -0600 Subject: [PATCH 199/522] Add shutdown support --- kernel | 2 +- mk/userspace/coreutils.mk | 2 +- programs/coreutils | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel b/kernel index 1d5c7d6..228cd79 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 1d5c7d6a4e6e8b4169e6c21e4c6591151f7e25c9 +Subproject commit 228cd79cd4baefbf72b6da7e70749488c888dc67 diff --git a/mk/userspace/coreutils.mk b/mk/userspace/coreutils.mk index 672df07..64200da 100644 --- a/mk/userspace/coreutils.mk +++ b/mk/userspace/coreutils.mk @@ -26,6 +26,7 @@ coreutils: \ filesystem/bin/rmdir \ filesystem/bin/rm \ filesystem/bin/seq \ + filesystem/bin/shutdown \ filesystem/bin/sleep \ filesystem/bin/sort \ filesystem/bin/tail \ @@ -37,7 +38,6 @@ coreutils: \ filesystem/bin/wc \ filesystem/bin/which \ filesystem/bin/yes - #filesystem/bin/shutdown filesystem/bin/%: programs/coreutils/Cargo.toml programs/coreutils/src/bin/%.rs $(BUILD)/libstd.rlib mkdir -p filesystem/bin diff --git a/programs/coreutils b/programs/coreutils index 0222774..e46d2fc 160000 --- a/programs/coreutils +++ b/programs/coreutils @@ -1 +1 @@ -Subproject commit 0222774182113f64e8e33e573e00f2f5f93543f7 +Subproject commit e46d2fccefc4fef455ca2be7c10142f81cb1573d From dea4ec095320c6b6c1199b85528f9cce392e661a Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 19 Mar 2017 16:46:15 -0600 Subject: [PATCH 200/522] Fix detection of initfs changes --- mk/initfs.mk | 22 ++++++++++++---------- mk/kernel.mk | 4 ++-- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/mk/initfs.mk b/mk/initfs.mk index df57df4..c6b9500 100644 --- a/mk/initfs.mk +++ b/mk/initfs.mk @@ -1,13 +1,15 @@ -$(BUILD)/initfs.rs: \ - initfs/bin/init \ - initfs/bin/ahcid \ - initfs/bin/bgad \ - initfs/bin/nvmed \ - initfs/bin/pcid \ - initfs/bin/ps2d \ - initfs/bin/redoxfs \ - initfs/bin/vesad \ - initfs/etc/** +$(KBUILD)/initfs.tag: initfs/bin/init \ + initfs/bin/ahcid \ + initfs/bin/bgad \ + initfs/bin/nvmed \ + initfs/bin/pcid \ + initfs/bin/ps2d \ + initfs/bin/redoxfs \ + initfs/bin/vboxd \ + initfs/bin/vesad \ + initfs/etc/** + $(KCARGO) clean --manifest-path kernel/Cargo.toml + touch $@ initfs/bin/%: programs/%/Cargo.toml programs/%/src/** $(BUILD)/libstd.rlib mkdir -p initfs/bin diff --git a/mk/kernel.mk b/mk/kernel.mk index 9760d0d..b4370b2 100644 --- a/mk/kernel.mk +++ b/mk/kernel.mk @@ -3,10 +3,10 @@ $(KBUILD)/libcollections.rlib: rust/src/libcollections/Cargo.toml rust/src/libco $(KCARGO) rustc --manifest-path $< $(KCARGOFLAGS) -o $@ cp rust/src/target/$(KTARGET)/release/deps/*.rlib $(KBUILD) -$(KBUILD)/libkernel.a: kernel/Cargo.toml kernel/arch/** kernel/src/** $(KBUILD)/libcollections.rlib $(BUILD)/initfs.rs +$(KBUILD)/libkernel.a: kernel/Cargo.toml kernel/arch/** kernel/src/** $(KBUILD)/libcollections.rlib $(KBUILD)/initfs.tag $(KCARGO) rustc --manifest-path $< --lib $(KCARGOFLAGS) -o $@ -$(KBUILD)/libkernel_live.a: kernel/Cargo.toml kernel/arch/** kernel/src/** $(KBUILD)/libcollections.rlib $(BUILD)/initfs.rs build/filesystem.bin +$(KBUILD)/libkernel_live.a: kernel/Cargo.toml kernel/arch/** kernel/src/** $(KBUILD)/libcollections.rlib $(KBUILD)/initfs.tag build/filesystem.bin $(KCARGO) rustc --manifest-path $< --lib --features live $(KCARGOFLAGS) -o $@ $(KBUILD)/kernel: $(KBUILD)/libkernel.a From f71fdad9759515059d5db982d639c9ddc9119048 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 20 Mar 2017 15:56:17 -0600 Subject: [PATCH 201/522] Update ion, update drivers --- Cargo.toml | 1 + drivers | 2 +- programs/ion | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index db3c91b..25f3d9b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ members = [ "drivers/pcid", "drivers/ps2d", "drivers/rtl8168d", + "drivers/vboxd", "drivers/vesad", "drivers/xhcid", "installer", diff --git a/drivers b/drivers index fe65978..66d2aa8 160000 --- a/drivers +++ b/drivers @@ -1 +1 @@ -Subproject commit fe65978ac46cbfd33851f09c985a212d01084499 +Subproject commit 66d2aa8c0150420db530b33a7119403af6c091e1 diff --git a/programs/ion b/programs/ion index 78ea6c2..f7e6772 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit 78ea6c299f43b1fd65fa46168a4023ce63ad1f8f +Subproject commit f7e67728d22a3721820a9587e790f8f52ef22dfb From d3e76de5e12644cf0bde5acf6768a88757ef30fb Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 20 Mar 2017 21:40:00 -0600 Subject: [PATCH 202/522] Update submodules --- drivers | 2 +- programs/orbutils | 2 +- schemes/orbital | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers b/drivers index 66d2aa8..63df9ff 160000 --- a/drivers +++ b/drivers @@ -1 +1 @@ -Subproject commit 66d2aa8c0150420db530b33a7119403af6c091e1 +Subproject commit 63df9fff38d58e3963962ca6da3966bbc29e102b diff --git a/programs/orbutils b/programs/orbutils index 65a15a9..27b59f7 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 65a15a90a2eb12eca91069212384d48feaa00182 +Subproject commit 27b59f74b1f0a29947349167df10e5b82ce02e74 diff --git a/schemes/orbital b/schemes/orbital index 8ff5cff..d622d6c 160000 --- a/schemes/orbital +++ b/schemes/orbital @@ -1 +1 @@ -Subproject commit 8ff5cff332055907ace5a99460571791b05ec2dd +Subproject commit d622d6c3620ab5aa4a3ca400cce1a21d29c03167 From b31a16dbba56ca5aa55fd7fad993b5fce2b4ca66 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 20 Mar 2017 21:40:19 -0600 Subject: [PATCH 203/522] Driver definition for vboxd --- initfs/etc/pcid.toml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/initfs/etc/pcid.toml b/initfs/etc/pcid.toml index 9b7e348..da0c570 100644 --- a/initfs/etc/pcid.toml +++ b/initfs/etc/pcid.toml @@ -11,15 +11,22 @@ subclass = 8 command = ["nvmed", "$NAME", "$BAR0", "$IRQ"] [[drivers]] -name = "Bochs Graphics Array" +name = "QEMU Graphics Array" class = 3 vendor = 4660 device = 4369 command = ["bgad", "$NAME", "$BAR0"] [[drivers]] -name = "Bochs Graphics Array" +name = "VirtualBox Graphics Array" class = 3 vendor = 33006 device = 48879 command = ["bgad", "$NAME", "$BAR0"] + +[[drivers]] +name = "VirtualBox Guest Device" +class = 8 +vendor = 33006 +device = 51966 +command = ["vboxd", "$NAME", "$BAR0", "$BAR1", "$IRQ"] From e1d16932e15c35de070cce99c0d53586c1b20897 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 20 Mar 2017 21:47:29 -0600 Subject: [PATCH 204/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index 228cd79..ffd7594 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 228cd79cd4baefbf72b6da7e70749488c888dc67 +Subproject commit ffd7594971f575662a9347e6fee363474319301d From 3d4e4f11c32049d41d51ae9e86ca522930606221 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 20 Mar 2017 22:01:38 -0600 Subject: [PATCH 205/522] Update drivers --- drivers | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers b/drivers index 63df9ff..f384376 160000 --- a/drivers +++ b/drivers @@ -1 +1 @@ -Subproject commit 63df9fff38d58e3963962ca6da3966bbc29e102b +Subproject commit f384376e194c65207473ca32b12f1e76a372570f From 91c903c3ac796825093508ba5e61408e1772f480 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 20 Mar 2017 22:04:56 -0600 Subject: [PATCH 206/522] Update Rust --- rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust b/rust index 0aeb9c1..134c4a0 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 0aeb9c12979e6da753701a798d04105b6b1a8c28 +Subproject commit 134c4a0f08a3d1f55ea8968fbe728fa935c71698 From 50effc4a70bd4eb3265fa7f33a5d1303987f67db Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 20 Mar 2017 22:24:10 -0600 Subject: [PATCH 207/522] Update drivers --- drivers | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers b/drivers index f384376..060934a 160000 --- a/drivers +++ b/drivers @@ -1 +1 @@ -Subproject commit f384376e194c65207473ca32b12f1e76a372570f +Subproject commit 060934a77df3850693778800deadcb5be1c3fb3b From 212c436c4fd8490e4a1bc44ae5af880c32780c68 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 20 Mar 2017 23:26:06 -0600 Subject: [PATCH 208/522] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 9962e4f..4d9a1d7 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ The website can be found at https://www.redox-os.org. Please make sure you use the **latest nightly** of `rustc` before building (for more troubleshooting, see ["Help! Redox won't compile!"](#compile-help)). [![Travis Build Status](https://travis-ci.org/redox-os/redox.svg?branch=master)](https://travis-ci.org/redox-os/redox) +[![Downloads](https://img.shields.io/github/downloads/redox-os/redox/total.svg)](https://githb.com/redox-os/releases) [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE.md) ![Rust Version](https://img.shields.io/badge/rust-rustc%201.16.0--nightly%20(24055d0f2%202017--01--31)-lightgrey.svg) From 9abf484c8b884a08c380b7517409660ebc73ab5d Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 20 Mar 2017 23:29:53 -0600 Subject: [PATCH 209/522] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4d9a1d7..0e28fa2 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@ The website can be found at https://www.redox-os.org. Please make sure you use the **latest nightly** of `rustc` before building (for more troubleshooting, see ["Help! Redox won't compile!"](#compile-help)). [![Travis Build Status](https://travis-ci.org/redox-os/redox.svg?branch=master)](https://travis-ci.org/redox-os/redox) -[![Downloads](https://img.shields.io/github/downloads/redox-os/redox/total.svg)](https://githb.com/redox-os/releases) +[![Downloads](https://img.shields.io/github/downloads/redox-os/redox/total.svg)](https://github.com/redox-os/redox/releases) [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE.md) -![Rust Version](https://img.shields.io/badge/rust-rustc%201.16.0--nightly%20(24055d0f2%202017--01--31)-lightgrey.svg) +![Rust Version](https://img.shields.io/badge/rust-nightly%202017--03--20-lightgrey.svg) ## Contents From cc43b3b4450c000058d12865dc7c536195e36e22 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 21 Mar 2017 20:49:44 -0600 Subject: [PATCH 210/522] Update kernel, coreutils, and ion --- kernel | 2 +- programs/coreutils | 2 +- programs/ion | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel b/kernel index ffd7594..906ef94 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit ffd7594971f575662a9347e6fee363474319301d +Subproject commit 906ef94ffd56b7ff2b5e425eac7a5ceb93ec6ad8 diff --git a/programs/coreutils b/programs/coreutils index e46d2fc..dcff976 160000 --- a/programs/coreutils +++ b/programs/coreutils @@ -1 +1 @@ -Subproject commit e46d2fccefc4fef455ca2be7c10142f81cb1573d +Subproject commit dcff9765ef13be1bcb45bfa663e6034671b1f716 diff --git a/programs/ion b/programs/ion index f7e6772..7a33445 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit f7e67728d22a3721820a9587e790f8f52ef22dfb +Subproject commit 7a33445935677ae41d6266aaf05f0f618febcae0 From 3deb3ea5d963bf755215bf2e3fb27addcbe541e1 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 21 Mar 2017 20:54:21 -0600 Subject: [PATCH 211/522] Update drivers --- drivers | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers b/drivers index 060934a..beef160 160000 --- a/drivers +++ b/drivers @@ -1 +1 @@ -Subproject commit 060934a77df3850693778800deadcb5be1c3fb3b +Subproject commit beef16096fb37b31b171f0f44b596c4a6019117d From fb35a645266b286aca6ea9db32a5ee7b4095a829 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 21 Mar 2017 21:24:14 -0600 Subject: [PATCH 212/522] Update orbutils --- programs/orbutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/orbutils b/programs/orbutils index 27b59f7..7a1c94c 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 27b59f74b1f0a29947349167df10e5b82ce02e74 +Subproject commit 7a1c94ce20065da3e64904aacb90e0b09efaf637 From a416b69888b8c57692254a166c7634fd31e7d29f Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 21 Mar 2017 21:42:51 -0600 Subject: [PATCH 213/522] Update orbital --- schemes/orbital | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schemes/orbital b/schemes/orbital index d622d6c..d85cfa3 160000 --- a/schemes/orbital +++ b/schemes/orbital @@ -1 +1 @@ -Subproject commit d622d6c3620ab5aa4a3ca400cce1a21d29c03167 +Subproject commit d85cfa35d0021a5f6a3a4a1e0239a756517ce89a From 6a56d2d08e1e20da62662afb3e7d98602cb15687 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 22 Mar 2017 13:16:15 -0600 Subject: [PATCH 214/522] Update drivers --- drivers | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers b/drivers index beef160..83dbbe2 160000 --- a/drivers +++ b/drivers @@ -1 +1 @@ -Subproject commit beef16096fb37b31b171f0f44b596c4a6019117d +Subproject commit 83dbbe2c418bc67d8aa2e2ff85de1c098221bdce From fc52cce83f42858669a507b2a74a92a16b184c34 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 22 Mar 2017 13:16:21 -0600 Subject: [PATCH 215/522] Update ion --- programs/ion | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/ion b/programs/ion index 7a33445..e53022f 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit 7a33445935677ae41d6266aaf05f0f618febcae0 +Subproject commit e53022f284ca075d8a17e2cd8b3d8a28b7d02b95 From 007603a53c81092d5ca5bcb5d4155e64ce97b94c Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 22 Mar 2017 13:47:30 -0600 Subject: [PATCH 216/522] Update rust --- rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust b/rust index 134c4a0..8c4f2c6 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 134c4a0f08a3d1f55ea8968fbe728fa935c71698 +Subproject commit 8c4f2c64c6759a82f143e23964a46a65c67509c9 From c5cd11cd80537f6af88076e02efad96068b510bf Mon Sep 17 00:00:00 2001 From: n0npax Date: Thu, 23 Mar 2017 07:01:58 +0100 Subject: [PATCH 217/522] add ln command to coreutils.mk --- mk/userspace/coreutils.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/mk/userspace/coreutils.mk b/mk/userspace/coreutils.mk index 64200da..8e330c3 100644 --- a/mk/userspace/coreutils.mk +++ b/mk/userspace/coreutils.mk @@ -15,6 +15,7 @@ coreutils: \ filesystem/bin/free \ filesystem/bin/head \ filesystem/bin/kill \ + filesystem/bin/ln \ filesystem/bin/ls \ filesystem/bin/mkdir \ filesystem/bin/mv \ From c01c1082f4dea109752866e8a92d3421fbbed529 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 23 Mar 2017 09:20:02 -0600 Subject: [PATCH 218/522] Update coreutils --- programs/coreutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/coreutils b/programs/coreutils index dcff976..c7acce9 160000 --- a/programs/coreutils +++ b/programs/coreutils @@ -1 +1 @@ -Subproject commit dcff9765ef13be1bcb45bfa663e6034671b1f716 +Subproject commit c7acce904a7ae76201af7769ed563ee387b91e9c From 003e4ff9058f62a67e61b3f2cda261b3bb9fb960 Mon Sep 17 00:00:00 2001 From: Richard Dodd Date: Fri, 24 Mar 2017 13:53:37 +0000 Subject: [PATCH 219/522] Don't install fuse if it's there already --- bootstrap.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap.sh b/bootstrap.sh index 643634f..a72ccfd 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -163,7 +163,7 @@ archLinux() fi echo "Installing fuse..." - sudo pacman -S fuse + sudo pacman -S --needed fuse } ############################################################################### From 435fb0b93215ec2f940abec16b3853daf03e4144 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 25 Mar 2017 10:25:13 +0100 Subject: [PATCH 220/522] Allow entering redox version in issue template. --- .github/ISSUE_TEMPLATE | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE index 204f577..00b7db7 100644 --- a/.github/ISSUE_TEMPLATE +++ b/.github/ISSUE_TEMPLATE @@ -4,7 +4,8 @@ **Actual behavior**: [describe the actual behavior, which is presented through the repro.]. -**Build information**: [output of `rustc -V`, `git rev-parse HEAD`, `qemu-i386 -version`, `uname -a`, etc.] +**Build information**: [only when using a self build version: output of `rustc -V`, `git rev-parse HEAD` `qemu-i386 -version`, `uname -a`, etc.] +**Redox release**: [only when using a prebuild version: redox version] **Blocking/related**: [issues or PRs blocking or being related to this issue.] From 63779b5df7dd7284f863c27a535440bf7eb1175b Mon Sep 17 00:00:00 2001 From: Niklas Claesson Date: Mon, 27 Mar 2017 17:13:06 +0200 Subject: [PATCH 221/522] Use absolute paths to virtualbox options --- mk/virtualbox.mk | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mk/virtualbox.mk b/mk/virtualbox.mk index a7d5d9d..b87e591 100644 --- a/mk/virtualbox.mk +++ b/mk/virtualbox.mk @@ -1,3 +1,4 @@ +BUILDDIR = $(abspath $(dir $(firstword $(MAKEFILE_LIST))))/build virtualbox: build/harddrive.bin echo "Delete VM" -$(VBM) unregistervm Redox --delete; \ @@ -22,10 +23,10 @@ virtualbox: build/harddrive.bin $(VBM) modifyvm Redox --nictype1 82540EM; \ $(VBM) modifyvm Redox --cableconnected1 on; \ $(VBM) modifyvm Redox --nictrace1 on; \ - $(VBM) modifyvm Redox --nictracefile1 build/network.pcap; \ + $(VBM) modifyvm Redox --nictracefile1 "$(BUILDDIR)/redox_network.pcap"; \ fi $(VBM) modifyvm Redox --uart1 0x3F8 4 - $(VBM) modifyvm Redox --uartmode1 file build/serial.log + $(VBM) modifyvm Redox --uartmode1 file "$(BUILDDIR)/redox_serial.log" $(VBM) modifyvm Redox --usb off # on $(VBM) modifyvm Redox --keyboard ps2 $(VBM) modifyvm Redox --mouse ps2 From 5dcd4ef65d8471ebaecfafd7d6596844b2cc92d3 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 27 Mar 2017 11:39:27 -0600 Subject: [PATCH 222/522] Update smith --- programs/smith | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/smith b/programs/smith index 41596f2..77883e3 160000 --- a/programs/smith +++ b/programs/smith @@ -1 +1 @@ -Subproject commit 41596f26c0d19278cf2c953569740048fe72011e +Subproject commit 77883e3ca200386344c6babacff852f296b7c541 From 5bd3447386da747ca0e0b5d90b6a105f1a4ed841 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Mon, 27 Mar 2017 13:13:31 -0700 Subject: [PATCH 223/522] tcpd: fix dup with address --- schemes/tcpd/src/main.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/schemes/tcpd/src/main.rs b/schemes/tcpd/src/main.rs index 5344abf..af18237 100644 --- a/schemes/tcpd/src/main.rs +++ b/schemes/tcpd/src/main.rs @@ -548,6 +548,8 @@ impl SchemeMut for Tcpd { let ip = new_handle.create_ip(self.rng.gen(), tcp.to_bytes()); self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO))).and(Ok(buf.len()))?; + new_handle.seq += 1; + Handle::Tcp(new_handle) } else { return Err(Error::new(EINVAL)); From 47077aee1202c29e865d2f25f6a614bdc0e2e7b6 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 27 Mar 2017 18:27:56 -0600 Subject: [PATCH 224/522] Update drivers, kernel, coreutils, extrautils, ion, and orbutils --- drivers | 2 +- kernel | 2 +- programs/coreutils | 2 +- programs/extrautils | 2 +- programs/ion | 2 +- programs/orbutils | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers b/drivers index 83dbbe2..2199185 160000 --- a/drivers +++ b/drivers @@ -1 +1 @@ -Subproject commit 83dbbe2c418bc67d8aa2e2ff85de1c098221bdce +Subproject commit 21991855fd98b6943251521e30677c9d24a74a54 diff --git a/kernel b/kernel index 906ef94..cbacd0e 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 906ef94ffd56b7ff2b5e425eac7a5ceb93ec6ad8 +Subproject commit cbacd0eea72df3bf5fa3040368fba39dc37350dd diff --git a/programs/coreutils b/programs/coreutils index c7acce9..4bf1255 160000 --- a/programs/coreutils +++ b/programs/coreutils @@ -1 +1 @@ -Subproject commit c7acce904a7ae76201af7769ed563ee387b91e9c +Subproject commit 4bf12550d8147ed230df5ca9b394e45523385777 diff --git a/programs/extrautils b/programs/extrautils index a2dc3d7..bd17000 160000 --- a/programs/extrautils +++ b/programs/extrautils @@ -1 +1 @@ -Subproject commit a2dc3d7d0e6337645aad070ee2895bbb96d2e3d2 +Subproject commit bd17000e2732f24fb534622335794f5032b9ea23 diff --git a/programs/ion b/programs/ion index e53022f..e120af9 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit e53022f284ca075d8a17e2cd8b3d8a28b7d02b95 +Subproject commit e120af98c8af8fc2e7f2356cec3d5ac4b20ac45a diff --git a/programs/orbutils b/programs/orbutils index 7a1c94c..ad97b57 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 7a1c94ce20065da3e64904aacb90e0b09efaf637 +Subproject commit ad97b57568f128b289a39ea0d0f8367c22a02965 From deeb218b765a2041186e4d5f996214fc15473443 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 27 Mar 2017 18:36:13 -0600 Subject: [PATCH 225/522] Update drivers, orbital --- drivers | 2 +- schemes/orbital | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers b/drivers index 2199185..f872fee 160000 --- a/drivers +++ b/drivers @@ -1 +1 @@ -Subproject commit 21991855fd98b6943251521e30677c9d24a74a54 +Subproject commit f872fee4e6d1e453ec2fe66fc9f5dab4762e3555 diff --git a/schemes/orbital b/schemes/orbital index d85cfa3..fbc5dae 160000 --- a/schemes/orbital +++ b/schemes/orbital @@ -1 +1 @@ -Subproject commit d85cfa35d0021a5f6a3a4a1e0239a756517ce89a +Subproject commit fbc5daeb2f65e54b924da464b1d5a34fc53a1bb3 From 4a20c8f6c01c5f34b3ea55085ce141f5f908a249 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 27 Mar 2017 18:55:06 -0600 Subject: [PATCH 226/522] Use patched termion, add resize executable, update rust nightly version --- Cargo.toml | 1 + README.md | 2 +- mk/userspace/extrautils.mk | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 25f3d9b..ec5436b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,3 +40,4 @@ members = [ [replace] "jpeg-decoder:0.1.11" = { git = "https://github.com/redox-os/jpeg-decoder.git", branch = "single_thread" } "liner:0.1.3" = { git = "https://github.com/redox-os/liner.git", branch = "redox" } +"termion:1.3.0" = { git = "https://github.com/redox-os/termion.git" } diff --git a/README.md b/README.md index 0e28fa2..52c1d32 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Please make sure you use the **latest nightly** of `rustc` before building (for [![Travis Build Status](https://travis-ci.org/redox-os/redox.svg?branch=master)](https://travis-ci.org/redox-os/redox) [![Downloads](https://img.shields.io/github/downloads/redox-os/redox/total.svg)](https://github.com/redox-os/redox/releases) [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE.md) -![Rust Version](https://img.shields.io/badge/rust-nightly%202017--03--20-lightgrey.svg) +![Rust Version](https://img.shields.io/badge/rust-nightly%202017--03--23-lightgrey.svg) ## Contents diff --git a/mk/userspace/extrautils.mk b/mk/userspace/extrautils.mk index 7a7774b..a24b6d1 100644 --- a/mk/userspace/extrautils.mk +++ b/mk/userspace/extrautils.mk @@ -8,6 +8,7 @@ extrautils: \ filesystem/bin/mdless \ filesystem/bin/mtxt \ filesystem/bin/rem \ + filesystem/bin/resize \ filesystem/bin/screenfetch #filesystem/bin/dmesg filesystem/bin/info filesystem/bin/watch From e78fe5dcf4676351651e5850aed2856d47753a3e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 27 Mar 2017 20:13:57 -0600 Subject: [PATCH 227/522] Remove termion override --- Cargo.toml | 1 - programs/extrautils | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ec5436b..25f3d9b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,4 +40,3 @@ members = [ [replace] "jpeg-decoder:0.1.11" = { git = "https://github.com/redox-os/jpeg-decoder.git", branch = "single_thread" } "liner:0.1.3" = { git = "https://github.com/redox-os/liner.git", branch = "redox" } -"termion:1.3.0" = { git = "https://github.com/redox-os/termion.git" } diff --git a/programs/extrautils b/programs/extrautils index bd17000..38a09e7 160000 --- a/programs/extrautils +++ b/programs/extrautils @@ -1 +1 @@ -Subproject commit bd17000e2732f24fb534622335794f5032b9ea23 +Subproject commit 38a09e71902413226aeaed4283196cb3f1ce1e13 From 8023270bda60a936fe281cdf3fab1c38598a960a Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 1 Apr 2017 21:12:53 -0600 Subject: [PATCH 228/522] Update submodules --- cookbook | 2 +- kernel | 2 +- programs/binutils | 2 +- programs/coreutils | 2 +- programs/ion | 2 +- programs/orbutils | 2 +- programs/smith | 2 +- schemes/orbital | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cookbook b/cookbook index cfa1711..f57cd8d 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit cfa1711df81e5d8b7ceff6c3ccc1d3870435177e +Subproject commit f57cd8dfc5973ad0f0901faa1b2be4c5dfa3678e diff --git a/kernel b/kernel index cbacd0e..be7f8d6 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit cbacd0eea72df3bf5fa3040368fba39dc37350dd +Subproject commit be7f8d64e665498f290a5422a019edc519c36b64 diff --git a/programs/binutils b/programs/binutils index 5599724..ce057ba 160000 --- a/programs/binutils +++ b/programs/binutils @@ -1 +1 @@ -Subproject commit 5599724eab8b28705f6b2b66145fdcb7e4ce2d4d +Subproject commit ce057bac70f18fe7fd004c68e58c07c1cc7174e0 diff --git a/programs/coreutils b/programs/coreutils index 4bf1255..c55c5b3 160000 --- a/programs/coreutils +++ b/programs/coreutils @@ -1 +1 @@ -Subproject commit 4bf12550d8147ed230df5ca9b394e45523385777 +Subproject commit c55c5b3dc3d149d62492c691b908898ea0d33603 diff --git a/programs/ion b/programs/ion index e120af9..3b26bb0 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit e120af98c8af8fc2e7f2356cec3d5ac4b20ac45a +Subproject commit 3b26bb0847ff3e9720a357e9c3d25736a46d4ce0 diff --git a/programs/orbutils b/programs/orbutils index ad97b57..644203b 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit ad97b57568f128b289a39ea0d0f8367c22a02965 +Subproject commit 644203b5e3b8d27496e6df29987f3fc6096965cc diff --git a/programs/smith b/programs/smith index 77883e3..aae147e 160000 --- a/programs/smith +++ b/programs/smith @@ -1 +1 @@ -Subproject commit 77883e3ca200386344c6babacff852f296b7c541 +Subproject commit aae147ec680994e3a849a7816bcaafa8327dc5a5 diff --git a/schemes/orbital b/schemes/orbital index fbc5dae..504eee8 160000 --- a/schemes/orbital +++ b/schemes/orbital @@ -1 +1 @@ -Subproject commit fbc5daeb2f65e54b924da464b1d5a34fc53a1bb3 +Subproject commit 504eee854b48cf06b5e0d6877e4066efdcb412c9 From 1a8759e68eaad618a7970d38d375ee93a425e2c3 Mon Sep 17 00:00:00 2001 From: Emanuele Antonio Faraone Date: Mon, 3 Apr 2017 12:39:29 +0200 Subject: [PATCH 229/522] New screenshots part two of this: https://github.com/redox-os/assets/pull/1 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 52c1d32..d43194e 100644 --- a/README.md +++ b/README.md @@ -29,11 +29,11 @@ Please make sure you use the **latest nightly** of `rustc` before building (for Redox Redox -Redox +Redox Redox Redox -Redox +Redox ## Ecosystem From b95d6ecbb99be771c06c6813c8b9802678b89874 Mon Sep 17 00:00:00 2001 From: Emanuele Antonio Faraone Date: Mon, 3 Apr 2017 15:03:52 +0200 Subject: [PATCH 230/522] Alphabetical order fix Alphabetical order fix, and a small change. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d43194e..a93e1cc 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ **Redox** is an operating system written in Rust, a language with focus on safety and high performance. Redox, following the microkernel design, aims to be secure, usable, and free. Redox is inspired by previous kernels and operating systems, such as SeL4, Minix, Plan 9, and BSD. -Redox _is not_ just a kernel, it's a full-featured Operating System, providing packages (memory allocator, file system, display manager, core utilities, etc.) that together make up a functional and convenient operating system. You can loosely think of it as the GNU or BSD ecosystem, but in a memory safe language and with modern technology. See [this list](#ecosystem) for overview of the ecosystem. +Redox _is not_ just a kernel, it's a **full-featured Operating System**, providing packages (memory allocator, file system, display manager, core utilities, etc.) that together make up a functional and convenient operating system. You can loosely think of it as the GNU or BSD ecosystem, but in a memory safe language and with modern technology. See [this list](#ecosystem) for overview of the ecosystem. The website can be found at https://www.redox-os.org. @@ -52,6 +52,7 @@ The ecosystem and software Redox OS provides is listed below. | [kernel](https://github.com/redox-os/kernel) | [**@jackpot51**](https://github.com/jackpot51) | [libextra](https://github.com/redox-os/libextra) | [**@ticki**](https://github.com/ticki) | [libpager](https://github.com/redox-os/libpager) | [**@ticki**](https://github.com/ticki) +| [libstd (Redox standard library)](https://github.com/redox-os/libstd) | [**@jackpot51**](https://github.com/jackpot51) | [Magnet (future package manager)](https://github.com/redox-os/magnet) | [**@ticki**](https://github.com/ticki) | [netutils](https://github.com/redox-os/netutils) | [**@jackpot51**](https://github.com/jackpot51) | [orbclient (Orbital client)](https://github.com/redox-os/orbclient) | [**@jackpot51**](https://github.com/jackpot51) @@ -66,7 +67,6 @@ The ecosystem and software Redox OS provides is listed below. | [redoxfs (old filesystem)](https://github.com/redox-os/redoxfs) | [**@jackpot51**](https://github.com/jackpot51) | [syscall](https://github.com/redox-os/syscall) | [**@jackpot51**](https://github.com/jackpot51) | [Sodium (Vim-inspired text editor)](https://github.com/redox-os/sodium) | [**@ticki**](https://github.com/ticki) -| [libstd (Redox standard library)](https://github.com/redox-os/libstd) | [**@jackpot51**](https://github.com/jackpot51) | [userutils](https://github.com/redox-os/userutils) | [**@jackpot51**](https://github.com/jackpot51) | [TFS (ticki filesystem)](https://github.com/ticki/tfs) | [**@ticki**](https://github.com/ticki) | [The Redox book](https://github.com/redox-os/book) | [**@ticki**](https://github.com/ticki) From 29e6283840a875469ec0a4f42c9269cc8053ff78 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 5 Apr 2017 20:11:30 -0600 Subject: [PATCH 231/522] Update submodules --- Cargo.toml | 2 +- README.md | 2 +- kernel | 2 +- mk/kernel.mk | 8 ++++---- programs/ion | 2 +- programs/orbutils | 2 +- programs/pkgutils | 2 +- programs/smith | 2 +- rust | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 25f3d9b..8ec8394 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,4 +39,4 @@ members = [ [replace] "jpeg-decoder:0.1.11" = { git = "https://github.com/redox-os/jpeg-decoder.git", branch = "single_thread" } -"liner:0.1.3" = { git = "https://github.com/redox-os/liner.git", branch = "redox" } +"termion:1.3.0" = { git = "https://github.com/redox-os/termion.git" } diff --git a/README.md b/README.md index d43194e..71c3501 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Please make sure you use the **latest nightly** of `rustc` before building (for [![Travis Build Status](https://travis-ci.org/redox-os/redox.svg?branch=master)](https://travis-ci.org/redox-os/redox) [![Downloads](https://img.shields.io/github/downloads/redox-os/redox/total.svg)](https://github.com/redox-os/redox/releases) [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE.md) -![Rust Version](https://img.shields.io/badge/rust-nightly%202017--03--23-lightgrey.svg) +![Rust Version](https://img.shields.io/badge/rust-nightly%202017--04--04-lightgrey.svg) ## Contents diff --git a/kernel b/kernel index be7f8d6..d26a9ee 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit be7f8d64e665498f290a5422a019edc519c36b64 +Subproject commit d26a9ee990016c9721a0748abd0329946dc63552 diff --git a/mk/kernel.mk b/mk/kernel.mk index b4370b2..5d56370 100644 --- a/mk/kernel.mk +++ b/mk/kernel.mk @@ -3,14 +3,14 @@ $(KBUILD)/libcollections.rlib: rust/src/libcollections/Cargo.toml rust/src/libco $(KCARGO) rustc --manifest-path $< $(KCARGOFLAGS) -o $@ cp rust/src/target/$(KTARGET)/release/deps/*.rlib $(KBUILD) -$(KBUILD)/libkernel.a: kernel/Cargo.toml kernel/arch/** kernel/src/** $(KBUILD)/libcollections.rlib $(KBUILD)/initfs.tag +$(KBUILD)/libkernel.a: kernel/Cargo.toml kernel/src/** $(KBUILD)/libcollections.rlib $(KBUILD)/initfs.tag $(KCARGO) rustc --manifest-path $< --lib $(KCARGOFLAGS) -o $@ -$(KBUILD)/libkernel_live.a: kernel/Cargo.toml kernel/arch/** kernel/src/** $(KBUILD)/libcollections.rlib $(KBUILD)/initfs.tag build/filesystem.bin +$(KBUILD)/libkernel_live.a: kernel/Cargo.toml kernel/src/** $(KBUILD)/libcollections.rlib $(KBUILD)/initfs.tag build/filesystem.bin $(KCARGO) rustc --manifest-path $< --lib --features live $(KCARGOFLAGS) -o $@ $(KBUILD)/kernel: $(KBUILD)/libkernel.a - $(LD) $(LDFLAGS) -z max-page-size=0x1000 -T kernel/arch/$(ARCH)/src/linker.ld -o $@ $< + $(LD) $(LDFLAGS) -z max-page-size=0x1000 -T kernel/linkers/$(ARCH).ld -o $@ $< $(KBUILD)/kernel_live: $(KBUILD)/libkernel_live.a - $(LD) $(LDFLAGS) -z max-page-size=0x1000 -T kernel/arch/$(ARCH)/src/linker.ld -o $@ $< + $(LD) $(LDFLAGS) -z max-page-size=0x1000 -T kernel/linkers/$(ARCH).ld -o $@ $< diff --git a/programs/ion b/programs/ion index 3b26bb0..dd052ae 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit 3b26bb0847ff3e9720a357e9c3d25736a46d4ce0 +Subproject commit dd052ae9591bfd83b9cb9210927e917e5ebbc4f6 diff --git a/programs/orbutils b/programs/orbutils index 644203b..eeafcf1 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 644203b5e3b8d27496e6df29987f3fc6096965cc +Subproject commit eeafcf19c9fcd212c8881686511208e90322bbbf diff --git a/programs/pkgutils b/programs/pkgutils index ffb3069..a93e7d6 160000 --- a/programs/pkgutils +++ b/programs/pkgutils @@ -1 +1 @@ -Subproject commit ffb30696a86de68c0c26563957fadaab8f9f657c +Subproject commit a93e7d658e7b6120614bca2f1b8ade5073c23621 diff --git a/programs/smith b/programs/smith index aae147e..8f68825 160000 --- a/programs/smith +++ b/programs/smith @@ -1 +1 @@ -Subproject commit aae147ec680994e3a849a7816bcaafa8327dc5a5 +Subproject commit 8f68825b06d14309eb3723f9c76f77b0e90ebee9 diff --git a/rust b/rust index 8c4f2c6..91ae22a 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 8c4f2c64c6759a82f143e23964a46a65c67509c9 +Subproject commit 91ae22a012fae7fa7589b1bba77bf4579708ee33 From af71453a2ec54bdab5ef210f0fa7e58a46fc933b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 5 Apr 2017 20:12:02 -0600 Subject: [PATCH 232/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index d26a9ee..a7f35e1 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit d26a9ee990016c9721a0748abd0329946dc63552 +Subproject commit a7f35e14cc0be480963b7094d1de5a8c1d3fa190 From bca05bccd772b4a858b079b134ef116839557cc7 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 5 Apr 2017 20:17:11 -0600 Subject: [PATCH 233/522] Update orbutils --- programs/orbutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/orbutils b/programs/orbutils index eeafcf1..39ba3c5 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit eeafcf19c9fcd212c8881686511208e90322bbbf +Subproject commit 39ba3c5bbe3956a3e02f21d78660566102e6cc50 From 03abf9c32b29d67ecb864d061e3b1b98a8fd4680 Mon Sep 17 00:00:00 2001 From: Petr Date: Thu, 6 Apr 2017 22:33:50 +0300 Subject: [PATCH 234/522] Make easy targets section more readable. For me (and as I think, for many others) it was very difficult to distinguish tasks that are proposed for Rust fluent developers (as well as OS and non-OS experts) and Rust newbies. Now it should be easier to read and understand. --- CONTRIBUTING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 83a3844..0f25fd0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -61,21 +61,21 @@ News and updates for Redox are posted at [redox-os.org/news](https://redox-os.or ### Low-Hanging Fruit - Easy Targets for Newbies -* If you're not fluent in Rust: +#### If you're not fluent in Rust: * Writing documentation * Using/testing Redox, filing issues for bugs and needed features * Web development ([Redox website, separate repo](https://github.com/redox-os/website)) * Writing unit tests (may require minimal knowledge of rust) -* If you are fluent in Rust, but not OS Development: +#### If you are fluent in Rust, but not OS Development: * Apps development * Shell ([Ion](https://github.com/redox-os/ion)) development * Package manager ([Magnet](https://github.com/redox-os/magnet)) development * Other high-level code tasks -* If you are fluent in Rust, and have experience with OS Dev: +#### If you are fluent in Rust, and have experience with OS Dev: * Familiarize yourself with the repository and codebase * Grep for `TODO`, `FIXME`, `BUG`, `UNOPTIMIZED`, `REWRITEME`, `DOCME`, and `PRETTYFYME` and fix the code you find. From ebfa32e4e26490549e30a1b093ef67653ed83f8c Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 6 Apr 2017 21:08:37 -0600 Subject: [PATCH 235/522] Add repo configuration --- filesystem/etc/pkg.d/50_redox | 1 + 1 file changed, 1 insertion(+) create mode 100644 filesystem/etc/pkg.d/50_redox diff --git a/filesystem/etc/pkg.d/50_redox b/filesystem/etc/pkg.d/50_redox new file mode 100644 index 0000000..4048482 --- /dev/null +++ b/filesystem/etc/pkg.d/50_redox @@ -0,0 +1 @@ +https://static.redox-os.org/pkg From 96bd85d08e60fbc3aae8abe9229452166974de2e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 6 Apr 2017 21:09:06 -0600 Subject: [PATCH 236/522] Update ion, pkgutils, userutils --- programs/ion | 2 +- programs/pkgutils | 2 +- programs/userutils | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/programs/ion b/programs/ion index dd052ae..6f51847 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit dd052ae9591bfd83b9cb9210927e917e5ebbc4f6 +Subproject commit 6f51847afcc7439d14926cf9249c23700f5c7e37 diff --git a/programs/pkgutils b/programs/pkgutils index a93e7d6..260a657 160000 --- a/programs/pkgutils +++ b/programs/pkgutils @@ -1 +1 @@ -Subproject commit a93e7d658e7b6120614bca2f1b8ade5073c23621 +Subproject commit 260a6578ab37454cfe902fafd2d41ec670f779e4 diff --git a/programs/userutils b/programs/userutils index 1ee223f..3ca1891 160000 --- a/programs/userutils +++ b/programs/userutils @@ -1 +1 @@ -Subproject commit 1ee223f9267113c8fb9e7db10c3704e768c2e9c4 +Subproject commit 3ca18917f88130f4734bcb4643a410e62e6cb24c From ae4bcb43e75c397d7a8260f99b3843629b1bb407 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 6 Apr 2017 21:43:02 -0600 Subject: [PATCH 237/522] Add gunzip/gzip --- mk/userspace/extrautils.mk | 2 ++ programs/extrautils | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/mk/userspace/extrautils.mk b/mk/userspace/extrautils.mk index a24b6d1..3f1843f 100644 --- a/mk/userspace/extrautils.mk +++ b/mk/userspace/extrautils.mk @@ -3,6 +3,8 @@ extrautils: \ filesystem/bin/cksum \ filesystem/bin/cur \ filesystem/bin/grep \ + filesystem/bin/gunzip \ + filesystem/bin/gzip \ filesystem/bin/less \ filesystem/bin/man \ filesystem/bin/mdless \ diff --git a/programs/extrautils b/programs/extrautils index 38a09e7..728da8d 160000 --- a/programs/extrautils +++ b/programs/extrautils @@ -1 +1 @@ -Subproject commit 38a09e71902413226aeaed4283196cb3f1ce1e13 +Subproject commit 728da8d08a57eb3e6db9e2b18c5b8e6a7e664a79 From e695897fe8d4ee1a08511a1839a647fa0be1743b Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Fri, 7 Apr 2017 18:36:09 -0700 Subject: [PATCH 238/522] tcpd: Fix behavior when reading to small buffer --- schemes/tcpd/src/main.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/schemes/tcpd/src/main.rs b/schemes/tcpd/src/main.rs index af18237..6bd53bc 100644 --- a/schemes/tcpd/src/main.rs +++ b/schemes/tcpd/src/main.rs @@ -574,12 +574,16 @@ impl SchemeMut for Tcpd { Handle::Tcp(ref mut handle) => { if ! handle.is_connected() { return Err(Error::new(ENOTCONN)); - } else if let Some((_ip, tcp)) = handle.data.pop_front() { + } else if let Some((ip, mut tcp)) = handle.data.pop_front() { let mut i = 0; - while i < buf.len() && i < tcp.data.len() { - buf[i] = tcp.data[i]; + let mut len = std::cmp::min(buf.len(), tcp.data.len()); + for c in tcp.data.drain(0..len) { + buf[i] = c; i += 1; } + if !tcp.data.is_empty() { + handle.data.push_front((ip, tcp)); + } return Ok(i); } else if handle.flags & O_NONBLOCK == O_NONBLOCK || handle.read_closed() { From 691252e72ca828dc99267c6941d8f9e1eb067553 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Fri, 7 Apr 2017 18:41:12 -0700 Subject: [PATCH 239/522] Slight simplification by using .enumerate() --- schemes/tcpd/src/main.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/schemes/tcpd/src/main.rs b/schemes/tcpd/src/main.rs index 6bd53bc..6660563 100644 --- a/schemes/tcpd/src/main.rs +++ b/schemes/tcpd/src/main.rs @@ -575,17 +575,15 @@ impl SchemeMut for Tcpd { if ! handle.is_connected() { return Err(Error::new(ENOTCONN)); } else if let Some((ip, mut tcp)) = handle.data.pop_front() { - let mut i = 0; - let mut len = std::cmp::min(buf.len(), tcp.data.len()); - for c in tcp.data.drain(0..len) { + let len = std::cmp::min(buf.len(), tcp.data.len()); + for (i, c) in tcp.data.drain(0..len).enumerate() { buf[i] = c; - i += 1; } if !tcp.data.is_empty() { handle.data.push_front((ip, tcp)); } - return Ok(i); + return Ok(len); } else if handle.flags & O_NONBLOCK == O_NONBLOCK || handle.read_closed() { return Ok(0); } else { From c90b6e9d19e6b1c65aac9a21d367b92ae47e7572 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 7 Apr 2017 19:58:33 -0600 Subject: [PATCH 240/522] Update installer and ion --- installer | 2 +- programs/ion | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/installer b/installer index cfdb2a4..4e9d22a 160000 --- a/installer +++ b/installer @@ -1 +1 @@ -Subproject commit cfdb2a49686c7bc64d2040dfdbb0650f792b4270 +Subproject commit 4e9d22ada4e650b8440e8c61ee653381b6b6a5ca diff --git a/programs/ion b/programs/ion index 6f51847..962a5e0 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit 6f51847afcc7439d14926cf9249c23700f5c7e37 +Subproject commit 962a5e03d7fa7efae1bdef6b10c3d59b5c89ebdd From 994f3d4d7b7a2eea1f4477495956b2a875c641ec Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 7 Apr 2017 20:28:12 -0600 Subject: [PATCH 241/522] Do not include display scheme --- programs/contain/src/main.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/programs/contain/src/main.rs b/programs/contain/src/main.rs index caefc16..a19acaf 100644 --- a/programs/contain/src/main.rs +++ b/programs/contain/src/main.rs @@ -19,7 +19,6 @@ fn usage() -> ! { fn enter(root: &Path, cmd: &str, args: &[String]) { let names = [ - "display", "pty", "rand", "tcp", From 0f0dab62e706af736b39b647acf2238e590aa060 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 7 Apr 2017 20:30:45 -0600 Subject: [PATCH 242/522] Update netutils, more advanced installer file --- filesystem/etc/{installer/minimal.toml => installer.toml} | 4 ++++ programs/netutils | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) rename filesystem/etc/{installer/minimal.toml => installer.toml} (88%) diff --git a/filesystem/etc/installer/minimal.toml b/filesystem/etc/installer.toml similarity index 88% rename from filesystem/etc/installer/minimal.toml rename to filesystem/etc/installer.toml index 535dc4d..e85d219 100644 --- a/filesystem/etc/installer/minimal.toml +++ b/filesystem/etc/installer.toml @@ -10,6 +10,10 @@ prompt = false coreutils = {} extrautils = {} ion = {} +netutils = {} +pkgutils = {} +tar = {} +userutils = {} # User settings [users.root] diff --git a/programs/netutils b/programs/netutils index b252355..ca1ef11 160000 --- a/programs/netutils +++ b/programs/netutils @@ -1 +1 @@ -Subproject commit b252355a9838d3be06d9446e6443c59c6d0a3305 +Subproject commit ca1ef1149741dd10a3d4d8f7c8ff523d1663ac83 From 4f329b88795c945df674b05076da18cdcc9518c3 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 7 Apr 2017 21:13:42 -0600 Subject: [PATCH 243/522] Install necessary config files --- filesystem/etc/installer.toml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/filesystem/etc/installer.toml b/filesystem/etc/installer.toml index e85d219..34347d2 100644 --- a/filesystem/etc/installer.toml +++ b/filesystem/etc/installer.toml @@ -15,6 +15,26 @@ pkgutils = {} tar = {} userutils = {} +[[files]] +path = "/etc/net/dns" +data = "208.67.222.222" + +[[files]] +path = "/etc/net/ip" +data = "10.0.2.15" + +[[files]] +path = "/etc/net/ip_router" +data = "10.0.2.2" + +[[files]] +path = "/etc/net/ip_subnet" +data = "255.255.255.0" + +[[files]] +path = "/etc/pkg.d/50_redox" +data = "https://static.redox-os.org/pkg" + # User settings [users.root] # Password is set to "password" From 00592767412dae63682d6c5d7e5c96cba73e8f4e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 7 Apr 2017 21:25:16 -0600 Subject: [PATCH 244/522] Do not include games or binutils by default --- .gitmodules | 6 ------ Cargo.toml | 2 -- mk/userspace/binutils.mk | 9 --------- mk/userspace/games.mk | 13 ------------- mk/userspace/mod.mk | 4 ---- programs/binutils | 1 - programs/games | 1 - 7 files changed, 36 deletions(-) delete mode 100644 mk/userspace/binutils.mk delete mode 100644 mk/userspace/games.mk delete mode 160000 programs/binutils delete mode 160000 programs/games diff --git a/.gitmodules b/.gitmodules index 8d3eafd..4530000 100644 --- a/.gitmodules +++ b/.gitmodules @@ -46,15 +46,9 @@ [submodule "docgen"] path = docgen url = https://github.com/redox-os/docgen.git -[submodule "programs/binutils"] - path = programs/binutils - url = https://github.com/redox-os/binutils.git [submodule "libc-artifacts"] path = libc-artifacts url = https://github.com/redox-os/libc-artifacts.git -[submodule "programs/games"] - path = programs/games - url = https://github.com/redox-os/games.git [submodule "kernel"] path = kernel url = https://github.com/redox-os/kernel.git diff --git a/Cargo.toml b/Cargo.toml index 8ec8394..5888ed1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,11 +14,9 @@ members = [ "installer", "kernel", "programs/acid", - "programs/binutils", "programs/contain", "programs/coreutils", "programs/extrautils", - "programs/games", "programs/init", "programs/ion", "programs/netutils", diff --git a/mk/userspace/binutils.mk b/mk/userspace/binutils.mk deleted file mode 100644 index 0a25ab4..0000000 --- a/mk/userspace/binutils.mk +++ /dev/null @@ -1,9 +0,0 @@ -binutils: \ - filesystem/bin/hex \ - filesystem/bin/hexdump \ - filesystem/bin/strings - -filesystem/bin/%: programs/binutils/Cargo.toml programs/binutils/src/bin/%.rs $(BUILD)/libstd.rlib - mkdir -p filesystem/bin - $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - $(STRIP) $@ diff --git a/mk/userspace/games.mk b/mk/userspace/games.mk deleted file mode 100644 index e65b00a..0000000 --- a/mk/userspace/games.mk +++ /dev/null @@ -1,13 +0,0 @@ -games: \ - filesystem/bin/baduk \ - filesystem/bin/ice \ - filesystem/bin/minesweeper \ - filesystem/bin/reblox \ - filesystem/bin/rusthello - -#filesystem/bin/snake - -filesystem/bin/%: programs/games/Cargo.toml programs/games/src/%/**.rs $(BUILD)/libstd.rlib - mkdir -p filesystem/bin - $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - $(STRIP) $@ diff --git a/mk/userspace/mod.mk b/mk/userspace/mod.mk index 2d6fc28..80b6612 100644 --- a/mk/userspace/mod.mk +++ b/mk/userspace/mod.mk @@ -2,7 +2,6 @@ userspace: \ drivers \ coreutils \ extrautils \ - games \ installer \ ion \ netutils \ @@ -12,15 +11,12 @@ userspace: \ schemes \ filesystem/bin/acid \ filesystem/bin/contain \ - filesystem/bin/redox_installer \ filesystem/bin/smith \ filesystem/bin/tar -include mk/userspace/binutils.mk include mk/userspace/coreutils.mk include mk/userspace/drivers.mk include mk/userspace/extrautils.mk -include mk/userspace/games.mk include mk/userspace/installer.mk include mk/userspace/ion.mk include mk/userspace/netutils.mk diff --git a/programs/binutils b/programs/binutils deleted file mode 160000 index ce057ba..0000000 --- a/programs/binutils +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ce057bac70f18fe7fd004c68e58c07c1cc7174e0 diff --git a/programs/games b/programs/games deleted file mode 160000 index c4984dc..0000000 --- a/programs/games +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c4984dc276bf5776f544b5f9f6996330e3ca4b51 From 3c795941afe77c04c00c22515d3f555ede136a05 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 7 Apr 2017 21:50:18 -0600 Subject: [PATCH 245/522] Update kernel, use login program in contain --- kernel | 2 +- programs/contain/src/main.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel b/kernel index a7f35e1..b286e69 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit a7f35e14cc0be480963b7094d1de5a8c1d3fa190 +Subproject commit b286e69c9dda75b0ad698446598a4fda130c35f6 diff --git a/programs/contain/src/main.rs b/programs/contain/src/main.rs index a19acaf..0cd1e01 100644 --- a/programs/contain/src/main.rs +++ b/programs/contain/src/main.rs @@ -88,7 +88,7 @@ pub fn main() { let mut args = env::args().skip(1); if let Some(root) = args.next() { - let cmd = args.next().unwrap_or(env::var("SHELL").unwrap_or("sh".to_string())); + let cmd = args.next().unwrap_or("login".to_string()); let args: Vec = args.collect(); enter(Path::new(&root), &cmd, &args); } else { From 51a06b8fbde33081fb4508582361da49db71f38a Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 8 Apr 2017 16:54:10 -0600 Subject: [PATCH 246/522] Update cookbook and ion --- cookbook | 2 +- programs/ion | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cookbook b/cookbook index f57cd8d..c2e3152 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit f57cd8dfc5973ad0f0901faa1b2be4c5dfa3678e +Subproject commit c2e315220b49c4ff3d974ee943ba3ea801c905bb diff --git a/programs/ion b/programs/ion index 962a5e0..aa49211 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit 962a5e03d7fa7efae1bdef6b10c3d59b5c89ebdd +Subproject commit aa4921102b16510859e181ff1ac299ca4f080a64 From d04f69f4b5faedd529224d50f86350cc29b51d1d Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 8 Apr 2017 17:40:38 -0600 Subject: [PATCH 247/522] Remove cookbook from redox repo --- .gitmodules | 3 --- cookbook | 1 - 2 files changed, 4 deletions(-) delete mode 160000 cookbook diff --git a/.gitmodules b/.gitmodules index 4530000..6f08870 100644 --- a/.gitmodules +++ b/.gitmodules @@ -61,9 +61,6 @@ [submodule "isolinux"] path = isolinux url = https://github.com/redox-os/isolinux.git -[submodule "cookbook"] - path = cookbook - url = https://github.com/redox-os/cookbook.git [submodule "programs/init"] path = programs/init url = https://github.com/redox-os/init.git diff --git a/cookbook b/cookbook deleted file mode 160000 index c2e3152..0000000 --- a/cookbook +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c2e315220b49c4ff3d974ee943ba3ea801c905bb From c6bb8ece3a74a2a29f62e75fb6b4455c3edc26c8 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 8 Apr 2017 17:53:09 -0600 Subject: [PATCH 248/522] Update extrautils --- programs/extrautils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/extrautils b/programs/extrautils index 728da8d..19d3d9d 160000 --- a/programs/extrautils +++ b/programs/extrautils @@ -1 +1 @@ -Subproject commit 728da8d08a57eb3e6db9e2b18c5b8e6a7e664a79 +Subproject commit 19d3d9ded97ab3fc260d70675a6bce46424f8526 From 56a594f4a081a70bc94bf1d9080b5fc4088a9479 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 8 Apr 2017 19:56:54 -0600 Subject: [PATCH 249/522] Update libc artifacts, ion --- libc-artifacts | 2 +- programs/ion | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libc-artifacts b/libc-artifacts index 8278a62..ecd2edd 160000 --- a/libc-artifacts +++ b/libc-artifacts @@ -1 +1 @@ -Subproject commit 8278a6252ca84ffef684bf3c371d8ab819c47ba4 +Subproject commit ecd2edd8935177cf9f160ae6ec11c22ee3a0a249 diff --git a/programs/ion b/programs/ion index aa49211..d4a7a18 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit aa4921102b16510859e181ff1ac299ca4f080a64 +Subproject commit d4a7a189cf05beb3ad55192c8a9c61c93031bdc6 From 7b8bdd0e918bd65e3522110b29aea016a1dac7ec Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 8 Apr 2017 20:04:45 -0600 Subject: [PATCH 250/522] Upgrade pkgutils --- programs/pkgutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/pkgutils b/programs/pkgutils index 260a657..a14452c 160000 --- a/programs/pkgutils +++ b/programs/pkgutils @@ -1 +1 @@ -Subproject commit 260a6578ab37454cfe902fafd2d41ec670f779e4 +Subproject commit a14452c70648405f32b7894baf228380a349c654 From 9970349f7a06c6a52868afdf5c935dc6f5514668 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 8 Apr 2017 22:00:01 -0600 Subject: [PATCH 251/522] Update kernel to add timeouts --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index b286e69..e43f5dd 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit b286e69c9dda75b0ad698446598a4fda130c35f6 +Subproject commit e43f5dda812e8d624c4c5426074765c8d73f5c7d From c4d652b1dea6d17e156925838c5fe47f00f085f0 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 8 Apr 2017 22:02:38 -0600 Subject: [PATCH 252/522] Add timeout example --- Cargo.toml | 1 + mk/userspace/mod.mk | 3 ++- programs/timeout/Cargo.toml | 8 +++++++ programs/timeout/src/main.rs | 44 ++++++++++++++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 programs/timeout/Cargo.toml create mode 100644 programs/timeout/src/main.rs diff --git a/Cargo.toml b/Cargo.toml index 5888ed1..00c3732 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ members = [ "programs/pkgutils", "programs/smith", "programs/tar", + "programs/timeout", "programs/userutils", "schemes/ethernetd", "schemes/ipd", diff --git a/mk/userspace/mod.mk b/mk/userspace/mod.mk index 80b6612..0a12655 100644 --- a/mk/userspace/mod.mk +++ b/mk/userspace/mod.mk @@ -12,7 +12,8 @@ userspace: \ filesystem/bin/acid \ filesystem/bin/contain \ filesystem/bin/smith \ - filesystem/bin/tar + filesystem/bin/tar \ + filesystem/bin/timeout include mk/userspace/coreutils.mk include mk/userspace/drivers.mk diff --git a/programs/timeout/Cargo.toml b/programs/timeout/Cargo.toml new file mode 100644 index 0000000..9ca5a42 --- /dev/null +++ b/programs/timeout/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "timeout" +version = "0.1.0" +authors = ["Jeremy Soller "] + +[dependencies] +redox_event = { git = "https://github.com/redox-os/event.git" } +redox_syscall = "0.1" diff --git a/programs/timeout/src/main.rs b/programs/timeout/src/main.rs new file mode 100644 index 0000000..baa7692 --- /dev/null +++ b/programs/timeout/src/main.rs @@ -0,0 +1,44 @@ +extern crate event; +extern crate syscall; + +use event::EventQueue; +use std::fs::File; +use std::io::{Result, Read, Write}; +use std::mem; +use std::os::unix::io::AsRawFd; +use syscall::data::TimeSpec; +use syscall::flag::CLOCK_MONOTONIC; + +fn main() { + let mut event_queue = EventQueue::::new().expect("timeout: failed to create event queue"); + + let path = format!("time:{}", CLOCK_MONOTONIC); + + let mut file = File::open(&path).expect(&format!("timeout: failed to open {}", path)); + + let mut timeout = TimeSpec::default(); + file.read(&mut timeout).unwrap(); + println!("Current: {:?}", timeout); + + timeout.tv_sec += 1; + println!("Setting timeout: {:?}", timeout); + file.write(&timeout).unwrap(); + + event_queue.add(file.as_raw_fd(), move |_count: usize| -> Result> { + let mut time = TimeSpec::default(); + if file.read(&mut time)? >= mem::size_of::() { + if time.tv_sec > timeout.tv_sec + || (time.tv_sec == timeout.tv_sec && time.tv_nsec >= timeout.tv_nsec ) + { + return Ok(Some(time)) + } + } + Ok(None) + }).expect("timeout: failed to poll time"); + + event_queue.trigger_all(0).expect("timeout: failed to trigger events"); + + let time = event_queue.run().expect("timeout: failed to run event loop"); + + println!("Time passed: {:?}", time); +} From 3d683e080a7beb632813cb3a56e2499a65a34b77 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 9 Apr 2017 08:36:14 -0600 Subject: [PATCH 253/522] Timeout in tcpd --- schemes/tcpd/src/main.rs | 147 ++++++++++++++++++++++++++++++++------- 1 file changed, 123 insertions(+), 24 deletions(-) diff --git a/schemes/tcpd/src/main.rs b/schemes/tcpd/src/main.rs index af18237..7eed94e 100644 --- a/schemes/tcpd/src/main.rs +++ b/schemes/tcpd/src/main.rs @@ -16,10 +16,25 @@ use std::rc::Rc; use event::EventQueue; use netutils::{n16, n32, Ipv4, Ipv4Addr, Ipv4Header, Tcp, TcpHeader, Checksum, TCP_FIN, TCP_SYN, TCP_RST, TCP_PSH, TCP_ACK}; use syscall::data::{Packet, TimeSpec}; -use syscall::error::{Error, Result, EACCES, EADDRINUSE, EBADF, EIO, EINVAL, EISCONN, EMSGSIZE, ENOTCONN, EWOULDBLOCK}; -use syscall::flag::{EVENT_READ, F_GETFL, F_SETFL, O_ACCMODE, O_CREAT, O_RDWR, O_NONBLOCK}; +use syscall::error::{Error, Result, EACCES, EADDRINUSE, EBADF, EIO, EINVAL, EISCONN, EMSGSIZE, ENOTCONN, ETIMEDOUT, EWOULDBLOCK}; +use syscall::flag::{CLOCK_MONOTONIC, EVENT_READ, F_GETFL, F_SETFL, O_ACCMODE, O_CREAT, O_RDWR, O_NONBLOCK}; use syscall::scheme::SchemeMut; +fn add_time(a: &TimeSpec, b: &TimeSpec) -> TimeSpec { + let mut secs = a.tv_sec + b.tv_sec; + + let mut nsecs = a.tv_nsec + b.tv_nsec; + while nsecs >= 1000000000 { + nsecs -= 1000000000; + secs += 1; + } + + TimeSpec { + tv_sec: secs, + tv_nsec: nsecs + } +} + fn parse_socket(socket: &str) -> (Ipv4Addr, u16) { let mut socket_parts = socket.split(":"); let host = Ipv4Addr::from_str(socket_parts.next().unwrap_or("")); @@ -55,8 +70,8 @@ struct TcpHandle { ack: u32, data: VecDeque<(Ipv4, Tcp)>, todo_dup: VecDeque, - todo_read: VecDeque, - todo_write: VecDeque, + todo_read: VecDeque<(Option, Packet)>, + todo_write: VecDeque<(Option, Packet)>, } impl TcpHandle { @@ -131,6 +146,7 @@ enum Handle { struct Tcpd { scheme_file: File, tcp_file: File, + time_file: File, ports: BTreeMap, next_id: usize, handles: BTreeMap, @@ -138,10 +154,11 @@ struct Tcpd { } impl Tcpd { - fn new(scheme_file: File, tcp_file: File) -> Self { + fn new(scheme_file: File, tcp_file: File, time_file: File) -> Self { Tcpd { scheme_file: scheme_file, tcp_file: tcp_file, + time_file: time_file, ports: BTreeMap::new(), next_id: 1, handles: BTreeMap::new(), @@ -156,6 +173,9 @@ impl Tcpd { break; } + let mut time = TimeSpec::default(); + syscall::clock_gettime(CLOCK_MONOTONIC, &mut time).map_err(|err| io::Error::from_raw_os_error(err.errno))?; + let a = packet.a; self.handle(&mut packet); if packet.a == (-EWOULDBLOCK) as usize { @@ -168,11 +188,31 @@ impl Tcpd { }, syscall::number::SYS_READ => { packet.a = a; - handle.todo_read.push_back(packet); + + let timeout = match handle.read_timeout { + Some(read_timeout) => { + let timeout = add_time(&time, &read_timeout); + self.time_file.write(&timeout)?; + Some(timeout) + }, + None => None + }; + + handle.todo_read.push_back((timeout, packet)); }, syscall::number::SYS_WRITE => { packet.a = a; - handle.todo_write.push_back(packet); + + let timeout = match handle.write_timeout { + Some(write_timeout) => { + let timeout = add_time(&time, &write_timeout); + self.time_file.write(&timeout)?; + Some(timeout) + }, + None => None + }; + + handle.todo_write.push_back((timeout, packet)); }, _ => { self.scheme_file.write(&packet)?; @@ -271,7 +311,7 @@ impl Tcpd { } while ! handle.todo_read.is_empty() && (! handle.data.is_empty() || handle.read_closed()) { - let mut packet = handle.todo_read.pop_front().unwrap(); + let (_timeout, mut packet) = handle.todo_read.pop_front().unwrap(); let buf = unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }; if let Some((_ip, tcp)) = handle.data.pop_front() { let mut i = 0; @@ -288,7 +328,7 @@ impl Tcpd { } if ! handle.todo_write.is_empty() && handle.state == State::Established { - let mut packet = handle.todo_write.pop_front().unwrap(); + let (_timeout, mut packet) = handle.todo_write.pop_front().unwrap(); let buf = unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }; let tcp = handle.create_tcp(TCP_ACK | TCP_PSH, buf.to_vec()); @@ -404,6 +444,49 @@ impl Tcpd { Ok(()) } + + fn time_event(&mut self) -> io::Result<()> { + let mut time = TimeSpec::default(); + if self.time_file.read(&mut time)? < mem::size_of::() { + return Err(io::Error::from_raw_os_error(EINVAL)); + } + + for (_id, handle) in self.handles.iter_mut() { + if let Handle::Tcp(ref mut handle) = *handle { + let mut i = 0; + while i < handle.todo_read.len() { + if let Some(timeout) = handle.todo_read.get(i).map(|e| e.0.clone()).unwrap_or(None) { + if time.tv_sec > timeout.tv_sec || (time.tv_sec == timeout.tv_sec && time.tv_nsec >= timeout.tv_nsec) { + let (_timeout, mut packet) = handle.todo_read.remove(i).unwrap(); + packet.a = (-ETIMEDOUT) as usize; + self.scheme_file.write(&packet)?; + } else { + i += 1; + } + } else { + i += 1; + } + } + + let mut i = 0; + while i < handle.todo_write.len() { + if let Some(timeout) = handle.todo_write.get(i).map(|e| e.0.clone()).unwrap_or(None) { + if time.tv_sec > timeout.tv_sec || (time.tv_sec == timeout.tv_sec && time.tv_nsec >= timeout.tv_nsec) { + let (_timeout, mut packet) = handle.todo_write.remove(i).unwrap(); + packet.a = (-ETIMEDOUT) as usize; + self.scheme_file.write(&packet)?; + } else { + i += 1; + } + } else { + i += 1; + } + } + } + } + + Ok(()) + } } impl SchemeMut for Tcpd { @@ -785,14 +868,21 @@ impl SchemeMut for Tcpd { } } -fn daemon(tcp_fd: usize, scheme_fd: usize) { - let tcp_file = unsafe { File::from_raw_fd(tcp_fd) }; +fn daemon(scheme_fd: usize, tcp_fd: usize, time_fd: usize) { let scheme_file = unsafe { File::from_raw_fd(scheme_fd) }; + let tcp_file = unsafe { File::from_raw_fd(tcp_fd) }; + let time_file = unsafe { File::from_raw_fd(time_fd) }; - let tcpd = Rc::new(RefCell::new(Tcpd::new(scheme_file, tcp_file))); + let tcpd = Rc::new(RefCell::new(Tcpd::new(scheme_file, tcp_file, time_file))); let mut event_queue = EventQueue::<()>::new().expect("tcpd: failed to create event queue"); + let time_tcpd = tcpd.clone(); + event_queue.add(time_fd, move |_count: usize| -> io::Result> { + time_tcpd.borrow_mut().time_event()?; + Ok(None) + }).expect("tcpd: failed to listen to events on time:"); + let tcp_tcpd = tcpd.clone(); event_queue.add(tcp_fd, move |_count: usize| -> io::Result> { tcp_tcpd.borrow_mut().tcp_event()?; @@ -810,23 +900,32 @@ fn daemon(tcp_fd: usize, scheme_fd: usize) { } fn main() { - match syscall::open("ip:6", O_RDWR | O_NONBLOCK) { - Ok(tcp_fd) => { - // Daemonize - if unsafe { syscall::clone(0).unwrap() } == 0 { - match syscall::open(":tcp", O_RDWR | O_CREAT | O_NONBLOCK) { - Ok(scheme_fd) => { - daemon(tcp_fd, scheme_fd); - }, - Err(err) => { - println!("tcpd: failed to create tcp scheme: {}", err); - process::exit(1); + let time_path = format!("time:{}", CLOCK_MONOTONIC); + match syscall::open(&time_path, O_RDWR) { + Ok(time_fd) => { + match syscall::open("ip:6", O_RDWR | O_NONBLOCK) { + Ok(tcp_fd) => { + // Daemonize + if unsafe { syscall::clone(0).unwrap() } == 0 { + match syscall::open(":tcp", O_RDWR | O_CREAT | O_NONBLOCK) { + Ok(scheme_fd) => { + daemon(scheme_fd, tcp_fd, time_fd); + }, + Err(err) => { + println!("tcpd: failed to create tcp scheme: {}", err); + process::exit(1); + } + } } + }, + Err(err) => { + println!("tcpd: failed to open ip:6: {}", err); + process::exit(1); } } }, Err(err) => { - println!("tcpd: failed to open ip:6: {}", err); + println!("tcpd: failed to open {}: {}", time_path, err); process::exit(1); } } From fbbc6a3ba5cc746b5e37c473730119ce3af56b88 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 9 Apr 2017 08:37:38 -0600 Subject: [PATCH 254/522] Add timeouts to netutils, orbutils, and pkgutils --- programs/netutils | 2 +- programs/orbutils | 2 +- programs/pkgutils | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/programs/netutils b/programs/netutils index ca1ef11..05cc30f 160000 --- a/programs/netutils +++ b/programs/netutils @@ -1 +1 @@ -Subproject commit ca1ef1149741dd10a3d4d8f7c8ff523d1663ac83 +Subproject commit 05cc30fb8bf8b4073abe31b66cc3580b982a672b diff --git a/programs/orbutils b/programs/orbutils index 39ba3c5..4b29335 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 39ba3c5bbe3956a3e02f21d78660566102e6cc50 +Subproject commit 4b29335ea78b3541c499a98dd4949552f804a264 diff --git a/programs/pkgutils b/programs/pkgutils index a14452c..0d208c8 160000 --- a/programs/pkgutils +++ b/programs/pkgutils @@ -1 +1 @@ -Subproject commit a14452c70648405f32b7894baf228380a349c654 +Subproject commit 0d208c8942bb7d14fff8223db0b972dd4b92bcfc From 1be3f0846390afa24f40c1fbc020090f0fe44347 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 9 Apr 2017 09:01:40 -0600 Subject: [PATCH 255/522] Implement timeouts in UDP --- schemes/tcpd/src/main.rs | 21 +++--- schemes/udpd/src/main.rs | 142 +++++++++++++++++++++++++++++++-------- 2 files changed, 127 insertions(+), 36 deletions(-) diff --git a/schemes/tcpd/src/main.rs b/schemes/tcpd/src/main.rs index 7eed94e..8d124d8 100644 --- a/schemes/tcpd/src/main.rs +++ b/schemes/tcpd/src/main.rs @@ -173,9 +173,6 @@ impl Tcpd { break; } - let mut time = TimeSpec::default(); - syscall::clock_gettime(CLOCK_MONOTONIC, &mut time).map_err(|err| io::Error::from_raw_os_error(err.errno))?; - let a = packet.a; self.handle(&mut packet); if packet.a == (-EWOULDBLOCK) as usize { @@ -191,6 +188,9 @@ impl Tcpd { let timeout = match handle.read_timeout { Some(read_timeout) => { + let mut time = TimeSpec::default(); + syscall::clock_gettime(CLOCK_MONOTONIC, &mut time).map_err(|err| io::Error::from_raw_os_error(err.errno))?; + let timeout = add_time(&time, &read_timeout); self.time_file.write(&timeout)?; Some(timeout) @@ -205,6 +205,9 @@ impl Tcpd { let timeout = match handle.write_timeout { Some(write_timeout) => { + let mut time = TimeSpec::default(); + syscall::clock_gettime(CLOCK_MONOTONIC, &mut time).map_err(|err| io::Error::from_raw_os_error(err.errno))?; + let timeout = add_time(&time, &write_timeout); self.time_file.write(&timeout)?; Some(timeout) @@ -677,7 +680,7 @@ impl SchemeMut for Tcpd { }; if let Handle::Tcp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - let read_timeout = |timeout: &Option, buf: &mut [u8]| -> Result { + let get_timeout = |timeout: &Option, buf: &mut [u8]| -> Result { if let Some(ref timespec) = *timeout { timespec.deref().read(buf).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO))) } else { @@ -695,10 +698,10 @@ impl SchemeMut for Tcpd { } }, SettingKind::ReadTimeout => { - read_timeout(&handle.read_timeout, buf) + get_timeout(&handle.read_timeout, buf) }, SettingKind::WriteTimeout => { - read_timeout(&handle.write_timeout, buf) + get_timeout(&handle.write_timeout, buf) } } } else { @@ -734,7 +737,7 @@ impl SchemeMut for Tcpd { }; if let Handle::Tcp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - let write_timeout = |timeout: &mut Option, buf: &[u8]| -> Result { + let set_timeout = |timeout: &mut Option, buf: &[u8]| -> Result { if buf.len() >= mem::size_of::() { let mut timespec = TimeSpec::default(); let count = timespec.deref_mut().write(buf).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?; @@ -756,10 +759,10 @@ impl SchemeMut for Tcpd { } }, SettingKind::ReadTimeout => { - write_timeout(&mut handle.read_timeout, buf) + set_timeout(&mut handle.read_timeout, buf) }, SettingKind::WriteTimeout => { - write_timeout(&mut handle.write_timeout, buf) + set_timeout(&mut handle.write_timeout, buf) } } } else { diff --git a/schemes/udpd/src/main.rs b/schemes/udpd/src/main.rs index 0715105..23d6479 100644 --- a/schemes/udpd/src/main.rs +++ b/schemes/udpd/src/main.rs @@ -17,10 +17,26 @@ use event::EventQueue; use netutils::{n16, Ipv4, Ipv4Addr, Ipv4Header, Checksum}; use netutils::udp::{Udp, UdpHeader}; use syscall::data::{Packet, TimeSpec}; -use syscall::error::{Error, Result, EACCES, EADDRINUSE, EBADF, EIO, EINVAL, EMSGSIZE, ENOTCONN, EWOULDBLOCK}; -use syscall::flag::{EVENT_READ, F_GETFL, F_SETFL, O_ACCMODE, O_CREAT, O_RDWR, O_NONBLOCK}; +use syscall::error::{Error, Result, EACCES, EADDRINUSE, EBADF, EIO, EINVAL, EMSGSIZE, ENOTCONN, ETIMEDOUT, EWOULDBLOCK}; +use syscall::flag::{CLOCK_MONOTONIC, EVENT_READ, F_GETFL, F_SETFL, O_ACCMODE, O_CREAT, O_RDWR, O_NONBLOCK}; +use syscall::number::{SYS_READ, SYS_WRITE}; use syscall::scheme::SchemeMut; +fn add_time(a: &TimeSpec, b: &TimeSpec) -> TimeSpec { + let mut secs = a.tv_sec + b.tv_sec; + + let mut nsecs = a.tv_nsec + b.tv_nsec; + while nsecs >= 1000000000 { + nsecs -= 1000000000; + secs += 1; + } + + TimeSpec { + tv_sec: secs, + tv_nsec: nsecs + } +} + fn parse_socket(socket: &str) -> (Ipv4Addr, u16) { let mut socket_parts = socket.split(":"); let host = Ipv4Addr::from_str(socket_parts.next().unwrap_or("")); @@ -37,7 +53,7 @@ struct UdpHandle { write_timeout: Option, ttl: u8, data: VecDeque>, - todo: VecDeque, + todo: VecDeque<(Option, Packet)>, } #[derive(Copy, Clone)] @@ -55,6 +71,7 @@ enum Handle { struct Udpd { scheme_file: File, udp_file: File, + time_file: File, ports: BTreeMap, next_id: usize, handles: BTreeMap, @@ -62,10 +79,11 @@ struct Udpd { } impl Udpd { - fn new(scheme_file: File, udp_file: File) -> Self { + fn new(scheme_file: File, udp_file: File, time_file: File) -> Self { Udpd { scheme_file: scheme_file, udp_file: udp_file, + time_file: time_file, ports: BTreeMap::new(), next_id: 1, handles: BTreeMap::new(), @@ -86,7 +104,33 @@ impl Udpd { packet.a = a; if let Some(mut handle) = self.handles.get_mut(&packet.b) { if let Handle::Udp(ref mut handle) = *handle { - handle.todo.push_back(packet); + let timeout = match packet.a { + SYS_READ => match handle.read_timeout { + Some(read_timeout) => { + let mut time = TimeSpec::default(); + syscall::clock_gettime(CLOCK_MONOTONIC, &mut time).map_err(|err| io::Error::from_raw_os_error(err.errno))?; + + let timeout = add_time(&time, &read_timeout); + self.time_file.write(&timeout)?; + Some(timeout) + }, + None => None + }, + SYS_WRITE => match handle.write_timeout { + Some(write_timeout) => { + let mut time = TimeSpec::default(); + syscall::clock_gettime(CLOCK_MONOTONIC, &mut time).map_err(|err| io::Error::from_raw_os_error(err.errno))?; + + let timeout = add_time(&time, &write_timeout); + self.time_file.write(&timeout)?; + Some(timeout) + }, + None => None + }, + _ => None + }; + + handle.todo.push_back((timeout, packet)); } } } else { @@ -120,7 +164,7 @@ impl Udpd { handle.data.push_back(udp.data.clone()); while ! handle.todo.is_empty() && ! handle.data.is_empty() { - let mut packet = handle.todo.pop_front().unwrap(); + let (_timeout, mut packet) = handle.todo.pop_front().unwrap(); let buf = unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }; let data = handle.data.pop_front().unwrap(); @@ -157,6 +201,34 @@ impl Udpd { Ok(()) } + + fn time_event(&mut self) -> io::Result<()> { + let mut time = TimeSpec::default(); + if self.time_file.read(&mut time)? < mem::size_of::() { + return Err(io::Error::from_raw_os_error(EINVAL)); + } + + for (_id, handle) in self.handles.iter_mut() { + if let Handle::Udp(ref mut handle) = *handle { + let mut i = 0; + while i < handle.todo.len() { + if let Some(timeout) = handle.todo.get(i).map(|e| e.0.clone()).unwrap_or(None) { + if time.tv_sec > timeout.tv_sec || (time.tv_sec == timeout.tv_sec && time.tv_nsec >= timeout.tv_nsec) { + let (_timeout, mut packet) = handle.todo.remove(i).unwrap(); + packet.a = (-ETIMEDOUT) as usize; + self.scheme_file.write(&packet)?; + } else { + i += 1; + } + } else { + i += 1; + } + } + } + } + + Ok(()) + } } impl SchemeMut for Udpd { @@ -272,7 +344,7 @@ impl SchemeMut for Udpd { }; if let Handle::Udp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - let read_timeout = |timeout: &Option, buf: &mut [u8]| -> Result { + let get_timeout = |timeout: &Option, buf: &mut [u8]| -> Result { if let Some(ref timespec) = *timeout { timespec.deref().read(buf).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO))) } else { @@ -290,10 +362,10 @@ impl SchemeMut for Udpd { } }, SettingKind::ReadTimeout => { - read_timeout(&handle.read_timeout, buf) + get_timeout(&handle.read_timeout, buf) }, SettingKind::WriteTimeout => { - read_timeout(&handle.write_timeout, buf) + get_timeout(&handle.write_timeout, buf) } } } else { @@ -349,7 +421,7 @@ impl SchemeMut for Udpd { }; if let Handle::Udp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - let write_timeout = |timeout: &mut Option, buf: &[u8]| -> Result { + let set_timeout = |timeout: &mut Option, buf: &[u8]| -> Result { if buf.len() >= mem::size_of::() { let mut timespec = TimeSpec::default(); let count = timespec.deref_mut().write(buf).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?; @@ -371,10 +443,10 @@ impl SchemeMut for Udpd { } }, SettingKind::ReadTimeout => { - write_timeout(&mut handle.read_timeout, buf) + set_timeout(&mut handle.read_timeout, buf) }, SettingKind::WriteTimeout => { - write_timeout(&mut handle.write_timeout, buf) + set_timeout(&mut handle.write_timeout, buf) } } } else { @@ -450,14 +522,21 @@ impl SchemeMut for Udpd { Ok(0) } } -fn daemon(udp_fd: usize, scheme_fd: usize) { - let udp_file = unsafe { File::from_raw_fd(udp_fd) }; +fn daemon(scheme_fd: usize, udp_fd: usize, time_fd: usize) { let scheme_file = unsafe { File::from_raw_fd(scheme_fd) }; + let udp_file = unsafe { File::from_raw_fd(udp_fd) }; + let time_file = unsafe { File::from_raw_fd(time_fd) }; - let udpd = Rc::new(RefCell::new(Udpd::new(scheme_file, udp_file))); + let udpd = Rc::new(RefCell::new(Udpd::new(scheme_file, udp_file, time_file))); let mut event_queue = EventQueue::<()>::new().expect("udpd: failed to create event queue"); + let time_udpd = udpd.clone(); + event_queue.add(time_fd, move |_count: usize| -> io::Result> { + time_udpd.borrow_mut().time_event()?; + Ok(None) + }).expect("udpd: failed to listen to events on time:"); + let udp_udpd = udpd.clone(); event_queue.add(udp_fd, move |_count: usize| -> io::Result> { udp_udpd.borrow_mut().udp_event()?; @@ -475,23 +554,32 @@ fn daemon(udp_fd: usize, scheme_fd: usize) { } fn main() { - match syscall::open("ip:11", O_RDWR | O_NONBLOCK) { - Ok(udp_fd) => { - // Daemonize - if unsafe { syscall::clone(0).unwrap() } == 0 { - match syscall::open(":udp", O_RDWR | O_CREAT | O_NONBLOCK) { - Ok(scheme_fd) => { - daemon(udp_fd, scheme_fd); - }, - Err(err) => { - println!("udpd: failed to create udp scheme: {}", err); - process::exit(1); + let time_path = format!("time:{}", CLOCK_MONOTONIC); + match syscall::open(&time_path, O_RDWR) { + Ok(time_fd) => { + match syscall::open("ip:11", O_RDWR | O_NONBLOCK) { + Ok(udp_fd) => { + // Daemonize + if unsafe { syscall::clone(0).unwrap() } == 0 { + match syscall::open(":udp", O_RDWR | O_CREAT | O_NONBLOCK) { + Ok(scheme_fd) => { + daemon(scheme_fd, udp_fd, time_fd); + }, + Err(err) => { + println!("udpd: failed to create udp scheme: {}", err); + process::exit(1); + } + } } + }, + Err(err) => { + println!("udpd: failed to open ip:11: {}", err); + process::exit(1); } } }, Err(err) => { - println!("udpd: failed to open ip:11: {}", err); + println!("udpd: failed to open {}: {}", time_path, err); process::exit(1); } } From 62bd720146809d669835ed90e88fe1ee63987813 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 9 Apr 2017 09:02:26 -0600 Subject: [PATCH 256/522] Update dhcpd --- programs/netutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/netutils b/programs/netutils index 05cc30f..da7aa5e 160000 --- a/programs/netutils +++ b/programs/netutils @@ -1 +1 @@ -Subproject commit 05cc30fb8bf8b4073abe31b66cc3580b982a672b +Subproject commit da7aa5e76cbf270820c1fdf36751baa4459f0c76 From db6ba2869f7642c4e05f2568867905b49b121e66 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 9 Apr 2017 13:03:34 -0600 Subject: [PATCH 257/522] Update installer and programs --- installer | 2 +- programs/ion | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/installer b/installer index 4e9d22a..7c7b30c 160000 --- a/installer +++ b/installer @@ -1 +1 @@ -Subproject commit 4e9d22ada4e650b8440e8c61ee653381b6b6a5ca +Subproject commit 7c7b30c16e29443cb83017b806411e3637184072 diff --git a/programs/ion b/programs/ion index d4a7a18..b1efe75 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit d4a7a189cf05beb3ad55192c8a9c61c93031bdc6 +Subproject commit b1efe75e9d90716815cd3c7ab4038d6fe6040c1f From 242341115c904992ab244ce36d2cf2a3203851d7 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 9 Apr 2017 21:22:44 -0600 Subject: [PATCH 258/522] Update editor --- programs/orbutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/orbutils b/programs/orbutils index 4b29335..0bc8063 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 4b29335ea78b3541c499a98dd4949552f804a264 +Subproject commit 0bc806355af9b2b442e2096814770b3c503cee0c From b969ec71ac005c829890b15857eeb5f50e0d4705 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 9 Apr 2017 21:51:51 -0600 Subject: [PATCH 259/522] Update coreutils --- programs/coreutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/coreutils b/programs/coreutils index c55c5b3..344f40b 160000 --- a/programs/coreutils +++ b/programs/coreutils @@ -1 +1 @@ -Subproject commit c55c5b3dc3d149d62492c691b908898ea0d33603 +Subproject commit 344f40b58b5f8bc334a430c02c71ed44998761ec From cc89638fcd66df8cc1c607ba3aa9149dc3db6b7a Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 9 Apr 2017 22:01:39 -0600 Subject: [PATCH 260/522] Update redoxfs --- schemes/redoxfs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schemes/redoxfs b/schemes/redoxfs index 3db0c2a..d0dfef2 160000 --- a/schemes/redoxfs +++ b/schemes/redoxfs @@ -1 +1 @@ -Subproject commit 3db0c2a4b1011a90b9d790f8be89436d07318166 +Subproject commit d0dfef2f0b46a7ca839ee3f56cfbf92ebf1cefdf From 2910bdc61c59a1cff197fecbdb96e2825724e2c5 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 9 Apr 2017 22:10:44 -0600 Subject: [PATCH 261/522] Update redoxfs and coreutils --- programs/coreutils | 2 +- schemes/redoxfs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/programs/coreutils b/programs/coreutils index 344f40b..b2c31a4 160000 --- a/programs/coreutils +++ b/programs/coreutils @@ -1 +1 @@ -Subproject commit 344f40b58b5f8bc334a430c02c71ed44998761ec +Subproject commit b2c31a4ae1e3bed4382e0d1e9beebaedefd155e9 diff --git a/schemes/redoxfs b/schemes/redoxfs index d0dfef2..f418d30 160000 --- a/schemes/redoxfs +++ b/schemes/redoxfs @@ -1 +1 @@ -Subproject commit d0dfef2f0b46a7ca839ee3f56cfbf92ebf1cefdf +Subproject commit f418d30dc9c08b9c45b51f335263fd057ca17f33 From b372383f5eeec149b7074ad52352ab468b565c54 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 10 Apr 2017 20:31:57 -0600 Subject: [PATCH 262/522] Update submodules --- drivers | 2 +- filesystem/ui | 2 +- schemes/orbital | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers b/drivers index f872fee..35cd7e4 160000 --- a/drivers +++ b/drivers @@ -1 +1 @@ -Subproject commit f872fee4e6d1e453ec2fe66fc9f5dab4762e3555 +Subproject commit 35cd7e4c13cc9951a601518880949fe56a271652 diff --git a/filesystem/ui b/filesystem/ui index b14a4f6..83e567b 160000 --- a/filesystem/ui +++ b/filesystem/ui @@ -1 +1 @@ -Subproject commit b14a4f6a1d50c1e284b312bec1a50b2f59465668 +Subproject commit 83e567bb6bcd04cfc8d80ae99665b038c546ecb5 diff --git a/schemes/orbital b/schemes/orbital index 504eee8..192a6b0 160000 --- a/schemes/orbital +++ b/schemes/orbital @@ -1 +1 @@ -Subproject commit 504eee854b48cf06b5e0d6877e4066efdcb412c9 +Subproject commit 192a6b0f0e40cecc70806112f73d234172bbc5fe From ec5e0527717054ce1a33970d28ccbcebb4566bb2 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 10 Apr 2017 20:50:28 -0600 Subject: [PATCH 263/522] Update file manager --- programs/orbutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/orbutils b/programs/orbutils index 0bc8063..626e341 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 0bc806355af9b2b442e2096814770b3c503cee0c +Subproject commit 626e34101ce8a9efc43a63c2b02b201a4c09bc03 From f35b69cccbb8b8d70186596c1a41ffbc5c6c65f1 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 10 Apr 2017 21:56:39 -0600 Subject: [PATCH 264/522] Update orbutils --- programs/orbutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/orbutils b/programs/orbutils index 626e341..ca7031e 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 626e34101ce8a9efc43a63c2b02b201a4c09bc03 +Subproject commit ca7031e5518b03a9ab39c992e9f7e859103a25f7 From 71f9680382fbe97711f0a9c9517da7c0af4c3ba3 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 11 Apr 2017 20:30:51 -0600 Subject: [PATCH 265/522] Update ion --- programs/ion | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/ion b/programs/ion index b1efe75..0283fcf 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit b1efe75e9d90716815cd3c7ab4038d6fe6040c1f +Subproject commit 0283fcf15236cafb2d9cae1137b9b5745276fd46 From c1e014112272a39fe703caaec22118752600b7e7 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 11 Apr 2017 22:01:25 -0600 Subject: [PATCH 266/522] Update orbutils, netutils, pkgutils --- programs/netutils | 2 +- programs/orbutils | 2 +- programs/pkgutils | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/programs/netutils b/programs/netutils index da7aa5e..f97aeea 160000 --- a/programs/netutils +++ b/programs/netutils @@ -1 +1 @@ -Subproject commit da7aa5e76cbf270820c1fdf36751baa4459f0c76 +Subproject commit f97aeea5cfd83d4fafc7673baae458433b0e7fd0 diff --git a/programs/orbutils b/programs/orbutils index ca7031e..8d50cb7 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit ca7031e5518b03a9ab39c992e9f7e859103a25f7 +Subproject commit 8d50cb7324238e5c1a3ab9c377f71332e958e61a diff --git a/programs/pkgutils b/programs/pkgutils index 0d208c8..6bdcd71 160000 --- a/programs/pkgutils +++ b/programs/pkgutils @@ -1 +1 @@ -Subproject commit 0d208c8942bb7d14fff8223db0b972dd4b92bcfc +Subproject commit 6bdcd7195379d3bc4eab04df73144e1ed31dda7e From ecb1be265a0ee068e961fcdc425b2898b607f462 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 12 Apr 2017 19:38:19 -0600 Subject: [PATCH 267/522] Update orbutils --- programs/orbutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/orbutils b/programs/orbutils index 8d50cb7..94a608c 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 8d50cb7324238e5c1a3ab9c377f71332e958e61a +Subproject commit 94a608ca8d8e84ee5ba138a221ee8815f9aad6d1 From 308a3a2b4cd1ddf961405ba3f59fbed2a7b618e0 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 12 Apr 2017 22:18:25 -0600 Subject: [PATCH 268/522] Update jpeg-decoder replacement --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 00c3732..958f397 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,5 +37,5 @@ members = [ ] [replace] -"jpeg-decoder:0.1.11" = { git = "https://github.com/redox-os/jpeg-decoder.git", branch = "single_thread" } +"jpeg-decoder:0.1.12" = { git = "https://github.com/redox-os/jpeg-decoder.git", branch = "single_thread" } "termion:1.3.0" = { git = "https://github.com/redox-os/termion.git" } From d299131fe662427875ca1b594eb9a00daafa89cd Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 12 Apr 2017 22:20:17 -0600 Subject: [PATCH 269/522] Update ion, coreutils, kernel --- kernel | 2 +- programs/coreutils | 2 +- programs/ion | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel b/kernel index e43f5dd..4204d99 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit e43f5dda812e8d624c4c5426074765c8d73f5c7d +Subproject commit 4204d9905e8e6b3057a28a9f3908116b3400bfc5 diff --git a/programs/coreutils b/programs/coreutils index b2c31a4..f5c3c8b 160000 --- a/programs/coreutils +++ b/programs/coreutils @@ -1 +1 @@ -Subproject commit b2c31a4ae1e3bed4382e0d1e9beebaedefd155e9 +Subproject commit f5c3c8b1831977a2d6709182c921623ca3b75c97 diff --git a/programs/ion b/programs/ion index 0283fcf..f0b0527 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit 0283fcf15236cafb2d9cae1137b9b5745276fd46 +Subproject commit f0b052750e28fafe04cebb36e273c3e9f2da2ce8 From d40ea37ad4f9aee5cda7da9cc6d5446dab2829dc Mon Sep 17 00:00:00 2001 From: Emanuele Antonio Faraone Date: Thu, 13 Apr 2017 19:43:00 +0200 Subject: [PATCH 270/522] Typo fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e888262..00caf31 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ and then rebuild! If you're interested in this project, and you'd like to help us out, [here](CONTRIBUTING.md) is a list of ways you can do just that. -## Cloning, Building, and Running +## Cloning, Building and Running Redox is big, even compressed. Downloading the full history may take a lot of bandwidth, and can even be costly on some data plans. Clone at your own risk! From 559372515cbdab0142fa56904a382fdf536939ce Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 13 Apr 2017 19:47:57 -0600 Subject: [PATCH 271/522] Update Rust, fix kernel targets, update coreutils, add Cargo.lock --- Cargo.lock | 1874 ++++++++++++++++++++++++++++++++++++++++++++ kernel | 2 +- programs/coreutils | 2 +- rust | 2 +- 4 files changed, 1877 insertions(+), 3 deletions(-) create mode 100644 Cargo.lock diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..6766868 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1874 @@ +[root] +name = "xhcid" +version = "0.1.0" +dependencies = [ + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "acid" +version = "0.1.0" +dependencies = [ + "x86 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "adler32" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ahcid" +version = "0.1.0" +dependencies = [ + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "alloc_kernel" +version = "0.1.0" +dependencies = [ + "linked_list_allocator 0.2.5 (git+https://github.com/phil-opp/linked-list-allocator.git)", + "spin 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ansi_term" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "argon2rs" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "blake2-rfc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", + "scoped_threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "arrayvec" +version = "0.3.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nodrop 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "base64" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bgad" +version = "0.1.0" +dependencies = [ + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bitflags" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "blake2-rfc" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "constant_time_eq 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byteorder" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byteorder" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byteorder" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "clipboard" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clipboard-win 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "objc-foundation 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "objc_id 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "x11 2.13.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "clipboard-win" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "windows-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "color_quant" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "constant_time_eq" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "contain" +version = "0.1.0" +dependencies = [ + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "coreutils" +version = "0.1.0" +dependencies = [ + "extra 0.1.0 (git+https://github.com/redox-os/libextra.git)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "csv" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "debug_unreachable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "deflate" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "adler32 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "deque" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "docgen" +version = "0.1.0" +dependencies = [ + "walkdir 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "e1000d" +version = "0.1.0" +dependencies = [ + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "netutils 0.1.0 (git+https://github.com/redox-os/netutils.git)", + "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "encoding" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "encoding-index-japanese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "encoding-index-korean" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "encoding-index-simpchinese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "encoding-index-singlebyte" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "encoding-index-tradchinese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "encoding_index_tests" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "enum_primitive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "error-chain" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ethernetd" +version = "0.1.0" +dependencies = [ + "netutils 0.1.0 (git+https://github.com/redox-os/netutils.git)", + "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "extra" +version = "0.1.0" +source = "git+https://github.com/redox-os/libextra.git#402932084acd5fef4812945887ceaaa2ddd5f264" + +[[package]] +name = "extrautils" +version = "0.1.0" +dependencies = [ + "extra 0.1.0 (git+https://github.com/redox-os/libextra.git)", + "libflate 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "pager 0.1.0 (git+https://github.com/redox-os/libpager.git)", + "raw-cpuid 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.3.0 (git+https://github.com/redox-os/termion.git)", +] + +[[package]] +name = "fuse" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "thread-scoped 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futf" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gcc" +version = "0.3.45" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "generic-array" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typenum 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gif" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "color_quant 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "glob" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "goblin" +version = "0.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "scroll 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "html5ever" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "html5ever-atoms 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tendril 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "html5ever-atoms" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "string_cache 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache_codegen 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "httparse" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "hyper" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hyper-rustls" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hyper 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki-roots 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "idna" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-bidi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "image" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gif 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "jpeg-decoder 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", + "num-rational 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "png 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "scoped_threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "inflate" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "init" +version = "0.1.0" +dependencies = [ + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ion-shell" +version = "1.0.0" +dependencies = [ + "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "liner 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "peg-syntax-ext 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "permutate 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "users 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ipd" +version = "0.1.0" +dependencies = [ + "netutils 0.1.0 (git+https://github.com/redox-os/netutils.git)", + "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "jpeg-decoder" +version = "0.1.12" +source = "git+https://github.com/redox-os/jpeg-decoder.git?branch=single_thread#0660fc061973598515ec5d39d03a1bc7e53d68f6" +dependencies = [ + "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "jpeg-decoder" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +replace = "jpeg-decoder 0.1.12 (git+https://github.com/redox-os/jpeg-decoder.git?branch=single_thread)" + +[[package]] +name = "kernel" +version = "0.1.0" +dependencies = [ + "alloc_kernel 0.1.0", + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "goblin 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "raw-cpuid 3.0.0 (git+https://github.com/gz/rust-cpuid)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "x86 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "language-tags" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lazy_static" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libflate" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "liner" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "linked-hash-map" +version = "0.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "linked_list_allocator" +version = "0.2.5" +source = "git+https://github.com/phil-opp/linked-list-allocator.git#ea8548db4b5a6ee0e2b847e96d6b4c31b7744567" + +[[package]] +name = "log" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lzw" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "matches" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "metadeps" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "error-chain 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mime" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mime_guess" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "mime 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "netutils" +version = "0.1.0" +source = "git+https://github.com/redox-os/netutils.git#f97aeea5cfd83d4fafc7673baae458433b0e7fd0" +dependencies = [ + "hyper 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-rustls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "ntpclient 0.0.1 (git+https://github.com/willem66745/ntpclient-rust)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "netutils" +version = "0.1.0" +dependencies = [ + "hyper 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-rustls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "ntpclient 0.0.1 (git+https://github.com/willem66745/ntpclient-rust)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "nodrop" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ntpclient" +version = "0.0.1" +source = "git+https://github.com/willem66745/ntpclient-rust#7e3bdf60eb940825789a8da5181025320e3050b0" +dependencies = [ + "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-bigint 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-complex 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", + "num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", + "num-rational 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-bigint" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-complex" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-integer" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-iter" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-rational" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-bigint 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "num_cpus" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "nvmed" +version = "0.1.0" +dependencies = [ + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "objc" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "objc-foundation" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "objc_id 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "objc_id" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "octavo" +version = "0.1.1" +source = "git+https://github.com/libOctavo/octavo.git#d94d924616dca83b9c6cfc815062276c5908713a" +dependencies = [ + "octavo-digest 0.1.2 (git+https://github.com/libOctavo/octavo.git)", +] + +[[package]] +name = "octavo-digest" +version = "0.1.2" +source = "git+https://github.com/libOctavo/octavo.git#d94d924616dca83b9c6cfc815062276c5908713a" +dependencies = [ + "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "static-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "odds" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "orbclient" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "sdl2 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "orbfont" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "orbclient 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rusttype 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "orbimage" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "image 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", + "orbclient 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "resize 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "orbital" +version = "0.1.0" +dependencies = [ + "orbclient 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "orbfont 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "orbimage 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "resize 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "orbtk" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "orbclient 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "orbfont 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "orbimage 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "orbutils" +version = "0.1.14" +dependencies = [ + "html5ever 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "html5ever-atoms 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-rustls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "mime_guess 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "orbclient 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "orbfont 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "orbimage 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "orbtk 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "ransid 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tendril 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "userutils 0.1.0 (git+https://github.com/redox-os/userutils.git)", +] + +[[package]] +name = "pager" +version = "0.1.0" +source = "git+https://github.com/redox-os/libpager.git#62b01eba8299143a1a5a78b36d85ab63251462b3" +dependencies = [ + "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pcid" +version = "0.1.0" +dependencies = [ + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "peg" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "peg-syntax-ext" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "peg 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "permutate" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "phf" +version = "0.7.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "phf_codegen" +version = "0.7.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "phf_generator" +version = "0.7.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "phf_shared" +version = "0.7.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pkg-config" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "pkgutils" +version = "0.1.0" +source = "git+https://github.com/redox-os/pkgutils.git#6bdcd7195379d3bc4eab04df73144e1ed31dda7e" +dependencies = [ + "hyper 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-rustls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "octavo 0.1.1 (git+https://github.com/libOctavo/octavo.git)", + "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pkgutils" +version = "0.1.0" +dependencies = [ + "hyper 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-rustls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "octavo 0.1.1 (git+https://github.com/libOctavo/octavo.git)", + "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "png" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "deflate 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "inflate 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ps2d" +version = "0.1.0" +dependencies = [ + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "orbclient 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ptyd" +version = "0.1.0" +dependencies = [ + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rand" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "randd" +version = "0.1.0" +dependencies = [ + "raw-cpuid 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ransid" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "raw-cpuid" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "raw-cpuid" +version = "3.0.0" +source = "git+https://github.com/gz/rust-cpuid#d8ff30d61fb2ef4700c88cb787f47f4085863c90" +dependencies = [ + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rayon-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon-core" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "redox_event" +version = "0.1.0" +source = "git+https://github.com/redox-os/event.git#285c93417cca031aea34a81d79d32c5b13f0af6c" +dependencies = [ + "redox_syscall 0.1.17 (git+https://github.com/redox-os/syscall.git)", +] + +[[package]] +name = "redox_installer" +version = "0.1.0" +dependencies = [ + "liner 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "pkgutils 0.1.0 (git+https://github.com/redox-os/pkgutils.git)", + "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "userutils 0.1.0 (git+https://github.com/redox-os/userutils.git)", +] + +[[package]] +name = "redox_syscall" +version = "0.1.17" +source = "git+https://github.com/redox-os/syscall.git#863080967dfee40e0a0c74936e43e79161e0aa6e" + +[[package]] +name = "redox_syscall" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "redoxfs" +version = "0.1.2" +dependencies = [ + "fuse 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "resize" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ring" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ropey" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rtl8168d" +version = "0.1.0" +dependencies = [ + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "netutils 0.1.0 (git+https://github.com/redox-os/netutils.git)", + "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc-serialize" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc_version" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustls" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rusttype" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "linked-hash-map 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "stb_truetype 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "same-file" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "scoped_threadpool" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "scroll" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "sdl2" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "sdl2-sys 0.27.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sdl2-sys" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "0.9.13" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde_codegen" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen_internals 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_codegen_internals" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "syn 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_codegen_internals" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "syn 0.11.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_derive" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde_codegen 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_derive" +version = "0.9.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen_internals 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_json" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "siphasher" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "smith" +version = "0.3.10" +dependencies = [ + "clipboard 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ropey 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "spin" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "static-buffer" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "stb_truetype" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "string_cache" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache_codegen 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "string_cache_codegen" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "string_cache_shared" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "syn" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.11.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synom" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tar" +version = "0.4.7" +dependencies = [ + "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tcpd" +version = "0.1.0" +dependencies = [ + "netutils 0.1.0 (git+https://github.com/redox-os/netutils.git)", + "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tempdir" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tendril" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "futf 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "utf-8 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "termion" +version = "1.3.0" +source = "git+https://github.com/redox-os/termion.git#550b9ea50a11c838533a0cf2cd9c8f7584927cdb" +dependencies = [ + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "termion" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +replace = "termion 1.3.0 (git+https://github.com/redox-os/termion.git)" + +[[package]] +name = "thread-scoped" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "time" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "timeout" +version = "0.1.0" +dependencies = [ + "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "toml" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "toml" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "traitobject" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "typeable" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "typenum" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "udpd" +version = "0.1.0" +dependencies = [ + "netutils 0.1.0 (git+https://github.com/redox-os/netutils.git)", + "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicase" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-bidi" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-normalization" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-segmentation" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-width" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unreachable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "untrusted" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "url" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "idna 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "user32-sys" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "users" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "userutils" +version = "0.1.0" +source = "git+https://github.com/redox-os/userutils.git#3ca18917f88130f4734bcb4643a410e62e6cb24c" +dependencies = [ + "argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "liner 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "userutils" +version = "0.1.0" +dependencies = [ + "argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "liner 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "utf-8" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "vboxd" +version = "0.1.0" +dependencies = [ + "orbclient 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "version_check" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "vesad" +version = "0.1.0" +dependencies = [ + "orbclient 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ransid 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "rusttype 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "walkdir" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "walkdir" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "webpki" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ring 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "webpki-roots" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "untrusted 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "windows-error" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "x11" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "metadeps 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "x86" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "csv 0.14.7 (registry+https://github.com/rust-lang/crates.io-index)", + "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "raw-cpuid 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[metadata] +"checksum adler32 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ff33fe13a08dbce05bcefa2c68eea4844941437e33d6f808240b54d7157b9cd" +"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" +"checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392" +"checksum arrayvec 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "35c1e907260135089def5aac0c66ca42624f2ed60652451812fedbc5a574baed" +"checksum base64 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2015e3793554aa5b6007e3a72959e84c1070039e74f13dde08fa64afe1ddd892" +"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" +"checksum blake2-rfc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "0c6a476f32fef3402f1161f89d0d39822809627754a126f8441ff2a9d45e2d59" +"checksum block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" +"checksum byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96c8b41881888cc08af32d47ac4edd52bc7fa27fef774be47a92443756451304" +"checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" +"checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8" +"checksum clipboard 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "811169a9ffda99ed1841a6db3c48cffbab9a9101376f77fee3c14a7581ab933d" +"checksum clipboard-win 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f05017278a9e5485eacce962c9efc52f720eef0d19646dc3a7af714aad22ed2c" +"checksum color_quant 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a475fc4af42d83d28adf72968d9bcfaf035a1a9381642d8e85d8a04957767b0d" +"checksum constant_time_eq 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "07dcb7959f0f6f1cf662f9a7ff389bcb919924d99ac41cf31f10d611d8721323" +"checksum csv 0.14.7 (registry+https://github.com/rust-lang/crates.io-index)" = "266c1815d7ca63a5bd86284043faf91e8c95e943e55ce05dc0ae08e952de18bc" +"checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3" +"checksum deflate 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "54b46d466b36f3bcc4dbb288be4f7de6f15ff90eda7a594408fbc7b780258e2f" +"checksum deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1614659040e711785ed8ea24219140654da1729f3ec8a47a9719d041112fe7bf" +"checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" +"checksum encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" +"checksum encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" +"checksum encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7" +"checksum encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a" +"checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" +"checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" +"checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" +"checksum error-chain 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "318cb3c71ee4cdea69fdc9e15c173b245ed6063e1709029e8fd32525a881120f" +"checksum extra 0.1.0 (git+https://github.com/redox-os/libextra.git)" = "" +"checksum fuse 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "adf08478eb39cff95e34daa7a2743a256d1c18388c0328d2f717e8ef748001f6" +"checksum futf 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "51f93f3de6ba1794dcd5810b3546d004600a59a98266487c8407bc4b24e398f3" +"checksum gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)" = "40899336fb50db0c78710f53e87afc54d8c7266fb76262fecc78ca1a7f09deae" +"checksum generic-array 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3406a3975bc944fdd85b7964d53296a0ff11f4b6c4704fa4972c9a7c8ba27367" +"checksum gif 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8a80d6fe9e52f637df9afd4779449a7be17c39cc9c35b01589bb833f956ba596" +"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" +"checksum goblin 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3536832676b9c0bde31ef9b6d1c8a9cc897267eaf15caaddcaef313f94b42e53" +"checksum html5ever 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a358fef34c3334e92cd34d83ce870a386334e605e7abe987a69a7078a4142c69" +"checksum html5ever-atoms 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4109e35fec157307b918eb9d5b7018e2fa771aea0c04831e22003ac4722fbd1b" +"checksum httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a6e7a63e511f9edffbab707141fbb8707d1a3098615fb2adbd5769cdfcc9b17d" +"checksum hyper 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)" = "38368702037feddcb6470b4dc641adcc585373ab037c757bbc2818a21968d051" +"checksum hyper-rustls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b948ce26b93a7cb182c84aa5205e614d54bf7a7194cfaec6ee3c45d83350700a" +"checksum idna 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6ac85ec3f80c8e4e99d9325521337e14ec7555c458a14e377d189659a427f375" +"checksum image 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "979bad0502082fd60053a490282e87d6c89650942e3a270e0d4c83569c7f5899" +"checksum inflate 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e7e0062d2dc2f17d2f13750d95316ae8a2ff909af0fda957084f5defd87c43bb" +"checksum jpeg-decoder 0.1.12 (git+https://github.com/redox-os/jpeg-decoder.git?branch=single_thread)" = "" +"checksum jpeg-decoder 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "919d49b634cde303392353c5dd51153ec005a1a981c6f4b8277692a51e9d260d" +"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" +"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" +"checksum libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122" +"checksum libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "88ee81885f9f04bff991e306fea7c1c60a5f0f9e409e99f6b40e3311a3363135" +"checksum libflate 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7aa60ce680c15f96b74bd6208256f112049ab20fd6da510f27f82cb78323a77" +"checksum liner 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5621a282d4baa2e8c0b815974bf3e2819eb860bfb7bf1d2f99049f10084a7102" +"checksum linked-hash-map 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "f26e961e0c884309cd527b1402a5409d35db612b36915d755e1a4f5c1547a31c" +"checksum linked_list_allocator 0.2.5 (git+https://github.com/phil-opp/linked-list-allocator.git)" = "" +"checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad" +"checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084" +"checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" +"checksum malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +"checksum matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efd7622e3022e1a6eaa602c4cea8912254e5582c9c692e9167714182244801b1" +"checksum metadeps 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829fffe7ea1d747e23f64be972991bc516b2f1ac2ae4a3b33d8bea150c410151" +"checksum mime 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5514f038123342d01ee5f95129e4ef1e0470c93bc29edf058a46f9ee3ba6737e" +"checksum mime_guess 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76da6df85047af8c0edfa53f48eb1073012ce1cc95c8fedc0a374f659a89dd65" +"checksum netutils 0.1.0 (git+https://github.com/redox-os/netutils.git)" = "" +"checksum nodrop 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "52cd74cd09beba596430cc6e3091b74007169a56246e1262f0ba451ea95117b2" +"checksum ntpclient 0.0.1 (git+https://github.com/willem66745/ntpclient-rust)" = "" +"checksum num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "98b15ba84e910ea7a1973bccd3df7b31ae282bf9d8bd2897779950c9b8303d40" +"checksum num-bigint 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "ba6d838b16e56da1b6c383d065ff1ec3c7d7797f65a3e8f6ba7092fd87820bac" +"checksum num-complex 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "148eb324ca772230853418731ffdf13531738b50f89b30692a01fcdcb0a64677" +"checksum num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "ef1a4bf6f9174aa5783a9b4cc892cacd11aebad6c69ad027a0b65c6ca5f8aa37" +"checksum num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d1891bd7b936f12349b7d1403761c8a0b85a18b148e9da4429d5d102c1a41e" +"checksum num-rational 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "c2dc5ea04020a8f18318ae485c751f8cfa1c0e69dcf465c29ddaaa64a313cc44" +"checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99" +"checksum num_cpus 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a18c392466409c50b87369414a2680c93e739aedeb498eb2bff7d7eb569744e2" +"checksum objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "877f30f37acef6749b1841cceab289707f211aecfc756553cd63976190e6cc2e" +"checksum objc-foundation 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" +"checksum objc_id 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e4730aa1c64d722db45f7ccc4113a3e2c465d018de6db4d3e7dfe031e8c8a297" +"checksum octavo 0.1.1 (git+https://github.com/libOctavo/octavo.git)" = "" +"checksum octavo-digest 0.1.2 (git+https://github.com/libOctavo/octavo.git)" = "" +"checksum odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "c3df9b730298cea3a1c3faa90b7e2f9df3a9c400d0936d6015e6165734eefcba" +"checksum orbclient 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "858fffc665397fca91f3d2c3f5d6cbe84932ae95d3c2701e96ca943a099b07d3" +"checksum orbfont 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9a781ee4a8df3d8206832ef8b8ccbb3f964aa0ec9e2794fdb8806d47bb0b89af" +"checksum orbimage 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c3b031607ef7a3c562949dfb595b1ea2b2d697b14544af407242a52dce811a6f" +"checksum orbtk 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "ae0386053f4a1a063579d374774b2c975501f373efbb81e2353f78f4c4f76911" +"checksum pager 0.1.0 (git+https://github.com/redox-os/libpager.git)" = "" +"checksum peg 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b2f7b0a8240dbf3d5cca65bba9791de310ce783d6e1426e56dc1278356b8017a" +"checksum peg-syntax-ext 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "40f9e24d396d5d1857dbacd9b8a12c9e9922f40a52ab56bfdb681194fbdd6bdc" +"checksum permutate 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b4ba980af238a6d6fcc0df53fe0d7920376bc4ce2c6ce298992891a230b47a8" +"checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc" +"checksum phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d62594c0bb54c464f633175d502038177e90309daf2e0158be42ed5f023ce88f" +"checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03" +"checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2" +"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" +"checksum pkgutils 0.1.0 (git+https://github.com/redox-os/pkgutils.git)" = "" +"checksum png 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3cb773e9a557edb568ce9935cf783e3cdcabe06a9449d41b3e5506d88e582c82" +"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" +"checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d" +"checksum ransid 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "e870a7ce03758d35a3b71e8cf07a38d84249aa545a49e8a7515afb0c12d33727" +"checksum raw-cpuid 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13b844e4049605ff38fed943f5c7b2c691fad68d9d5bf074d2720554c4e48246" +"checksum raw-cpuid 3.0.0 (git+https://github.com/gz/rust-cpuid)" = "" +"checksum rayon 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8c83adcb08e5b922e804fe1918142b422602ef11f2fd670b0b52218cb5984a20" +"checksum rayon-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "767d91bacddf07d442fe39257bf04fd95897d1c47c545d009f6beb03efd038f8" +"checksum redox_event 0.1.0 (git+https://github.com/redox-os/event.git)" = "" +"checksum redox_syscall 0.1.17 (git+https://github.com/redox-os/syscall.git)" = "" +"checksum redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "29dbdfd4b9df8ab31dec47c6087b7b13cbf4a776f335e4de8efba8288dda075b" +"checksum resize 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e8f5c5cf4d79776ed121e1c5052718b4bb06d2b48049144a2f0e5ad613b608e" +"checksum ring 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6210568620e7b9d3f6e27f4bef63140cb88a15fbfb49b041bd3343b92c109166" +"checksum ropey 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ffbce36196db96680b526bc2e2e27f23003e5ffab07271a176646c26dd0028b" +"checksum rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "684ce48436d6465300c9ea783b6b14c4361d6b8dcbb1375b486a69cc19e2dfb0" +"checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" +"checksum rustls 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fcfb2a577b14dca9caf13e6c6aa86d61158aa677347fbc155e5a1dac0f3b718f" +"checksum rusttype 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c64ffc93b0cc5a6f5e5e84da2a4082b0271e0a1dd76e821bdac570bda7797e" +"checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7" +"checksum scoped_threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3ef399c8893e8cb7aa9696e895427fab3a6bf265977bb96e126f24ddd2cda85a" +"checksum scroll 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "39c82d0508f6a56bdb409031382d62e9fa7f5e198fa04dfc06a7a96f1dfc101d" +"checksum sdl2 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c366cfa1f22d001774214ce2fb13f369af760b016bc79cc62d7f5ae15c00fea" +"checksum sdl2-sys 0.27.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8d9f87e3d948f94f2d8688970422f49249c20e97f8f3aad76cb8729901d4eb10" +"checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" +"checksum serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97b18e9e53de541f11e497357d6c5eaeb39f0cb9c8734e274abe4935f6991fa" +"checksum serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" +"checksum serde 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)" = "231dfd55909400769e437326cfb4af8bec97c3dd56ab3d02df8ef5c7e00f179b" +"checksum serde_codegen 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "a4c5d8a33087d8984f9535daa62a6498a08f6476050b00ab9339dd847e4c25cc" +"checksum serde_codegen_internals 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "afad7924a009f859f380e4a2e3a509a845c2ac66435fcead74a4d983b21ae806" +"checksum serde_codegen_internals 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bc888bd283bd2420b16ad0d860e35ad8acb21941180a83a189bb2046f9d00400" +"checksum serde_derive 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "ce44e5f4264b39e9d29c875357b7cc3ebdfb967bb9e22bfb5e44ffa400af5306" +"checksum serde_derive 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)" = "d75c72ef4dd193d89eb652b73890fe2489996c9ead8b37980f57a1078f96ed50" +"checksum serde_json 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5aaee47e038bf9552d30380d3973fff2593ee0a76d81ad4c581f267cdcadf36" +"checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" +"checksum spin 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1d16a26e2b789f86aabddbe91cb82ee2e822beb8a59840d631941b625ef77e53" +"checksum static-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6da6a96247d4b372d3ed90dec2c129ab57c934359ac4c6adbaa5871cd0737437" +"checksum stb_truetype 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "21b5c3b588a493a477e0d99769ee091b3627625f9ba4bdd882e6b4b0b0958805" +"checksum string_cache 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d192db2123fac37399e1ca61557904a5c3fb6fc24c73d2e47b15d20dc32470" +"checksum string_cache_codegen 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0c9dfe1a7c8bba1ecb90730d269fdc08afe93d23c28dd6c4aa5cabd79a05a05e" +"checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc" +"checksum syn 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)" = "58fd09df59565db3399efbba34ba8a2fec1307511ebd245d0061ff9d42691673" +"checksum syn 0.11.10 (registry+https://github.com/rust-lang/crates.io-index)" = "171b739972d9a1bfb169e8077238b51f9ebeaae4ff6e08072f7ba386a8802da2" +"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +"checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" +"checksum tendril 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cebf864c2d90394a1b66d6fe45963f9a177f2af81a0edea5060f77627f9c4587" +"checksum termion 1.3.0 (git+https://github.com/redox-os/termion.git)" = "" +"checksum termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b41865823fb8c7873ff869893219b3188e7fcd66c10effb97f2b2f63ea98681" +"checksum thread-scoped 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14387dce246d09efe184c8ebc34d9db5c0672a908b2f50efc53359ae13d5ae68" +"checksum time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "211b63c112206356ef1ff9b19355f43740fc3f85960c598a93d3a3d3ba7beade" +"checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4" +"checksum toml 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd86ad9ebee246fdedd610e0f6d0587b754a3d81438db930a244d0480ed7878f" +"checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" +"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" +"checksum typenum 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f06b0aa9c30a626496836e8de28bd2910cf6c8614e9579c9f8644b0a5d8fb0f5" +"checksum unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "13a5906ca2b98c799f4b1ab4557b76367ebd6ae5ef14930ec841c74aed5f3764" +"checksum unicode-bidi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3a078ebdd62c0e71a709c3d53d2af693fe09fe93fbff8344aebe289b78f9032" +"checksum unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e28fa37426fceeb5cf8f41ee273faa7c82c47dc8fba5853402841e665fcd86ff" +"checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3" +"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" +"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" +"checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91" +"checksum untrusted 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "193df64312e3515fd983ded55ad5bcaa7647a035804828ed757e832ce6029ef3" +"checksum url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5ba8a749fb4479b043733416c244fa9d1d3af3d7c23804944651c8a448cb87e" +"checksum user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47" +"checksum users 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7ae8fdf783cb9652109c99886459648feb92ecc749e6b8e7930f6decba74c7c" +"checksum userutils 0.1.0 (git+https://github.com/redox-os/userutils.git)" = "" +"checksum utf-8 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9aee9ba280438b56d1ebc5329f2094f0ff457f811eeeff0b278d75aa99db400" +"checksum version_check 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f2edadb5308f31d97771a678c33df28f18d04f61de3fe21b9452f37854eb6c08" +"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +"checksum walkdir 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c66c0b9792f0a765345452775f3adbd28dde9d33f30d13e5dcc5ae17cf6f3780" +"checksum walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bb08f9e670fab86099470b97cd2b252d6527f0b3cc1401acdb595ffc9dd288ff" +"checksum webpki 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4155c3a648038ca6b3568ab34e7da1866592ef40b2543fea412461364ef3cbfc" +"checksum webpki-roots 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f611ac968bda097564945980dfcbb840fb6e0380b9d9d34ac6e4c6067ecb3060" +"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" +"checksum windows-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d8570474f84367116f48f9fb2ae3e0347600029909096a15a5e6509bd4a03c50" +"checksum x11 2.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab7c9c8fcd61c1453aa7506d45be2fa916512f0c4ec985ef20bba3d575a23a6" +"checksum x86 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "127728f29f7cfb243a9264c80fc7e57bd1abb3ab015850b05736efda2abe5859" diff --git a/kernel b/kernel index 4204d99..56a533f 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 4204d9905e8e6b3057a28a9f3908116b3400bfc5 +Subproject commit 56a533fbbc963f67ca0e614d43610bac45e44b0b diff --git a/programs/coreutils b/programs/coreutils index f5c3c8b..81ae3b9 160000 --- a/programs/coreutils +++ b/programs/coreutils @@ -1 +1 @@ -Subproject commit f5c3c8b1831977a2d6709182c921623ca3b75c97 +Subproject commit 81ae3b9a8549215f9b2ad850c633ba0fca502756 diff --git a/rust b/rust index 91ae22a..28a7429 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 91ae22a012fae7fa7589b1bba77bf4579708ee33 +Subproject commit 28a74299778cdad4ea999e4ee8f8c1ef793338bd From 259ef70acf8940784b9ae5100f723da5497cc23d Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 14 Apr 2017 21:35:09 -0600 Subject: [PATCH 272/522] Update kernel, extrautils, ion, orbutils, pkgutils --- kernel | 2 +- programs/extrautils | 2 +- programs/ion | 2 +- programs/orbutils | 2 +- programs/pkgutils | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/kernel b/kernel index 56a533f..7b5873e 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 56a533fbbc963f67ca0e614d43610bac45e44b0b +Subproject commit 7b5873e4607ec9b7cf3d7a0e1a61bd246478c66a diff --git a/programs/extrautils b/programs/extrautils index 19d3d9d..a40331e 160000 --- a/programs/extrautils +++ b/programs/extrautils @@ -1 +1 @@ -Subproject commit 19d3d9ded97ab3fc260d70675a6bce46424f8526 +Subproject commit a40331e88c44fd34605f47ecf127e011c65fdc4e diff --git a/programs/ion b/programs/ion index f0b0527..d77d137 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit f0b052750e28fafe04cebb36e273c3e9f2da2ce8 +Subproject commit d77d13743df25c673341153c3c0db199f84efa55 diff --git a/programs/orbutils b/programs/orbutils index 94a608c..7e09e83 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 94a608ca8d8e84ee5ba138a221ee8815f9aad6d1 +Subproject commit 7e09e836b4eb23196c5cbec378555be32e89f860 diff --git a/programs/pkgutils b/programs/pkgutils index 6bdcd71..9c80d54 160000 --- a/programs/pkgutils +++ b/programs/pkgutils @@ -1 +1 @@ -Subproject commit 6bdcd7195379d3bc4eab04df73144e1ed31dda7e +Subproject commit 9c80d548c636182437c2cef60afa6b988a69332b From 1d91776bd55135c46bf06bec60c15c75093ddae9 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 14 Apr 2017 21:35:46 -0600 Subject: [PATCH 273/522] Update Cargo.lock --- Cargo.lock | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 6766868..439f537 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -300,6 +300,11 @@ dependencies = [ "termion 1.3.0 (git+https://github.com/redox-os/termion.git)", ] +[[package]] +name = "fnv" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "fuse" version = "0.2.8" @@ -459,6 +464,7 @@ name = "ion-shell" version = "1.0.0" dependencies = [ "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "liner 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "peg-syntax-ext 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -948,7 +954,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "pkgutils" version = "0.1.0" -source = "git+https://github.com/redox-os/pkgutils.git#6bdcd7195379d3bc4eab04df73144e1ed31dda7e" +source = "git+https://github.com/redox-os/pkgutils.git#9c80d548c636182437c2cef60afa6b988a69332b" dependencies = [ "hyper 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-rustls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1729,6 +1735,7 @@ dependencies = [ "checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" "checksum error-chain 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "318cb3c71ee4cdea69fdc9e15c173b245ed6063e1709029e8fd32525a881120f" "checksum extra 0.1.0 (git+https://github.com/redox-os/libextra.git)" = "" +"checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344" "checksum fuse 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "adf08478eb39cff95e34daa7a2743a256d1c18388c0328d2f717e8ef748001f6" "checksum futf 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "51f93f3de6ba1794dcd5810b3546d004600a59a98266487c8407bc4b24e398f3" "checksum gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)" = "40899336fb50db0c78710f53e87afc54d8c7266fb76262fecc78ca1a7f09deae" From 5e7a55e0b23829e46868a29bfd7e5ada7d85476a Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 14 Apr 2017 21:36:32 -0600 Subject: [PATCH 274/522] Do not ignore Cargo.lock --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index a8b6ee3..a3e3243 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -Cargo.lock build target initfs/bin From 39e56db812bdde279018a91cbc66315648166dd0 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 15 Apr 2017 09:50:34 -0600 Subject: [PATCH 275/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index 7b5873e..a38f32c 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 7b5873e4607ec9b7cf3d7a0e1a61bd246478c66a +Subproject commit a38f32c7351f85b1eaa9d9b426fd9a95135479ef From 1664f6cf034fb66507482bd898f983227d903240 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 15 Apr 2017 09:50:47 -0600 Subject: [PATCH 276/522] Add path implementation to rand --- schemes/randd/src/main.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/schemes/randd/src/main.rs b/schemes/randd/src/main.rs index 116c664..c15936d 100644 --- a/schemes/randd/src/main.rs +++ b/schemes/randd/src/main.rs @@ -42,6 +42,16 @@ impl SchemeMut for RandScheme { Ok(i) } + fn fpath(&mut self, _file: usize, buf: &mut [u8]) -> Result { + let mut i = 0; + let scheme_path = b"rand"; + while i < buf.len() && i < scheme_path.len() { + buf[i] = scheme_path[i]; + i += 1; + } + Ok(i) + } + fn close(&mut self, _file: usize) -> Result { Ok(0) } From feaa5483964388f7a5a9ae91e769e634ff28a78e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 15 Apr 2017 09:57:12 -0600 Subject: [PATCH 277/522] Update init --- programs/init | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/init b/programs/init index 1b684e2..6c1f476 160000 --- a/programs/init +++ b/programs/init @@ -1 +1 @@ -Subproject commit 1b684e24064c911705112ecc9a92a7f5e17c0418 +Subproject commit 6c1f476735e11d84b445dc8e60662f94f96434cc From 4ff7fac7a3ef4c8a997ffa31b09abf242164c91e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 15 Apr 2017 09:57:49 -0600 Subject: [PATCH 278/522] Update drivers --- drivers | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers b/drivers index 35cd7e4..1e70139 160000 --- a/drivers +++ b/drivers @@ -1 +1 @@ -Subproject commit 35cd7e4c13cc9951a601518880949fe56a271652 +Subproject commit 1e7013915b589531aec378df4cd51d615d8abb46 From c0aeddd8d8fa34601ea39fc851f74980e64010be Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 15 Apr 2017 09:58:14 -0600 Subject: [PATCH 279/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index a38f32c..1e8df4b 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit a38f32c7351f85b1eaa9d9b426fd9a95135479ef +Subproject commit 1e8df4b905499d9a06182fc0df826ab4616145ce From 69bc31f7addb64378aea1302523609017503b7b1 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 15 Apr 2017 10:09:03 -0600 Subject: [PATCH 280/522] Update orbital --- schemes/orbital | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schemes/orbital b/schemes/orbital index 192a6b0..19e475b 160000 --- a/schemes/orbital +++ b/schemes/orbital @@ -1 +1 @@ -Subproject commit 192a6b0f0e40cecc70806112f73d234172bbc5fe +Subproject commit 19e475b0fac8f197fb779f87c5b14f4d48b04829 From 26f35b36f4b945cb6163c2a9a2193de5fa79e868 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 15 Apr 2017 19:22:43 -0600 Subject: [PATCH 281/522] Update orbtk to 0.2.19 --- Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 439f537..9edcd00 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -842,7 +842,7 @@ dependencies = [ [[package]] name = "orbtk" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "orbclient 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -864,7 +864,7 @@ dependencies = [ "orbclient 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "orbfont 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "orbimage 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "orbtk 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "orbtk 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "ransid 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1790,7 +1790,7 @@ dependencies = [ "checksum orbclient 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "858fffc665397fca91f3d2c3f5d6cbe84932ae95d3c2701e96ca943a099b07d3" "checksum orbfont 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9a781ee4a8df3d8206832ef8b8ccbb3f964aa0ec9e2794fdb8806d47bb0b89af" "checksum orbimage 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c3b031607ef7a3c562949dfb595b1ea2b2d697b14544af407242a52dce811a6f" -"checksum orbtk 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "ae0386053f4a1a063579d374774b2c975501f373efbb81e2353f78f4c4f76911" +"checksum orbtk 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "2bca50ac6874107a922dd26dc79889b963afce69075940463ce026b5281bf9f1" "checksum pager 0.1.0 (git+https://github.com/redox-os/libpager.git)" = "" "checksum peg 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b2f7b0a8240dbf3d5cca65bba9791de310ce783d6e1426e56dc1278356b8017a" "checksum peg-syntax-ext 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "40f9e24d396d5d1857dbacd9b8a12c9e9922f40a52ab56bfdb681194fbdd6bdc" From 03bcbf7f057693b6291067067e0ed42cff544041 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 15 Apr 2017 19:57:15 -0600 Subject: [PATCH 282/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index 1e8df4b..66120cf 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 1e8df4b905499d9a06182fc0df826ab4616145ce +Subproject commit 66120cf20165f09cbedfdaeee1161c18050b8b58 From 7341f1820df8e54cdd2d7b480393628cb2bb708b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 15 Apr 2017 21:39:18 -0600 Subject: [PATCH 283/522] Update orbutils --- programs/orbutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/orbutils b/programs/orbutils index 7e09e83..cb3b825 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 7e09e836b4eb23196c5cbec378555be32e89f860 +Subproject commit cb3b8259dc84390fc63c1150d80ac8da328c4b8a From 9b1ecb24bc5b55858c99ce934a62765672f045ce Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 15 Apr 2017 21:39:24 -0600 Subject: [PATCH 284/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index 66120cf..9d39317 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 66120cf20165f09cbedfdaeee1161c18050b8b58 +Subproject commit 9d39317f95d2f6b876cc1fdd59b757f7e8a9346a From cd92dbe9b1d2f7c4f50738425668e634eb86ff2e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 15 Apr 2017 21:39:38 -0600 Subject: [PATCH 285/522] Update dependencies for orbutils --- Cargo.lock | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.lock b/Cargo.lock index 9edcd00..e2b398f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -866,6 +866,7 @@ dependencies = [ "orbimage 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "orbtk 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "ransid 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "tendril 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", From 9a1761651a991ad04b21c072466a7557cb37f36c Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 15 Apr 2017 22:04:42 -0600 Subject: [PATCH 286/522] Update orbutils --- programs/orbutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/orbutils b/programs/orbutils index cb3b825..75175bc 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit cb3b8259dc84390fc63c1150d80ac8da328c4b8a +Subproject commit 75175bcce78625bc1896c34d6e2a493767a3559c From 82a80dec9277e0af51a41676ddb4754c1e5eba9f Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 15 Apr 2017 22:09:46 -0600 Subject: [PATCH 287/522] Update orbutils --- programs/orbutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/orbutils b/programs/orbutils index 75175bc..9ff20a1 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 75175bcce78625bc1896c34d6e2a493767a3559c +Subproject commit 9ff20a1ddf6d821b6327f2b64975ac93980b8315 From 4494f3c8fced49ce54730f160c9440da65546ca1 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 15 Apr 2017 22:19:26 -0600 Subject: [PATCH 288/522] Update orbutils --- programs/orbutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/orbutils b/programs/orbutils index 9ff20a1..f2bfb0f 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 9ff20a1ddf6d821b6327f2b64975ac93980b8315 +Subproject commit f2bfb0faa19142a34e566f2962544cad1fafb27f From 60229980b06a3b99a4f34a2a6ea992fd676bd8af Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 15 Apr 2017 22:35:37 -0600 Subject: [PATCH 289/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index 9d39317..ea1150c 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 9d39317f95d2f6b876cc1fdd59b757f7e8a9346a +Subproject commit ea1150cd9b4a06dfbdb32beda634816ec1a93dd4 From 58b1e57d224d4988579545f40700bdcfae777d2c Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 15 Apr 2017 22:36:06 -0600 Subject: [PATCH 290/522] Update extrautils --- programs/extrautils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/extrautils b/programs/extrautils index a40331e..1f7c539 160000 --- a/programs/extrautils +++ b/programs/extrautils @@ -1 +1 @@ -Subproject commit a40331e88c44fd34605f47ecf127e011c65fdc4e +Subproject commit 1f7c539245fba17965323445d5be11cd4dffd168 From cd5332c9735f0642f6ed04a7ad260bec1a7c3cd1 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 16 Apr 2017 12:54:14 -0600 Subject: [PATCH 291/522] Update to perform cloexec in kernel --- kernel | 2 +- programs/init | 2 +- programs/ion | 2 +- programs/orbutils | 2 +- rust | 2 +- schemes/ptyd/src/main.rs | 36 +++++++++++++++++++++++++++++++++++- schemes/redoxfs | 2 +- 7 files changed, 41 insertions(+), 7 deletions(-) diff --git a/kernel b/kernel index ea1150c..d036c66 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit ea1150cd9b4a06dfbdb32beda634816ec1a93dd4 +Subproject commit d036c667a1ad7e104cd48846bf6b90961da8c1fb diff --git a/programs/init b/programs/init index 6c1f476..032a45c 160000 --- a/programs/init +++ b/programs/init @@ -1 +1 @@ -Subproject commit 6c1f476735e11d84b445dc8e60662f94f96434cc +Subproject commit 032a45c55242aebaa9f6a03fa9d11da881bfcb1f diff --git a/programs/ion b/programs/ion index d77d137..2afa32c 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit d77d13743df25c673341153c3c0db199f84efa55 +Subproject commit 2afa32c5b5e98a6bbf16b323f0ed72e16f2530c3 diff --git a/programs/orbutils b/programs/orbutils index f2bfb0f..1991d0b 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit f2bfb0faa19142a34e566f2962544cad1fafb27f +Subproject commit 1991d0bbe3f4e5060b9e6878f449619f45d9f595 diff --git a/rust b/rust index 28a7429..1bc9e5d 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 28a74299778cdad4ea999e4ee8f8c1ef793338bd +Subproject commit 1bc9e5da2367cdeebd86afb4ad1a3d45aae53837 diff --git a/schemes/ptyd/src/main.rs b/schemes/ptyd/src/main.rs index d03bd4f..2a982fa 100644 --- a/schemes/ptyd/src/main.rs +++ b/schemes/ptyd/src/main.rs @@ -11,7 +11,7 @@ use std::str; use syscall::data::Packet; use syscall::error::{Error, Result, EBADF, EINVAL, ENOENT, EPIPE, EWOULDBLOCK}; -use syscall::flag::O_NONBLOCK; +use syscall::flag::{F_GETFL, F_SETFL, O_ACCMODE, O_NONBLOCK}; use syscall::scheme::SchemeMut; pub struct PtyScheme { @@ -102,6 +102,18 @@ impl SchemeMut for PtyScheme { Err(Error::new(EBADF)) } + fn fcntl(&mut self, id: usize, cmd: usize, arg: usize) -> Result { + if let Some(pipe) = self.ptys.0.get_mut(&id) { + return pipe.fcntl(cmd, arg); + } + + if let Some(pipe) = self.ptys.1.get_mut(&id) { + return pipe.fcntl(cmd, arg); + } + + Err(Error::new(EBADF)) + } + fn fevent(&mut self, id: usize, _flags: usize) -> Result { if self.ptys.0.contains_key(&id) || self.ptys.1.contains_key(&id) { Ok(id) @@ -203,6 +215,17 @@ impl PtyMaster { Ok(i) } + + fn fcntl(&mut self, cmd: usize, arg: usize) -> Result { + match cmd { + F_GETFL => Ok(self.flags), + F_SETFL => { + self.flags = arg & ! O_ACCMODE; + Ok(0) + }, + _ => Err(Error::new(EINVAL)) + } + } } /// Read side of a pipe @@ -286,6 +309,17 @@ impl PtySlave { Err(Error::new(EPIPE)) } } + + fn fcntl(&mut self, cmd: usize, arg: usize) -> Result { + match cmd { + F_GETFL => Ok(self.flags), + F_SETFL => { + self.flags = arg & ! O_ACCMODE; + Ok(0) + }, + _ => Err(Error::new(EINVAL)) + } + } } fn main(){ diff --git a/schemes/redoxfs b/schemes/redoxfs index f418d30..f0c38fe 160000 --- a/schemes/redoxfs +++ b/schemes/redoxfs @@ -1 +1 @@ -Subproject commit f418d30dc9c08b9c45b51f335263fd057ca17f33 +Subproject commit f0c38fe609d666254ec29f6906603c3a3940ee46 From 054e1edbc98919db3bedd9f7ac7b2b577bafc370 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 16 Apr 2017 14:19:53 -0600 Subject: [PATCH 292/522] Add replacements as submodules --- .gitmodules | 18 ++++++++++++++++++ Cargo.lock | 41 +++++++++++++++++++++++++++++++++-------- Cargo.toml | 8 ++++++-- libs/jpeg-decoder | 1 + libs/orbclient | 1 + libs/orbfont | 1 + libs/orbimage | 1 + libs/orbtk | 1 + libs/termion | 1 + 9 files changed, 63 insertions(+), 10 deletions(-) create mode 160000 libs/jpeg-decoder create mode 160000 libs/orbclient create mode 160000 libs/orbfont create mode 160000 libs/orbimage create mode 160000 libs/orbtk create mode 160000 libs/termion diff --git a/.gitmodules b/.gitmodules index 6f08870..e6a37a4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -64,3 +64,21 @@ [submodule "programs/init"] path = programs/init url = https://github.com/redox-os/init.git +[submodule "libs/orbclient"] + path = libs/orbclient + url = https://github.com/redox-os/orbclient.git +[submodule "libs/orbtk"] + path = libs/orbtk + url = https://github.com/redox-os/orbtk.git +[submodule "libs/orbimage"] + path = libs/orbimage + url = https://github.com/redox-os/orbimage.git +[submodule "libs/orbfont"] + path = libs/orbfont + url = https://github.com/redox-os/orbfont.git +[submodule "libs/jpeg-decoder"] + path = libs/jpeg-decoder + url = https://github.com/redox-os/jpeg-decoder.git +[submodule "libs/termion"] + path = libs/termion + url = https://github.com/redox-os/termion.git diff --git a/Cargo.lock b/Cargo.lock index e2b398f..6319d8f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -486,7 +486,6 @@ dependencies = [ [[package]] name = "jpeg-decoder" version = "0.1.12" -source = "git+https://github.com/redox-os/jpeg-decoder.git?branch=single_thread#0660fc061973598515ec5d39d03a1bc7e53d68f6" dependencies = [ "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -495,7 +494,7 @@ dependencies = [ name = "jpeg-decoder" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -replace = "jpeg-decoder 0.1.12 (git+https://github.com/redox-os/jpeg-decoder.git?branch=single_thread)" +replace = "jpeg-decoder 0.1.12" [[package]] name = "kernel" @@ -801,31 +800,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "orbclient" version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "sdl2 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "orbclient" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +replace = "orbclient 0.3.3" + [[package]] name = "orbfont" version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "orbclient 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "rusttype 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "orbfont" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +replace = "orbfont 0.1.7" + [[package]] name = "orbimage" version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "image 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", "orbclient 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "resize 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "orbimage" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +replace = "orbimage 0.1.15" + [[package]] name = "orbital" version = "0.1.0" @@ -843,13 +857,18 @@ dependencies = [ [[package]] name = "orbtk" version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "orbclient 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "orbfont 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "orbimage 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "orbtk" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +replace = "orbtk 0.2.19" + [[package]] name = "orbutils" version = "0.1.14" @@ -1424,11 +1443,18 @@ dependencies = [ "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "termion" +version = "1.3.0" +dependencies = [ + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "termion" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -replace = "termion 1.3.0 (git+https://github.com/redox-os/termion.git)" +replace = "termion 1.3.0" [[package]] name = "thread-scoped" @@ -1752,7 +1778,6 @@ dependencies = [ "checksum idna 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6ac85ec3f80c8e4e99d9325521337e14ec7555c458a14e377d189659a427f375" "checksum image 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "979bad0502082fd60053a490282e87d6c89650942e3a270e0d4c83569c7f5899" "checksum inflate 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e7e0062d2dc2f17d2f13750d95316ae8a2ff909af0fda957084f5defd87c43bb" -"checksum jpeg-decoder 0.1.12 (git+https://github.com/redox-os/jpeg-decoder.git?branch=single_thread)" = "" "checksum jpeg-decoder 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "919d49b634cde303392353c5dd51153ec005a1a981c6f4b8277692a51e9d260d" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" diff --git a/Cargo.toml b/Cargo.toml index 958f397..96ec5e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,5 +37,9 @@ members = [ ] [replace] -"jpeg-decoder:0.1.12" = { git = "https://github.com/redox-os/jpeg-decoder.git", branch = "single_thread" } -"termion:1.3.0" = { git = "https://github.com/redox-os/termion.git" } +"jpeg-decoder:0.1.12" = { path = "libs/jpeg-decoder" } +"orbclient:0.3.3" = { path = "libs/orbclient" } +"orbfont:0.1.7" = { path = "libs/orbfont" } +"orbimage:0.1.15" = { path = "libs/orbimage" } +"orbtk:0.2.19" = { path = "libs/orbtk" } +"termion:1.3.0" = { path = "libs/termion" } diff --git a/libs/jpeg-decoder b/libs/jpeg-decoder new file mode 160000 index 0000000..0660fc0 --- /dev/null +++ b/libs/jpeg-decoder @@ -0,0 +1 @@ +Subproject commit 0660fc061973598515ec5d39d03a1bc7e53d68f6 diff --git a/libs/orbclient b/libs/orbclient new file mode 160000 index 0000000..2266aac --- /dev/null +++ b/libs/orbclient @@ -0,0 +1 @@ +Subproject commit 2266aac1a9f300941d72d51e9a7fdb23eceeeb7e diff --git a/libs/orbfont b/libs/orbfont new file mode 160000 index 0000000..8a8d19d --- /dev/null +++ b/libs/orbfont @@ -0,0 +1 @@ +Subproject commit 8a8d19dcddbd78b3d3b12f7a7264c97c506b0a01 diff --git a/libs/orbimage b/libs/orbimage new file mode 160000 index 0000000..cc3b593 --- /dev/null +++ b/libs/orbimage @@ -0,0 +1 @@ +Subproject commit cc3b593a585e339819cafcd8133b22cc6242f84d diff --git a/libs/orbtk b/libs/orbtk new file mode 160000 index 0000000..9ff1aa4 --- /dev/null +++ b/libs/orbtk @@ -0,0 +1 @@ +Subproject commit 9ff1aa42bdd7404585e5cf7f666e2a0f67c4e4be diff --git a/libs/termion b/libs/termion new file mode 160000 index 0000000..550b9ea --- /dev/null +++ b/libs/termion @@ -0,0 +1 @@ +Subproject commit 550b9ea50a11c838533a0cf2cd9c8f7584927cdb From 5f40fe640657a27a73b448a7024e5524208a0fbc Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 16 Apr 2017 14:26:41 -0600 Subject: [PATCH 293/522] Add more replacements --- .gitmodules | 9 +++++++++ Cargo.lock | 5 +++++ Cargo.toml | 3 +++ libs/event | 1 + libs/extra | 1 + libs/syscall | 1 + 6 files changed, 20 insertions(+) create mode 160000 libs/event create mode 160000 libs/extra create mode 160000 libs/syscall diff --git a/.gitmodules b/.gitmodules index e6a37a4..5ad72a9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -82,3 +82,12 @@ [submodule "libs/termion"] path = libs/termion url = https://github.com/redox-os/termion.git +[submodule "libs/syscall"] + path = libs/syscall + url = https://github.com/redox-os/syscall.git +[submodule "libs/extra"] + path = libs/extra + url = https://github.com/redox-os/libextra.git +[submodule "libs/event"] + path = libs/event + url = https://github.com/redox-os/event.git diff --git a/Cargo.lock b/Cargo.lock index 6319d8f..3346360 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1110,10 +1110,15 @@ name = "redox_syscall" version = "0.1.17" source = "git+https://github.com/redox-os/syscall.git#863080967dfee40e0a0c74936e43e79161e0aa6e" +[[package]] +name = "redox_syscall" +version = "0.1.17" + [[package]] name = "redox_syscall" version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" +replace = "redox_syscall 0.1.17" [[package]] name = "redoxfs" diff --git a/Cargo.toml b/Cargo.toml index 96ec5e9..3a5317b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,9 +37,12 @@ members = [ ] [replace] +"extra:0.1.0" = { path = "libs/extra" } "jpeg-decoder:0.1.12" = { path = "libs/jpeg-decoder" } "orbclient:0.3.3" = { path = "libs/orbclient" } "orbfont:0.1.7" = { path = "libs/orbfont" } "orbimage:0.1.15" = { path = "libs/orbimage" } "orbtk:0.2.19" = { path = "libs/orbtk" } +"redox_event:0.1.0" = { path = "libs/event" } +"redox_syscall:0.1.17" = { path = "libs/syscall" } "termion:1.3.0" = { path = "libs/termion" } diff --git a/libs/event b/libs/event new file mode 160000 index 0000000..285c934 --- /dev/null +++ b/libs/event @@ -0,0 +1 @@ +Subproject commit 285c93417cca031aea34a81d79d32c5b13f0af6c diff --git a/libs/extra b/libs/extra new file mode 160000 index 0000000..4029320 --- /dev/null +++ b/libs/extra @@ -0,0 +1 @@ +Subproject commit 402932084acd5fef4812945887ceaaa2ddd5f264 diff --git a/libs/syscall b/libs/syscall new file mode 160000 index 0000000..8630809 --- /dev/null +++ b/libs/syscall @@ -0,0 +1 @@ +Subproject commit 863080967dfee40e0a0c74936e43e79161e0aa6e From 072a202e0301aee20faeea846f2e1d2d705c1259 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 16 Apr 2017 14:50:04 -0600 Subject: [PATCH 294/522] Add more libs --- .gitmodules | 9 +++++++++ Cargo.toml | 3 +++ libs/pager | 1 + libs/ransid | 1 + libs/same-file | 1 + 5 files changed, 15 insertions(+) create mode 160000 libs/pager create mode 160000 libs/ransid create mode 160000 libs/same-file diff --git a/.gitmodules b/.gitmodules index 5ad72a9..daa0e64 100644 --- a/.gitmodules +++ b/.gitmodules @@ -91,3 +91,12 @@ [submodule "libs/event"] path = libs/event url = https://github.com/redox-os/event.git +[submodule "libs/pager"] + path = libs/pager + url = https://github.com/redox-os/libpager.git +[submodule "libs/ransid"] + path = libs/ransid + url = https://github.com/redox-os/ransid.git +[submodule "libs/same-file"] + path = libs/same-file + url = https://github.com/redox-os/same-file.git diff --git a/Cargo.toml b/Cargo.toml index 3a5317b..bdc2a6b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,6 +43,9 @@ members = [ "orbfont:0.1.7" = { path = "libs/orbfont" } "orbimage:0.1.15" = { path = "libs/orbimage" } "orbtk:0.2.19" = { path = "libs/orbtk" } +"pager:0.1.0" = { path = "libs/pager" } +"ransid:0.2.7" = { path = "libs/ransid" } "redox_event:0.1.0" = { path = "libs/event" } "redox_syscall:0.1.17" = { path = "libs/syscall" } +"same-file:0.1.2" = { path = "libs/same-file" } "termion:1.3.0" = { path = "libs/termion" } diff --git a/libs/pager b/libs/pager new file mode 160000 index 0000000..62b01eb --- /dev/null +++ b/libs/pager @@ -0,0 +1 @@ +Subproject commit 62b01eba8299143a1a5a78b36d85ab63251462b3 diff --git a/libs/ransid b/libs/ransid new file mode 160000 index 0000000..20d2db3 --- /dev/null +++ b/libs/ransid @@ -0,0 +1 @@ +Subproject commit 20d2db307bc9926a33f437b688925ba3a37821c2 diff --git a/libs/same-file b/libs/same-file new file mode 160000 index 0000000..d034b7f --- /dev/null +++ b/libs/same-file @@ -0,0 +1 @@ +Subproject commit d034b7f24b4a3eeb56baccbdcbfcdfce95940487 From 0341afd60dde68c39118d01fb97b75f8c16fa7ba Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 16 Apr 2017 14:51:44 -0600 Subject: [PATCH 295/522] Add mio --- .gitmodules | 3 +++ Cargo.toml | 1 + libs/mio | 1 + 3 files changed, 5 insertions(+) create mode 160000 libs/mio diff --git a/.gitmodules b/.gitmodules index daa0e64..04a9619 100644 --- a/.gitmodules +++ b/.gitmodules @@ -100,3 +100,6 @@ [submodule "libs/same-file"] path = libs/same-file url = https://github.com/redox-os/same-file.git +[submodule "libs/mio"] + path = libs/mio + url = https://github.com/redox-os/mio.git diff --git a/Cargo.toml b/Cargo.toml index bdc2a6b..43f59bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,6 +39,7 @@ members = [ [replace] "extra:0.1.0" = { path = "libs/extra" } "jpeg-decoder:0.1.12" = { path = "libs/jpeg-decoder" } +"mio:0.6.2" = { path = "libs/mio" } "orbclient:0.3.3" = { path = "libs/orbclient" } "orbfont:0.1.7" = { path = "libs/orbfont" } "orbimage:0.1.15" = { path = "libs/orbimage" } diff --git a/libs/mio b/libs/mio new file mode 160000 index 0000000..a4f7f6a --- /dev/null +++ b/libs/mio @@ -0,0 +1 @@ +Subproject commit a4f7f6a4e106fa52702a2dc1c4b2bb747bd0bf9a From 06413212660a8cb7f69ff8ccffc0ec8beb148604 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 16 Apr 2017 14:52:07 -0600 Subject: [PATCH 296/522] Update cargo lock file --- Cargo.lock | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 3346360..376cce9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1041,10 +1041,15 @@ dependencies = [ "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ransid" +version = "0.2.7" + [[package]] name = "ransid" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" +replace = "ransid 0.2.7" [[package]] name = "raw-cpuid" From 35b42724c3f30227d2b2b97c5ebb37772b91299b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 16 Apr 2017 14:58:12 -0600 Subject: [PATCH 297/522] Readd binutils and games --- .gitmodules | 6 ++++++ programs/binutils | 1 + programs/games | 1 + 3 files changed, 8 insertions(+) create mode 160000 programs/binutils create mode 160000 programs/games diff --git a/.gitmodules b/.gitmodules index 04a9619..636c25d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -103,3 +103,9 @@ [submodule "libs/mio"] path = libs/mio url = https://github.com/redox-os/mio.git +[submodule "programs/binutils"] + path = programs/binutils + url = https://github.com/redox-os/binutils.git +[submodule "programs/games"] + path = programs/games + url = https://github.com/redox-os/games.git diff --git a/programs/binutils b/programs/binutils new file mode 160000 index 0000000..ce057ba --- /dev/null +++ b/programs/binutils @@ -0,0 +1 @@ +Subproject commit ce057bac70f18fe7fd004c68e58c07c1cc7174e0 diff --git a/programs/games b/programs/games new file mode 160000 index 0000000..c4984dc --- /dev/null +++ b/programs/games @@ -0,0 +1 @@ +Subproject commit c4984dc276bf5776f544b5f9f6996330e3ca4b51 From d39201bfa09c31a59804779855d24929e773876f Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 16 Apr 2017 15:02:38 -0600 Subject: [PATCH 298/522] Add ralloc and sodium --- .gitmodules | 6 ++++++ Cargo.toml | 1 + libs/ralloc | 1 + programs/sodium | 1 + 4 files changed, 9 insertions(+) create mode 160000 libs/ralloc create mode 160000 programs/sodium diff --git a/.gitmodules b/.gitmodules index 636c25d..93dfd1a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -109,3 +109,9 @@ [submodule "programs/games"] path = programs/games url = https://github.com/redox-os/games.git +[submodule "programs/sodium"] + path = programs/sodium + url = https://github.com/redox-os/sodium.git +[submodule "libs/ralloc"] + path = libs/ralloc + url = https://github.com/redox-os/ralloc.git diff --git a/Cargo.toml b/Cargo.toml index 43f59bd..18a6498 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,6 +45,7 @@ members = [ "orbimage:0.1.15" = { path = "libs/orbimage" } "orbtk:0.2.19" = { path = "libs/orbtk" } "pager:0.1.0" = { path = "libs/pager" } +"ralloc:1.0.0" = { path = "libs/ralloc" } "ransid:0.2.7" = { path = "libs/ransid" } "redox_event:0.1.0" = { path = "libs/event" } "redox_syscall:0.1.17" = { path = "libs/syscall" } diff --git a/libs/ralloc b/libs/ralloc new file mode 160000 index 0000000..e31a743 --- /dev/null +++ b/libs/ralloc @@ -0,0 +1 @@ +Subproject commit e31a743ec384bac8ecc0bdc82d63ae3534016416 diff --git a/programs/sodium b/programs/sodium new file mode 160000 index 0000000..4104a44 --- /dev/null +++ b/programs/sodium @@ -0,0 +1 @@ +Subproject commit 4104a44ad839abf297dcd0182e41099cf6e5436c From 51fbacf2b33b6fcdadae23a4f83d84d4dd8e8905 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 16 Apr 2017 15:03:52 -0600 Subject: [PATCH 299/522] Update cargo.toml and cargo.lock --- Cargo.lock | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 3 +++ 2 files changed, 75 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 376cce9..9d1f681 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -71,6 +71,18 @@ dependencies = [ "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "binutils" +version = "0.1.0" +dependencies = [ + "extra 0.1.0 (git+https://github.com/redox-os/libextra.git)", +] + +[[package]] +name = "bitflags" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "bitflags" version = "0.7.0" @@ -326,6 +338,16 @@ dependencies = [ "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "games-for-redox" +version = "0.1.0" +dependencies = [ + "extra 0.1.0 (git+https://github.com/redox-os/libextra.git)", + "libgo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "liner 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "gcc" version = "0.3.45" @@ -546,6 +568,14 @@ dependencies = [ "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "libgo" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "liner" version = "0.1.4" @@ -797,6 +827,15 @@ name = "odds" version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "orbclient" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "sdl2 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "orbclient" version = "0.3.3" @@ -1222,6 +1261,18 @@ name = "scroll" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "sdl2" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "sdl2-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "sdl2" version = "0.29.1" @@ -1235,6 +1286,15 @@ dependencies = [ "sdl2-sys 0.27.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "sdl2-sys" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "sdl2-sys" version = "0.27.3" @@ -1333,6 +1393,13 @@ dependencies = [ "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "sodium" +version = "0.1.0" +dependencies = [ + "orbclient 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "spin" version = "0.4.5" @@ -1748,6 +1815,7 @@ dependencies = [ "checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392" "checksum arrayvec 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "35c1e907260135089def5aac0c66ca42624f2ed60652451812fedbc5a574baed" "checksum base64 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2015e3793554aa5b6007e3a72959e84c1070039e74f13dde08fa64afe1ddd892" +"checksum bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "32866f4d103c4e438b1db1158aa1b1a80ee078e5d77a59a2f906fd62a577389c" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum blake2-rfc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "0c6a476f32fef3402f1161f89d0d39822809627754a126f8441ff2a9d45e2d59" "checksum block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" @@ -1795,6 +1863,7 @@ dependencies = [ "checksum libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122" "checksum libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "88ee81885f9f04bff991e306fea7c1c60a5f0f9e409e99f6b40e3311a3363135" "checksum libflate 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7aa60ce680c15f96b74bd6208256f112049ab20fd6da510f27f82cb78323a77" +"checksum libgo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "99a64661b7d5c8b2ccb779e3fb0ced098426bb9bfbded934aa76ef227300e0cf" "checksum liner 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5621a282d4baa2e8c0b815974bf3e2819eb860bfb7bf1d2f99049f10084a7102" "checksum linked-hash-map 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "f26e961e0c884309cd527b1402a5409d35db612b36915d755e1a4f5c1547a31c" "checksum linked_list_allocator 0.2.5 (git+https://github.com/phil-opp/linked-list-allocator.git)" = "" @@ -1823,6 +1892,7 @@ dependencies = [ "checksum octavo 0.1.1 (git+https://github.com/libOctavo/octavo.git)" = "" "checksum octavo-digest 0.1.2 (git+https://github.com/libOctavo/octavo.git)" = "" "checksum odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "c3df9b730298cea3a1c3faa90b7e2f9df3a9c400d0936d6015e6165734eefcba" +"checksum orbclient 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "6e8e982388f410b93ce531c13aa6bf1203d9e806e8034d8cb91d65a570a413a5" "checksum orbclient 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "858fffc665397fca91f3d2c3f5d6cbe84932ae95d3c2701e96ca943a099b07d3" "checksum orbfont 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9a781ee4a8df3d8206832ef8b8ccbb3f964aa0ec9e2794fdb8806d47bb0b89af" "checksum orbimage 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c3b031607ef7a3c562949dfb595b1ea2b2d697b14544af407242a52dce811a6f" @@ -1859,7 +1929,9 @@ dependencies = [ "checksum scoped_threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3ef399c8893e8cb7aa9696e895427fab3a6bf265977bb96e126f24ddd2cda85a" "checksum scroll 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "39c82d0508f6a56bdb409031382d62e9fa7f5e198fa04dfc06a7a96f1dfc101d" "checksum sdl2 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c366cfa1f22d001774214ce2fb13f369af760b016bc79cc62d7f5ae15c00fea" +"checksum sdl2 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9cf70f3d302b61311856bcbd9c9d000aadc7c595574214335cf09035fdced2c9" "checksum sdl2-sys 0.27.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8d9f87e3d948f94f2d8688970422f49249c20e97f8f3aad76cb8729901d4eb10" +"checksum sdl2-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "657e3a3a175fda33c05d943923a768c7bf94c3b5fad05dcb31fc0321b11f47bd" "checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" "checksum serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97b18e9e53de541f11e497357d6c5eaeb39f0cb9c8734e274abe4935f6991fa" "checksum serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" diff --git a/Cargo.toml b/Cargo.toml index 18a6498..5104b8a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,15 +14,18 @@ members = [ "installer", "kernel", "programs/acid", + "programs/binutils", "programs/contain", "programs/coreutils", "programs/extrautils", + "programs/games", "programs/init", "programs/ion", "programs/netutils", "programs/orbutils", "programs/pkgutils", "programs/smith", + "programs/sodium", "programs/tar", "programs/timeout", "programs/userutils", From f58e35b46f00ebeeaf718deb12104308f0a1ca65 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 16 Apr 2017 15:41:47 -0600 Subject: [PATCH 300/522] Update orbclient --- Cargo.lock | 24 ++++++++++++------------ Cargo.toml | 3 ++- libs/orbclient | 2 +- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9d1f681..419b7d5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -838,7 +838,7 @@ dependencies = [ [[package]] name = "orbclient" -version = "0.3.3" +version = "0.3.4" dependencies = [ "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "sdl2 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -846,15 +846,15 @@ dependencies = [ [[package]] name = "orbclient" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -replace = "orbclient 0.3.3" +replace = "orbclient 0.3.4" [[package]] name = "orbfont" version = "0.1.7" dependencies = [ - "orbclient 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "rusttype 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -869,7 +869,7 @@ name = "orbimage" version = "0.1.15" dependencies = [ "image 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", - "orbclient 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "resize 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -883,7 +883,7 @@ replace = "orbimage 0.1.15" name = "orbital" version = "0.1.0" dependencies = [ - "orbclient 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "orbfont 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "orbimage 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", @@ -897,7 +897,7 @@ dependencies = [ name = "orbtk" version = "0.2.19" dependencies = [ - "orbclient 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "orbfont 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "orbimage 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -919,7 +919,7 @@ dependencies = [ "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "orbclient 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "orbfont 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "orbimage 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "orbtk 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1047,7 +1047,7 @@ name = "ps2d" version = "0.1.0" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "orbclient 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1709,7 +1709,7 @@ dependencies = [ name = "vboxd" version = "0.1.0" dependencies = [ - "orbclient 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1723,7 +1723,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "vesad" version = "0.1.0" dependencies = [ - "orbclient 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "ransid 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "rusttype 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1893,7 +1893,7 @@ dependencies = [ "checksum octavo-digest 0.1.2 (git+https://github.com/libOctavo/octavo.git)" = "" "checksum odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "c3df9b730298cea3a1c3faa90b7e2f9df3a9c400d0936d6015e6165734eefcba" "checksum orbclient 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "6e8e982388f410b93ce531c13aa6bf1203d9e806e8034d8cb91d65a570a413a5" -"checksum orbclient 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "858fffc665397fca91f3d2c3f5d6cbe84932ae95d3c2701e96ca943a099b07d3" +"checksum orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "06be24afab121c4167c8e9c9781e49b7c232f774815816b67c7c6aa7fc503cf1" "checksum orbfont 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9a781ee4a8df3d8206832ef8b8ccbb3f964aa0ec9e2794fdb8806d47bb0b89af" "checksum orbimage 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c3b031607ef7a3c562949dfb595b1ea2b2d697b14544af407242a52dce811a6f" "checksum orbtk 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "2bca50ac6874107a922dd26dc79889b963afce69075940463ce026b5281bf9f1" diff --git a/Cargo.toml b/Cargo.toml index 5104b8a..8469ac1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ members = [ "drivers/xhcid", "installer", "kernel", + "libs/orbclient", "programs/acid", "programs/binutils", "programs/contain", @@ -43,7 +44,7 @@ members = [ "extra:0.1.0" = { path = "libs/extra" } "jpeg-decoder:0.1.12" = { path = "libs/jpeg-decoder" } "mio:0.6.2" = { path = "libs/mio" } -"orbclient:0.3.3" = { path = "libs/orbclient" } +"orbclient:0.3.4" = { path = "libs/orbclient" } "orbfont:0.1.7" = { path = "libs/orbfont" } "orbimage:0.1.15" = { path = "libs/orbimage" } "orbtk:0.2.19" = { path = "libs/orbtk" } diff --git a/libs/orbclient b/libs/orbclient index 2266aac..4a31537 160000 --- a/libs/orbclient +++ b/libs/orbclient @@ -1 +1 @@ -Subproject commit 2266aac1a9f300941d72d51e9a7fdb23eceeeb7e +Subproject commit 4a3153798bd8d22380f057c07f1e77f8bd9a3cec From 66e090b9430043935aa312b10b3ab818018fabc9 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 17 Apr 2017 19:25:15 -0600 Subject: [PATCH 301/522] Increase FS size Update list of crates in workspace --- Cargo.lock | 365 ++++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 14 ++ mk/filesystem.mk | 2 +- 3 files changed, 373 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 419b7d5..99b8619 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,6 +28,22 @@ dependencies = [ "spin 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "aho-corasick" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aho-corasick" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "alloc_kernel" version = "0.1.0" @@ -36,6 +52,16 @@ dependencies = [ "spin 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "alxd" +version = "0.1.0" +dependencies = [ + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "netutils 0.1.0 (git+https://github.com/redox-os/netutils.git)", + "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ansi_term" version = "0.9.0" @@ -83,6 +109,11 @@ name = "bitflags" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bitflags" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "bitflags" version = "0.7.0" @@ -116,6 +147,16 @@ name = "byteorder" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bytes" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cfg-if" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "clipboard" version = "0.1.2" @@ -206,6 +247,17 @@ dependencies = [ "walkdir 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "docopt" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "e1000d" version = "0.1.0" @@ -281,6 +333,15 @@ dependencies = [ "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "env_logger" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "error-chain" version = "0.7.2" @@ -300,6 +361,10 @@ name = "extra" version = "0.1.0" source = "git+https://github.com/redox-os/libextra.git#402932084acd5fef4812945887ceaaa2ddd5f264" +[[package]] +name = "extra" +version = "0.1.0" + [[package]] name = "extrautils" version = "0.1.0" @@ -312,6 +377,15 @@ dependencies = [ "termion 1.3.0 (git+https://github.com/redox-os/termion.git)", ] +[[package]] +name = "flate2" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fnv" version = "1.0.5" @@ -510,6 +584,10 @@ name = "jpeg-decoder" version = "0.1.12" dependencies = [ "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "png 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -550,6 +628,11 @@ name = "lazy_static" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "lazycell" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "libc" version = "0.1.12" @@ -623,6 +706,22 @@ name = "matches" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "memchr" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "memchr" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "metadeps" version = "1.1.1" @@ -652,6 +751,57 @@ dependencies = [ "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "miniz-sys" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mio" +version = "0.6.2" +dependencies = [ + "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "miow" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "net2" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "netutils" version = "0.1.0" @@ -677,6 +827,19 @@ dependencies = [ "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "nix" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "nodrop" version = "0.1.9" @@ -888,8 +1051,8 @@ dependencies = [ "orbimage 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "resize 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -940,6 +1103,13 @@ dependencies = [ "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "pager" +version = "0.1.0" +dependencies = [ + "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "pcid" version = "0.1.0" @@ -1031,6 +1201,17 @@ dependencies = [ "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "png" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "inflate 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "png" version = "0.6.2" @@ -1064,6 +1245,21 @@ name = "quote" version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ralloc" +version = "1.0.0" +dependencies = [ + "ralloc_shim 0.1.1", + "unborrow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ralloc_shim" +version = "0.1.1" +dependencies = [ + "sc 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand" version = "0.3.15" @@ -1135,6 +1331,13 @@ dependencies = [ "redox_syscall 0.1.17 (git+https://github.com/redox-os/syscall.git)", ] +[[package]] +name = "redox_event" +version = "0.1.0" +dependencies = [ + "redox_syscall 0.1.17 (git+https://github.com/redox-os/syscall.git)", +] + [[package]] name = "redox_installer" version = "0.1.0" @@ -1174,6 +1377,40 @@ dependencies = [ "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "regex" +version = "0.1.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "regex-syntax" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "resize" version = "0.2.0" @@ -1242,6 +1479,15 @@ dependencies = [ "stb_truetype 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "same-file" +version = "0.1.2" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "same-file" version = "0.1.3" @@ -1251,6 +1497,11 @@ dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "sc" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "scoped_threadpool" version = "0.1.7" @@ -1323,7 +1574,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "0.9.13" +version = "0.9.14" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1362,7 +1613,7 @@ dependencies = [ [[package]] name = "serde_derive" -version = "0.9.13" +version = "0.9.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1384,6 +1635,11 @@ name = "siphasher" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "slab" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "smith" version = "0.3.10" @@ -1449,6 +1705,11 @@ name = "string_cache_shared" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "strsim" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "syn" version = "0.10.8" @@ -1533,11 +1794,46 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" replace = "termion 1.3.0" +[[package]] +name = "thread-id" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thread-id" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "thread-scoped" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "thread_local" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thread_local" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "time" version = "0.1.36" @@ -1571,7 +1867,7 @@ name = "toml" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1599,6 +1895,11 @@ dependencies = [ "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "unborrow" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicase" version = "1.4.0" @@ -1705,6 +2006,16 @@ dependencies = [ "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "utf8-ranges" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "utf8-ranges" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "vboxd" version = "0.1.0" @@ -1788,6 +2099,15 @@ name = "windows-error" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "x11" version = "2.13.0" @@ -1811,17 +2131,22 @@ dependencies = [ [metadata] "checksum adler32 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ff33fe13a08dbce05bcefa2c68eea4844941437e33d6f808240b54d7157b9cd" +"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" +"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" "checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392" "checksum arrayvec 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "35c1e907260135089def5aac0c66ca42624f2ed60652451812fedbc5a574baed" "checksum base64 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2015e3793554aa5b6007e3a72959e84c1070039e74f13dde08fa64afe1ddd892" "checksum bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "32866f4d103c4e438b1db1158aa1b1a80ee078e5d77a59a2f906fd62a577389c" +"checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum blake2-rfc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "0c6a476f32fef3402f1161f89d0d39822809627754a126f8441ff2a9d45e2d59" "checksum block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" "checksum byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96c8b41881888cc08af32d47ac4edd52bc7fa27fef774be47a92443756451304" "checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" "checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8" +"checksum bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c129aff112dcc562970abb69e2508b40850dd24c274761bb50fb8a0067ba6c27" +"checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c" "checksum clipboard 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "811169a9ffda99ed1841a6db3c48cffbab9a9101376f77fee3c14a7581ab933d" "checksum clipboard-win 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f05017278a9e5485eacce962c9efc52f720eef0d19646dc3a7af714aad22ed2c" "checksum color_quant 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a475fc4af42d83d28adf72968d9bcfaf035a1a9381642d8e85d8a04957767b0d" @@ -1830,6 +2155,7 @@ dependencies = [ "checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3" "checksum deflate 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "54b46d466b36f3bcc4dbb288be4f7de6f15ff90eda7a594408fbc7b780258e2f" "checksum deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1614659040e711785ed8ea24219140654da1729f3ec8a47a9719d041112fe7bf" +"checksum docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab32ea6e284d87987066f21a9e809a73c14720571ef34516f0890b3d355ccfd8" "checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" "checksum encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" "checksum encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" @@ -1838,8 +2164,10 @@ dependencies = [ "checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" "checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" "checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" +"checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" "checksum error-chain 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "318cb3c71ee4cdea69fdc9e15c173b245ed6063e1709029e8fd32525a881120f" "checksum extra 0.1.0 (git+https://github.com/redox-os/libextra.git)" = "" +"checksum flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "36df0166e856739905cd3d7e0b210fe818592211a008862599845e012d8d304c" "checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344" "checksum fuse 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "adf08478eb39cff95e34daa7a2743a256d1c18388c0328d2f717e8ef748001f6" "checksum futf 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "51f93f3de6ba1794dcd5810b3546d004600a59a98266487c8407bc4b24e398f3" @@ -1860,6 +2188,7 @@ dependencies = [ "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" "checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" +"checksum lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce12306c4739d86ee97c23139f3a34ddf0387bbf181bc7929d287025a8c3ef6b" "checksum libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122" "checksum libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "88ee81885f9f04bff991e306fea7c1c60a5f0f9e409e99f6b40e3311a3363135" "checksum libflate 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7aa60ce680c15f96b74bd6208256f112049ab20fd6da510f27f82cb78323a77" @@ -1872,10 +2201,16 @@ dependencies = [ "checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" "checksum malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" "checksum matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efd7622e3022e1a6eaa602c4cea8912254e5582c9c692e9167714182244801b1" +"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" +"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" "checksum metadeps 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829fffe7ea1d747e23f64be972991bc516b2f1ac2ae4a3b33d8bea150c410151" "checksum mime 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5514f038123342d01ee5f95129e4ef1e0470c93bc29edf058a46f9ee3ba6737e" "checksum mime_guess 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76da6df85047af8c0edfa53f48eb1073012ce1cc95c8fedc0a374f659a89dd65" +"checksum miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "28eaee17666671fa872e567547e8428e83308ebe5808cdf6a0e28397dbe2c726" +"checksum miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3e690c5df6b2f60acd45d56378981e827ff8295562fc8d34f573deb267a59cd1" +"checksum net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)" = "18b9642ad6222faf5ce46f6966f59b71b9775ad5758c9e09fcf0a6c8061972b4" "checksum netutils 0.1.0 (git+https://github.com/redox-os/netutils.git)" = "" +"checksum nix 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0d95c5fa8b641c10ad0b8887454ebaafa3c92b5cd5350f8fc693adafd178e7b" "checksum nodrop 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "52cd74cd09beba596430cc6e3091b74007169a56246e1262f0ba451ea95117b2" "checksum ntpclient 0.0.1 (git+https://github.com/willem66745/ntpclient-rust)" = "" "checksum num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "98b15ba84e910ea7a1973bccd3df7b31ae282bf9d8bd2897779950c9b8303d40" @@ -1907,6 +2242,7 @@ dependencies = [ "checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2" "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" "checksum pkgutils 0.1.0 (git+https://github.com/redox-os/pkgutils.git)" = "" +"checksum png 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "06208e2ee243e3118a55dda9318f821f206d8563fb8d4df258767f8e62bb0997" "checksum png 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3cb773e9a557edb568ce9935cf783e3cdcabe06a9449d41b3e5506d88e582c82" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d" @@ -1918,6 +2254,10 @@ dependencies = [ "checksum redox_event 0.1.0 (git+https://github.com/redox-os/event.git)" = "" "checksum redox_syscall 0.1.17 (git+https://github.com/redox-os/syscall.git)" = "" "checksum redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "29dbdfd4b9df8ab31dec47c6087b7b13cbf4a776f335e4de8efba8288dda075b" +"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" +"checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01" +"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" +"checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457" "checksum resize 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e8f5c5cf4d79776ed121e1c5052718b4bb06d2b48049144a2f0e5ad613b608e" "checksum ring 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6210568620e7b9d3f6e27f4bef63140cb88a15fbfb49b041bd3343b92c109166" "checksum ropey 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ffbce36196db96680b526bc2e2e27f23003e5ffab07271a176646c26dd0028b" @@ -1926,6 +2266,7 @@ dependencies = [ "checksum rustls 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fcfb2a577b14dca9caf13e6c6aa86d61158aa677347fbc155e5a1dac0f3b718f" "checksum rusttype 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c64ffc93b0cc5a6f5e5e84da2a4082b0271e0a1dd76e821bdac570bda7797e" "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7" +"checksum sc 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "75a5fa736d03da66e77fb5827f78e2112754c6c78035c4269f192d21615b39f0" "checksum scoped_threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3ef399c8893e8cb7aa9696e895427fab3a6bf265977bb96e126f24ddd2cda85a" "checksum scroll 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "39c82d0508f6a56bdb409031382d62e9fa7f5e198fa04dfc06a7a96f1dfc101d" "checksum sdl2 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c366cfa1f22d001774214ce2fb13f369af760b016bc79cc62d7f5ae15c00fea" @@ -1935,20 +2276,22 @@ dependencies = [ "checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" "checksum serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97b18e9e53de541f11e497357d6c5eaeb39f0cb9c8734e274abe4935f6991fa" "checksum serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" -"checksum serde 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)" = "231dfd55909400769e437326cfb4af8bec97c3dd56ab3d02df8ef5c7e00f179b" +"checksum serde 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)" = "a4c9a40d556f8431394def53446db659f796dc87a53ef67b7541f21057fbdd91" "checksum serde_codegen 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "a4c5d8a33087d8984f9535daa62a6498a08f6476050b00ab9339dd847e4c25cc" "checksum serde_codegen_internals 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "afad7924a009f859f380e4a2e3a509a845c2ac66435fcead74a4d983b21ae806" "checksum serde_codegen_internals 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bc888bd283bd2420b16ad0d860e35ad8acb21941180a83a189bb2046f9d00400" "checksum serde_derive 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "ce44e5f4264b39e9d29c875357b7cc3ebdfb967bb9e22bfb5e44ffa400af5306" -"checksum serde_derive 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)" = "d75c72ef4dd193d89eb652b73890fe2489996c9ead8b37980f57a1078f96ed50" +"checksum serde_derive 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)" = "3e472ff72816522c7837cf932585a838576a85e8642632ccf7b8d43b7a1bf1af" "checksum serde_json 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5aaee47e038bf9552d30380d3973fff2593ee0a76d81ad4c581f267cdcadf36" "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" +"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" "checksum spin 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1d16a26e2b789f86aabddbe91cb82ee2e822beb8a59840d631941b625ef77e53" "checksum static-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6da6a96247d4b372d3ed90dec2c129ab57c934359ac4c6adbaa5871cd0737437" "checksum stb_truetype 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "21b5c3b588a493a477e0d99769ee091b3627625f9ba4bdd882e6b4b0b0958805" "checksum string_cache 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d192db2123fac37399e1ca61557904a5c3fb6fc24c73d2e47b15d20dc32470" "checksum string_cache_codegen 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0c9dfe1a7c8bba1ecb90730d269fdc08afe93d23c28dd6c4aa5cabd79a05a05e" "checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc" +"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" "checksum syn 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)" = "58fd09df59565db3399efbba34ba8a2fec1307511ebd245d0061ff9d42691673" "checksum syn 0.11.10 (registry+https://github.com/rust-lang/crates.io-index)" = "171b739972d9a1bfb169e8077238b51f9ebeaae4ff6e08072f7ba386a8802da2" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" @@ -1956,13 +2299,18 @@ dependencies = [ "checksum tendril 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cebf864c2d90394a1b66d6fe45963f9a177f2af81a0edea5060f77627f9c4587" "checksum termion 1.3.0 (git+https://github.com/redox-os/termion.git)" = "" "checksum termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b41865823fb8c7873ff869893219b3188e7fcd66c10effb97f2b2f63ea98681" +"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" +"checksum thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437c97558c70d129e40629a5b385b3fb1ffac301e63941335e4d354081ec14a" "checksum thread-scoped 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14387dce246d09efe184c8ebc34d9db5c0672a908b2f50efc53359ae13d5ae68" +"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" +"checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7" "checksum time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "211b63c112206356ef1ff9b19355f43740fc3f85960c598a93d3a3d3ba7beade" "checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4" "checksum toml 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd86ad9ebee246fdedd610e0f6d0587b754a3d81438db930a244d0480ed7878f" "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" "checksum typenum 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f06b0aa9c30a626496836e8de28bd2910cf6c8614e9579c9f8644b0a5d8fb0f5" +"checksum unborrow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e92e959f029e4f8ee25d70d15ab58d2b46f98a17bc238b9265ff0c26f6f3d67f" "checksum unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "13a5906ca2b98c799f4b1ab4557b76367ebd6ae5ef14930ec841c74aed5f3764" "checksum unicode-bidi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3a078ebdd62c0e71a709c3d53d2af693fe09fe93fbff8344aebe289b78f9032" "checksum unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e28fa37426fceeb5cf8f41ee273faa7c82c47dc8fba5853402841e665fcd86ff" @@ -1976,6 +2324,8 @@ dependencies = [ "checksum users 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7ae8fdf783cb9652109c99886459648feb92ecc749e6b8e7930f6decba74c7c" "checksum userutils 0.1.0 (git+https://github.com/redox-os/userutils.git)" = "" "checksum utf-8 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9aee9ba280438b56d1ebc5329f2094f0ff457f811eeeff0b278d75aa99db400" +"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" +"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum version_check 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f2edadb5308f31d97771a678c33df28f18d04f61de3fe21b9452f37854eb6c08" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum walkdir 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c66c0b9792f0a765345452775f3adbd28dde9d33f30d13e5dcc5ae17cf6f3780" @@ -1985,5 +2335,6 @@ dependencies = [ "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum windows-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d8570474f84367116f48f9fb2ae3e0347600029909096a15a5e6509bd4a03c50" +"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum x11 2.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab7c9c8fcd61c1453aa7506d45be2fa916512f0c4ec985ef20bba3d575a23a6" "checksum x86 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "127728f29f7cfb243a9264c80fc7e57bd1abb3ab015850b05736efda2abe5859" diff --git a/Cargo.toml b/Cargo.toml index 8469ac1..548dc72 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ members = [ "docgen", "drivers/ahcid", + "drivers/alxd", "drivers/bgad", "drivers/e1000d", "drivers/nvmed", @@ -13,7 +14,20 @@ members = [ "drivers/xhcid", "installer", "kernel", + "libs/event", + "libs/extra", + "libs/jpeg-decoder", + "libs/mio", "libs/orbclient", + "libs/orbfont", + "libs/orbimage", + "libs/orbtk", + "libs/pager", + "libs/ralloc", + "libs/ransid", + "libs/same-file", + "libs/syscall", + "libs/termion", "programs/acid", "programs/binutils", "programs/contain", diff --git a/mk/filesystem.mk b/mk/filesystem.mk index 956c31f..eb482e6 100644 --- a/mk/filesystem.mk +++ b/mk/filesystem.mk @@ -1,7 +1,7 @@ build/filesystem.bin: userspace -$(FUMOUNT) build/filesystem/ || true rm -rf $@ build/filesystem/ - dd if=/dev/zero of=$@ bs=1048576 count=64 + dd if=/dev/zero of=$@ bs=1048576 count=128 cargo run --manifest-path schemes/redoxfs/Cargo.toml --release --bin redoxfs-mkfs $@ mkdir -p build/filesystem/ cargo build --manifest-path schemes/redoxfs/Cargo.toml --release --bin redoxfs From a139f0d260a69fe2ef9e58da2d5df4b5faf31e01 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 17 Apr 2017 19:57:36 -0600 Subject: [PATCH 302/522] Remove ralloc from worspace as it creates error messages --- Cargo.lock | 27 --------------------------- Cargo.toml | 2 +- 2 files changed, 1 insertion(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 99b8619..1646050 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1245,21 +1245,6 @@ name = "quote" version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "ralloc" -version = "1.0.0" -dependencies = [ - "ralloc_shim 0.1.1", - "unborrow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ralloc_shim" -version = "0.1.1" -dependencies = [ - "sc 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rand" version = "0.3.15" @@ -1497,11 +1482,6 @@ dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "sc" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "scoped_threadpool" version = "0.1.7" @@ -1895,11 +1875,6 @@ dependencies = [ "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "unborrow" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "unicase" version = "1.4.0" @@ -2266,7 +2241,6 @@ dependencies = [ "checksum rustls 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fcfb2a577b14dca9caf13e6c6aa86d61158aa677347fbc155e5a1dac0f3b718f" "checksum rusttype 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c64ffc93b0cc5a6f5e5e84da2a4082b0271e0a1dd76e821bdac570bda7797e" "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7" -"checksum sc 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "75a5fa736d03da66e77fb5827f78e2112754c6c78035c4269f192d21615b39f0" "checksum scoped_threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3ef399c8893e8cb7aa9696e895427fab3a6bf265977bb96e126f24ddd2cda85a" "checksum scroll 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "39c82d0508f6a56bdb409031382d62e9fa7f5e198fa04dfc06a7a96f1dfc101d" "checksum sdl2 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c366cfa1f22d001774214ce2fb13f369af760b016bc79cc62d7f5ae15c00fea" @@ -2310,7 +2284,6 @@ dependencies = [ "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" "checksum typenum 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f06b0aa9c30a626496836e8de28bd2910cf6c8614e9579c9f8644b0a5d8fb0f5" -"checksum unborrow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e92e959f029e4f8ee25d70d15ab58d2b46f98a17bc238b9265ff0c26f6f3d67f" "checksum unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "13a5906ca2b98c799f4b1ab4557b76367ebd6ae5ef14930ec841c74aed5f3764" "checksum unicode-bidi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3a078ebdd62c0e71a709c3d53d2af693fe09fe93fbff8344aebe289b78f9032" "checksum unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e28fa37426fceeb5cf8f41ee273faa7c82c47dc8fba5853402841e665fcd86ff" diff --git a/Cargo.toml b/Cargo.toml index 548dc72..74692b5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ members = [ "libs/orbimage", "libs/orbtk", "libs/pager", - "libs/ralloc", + #TODO "libs/ralloc", "libs/ransid", "libs/same-file", "libs/syscall", From 07f3659f55c54b7f00a6ce4b43446c56ed315e0a Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 17 Apr 2017 20:37:06 -0600 Subject: [PATCH 303/522] Quieter filesystem generation --- mk/filesystem.mk | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mk/filesystem.mk b/mk/filesystem.mk index eb482e6..d1eb674 100644 --- a/mk/filesystem.mk +++ b/mk/filesystem.mk @@ -2,10 +2,10 @@ build/filesystem.bin: userspace -$(FUMOUNT) build/filesystem/ || true rm -rf $@ build/filesystem/ dd if=/dev/zero of=$@ bs=1048576 count=128 - cargo run --manifest-path schemes/redoxfs/Cargo.toml --release --bin redoxfs-mkfs $@ + cargo run --manifest-path schemes/redoxfs/Cargo.toml --quiet --release --bin redoxfs-mkfs $@ mkdir -p build/filesystem/ - cargo build --manifest-path schemes/redoxfs/Cargo.toml --release --bin redoxfs - cargo run --manifest-path schemes/redoxfs/Cargo.toml --release --bin redoxfs -- $@ build/filesystem/ + cargo build --manifest-path schemes/redoxfs/Cargo.toml --quiet --release --bin redoxfs + cargo run --manifest-path schemes/redoxfs/Cargo.toml --quiet --release --bin redoxfs -- $@ build/filesystem/ sleep 2 pgrep redoxfs cp -RL filesystem/* build/filesystem/ @@ -30,8 +30,8 @@ build/filesystem.bin: userspace mount: FORCE mkdir -p build/filesystem/ - cargo build --manifest-path schemes/redoxfs/Cargo.toml --release --bin redoxfs - cargo run --manifest-path schemes/redoxfs/Cargo.toml --release --bin redoxfs -- build/harddrive.bin build/filesystem/ + cargo build --manifest-path schemes/redoxfs/Cargo.toml --quiet --release --bin redoxfs + cargo run --manifest-path schemes/redoxfs/Cargo.toml --quiet --release --bin redoxfs -- build/harddrive.bin build/filesystem/ sleep 2 pgrep redoxfs From 887ecfe83823e4a689dd28a05265cfa5f27a73fc Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 18 Apr 2017 21:06:19 -0600 Subject: [PATCH 304/522] Update drivers, coreutils, rust, orbital --- Cargo.lock | 7 ++++--- drivers | 2 +- programs/coreutils | 2 +- rust | 2 +- schemes/orbital | 2 +- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1646050..a4a7a60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -484,7 +484,7 @@ dependencies = [ [[package]] name = "httparse" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -492,7 +492,7 @@ name = "hyper" version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1049,6 +1049,7 @@ dependencies = [ "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "orbfont 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "orbimage 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "resize 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2153,7 +2154,7 @@ dependencies = [ "checksum goblin 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3536832676b9c0bde31ef9b6d1c8a9cc897267eaf15caaddcaef313f94b42e53" "checksum html5ever 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a358fef34c3334e92cd34d83ce870a386334e605e7abe987a69a7078a4142c69" "checksum html5ever-atoms 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4109e35fec157307b918eb9d5b7018e2fa771aea0c04831e22003ac4722fbd1b" -"checksum httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a6e7a63e511f9edffbab707141fbb8707d1a3098615fb2adbd5769cdfcc9b17d" +"checksum httparse 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77f756bed9ee3a83ce98774f4155b42a31b787029013f3a7d83eca714e500e21" "checksum hyper 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)" = "38368702037feddcb6470b4dc641adcc585373ab037c757bbc2818a21968d051" "checksum hyper-rustls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b948ce26b93a7cb182c84aa5205e614d54bf7a7194cfaec6ee3c45d83350700a" "checksum idna 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6ac85ec3f80c8e4e99d9325521337e14ec7555c458a14e377d189659a427f375" diff --git a/drivers b/drivers index 1e70139..b3849dd 160000 --- a/drivers +++ b/drivers @@ -1 +1 @@ -Subproject commit 1e7013915b589531aec378df4cd51d615d8abb46 +Subproject commit b3849ddf364c21fa2689a68b337bd61c099bc5f6 diff --git a/programs/coreutils b/programs/coreutils index 81ae3b9..5ccbc51 160000 --- a/programs/coreutils +++ b/programs/coreutils @@ -1 +1 @@ -Subproject commit 81ae3b9a8549215f9b2ad850c633ba0fca502756 +Subproject commit 5ccbc51583be0d4049a95a147ea00b61afb359d9 diff --git a/rust b/rust index 1bc9e5d..9f2abad 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 1bc9e5da2367cdeebd86afb4ad1a3d45aae53837 +Subproject commit 9f2abadca2d065bf81772cb84981d0a22d8e98b3 diff --git a/schemes/orbital b/schemes/orbital index 19e475b..e8a7304 160000 --- a/schemes/orbital +++ b/schemes/orbital @@ -1 +1 @@ -Subproject commit 19e475b0fac8f197fb779f87c5b14f4d48b04829 +Subproject commit e8a73040268708a5f8bde3e9d703f6cbbab2b85f From 91346372284d269dbac2e354f715d0cb9a01544f Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 18 Apr 2017 21:26:53 -0600 Subject: [PATCH 305/522] Update kernel, update rust version in README --- README.md | 2 +- kernel | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 00caf31..3b66d75 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Please make sure you use the **latest nightly** of `rustc` before building (for [![Travis Build Status](https://travis-ci.org/redox-os/redox.svg?branch=master)](https://travis-ci.org/redox-os/redox) [![Downloads](https://img.shields.io/github/downloads/redox-os/redox/total.svg)](https://github.com/redox-os/redox/releases) [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE.md) -![Rust Version](https://img.shields.io/badge/rust-nightly%202017--04--04-lightgrey.svg) +![Rust Version](https://img.shields.io/badge/rust-nightly%202017--04--18-lightgrey.svg) ## Contents diff --git a/kernel b/kernel index d036c66..40ff16e 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit d036c667a1ad7e104cd48846bf6b90961da8c1fb +Subproject commit 40ff16e42dd256664ed1bd018ddcecb138e48ed1 From 64c8fc9f774e7787d166c86cadd47bb05246ca4f Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 19 Apr 2017 21:56:22 -0600 Subject: [PATCH 306/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index 40ff16e..efd64d5 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 40ff16e42dd256664ed1bd018ddcecb138e48ed1 +Subproject commit efd64d55e1c684279ea1d96fe0da2ee659280d66 From f196535fc504f271db4b953fd54b3250b13af367 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 20 Apr 2017 19:31:02 -0600 Subject: [PATCH 307/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index efd64d5..dd98bfe 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit efd64d55e1c684279ea1d96fe0da2ee659280d66 +Subproject commit dd98bfec5c254f965f8293bae8c3738712a9d2ad From 3733157bc38f5dcd51589e1d6549830521c99ce4 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 20 Apr 2017 19:37:31 -0600 Subject: [PATCH 308/522] Update coreutils and ion --- programs/coreutils | 2 +- programs/ion | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/programs/coreutils b/programs/coreutils index 5ccbc51..bc953d8 160000 --- a/programs/coreutils +++ b/programs/coreutils @@ -1 +1 @@ -Subproject commit 5ccbc51583be0d4049a95a147ea00b61afb359d9 +Subproject commit bc953d8f25da20bd691b1855bc382cdd00a8603b diff --git a/programs/ion b/programs/ion index 2afa32c..e2547d6 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit 2afa32c5b5e98a6bbf16b323f0ed72e16f2530c3 +Subproject commit e2547d699fcd9149bfcc17a4fb090822bbc641dc From 9aa81e571dd39fe145354ba3553ea7676d299b2b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 20 Apr 2017 19:37:39 -0600 Subject: [PATCH 309/522] Update Cargo.lock --- Cargo.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a4a7a60..fd4b823 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -489,7 +489,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hyper" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "httparse 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -511,7 +511,7 @@ name = "hyper-rustls" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hyper 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "webpki-roots 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -807,7 +807,7 @@ name = "netutils" version = "0.1.0" source = "git+https://github.com/redox-os/netutils.git#f97aeea5cfd83d4fafc7673baae458433b0e7fd0" dependencies = [ - "hyper 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-rustls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "ntpclient 0.0.1 (git+https://github.com/willem66745/ntpclient-rust)", @@ -819,7 +819,7 @@ dependencies = [ name = "netutils" version = "0.1.0" dependencies = [ - "hyper 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-rustls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "ntpclient 0.0.1 (git+https://github.com/willem66745/ntpclient-rust)", @@ -1078,7 +1078,7 @@ version = "0.1.14" dependencies = [ "html5ever 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "html5ever-atoms 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-rustls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1186,7 +1186,7 @@ name = "pkgutils" version = "0.1.0" source = "git+https://github.com/redox-os/pkgutils.git#9c80d548c636182437c2cef60afa6b988a69332b" dependencies = [ - "hyper 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-rustls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "octavo 0.1.1 (git+https://github.com/libOctavo/octavo.git)", "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1196,7 +1196,7 @@ dependencies = [ name = "pkgutils" version = "0.1.0" dependencies = [ - "hyper 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-rustls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "octavo 0.1.1 (git+https://github.com/libOctavo/octavo.git)", "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1581,7 +1581,7 @@ name = "serde_codegen_internals" version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "syn 0.11.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1599,7 +1599,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "serde_codegen_internals 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.11.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1702,7 +1702,7 @@ dependencies = [ [[package]] name = "syn" -version = "0.11.10" +version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2155,7 +2155,7 @@ dependencies = [ "checksum html5ever 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a358fef34c3334e92cd34d83ce870a386334e605e7abe987a69a7078a4142c69" "checksum html5ever-atoms 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4109e35fec157307b918eb9d5b7018e2fa771aea0c04831e22003ac4722fbd1b" "checksum httparse 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77f756bed9ee3a83ce98774f4155b42a31b787029013f3a7d83eca714e500e21" -"checksum hyper 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)" = "38368702037feddcb6470b4dc641adcc585373ab037c757bbc2818a21968d051" +"checksum hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)" = "94da93321c171e26481afeebe8288757b0501901b7c5492648163d8ec4942ec5" "checksum hyper-rustls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b948ce26b93a7cb182c84aa5205e614d54bf7a7194cfaec6ee3c45d83350700a" "checksum idna 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6ac85ec3f80c8e4e99d9325521337e14ec7555c458a14e377d189659a427f375" "checksum image 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "979bad0502082fd60053a490282e87d6c89650942e3a270e0d4c83569c7f5899" @@ -2268,7 +2268,7 @@ dependencies = [ "checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc" "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" "checksum syn 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)" = "58fd09df59565db3399efbba34ba8a2fec1307511ebd245d0061ff9d42691673" -"checksum syn 0.11.10 (registry+https://github.com/rust-lang/crates.io-index)" = "171b739972d9a1bfb169e8077238b51f9ebeaae4ff6e08072f7ba386a8802da2" +"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" "checksum tendril 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cebf864c2d90394a1b66d6fe45963f9a177f2af81a0edea5060f77627f9c4587" From 98e7a35630d8d16ad49ac7ff8aaa6d2937e34bb2 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 22 Apr 2017 20:06:56 -0600 Subject: [PATCH 310/522] Update to break tar into library and utility --- .gitmodules | 6 ++-- Cargo.lock | 66 ++++++++++++++++++++++++-------------- Cargo.toml | 3 +- libs/tar | 1 + mk/userspace/extrautils.mk | 3 +- mk/userspace/mod.mk | 1 - programs/extrautils | 2 +- programs/tar | 1 - 8 files changed, 51 insertions(+), 32 deletions(-) create mode 160000 libs/tar delete mode 160000 programs/tar diff --git a/.gitmodules b/.gitmodules index 93dfd1a..3ef03da 100644 --- a/.gitmodules +++ b/.gitmodules @@ -34,9 +34,6 @@ [submodule "programs/acid"] path = programs/acid url = https://github.com/redox-os/acid.git -[submodule "programs/tar"] - path = programs/tar - url = https://github.com/redox-os/tar-rs.git [submodule "programs/pkgutils"] path = programs/pkgutils url = https://github.com/redox-os/pkgutils.git @@ -115,3 +112,6 @@ [submodule "libs/ralloc"] path = libs/ralloc url = https://github.com/redox-os/ralloc.git +[submodule "libs/tar"] + path = libs/tar + url = https://github.com/redox-os/tar-rs.git diff --git a/Cargo.lock b/Cargo.lock index fd4b823..6cd2f44 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -212,7 +212,7 @@ version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -254,7 +254,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -374,6 +374,7 @@ dependencies = [ "pager 0.1.0 (git+https://github.com/redox-os/libpager.git)", "raw-cpuid 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "tar 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.3.0 (git+https://github.com/redox-os/termion.git)", ] @@ -468,7 +469,7 @@ dependencies = [ "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", "tendril 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -497,7 +498,7 @@ dependencies = [ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -508,7 +509,7 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -528,13 +529,12 @@ dependencies = [ [[package]] name = "image" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gif 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "jpeg-decoder 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", "num-rational 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", @@ -808,7 +808,7 @@ version = "0.1.0" source = "git+https://github.com/redox-os/netutils.git#f97aeea5cfd83d4fafc7673baae458433b0e7fd0" dependencies = [ "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-rustls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-rustls 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "ntpclient 0.0.1 (git+https://github.com/willem66745/ntpclient-rust)", "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", @@ -820,7 +820,7 @@ name = "netutils" version = "0.1.0" dependencies = [ "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-rustls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-rustls 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "ntpclient 0.0.1 (git+https://github.com/willem66745/ntpclient-rust)", "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", @@ -878,7 +878,7 @@ dependencies = [ "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -887,7 +887,7 @@ version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -915,7 +915,7 @@ dependencies = [ "num-bigint 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1031,7 +1031,7 @@ replace = "orbfont 0.1.7" name = "orbimage" version = "0.1.15" dependencies = [ - "image 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", + "image 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)", "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "resize 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1079,7 +1079,7 @@ dependencies = [ "html5ever 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "html5ever-atoms 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-rustls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-rustls 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1116,7 +1116,7 @@ name = "pcid" version = "0.1.0" dependencies = [ "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1187,7 +1187,7 @@ version = "0.1.0" source = "git+https://github.com/redox-os/pkgutils.git#9c80d548c636182437c2cef60afa6b988a69332b" dependencies = [ "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-rustls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-rustls 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "octavo 0.1.1 (git+https://github.com/libOctavo/octavo.git)", "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1197,7 +1197,7 @@ name = "pkgutils" version = "0.1.0" dependencies = [ "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-rustls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-rustls 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "octavo 0.1.1 (git+https://github.com/libOctavo/octavo.git)", "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1431,7 +1431,7 @@ dependencies = [ [[package]] name = "rustc-serialize" -version = "0.3.23" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1720,11 +1720,19 @@ dependencies = [ [[package]] name = "tar" -version = "0.4.7" +version = "0.4.11" dependencies = [ + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tar" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +replace = "tar 0.4.11" + [[package]] name = "tcpd" version = "0.1.0" @@ -1839,7 +1847,7 @@ name = "toml" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2046,7 +2054,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ring 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2105,6 +2113,14 @@ dependencies = [ "serde_json 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "xattr" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + [metadata] "checksum adler32 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ff33fe13a08dbce05bcefa2c68eea4844941437e33d6f808240b54d7157b9cd" "checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" @@ -2156,9 +2172,9 @@ dependencies = [ "checksum html5ever-atoms 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4109e35fec157307b918eb9d5b7018e2fa771aea0c04831e22003ac4722fbd1b" "checksum httparse 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77f756bed9ee3a83ce98774f4155b42a31b787029013f3a7d83eca714e500e21" "checksum hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)" = "94da93321c171e26481afeebe8288757b0501901b7c5492648163d8ec4942ec5" -"checksum hyper-rustls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b948ce26b93a7cb182c84aa5205e614d54bf7a7194cfaec6ee3c45d83350700a" +"checksum hyper-rustls 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "68fdeacba341bed69e9b8fb8acbe618f18c5614e173895635ee7cb7eae57fd3d" "checksum idna 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6ac85ec3f80c8e4e99d9325521337e14ec7555c458a14e377d189659a427f375" -"checksum image 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "979bad0502082fd60053a490282e87d6c89650942e3a270e0d4c83569c7f5899" +"checksum image 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d95816db758249fe16f23a4e23f1a3a817fe11892dbfd1c5836f625324702158" "checksum inflate 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e7e0062d2dc2f17d2f13750d95316ae8a2ff909af0fda957084f5defd87c43bb" "checksum jpeg-decoder 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "919d49b634cde303392353c5dd51153ec005a1a981c6f4b8277692a51e9d260d" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" @@ -2237,7 +2253,7 @@ dependencies = [ "checksum resize 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e8f5c5cf4d79776ed121e1c5052718b4bb06d2b48049144a2f0e5ad613b608e" "checksum ring 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6210568620e7b9d3f6e27f4bef63140cb88a15fbfb49b041bd3343b92c109166" "checksum ropey 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ffbce36196db96680b526bc2e2e27f23003e5ffab07271a176646c26dd0028b" -"checksum rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "684ce48436d6465300c9ea783b6b14c4361d6b8dcbb1375b486a69cc19e2dfb0" +"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" "checksum rustls 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fcfb2a577b14dca9caf13e6c6aa86d61158aa677347fbc155e5a1dac0f3b718f" "checksum rusttype 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c64ffc93b0cc5a6f5e5e84da2a4082b0271e0a1dd76e821bdac570bda7797e" @@ -2270,6 +2286,7 @@ dependencies = [ "checksum syn 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)" = "58fd09df59565db3399efbba34ba8a2fec1307511ebd245d0061ff9d42691673" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +"checksum tar 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c2374f318bbe2c5ac6c83dd6240d5f1a73106f72d39b3f7d6f8d8637c7b425d8" "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" "checksum tendril 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cebf864c2d90394a1b66d6fe45963f9a177f2af81a0edea5060f77627f9c4587" "checksum termion 1.3.0 (git+https://github.com/redox-os/termion.git)" = "" @@ -2312,3 +2329,4 @@ dependencies = [ "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum x11 2.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab7c9c8fcd61c1453aa7506d45be2fa916512f0c4ec985ef20bba3d575a23a6" "checksum x86 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "127728f29f7cfb243a9264c80fc7e57bd1abb3ab015850b05736efda2abe5859" +"checksum xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "5f04de8a1346489a2f9e9bd8526b73d135ec554227b17568456e86aa35b6f3fc" diff --git a/Cargo.toml b/Cargo.toml index 74692b5..d0897f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ members = [ "libs/ransid", "libs/same-file", "libs/syscall", + "libs/tar", "libs/termion", "programs/acid", "programs/binutils", @@ -41,7 +42,6 @@ members = [ "programs/pkgutils", "programs/smith", "programs/sodium", - "programs/tar", "programs/timeout", "programs/userutils", "schemes/ethernetd", @@ -68,4 +68,5 @@ members = [ "redox_event:0.1.0" = { path = "libs/event" } "redox_syscall:0.1.17" = { path = "libs/syscall" } "same-file:0.1.2" = { path = "libs/same-file" } +"tar:0.4.11" = { path = "libs/tar" } "termion:1.3.0" = { path = "libs/termion" } diff --git a/libs/tar b/libs/tar new file mode 160000 index 0000000..395f33a --- /dev/null +++ b/libs/tar @@ -0,0 +1 @@ +Subproject commit 395f33aabec89131e6ae840174a680eca6be6257 diff --git a/mk/userspace/extrautils.mk b/mk/userspace/extrautils.mk index 3f1843f..ceb4c17 100644 --- a/mk/userspace/extrautils.mk +++ b/mk/userspace/extrautils.mk @@ -11,7 +11,8 @@ extrautils: \ filesystem/bin/mtxt \ filesystem/bin/rem \ filesystem/bin/resize \ - filesystem/bin/screenfetch + filesystem/bin/screenfetch \ + filesystem/bin/tar #filesystem/bin/dmesg filesystem/bin/info filesystem/bin/watch filesystem/bin/%: programs/extrautils/Cargo.toml programs/extrautils/src/bin/%.rs $(BUILD)/libstd.rlib diff --git a/mk/userspace/mod.mk b/mk/userspace/mod.mk index 0a12655..903efe4 100644 --- a/mk/userspace/mod.mk +++ b/mk/userspace/mod.mk @@ -12,7 +12,6 @@ userspace: \ filesystem/bin/acid \ filesystem/bin/contain \ filesystem/bin/smith \ - filesystem/bin/tar \ filesystem/bin/timeout include mk/userspace/coreutils.mk diff --git a/programs/extrautils b/programs/extrautils index 1f7c539..26f6ff5 160000 --- a/programs/extrautils +++ b/programs/extrautils @@ -1 +1 @@ -Subproject commit 1f7c539245fba17965323445d5be11cd4dffd168 +Subproject commit 26f6ff59a7c789b1d00819fd61ba9ce8f97feec5 diff --git a/programs/tar b/programs/tar deleted file mode 160000 index efb5b05..0000000 --- a/programs/tar +++ /dev/null @@ -1 +0,0 @@ -Subproject commit efb5b052480b2822a4401358c6ee6be3c33b969c From bc71c369a3852eb5dcb3ca7d0a4fcddeba17636b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 22 Apr 2017 21:01:10 -0600 Subject: [PATCH 311/522] Update ion, smith, and Rust --- programs/ion | 2 +- programs/smith | 2 +- rust | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/programs/ion b/programs/ion index e2547d6..65d367b 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit e2547d699fcd9149bfcc17a4fb090822bbc641dc +Subproject commit 65d367bc9db10b8015b980d0e89ef3cf5d645c20 diff --git a/programs/smith b/programs/smith index 8f68825..53f8f25 160000 --- a/programs/smith +++ b/programs/smith @@ -1 +1 @@ -Subproject commit 8f68825b06d14309eb3723f9c76f77b0e90ebee9 +Subproject commit 53f8f25928e6efe1733612960da72cdbf97041d0 diff --git a/rust b/rust index 9f2abad..252d3da 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 9f2abadca2d065bf81772cb84981d0a22d8e98b3 +Subproject commit 252d3da8a6c715ccafcf77d83b826f6fb899cfe5 From d8b8101bf01939ba7dfc6b497744d47d7147fdd9 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 22 Apr 2017 21:05:07 -0600 Subject: [PATCH 312/522] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3b66d75..a808136 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Please make sure you use the **latest nightly** of `rustc` before building (for [![Travis Build Status](https://travis-ci.org/redox-os/redox.svg?branch=master)](https://travis-ci.org/redox-os/redox) [![Downloads](https://img.shields.io/github/downloads/redox-os/redox/total.svg)](https://github.com/redox-os/redox/releases) [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE.md) -![Rust Version](https://img.shields.io/badge/rust-nightly%202017--04--18-lightgrey.svg) +![Rust Version](https://img.shields.io/badge/rust-nightly%202017--04--22-lightgrey.svg) ## Contents From fbb93d9d6c955537f44d45c0068c03861fbfe287 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 25 Apr 2017 13:10:54 -0600 Subject: [PATCH 313/522] Update extrautils --- programs/extrautils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/extrautils b/programs/extrautils index 26f6ff5..3f7d502 160000 --- a/programs/extrautils +++ b/programs/extrautils @@ -1 +1 @@ -Subproject commit 26f6ff59a7c789b1d00819fd61ba9ce8f97feec5 +Subproject commit 3f7d5027883169385086ea674be4127e7962e5b9 From 736c8d23317680040678d197afaf32e3e1c4b7d4 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 25 Apr 2017 17:52:09 -0600 Subject: [PATCH 314/522] Update submodules and Cargo.lock --- Cargo.lock | 95 +++++++++++++++++++++++++++++++++-------------- drivers | 2 +- kernel | 2 +- libs/tar | 2 +- programs/ion | 2 +- programs/pkgutils | 2 +- 6 files changed, 73 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6cd2f44..5405805 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -78,7 +78,7 @@ dependencies = [ [[package]] name = "arrayvec" -version = "0.3.22" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "nodrop 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -374,7 +374,7 @@ dependencies = [ "pager 0.1.0 (git+https://github.com/redox-os/libpager.git)", "raw-cpuid 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tar 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tar 0.4.11 (git+https://github.com/redox-os/tar-rs.git)", "termion 1.3.0 (git+https://github.com/redox-os/termion.git)", ] @@ -401,7 +401,7 @@ dependencies = [ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "thread-scoped 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -500,7 +500,7 @@ dependencies = [ "num_cpus 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -854,7 +854,7 @@ version = "0.0.1" source = "git+https://github.com/willem66745/ntpclient-rust#7e3bdf60eb940825789a8da5181025320e3050b0" dependencies = [ "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1052,8 +1052,8 @@ dependencies = [ "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "resize 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1116,8 +1116,9 @@ name = "pcid" version = "0.1.0" dependencies = [ "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1184,11 +1185,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "pkgutils" version = "0.1.0" -source = "git+https://github.com/redox-os/pkgutils.git#9c80d548c636182437c2cef60afa6b988a69332b" +source = "git+https://github.com/redox-os/pkgutils.git#4cf2e9d216721282a8f2bb82c031ee90ede878f4" dependencies = [ "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-rustls 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "octavo 0.1.1 (git+https://github.com/libOctavo/octavo.git)", + "tar 0.4.11 (git+https://github.com/redox-os/tar-rs.git)", "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1199,6 +1201,7 @@ dependencies = [ "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-rustls 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "octavo 0.1.1 (git+https://github.com/libOctavo/octavo.git)", + "tar 0.4.11 (git+https://github.com/redox-os/tar-rs.git)", "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1360,7 +1363,7 @@ dependencies = [ "fuse 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "spin 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1450,7 +1453,7 @@ dependencies = [ "base64 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "ring 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "webpki 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1460,7 +1463,7 @@ name = "rusttype" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", "linked-hash-map 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "stb_truetype 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1555,7 +1558,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "0.9.14" +version = "0.9.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1594,7 +1602,7 @@ dependencies = [ [[package]] name = "serde_derive" -version = "0.9.14" +version = "0.9.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1602,6 +1610,25 @@ dependencies = [ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "serde_derive" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_derive_internals" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", + "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "serde_json" version = "0.6.1" @@ -1721,17 +1748,20 @@ dependencies = [ [[package]] name = "tar" version = "0.4.11" +source = "git+https://github.com/redox-os/tar-rs.git#1ccf2baf1703bd30807c3f11a8a874ea53af6f74" dependencies = [ "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tar" version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -replace = "tar 0.4.11" +dependencies = [ + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "tcpd" @@ -1825,7 +1855,7 @@ dependencies = [ [[package]] name = "time" -version = "0.1.36" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1847,7 +1877,6 @@ name = "toml" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1856,7 +1885,15 @@ name = "toml" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "toml" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2055,7 +2092,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ring 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2127,7 +2164,7 @@ dependencies = [ "checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" "checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392" -"checksum arrayvec 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "35c1e907260135089def5aac0c66ca42624f2ed60652451812fedbc5a574baed" +"checksum arrayvec 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "699e63a93b79d717e8c3b5eb1b28b7780d0d6d9e59a72eb769291c83b0c8dc67" "checksum base64 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2015e3793554aa5b6007e3a72959e84c1070039e74f13dde08fa64afe1ddd892" "checksum bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "32866f4d103c4e438b1db1158aa1b1a80ee078e5d77a59a2f906fd62a577389c" "checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" @@ -2267,12 +2304,15 @@ dependencies = [ "checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" "checksum serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97b18e9e53de541f11e497357d6c5eaeb39f0cb9c8734e274abe4935f6991fa" "checksum serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" -"checksum serde 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)" = "a4c9a40d556f8431394def53446db659f796dc87a53ef67b7541f21057fbdd91" +"checksum serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)" = "34b623917345a631dc9608d5194cc206b3fe6c3554cd1c75b937e55e285254af" +"checksum serde 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1be24992f20bb7dfb9932a152a6f51ed7f756ebd8df1ea707ecab09d615d3ede" "checksum serde_codegen 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "a4c5d8a33087d8984f9535daa62a6498a08f6476050b00ab9339dd847e4c25cc" "checksum serde_codegen_internals 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "afad7924a009f859f380e4a2e3a509a845c2ac66435fcead74a4d983b21ae806" "checksum serde_codegen_internals 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bc888bd283bd2420b16ad0d860e35ad8acb21941180a83a189bb2046f9d00400" "checksum serde_derive 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "ce44e5f4264b39e9d29c875357b7cc3ebdfb967bb9e22bfb5e44ffa400af5306" -"checksum serde_derive 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)" = "3e472ff72816522c7837cf932585a838576a85e8642632ccf7b8d43b7a1bf1af" +"checksum serde_derive 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)" = "978fd866f4d4872084a81ccc35e275158351d3b9fe620074e7d7504b816b74ba" +"checksum serde_derive 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "94f3c3fd5cd27ffda6e1f330daed369d087b50557d59bd19c230c893f4fced60" +"checksum serde_derive_internals 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "021c338d22c7e30f957a6ab7e388cb6098499dda9fd4ba1661ee074ca7a180d1" "checksum serde_json 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5aaee47e038bf9552d30380d3973fff2593ee0a76d81ad4c581f267cdcadf36" "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" @@ -2286,7 +2326,7 @@ dependencies = [ "checksum syn 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)" = "58fd09df59565db3399efbba34ba8a2fec1307511ebd245d0061ff9d42691673" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" -"checksum tar 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c2374f318bbe2c5ac6c83dd6240d5f1a73106f72d39b3f7d6f8d8637c7b425d8" +"checksum tar 0.4.11 (git+https://github.com/redox-os/tar-rs.git)" = "" "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" "checksum tendril 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cebf864c2d90394a1b66d6fe45963f9a177f2af81a0edea5060f77627f9c4587" "checksum termion 1.3.0 (git+https://github.com/redox-os/termion.git)" = "" @@ -2296,9 +2336,10 @@ dependencies = [ "checksum thread-scoped 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14387dce246d09efe184c8ebc34d9db5c0672a908b2f50efc53359ae13d5ae68" "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" "checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7" -"checksum time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "211b63c112206356ef1ff9b19355f43740fc3f85960c598a93d3a3d3ba7beade" +"checksum time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "ffd7ccbf969a892bf83f1e441126968a07a3941c24ff522a26af9f9f4585d1a3" "checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4" "checksum toml 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd86ad9ebee246fdedd610e0f6d0587b754a3d81438db930a244d0480ed7878f" +"checksum toml 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3063405db158de3dce8efad5fc89cf1baffb9501a3647dc9505ba109694ce31f" "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" "checksum typenum 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f06b0aa9c30a626496836e8de28bd2910cf6c8614e9579c9f8644b0a5d8fb0f5" diff --git a/drivers b/drivers index b3849dd..d3c29d0 160000 --- a/drivers +++ b/drivers @@ -1 +1 @@ -Subproject commit b3849ddf364c21fa2689a68b337bd61c099bc5f6 +Subproject commit d3c29d0fb44011b2ad7bfe421d4ab01d590cb4ab diff --git a/kernel b/kernel index dd98bfe..0a457bd 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit dd98bfec5c254f965f8293bae8c3738712a9d2ad +Subproject commit 0a457bdcedf0f5e64a641e272b647124b20f3ec4 diff --git a/libs/tar b/libs/tar index 395f33a..1ccf2ba 160000 --- a/libs/tar +++ b/libs/tar @@ -1 +1 @@ -Subproject commit 395f33aabec89131e6ae840174a680eca6be6257 +Subproject commit 1ccf2baf1703bd30807c3f11a8a874ea53af6f74 diff --git a/programs/ion b/programs/ion index 65d367b..34d8536 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit 65d367bc9db10b8015b980d0e89ef3cf5d645c20 +Subproject commit 34d8536e31478f729869c916ecffc425ea449a87 diff --git a/programs/pkgutils b/programs/pkgutils index 9c80d54..4cf2e9d 160000 --- a/programs/pkgutils +++ b/programs/pkgutils @@ -1 +1 @@ -Subproject commit 9c80d548c636182437c2cef60afa6b988a69332b +Subproject commit 4cf2e9d216721282a8f2bb82c031ee90ede878f4 From e19964d02348a26b4cab9eb25879b1f789e92289 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 25 Apr 2017 18:20:56 -0600 Subject: [PATCH 315/522] Move repos --- filesystem/etc/installer.toml | 2 +- filesystem/etc/pkg.d/{ => repos}/50_redox | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename filesystem/etc/pkg.d/{ => repos}/50_redox (100%) diff --git a/filesystem/etc/installer.toml b/filesystem/etc/installer.toml index 34347d2..09e4772 100644 --- a/filesystem/etc/installer.toml +++ b/filesystem/etc/installer.toml @@ -32,7 +32,7 @@ path = "/etc/net/ip_subnet" data = "255.255.255.0" [[files]] -path = "/etc/pkg.d/50_redox" +path = "/etc/pkg.d/repos/50_redox" data = "https://static.redox-os.org/pkg" # User settings diff --git a/filesystem/etc/pkg.d/50_redox b/filesystem/etc/pkg.d/repos/50_redox similarity index 100% rename from filesystem/etc/pkg.d/50_redox rename to filesystem/etc/pkg.d/repos/50_redox From 5d7554262965af564b4d193d814804f3632dd064 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 25 Apr 2017 18:21:08 -0600 Subject: [PATCH 316/522] Update pkgutils --- programs/pkgutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/pkgutils b/programs/pkgutils index 4cf2e9d..a0ec9c6 160000 --- a/programs/pkgutils +++ b/programs/pkgutils @@ -1 +1 @@ -Subproject commit 4cf2e9d216721282a8f2bb82c031ee90ede878f4 +Subproject commit a0ec9c605c1005fc62c0599190a94eca5fa4e4ee From 4c9e8bf8461158e8a53f6174c32d466232e1e611 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 25 Apr 2017 18:46:19 -0600 Subject: [PATCH 317/522] Revert "Move repos" This reverts commit e19964d02348a26b4cab9eb25879b1f789e92289. --- filesystem/etc/installer.toml | 2 +- filesystem/etc/pkg.d/{repos => }/50_redox | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename filesystem/etc/pkg.d/{repos => }/50_redox (100%) diff --git a/filesystem/etc/installer.toml b/filesystem/etc/installer.toml index 09e4772..34347d2 100644 --- a/filesystem/etc/installer.toml +++ b/filesystem/etc/installer.toml @@ -32,7 +32,7 @@ path = "/etc/net/ip_subnet" data = "255.255.255.0" [[files]] -path = "/etc/pkg.d/repos/50_redox" +path = "/etc/pkg.d/50_redox" data = "https://static.redox-os.org/pkg" # User settings diff --git a/filesystem/etc/pkg.d/repos/50_redox b/filesystem/etc/pkg.d/50_redox similarity index 100% rename from filesystem/etc/pkg.d/repos/50_redox rename to filesystem/etc/pkg.d/50_redox From 2c8987b88e55e305f323b0e33e11397d009cf025 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 25 Apr 2017 18:46:39 -0600 Subject: [PATCH 318/522] Update pkgutils --- programs/pkgutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/pkgutils b/programs/pkgutils index a0ec9c6..ac0f5f2 160000 --- a/programs/pkgutils +++ b/programs/pkgutils @@ -1 +1 @@ -Subproject commit a0ec9c605c1005fc62c0599190a94eca5fa4e4ee +Subproject commit ac0f5f2f73935fa8e0adf6cb2245c0d49c7e971f From a24ab7b047e9e1d491a49e4356d01a66d9367ad4 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 25 Apr 2017 21:44:11 -0600 Subject: [PATCH 319/522] Update pkgutils, netutils --- programs/netutils | 2 +- programs/pkgutils | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/programs/netutils b/programs/netutils index f97aeea..ed22829 160000 --- a/programs/netutils +++ b/programs/netutils @@ -1 +1 @@ -Subproject commit f97aeea5cfd83d4fafc7673baae458433b0e7fd0 +Subproject commit ed22829acd318a33d0580abee182da6fb11c972a diff --git a/programs/pkgutils b/programs/pkgutils index ac0f5f2..de65cd2 160000 --- a/programs/pkgutils +++ b/programs/pkgutils @@ -1 +1 @@ -Subproject commit ac0f5f2f73935fa8e0adf6cb2245c0d49c7e971f +Subproject commit de65cd20e7ba5325d8a3b7a86e42fe48271a063c From 3f56eb7b34129bdea9f59130aca14e68a91b9bce Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 25 Apr 2017 21:44:38 -0600 Subject: [PATCH 320/522] Update pkgutils --- programs/pkgutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/pkgutils b/programs/pkgutils index de65cd2..96436d9 160000 --- a/programs/pkgutils +++ b/programs/pkgutils @@ -1 +1 @@ -Subproject commit de65cd20e7ba5325d8a3b7a86e42fe48271a063c +Subproject commit 96436d966677af844bfe83c468dfe859509274ce From a9647859d0ccdac8701748017640d2ca821db8f4 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 25 Apr 2017 21:51:57 -0600 Subject: [PATCH 321/522] Update netutils --- programs/netutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/netutils b/programs/netutils index ed22829..074c900 160000 --- a/programs/netutils +++ b/programs/netutils @@ -1 +1 @@ -Subproject commit ed22829acd318a33d0580abee182da6fb11c972a +Subproject commit 074c900be31586f405cc46503a807e7ab8a7a2bb From 58347548212dbddd7adaa350d30b4bb39947fa5d Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 26 Apr 2017 19:43:39 -0600 Subject: [PATCH 322/522] Update submodules and dependencies --- Cargo.lock | 91 ++++++++++++++++++++++++----------------------- installer | 2 +- programs/pkgutils | 2 +- programs/smith | 2 +- schemes/redoxfs | 2 +- 5 files changed, 51 insertions(+), 48 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5405805..aa3eaea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -225,7 +225,7 @@ dependencies = [ [[package]] name = "deflate" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "adler32 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -234,11 +234,8 @@ dependencies = [ [[package]] name = "deque" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "docgen" @@ -383,7 +380,7 @@ name = "flate2" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -497,7 +494,7 @@ dependencies = [ "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", @@ -640,7 +637,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.21" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -698,7 +695,7 @@ name = "malloc_buf" version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -711,7 +708,7 @@ name = "memchr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -719,7 +716,7 @@ name = "memchr" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -757,7 +754,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -768,7 +765,7 @@ dependencies = [ "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", @@ -797,7 +794,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -805,11 +802,11 @@ dependencies = [ [[package]] name = "netutils" version = "0.1.0" -source = "git+https://github.com/redox-os/netutils.git#f97aeea5cfd83d4fafc7673baae458433b0e7fd0" +source = "git+https://github.com/redox-os/netutils.git#074c900be31586f405cc46503a807e7ab8a7a2bb" dependencies = [ "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-rustls 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "ntpclient 0.0.1 (git+https://github.com/willem66745/ntpclient-rust)", "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -821,7 +818,7 @@ version = "0.1.0" dependencies = [ "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-rustls 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "ntpclient 0.0.1 (git+https://github.com/willem66745/ntpclient-rust)", "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -834,7 +831,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -925,10 +922,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "num_cpus" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1080,7 +1077,7 @@ dependencies = [ "html5ever-atoms 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-rustls 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1185,13 +1182,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "pkgutils" version = "0.1.0" -source = "git+https://github.com/redox-os/pkgutils.git#4cf2e9d216721282a8f2bb82c031ee90ede878f4" +source = "git+https://github.com/redox-os/pkgutils.git#26ec0bd59734fcbf2c24c90d03a73bae244f45a6" dependencies = [ "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-rustls 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "octavo 0.1.1 (git+https://github.com/libOctavo/octavo.git)", + "serde 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.11 (git+https://github.com/redox-os/tar-rs.git)", "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1201,8 +1201,11 @@ dependencies = [ "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-rustls 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "octavo 0.1.1 (git+https://github.com/libOctavo/octavo.git)", + "serde 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.11 (git+https://github.com/redox-os/tar-rs.git)", "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1222,7 +1225,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "deflate 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "deflate 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", "inflate 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1254,7 +1257,7 @@ name = "rand" version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1305,10 +1308,10 @@ name = "rayon-core" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "deque 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1412,7 +1415,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1515,7 +1518,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "sdl2-sys 0.27.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1535,7 +1538,7 @@ name = "sdl2-sys" version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1750,7 +1753,7 @@ name = "tar" version = "0.4.11" source = "git+https://github.com/redox-os/tar-rs.git#1ccf2baf1703bd30807c3f11a8a874ea53af6f74" dependencies = [ - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1758,7 +1761,7 @@ dependencies = [ name = "tar" version = "0.4.11" dependencies = [ - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1797,14 +1800,14 @@ name = "termion" version = "1.3.0" source = "git+https://github.com/redox-os/termion.git#550b9ea50a11c838533a0cf2cd9c8f7584927cdb" dependencies = [ - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "termion" version = "1.3.0" dependencies = [ - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1819,7 +1822,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1828,7 +1831,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1859,7 +1862,7 @@ version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1993,7 +1996,7 @@ name = "users" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2134,7 +2137,7 @@ name = "x11" version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "metadeps 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2155,7 +2158,7 @@ name = "xattr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [metadata] @@ -2182,8 +2185,8 @@ dependencies = [ "checksum constant_time_eq 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "07dcb7959f0f6f1cf662f9a7ff389bcb919924d99ac41cf31f10d611d8721323" "checksum csv 0.14.7 (registry+https://github.com/rust-lang/crates.io-index)" = "266c1815d7ca63a5bd86284043faf91e8c95e943e55ce05dc0ae08e952de18bc" "checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3" -"checksum deflate 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "54b46d466b36f3bcc4dbb288be4f7de6f15ff90eda7a594408fbc7b780258e2f" -"checksum deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1614659040e711785ed8ea24219140654da1729f3ec8a47a9719d041112fe7bf" +"checksum deflate 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9f93b00ea29c37827cb6b2929ce666104b3e46cc5d18c6d02ddef275634c472a" +"checksum deque 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a694dae478589798d752c7125542f8a5ae8b6e59476172baf2eed67357bdfa27" "checksum docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab32ea6e284d87987066f21a9e809a73c14720571ef34516f0890b3d355ccfd8" "checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" "checksum encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" @@ -2219,7 +2222,7 @@ dependencies = [ "checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" "checksum lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce12306c4739d86ee97c23139f3a34ddf0387bbf181bc7929d287025a8c3ef6b" "checksum libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122" -"checksum libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "88ee81885f9f04bff991e306fea7c1c60a5f0f9e409e99f6b40e3311a3363135" +"checksum libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)" = "babb8281da88cba992fa1f4ddec7d63ed96280a1a53ec9b919fd37b53d71e502" "checksum libflate 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7aa60ce680c15f96b74bd6208256f112049ab20fd6da510f27f82cb78323a77" "checksum libgo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "99a64661b7d5c8b2ccb779e3fb0ced098426bb9bfbded934aa76ef227300e0cf" "checksum liner 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5621a282d4baa2e8c0b815974bf3e2819eb860bfb7bf1d2f99049f10084a7102" @@ -2249,7 +2252,7 @@ dependencies = [ "checksum num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d1891bd7b936f12349b7d1403761c8a0b85a18b148e9da4429d5d102c1a41e" "checksum num-rational 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "c2dc5ea04020a8f18318ae485c751f8cfa1c0e69dcf465c29ddaaa64a313cc44" "checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99" -"checksum num_cpus 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a18c392466409c50b87369414a2680c93e739aedeb498eb2bff7d7eb569744e2" +"checksum num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca313f1862c7ec3e0dfe8ace9fa91b1d9cb5c84ace3d00f5ec4216238e93c167" "checksum objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "877f30f37acef6749b1841cceab289707f211aecfc756553cd63976190e6cc2e" "checksum objc-foundation 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" "checksum objc_id 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e4730aa1c64d722db45f7ccc4113a3e2c465d018de6db4d3e7dfe031e8c8a297" diff --git a/installer b/installer index 7c7b30c..c2bae24 160000 --- a/installer +++ b/installer @@ -1 +1 @@ -Subproject commit 7c7b30c16e29443cb83017b806411e3637184072 +Subproject commit c2bae24835735df247e27093aa43bd1d0fe2a655 diff --git a/programs/pkgutils b/programs/pkgutils index 96436d9..26ec0bd 160000 --- a/programs/pkgutils +++ b/programs/pkgutils @@ -1 +1 @@ -Subproject commit 96436d966677af844bfe83c468dfe859509274ce +Subproject commit 26ec0bd59734fcbf2c24c90d03a73bae244f45a6 diff --git a/programs/smith b/programs/smith index 53f8f25..a36e2fd 160000 --- a/programs/smith +++ b/programs/smith @@ -1 +1 @@ -Subproject commit 53f8f25928e6efe1733612960da72cdbf97041d0 +Subproject commit a36e2fd252b99d24b13beb0ddadca87adc926452 diff --git a/schemes/redoxfs b/schemes/redoxfs index f0c38fe..6c1d98c 160000 --- a/schemes/redoxfs +++ b/schemes/redoxfs @@ -1 +1 @@ -Subproject commit f0c38fe609d666254ec29f6906603c3a3940ee46 +Subproject commit 6c1d98cea83e2bb02b940959e6b07625ec12656f From 195be9bdf6dafce00fa3a6cac546c8d39f1251ca Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 26 Apr 2017 21:29:34 -0600 Subject: [PATCH 323/522] Update drivers and bootloader --- bootloader | 2 +- drivers | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bootloader b/bootloader index eb3de28..5e5e080 160000 --- a/bootloader +++ b/bootloader @@ -1 +1 @@ -Subproject commit eb3de2861b532b31e633b10fbf14ae87d5980155 +Subproject commit 5e5e080d618db036c632e096bdf6ce5c77b33bae diff --git a/drivers b/drivers index d3c29d0..15675ea 160000 --- a/drivers +++ b/drivers @@ -1 +1 @@ -Subproject commit d3c29d0fb44011b2ad7bfe421d4ab01d590cb4ab +Subproject commit 15675ea9c3de8b552743f83ec2f9a7bbba538c15 From 305b6b8dcff6b306d665f6d555c4365ff4f16351 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 26 Apr 2017 21:29:56 -0600 Subject: [PATCH 324/522] Add Intel 82579V --- filesystem/etc/pcid.toml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/filesystem/etc/pcid.toml b/filesystem/etc/pcid.toml index f8a9515..ca097ce 100644 --- a/filesystem/etc/pcid.toml +++ b/filesystem/etc/pcid.toml @@ -19,6 +19,13 @@ vendor = 32902 device = 4111 command = ["/sbin/e1000d", "$NAME", "$BAR0", "$IRQ"] +[[drivers]] +name = "82579V NIC" +class = 2 +vendor = 32902 +device = 5379 +command = ["/sbin/e1000d", "$NAME", "$BAR0", "$IRQ"] + [[drivers]] name = "RTL8168 NIC" class = 2 From 7154acff1e4ddc1b0d226fbd646c7d7feddde18d Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 29 Apr 2017 15:42:48 -0600 Subject: [PATCH 325/522] Update submodules and dependencies --- Cargo.lock | 43 +++++++++++++++++++++++++++++-------------- kernel | 2 +- programs/ion | 2 +- programs/sodium | 2 +- rust | 2 +- 5 files changed, 33 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aa3eaea..b207684 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -225,7 +225,7 @@ dependencies = [ [[package]] name = "deflate" -version = "0.7.7" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "adler32 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -562,6 +562,8 @@ dependencies = [ "liner 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "peg-syntax-ext 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "permutate 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallstring 0.1.0", + "smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "users 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1113,8 +1115,8 @@ name = "pcid" version = "0.1.0" dependencies = [ "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1187,8 +1189,8 @@ dependencies = [ "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-rustls 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "octavo 0.1.1 (git+https://github.com/libOctavo/octavo.git)", - "serde 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.11 (git+https://github.com/redox-os/tar-rs.git)", "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1201,8 +1203,8 @@ dependencies = [ "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-rustls 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "octavo 0.1.1 (git+https://github.com/libOctavo/octavo.git)", - "serde 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.11 (git+https://github.com/redox-os/tar-rs.git)", "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1225,7 +1227,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "deflate 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", + "deflate 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", "inflate 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1566,7 +1568,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1615,7 +1617,7 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1651,6 +1653,18 @@ name = "slab" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "smallstring" +version = "0.1.0" +dependencies = [ + "smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "smallvec" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "smith" version = "0.3.10" @@ -1896,7 +1910,7 @@ name = "toml" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2185,7 +2199,7 @@ dependencies = [ "checksum constant_time_eq 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "07dcb7959f0f6f1cf662f9a7ff389bcb919924d99ac41cf31f10d611d8721323" "checksum csv 0.14.7 (registry+https://github.com/rust-lang/crates.io-index)" = "266c1815d7ca63a5bd86284043faf91e8c95e943e55ce05dc0ae08e952de18bc" "checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3" -"checksum deflate 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9f93b00ea29c37827cb6b2929ce666104b3e46cc5d18c6d02ddef275634c472a" +"checksum deflate 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "464225978f3f01068194aa948852ec121d179c3f874d499d74c432953bf1917b" "checksum deque 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a694dae478589798d752c7125542f8a5ae8b6e59476172baf2eed67357bdfa27" "checksum docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab32ea6e284d87987066f21a9e809a73c14720571ef34516f0890b3d355ccfd8" "checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" @@ -2308,17 +2322,18 @@ dependencies = [ "checksum serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97b18e9e53de541f11e497357d6c5eaeb39f0cb9c8734e274abe4935f6991fa" "checksum serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" "checksum serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)" = "34b623917345a631dc9608d5194cc206b3fe6c3554cd1c75b937e55e285254af" -"checksum serde 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1be24992f20bb7dfb9932a152a6f51ed7f756ebd8df1ea707ecab09d615d3ede" +"checksum serde 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3b46a59dd63931010fdb1d88538513f3279090d88b5c22ef4fe8440cfffcc6e3" "checksum serde_codegen 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "a4c5d8a33087d8984f9535daa62a6498a08f6476050b00ab9339dd847e4c25cc" "checksum serde_codegen_internals 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "afad7924a009f859f380e4a2e3a509a845c2ac66435fcead74a4d983b21ae806" "checksum serde_codegen_internals 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bc888bd283bd2420b16ad0d860e35ad8acb21941180a83a189bb2046f9d00400" "checksum serde_derive 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "ce44e5f4264b39e9d29c875357b7cc3ebdfb967bb9e22bfb5e44ffa400af5306" "checksum serde_derive 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)" = "978fd866f4d4872084a81ccc35e275158351d3b9fe620074e7d7504b816b74ba" -"checksum serde_derive 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "94f3c3fd5cd27ffda6e1f330daed369d087b50557d59bd19c230c893f4fced60" +"checksum serde_derive 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6c06b68790963518008b8ae0152d48be4bbbe77015d2c717f6282eea1824be9a" "checksum serde_derive_internals 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "021c338d22c7e30f957a6ab7e388cb6098499dda9fd4ba1661ee074ca7a180d1" "checksum serde_json 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5aaee47e038bf9552d30380d3973fff2593ee0a76d81ad4c581f267cdcadf36" "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" +"checksum smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4f8266519bc1d17d0b5b16f6c21295625d562841c708f6376f49028a43e9c11e" "checksum spin 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1d16a26e2b789f86aabddbe91cb82ee2e822beb8a59840d631941b625ef77e53" "checksum static-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6da6a96247d4b372d3ed90dec2c129ab57c934359ac4c6adbaa5871cd0737437" "checksum stb_truetype 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "21b5c3b588a493a477e0d99769ee091b3627625f9ba4bdd882e6b4b0b0958805" diff --git a/kernel b/kernel index 0a457bd..b3a25bd 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 0a457bdcedf0f5e64a641e272b647124b20f3ec4 +Subproject commit b3a25bd3a39cd527b80d5ab2ea0da56a91e10540 diff --git a/programs/ion b/programs/ion index 34d8536..e75823a 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit 34d8536e31478f729869c916ecffc425ea449a87 +Subproject commit e75823a64cfaa264b3f4232dc1920d9c8a4bb959 diff --git a/programs/sodium b/programs/sodium index 4104a44..0334b3d 160000 --- a/programs/sodium +++ b/programs/sodium @@ -1 +1 @@ -Subproject commit 4104a44ad839abf297dcd0182e41099cf6e5436c +Subproject commit 0334b3d178b605e9bb46f98f1f2bea64c121cd2f diff --git a/rust b/rust index 252d3da..e326e86 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 252d3da8a6c715ccafcf77d83b826f6fb899cfe5 +Subproject commit e326e86b47edcded3313944a81f126a633032d86 From 8828b2227cc9aa57fb9fe47cc91555afd81416f2 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 30 Apr 2017 19:50:43 -0600 Subject: [PATCH 326/522] Update peg --- Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b207684..7b1b7af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -560,7 +560,7 @@ dependencies = [ "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "liner 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "peg-syntax-ext 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "peg-syntax-ext 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "permutate 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallstring 0.1.0", "smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1122,7 +1122,7 @@ dependencies = [ [[package]] name = "peg" -version = "0.4.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1130,10 +1130,10 @@ dependencies = [ [[package]] name = "peg-syntax-ext" -version = "0.4.2" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "peg 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "peg 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2279,8 +2279,8 @@ dependencies = [ "checksum orbimage 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c3b031607ef7a3c562949dfb595b1ea2b2d697b14544af407242a52dce811a6f" "checksum orbtk 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "2bca50ac6874107a922dd26dc79889b963afce69075940463ce026b5281bf9f1" "checksum pager 0.1.0 (git+https://github.com/redox-os/libpager.git)" = "" -"checksum peg 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b2f7b0a8240dbf3d5cca65bba9791de310ce783d6e1426e56dc1278356b8017a" -"checksum peg-syntax-ext 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "40f9e24d396d5d1857dbacd9b8a12c9e9922f40a52ab56bfdb681194fbdd6bdc" +"checksum peg 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a85e13cbc4888df1091443e418a772c94163ab5a9cfcfe57d7fcf6ab1057b3c2" +"checksum peg-syntax-ext 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73c6541641bcf873455f1d208566ee3c85543de74f2a65a198109e86365501a8" "checksum permutate 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b4ba980af238a6d6fcc0df53fe0d7920376bc4ce2c6ce298992891a230b47a8" "checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc" "checksum phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d62594c0bb54c464f633175d502038177e90309daf2e0158be42ed5f023ce88f" From bc48ada0e6ea27a4a44fe24554608dfa502a8d20 Mon Sep 17 00:00:00 2001 From: Abdel-Rahman Date: Mon, 1 May 2017 19:13:30 +0300 Subject: [PATCH 327/522] CONTRIBUTING.md: Replace Magnets with pkgutils --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0f25fd0..4c27589 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -72,7 +72,7 @@ News and updates for Redox are posted at [redox-os.org/news](https://redox-os.or * Apps development * Shell ([Ion](https://github.com/redox-os/ion)) development - * Package manager ([Magnet](https://github.com/redox-os/magnet)) development + * Package management ([pkgutils](https://github.com/redox-os/pkgutils)) development * Other high-level code tasks #### If you are fluent in Rust, and have experience with OS Dev: From 1246e3d08ad8de79757726a64c97ddb8ef463644 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20DESBRI=C3=88RES?= Date: Tue, 2 May 2017 22:08:35 +0200 Subject: [PATCH 328/522] + rustup update --- README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index a808136..8e0b8d9 100644 --- a/README.md +++ b/README.md @@ -77,12 +77,13 @@ The ecosystem and software Redox OS provides is listed below. Sometimes things go wrong when compiling. Try the following before opening an issue: -1. Run `make clean`. -2. Run `git clean -Xfd`. -3. Make sure you have **the latest version of Rust nightly!** ([rustup.rs](https://www.rustup.rs) is recommended for managing Rust versions. If you already have it, run `rustup`). -4. Update **GNU Make**, **NASM** and **QEMU/VirtualBox**. -5. Pull the upstream master branch (`git remote add upstream git@github.com:redox-os/redox.git; git pull upstream master`). -6. Update submodules (`git submodule update --recursive --init`). +1. Run `rustup update` +2. Run `make clean`. +3. Run `git clean -Xfd`. +4. Make sure you have **the latest version of Rust nightly!** ([rustup.rs](https://www.rustup.rs) is recommended for managing Rust versions. If you already have it, run `rustup`). +5. Update **GNU Make**, **NASM** and **QEMU/VirtualBox**. +6. Pull the upstream master branch (`git remote add upstream git@github.com:redox-os/redox.git; git pull upstream master`). +7. Update submodules (`git submodule update --recursive --init`). and then rebuild! From 98649e5346e6f1fe866dff770cb03bd55e351606 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 3 May 2017 20:51:17 -0600 Subject: [PATCH 329/522] Update ion, smith, Rust, and dependencies --- Cargo.lock | 19 +++++-------------- programs/ion | 2 +- programs/smith | 2 +- rust | 2 +- 4 files changed, 8 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7b1b7af..8f41eed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -560,7 +560,7 @@ dependencies = [ "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "liner 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "peg-syntax-ext 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "peg 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "permutate 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallstring 0.1.0", "smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1128,14 +1128,6 @@ dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "peg-syntax-ext" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "peg 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "permutate" version = "0.2.0" @@ -1412,7 +1404,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ring" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1457,7 +1449,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "webpki 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2107,7 +2099,7 @@ name = "webpki" version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ring 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2280,7 +2272,6 @@ dependencies = [ "checksum orbtk 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "2bca50ac6874107a922dd26dc79889b963afce69075940463ce026b5281bf9f1" "checksum pager 0.1.0 (git+https://github.com/redox-os/libpager.git)" = "" "checksum peg 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a85e13cbc4888df1091443e418a772c94163ab5a9cfcfe57d7fcf6ab1057b3c2" -"checksum peg-syntax-ext 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73c6541641bcf873455f1d208566ee3c85543de74f2a65a198109e86365501a8" "checksum permutate 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b4ba980af238a6d6fcc0df53fe0d7920376bc4ce2c6ce298992891a230b47a8" "checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc" "checksum phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d62594c0bb54c464f633175d502038177e90309daf2e0158be42ed5f023ce88f" @@ -2305,7 +2296,7 @@ dependencies = [ "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" "checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457" "checksum resize 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e8f5c5cf4d79776ed121e1c5052718b4bb06d2b48049144a2f0e5ad613b608e" -"checksum ring 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6210568620e7b9d3f6e27f4bef63140cb88a15fbfb49b041bd3343b92c109166" +"checksum ring 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "621adad0185f587ad058bbecededfa2413f5f2e999563bc96349dead9e00d25c" "checksum ropey 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ffbce36196db96680b526bc2e2e27f23003e5ffab07271a176646c26dd0028b" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" diff --git a/programs/ion b/programs/ion index e75823a..b86941d 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit e75823a64cfaa264b3f4232dc1920d9c8a4bb959 +Subproject commit b86941d8a159466c8d4c953ad4a0f4f5130aacca diff --git a/programs/smith b/programs/smith index a36e2fd..9e39ff1 160000 --- a/programs/smith +++ b/programs/smith @@ -1 +1 @@ -Subproject commit a36e2fd252b99d24b13beb0ddadca87adc926452 +Subproject commit 9e39ff178cf9abb5b09812b377082f3a5bb847b7 diff --git a/rust b/rust index e326e86..b16c7a2 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit e326e86b47edcded3313944a81f126a633032d86 +Subproject commit b16c7a235fa0f57fed6b7ec13ffd3cff1bcdd9ad From aba92d0528dabeeabcb8fdf640ac6c8403cd8494 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 3 May 2017 22:09:58 -0600 Subject: [PATCH 330/522] Update dependencies and submodules --- .gitmodules | 3 ++ Cargo.lock | 81 ++++++++++++++-------------------------- Cargo.toml | 1 + libs/event | 2 +- mk/userspace/mod.mk | 10 ++++- mk/userspace/orbutils.mk | 2 +- programs/ion | 2 +- programs/orbterm | 1 + programs/orbutils | 2 +- programs/sodium | 2 +- 10 files changed, 47 insertions(+), 59 deletions(-) create mode 160000 programs/orbterm diff --git a/.gitmodules b/.gitmodules index 3ef03da..f138b20 100644 --- a/.gitmodules +++ b/.gitmodules @@ -115,3 +115,6 @@ [submodule "libs/tar"] path = libs/tar url = https://github.com/redox-os/tar-rs.git +[submodule "programs/orbterm"] + path = programs/orbterm + url = https://github.com/redox-os/orbterm.git diff --git a/Cargo.lock b/Cargo.lock index 8f41eed..98ae90e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -104,11 +104,6 @@ dependencies = [ "extra 0.1.0 (git+https://github.com/redox-os/libextra.git)", ] -[[package]] -name = "bitflags" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "bitflags" version = "0.4.0" @@ -554,7 +549,7 @@ dependencies = [ [[package]] name = "ion-shell" -version = "1.0.0" +version = "1.0.1" dependencies = [ "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -562,7 +557,7 @@ dependencies = [ "liner 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "peg 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "permutate 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallstring 0.1.0", + "smallstring 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "users 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -989,15 +984,6 @@ name = "odds" version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "orbclient" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "sdl2 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "orbclient" version = "0.3.4" @@ -1056,6 +1042,18 @@ dependencies = [ "toml 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "orbterm" +version = "0.1.0" +dependencies = [ + "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "orbfont 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "ransid 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_event 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "orbtk" version = "0.2.19" @@ -1086,7 +1084,6 @@ dependencies = [ "orbfont 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "orbimage 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "orbtk 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", - "ransid 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1312,18 +1309,24 @@ dependencies = [ [[package]] name = "redox_event" version = "0.1.0" -source = "git+https://github.com/redox-os/event.git#285c93417cca031aea34a81d79d32c5b13f0af6c" +source = "git+https://github.com/redox-os/event.git#1333e640e1c58cf3808372147f34e91ff0d7f13c" dependencies = [ - "redox_syscall 0.1.17 (git+https://github.com/redox-os/syscall.git)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "redox_event" version = "0.1.0" dependencies = [ - "redox_syscall 0.1.17 (git+https://github.com/redox-os/syscall.git)", + "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "redox_event" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +replace = "redox_event 0.1.0" + [[package]] name = "redox_installer" version = "0.1.0" @@ -1338,11 +1341,6 @@ dependencies = [ "userutils 0.1.0 (git+https://github.com/redox-os/userutils.git)", ] -[[package]] -name = "redox_syscall" -version = "0.1.17" -source = "git+https://github.com/redox-os/syscall.git#863080967dfee40e0a0c74936e43e79161e0aa6e" - [[package]] name = "redox_syscall" version = "0.1.17" @@ -1493,18 +1491,6 @@ name = "scroll" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "sdl2" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "sdl2-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "sdl2" version = "0.29.1" @@ -1518,15 +1504,6 @@ dependencies = [ "sdl2-sys 0.27.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "sdl2-sys" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "sdl2-sys" version = "0.27.3" @@ -1647,7 +1624,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "smallstring" -version = "0.1.0" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1670,7 +1648,7 @@ dependencies = [ name = "sodium" version = "0.1.0" dependencies = [ - "orbclient 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2175,7 +2153,6 @@ dependencies = [ "checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392" "checksum arrayvec 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "699e63a93b79d717e8c3b5eb1b28b7780d0d6d9e59a72eb769291c83b0c8dc67" "checksum base64 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2015e3793554aa5b6007e3a72959e84c1070039e74f13dde08fa64afe1ddd892" -"checksum bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "32866f4d103c4e438b1db1158aa1b1a80ee078e5d77a59a2f906fd62a577389c" "checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum blake2-rfc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "0c6a476f32fef3402f1161f89d0d39822809627754a126f8441ff2a9d45e2d59" @@ -2265,7 +2242,6 @@ dependencies = [ "checksum octavo 0.1.1 (git+https://github.com/libOctavo/octavo.git)" = "" "checksum octavo-digest 0.1.2 (git+https://github.com/libOctavo/octavo.git)" = "" "checksum odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "c3df9b730298cea3a1c3faa90b7e2f9df3a9c400d0936d6015e6165734eefcba" -"checksum orbclient 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "6e8e982388f410b93ce531c13aa6bf1203d9e806e8034d8cb91d65a570a413a5" "checksum orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "06be24afab121c4167c8e9c9781e49b7c232f774815816b67c7c6aa7fc503cf1" "checksum orbfont 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9a781ee4a8df3d8206832ef8b8ccbb3f964aa0ec9e2794fdb8806d47bb0b89af" "checksum orbimage 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c3b031607ef7a3c562949dfb595b1ea2b2d697b14544af407242a52dce811a6f" @@ -2289,7 +2265,7 @@ dependencies = [ "checksum rayon 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8c83adcb08e5b922e804fe1918142b422602ef11f2fd670b0b52218cb5984a20" "checksum rayon-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "767d91bacddf07d442fe39257bf04fd95897d1c47c545d009f6beb03efd038f8" "checksum redox_event 0.1.0 (git+https://github.com/redox-os/event.git)" = "" -"checksum redox_syscall 0.1.17 (git+https://github.com/redox-os/syscall.git)" = "" +"checksum redox_event 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98e1a40d38f45a3ad65fd088640eeee7b215adcd73041b9f94b92204cca9572a" "checksum redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "29dbdfd4b9df8ab31dec47c6087b7b13cbf4a776f335e4de8efba8288dda075b" "checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" "checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01" @@ -2306,9 +2282,7 @@ dependencies = [ "checksum scoped_threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3ef399c8893e8cb7aa9696e895427fab3a6bf265977bb96e126f24ddd2cda85a" "checksum scroll 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "39c82d0508f6a56bdb409031382d62e9fa7f5e198fa04dfc06a7a96f1dfc101d" "checksum sdl2 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c366cfa1f22d001774214ce2fb13f369af760b016bc79cc62d7f5ae15c00fea" -"checksum sdl2 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9cf70f3d302b61311856bcbd9c9d000aadc7c595574214335cf09035fdced2c9" "checksum sdl2-sys 0.27.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8d9f87e3d948f94f2d8688970422f49249c20e97f8f3aad76cb8729901d4eb10" -"checksum sdl2-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "657e3a3a175fda33c05d943923a768c7bf94c3b5fad05dcb31fc0321b11f47bd" "checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" "checksum serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97b18e9e53de541f11e497357d6c5eaeb39f0cb9c8734e274abe4935f6991fa" "checksum serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" @@ -2324,6 +2298,7 @@ dependencies = [ "checksum serde_json 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5aaee47e038bf9552d30380d3973fff2593ee0a76d81ad4c581f267cdcadf36" "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" +"checksum smallstring 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9c6e750a9d4e05a288f03409aa6feca513a16256a34ec6a366fdff7dadf74a24" "checksum smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4f8266519bc1d17d0b5b16f6c21295625d562841c708f6376f49028a43e9c11e" "checksum spin 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1d16a26e2b789f86aabddbe91cb82ee2e822beb8a59840d631941b625ef77e53" "checksum static-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6da6a96247d4b372d3ed90dec2c129ab57c934359ac4c6adbaa5871cd0737437" diff --git a/Cargo.toml b/Cargo.toml index d0897f9..ddef38b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,6 +38,7 @@ members = [ "programs/init", "programs/ion", "programs/netutils", + "programs/orbterm", "programs/orbutils", "programs/pkgutils", "programs/smith", diff --git a/libs/event b/libs/event index 285c934..1333e64 160000 --- a/libs/event +++ b/libs/event @@ -1 +1 @@ -Subproject commit 285c93417cca031aea34a81d79d32c5b13f0af6c +Subproject commit 1333e640e1c58cf3808372147f34e91ff0d7f13c diff --git a/mk/userspace/mod.mk b/mk/userspace/mod.mk index 903efe4..4edff9d 100644 --- a/mk/userspace/mod.mk +++ b/mk/userspace/mod.mk @@ -12,7 +12,9 @@ userspace: \ filesystem/bin/acid \ filesystem/bin/contain \ filesystem/bin/smith \ - filesystem/bin/timeout + filesystem/bin/timeout \ + filesystem/ui/bin/orbterm \ + filesystem/ui/bin/sodium include mk/userspace/coreutils.mk include mk/userspace/drivers.mk @@ -39,3 +41,9 @@ filesystem/bin/%: programs/%/Cargo.toml programs/%/src/** $(BUILD)/libstd.rlib mkdir -p filesystem/bin $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ $(STRIP) $@ + +filesystem/ui/bin/%: programs/%/Cargo.toml programs/%/src/**.rs $(BUILD)/libstd.rlib + mkdir -p filesystem/ui/bin + $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ + $(STRIP) $@ + diff --git a/mk/userspace/orbutils.mk b/mk/userspace/orbutils.mk index df60cf4..def6d73 100644 --- a/mk/userspace/orbutils.mk +++ b/mk/userspace/orbutils.mk @@ -6,7 +6,7 @@ orbutils: \ filesystem/ui/bin/file_manager \ filesystem/ui/bin/launcher \ filesystem/ui/bin/orblogin \ - filesystem/ui/bin/terminal \ + filesystem/ui/bin/orbterm \ filesystem/ui/bin/viewer filesystem/ui/bin/%: programs/orbutils/Cargo.toml programs/orbutils/src/%/**.rs $(BUILD)/libstd.rlib diff --git a/programs/ion b/programs/ion index b86941d..1d47bae 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit b86941d8a159466c8d4c953ad4a0f4f5130aacca +Subproject commit 1d47baee4587537d31d59a34d5e887f640f1ff9e diff --git a/programs/orbterm b/programs/orbterm new file mode 160000 index 0000000..2c5b1cf --- /dev/null +++ b/programs/orbterm @@ -0,0 +1 @@ +Subproject commit 2c5b1cfa4a1c1ce1f46a75b3143c7bc530da3f96 diff --git a/programs/orbutils b/programs/orbutils index 1991d0b..99c5e04 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 1991d0bbe3f4e5060b9e6878f449619f45d9f595 +Subproject commit 99c5e04e24084244b5d02b29ee95041b4d02bbf6 diff --git a/programs/sodium b/programs/sodium index 0334b3d..86fc766 160000 --- a/programs/sodium +++ b/programs/sodium @@ -1 +1 @@ -Subproject commit 0334b3d178b605e9bb46f98f1f2bea64c121cd2f +Subproject commit 86fc766160cf2a0996f1ca6de6e301c35807f7fb From 8a85aae7bd5fe1795a4be6d92e11e62aa5e3ff6c Mon Sep 17 00:00:00 2001 From: equal-l2 Date: Sat, 6 May 2017 06:34:07 +0900 Subject: [PATCH 331/522] Remove unnecessary taps --- bootstrap.sh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/bootstrap.sh b/bootstrap.sh index a72ccfd..346d2b2 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -110,10 +110,6 @@ osx_homebrew() echo "Homebrew detected! Now updating..." brew update - echo "Tapping required taps..." - brew tap homebrew/versions - brew tap glendc/gcc_cross_compilers - echo "Installing missing packages..." install_brew_pkg "git" From 28712d734a8a6663945a53986996caff9effffc0 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 7 May 2017 08:47:46 -0600 Subject: [PATCH 332/522] Update orbfont, ion, and orbterm --- Cargo.lock | 46 +++++++++++++++++++++++----------------------- Cargo.toml | 2 +- libs/orbfont | 2 +- programs/ion | 2 +- programs/orbterm | 2 +- 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 98ae90e..4ad31c6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -220,7 +220,7 @@ dependencies = [ [[package]] name = "deflate" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "adler32 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -463,7 +463,7 @@ dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tendril 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tendril 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -557,7 +557,7 @@ dependencies = [ "liner 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "peg 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "permutate 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallstring 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallstring 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "users 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -765,7 +765,7 @@ dependencies = [ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -779,14 +779,14 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "net2" -version = "0.2.27" +version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1000,7 +1000,7 @@ replace = "orbclient 0.3.4" [[package]] name = "orbfont" -version = "0.1.7" +version = "0.1.8" dependencies = [ "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "rusttype 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1008,9 +1008,9 @@ dependencies = [ [[package]] name = "orbfont" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -replace = "orbfont 0.1.7" +replace = "orbfont 0.1.8" [[package]] name = "orbimage" @@ -1032,7 +1032,7 @@ name = "orbital" version = "0.1.0" dependencies = [ "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "orbfont 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "orbfont 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "orbimage 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1044,11 +1044,11 @@ dependencies = [ [[package]] name = "orbterm" -version = "0.1.0" +version = "0.1.1" dependencies = [ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "orbfont 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "orbfont 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "ransid 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "redox_event 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1059,7 +1059,7 @@ name = "orbtk" version = "0.2.19" dependencies = [ "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "orbfont 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "orbfont 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "orbimage 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1081,13 +1081,13 @@ dependencies = [ "mime 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "orbfont 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "orbfont 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "orbimage 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "orbtk 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tendril 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tendril 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "userutils 0.1.0 (git+https://github.com/redox-os/userutils.git)", ] @@ -1216,7 +1216,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "deflate 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", + "deflate 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)", "inflate 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1624,7 +1624,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "smallstring" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1770,7 +1770,7 @@ dependencies = [ [[package]] name = "tendril" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2168,7 +2168,7 @@ dependencies = [ "checksum constant_time_eq 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "07dcb7959f0f6f1cf662f9a7ff389bcb919924d99ac41cf31f10d611d8721323" "checksum csv 0.14.7 (registry+https://github.com/rust-lang/crates.io-index)" = "266c1815d7ca63a5bd86284043faf91e8c95e943e55ce05dc0ae08e952de18bc" "checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3" -"checksum deflate 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "464225978f3f01068194aa948852ec121d179c3f874d499d74c432953bf1917b" +"checksum deflate 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8f39474a23b492b7ec97604c7828abd05771b28ed03cac0c6b884e79f9980283" "checksum deque 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a694dae478589798d752c7125542f8a5ae8b6e59476172baf2eed67357bdfa27" "checksum docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab32ea6e284d87987066f21a9e809a73c14720571ef34516f0890b3d355ccfd8" "checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" @@ -2223,7 +2223,7 @@ dependencies = [ "checksum mime_guess 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76da6df85047af8c0edfa53f48eb1073012ce1cc95c8fedc0a374f659a89dd65" "checksum miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "28eaee17666671fa872e567547e8428e83308ebe5808cdf6a0e28397dbe2c726" "checksum miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3e690c5df6b2f60acd45d56378981e827ff8295562fc8d34f573deb267a59cd1" -"checksum net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)" = "18b9642ad6222faf5ce46f6966f59b71b9775ad5758c9e09fcf0a6c8061972b4" +"checksum net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "bc01404e7568680f1259aa5729539f221cb1e6d047a0d9053cab4be8a73b5d67" "checksum netutils 0.1.0 (git+https://github.com/redox-os/netutils.git)" = "" "checksum nix 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0d95c5fa8b641c10ad0b8887454ebaafa3c92b5cd5350f8fc693adafd178e7b" "checksum nodrop 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "52cd74cd09beba596430cc6e3091b74007169a56246e1262f0ba451ea95117b2" @@ -2243,7 +2243,7 @@ dependencies = [ "checksum octavo-digest 0.1.2 (git+https://github.com/libOctavo/octavo.git)" = "" "checksum odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "c3df9b730298cea3a1c3faa90b7e2f9df3a9c400d0936d6015e6165734eefcba" "checksum orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "06be24afab121c4167c8e9c9781e49b7c232f774815816b67c7c6aa7fc503cf1" -"checksum orbfont 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9a781ee4a8df3d8206832ef8b8ccbb3f964aa0ec9e2794fdb8806d47bb0b89af" +"checksum orbfont 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "da4dfbc851e5c24c3cf1e16ec5222f868f3362d2b7493d0b53051fe2669267a2" "checksum orbimage 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c3b031607ef7a3c562949dfb595b1ea2b2d697b14544af407242a52dce811a6f" "checksum orbtk 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "2bca50ac6874107a922dd26dc79889b963afce69075940463ce026b5281bf9f1" "checksum pager 0.1.0 (git+https://github.com/redox-os/libpager.git)" = "" @@ -2298,7 +2298,7 @@ dependencies = [ "checksum serde_json 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5aaee47e038bf9552d30380d3973fff2593ee0a76d81ad4c581f267cdcadf36" "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" -"checksum smallstring 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9c6e750a9d4e05a288f03409aa6feca513a16256a34ec6a366fdff7dadf74a24" +"checksum smallstring 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30950abdb5b38f56a0e181ae56ed64a539b64fa77ea6325147203dc7faeb087f" "checksum smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4f8266519bc1d17d0b5b16f6c21295625d562841c708f6376f49028a43e9c11e" "checksum spin 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1d16a26e2b789f86aabddbe91cb82ee2e822beb8a59840d631941b625ef77e53" "checksum static-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6da6a96247d4b372d3ed90dec2c129ab57c934359ac4c6adbaa5871cd0737437" @@ -2312,7 +2312,7 @@ dependencies = [ "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum tar 0.4.11 (git+https://github.com/redox-os/tar-rs.git)" = "" "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" -"checksum tendril 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cebf864c2d90394a1b66d6fe45963f9a177f2af81a0edea5060f77627f9c4587" +"checksum tendril 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4ce04c250d202db8004921e3d3bc95eaa4f2126c6937a428ae39d12d0e38df62" "checksum termion 1.3.0 (git+https://github.com/redox-os/termion.git)" = "" "checksum termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b41865823fb8c7873ff869893219b3188e7fcd66c10effb97f2b2f63ea98681" "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" diff --git a/Cargo.toml b/Cargo.toml index ddef38b..2031eff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,7 +60,7 @@ members = [ "jpeg-decoder:0.1.12" = { path = "libs/jpeg-decoder" } "mio:0.6.2" = { path = "libs/mio" } "orbclient:0.3.4" = { path = "libs/orbclient" } -"orbfont:0.1.7" = { path = "libs/orbfont" } +"orbfont:0.1.8" = { path = "libs/orbfont" } "orbimage:0.1.15" = { path = "libs/orbimage" } "orbtk:0.2.19" = { path = "libs/orbtk" } "pager:0.1.0" = { path = "libs/pager" } diff --git a/libs/orbfont b/libs/orbfont index 8a8d19d..f554cec 160000 --- a/libs/orbfont +++ b/libs/orbfont @@ -1 +1 @@ -Subproject commit 8a8d19dcddbd78b3d3b12f7a7264c97c506b0a01 +Subproject commit f554cec35c9614939590ec5d799d01a593d3c446 diff --git a/programs/ion b/programs/ion index 1d47bae..ae73d27 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit 1d47baee4587537d31d59a34d5e887f640f1ff9e +Subproject commit ae73d27b07db96c6e6520c559ba03c117e048b43 diff --git a/programs/orbterm b/programs/orbterm index 2c5b1cf..3b1834c 160000 --- a/programs/orbterm +++ b/programs/orbterm @@ -1 +1 @@ -Subproject commit 2c5b1cfa4a1c1ce1f46a75b3143c7bc530da3f96 +Subproject commit 3b1834c79d8d65adceefc302cf02d6060a056027 From 184e790732f059590699737cc6ce4cdee76e12f1 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 7 May 2017 08:55:21 -0600 Subject: [PATCH 333/522] Update UI folder --- filesystem/ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/filesystem/ui b/filesystem/ui index 83e567b..d6a5749 160000 --- a/filesystem/ui +++ b/filesystem/ui @@ -1 +1 @@ -Subproject commit 83e567bb6bcd04cfc8d80ae99665b038c546ecb5 +Subproject commit d6a5749d61df72e8a339335be5429d843fa401b1 From f62fc652743ffd2b10c41b631146d7243d59da86 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 7 May 2017 15:25:18 -0600 Subject: [PATCH 334/522] Update orbterm --- programs/orbterm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/orbterm b/programs/orbterm index 3b1834c..4143dcf 160000 --- a/programs/orbterm +++ b/programs/orbterm @@ -1 +1 @@ -Subproject commit 3b1834c79d8d65adceefc302cf02d6060a056027 +Subproject commit 4143dcf160648a048d579553ab29ba18fb47c23c From 61788c5a27bae30f8e7c272e7555a2ffbb300294 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 7 May 2017 17:18:22 -0600 Subject: [PATCH 335/522] Upgrade pkgutils --- programs/pkgutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/pkgutils b/programs/pkgutils index 26ec0bd..b9c10c9 160000 --- a/programs/pkgutils +++ b/programs/pkgutils @@ -1 +1 @@ -Subproject commit 26ec0bd59734fcbf2c24c90d03a73bae244f45a6 +Subproject commit b9c10c980e1724270b7e90d3c2d4999c398814b8 From 991d698ed3a31127f3b08db87edbf0d382d737a5 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 7 May 2017 17:18:42 -0600 Subject: [PATCH 336/522] Upgrade dependencies --- Cargo.lock | 30 +++++++++++++++++++----------- flash.sh | 23 +++++++++++++++++++++++ 2 files changed, 42 insertions(+), 11 deletions(-) create mode 100755 flash.sh diff --git a/Cargo.lock b/Cargo.lock index 4ad31c6..2350312 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -411,7 +411,7 @@ version = "0.1.0" dependencies = [ "extra 0.1.0 (git+https://github.com/redox-os/libextra.git)", "libgo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "liner 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "liner 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -554,7 +554,7 @@ dependencies = [ "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "liner 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "liner 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "peg 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "permutate 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallstring 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -655,7 +655,7 @@ dependencies = [ [[package]] name = "liner" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1044,7 +1044,7 @@ dependencies = [ [[package]] name = "orbterm" -version = "0.1.1" +version = "0.1.2" dependencies = [ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1173,16 +1173,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "pkgutils" version = "0.1.0" -source = "git+https://github.com/redox-os/pkgutils.git#26ec0bd59734fcbf2c24c90d03a73bae244f45a6" +source = "git+https://github.com/redox-os/pkgutils.git#b9c10c980e1724270b7e90d3c2d4999c398814b8" dependencies = [ "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-rustls 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "liner 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "octavo 0.1.1 (git+https://github.com/libOctavo/octavo.git)", "serde 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.11 (git+https://github.com/redox-os/tar-rs.git)", - "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "version-compare 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1191,12 +1192,13 @@ version = "0.1.0" dependencies = [ "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-rustls 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "liner 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "octavo 0.1.1 (git+https://github.com/libOctavo/octavo.git)", "serde 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.11 (git+https://github.com/redox-os/tar-rs.git)", - "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "version-compare 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1331,7 +1333,7 @@ replace = "redox_event 0.1.0" name = "redox_installer" version = "0.1.0" dependencies = [ - "liner 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "liner 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "pkgutils 0.1.0 (git+https://github.com/redox-os/pkgutils.git)", "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1989,7 +1991,7 @@ version = "0.1.0" source = "git+https://github.com/redox-os/userutils.git#3ca18917f88130f4734bcb4643a410e62e6cb24c" dependencies = [ "argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "liner 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "liner 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2000,7 +2002,7 @@ name = "userutils" version = "0.1.0" dependencies = [ "argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "liner 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "liner 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2033,6 +2035,11 @@ dependencies = [ "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "version-compare" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "version_check" version = "0.1.0" @@ -2208,7 +2215,7 @@ dependencies = [ "checksum libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)" = "babb8281da88cba992fa1f4ddec7d63ed96280a1a53ec9b919fd37b53d71e502" "checksum libflate 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7aa60ce680c15f96b74bd6208256f112049ab20fd6da510f27f82cb78323a77" "checksum libgo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "99a64661b7d5c8b2ccb779e3fb0ced098426bb9bfbded934aa76ef227300e0cf" -"checksum liner 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5621a282d4baa2e8c0b815974bf3e2819eb860bfb7bf1d2f99049f10084a7102" +"checksum liner 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f9e406164c25b420480023985bdf65cef366855666ad4cb12cd3eaee82dcb399" "checksum linked-hash-map 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "f26e961e0c884309cd527b1402a5409d35db612b36915d755e1a4f5c1547a31c" "checksum linked_list_allocator 0.2.5 (git+https://github.com/phil-opp/linked-list-allocator.git)" = "" "checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad" @@ -2342,6 +2349,7 @@ dependencies = [ "checksum utf-8 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9aee9ba280438b56d1ebc5329f2094f0ff457f811eeeff0b278d75aa99db400" "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" +"checksum version-compare 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cb766fdc689f3a5e38b2a0eb9dff9ac4a8961c09bb99064ecf88702a39b1992e" "checksum version_check 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f2edadb5308f31d97771a678c33df28f18d04f61de3fe21b9452f37854eb6c08" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum walkdir 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c66c0b9792f0a765345452775f3adbd28dde9d33f30d13e5dcc5ae17cf6f3780" diff --git a/flash.sh b/flash.sh new file mode 100755 index 0000000..5099457 --- /dev/null +++ b/flash.sh @@ -0,0 +1,23 @@ +#!/bin/bash +set -e + +ISO="build/livedisk.iso" +DISK="/dev/disk/by-id/usb-Generic_USB_SD_Reader_12345678901234567890-0:0" + +if [ ! -f "$ISO" ] +then + echo "Did not find ISO $ISO" + exit 1 +fi + +if [ ! -b "$DISK" ] +then + echo "Did not find disk $DISK" + exit 1 +fi + +echo "Flashing $ISO to $DISK" +pv "$ISO" | sudo dd of="$DISK" +sync +sudo eject "$DISK" +echo "Successfully flashed $DISK" From 9034701e8f5d91dc24a796192a8682c69ed42e9b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 8 May 2017 20:46:17 -0600 Subject: [PATCH 337/522] Ability to use cookbook from inside Redox repo --- .gitmodules | 3 +++ Cargo.toml | 1 + cookbook | 1 + 3 files changed, 5 insertions(+) create mode 160000 cookbook diff --git a/.gitmodules b/.gitmodules index f138b20..3eeeb4d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -118,3 +118,6 @@ [submodule "programs/orbterm"] path = programs/orbterm url = https://github.com/redox-os/orbterm.git +[submodule "cookbook"] + path = cookbook + url = https://github.com/redox-os/cookbook.git diff --git a/Cargo.toml b/Cargo.toml index 2031eff..5513d32 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,5 @@ [workspace] +exclude = ["cookbook"] members = [ "docgen", "drivers/ahcid", diff --git a/cookbook b/cookbook new file mode 160000 index 0000000..4a18e61 --- /dev/null +++ b/cookbook @@ -0,0 +1 @@ +Subproject commit 4a18e61514133017e31d67d31931b1bee621f0c2 From c9950beec225503f35cd3ffdd7ec1206ba662816 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 10 May 2017 21:39:05 -0600 Subject: [PATCH 338/522] Convert to cookbook based build --- .gitignore | 5 - .gitmodules | 129 +- Cargo.lock | 2365 ---------------------- Cargo.toml | 74 - Makefile | 12 +- bootloader | 2 +- cookbook | 2 +- docgen | 1 - drivers | 1 - filesystem.toml | 175 ++ filesystem/etc/group | 1 - filesystem/etc/hostname | 1 - filesystem/etc/init.d/00_base | 3 - filesystem/etc/init.d/10_net | 5 - filesystem/etc/init.d/20_orbital | 1 - filesystem/etc/init.d/30_console | 2 - filesystem/etc/installer.toml | 45 - filesystem/etc/issue | 6 - filesystem/etc/motd | 2 - filesystem/etc/net/dns | 1 - filesystem/etc/net/ip | 1 - filesystem/etc/net/ip_router | 1 - filesystem/etc/net/ip_subnet | 1 - filesystem/etc/net/mac | 1 - filesystem/etc/passwd | 2 - filesystem/etc/pcid.toml | 41 - filesystem/etc/pkg.d/50_redox | 1 - filesystem/home/user/LICENSE | 1 - filesystem/home/user/README.md | 1 - filesystem/root/LICENSE | 1 - filesystem/root/README.md | 1 - filesystem/ui | 1 - initfs/etc/pcid.toml => initfs.toml | 32 + initfs/etc/init.rc | 9 - installer | 2 +- kernel | 2 +- krustc.sh | 21 - krustdoc.sh | 2 - libc-artifacts | 1 - libs/event | 1 - libs/extra | 1 - libs/jpeg-decoder | 1 - libs/mio | 1 - libs/orbclient | 1 - libs/orbfont | 1 - libs/orbimage | 1 - libs/orbtk | 1 - libs/pager | 1 - libs/ralloc | 1 - libs/ransid | 1 - libs/same-file | 1 - libs/syscall | 1 - libs/tar | 1 - libs/termion | 1 - mk/config.mk | 15 +- mk/disk.mk | 4 +- mk/doc.mk | 13 - mk/filesystem.mk | 14 +- mk/initfs.mk | 20 +- mk/kernel.mk | 21 +- mk/userspace/coreutils.mk | 46 - mk/userspace/drivers.mk | 15 - mk/userspace/extrautils.mk | 21 - mk/userspace/installer.mk | 7 - mk/userspace/ion.mk | 11 - mk/userspace/mod.mk | 49 - mk/userspace/netutils.mk | 14 - mk/userspace/orbutils.mk | 15 - mk/userspace/pkgutils.mk | 7 - mk/userspace/schemes.mk | 25 - mk/userspace/userutils.mk | 13 - paper/redox.tex | 84 - programs/acid | 1 - programs/binutils | 1 - programs/contain/Cargo.toml | 6 - programs/contain/src/chroot.rs | 172 -- programs/contain/src/main.rs | 97 - programs/coreutils | 1 - programs/extrautils | 1 - programs/games | 1 - programs/init | 1 - programs/ion | 1 - programs/netutils | 1 - programs/orbterm | 1 - programs/orbutils | 1 - programs/pkgutils | 1 - programs/smith | 1 - programs/sodium | 1 - programs/timeout/Cargo.toml | 8 - programs/timeout/src/main.rs | 44 - programs/userutils | 1 - res/fonts/DejaVuSansMono-Bold.ttf | Bin 331992 -> 0 bytes res/fonts/DejaVuSansMono-BoldOblique.ttf | Bin 253580 -> 0 bytes res/fonts/DejaVuSansMono-LICENSE | 187 -- res/fonts/DejaVuSansMono-Oblique.ttf | Bin 251932 -> 0 bytes res/fonts/DejaVuSansMono.ttf | Bin 340712 -> 0 bytes rustc.sh | 21 - rustdoc.sh | 2 - rustfmt.toml | 5 - schemes/ethernetd/Cargo.toml | 8 - schemes/ethernetd/src/main.rs | 110 - schemes/ethernetd/src/scheme.rs | 164 -- schemes/ipd/Cargo.toml | 8 - schemes/ipd/src/interface/ethernet.rs | 155 -- schemes/ipd/src/interface/loopback.rs | 50 - schemes/ipd/src/interface/mod.rs | 19 - schemes/ipd/src/main.rs | 341 ---- schemes/orbital | 1 - schemes/ptyd/Cargo.toml | 6 - schemes/ptyd/src/main.rs | 414 ---- schemes/randd/Cargo.toml | 7 - schemes/randd/src/main.rs | 92 - schemes/redoxfs | 1 - schemes/tcpd/Cargo.toml | 9 - schemes/tcpd/src/main.rs | 937 --------- schemes/udpd/Cargo.toml | 9 - schemes/udpd/src/main.rs | 586 ------ 117 files changed, 246 insertions(+), 6591 deletions(-) delete mode 100644 Cargo.lock delete mode 100644 Cargo.toml delete mode 160000 docgen delete mode 160000 drivers create mode 100644 filesystem.toml delete mode 100644 filesystem/etc/group delete mode 100644 filesystem/etc/hostname delete mode 100644 filesystem/etc/init.d/00_base delete mode 100644 filesystem/etc/init.d/10_net delete mode 100644 filesystem/etc/init.d/20_orbital delete mode 100644 filesystem/etc/init.d/30_console delete mode 100644 filesystem/etc/installer.toml delete mode 100644 filesystem/etc/issue delete mode 100644 filesystem/etc/motd delete mode 100644 filesystem/etc/net/dns delete mode 100644 filesystem/etc/net/ip delete mode 100644 filesystem/etc/net/ip_router delete mode 100644 filesystem/etc/net/ip_subnet delete mode 100644 filesystem/etc/net/mac delete mode 100644 filesystem/etc/passwd delete mode 100644 filesystem/etc/pcid.toml delete mode 100644 filesystem/etc/pkg.d/50_redox delete mode 120000 filesystem/home/user/LICENSE delete mode 120000 filesystem/home/user/README.md delete mode 120000 filesystem/root/LICENSE delete mode 120000 filesystem/root/README.md delete mode 160000 filesystem/ui rename initfs/etc/pcid.toml => initfs.toml (56%) delete mode 100644 initfs/etc/init.rc delete mode 100755 krustc.sh delete mode 100755 krustdoc.sh delete mode 160000 libc-artifacts delete mode 160000 libs/event delete mode 160000 libs/extra delete mode 160000 libs/jpeg-decoder delete mode 160000 libs/mio delete mode 160000 libs/orbclient delete mode 160000 libs/orbfont delete mode 160000 libs/orbimage delete mode 160000 libs/orbtk delete mode 160000 libs/pager delete mode 160000 libs/ralloc delete mode 160000 libs/ransid delete mode 160000 libs/same-file delete mode 160000 libs/syscall delete mode 160000 libs/tar delete mode 160000 libs/termion delete mode 100644 mk/doc.mk delete mode 100644 mk/userspace/coreutils.mk delete mode 100644 mk/userspace/drivers.mk delete mode 100644 mk/userspace/extrautils.mk delete mode 100644 mk/userspace/installer.mk delete mode 100644 mk/userspace/ion.mk delete mode 100644 mk/userspace/mod.mk delete mode 100644 mk/userspace/netutils.mk delete mode 100644 mk/userspace/orbutils.mk delete mode 100644 mk/userspace/pkgutils.mk delete mode 100644 mk/userspace/schemes.mk delete mode 100644 mk/userspace/userutils.mk delete mode 100644 paper/redox.tex delete mode 160000 programs/acid delete mode 160000 programs/binutils delete mode 100644 programs/contain/Cargo.toml delete mode 100644 programs/contain/src/chroot.rs delete mode 100644 programs/contain/src/main.rs delete mode 160000 programs/coreutils delete mode 160000 programs/extrautils delete mode 160000 programs/games delete mode 160000 programs/init delete mode 160000 programs/ion delete mode 160000 programs/netutils delete mode 160000 programs/orbterm delete mode 160000 programs/orbutils delete mode 160000 programs/pkgutils delete mode 160000 programs/smith delete mode 160000 programs/sodium delete mode 100644 programs/timeout/Cargo.toml delete mode 100644 programs/timeout/src/main.rs delete mode 160000 programs/userutils delete mode 100644 res/fonts/DejaVuSansMono-Bold.ttf delete mode 100644 res/fonts/DejaVuSansMono-BoldOblique.ttf delete mode 100644 res/fonts/DejaVuSansMono-LICENSE delete mode 100644 res/fonts/DejaVuSansMono-Oblique.ttf delete mode 100644 res/fonts/DejaVuSansMono.ttf delete mode 100755 rustc.sh delete mode 100755 rustdoc.sh delete mode 100644 rustfmt.toml delete mode 100644 schemes/ethernetd/Cargo.toml delete mode 100644 schemes/ethernetd/src/main.rs delete mode 100644 schemes/ethernetd/src/scheme.rs delete mode 100644 schemes/ipd/Cargo.toml delete mode 100644 schemes/ipd/src/interface/ethernet.rs delete mode 100644 schemes/ipd/src/interface/loopback.rs delete mode 100644 schemes/ipd/src/interface/mod.rs delete mode 100644 schemes/ipd/src/main.rs delete mode 160000 schemes/orbital delete mode 100644 schemes/ptyd/Cargo.toml delete mode 100644 schemes/ptyd/src/main.rs delete mode 100644 schemes/randd/Cargo.toml delete mode 100644 schemes/randd/src/main.rs delete mode 160000 schemes/redoxfs delete mode 100644 schemes/tcpd/Cargo.toml delete mode 100644 schemes/tcpd/src/main.rs delete mode 100644 schemes/udpd/Cargo.toml delete mode 100644 schemes/udpd/src/main.rs diff --git a/.gitignore b/.gitignore index a3e3243..378eac2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1 @@ build -target -initfs/bin -filesystem/bin -filesystem/ref -filesystem/sbin diff --git a/.gitmodules b/.gitmodules index 3eeeb4d..16b9f4f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,123 +1,18 @@ -[submodule "rust"] - path = rust - url = https://github.com/redox-os/rust.git -[submodule "ion"] - path = programs/ion - url = https://github.com/redox-os/ion.git -[submodule "programs/coreutils"] - path = programs/coreutils - url = https://github.com/redox-os/coreutils.git -[submodule "schemes/redoxfs"] - path = schemes/redoxfs - url = https://github.com/redox-os/redoxfs -[submodule "programs/extrautils"] - path = programs/extrautils - url = https://github.com/redox-os/extrautils.git -[submodule "programs/smith"] - path = programs/smith - url = https://github.com/IGI-111/Smith.git -[submodule "programs/userutils"] - path = programs/userutils - url = https://github.com/redox-os/userutils.git -[submodule "programs/netutils"] - path = programs/netutils - url = https://github.com/redox-os/netutils.git -[submodule "schemes/orbital"] - path = schemes/orbital - url = https://github.com/redox-os/orbital.git -[submodule "programs/orbutils"] - path = programs/orbutils - url = https://github.com/redox-os/orbutils.git -[submodule "filesystem/ui"] - path = filesystem/ui - url = https://github.com/redox-os/orbdata.git -[submodule "programs/acid"] - path = programs/acid - url = https://github.com/redox-os/acid.git -[submodule "programs/pkgutils"] - path = programs/pkgutils - url = https://github.com/redox-os/pkgutils.git -[submodule "installer"] - path = installer - url = https://github.com/redox-os/installer.git -[submodule "docgen"] - path = docgen - url = https://github.com/redox-os/docgen.git -[submodule "libc-artifacts"] - path = libc-artifacts - url = https://github.com/redox-os/libc-artifacts.git -[submodule "kernel"] - path = kernel - url = https://github.com/redox-os/kernel.git -[submodule "drivers"] - path = drivers - url = https://github.com/redox-os/drivers.git [submodule "bootloader"] path = bootloader url = https://github.com/redox-os/bootloader.git -[submodule "isolinux"] - path = isolinux - url = https://github.com/redox-os/isolinux.git -[submodule "programs/init"] - path = programs/init - url = https://github.com/redox-os/init.git -[submodule "libs/orbclient"] - path = libs/orbclient - url = https://github.com/redox-os/orbclient.git -[submodule "libs/orbtk"] - path = libs/orbtk - url = https://github.com/redox-os/orbtk.git -[submodule "libs/orbimage"] - path = libs/orbimage - url = https://github.com/redox-os/orbimage.git -[submodule "libs/orbfont"] - path = libs/orbfont - url = https://github.com/redox-os/orbfont.git -[submodule "libs/jpeg-decoder"] - path = libs/jpeg-decoder - url = https://github.com/redox-os/jpeg-decoder.git -[submodule "libs/termion"] - path = libs/termion - url = https://github.com/redox-os/termion.git -[submodule "libs/syscall"] - path = libs/syscall - url = https://github.com/redox-os/syscall.git -[submodule "libs/extra"] - path = libs/extra - url = https://github.com/redox-os/libextra.git -[submodule "libs/event"] - path = libs/event - url = https://github.com/redox-os/event.git -[submodule "libs/pager"] - path = libs/pager - url = https://github.com/redox-os/libpager.git -[submodule "libs/ransid"] - path = libs/ransid - url = https://github.com/redox-os/ransid.git -[submodule "libs/same-file"] - path = libs/same-file - url = https://github.com/redox-os/same-file.git -[submodule "libs/mio"] - path = libs/mio - url = https://github.com/redox-os/mio.git -[submodule "programs/binutils"] - path = programs/binutils - url = https://github.com/redox-os/binutils.git -[submodule "programs/games"] - path = programs/games - url = https://github.com/redox-os/games.git -[submodule "programs/sodium"] - path = programs/sodium - url = https://github.com/redox-os/sodium.git -[submodule "libs/ralloc"] - path = libs/ralloc - url = https://github.com/redox-os/ralloc.git -[submodule "libs/tar"] - path = libs/tar - url = https://github.com/redox-os/tar-rs.git -[submodule "programs/orbterm"] - path = programs/orbterm - url = https://github.com/redox-os/orbterm.git [submodule "cookbook"] path = cookbook url = https://github.com/redox-os/cookbook.git +[submodule "installer"] + path = installer + url = https://github.com/redox-os/installer.git +[submodule "isolinux"] + path = isolinux + url = https://github.com/redox-os/isolinux.git +[submodule "kernel"] + path = kernel + url = https://github.com/redox-os/kernel.git +[submodule "rust"] + path = rust + url = https://github.com/redox-os/rust.git diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index 2350312..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,2365 +0,0 @@ -[root] -name = "xhcid" -version = "0.1.0" -dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "acid" -version = "0.1.0" -dependencies = [ - "x86 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "adler32" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "ahcid" -version = "0.1.0" -dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "aho-corasick" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "aho-corasick" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "alloc_kernel" -version = "0.1.0" -dependencies = [ - "linked_list_allocator 0.2.5 (git+https://github.com/phil-opp/linked-list-allocator.git)", - "spin 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "alxd" -version = "0.1.0" -dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "netutils 0.1.0 (git+https://github.com/redox-os/netutils.git)", - "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ansi_term" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "argon2rs" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "blake2-rfc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", - "scoped_threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "arrayvec" -version = "0.3.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "nodrop 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "base64" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bgad" -version = "0.1.0" -dependencies = [ - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "binutils" -version = "0.1.0" -dependencies = [ - "extra 0.1.0 (git+https://github.com/redox-os/libextra.git)", -] - -[[package]] -name = "bitflags" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bitflags" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "blake2-rfc" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "constant_time_eq 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "block" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "byteorder" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "byteorder" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "byteorder" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bytes" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "cfg-if" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "clipboard" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "clipboard-win 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "objc-foundation 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "objc_id 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "x11 2.13.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "clipboard-win" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "windows-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "color_quant" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "constant_time_eq" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "contain" -version = "0.1.0" -dependencies = [ - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "coreutils" -version = "0.1.0" -dependencies = [ - "extra 0.1.0 (git+https://github.com/redox-os/libextra.git)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "csv" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "debug_unreachable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "deflate" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "adler32 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "deque" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "docgen" -version = "0.1.0" -dependencies = [ - "walkdir 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "docopt" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "e1000d" -version = "0.1.0" -dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "netutils 0.1.0 (git+https://github.com/redox-os/netutils.git)", - "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "encoding" -version = "0.2.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "encoding-index-japanese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "encoding-index-korean" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "encoding-index-simpchinese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "encoding-index-singlebyte" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "encoding-index-tradchinese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "encoding_index_tests" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "enum_primitive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "env_logger" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "error-chain" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "ethernetd" -version = "0.1.0" -dependencies = [ - "netutils 0.1.0 (git+https://github.com/redox-os/netutils.git)", - "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "extra" -version = "0.1.0" -source = "git+https://github.com/redox-os/libextra.git#402932084acd5fef4812945887ceaaa2ddd5f264" - -[[package]] -name = "extra" -version = "0.1.0" - -[[package]] -name = "extrautils" -version = "0.1.0" -dependencies = [ - "extra 0.1.0 (git+https://github.com/redox-os/libextra.git)", - "libflate 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "pager 0.1.0 (git+https://github.com/redox-os/libpager.git)", - "raw-cpuid 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tar 0.4.11 (git+https://github.com/redox-os/tar-rs.git)", - "termion 1.3.0 (git+https://github.com/redox-os/termion.git)", -] - -[[package]] -name = "flate2" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fnv" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "fuse" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "thread-scoped 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "futf" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "games-for-redox" -version = "0.1.0" -dependencies = [ - "extra 0.1.0 (git+https://github.com/redox-os/libextra.git)", - "libgo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "liner 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gcc" -version = "0.3.45" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "generic-array" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "typenum 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gif" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "color_quant 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "glob" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "goblin" -version = "0.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "scroll 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "html5ever" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "html5ever-atoms 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tendril 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "html5ever-atoms" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "string_cache 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache_codegen 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "httparse" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "hyper" -version = "0.10.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "httparse 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hyper-rustls" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki-roots 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "idna" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "image" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "gif 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "jpeg-decoder 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", - "num-rational 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "png 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "scoped_threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "inflate" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "init" -version = "0.1.0" -dependencies = [ - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ion-shell" -version = "1.0.1" -dependencies = [ - "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "liner 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "peg 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "permutate 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallstring 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "users 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ipd" -version = "0.1.0" -dependencies = [ - "netutils 0.1.0 (git+https://github.com/redox-os/netutils.git)", - "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "jpeg-decoder" -version = "0.1.12" -dependencies = [ - "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "png 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "jpeg-decoder" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -replace = "jpeg-decoder 0.1.12" - -[[package]] -name = "kernel" -version = "0.1.0" -dependencies = [ - "alloc_kernel 0.1.0", - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "goblin 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "raw-cpuid 3.0.0 (git+https://github.com/gz/rust-cpuid)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "x86 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "language-tags" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "lazy_static" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "lazycell" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "libc" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "libc" -version = "0.2.22" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "libflate" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libgo" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "liner" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "linked-hash-map" -version = "0.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "linked_list_allocator" -version = "0.2.5" -source = "git+https://github.com/phil-opp/linked-list-allocator.git#ea8548db4b5a6ee0e2b847e96d6b4c31b7744567" - -[[package]] -name = "log" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "lzw" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "mac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "malloc_buf" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "matches" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "memchr" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "memchr" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "metadeps" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "error-chain 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "mime" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "mime_guess" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "mime 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "miniz-sys" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "mio" -version = "0.6.2" -dependencies = [ - "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", - "nix 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "miow" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "net2" -version = "0.2.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "netutils" -version = "0.1.0" -source = "git+https://github.com/redox-os/netutils.git#074c900be31586f405cc46503a807e7ab8a7a2bb" -dependencies = [ - "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-rustls 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "ntpclient 0.0.1 (git+https://github.com/willem66745/ntpclient-rust)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "netutils" -version = "0.1.0" -dependencies = [ - "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-rustls 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "ntpclient 0.0.1 (git+https://github.com/willem66745/ntpclient-rust)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "nix" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "nodrop" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ntpclient" -version = "0.0.1" -source = "git+https://github.com/willem66745/ntpclient-rust#7e3bdf60eb940825789a8da5181025320e3050b0" -dependencies = [ - "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-bigint 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "num-complex 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", - "num-rational 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-bigint" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-complex" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-integer" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-iter" -version = "0.1.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-rational" -version = "0.1.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-bigint 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-traits" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "num_cpus" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "nvmed" -version = "0.1.0" -dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "objc" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "objc-foundation" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "objc_id 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "objc_id" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "octavo" -version = "0.1.1" -source = "git+https://github.com/libOctavo/octavo.git#d94d924616dca83b9c6cfc815062276c5908713a" -dependencies = [ - "octavo-digest 0.1.2 (git+https://github.com/libOctavo/octavo.git)", -] - -[[package]] -name = "octavo-digest" -version = "0.1.2" -source = "git+https://github.com/libOctavo/octavo.git#d94d924616dca83b9c6cfc815062276c5908713a" -dependencies = [ - "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "static-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "typenum 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "odds" -version = "0.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "orbclient" -version = "0.3.4" -dependencies = [ - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "sdl2 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "orbclient" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -replace = "orbclient 0.3.4" - -[[package]] -name = "orbfont" -version = "0.1.8" -dependencies = [ - "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rusttype 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "orbfont" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -replace = "orbfont 0.1.8" - -[[package]] -name = "orbimage" -version = "0.1.15" -dependencies = [ - "image 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)", - "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "resize 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "orbimage" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -replace = "orbimage 0.1.15" - -[[package]] -name = "orbital" -version = "0.1.0" -dependencies = [ - "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "orbfont 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "orbimage 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "resize 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "orbterm" -version = "0.1.2" -dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "orbfont 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ransid 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_event 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "orbtk" -version = "0.2.19" -dependencies = [ - "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "orbfont 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "orbimage 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "orbtk" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -replace = "orbtk 0.2.19" - -[[package]] -name = "orbutils" -version = "0.1.14" -dependencies = [ - "html5ever 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", - "html5ever-atoms 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-rustls 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "orbfont 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "orbimage 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "orbtk 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tendril 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "userutils 0.1.0 (git+https://github.com/redox-os/userutils.git)", -] - -[[package]] -name = "pager" -version = "0.1.0" -source = "git+https://github.com/redox-os/libpager.git#62b01eba8299143a1a5a78b36d85ab63251462b3" -dependencies = [ - "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "pager" -version = "0.1.0" -dependencies = [ - "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "pcid" -version = "0.1.0" -dependencies = [ - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "peg" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "permutate" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "phf" -version = "0.7.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "phf_codegen" -version = "0.7.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "phf_generator" -version = "0.7.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "phf_shared" -version = "0.7.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "pkg-config" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "pkgutils" -version = "0.1.0" -source = "git+https://github.com/redox-os/pkgutils.git#b9c10c980e1724270b7e90d3c2d4999c398814b8" -dependencies = [ - "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-rustls 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "liner 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "octavo 0.1.1 (git+https://github.com/libOctavo/octavo.git)", - "serde 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tar 0.4.11 (git+https://github.com/redox-os/tar-rs.git)", - "toml 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "version-compare 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "pkgutils" -version = "0.1.0" -dependencies = [ - "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-rustls 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "liner 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "octavo 0.1.1 (git+https://github.com/libOctavo/octavo.git)", - "serde 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tar 0.4.11 (git+https://github.com/redox-os/tar-rs.git)", - "toml 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "version-compare 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "png" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", - "inflate 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "png" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "deflate 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)", - "inflate 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ps2d" -version = "0.1.0" -dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ptyd" -version = "0.1.0" -dependencies = [ - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "quote" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rand" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "randd" -version = "0.1.0" -dependencies = [ - "raw-cpuid 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ransid" -version = "0.2.7" - -[[package]] -name = "ransid" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -replace = "ransid 0.2.7" - -[[package]] -name = "raw-cpuid" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "raw-cpuid" -version = "3.0.0" -source = "git+https://github.com/gz/rust-cpuid#d8ff30d61fb2ef4700c88cb787f47f4085863c90" -dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rayon" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rayon-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rayon-core" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "deque 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "redox_event" -version = "0.1.0" -source = "git+https://github.com/redox-os/event.git#1333e640e1c58cf3808372147f34e91ff0d7f13c" -dependencies = [ - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "redox_event" -version = "0.1.0" -dependencies = [ - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "redox_event" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -replace = "redox_event 0.1.0" - -[[package]] -name = "redox_installer" -version = "0.1.0" -dependencies = [ - "liner 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "pkgutils 0.1.0 (git+https://github.com/redox-os/pkgutils.git)", - "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "userutils 0.1.0 (git+https://github.com/redox-os/userutils.git)", -] - -[[package]] -name = "redox_syscall" -version = "0.1.17" - -[[package]] -name = "redox_syscall" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -replace = "redox_syscall 0.1.17" - -[[package]] -name = "redoxfs" -version = "0.1.2" -dependencies = [ - "fuse 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "regex" -version = "0.1.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "regex" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "regex-syntax" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "regex-syntax" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "resize" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "ring" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ropey" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rtl8168d" -version = "0.1.0" -dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "netutils 0.1.0 (git+https://github.com/redox-os/netutils.git)", - "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rustc-serialize" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rustc_version" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rustls" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "base64 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rusttype" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", - "linked-hash-map 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)", - "stb_truetype 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "same-file" -version = "0.1.2" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "same-file" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "scoped_threadpool" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "scroll" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "sdl2" -version = "0.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "sdl2-sys 0.27.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sdl2-sys" -version = "0.27.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "semver" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "serde" -version = "0.6.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "serde" -version = "0.9.15" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "serde" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "serde_codegen" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_codegen_internals 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_codegen_internals" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "syn 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_codegen_internals" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_derive" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde_codegen 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_derive" -version = "0.9.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_codegen_internals 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_derive" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive_internals 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_derive_internals" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", - "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_json" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "siphasher" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "slab" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "smallstring" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "smallvec" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "smith" -version = "0.3.10" -dependencies = [ - "clipboard 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ropey 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sodium" -version = "0.1.0" -dependencies = [ - "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "spin" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "static-buffer" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "generic-array 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "typenum 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "stb_truetype" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "string_cache" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache_codegen 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "string_cache_codegen" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "string_cache_shared" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "strsim" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "syn" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syn" -version = "0.11.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "synom" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tar" -version = "0.4.11" -source = "git+https://github.com/redox-os/tar-rs.git#1ccf2baf1703bd30807c3f11a8a874ea53af6f74" -dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tar" -version = "0.4.11" -dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tcpd" -version = "0.1.0" -dependencies = [ - "netutils 0.1.0 (git+https://github.com/redox-os/netutils.git)", - "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tempdir" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tendril" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "futf 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "utf-8 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "termion" -version = "1.3.0" -source = "git+https://github.com/redox-os/termion.git#550b9ea50a11c838533a0cf2cd9c8f7584927cdb" -dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "termion" -version = "1.3.0" -dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "termion" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -replace = "termion 1.3.0" - -[[package]] -name = "thread-id" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "thread-id" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "thread-scoped" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "thread_local" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "thread_local" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "time" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "timeout" -version = "0.1.0" -dependencies = [ - "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "toml" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "toml" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "toml" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "traitobject" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "typeable" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "typenum" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "udpd" -version = "0.1.0" -dependencies = [ - "netutils 0.1.0 (git+https://github.com/redox-os/netutils.git)", - "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicase" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-bidi" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-normalization" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-segmentation" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-width" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-xid" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unreachable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "untrusted" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "url" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "idna 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "user32-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "users" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "userutils" -version = "0.1.0" -source = "git+https://github.com/redox-os/userutils.git#3ca18917f88130f4734bcb4643a410e62e6cb24c" -dependencies = [ - "argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "liner 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "userutils" -version = "0.1.0" -dependencies = [ - "argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "liner 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "utf-8" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "utf8-ranges" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "utf8-ranges" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "vboxd" -version = "0.1.0" -dependencies = [ - "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "version-compare" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "version_check" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "vesad" -version = "0.1.0" -dependencies = [ - "orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ransid 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "rusttype 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "walkdir" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "walkdir" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "webpki" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ring 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "webpki-roots" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "untrusted 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "windows-error" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "ws2_32-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "x11" -version = "2.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "metadeps 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "x86" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "csv 0.14.7 (registry+https://github.com/rust-lang/crates.io-index)", - "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "raw-cpuid 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "xattr" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[metadata] -"checksum adler32 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ff33fe13a08dbce05bcefa2c68eea4844941437e33d6f808240b54d7157b9cd" -"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" -"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" -"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" -"checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392" -"checksum arrayvec 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "699e63a93b79d717e8c3b5eb1b28b7780d0d6d9e59a72eb769291c83b0c8dc67" -"checksum base64 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2015e3793554aa5b6007e3a72959e84c1070039e74f13dde08fa64afe1ddd892" -"checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" -"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" -"checksum blake2-rfc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "0c6a476f32fef3402f1161f89d0d39822809627754a126f8441ff2a9d45e2d59" -"checksum block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" -"checksum byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96c8b41881888cc08af32d47ac4edd52bc7fa27fef774be47a92443756451304" -"checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" -"checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8" -"checksum bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c129aff112dcc562970abb69e2508b40850dd24c274761bb50fb8a0067ba6c27" -"checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c" -"checksum clipboard 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "811169a9ffda99ed1841a6db3c48cffbab9a9101376f77fee3c14a7581ab933d" -"checksum clipboard-win 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f05017278a9e5485eacce962c9efc52f720eef0d19646dc3a7af714aad22ed2c" -"checksum color_quant 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a475fc4af42d83d28adf72968d9bcfaf035a1a9381642d8e85d8a04957767b0d" -"checksum constant_time_eq 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "07dcb7959f0f6f1cf662f9a7ff389bcb919924d99ac41cf31f10d611d8721323" -"checksum csv 0.14.7 (registry+https://github.com/rust-lang/crates.io-index)" = "266c1815d7ca63a5bd86284043faf91e8c95e943e55ce05dc0ae08e952de18bc" -"checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3" -"checksum deflate 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8f39474a23b492b7ec97604c7828abd05771b28ed03cac0c6b884e79f9980283" -"checksum deque 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a694dae478589798d752c7125542f8a5ae8b6e59476172baf2eed67357bdfa27" -"checksum docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab32ea6e284d87987066f21a9e809a73c14720571ef34516f0890b3d355ccfd8" -"checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" -"checksum encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" -"checksum encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" -"checksum encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7" -"checksum encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a" -"checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" -"checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" -"checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" -"checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" -"checksum error-chain 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "318cb3c71ee4cdea69fdc9e15c173b245ed6063e1709029e8fd32525a881120f" -"checksum extra 0.1.0 (git+https://github.com/redox-os/libextra.git)" = "" -"checksum flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "36df0166e856739905cd3d7e0b210fe818592211a008862599845e012d8d304c" -"checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344" -"checksum fuse 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "adf08478eb39cff95e34daa7a2743a256d1c18388c0328d2f717e8ef748001f6" -"checksum futf 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "51f93f3de6ba1794dcd5810b3546d004600a59a98266487c8407bc4b24e398f3" -"checksum gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)" = "40899336fb50db0c78710f53e87afc54d8c7266fb76262fecc78ca1a7f09deae" -"checksum generic-array 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3406a3975bc944fdd85b7964d53296a0ff11f4b6c4704fa4972c9a7c8ba27367" -"checksum gif 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8a80d6fe9e52f637df9afd4779449a7be17c39cc9c35b01589bb833f956ba596" -"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" -"checksum goblin 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3536832676b9c0bde31ef9b6d1c8a9cc897267eaf15caaddcaef313f94b42e53" -"checksum html5ever 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a358fef34c3334e92cd34d83ce870a386334e605e7abe987a69a7078a4142c69" -"checksum html5ever-atoms 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4109e35fec157307b918eb9d5b7018e2fa771aea0c04831e22003ac4722fbd1b" -"checksum httparse 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77f756bed9ee3a83ce98774f4155b42a31b787029013f3a7d83eca714e500e21" -"checksum hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)" = "94da93321c171e26481afeebe8288757b0501901b7c5492648163d8ec4942ec5" -"checksum hyper-rustls 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "68fdeacba341bed69e9b8fb8acbe618f18c5614e173895635ee7cb7eae57fd3d" -"checksum idna 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6ac85ec3f80c8e4e99d9325521337e14ec7555c458a14e377d189659a427f375" -"checksum image 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d95816db758249fe16f23a4e23f1a3a817fe11892dbfd1c5836f625324702158" -"checksum inflate 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e7e0062d2dc2f17d2f13750d95316ae8a2ff909af0fda957084f5defd87c43bb" -"checksum jpeg-decoder 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "919d49b634cde303392353c5dd51153ec005a1a981c6f4b8277692a51e9d260d" -"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" -"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" -"checksum lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce12306c4739d86ee97c23139f3a34ddf0387bbf181bc7929d287025a8c3ef6b" -"checksum libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122" -"checksum libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)" = "babb8281da88cba992fa1f4ddec7d63ed96280a1a53ec9b919fd37b53d71e502" -"checksum libflate 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7aa60ce680c15f96b74bd6208256f112049ab20fd6da510f27f82cb78323a77" -"checksum libgo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "99a64661b7d5c8b2ccb779e3fb0ced098426bb9bfbded934aa76ef227300e0cf" -"checksum liner 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f9e406164c25b420480023985bdf65cef366855666ad4cb12cd3eaee82dcb399" -"checksum linked-hash-map 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "f26e961e0c884309cd527b1402a5409d35db612b36915d755e1a4f5c1547a31c" -"checksum linked_list_allocator 0.2.5 (git+https://github.com/phil-opp/linked-list-allocator.git)" = "" -"checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad" -"checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084" -"checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" -"checksum malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" -"checksum matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efd7622e3022e1a6eaa602c4cea8912254e5582c9c692e9167714182244801b1" -"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" -"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" -"checksum metadeps 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829fffe7ea1d747e23f64be972991bc516b2f1ac2ae4a3b33d8bea150c410151" -"checksum mime 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5514f038123342d01ee5f95129e4ef1e0470c93bc29edf058a46f9ee3ba6737e" -"checksum mime_guess 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76da6df85047af8c0edfa53f48eb1073012ce1cc95c8fedc0a374f659a89dd65" -"checksum miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "28eaee17666671fa872e567547e8428e83308ebe5808cdf6a0e28397dbe2c726" -"checksum miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3e690c5df6b2f60acd45d56378981e827ff8295562fc8d34f573deb267a59cd1" -"checksum net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "bc01404e7568680f1259aa5729539f221cb1e6d047a0d9053cab4be8a73b5d67" -"checksum netutils 0.1.0 (git+https://github.com/redox-os/netutils.git)" = "" -"checksum nix 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0d95c5fa8b641c10ad0b8887454ebaafa3c92b5cd5350f8fc693adafd178e7b" -"checksum nodrop 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "52cd74cd09beba596430cc6e3091b74007169a56246e1262f0ba451ea95117b2" -"checksum ntpclient 0.0.1 (git+https://github.com/willem66745/ntpclient-rust)" = "" -"checksum num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "98b15ba84e910ea7a1973bccd3df7b31ae282bf9d8bd2897779950c9b8303d40" -"checksum num-bigint 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "ba6d838b16e56da1b6c383d065ff1ec3c7d7797f65a3e8f6ba7092fd87820bac" -"checksum num-complex 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "148eb324ca772230853418731ffdf13531738b50f89b30692a01fcdcb0a64677" -"checksum num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "ef1a4bf6f9174aa5783a9b4cc892cacd11aebad6c69ad027a0b65c6ca5f8aa37" -"checksum num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d1891bd7b936f12349b7d1403761c8a0b85a18b148e9da4429d5d102c1a41e" -"checksum num-rational 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "c2dc5ea04020a8f18318ae485c751f8cfa1c0e69dcf465c29ddaaa64a313cc44" -"checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99" -"checksum num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca313f1862c7ec3e0dfe8ace9fa91b1d9cb5c84ace3d00f5ec4216238e93c167" -"checksum objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "877f30f37acef6749b1841cceab289707f211aecfc756553cd63976190e6cc2e" -"checksum objc-foundation 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" -"checksum objc_id 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e4730aa1c64d722db45f7ccc4113a3e2c465d018de6db4d3e7dfe031e8c8a297" -"checksum octavo 0.1.1 (git+https://github.com/libOctavo/octavo.git)" = "" -"checksum octavo-digest 0.1.2 (git+https://github.com/libOctavo/octavo.git)" = "" -"checksum odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "c3df9b730298cea3a1c3faa90b7e2f9df3a9c400d0936d6015e6165734eefcba" -"checksum orbclient 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "06be24afab121c4167c8e9c9781e49b7c232f774815816b67c7c6aa7fc503cf1" -"checksum orbfont 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "da4dfbc851e5c24c3cf1e16ec5222f868f3362d2b7493d0b53051fe2669267a2" -"checksum orbimage 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c3b031607ef7a3c562949dfb595b1ea2b2d697b14544af407242a52dce811a6f" -"checksum orbtk 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "2bca50ac6874107a922dd26dc79889b963afce69075940463ce026b5281bf9f1" -"checksum pager 0.1.0 (git+https://github.com/redox-os/libpager.git)" = "" -"checksum peg 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a85e13cbc4888df1091443e418a772c94163ab5a9cfcfe57d7fcf6ab1057b3c2" -"checksum permutate 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b4ba980af238a6d6fcc0df53fe0d7920376bc4ce2c6ce298992891a230b47a8" -"checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc" -"checksum phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d62594c0bb54c464f633175d502038177e90309daf2e0158be42ed5f023ce88f" -"checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03" -"checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2" -"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" -"checksum pkgutils 0.1.0 (git+https://github.com/redox-os/pkgutils.git)" = "" -"checksum png 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "06208e2ee243e3118a55dda9318f821f206d8563fb8d4df258767f8e62bb0997" -"checksum png 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3cb773e9a557edb568ce9935cf783e3cdcabe06a9449d41b3e5506d88e582c82" -"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" -"checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d" -"checksum ransid 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "e870a7ce03758d35a3b71e8cf07a38d84249aa545a49e8a7515afb0c12d33727" -"checksum raw-cpuid 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13b844e4049605ff38fed943f5c7b2c691fad68d9d5bf074d2720554c4e48246" -"checksum raw-cpuid 3.0.0 (git+https://github.com/gz/rust-cpuid)" = "" -"checksum rayon 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8c83adcb08e5b922e804fe1918142b422602ef11f2fd670b0b52218cb5984a20" -"checksum rayon-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "767d91bacddf07d442fe39257bf04fd95897d1c47c545d009f6beb03efd038f8" -"checksum redox_event 0.1.0 (git+https://github.com/redox-os/event.git)" = "" -"checksum redox_event 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98e1a40d38f45a3ad65fd088640eeee7b215adcd73041b9f94b92204cca9572a" -"checksum redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "29dbdfd4b9df8ab31dec47c6087b7b13cbf4a776f335e4de8efba8288dda075b" -"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" -"checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01" -"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" -"checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457" -"checksum resize 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e8f5c5cf4d79776ed121e1c5052718b4bb06d2b48049144a2f0e5ad613b608e" -"checksum ring 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "621adad0185f587ad058bbecededfa2413f5f2e999563bc96349dead9e00d25c" -"checksum ropey 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ffbce36196db96680b526bc2e2e27f23003e5ffab07271a176646c26dd0028b" -"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" -"checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" -"checksum rustls 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fcfb2a577b14dca9caf13e6c6aa86d61158aa677347fbc155e5a1dac0f3b718f" -"checksum rusttype 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c64ffc93b0cc5a6f5e5e84da2a4082b0271e0a1dd76e821bdac570bda7797e" -"checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7" -"checksum scoped_threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3ef399c8893e8cb7aa9696e895427fab3a6bf265977bb96e126f24ddd2cda85a" -"checksum scroll 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "39c82d0508f6a56bdb409031382d62e9fa7f5e198fa04dfc06a7a96f1dfc101d" -"checksum sdl2 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c366cfa1f22d001774214ce2fb13f369af760b016bc79cc62d7f5ae15c00fea" -"checksum sdl2-sys 0.27.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8d9f87e3d948f94f2d8688970422f49249c20e97f8f3aad76cb8729901d4eb10" -"checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" -"checksum serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97b18e9e53de541f11e497357d6c5eaeb39f0cb9c8734e274abe4935f6991fa" -"checksum serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" -"checksum serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)" = "34b623917345a631dc9608d5194cc206b3fe6c3554cd1c75b937e55e285254af" -"checksum serde 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3b46a59dd63931010fdb1d88538513f3279090d88b5c22ef4fe8440cfffcc6e3" -"checksum serde_codegen 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "a4c5d8a33087d8984f9535daa62a6498a08f6476050b00ab9339dd847e4c25cc" -"checksum serde_codegen_internals 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "afad7924a009f859f380e4a2e3a509a845c2ac66435fcead74a4d983b21ae806" -"checksum serde_codegen_internals 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bc888bd283bd2420b16ad0d860e35ad8acb21941180a83a189bb2046f9d00400" -"checksum serde_derive 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "ce44e5f4264b39e9d29c875357b7cc3ebdfb967bb9e22bfb5e44ffa400af5306" -"checksum serde_derive 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)" = "978fd866f4d4872084a81ccc35e275158351d3b9fe620074e7d7504b816b74ba" -"checksum serde_derive 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6c06b68790963518008b8ae0152d48be4bbbe77015d2c717f6282eea1824be9a" -"checksum serde_derive_internals 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "021c338d22c7e30f957a6ab7e388cb6098499dda9fd4ba1661ee074ca7a180d1" -"checksum serde_json 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5aaee47e038bf9552d30380d3973fff2593ee0a76d81ad4c581f267cdcadf36" -"checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" -"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" -"checksum smallstring 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30950abdb5b38f56a0e181ae56ed64a539b64fa77ea6325147203dc7faeb087f" -"checksum smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4f8266519bc1d17d0b5b16f6c21295625d562841c708f6376f49028a43e9c11e" -"checksum spin 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1d16a26e2b789f86aabddbe91cb82ee2e822beb8a59840d631941b625ef77e53" -"checksum static-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6da6a96247d4b372d3ed90dec2c129ab57c934359ac4c6adbaa5871cd0737437" -"checksum stb_truetype 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "21b5c3b588a493a477e0d99769ee091b3627625f9ba4bdd882e6b4b0b0958805" -"checksum string_cache 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d192db2123fac37399e1ca61557904a5c3fb6fc24c73d2e47b15d20dc32470" -"checksum string_cache_codegen 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0c9dfe1a7c8bba1ecb90730d269fdc08afe93d23c28dd6c4aa5cabd79a05a05e" -"checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc" -"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" -"checksum syn 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)" = "58fd09df59565db3399efbba34ba8a2fec1307511ebd245d0061ff9d42691673" -"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" -"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" -"checksum tar 0.4.11 (git+https://github.com/redox-os/tar-rs.git)" = "" -"checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" -"checksum tendril 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4ce04c250d202db8004921e3d3bc95eaa4f2126c6937a428ae39d12d0e38df62" -"checksum termion 1.3.0 (git+https://github.com/redox-os/termion.git)" = "" -"checksum termion 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b41865823fb8c7873ff869893219b3188e7fcd66c10effb97f2b2f63ea98681" -"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" -"checksum thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437c97558c70d129e40629a5b385b3fb1ffac301e63941335e4d354081ec14a" -"checksum thread-scoped 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14387dce246d09efe184c8ebc34d9db5c0672a908b2f50efc53359ae13d5ae68" -"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" -"checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7" -"checksum time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "ffd7ccbf969a892bf83f1e441126968a07a3941c24ff522a26af9f9f4585d1a3" -"checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4" -"checksum toml 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd86ad9ebee246fdedd610e0f6d0587b754a3d81438db930a244d0480ed7878f" -"checksum toml 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3063405db158de3dce8efad5fc89cf1baffb9501a3647dc9505ba109694ce31f" -"checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" -"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" -"checksum typenum 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f06b0aa9c30a626496836e8de28bd2910cf6c8614e9579c9f8644b0a5d8fb0f5" -"checksum unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "13a5906ca2b98c799f4b1ab4557b76367ebd6ae5ef14930ec841c74aed5f3764" -"checksum unicode-bidi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3a078ebdd62c0e71a709c3d53d2af693fe09fe93fbff8344aebe289b78f9032" -"checksum unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e28fa37426fceeb5cf8f41ee273faa7c82c47dc8fba5853402841e665fcd86ff" -"checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3" -"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" -"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" -"checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91" -"checksum untrusted 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "193df64312e3515fd983ded55ad5bcaa7647a035804828ed757e832ce6029ef3" -"checksum url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5ba8a749fb4479b043733416c244fa9d1d3af3d7c23804944651c8a448cb87e" -"checksum user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47" -"checksum users 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7ae8fdf783cb9652109c99886459648feb92ecc749e6b8e7930f6decba74c7c" -"checksum userutils 0.1.0 (git+https://github.com/redox-os/userutils.git)" = "" -"checksum utf-8 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9aee9ba280438b56d1ebc5329f2094f0ff457f811eeeff0b278d75aa99db400" -"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" -"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" -"checksum version-compare 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cb766fdc689f3a5e38b2a0eb9dff9ac4a8961c09bb99064ecf88702a39b1992e" -"checksum version_check 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f2edadb5308f31d97771a678c33df28f18d04f61de3fe21b9452f37854eb6c08" -"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum walkdir 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c66c0b9792f0a765345452775f3adbd28dde9d33f30d13e5dcc5ae17cf6f3780" -"checksum walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bb08f9e670fab86099470b97cd2b252d6527f0b3cc1401acdb595ffc9dd288ff" -"checksum webpki 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4155c3a648038ca6b3568ab34e7da1866592ef40b2543fea412461364ef3cbfc" -"checksum webpki-roots 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f611ac968bda097564945980dfcbb840fb6e0380b9d9d34ac6e4c6067ecb3060" -"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" -"checksum windows-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d8570474f84367116f48f9fb2ae3e0347600029909096a15a5e6509bd4a03c50" -"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -"checksum x11 2.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab7c9c8fcd61c1453aa7506d45be2fa916512f0c4ec985ef20bba3d575a23a6" -"checksum x86 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "127728f29f7cfb243a9264c80fc7e57bd1abb3ab015850b05736efda2abe5859" -"checksum xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "5f04de8a1346489a2f9e9bd8526b73d135ec554227b17568456e86aa35b6f3fc" diff --git a/Cargo.toml b/Cargo.toml deleted file mode 100644 index 5513d32..0000000 --- a/Cargo.toml +++ /dev/null @@ -1,74 +0,0 @@ -[workspace] -exclude = ["cookbook"] -members = [ - "docgen", - "drivers/ahcid", - "drivers/alxd", - "drivers/bgad", - "drivers/e1000d", - "drivers/nvmed", - "drivers/pcid", - "drivers/ps2d", - "drivers/rtl8168d", - "drivers/vboxd", - "drivers/vesad", - "drivers/xhcid", - "installer", - "kernel", - "libs/event", - "libs/extra", - "libs/jpeg-decoder", - "libs/mio", - "libs/orbclient", - "libs/orbfont", - "libs/orbimage", - "libs/orbtk", - "libs/pager", - #TODO "libs/ralloc", - "libs/ransid", - "libs/same-file", - "libs/syscall", - "libs/tar", - "libs/termion", - "programs/acid", - "programs/binutils", - "programs/contain", - "programs/coreutils", - "programs/extrautils", - "programs/games", - "programs/init", - "programs/ion", - "programs/netutils", - "programs/orbterm", - "programs/orbutils", - "programs/pkgutils", - "programs/smith", - "programs/sodium", - "programs/timeout", - "programs/userutils", - "schemes/ethernetd", - "schemes/ipd", - "schemes/orbital", - "schemes/ptyd", - "schemes/randd", - "schemes/redoxfs", - "schemes/tcpd", - "schemes/udpd" -] - -[replace] -"extra:0.1.0" = { path = "libs/extra" } -"jpeg-decoder:0.1.12" = { path = "libs/jpeg-decoder" } -"mio:0.6.2" = { path = "libs/mio" } -"orbclient:0.3.4" = { path = "libs/orbclient" } -"orbfont:0.1.8" = { path = "libs/orbfont" } -"orbimage:0.1.15" = { path = "libs/orbimage" } -"orbtk:0.2.19" = { path = "libs/orbtk" } -"pager:0.1.0" = { path = "libs/pager" } -"ralloc:1.0.0" = { path = "libs/ralloc" } -"ransid:0.2.7" = { path = "libs/ransid" } -"redox_event:0.1.0" = { path = "libs/event" } -"redox_syscall:0.1.17" = { path = "libs/syscall" } -"same-file:0.1.2" = { path = "libs/same-file" } -"tar:0.4.11" = { path = "libs/tar" } -"termion:1.3.0" = { path = "libs/termion" } diff --git a/Makefile b/Makefile index 461c1fa..7eb8525 100644 --- a/Makefile +++ b/Makefile @@ -8,12 +8,8 @@ live: build/livedisk.bin iso: build/livedisk.iso clean: - cargo clean - cargo clean --manifest-path rust/src/libcollections/Cargo.toml - cargo clean --manifest-path rust/src/libstd/Cargo.toml + cargo clean --manifest-path kernel/Cargo.toml -$(FUMOUNT) build/filesystem/ || true - rm -rf initfs/bin - rm -rf filesystem/bin filesystem/sbin filesystem/ui/bin rm -rf build update: @@ -35,12 +31,6 @@ include mk/virtualbox.mk # Kernel recipes include mk/kernel.mk -# Userspace recipes -include mk/userspace/mod.mk - -# Documentation -include mk/doc.mk - # Filesystem recipes include mk/initfs.mk include mk/filesystem.mk diff --git a/bootloader b/bootloader index 5e5e080..787f018 160000 --- a/bootloader +++ b/bootloader @@ -1 +1 @@ -Subproject commit 5e5e080d618db036c632e096bdf6ce5c77b33bae +Subproject commit 787f0184fa96a227e51a7ce083a29b06f8945fd8 diff --git a/cookbook b/cookbook index 4a18e61..0506e36 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 4a18e61514133017e31d67d31931b1bee621f0c2 +Subproject commit 0506e3602e7e59de94a0e6c200d9aef82fe8e82c diff --git a/docgen b/docgen deleted file mode 160000 index 52fb886..0000000 --- a/docgen +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 52fb8863efdd0862b2439f87faff2457b43cac62 diff --git a/drivers b/drivers deleted file mode 160000 index 15675ea..0000000 --- a/drivers +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 15675ea9c3de8b552743f83ec2f9a7bbba538c15 diff --git a/filesystem.toml b/filesystem.toml new file mode 100644 index 0000000..d876abe --- /dev/null +++ b/filesystem.toml @@ -0,0 +1,175 @@ +# This is the default configuration file + +# General settings +[general] +# Do not prompt if settings are not defined +prompt = false +sysroot = "build/filesystem" + +# Package settings +[packages] +acid = {} +binutils = {} +contain = {} +coreutils = {} +drivers = {} +extrautils = {} +games = {} +init = {} +installer = {} +ion = {} +lua = {} +netstack = {} +netutils = {} +orbdata = {} +orbital = {} +orbterm = {} +orbutils = {} +#pixelcannon = {} +pkgutils = {} +ptyd = {} +randd = {} +redoxfs = {} +smith = {} +#sodium = {} +userutils = {} + +# User settings +[users.root] +# Password is set to "password" +password = "$argon2i$m=4096,t=10,p=1$Tnc4UVV0N00$ML9LIOujd3nmAfkAwEcSTMPqakWUF0OUiLWrIy0nGLk" +uid = 0 +gid = 0 +name = "root" +home = "/root" + +[users.user] +# Password is unset +password = "" + +[[files]] +path = "/etc/init.d/00_base" +data = """ +randd +ptyd +pcid /etc/pcid.toml +""" + +[[files]] +path = "/etc/init.d/10_net" +data = """ +ethernetd +ipd +tcpd +udpd +dhcpd -b +""" + +[[files]] +path = "/etc/init.d/20_orbital" +data = """ +orbital display:3/activate /ui/bin/orblogin /ui/bin/launcher +""" + +[[files]] +path = "/etc/init.d/30_console" +data = """ +getty display:2 +getty debug: -J +""" + +[[files]] +path = "/etc/net/dns" +data = "208.67.222.222" + +[[files]] +path = "/etc/net/ip" +data = "10.0.2.15" + +[[files]] +path = "/etc/net/ip_router" +data = "10.0.2.2" + +[[files]] +path = "/etc/net/ip_subnet" +data = "255.255.255.0" + +[[files]] +path = "/etc/net/mac" +data = "00.00.00.00.00.00" + +[[files]] +path = "/etc/pkg.d/50_redox" +data = "https://static.redox-os.org/pkg" + +[[files]] +path = "/etc/group" +data = "sudo;1;user" + +[[files]] +path = "/etc/hostname" +data = "redox" + +[[files]] +path = "/etc/issue" +data = """ +########## Redox OS ########## +# Login with the following: # +# `user` # +# `root`:`password` # +############################## + +""" + +[[files]] +path = "/etc/motd" +data = """ +Welcome to Redox OS! + +""" + +[[files]] +path = "/etc/pcid.toml" +data = """ +[[drivers]] +name = "82543GC NIC" +class = 2 +vendor = 32902 +device = 4100 +command = ["e1000d", "$NAME", "$BAR0", "$IRQ"] + +[[drivers]] +name = "82540EM NIC" +class = 2 +vendor = 32902 +device = 4110 +command = ["e1000d", "$NAME", "$BAR0", "$IRQ"] + +[[drivers]] +name = "82545EM NIC" +class = 2 +vendor = 32902 +device = 4111 +command = ["e1000d", "$NAME", "$BAR0", "$IRQ"] + +[[drivers]] +name = "82579V NIC" +class = 2 +vendor = 32902 +device = 5379 +command = ["e1000d", "$NAME", "$BAR0", "$IRQ"] + +[[drivers]] +name = "RTL8168 NIC" +class = 2 +vendor = 4332 +device = 33128 +command = ["rtl8168d", "$NAME", "$BAR2", "$IRQ"] + +[[drivers]] +name = "XHCI" +class = 12 +subclass = 3 +interface = 48 +command = ["xhcid", "$NAME", "$BAR0", "$IRQ"] +""" diff --git a/filesystem/etc/group b/filesystem/etc/group deleted file mode 100644 index 62fcd49..0000000 --- a/filesystem/etc/group +++ /dev/null @@ -1 +0,0 @@ -sudo;1;user diff --git a/filesystem/etc/hostname b/filesystem/etc/hostname deleted file mode 100644 index 5e07ae0..0000000 --- a/filesystem/etc/hostname +++ /dev/null @@ -1 +0,0 @@ -redox diff --git a/filesystem/etc/init.d/00_base b/filesystem/etc/init.d/00_base deleted file mode 100644 index d34f472..0000000 --- a/filesystem/etc/init.d/00_base +++ /dev/null @@ -1,3 +0,0 @@ -/sbin/randd -/sbin/ptyd -/sbin/pcid /etc/pcid.toml diff --git a/filesystem/etc/init.d/10_net b/filesystem/etc/init.d/10_net deleted file mode 100644 index 21de468..0000000 --- a/filesystem/etc/init.d/10_net +++ /dev/null @@ -1,5 +0,0 @@ -/sbin/ethernetd -/sbin/ipd -/sbin/tcpd -/sbin/udpd -dhcpd -b diff --git a/filesystem/etc/init.d/20_orbital b/filesystem/etc/init.d/20_orbital deleted file mode 100644 index 583ebd1..0000000 --- a/filesystem/etc/init.d/20_orbital +++ /dev/null @@ -1 +0,0 @@ -/sbin/orbital display:3/activate /ui/bin/orblogin /ui/bin/launcher diff --git a/filesystem/etc/init.d/30_console b/filesystem/etc/init.d/30_console deleted file mode 100644 index c981568..0000000 --- a/filesystem/etc/init.d/30_console +++ /dev/null @@ -1,2 +0,0 @@ -getty display:2 -getty debug: -J diff --git a/filesystem/etc/installer.toml b/filesystem/etc/installer.toml deleted file mode 100644 index 34347d2..0000000 --- a/filesystem/etc/installer.toml +++ /dev/null @@ -1,45 +0,0 @@ -# This is the default configuration file - -# General settings -[general] -# Do not prompt if settings are not defined -prompt = false - -# Package settings -[packages] -coreutils = {} -extrautils = {} -ion = {} -netutils = {} -pkgutils = {} -tar = {} -userutils = {} - -[[files]] -path = "/etc/net/dns" -data = "208.67.222.222" - -[[files]] -path = "/etc/net/ip" -data = "10.0.2.15" - -[[files]] -path = "/etc/net/ip_router" -data = "10.0.2.2" - -[[files]] -path = "/etc/net/ip_subnet" -data = "255.255.255.0" - -[[files]] -path = "/etc/pkg.d/50_redox" -data = "https://static.redox-os.org/pkg" - -# User settings -[users.root] -# Password is set to "password" -password = "$argon2i$m=4096,t=10,p=1$Tnc4UVV0N00$ML9LIOujd3nmAfkAwEcSTMPqakWUF0OUiLWrIy0nGLk" -uid = 0 -gid = 0 -name = "root" -home = "/root" diff --git a/filesystem/etc/issue b/filesystem/etc/issue deleted file mode 100644 index 6a963d8..0000000 --- a/filesystem/etc/issue +++ /dev/null @@ -1,6 +0,0 @@ -########## Redox OS ########## -# Login with the following: # -# `user` # -# `root`:`password` # -############################## - diff --git a/filesystem/etc/motd b/filesystem/etc/motd deleted file mode 100644 index 5cd097a..0000000 --- a/filesystem/etc/motd +++ /dev/null @@ -1,2 +0,0 @@ -Welcome to Redox OS! - diff --git a/filesystem/etc/net/dns b/filesystem/etc/net/dns deleted file mode 100644 index 85e3287..0000000 --- a/filesystem/etc/net/dns +++ /dev/null @@ -1 +0,0 @@ -208.67.222.222 diff --git a/filesystem/etc/net/ip b/filesystem/etc/net/ip deleted file mode 100644 index b86c8a7..0000000 --- a/filesystem/etc/net/ip +++ /dev/null @@ -1 +0,0 @@ -10.0.2.15 diff --git a/filesystem/etc/net/ip_router b/filesystem/etc/net/ip_router deleted file mode 100644 index 2e66646..0000000 --- a/filesystem/etc/net/ip_router +++ /dev/null @@ -1 +0,0 @@ -10.0.2.2 diff --git a/filesystem/etc/net/ip_subnet b/filesystem/etc/net/ip_subnet deleted file mode 100644 index d30f9e9..0000000 --- a/filesystem/etc/net/ip_subnet +++ /dev/null @@ -1 +0,0 @@ -255.255.255.0 diff --git a/filesystem/etc/net/mac b/filesystem/etc/net/mac deleted file mode 100644 index f02dd3e..0000000 --- a/filesystem/etc/net/mac +++ /dev/null @@ -1 +0,0 @@ -00.00.00.00.00.00 diff --git a/filesystem/etc/passwd b/filesystem/etc/passwd deleted file mode 100644 index 7baaf91..0000000 --- a/filesystem/etc/passwd +++ /dev/null @@ -1,2 +0,0 @@ -root;$argon2i$m=4096,t=10,p=1$Tnc4UVV0N00$ML9LIOujd3nmAfkAwEcSTMPqakWUF0OUiLWrIy0nGLk;0;0;root;/root;/bin/ion -user;;1000;1000;user;/home/user;/bin/ion diff --git a/filesystem/etc/pcid.toml b/filesystem/etc/pcid.toml deleted file mode 100644 index ca097ce..0000000 --- a/filesystem/etc/pcid.toml +++ /dev/null @@ -1,41 +0,0 @@ -[[drivers]] -name = "82543GC NIC" -class = 2 -vendor = 32902 -device = 4100 -command = ["/sbin/e1000d", "$NAME", "$BAR0", "$IRQ"] - -[[drivers]] -name = "82540EM NIC" -class = 2 -vendor = 32902 -device = 4110 -command = ["/sbin/e1000d", "$NAME", "$BAR0", "$IRQ"] - -[[drivers]] -name = "82545EM NIC" -class = 2 -vendor = 32902 -device = 4111 -command = ["/sbin/e1000d", "$NAME", "$BAR0", "$IRQ"] - -[[drivers]] -name = "82579V NIC" -class = 2 -vendor = 32902 -device = 5379 -command = ["/sbin/e1000d", "$NAME", "$BAR0", "$IRQ"] - -[[drivers]] -name = "RTL8168 NIC" -class = 2 -vendor = 4332 -device = 33128 -command = ["/sbin/rtl8168d", "$NAME", "$BAR2", "$IRQ"] - -[[drivers]] -name = "XHCI" -class = 12 -subclass = 3 -interface = 48 -command = ["/sbin/xhcid", "$NAME", "$BAR0", "$IRQ"] diff --git a/filesystem/etc/pkg.d/50_redox b/filesystem/etc/pkg.d/50_redox deleted file mode 100644 index 4048482..0000000 --- a/filesystem/etc/pkg.d/50_redox +++ /dev/null @@ -1 +0,0 @@ -https://static.redox-os.org/pkg diff --git a/filesystem/home/user/LICENSE b/filesystem/home/user/LICENSE deleted file mode 120000 index 5853aae..0000000 --- a/filesystem/home/user/LICENSE +++ /dev/null @@ -1 +0,0 @@ -../../../LICENSE \ No newline at end of file diff --git a/filesystem/home/user/README.md b/filesystem/home/user/README.md deleted file mode 120000 index 8a33348..0000000 --- a/filesystem/home/user/README.md +++ /dev/null @@ -1 +0,0 @@ -../../../README.md \ No newline at end of file diff --git a/filesystem/root/LICENSE b/filesystem/root/LICENSE deleted file mode 120000 index 30cff74..0000000 --- a/filesystem/root/LICENSE +++ /dev/null @@ -1 +0,0 @@ -../../LICENSE \ No newline at end of file diff --git a/filesystem/root/README.md b/filesystem/root/README.md deleted file mode 120000 index fe84005..0000000 --- a/filesystem/root/README.md +++ /dev/null @@ -1 +0,0 @@ -../../README.md \ No newline at end of file diff --git a/filesystem/ui b/filesystem/ui deleted file mode 160000 index d6a5749..0000000 --- a/filesystem/ui +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d6a5749d61df72e8a339335be5429d843fa401b1 diff --git a/initfs/etc/pcid.toml b/initfs.toml similarity index 56% rename from initfs/etc/pcid.toml rename to initfs.toml index da0c570..c64b788 100644 --- a/initfs/etc/pcid.toml +++ b/initfs.toml @@ -1,3 +1,34 @@ +# This is the default configuration file + +# General settings +[general] +# Do not prompt if settings are not defined +prompt = false +sysroot = "build/initfs" + +# Package settings +[packages] +drivers = {} +init = {} +redoxfs = {} + +[[files]] +path="/etc/init.rc" +data=""" +export PATH initfs:/bin +vesad T T G +stdio display:1 +ps2d +pcid /etc/pcid.toml +redoxfs disk:0 file +cd file: +export PATH file:/bin +run.d /etc/init.d +""" + +[[files]] +path="/etc/pcid.toml" +data=""" [[drivers]] name = "AHCI storage" class = 1 @@ -30,3 +61,4 @@ class = 8 vendor = 33006 device = 51966 command = ["vboxd", "$NAME", "$BAR0", "$BAR1", "$IRQ"] +""" diff --git a/initfs/etc/init.rc b/initfs/etc/init.rc deleted file mode 100644 index bd7548b..0000000 --- a/initfs/etc/init.rc +++ /dev/null @@ -1,9 +0,0 @@ -export PATH initfs:/bin -vesad T T G -stdio display:1 -ps2d -pcid /etc/pcid.toml -redoxfs disk:0 file -cd file: -export PATH file:/bin -run.d /etc/init.d diff --git a/installer b/installer index c2bae24..318e7bb 160000 --- a/installer +++ b/installer @@ -1 +1 @@ -Subproject commit c2bae24835735df247e27093aa43bd1d0fe2a655 +Subproject commit 318e7bb89f37228984bc92976ecdb28adb63dcf0 diff --git a/kernel b/kernel index b3a25bd..62d3f4b 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit b3a25bd3a39cd527b80d5ab2ea0da56a91e10540 +Subproject commit 62d3f4bd93c425b263bd9b762632f4601e0ec1c5 diff --git a/krustc.sh b/krustc.sh deleted file mode 100755 index cc510e8..0000000 --- a/krustc.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -have_o=false -for arg in "$@"; do - if [[ "$arg" = "-o" ]]; then - have_o=true - break - fi -done - -args=() -for arg in "$@"; do - if [[ $have_o = true && "$arg" =~ ^extra-filename= ]]; then - unset args[${#args[@]}-1] - elif [[ $have_o = true && "$arg" =~ ^--emit= ]]; then - args+=("--emit=link") - else - args+=("$arg") - fi -done - -RUST_BACKTRACE=1 exec rustc -L build/kernel "${args[@]}" diff --git a/krustdoc.sh b/krustdoc.sh deleted file mode 100755 index 8365834..0000000 --- a/krustdoc.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -RUST_BACKTRACE=1 rustdoc -L build/kernel $* diff --git a/libc-artifacts b/libc-artifacts deleted file mode 160000 index ecd2edd..0000000 --- a/libc-artifacts +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ecd2edd8935177cf9f160ae6ec11c22ee3a0a249 diff --git a/libs/event b/libs/event deleted file mode 160000 index 1333e64..0000000 --- a/libs/event +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 1333e640e1c58cf3808372147f34e91ff0d7f13c diff --git a/libs/extra b/libs/extra deleted file mode 160000 index 4029320..0000000 --- a/libs/extra +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 402932084acd5fef4812945887ceaaa2ddd5f264 diff --git a/libs/jpeg-decoder b/libs/jpeg-decoder deleted file mode 160000 index 0660fc0..0000000 --- a/libs/jpeg-decoder +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0660fc061973598515ec5d39d03a1bc7e53d68f6 diff --git a/libs/mio b/libs/mio deleted file mode 160000 index a4f7f6a..0000000 --- a/libs/mio +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a4f7f6a4e106fa52702a2dc1c4b2bb747bd0bf9a diff --git a/libs/orbclient b/libs/orbclient deleted file mode 160000 index 4a31537..0000000 --- a/libs/orbclient +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 4a3153798bd8d22380f057c07f1e77f8bd9a3cec diff --git a/libs/orbfont b/libs/orbfont deleted file mode 160000 index f554cec..0000000 --- a/libs/orbfont +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f554cec35c9614939590ec5d799d01a593d3c446 diff --git a/libs/orbimage b/libs/orbimage deleted file mode 160000 index cc3b593..0000000 --- a/libs/orbimage +++ /dev/null @@ -1 +0,0 @@ -Subproject commit cc3b593a585e339819cafcd8133b22cc6242f84d diff --git a/libs/orbtk b/libs/orbtk deleted file mode 160000 index 9ff1aa4..0000000 --- a/libs/orbtk +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9ff1aa42bdd7404585e5cf7f666e2a0f67c4e4be diff --git a/libs/pager b/libs/pager deleted file mode 160000 index 62b01eb..0000000 --- a/libs/pager +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 62b01eba8299143a1a5a78b36d85ab63251462b3 diff --git a/libs/ralloc b/libs/ralloc deleted file mode 160000 index e31a743..0000000 --- a/libs/ralloc +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e31a743ec384bac8ecc0bdc82d63ae3534016416 diff --git a/libs/ransid b/libs/ransid deleted file mode 160000 index 20d2db3..0000000 --- a/libs/ransid +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 20d2db307bc9926a33f437b688925ba3a37821c2 diff --git a/libs/same-file b/libs/same-file deleted file mode 160000 index d034b7f..0000000 --- a/libs/same-file +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d034b7f24b4a3eeb56baccbdcbfcdfce95940487 diff --git a/libs/syscall b/libs/syscall deleted file mode 160000 index 8630809..0000000 --- a/libs/syscall +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 863080967dfee40e0a0c74936e43e79161e0aa6e diff --git a/libs/tar b/libs/tar deleted file mode 160000 index 1ccf2ba..0000000 --- a/libs/tar +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 1ccf2baf1703bd30807c3f11a8a874ea53af6f74 diff --git a/libs/termion b/libs/termion deleted file mode 160000 index 550b9ea..0000000 --- a/libs/termion +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 550b9ea50a11c838533a0cf2cd9c8f7584927cdb diff --git a/mk/config.mk b/mk/config.mk index b6567e9..db36a11 100644 --- a/mk/config.mk +++ b/mk/config.mk @@ -7,7 +7,6 @@ ifeq ($(UNAME),Darwin) ECHO=/bin/echo FUMOUNT=sudo umount export LD=$(ARCH)-elf-ld - export LDFLAGS=--gc-sections export NPROC=sysctl -n hw.ncpu export STRIP=$(ARCH)-elf-strip VB_AUDIO=coreaudio @@ -16,7 +15,6 @@ else ECHO=echo FUMOUNT=fusermount -u export LD=ld - export LDFLAGS=--gc-sections export NPROC=nproc export STRIP=strip VB_AUDIO="pulse" @@ -25,23 +23,14 @@ endif # Automatic variables ROOT=$(PWD) +export INITFS_FOLDER=$(ROOT)/build/initfs export RUST_TARGET_PATH=$(ROOT)/kernel/targets -export CC=$(ROOT)/libc-artifacts/gcc.sh -export CFLAGS=-fno-stack-protector -U_FORTIFY_SOURCE +export XARGO_RUST_SRC=$(ROOT)/rust/src # Kernel variables KTARGET=$(ARCH)-unknown-none KBUILD=build/kernel -KRUSTC=./krustc.sh -KRUSTDOC=./krustdoc.sh -KCARGO=RUSTC="$(KRUSTC)" RUSTDOC="$(KRUSTDOC)" CARGO_INCREMENTAL=1 cargo -KCARGOFLAGS=--target $(KTARGET) --release -- -C soft-float # Userspace variables export TARGET=$(ARCH)-unknown-redox BUILD=build/userspace -export INITFS_FOLDER=$(ROOT)/initfs -RUSTC=$(PWD)/rustc.sh -RUSTDOC=./rustdoc.sh -CARGO=RUSTC="$(RUSTC)" RUSTDOC="$(RUSTDOC)" CARGO_INCREMENTAL=1 cargo -CARGOFLAGS=--target $(TARGET) --release -- -C codegen-units=`$(NPROC)` diff --git a/mk/disk.mk b/mk/disk.mk index bf4996e..d0a8972 100644 --- a/mk/disk.mk +++ b/mk/disk.mk @@ -1,7 +1,7 @@ -build/harddrive.bin: $(KBUILD)/kernel bootloader/$(ARCH)/** build/filesystem.bin +build/harddrive.bin: build/kernel bootloader/$(ARCH)/** build/filesystem.bin nasm -f bin -o $@ -D ARCH_$(ARCH) -ibootloader/$(ARCH)/ bootloader/$(ARCH)/harddrive.asm -build/livedisk.bin: $(KBUILD)/kernel_live bootloader/$(ARCH)/** +build/livedisk.bin: build/kernel_live bootloader/$(ARCH)/** nasm -f bin -o $@ -D ARCH_$(ARCH) -ibootloader/$(ARCH)/ bootloader/$(ARCH)/livedisk.asm build/%.bin.gz: build/%.bin diff --git a/mk/doc.mk b/mk/doc.mk deleted file mode 100644 index 78371f7..0000000 --- a/mk/doc.mk +++ /dev/null @@ -1,13 +0,0 @@ -doc: $(KBUILD)/libkernel.a $(BUILD)/libstd.rlib FORCE - $(KCARGO) doc --target $(KTARGET) --manifest-path kernel/Cargo.toml - $(CARGO) doc --target $(TARGET) --manifest-path rust/src/libstd/Cargo.toml - -ref: FORCE - rm -rf filesystem/ref/ - mkdir -p filesystem/ref/ - #cargo run --manifest-path docgen/Cargo.toml -- programs/binutils/src/bin/ filesystem/ref/ - cargo run --manifest-path docgen/Cargo.toml -- programs/coreutils/src/bin/ filesystem/ref/ - cargo run --manifest-path docgen/Cargo.toml -- programs/extrautils/src/bin/ filesystem/ref/ - cargo run --manifest-path docgen/Cargo.toml -- programs/netutils/src/ filesystem/ref/ - cargo run --manifest-path docgen/Cargo.toml -- programs/pkgutils/src/ filesystem/ref/ - cargo run --manifest-path docgen/Cargo.toml -- programs/userutils/src/ filesystem/ref/ diff --git a/mk/filesystem.mk b/mk/filesystem.mk index d1eb674..cce220b 100644 --- a/mk/filesystem.mk +++ b/mk/filesystem.mk @@ -1,14 +1,14 @@ -build/filesystem.bin: userspace +build/filesystem.bin: filesystem.toml -$(FUMOUNT) build/filesystem/ || true rm -rf $@ build/filesystem/ dd if=/dev/zero of=$@ bs=1048576 count=128 - cargo run --manifest-path schemes/redoxfs/Cargo.toml --quiet --release --bin redoxfs-mkfs $@ + cargo run --manifest-path installer/redoxfs/Cargo.toml --quiet --release --bin redoxfs-mkfs $@ mkdir -p build/filesystem/ - cargo build --manifest-path schemes/redoxfs/Cargo.toml --quiet --release --bin redoxfs - cargo run --manifest-path schemes/redoxfs/Cargo.toml --quiet --release --bin redoxfs -- $@ build/filesystem/ + cargo build --manifest-path installer/redoxfs/Cargo.toml --quiet --release --bin redoxfs + cargo run --manifest-path installer/redoxfs/Cargo.toml --quiet --release --bin redoxfs -- $@ build/filesystem/ sleep 2 pgrep redoxfs - cp -RL filesystem/* build/filesystem/ + cargo run --manifest-path installer/Cargo.toml -- --cookbook=cookbook $< chown -R 0:0 build/filesystem chown -R 1000:1000 build/filesystem/home/user chmod -R uog+rX build/filesystem @@ -30,8 +30,8 @@ build/filesystem.bin: userspace mount: FORCE mkdir -p build/filesystem/ - cargo build --manifest-path schemes/redoxfs/Cargo.toml --quiet --release --bin redoxfs - cargo run --manifest-path schemes/redoxfs/Cargo.toml --quiet --release --bin redoxfs -- build/harddrive.bin build/filesystem/ + cargo build --manifest-path installer/redoxfs/Cargo.toml --quiet --release --bin redoxfs + cargo run --manifest-path installer/redoxfs/Cargo.toml --quiet --release --bin redoxfs -- build/harddrive.bin build/filesystem/ sleep 2 pgrep redoxfs diff --git a/mk/initfs.mk b/mk/initfs.mk index c6b9500..d335f12 100644 --- a/mk/initfs.mk +++ b/mk/initfs.mk @@ -1,17 +1,3 @@ -$(KBUILD)/initfs.tag: initfs/bin/init \ - initfs/bin/ahcid \ - initfs/bin/bgad \ - initfs/bin/nvmed \ - initfs/bin/pcid \ - initfs/bin/ps2d \ - initfs/bin/redoxfs \ - initfs/bin/vboxd \ - initfs/bin/vesad \ - initfs/etc/** - $(KCARGO) clean --manifest-path kernel/Cargo.toml - touch $@ - -initfs/bin/%: programs/%/Cargo.toml programs/%/src/** $(BUILD)/libstd.rlib - mkdir -p initfs/bin - $(CARGO) rustc --manifest-path $< $(CARGOFLAGS) -o $@ - $(STRIP) $@ +build/initfs.tag: initfs.toml + cargo run --manifest-path installer/Cargo.toml -- --cookbook=cookbook $< + touch $@ diff --git a/mk/kernel.mk b/mk/kernel.mk index 5d56370..6b9cc48 100644 --- a/mk/kernel.mk +++ b/mk/kernel.mk @@ -1,16 +1,11 @@ -$(KBUILD)/libcollections.rlib: rust/src/libcollections/Cargo.toml rust/src/libcollections/** - mkdir -p $(KBUILD) - $(KCARGO) rustc --manifest-path $< $(KCARGOFLAGS) -o $@ - cp rust/src/target/$(KTARGET)/release/deps/*.rlib $(KBUILD) +build/libkernel.a: kernel/Cargo.toml kernel/src/** build/initfs.tag + cd kernel && xargo rustc --lib --target $(KTARGET) --release -- -C soft-float --emit link=../$@ -$(KBUILD)/libkernel.a: kernel/Cargo.toml kernel/src/** $(KBUILD)/libcollections.rlib $(KBUILD)/initfs.tag - $(KCARGO) rustc --manifest-path $< --lib $(KCARGOFLAGS) -o $@ +build/libkernel_live.a: kernel/Cargo.toml kernel/src/** build/initfs.tag build/filesystem.bin + cd kernel && xargo rustc --lib --features live --target $(KTARGET) --release -- -C soft-float --emit link=../$@ -$(KBUILD)/libkernel_live.a: kernel/Cargo.toml kernel/src/** $(KBUILD)/libcollections.rlib $(KBUILD)/initfs.tag build/filesystem.bin - $(KCARGO) rustc --manifest-path $< --lib --features live $(KCARGOFLAGS) -o $@ +build/kernel: build/libkernel.a + $(LD) --gc-sections -z max-page-size=0x1000 -T kernel/linkers/$(ARCH).ld -o $@ $< -$(KBUILD)/kernel: $(KBUILD)/libkernel.a - $(LD) $(LDFLAGS) -z max-page-size=0x1000 -T kernel/linkers/$(ARCH).ld -o $@ $< - -$(KBUILD)/kernel_live: $(KBUILD)/libkernel_live.a - $(LD) $(LDFLAGS) -z max-page-size=0x1000 -T kernel/linkers/$(ARCH).ld -o $@ $< +build/kernel_live: build/libkernel_live.a + $(LD) --gc-sections -z max-page-size=0x1000 -T kernel/linkers/$(ARCH).ld -o $@ $< diff --git a/mk/userspace/coreutils.mk b/mk/userspace/coreutils.mk deleted file mode 100644 index 8e330c3..0000000 --- a/mk/userspace/coreutils.mk +++ /dev/null @@ -1,46 +0,0 @@ -coreutils: \ - filesystem/bin/basename \ - filesystem/bin/cat \ - filesystem/bin/chmod \ - filesystem/bin/clear \ - filesystem/bin/cp \ - filesystem/bin/cut \ - filesystem/bin/date \ - filesystem/bin/dd \ - filesystem/bin/df \ - filesystem/bin/du \ - filesystem/bin/echo \ - filesystem/bin/env \ - filesystem/bin/false \ - filesystem/bin/free \ - filesystem/bin/head \ - filesystem/bin/kill \ - filesystem/bin/ln \ - filesystem/bin/ls \ - filesystem/bin/mkdir \ - filesystem/bin/mv \ - filesystem/bin/printenv \ - filesystem/bin/ps \ - filesystem/bin/pwd \ - filesystem/bin/realpath \ - filesystem/bin/reset \ - filesystem/bin/rmdir \ - filesystem/bin/rm \ - filesystem/bin/seq \ - filesystem/bin/shutdown \ - filesystem/bin/sleep \ - filesystem/bin/sort \ - filesystem/bin/tail \ - filesystem/bin/tee \ - filesystem/bin/test \ - filesystem/bin/time \ - filesystem/bin/touch \ - filesystem/bin/true \ - filesystem/bin/wc \ - filesystem/bin/which \ - filesystem/bin/yes - -filesystem/bin/%: programs/coreutils/Cargo.toml programs/coreutils/src/bin/%.rs $(BUILD)/libstd.rlib - mkdir -p filesystem/bin - $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - $(STRIP) $@ diff --git a/mk/userspace/drivers.mk b/mk/userspace/drivers.mk deleted file mode 100644 index b3d06bc..0000000 --- a/mk/userspace/drivers.mk +++ /dev/null @@ -1,15 +0,0 @@ -drivers: \ - filesystem/sbin/pcid \ - filesystem/sbin/e1000d \ - filesystem/sbin/rtl8168d \ - filesystem/sbin/xhcid - -initfs/bin/%: drivers/%/Cargo.toml drivers/%/src/** $(BUILD)/libstd.rlib - mkdir -p initfs/bin - $(CARGO) rustc --manifest-path $< $(CARGOFLAGS) -o $@ - $(STRIP) $@ - -filesystem/sbin/%: drivers/%/Cargo.toml drivers/%/src/** $(BUILD)/libstd.rlib - mkdir -p filesystem/sbin - $(CARGO) rustc --manifest-path $< $(CARGOFLAGS) -o $@ - $(STRIP) $@ diff --git a/mk/userspace/extrautils.mk b/mk/userspace/extrautils.mk deleted file mode 100644 index ceb4c17..0000000 --- a/mk/userspace/extrautils.mk +++ /dev/null @@ -1,21 +0,0 @@ -extrautils: \ - filesystem/bin/calc \ - filesystem/bin/cksum \ - filesystem/bin/cur \ - filesystem/bin/grep \ - filesystem/bin/gunzip \ - filesystem/bin/gzip \ - filesystem/bin/less \ - filesystem/bin/man \ - filesystem/bin/mdless \ - filesystem/bin/mtxt \ - filesystem/bin/rem \ - filesystem/bin/resize \ - filesystem/bin/screenfetch \ - filesystem/bin/tar - #filesystem/bin/dmesg filesystem/bin/info filesystem/bin/watch - -filesystem/bin/%: programs/extrautils/Cargo.toml programs/extrautils/src/bin/%.rs $(BUILD)/libstd.rlib - mkdir -p filesystem/bin - $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - $(STRIP) $@ diff --git a/mk/userspace/installer.mk b/mk/userspace/installer.mk deleted file mode 100644 index 448da59..0000000 --- a/mk/userspace/installer.mk +++ /dev/null @@ -1,7 +0,0 @@ -installer: \ - filesystem/bin/redox_installer - -filesystem/bin/redox_installer: installer/Cargo.toml installer/src/** $(BUILD)/libstd.rlib - mkdir -p filesystem/bin - $(CARGO) rustc --manifest-path $< --bin redox_installer $(CARGOFLAGS) -o $@ - $(STRIP) $@ diff --git a/mk/userspace/ion.mk b/mk/userspace/ion.mk deleted file mode 100644 index 48161a4..0000000 --- a/mk/userspace/ion.mk +++ /dev/null @@ -1,11 +0,0 @@ -ion: \ - filesystem/bin/ion \ - filesystem/bin/sh - -filesystem/test/ion: programs/ion/Cargo.toml programs/ion/src/** $(BUILD)/libstd.rlib $(BUILD)/libtest.rlib - mkdir -p filesystem/test - $(CARGO) test --no-run --manifest-path $< $(CARGOFLAGS) - cp programs/ion/target/$(TARGET)/release/deps/ion-* $@ - -filesystem/bin/sh: filesystem/bin/ion - cp $< $@ diff --git a/mk/userspace/mod.mk b/mk/userspace/mod.mk deleted file mode 100644 index 4edff9d..0000000 --- a/mk/userspace/mod.mk +++ /dev/null @@ -1,49 +0,0 @@ -userspace: \ - drivers \ - coreutils \ - extrautils \ - installer \ - ion \ - netutils \ - orbutils \ - pkgutils \ - userutils \ - schemes \ - filesystem/bin/acid \ - filesystem/bin/contain \ - filesystem/bin/smith \ - filesystem/bin/timeout \ - filesystem/ui/bin/orbterm \ - filesystem/ui/bin/sodium - -include mk/userspace/coreutils.mk -include mk/userspace/drivers.mk -include mk/userspace/extrautils.mk -include mk/userspace/installer.mk -include mk/userspace/ion.mk -include mk/userspace/netutils.mk -include mk/userspace/orbutils.mk -include mk/userspace/pkgutils.mk -include mk/userspace/schemes.mk -include mk/userspace/userutils.mk - -$(BUILD)/libstd.rlib: rust/src/libstd/Cargo.toml rust/src/libstd/** - mkdir -p $(BUILD) - $(CARGO) rustc --manifest-path $< --features "panic-unwind" $(CARGOFLAGS) -L native=libc-artifacts/usr/lib -o $@ - cp rust/src/target/$(TARGET)/release/deps/*.rlib $(BUILD) - -$(BUILD)/libtest.rlib: rust/src/libtest/Cargo.toml rust/src/libtest/** $(BUILD)/libstd.rlib - mkdir -p $(BUILD) - $(CARGO) rustc --manifest-path $< $(CARGOFLAGS) -L native=libc-artifacts/usr/lib -o $@ - cp rust/src/target/$(TARGET)/release/deps/*.rlib $(BUILD) - -filesystem/bin/%: programs/%/Cargo.toml programs/%/src/** $(BUILD)/libstd.rlib - mkdir -p filesystem/bin - $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - $(STRIP) $@ - -filesystem/ui/bin/%: programs/%/Cargo.toml programs/%/src/**.rs $(BUILD)/libstd.rlib - mkdir -p filesystem/ui/bin - $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - $(STRIP) $@ - diff --git a/mk/userspace/netutils.mk b/mk/userspace/netutils.mk deleted file mode 100644 index eda3602..0000000 --- a/mk/userspace/netutils.mk +++ /dev/null @@ -1,14 +0,0 @@ -netutils: \ - filesystem/bin/dhcpd \ - filesystem/bin/dns \ - filesystem/bin/httpd \ - filesystem/bin/irc \ - filesystem/bin/nc \ - filesystem/bin/ntp \ - filesystem/bin/telnetd \ - filesystem/bin/wget - -filesystem/bin/%: programs/netutils/Cargo.toml programs/netutils/src/%/**.rs $(BUILD)/libstd.rlib - mkdir -p filesystem/bin - $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - $(STRIP) $@ diff --git a/mk/userspace/orbutils.mk b/mk/userspace/orbutils.mk deleted file mode 100644 index def6d73..0000000 --- a/mk/userspace/orbutils.mk +++ /dev/null @@ -1,15 +0,0 @@ -orbutils: \ - filesystem/ui/bin/browser \ - filesystem/ui/bin/calculator \ - filesystem/ui/bin/character_map \ - filesystem/ui/bin/editor \ - filesystem/ui/bin/file_manager \ - filesystem/ui/bin/launcher \ - filesystem/ui/bin/orblogin \ - filesystem/ui/bin/orbterm \ - filesystem/ui/bin/viewer - -filesystem/ui/bin/%: programs/orbutils/Cargo.toml programs/orbutils/src/%/**.rs $(BUILD)/libstd.rlib - mkdir -p filesystem/ui/bin - $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - $(STRIP) $@ diff --git a/mk/userspace/pkgutils.mk b/mk/userspace/pkgutils.mk deleted file mode 100644 index 156c532..0000000 --- a/mk/userspace/pkgutils.mk +++ /dev/null @@ -1,7 +0,0 @@ -pkgutils: \ - filesystem/bin/pkg - -filesystem/bin/%: programs/pkgutils/Cargo.toml programs/pkgutils/src/*.rs programs/pkgutils/src/bin/%.rs $(BUILD)/libstd.rlib - mkdir -p filesystem/bin - $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - $(STRIP) $@ diff --git a/mk/userspace/schemes.mk b/mk/userspace/schemes.mk deleted file mode 100644 index b28485f..0000000 --- a/mk/userspace/schemes.mk +++ /dev/null @@ -1,25 +0,0 @@ -schemes: \ - filesystem/sbin/ethernetd \ - filesystem/sbin/ipd \ - filesystem/sbin/orbital \ - filesystem/sbin/ptyd \ - filesystem/sbin/randd \ - filesystem/sbin/redoxfs \ - filesystem/sbin/redoxfs-mkfs \ - filesystem/sbin/tcpd \ - filesystem/sbin/udpd - -initfs/bin/%: schemes/%/Cargo.toml schemes/%/src/** $(BUILD)/libstd.rlib - mkdir -p initfs/bin - $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - $(STRIP) $@ - -filesystem/sbin/%: schemes/%/Cargo.toml schemes/%/src/** $(BUILD)/libstd.rlib - mkdir -p filesystem/sbin - $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - $(STRIP) $@ - -filesystem/sbin/redoxfs-mkfs: schemes/redoxfs/Cargo.toml schemes/redoxfs/src/** $(BUILD)/libstd.rlib - mkdir -p filesystem/bin - $(CARGO) rustc --manifest-path $< --bin redoxfs-mkfs $(CARGOFLAGS) -o $@ - $(STRIP) $@ diff --git a/mk/userspace/userutils.mk b/mk/userspace/userutils.mk deleted file mode 100644 index 9b144e0..0000000 --- a/mk/userspace/userutils.mk +++ /dev/null @@ -1,13 +0,0 @@ -userutils: \ - filesystem/bin/getty \ - filesystem/bin/id \ - filesystem/bin/login \ - filesystem/bin/passwd \ - filesystem/bin/su \ - filesystem/bin/sudo \ - filesystem/bin/whoami - -filesystem/bin/%: programs/userutils/Cargo.toml programs/userutils/src/bin/%.rs $(BUILD)/libstd.rlib - mkdir -p filesystem/bin - $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - $(STRIP) $@ diff --git a/paper/redox.tex b/paper/redox.tex deleted file mode 100644 index c458d68..0000000 --- a/paper/redox.tex +++ /dev/null @@ -1,84 +0,0 @@ -\documentclass[11pt]{article} -\usepackage[T1]{fontenc} -\usepackage{amsmath, amsfonts, amssymb, amsthm, url, lmodern, color, graphicx} - -\title{Redox and system calls -- a multi-level kernel space} -\author{Redox OS developers} -\date{\today} - -\begin{document} - \maketitle - - %%% DISCLAIMER %%% - - \begin{titlepage} - \centering \huge\bfseries The following document is an incomplete draft. - \end{titlepage} - - %%% START OF DOCUMENT %%% - - \maketitle - - \begin{abstract} - In this paper, we review Redox's core system call interface. Redox has - multiple levels of kernel space, and the top one consists of a very - minimal system call interface, which we go over here. - \end{abstract} - - \section{Introduction} - TODO - - \section{Executing system calls} - We allow multiplied system calls, a generalized version of concept of - multicalls in the \emph{kqueue} system call. - - Depending on the platform, system calls might be sent through interrupts or - \texttt{sysenter}. What we are really interested in, though, is the state - when we leave user space. - - \begin{description} - \item [\texttt{rax}/\texttt{eax}] stores the pointer to the array of system calls. - \item [\texttt{rbx}/\texttt{ebx}] stores the number of system calls in - this bundle. - \end{description} - - \section{The interface} - Each entry in this system call bundle buffer needs an ABI representation. - We represent the interface for the \emph{core system calls}. - - The representation is as follows: - - \begin{description} - \item [The system call ID] this is an unsigned 16-bit integer - representing which system call is used. - \item [First argument] this 64-bit integer is used as defined by the - system call. - \item [Second argument] this 64-bit integer is used as defined by the - system call. - \end{description} - - The return value of the system call is placed in the respective element. - - \subsection{Access management} - The memory access management is a set of system calls taken pointer and - size, respectively. - - It contains of four calls: - - \begin{description} - \item [Make memory readable]. - \item [Make memory unreadable]. - \item [Make memory writable]. - \item [Make memory unwritable]. - \item [Make memory executable]. - \item [Make memory unexecutable]. - \end{description} - - \subsection{Access management} - - %%% BIBLIOGRAPHY %%% - - \begin{thebibliography}{9} - TODO - \end{thebibliography} -\end{document} diff --git a/programs/acid b/programs/acid deleted file mode 160000 index 99b7633..0000000 --- a/programs/acid +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 99b7633a0a8b23befecb3703f1b7c06603cf7ba4 diff --git a/programs/binutils b/programs/binutils deleted file mode 160000 index ce057ba..0000000 --- a/programs/binutils +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ce057bac70f18fe7fd004c68e58c07c1cc7174e0 diff --git a/programs/contain/Cargo.toml b/programs/contain/Cargo.toml deleted file mode 100644 index a11d6d0..0000000 --- a/programs/contain/Cargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "contain" -version = "0.1.0" - -[dependencies] -redox_syscall = "0.1" diff --git a/programs/contain/src/chroot.rs b/programs/contain/src/chroot.rs deleted file mode 100644 index edce9ea..0000000 --- a/programs/contain/src/chroot.rs +++ /dev/null @@ -1,172 +0,0 @@ -use syscall; -use syscall::data::{Stat, StatVfs}; -use syscall::error::{Error, EBADF, EINVAL, EPERM, Result}; -use syscall::scheme::Scheme; - -use std::str; -use std::path::PathBuf; - -pub struct ChrootScheme { - root: PathBuf -} - -impl ChrootScheme { - pub fn new(root: PathBuf) -> ChrootScheme { - ChrootScheme { - root: root - } - } - - fn translate(&self, path: &[u8]) -> Result { - let path = str::from_utf8(path).or(Err(Error::new(EINVAL)))?; - let mut translated = self.root.clone(); - translated.push(path.trim_left_matches('/')); - if translated.starts_with(&self.root) { - translated.into_os_string().into_string().or(Err(Error::new(EINVAL))) - } else { - println!("escaped chroot"); - Err(Error::new(EPERM)) - } - } -} - -impl Scheme for ChrootScheme { - fn open(&self, path: &[u8], flags: usize, uid: u32, gid: u32) -> Result { - if uid != 0 { - syscall::setreuid(0, uid as usize)?; - } - if gid != 0 { - syscall::setregid(0, gid as usize)?; - } - let res = syscall::open(&self.translate(path)?, flags); - if uid != 0 { - syscall::setreuid(0, 0).unwrap(); - } - if gid != 0 { - syscall::setregid(0, 0).unwrap(); - } - res - } - - fn chmod(&self, path: &[u8], mode: u16, uid: u32, gid: u32) -> Result { - if uid != 0 { - syscall::setreuid(0, uid as usize)?; - } - if gid != 0 { - syscall::setregid(0, gid as usize)?; - } - let res = syscall::chmod(&self.translate(path)?, mode as usize); - if uid != 0 { - syscall::setreuid(0, 0).unwrap(); - } - if gid != 0 { - syscall::setregid(0, 0).unwrap(); - } - res - } - - fn rmdir(&self, path: &[u8], uid: u32, gid: u32) -> Result { - if uid != 0 { - syscall::setreuid(0, uid as usize)?; - } - if gid != 0 { - syscall::setregid(0, gid as usize)?; - } - let res = syscall::rmdir(&self.translate(path)?); - if uid != 0 { - syscall::setreuid(0, 0).unwrap(); - } - if gid != 0 { - syscall::setregid(0, 0).unwrap(); - } - res - } - - fn unlink(&self, path: &[u8], uid: u32, gid: u32) -> Result { - if uid != 0 { - syscall::setreuid(0, uid as usize)?; - } - if gid != 0 { - syscall::setregid(0, gid as usize)?; - } - let res = syscall::unlink(&self.translate(path)?); - if uid != 0 { - syscall::setreuid(0, 0).unwrap(); - } - if gid != 0 { - syscall::setregid(0, 0).unwrap(); - } - res - } - - /* Resource operations */ - fn dup(&self, old_id: usize, buf: &[u8]) -> Result { - syscall::dup(old_id, buf) - } - - fn read(&self, id: usize, buf: &mut [u8]) -> Result { - syscall::read(id, buf) - } - - fn write(&self, id: usize, buf: &[u8]) -> Result { - syscall::write(id, buf) - } - - fn seek(&self, id: usize, pos: usize, whence: usize) -> Result { - syscall::lseek(id, pos as isize, whence) - } - - fn fcntl(&self, id: usize, cmd: usize, arg: usize) -> Result { - syscall::fcntl(id, cmd, arg) - } - - fn fevent(&self, _id: usize, _flags: usize) -> Result { - //TODO - Err(Error::new(EBADF)) - } - - fn fmap(&self, _id: usize, _offset: usize, _size: usize) -> Result { - //TODO - Err(Error::new(EBADF)) - } - - fn fpath(&self, id: usize, buf: &mut [u8]) -> Result { - let count = syscall::fpath(id, buf)?; - - let translated = { - let path = str::from_utf8(&buf[.. count]).or(Err(Error::new(EINVAL)))?; - let translated = path.to_string().replace(self.root.to_str().ok_or(Error::new(EINVAL))?, ""); - format!("file:{}", translated.trim_left_matches('/')) - }; - - let path = translated.as_bytes(); - - let mut i = 0; - while i < buf.len() && i < path.len() { - buf[i] = path[i]; - i += 1; - } - - Ok(i) - } - - fn fstat(&self, id: usize, stat: &mut Stat) -> Result { - syscall::fstat(id, stat) - } - - fn fstatvfs(&self, id: usize, stat: &mut StatVfs) -> Result { - syscall::fstatvfs(id, stat) - } - - fn fsync(&self, id: usize) -> Result { - syscall::fsync(id) - } - - fn ftruncate(&self, id: usize, len: usize) -> Result { - syscall::ftruncate(id, len) - } - - fn close(&self, id: usize) -> Result { - syscall::close(id) - } -} diff --git a/programs/contain/src/main.rs b/programs/contain/src/main.rs deleted file mode 100644 index 0cd1e01..0000000 --- a/programs/contain/src/main.rs +++ /dev/null @@ -1,97 +0,0 @@ -extern crate syscall; - -use syscall::scheme::Scheme; - -use std::{env, fs,thread}; -use std::io::{stderr, Write}; -use std::os::unix::process::CommandExt; -use std::path::Path; -use std::process::{self, Command}; - -use self::chroot::ChrootScheme; - -mod chroot; - -fn usage() -> ! { - write!(stderr(), "contain root cmd args..\n").unwrap(); - process::exit(1); -} - -fn enter(root: &Path, cmd: &str, args: &[String]) { - let names = [ - "pty", - "rand", - "tcp", - "udp" - ]; - - let mut name_ptrs = Vec::new(); - for name in names.iter() { - name_ptrs.push([name.as_ptr() as usize, name.len()]); - } - - let new_ns = syscall::mkns(&name_ptrs).unwrap(); - - let root_canon = fs::canonicalize(root).unwrap(); - let root_thread = thread::spawn(move || { - syscall::setrens(-1isize as usize, new_ns).unwrap(); - let scheme_fd = syscall::open(":file", syscall::O_CREAT | syscall::O_RDWR | syscall::O_CLOEXEC).unwrap(); - syscall::setrens(-1isize as usize, syscall::getns().unwrap()).unwrap(); - - let chroot_scheme = ChrootScheme::new(root_canon); - loop { - let mut packet = syscall::Packet::default(); - if syscall::read(scheme_fd, &mut packet).unwrap() == 0 { - break; - } - chroot_scheme.handle(&mut packet); - syscall::write(scheme_fd, &packet).unwrap(); - } - - let _ = syscall::close(scheme_fd); - }); - - let pid = unsafe { syscall::clone(0).unwrap() }; - if pid == 0 { - syscall::setrens(new_ns, new_ns).unwrap(); - - println!("Container {}: enter: {}", new_ns, cmd); - - let mut command = Command::new(&cmd); - for arg in args { - command.arg(&arg); - } - command.current_dir("/"); - - let err = command.exec(); - - panic!("contain: failed to launch {}: {}", cmd, err); - } else { - let mut status = 0; - syscall::waitpid(pid, &mut status, 0).unwrap(); - - loop { - let mut c_status = 0; - let c_pid = syscall::waitpid(0, &mut c_status, syscall::WNOHANG).unwrap(); - if c_pid == 0 { - break; - } else { - println!("Container zombie {}: {:X}", c_pid, c_status); - } - } - - println!("Container {}: exit: {:X}", new_ns, status); - } -} - -pub fn main() { - let mut args = env::args().skip(1); - - if let Some(root) = args.next() { - let cmd = args.next().unwrap_or("login".to_string()); - let args: Vec = args.collect(); - enter(Path::new(&root), &cmd, &args); - } else { - usage(); - } -} diff --git a/programs/coreutils b/programs/coreutils deleted file mode 160000 index bc953d8..0000000 --- a/programs/coreutils +++ /dev/null @@ -1 +0,0 @@ -Subproject commit bc953d8f25da20bd691b1855bc382cdd00a8603b diff --git a/programs/extrautils b/programs/extrautils deleted file mode 160000 index 3f7d502..0000000 --- a/programs/extrautils +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 3f7d5027883169385086ea674be4127e7962e5b9 diff --git a/programs/games b/programs/games deleted file mode 160000 index c4984dc..0000000 --- a/programs/games +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c4984dc276bf5776f544b5f9f6996330e3ca4b51 diff --git a/programs/init b/programs/init deleted file mode 160000 index 032a45c..0000000 --- a/programs/init +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 032a45c55242aebaa9f6a03fa9d11da881bfcb1f diff --git a/programs/ion b/programs/ion deleted file mode 160000 index ae73d27..0000000 --- a/programs/ion +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ae73d27b07db96c6e6520c559ba03c117e048b43 diff --git a/programs/netutils b/programs/netutils deleted file mode 160000 index 074c900..0000000 --- a/programs/netutils +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 074c900be31586f405cc46503a807e7ab8a7a2bb diff --git a/programs/orbterm b/programs/orbterm deleted file mode 160000 index 4143dcf..0000000 --- a/programs/orbterm +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 4143dcf160648a048d579553ab29ba18fb47c23c diff --git a/programs/orbutils b/programs/orbutils deleted file mode 160000 index 99c5e04..0000000 --- a/programs/orbutils +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 99c5e04e24084244b5d02b29ee95041b4d02bbf6 diff --git a/programs/pkgutils b/programs/pkgutils deleted file mode 160000 index b9c10c9..0000000 --- a/programs/pkgutils +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b9c10c980e1724270b7e90d3c2d4999c398814b8 diff --git a/programs/smith b/programs/smith deleted file mode 160000 index 9e39ff1..0000000 --- a/programs/smith +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9e39ff178cf9abb5b09812b377082f3a5bb847b7 diff --git a/programs/sodium b/programs/sodium deleted file mode 160000 index 86fc766..0000000 --- a/programs/sodium +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 86fc766160cf2a0996f1ca6de6e301c35807f7fb diff --git a/programs/timeout/Cargo.toml b/programs/timeout/Cargo.toml deleted file mode 100644 index 9ca5a42..0000000 --- a/programs/timeout/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "timeout" -version = "0.1.0" -authors = ["Jeremy Soller "] - -[dependencies] -redox_event = { git = "https://github.com/redox-os/event.git" } -redox_syscall = "0.1" diff --git a/programs/timeout/src/main.rs b/programs/timeout/src/main.rs deleted file mode 100644 index baa7692..0000000 --- a/programs/timeout/src/main.rs +++ /dev/null @@ -1,44 +0,0 @@ -extern crate event; -extern crate syscall; - -use event::EventQueue; -use std::fs::File; -use std::io::{Result, Read, Write}; -use std::mem; -use std::os::unix::io::AsRawFd; -use syscall::data::TimeSpec; -use syscall::flag::CLOCK_MONOTONIC; - -fn main() { - let mut event_queue = EventQueue::::new().expect("timeout: failed to create event queue"); - - let path = format!("time:{}", CLOCK_MONOTONIC); - - let mut file = File::open(&path).expect(&format!("timeout: failed to open {}", path)); - - let mut timeout = TimeSpec::default(); - file.read(&mut timeout).unwrap(); - println!("Current: {:?}", timeout); - - timeout.tv_sec += 1; - println!("Setting timeout: {:?}", timeout); - file.write(&timeout).unwrap(); - - event_queue.add(file.as_raw_fd(), move |_count: usize| -> Result> { - let mut time = TimeSpec::default(); - if file.read(&mut time)? >= mem::size_of::() { - if time.tv_sec > timeout.tv_sec - || (time.tv_sec == timeout.tv_sec && time.tv_nsec >= timeout.tv_nsec ) - { - return Ok(Some(time)) - } - } - Ok(None) - }).expect("timeout: failed to poll time"); - - event_queue.trigger_all(0).expect("timeout: failed to trigger events"); - - let time = event_queue.run().expect("timeout: failed to run event loop"); - - println!("Time passed: {:?}", time); -} diff --git a/programs/userutils b/programs/userutils deleted file mode 160000 index 3ca1891..0000000 --- a/programs/userutils +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 3ca18917f88130f4734bcb4643a410e62e6cb24c diff --git a/res/fonts/DejaVuSansMono-Bold.ttf b/res/fonts/DejaVuSansMono-Bold.ttf deleted file mode 100644 index 8184ced8cf853a64c3aa6f9afd722cdbf597c38c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 331992 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�SrtJe5~>2AwX)*MpviU6J~VMNb0P591iP{sNJfy! z`fOEH zPe~u6%-@*5pBb1KO#lC2nZt5~fr9~bJ1BHjBB(85$7C$3#01;v1z(=6rmn`MY-%LO zC@#j7Q8;hj!})WIQmmZ3YI@@uQUrvQ6$>6MT=1w+K}AR)xjDAC-`vrfY1gWcD_4G8 zRn1~#Hl;7(KSLxxuY^+7nl+z3tyxp0B+0`c$;c4VH^t0|fr&wyfrn)q%Q^7KEd!&P zx+#l-swf+~pqRL*iUO;tnLVSKxFDN4qh3chqZCsXqj-ONd;h*4cW3k2&>h2c~$5La*B#FyNQZ2urQb~7_rP{?HPf0f|?WCrNgl>9CfoLG3gK@K?qm`6YqoXrZR`13`vzPvJ zpO?$*XP=psw4QO<>avL)MW*#;;RoDPH8jFA4Gc|9QZ#k#84pA9jQ+n@EQ?s`8O#_! zJ1ULDM8Um0Sw=7=D!?iNTABsE&0by5Or4LBT~Jxj1T;GVW~dvBiQ6$U3YrOs)2sNzMBA1^A7 zYHQ=>_sYtiIyF1Xi=P`jmSFThjb%Q|F;EX#RRlCGY%I>MZVFn{q|Ph^4I=@xFfv92 ztsrxxtF;YNM+cKlyRIB7ACsb5q*jWkgmeXOa$3B<1b>yDmcMk1k*4{hs8q&;-ah7p zB%1`LMn*Wqq}ip*F4#WST89Vq%cHGnDmUmTM#i+6P>Y6d0-Q3hs~JuK%L)WPRy7zu$o9*||zAWtfrnwtr$feJctb`vIbQzJ2P z(1{w1ptgvbx)PI7gtJK0{FK_#()tvY^un&XlrT*b1KAeV#*&P)bX!)71IUA>8$?S9xe6ouKshqd{HAm0~13e zqXSC?^Ew6v21f=4VQ_s6a+TOF$9ArmPOBu+7bkkmNy9kfsrvvU=q6 zAO%k4YFiC;LDgz`*$6*p*D5=IA+;(ybqzt~&n#-sgXFoCt8M)S)T-rVBf-+@8p5hz z9Uytejsr5OsYXVrsge&=PUe`IWv3V!r<`Qoud(OmY%qTFOk)P3o`QM9w zHyAY-C7A!6`S)@9zYqV;GBHXrYJl=QD}yrwD@z|s0|P&U0)q-e2tx`310%Sxt;EMD zDgvs`6+z3GK&vT1Cklb<8Aee>Q$|79ES0g5xTy(f)iJ2K4xJhRt6N~>E`6gb*j3JNl^=P%s@IgY;n9*EV%-G0|5he(VE=FT!BXdMJL*h^vst{o& zNa;#XPBBd}F-a`X zYlw+!h;eyW|IKAe@A~(uhe_w}7VC|ytb76j()@f!_@(*z zrTJOe7(F9ASy=dF`2?i-_@o5{c-h$gz4KAwYD#CG}ZR^*S0eLX{qb$_&vwKfH}7)B&6u?@zjEXR9(iqO#c)a zSQzg8|H1s3%v2hBKxlOw2G4N4wj;-IM#$O!`M zZ0w-Tnx@94po8O;MU6#;%|M9>oIb^w6&Xb27-0#Kjq#AA6dR|ZtP&%mlCp!igeaeo zs)MqkgQ_5}n7D+!iZUakvYY`YyQCB&)AK)X@7?L`P3-M$HB_~CwO2LS#w7Z0ri6~Z zuDFD*n1nW?i;ljbHXo0?iM1oMlZ~AcHz%Kjf|9bGl9HXWl7a+32e*=)jT5t@wXp&Z zpSGca4m0z=J&fLrLTQnysgY^_-l^IsJ18kRD4Xd1d pe-)04I)709}B|-1~wK) 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 z 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 diff --git a/res/fonts/DejaVuSansMono-BoldOblique.ttf b/res/fonts/DejaVuSansMono-BoldOblique.ttf deleted file mode 100644 index 754dca7325de222c8dbdd1f98ae2c1401f882a42..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 253580 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�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 diff --git a/res/fonts/DejaVuSansMono-LICENSE b/res/fonts/DejaVuSansMono-LICENSE deleted file mode 100644 index df52c17..0000000 --- a/res/fonts/DejaVuSansMono-LICENSE +++ /dev/null @@ -1,187 +0,0 @@ -Fonts are (c) Bitstream (see below). DejaVu changes are in public domain. -Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below) - - -Bitstream Vera Fonts Copyright ------------------------------- - -Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is -a trademark of Bitstream, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of the fonts accompanying this license ("Fonts") and associated -documentation files (the "Font Software"), to reproduce and distribute the -Font Software, including without limitation the rights to use, copy, merge, -publish, distribute, and/or sell copies of the Font Software, and to permit -persons to whom the Font Software is furnished to do so, subject to the -following conditions: - -The above copyright and trademark notices and this permission notice shall -be included in all copies of one or more of the Font Software typefaces. - -The Font Software may be modified, altered, or added to, and in particular -the designs of glyphs or characters in the Fonts may be modified and -additional glyphs or characters may be added to the Fonts, only if the fonts -are renamed to names not containing either the words "Bitstream" or the word -"Vera". - -This License becomes null and void to the extent applicable to Fonts or Font -Software that has been modified and is distributed under the "Bitstream -Vera" names. - -The Font Software may be sold as part of a larger software package but no -copy of one or more of the Font Software typefaces may be sold by itself. - -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, -TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME -FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING -ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE -FONT SOFTWARE. - -Except as contained in this notice, the names of Gnome, the Gnome -Foundation, and Bitstream Inc., shall not be used in advertising or -otherwise to promote the sale, use or other dealings in this Font Software -without prior written authorization from the Gnome Foundation or Bitstream -Inc., respectively. For further information, contact: fonts at gnome dot -org. - -Arev Fonts Copyright ------------------------------- - -Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of the fonts accompanying this license ("Fonts") and -associated documentation files (the "Font Software"), to reproduce -and distribute the modifications to the Bitstream Vera Font Software, -including without limitation the rights to use, copy, merge, publish, -distribute, and/or sell copies of the Font Software, and to permit -persons to whom the Font Software is furnished to do so, subject to -the following conditions: - -The above copyright and trademark notices and this permission notice -shall be included in all copies of one or more of the Font Software -typefaces. - -The Font Software may be modified, altered, or added to, and in -particular the designs of glyphs or characters in the Fonts may be -modified and additional glyphs or characters may be added to the -Fonts, only if the fonts are renamed to names not containing either -the words "Tavmjong Bah" or the word "Arev". - -This License becomes null and void to the extent applicable to Fonts -or Font Software that has been modified and is distributed under the -"Tavmjong Bah Arev" names. - -The Font Software may be sold as part of a larger software package but -no copy of one or more of the Font Software typefaces may be sold by -itself. - -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL -TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. - -Except as contained in this notice, the name of Tavmjong Bah shall not -be used in advertising or otherwise to promote the sale, use or other -dealings in this Font Software without prior written authorization -from Tavmjong Bah. For further information, contact: tavmjong @ free -. fr. - -TeX Gyre DJV Math ------------------ -Fonts are (c) Bitstream (see below). DejaVu changes are in public domain. - -Math extensions done by B. Jackowski, P. Strzelczyk and P. Pianowski -(on behalf of TeX users groups) are in public domain. - -Letters imported from Euler Fraktur from AMSfonts are (c) American -Mathematical Society (see below). -Bitstream Vera Fonts Copyright -Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera -is a trademark of Bitstream, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of the fonts accompanying this license (“Fonts”) and associated -documentation -files (the “Font Software”), to reproduce and distribute the Font Software, -including without limitation the rights to use, copy, merge, publish, -distribute, -and/or sell copies of the Font Software, and to permit persons to whom -the Font Software is furnished to do so, subject to the following -conditions: - -The above copyright and trademark notices and this permission notice -shall be -included in all copies of one or more of the Font Software typefaces. - -The Font Software may be modified, altered, or added to, and in particular -the designs of glyphs or characters in the Fonts may be modified and -additional -glyphs or characters may be added to the Fonts, only if the fonts are -renamed -to names not containing either the words “Bitstream” or the word “Vera”. - -This License becomes null and void to the extent applicable to Fonts or -Font Software -that has been modified and is distributed under the “Bitstream Vera” -names. - -The Font Software may be sold as part of a larger software package but -no copy -of one or more of the Font Software typefaces may be sold by itself. - -THE FONT SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, -TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME -FOUNDATION -BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, -SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN -ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR -INABILITY TO USE -THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. -Except as contained in this notice, the names of GNOME, the GNOME -Foundation, -and Bitstream Inc., shall not be used in advertising or otherwise to promote -the sale, use or other dealings in this Font Software without prior written -authorization from the GNOME Foundation or Bitstream Inc., respectively. -For further information, contact: fonts at gnome dot org. - -AMSFonts (v. 2.2) copyright - -The PostScript Type 1 implementation of the AMSFonts produced by and -previously distributed by Blue Sky Research and Y&Y, Inc. are now freely -available for general use. This has been accomplished through the -cooperation -of a consortium of scientific publishers with Blue Sky Research and Y&Y. -Members of this consortium include: - -Elsevier Science IBM Corporation Society for Industrial and Applied -Mathematics (SIAM) Springer-Verlag American Mathematical Society (AMS) - -In order to assure the authenticity of these fonts, copyright will be -held by -the American Mathematical Society. This is not meant to restrict in any way -the legitimate use of the fonts, such as (but not limited to) electronic -distribution of documents containing these fonts, inclusion of these fonts -into other public domain or commercial font collections or computer -applications, use of the outline data to create derivative fonts and/or -faces, etc. However, the AMS does require that the AMS copyright notice be -removed from any derivative versions of the fonts which have been altered in -any way. In addition, to ensure the fidelity of TeX documents using Computer -Modern fonts, Professor Donald Knuth, creator of the Computer Modern faces, -has requested that any alterations which yield different font metrics be -given a different name. - -$Id$ diff --git a/res/fonts/DejaVuSansMono-Oblique.ttf b/res/fonts/DejaVuSansMono-Oblique.ttf deleted file mode 100644 index 4c858d401ad72117f18a29a9b5b9348ee7a51aba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 251932 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�zs&&a6A*Z``FPw7cstycCik&6a9z%WXV8CDaY7F78618R-^96n}M21W+Z zyyO+utDtpzkcBUx1!cyHpus;DWl$k)WG1Ah%=jF%mJBuv`RkgN_P@)&OHWNb)w9c_ zp%*^=`1tnSM}Jo^{hPwbHJO3=|2_r=mVWSBGAZ!bCTL|Rs1c~DXe1^8ImDeolMys1 zCe98y=2)AN-I$&6am1JDYx8UWB{A+kePPF(+SY#u|K0s(Noj-niO_+}H z-`7fvw$+`hm|p!A1L0No&RLglS+S$sfsuI$xWBxNfdRA+j)4tS0w^;o3M(^R{=4cr z(|Jaw$;Vj5f4u~akufm+{}0+{01guc$ofz43Ae(?lc2&NcPbizu18@~PMf&+a9u}$ zN4Qz#$t<1Ryt3-kRTmX5wljvEe|(-*|L?oieFd3+C-G%%1kHZVN&4H#RKAR9$L7V` zKY-i?>d%7a+rj0YngSbi)D2_@JC|1nD{cwHT6C>5L=KuZ(&nP8XQv9qygGos9>s_QW_ z{@7Af*P9}|zxPRY3b}(}FcC*AF*GG)< zjBCKl7Qt;Mj{lEY_}D;eBGnlfkSllaL>1I3&^levga>#|5VVh35wY6%olQtM%8KMe zvTC^nOF)~&EG;C#H6>`}F>_Fmjt){)4qMY>(*PQbU}OmW|CmLJr5ZG+1)3LE5Mp9b zR8oVU#0*}g$;Qqo8MG{jk>y49zj^=u1Ws~QwS}x^ovGHBu`zG2ObAkuB8E*HzKY%PU}WWo3Xb3tQO{Ms0oN zf185(ge|@Qy|r{<&InO9UdYJ9C^UDjppfz!Z86cpqJL>c?Ccx9?FFUb&VOMn#o+dp z3Md|+oi$crV@AYUFndt14%Bo3tp*iiED3hHI!jZ_^(v!N!M1;ACB!8>*yJo)jg8gh zO%|$ZK=x~Cx?W{;lU0k3ZLyGJ^)S$vyuV%Av^!wS1XEK+p3MQ-!f@-kVSTyZO~^?c zd@luPJu_%5mO&KMFAz3^EO$kUa!{AifECOSD0e?yIMOoF~$96RQh+|-mp89s1%-#W@LS7YVvQ)%E#KpwTjX^Vq;EbiNX3qFOQ;nDT?=wzeo%9CAZdP%#2^03ObvNc> zn#;kfK0nAmFhnVMS>TyS5#EhGvT`EA0gCd5Ee5*k*SgNzS^S&hsvN~MA))Nw+eHf} zrq5yAt*)HH$S5ggvQA59jeJCP7^dym(ez44Mbn z;BEr5KpDmy)D{7?LO^S1PZgOO3rR5wUkr?hN>NA-3GwM#%E#ki-@Z&{{0TFN-vk-;hEPK=imq`OBnxO{Qrt&IZHKz69WTj z?h_YdM~!QCb#^u;zBo-SQH83?1NJRWN=A;3-i?0#!u+Ntg=I1|X?FJ9{Q3qN7B0@g ziox#gHgkRL*baBe$_WemE65o%>+7h0WMs1?!u|e^Y0a>>U&P4f$iT#~;r}(3aF$92 zQ3h?$3?wrXD`?giJVOWyT{}i~HB~cn(4reYM(_?9b~a@;P+`gR`QO^0aK_*=M_)dE zL#gf#xz27iH(6u-f5&5|t_=y66=_S4^%s#XEn73i>#dU?^NoLT|C|`j9K8I@?n zp9jk~@S0yxY6m43aDD?-WNhq62maeLL3)a2493!o>`H9lE+lg#yIM?ao1vVvrKX1D z1;gg%Gjn0oPG4ibI3BHy)H^4J5eL72w5_D0`?^C~FF%mz)>3)!)V3G{*uw^?_I{_jMx7q-Mj^MU++H;mNP6d3|tIq3=E70!mLoMh1tN1 z;=nsu%;1hQH#0U+WL_Ec???NNfRv8B zW4d2-(5b&~Ou^NmT}o=*Z4|{ z6&3zVD=Y%lf7$fY*APG4ma<)BRWfFGA0OvGm`an-3Wa zZ~m?M_rgfx>KSPxCYygw{|>xhVg1M$#<-qI_FnKkK5F?P_Zax+yncF=lqGsa*4Zr;4ZSa$OtW2>V4zlZ-WDJV0VP2mx#E)?Zq z@?sMESIF4^_x{J_%a?CVm}i}lVb8$GaOPhS%W9T524MyU(3}*c>JT<&R2BxMAGI^> zJKAOa3!2s`R`2|Gd1r~sp29UXj4MEAxPaEhGFATk!W5R60$Lc$$e_x=z{1KV0$R_) z2;SW<#typp9Mql#F_050<4k6k-NmbGb=r5f!m&*g_7B-aUY`EPvE<+B{(eT&C5)M%_4VQm49vS( z5UggI;@9a`HSM~gV52YEecS$)#?aWF$#$?_9*Q^e-3XKs|@372= zo?8MP834J1k%xJb^uNiA8FQuoOuyHP!0Cqn^t%qTQy3 zDTU4Q4@qF0Hd(`d&Xq&QxU50--8OHi>rrnDFqC;Zb^>wAS|J{4w({NQ)suG%2-c}xQLC@wg)~m=6Hx$OuFur@w;nVq%+&a|9<*Gasqyy$ z@N#_yMh549rbO5YD_S6Sx?5ti^WWL!IlB4wxGnv8okC28U|~drf*xqs0(`XGC!G16 zhwH_E_y2yMawrSD(NKh`5fmPO>zNus;Q<{j2aknG{tIL2W~m0P#R9D|gSy9D7=9cH z$RQvXv9qx=&e!q}=rECEa#mH7ySG!()z>Ftg}uFQ%g$zb``G;8UkV(dt(keTMS$;->f76b=;D;Xk7Qqu%->_x^qOcWM0*mg+y1%j2{^*a{xs;Bv!r#l>D#ks% zvCb^j|1SM|^zY%n%Z$2=@{Dqma^p8_h|m4|pv6Bo*Pnrj!Igo5{OO;jlq!bJ+wbWRI zm_$^U%>DPSk1>GJT9A#2Q&4w%p07Wvew%N;x{eW>rW`X*f=GeWa{Ew!?Va1U?bP-U zwOuK+Ks%PHrhk(wm{KF3{rl3_+}zhT^}6tCP%+QI%#i#qoTZjcm;tnt+!(Yw z)!dqi9lVqdv|E#((U@JE$=nz=u3#<>+C&EGsW1wI_rQybF>U=I|6#`m`45J(J>$$R zW|S@0hYIMg@QJf9pIN`G2WPLha%-wTzWm^Or37BUL&b6o1o7r9LcK z@>aZh8YmX0SBtOsb4bc5@9MQ&r$5)3JtRDHuU*aaWME|2{QoJ70;DYs?>`BHMykN= zJ9Rbn8`8?kI&;#~Rf~7t+NtE1mfk8XCN8~3h=VgVZ6A~0?*;49j0~BXSQ!`@y8b_9 z@nYiw)znC4F)EwG%vvX-q^vVPB~#_-&VN^SD*2_SwF--iK@7{>&HUr%H<)4I@+bXY z81ogD1kj8al6lPhD8nBJ)4OGqRCMN~WvCYKJSfQ`Co7w2DDSq_&R&y+5!EV?yZ4{U&Ou9- z@gO4bAy%dC|GNq1g(=JrknA)7?O$Z6W)Otz(F0oq>c}XvgQ{Ll&D7K_7v*+m8R*It zLEB21Oi!;QCCo7}n(=p4KX^{ifPsPe9@GqIV++>t6BlE8S;CkJZe-<`$Vp3Q@0Po` z#onIjDM&L@*enBsISEM&ObomX49u@t5*Wlly#`QESX@|{Sq)T8gN{If^c#_m7GOGS zqNSx=bT~`X#3XTL%+6bkEjMFg6hwOdxj7vx_wW!9FgGt};uSPAi~DzuQNB<`^`AOR zLO|f6%pS(M|JG}32Zv~Bf!aE}3=Aws;P!%!ZeV9q1}y^v7Z{+``|NCtU^duGOt(`* zL=>uOZvLyewKHaAqLWkTt;4U}?HvA|KUVJUDIj2BR(^~rSh^>3QD6W|!asFYl|n}O zf9K-N%>J2cX@vx9YlGW63`PIKSkhRkLFW-d=4e2*rMQ?p$m<}cvXVX{a?CS}fp!r< zN-%v;Y6Fk3h_R$8xh;(9^zjwo)za#-+2iaYE!W$7BPw2mNlr!JeRhf#eSWJhL%={gQ|)mpO&vr=bY$hK^7ipYPStfH5b-5h>& z2s4YF{J(iIYIiVu?za3Yr#Ih~yO2srT=vnzuNHqgc+W8~0cT(h~HowFuSOYHMjx&7)+sayYD z)Y4?++xJpA6C7|Uy80rsj2#WckI&9`NVsu{W!;vTu$dZ~=?shv%l;i=ac4;Y^&7#5 z+X;jA*_nfeu0XkvnTgBpUz`l%qB03@@WDQv>Sc`DGXJjH{X4{H*Uyvy-m&v{LI1x) z42+Bp|H4@wvCadV1=bC1gu}Ki)!Bhh3OWfl>m<_oK)=6(&0^u~XS8Er`hWKSV^#*1 z1O{v~pkjuWz-so4nv9~*{h7uJ>ymaPFJ4?c{Fks|t#$DP~A>q>U-HZy^*>bY_h7sC~TNK{JDJe?n{agLd zuBcE)*2BA-dC!tNu9^Am^A9B^&6|{xZ+~Y=N?~5d>wkA9PI@vqI~TMcc@hHyOCfY` zg(AcrZAS3sAMoIZxR^a7bTCX^jcEm=6V#4}Zd>i`wen}nFa~$a$;zdhOaME?BG85T z7SxV}glpi=fWfq^BIB>}XS5Uh@wQ5igN!4f)|@87(&eE;T8VLZB)pRr^ubJm|}Ak32R zCyRL+XivdL1_qYhY+RszFC#45@q-o_Fe)>3m#(RqESKYx+H3=Ax{S!zN3a$#f8Kn%08@U@#~7~60DeVleWjivUV1>=do6aIc? z;syDMq3&N8i!h{p0op61h+O_bR(xeMEm!y(!z8I7%gtjgEoa)UrLD>G_oX7!l7HMR z2`m2GUJfm}L{>1Xg4=~I|0l96Vo6{S0gcrwvau_hnJYrJpfMT?85^;)DViIAa;P#J zlLs%)Odj5U(-fHlARA8pY*<%v`>~$NzfGJX>$rs6B8_dVO;#|gPG0fnHlxC~y_3zN znLy$6<)07B6lnazH+X=KqXCb!LCS1xMu@FU)mf$R%@%P93CU{S`*Qac7RyNbf;JT~ z@&8SgVa`%uyknu2o6&Xm6I!ow@(Knf2IYS~EZHmx3@YG}7X@=OR`Br(pvn?r39Qr0 zF2=5Grf$H_X08S;i5PwUZB#d6)ciI{1hnU5={iN2jsG|@%c31@rNt})6=n*^O02Ui zIod41Id5O#KcBt7Sy`;L3|qZG9oxx}E^m5wVQA`-APd3DUs~S!-k@<3bde?y^s-g1<39Y(8m8m_6Kr2g(Y=-HwT0Sg((JyhJ-Q-=Y*&zHnnf4KgBFpap`riY zW`(J+*r9mm_XCt*1oZ*q7<5^RS)3Sn8Kglgdq8y&q@n{Cji4QHkh7bV*uhIe!E$_{ z!Yoc}=Z+hfYpXT2{!RTCP+R*zCMb|m>Wz$aU|?5oMa2nD4Gn!gX=zSQ|2S!BCetf( z=FXjS<;K4YGiKcEO-?@6+m)7WACQL(jvCD z$$5qb;&PRh2md8A3H_U4Y-S&0Xv}!%-wSOmd%dugQ#vy3?f51A{7Pqqgn-IOCWfm2 z*I1O{a~DeNe2n6d)AB$Ti;Een2n(r;F*C8Use=l2J4SQR;V__mmrU&?&OUOmNefqg zeq-HI#*py9#BaV%|Bfe5S{ob!o4zP3T{DgOhMDawbGf;4W`14{W{iyc7#9^!|5x#E z#UVSU@USWAeKOL0=~KePKw}Al3=E(uG*2HAq?AyjJ;yhXb{vG?|8vQiXWM!E|L^oQSw6)Ltf8#lMm))qnIsm#i=`DE$j#wP6FDs;0@n z02=WJjVTI&5&~%A6%ilojLKY$;$lYTW-_!FdwbW%T3Sk|fg)nR ze7(P#n(V)GyWab2Xxt79_1Dn69l9dLz;MwbCV@qZ3=L9_K^n$0f8JtQ@-M5TxVVII zT1jy+xEutnaq?jk0-x^#3Np}`04VrS%39Fy0cgRKvbixMzA{(qx%_jpQ>IVkpJFe2 zuPpiZhEW7O#sw>XRY0p$aFxE+jG(9mpH9!jriHr{wsU(b58fIm&$#0Xwu18CESSv< z49x#O{eR4IpG|~;ok0OqZVG|ckP4|Ov4Tdw*g^X_wHYD92TY(vqvB%X%#6$ZE!I!+ zw^+}}U6vQZ#I5-E2;+R2zh4F86ir+m{ThG4A8#Yd3Qf2z}FYEbp#%a&Bnd1KW ztoU<#@`^-bLq-=S0Y(=?1K&TtnOQ;oMbUpgEN|FE7ihqw}#%@Fdf<5!F_t(*^*FPjBtahC zAmuzIWofw`jb`Si<{X6$PMT$bGJ$sac8_Hqmr2XHX7d~8TKT04@QaHiDJR%T%CD%l zO$T?OLqZ%p75Q|$eLClC6BJZbn|}#>TEo9X{eKs9`uUogMh1FosA%%5Oa*tLnHaAB z3uF1pCc>Z!p0!|B1f>Z0;0qi4ux@)sP#FW7%rKT_6cPrlZWl9VGPYxskM z8G+`y)!87+o)DqU2wf1xu4XP|t_(Vsh>73siB#oWV_iKpMKv8QgPg!1e^n;t(9$gi zDklsz`1oQ(B&3BTi|U;r;mydbpc~H3=V$v$&%n6oZkd#j5pfnKsRzw{OYccIJzJ^g-vE?p{4JAR`$vcK~U71pa@_{1==K%t0v`ykrc#NCuLY zL4yXMb|#?;9s0x49P&;I$v%m(p$+y6%_M_CmZctC3&g^i^dL5NYA zn^75s(_Uiup~L7y$-lFmCVx78N{rrj8oe+1cMim33jHU}_!5Nw_A)X3{l{txVuLV* z5AFjhFsxzwzH}J2aD&*$!M&>bU+EreZLopOffTlesa5z@q-F?a`u7;~#v ziKmdQUtFV*Yw4;ICzBel%48Pyf31w=k&)Rk|K>5L|66Tg0orW{GOLTZmGu*Ny@E05 z%0N8p6^=84jgmw%K37oO&bDZQ;3OwGSwWULmKJSI|JoSKBO|h6{>@`D3@$e_3zwDw zj}b93Rx!?H4rl$szzs?VjK)ZdfsEOenKqZyh}RV92+BKI3#=)TDrWirx2Ym0!Yqur zs0ox_85yIQdYDUC`N3o5kSYhXm>jaoLYz54NJl2AUeuwqs#MsZA(%&2kYzp>XJPig zZA`_9mgY>%pmrN$EK?1087l+W4CqBLpcxcUou#JEScqW;(;JW(j9!0x6D`e|nZRaf zG0tUnW@P|}8Qcu?nGUFlb}$oj_?QHRg`DLCb&51J#hDm|^&3KXWQ5@6U-jS)la`J! zGppc+*u=!}g{g=6E-M3cOdc{et_^BUg9;z;yc+7*_yz}aZXqAv&M#FZ##wfnnkKE) z{W@yu|CZEx>*#WFDl2=}GT-F)vyRr)Wh(ynT~x$=;c8Pkx&I8}68d@)k|4h^oMGx= zsb^&XjaQ)*0%u^^{%nWI-wu}lpezo;@NCY&$nb}8E{g~&12}eJSKL63u`yjg^Uoflc7bktg8$`2M^x@D7duT}KAO z;0yN{mCYHAnVC-i(PZSCwTAildB(bbO$>~TQ<;x5r-RLAU^HfDR2F8+`lIph)2uaY zBIo}#G1f8s|Ihe=)f``XJ#oJs9)SO}LWqHTK!j{Is#t`Jd$HL0g#L&pj!pz9b#Ktag z1#%Jkmp4Y11`OUCI77TQ@P$N2>}6p8e}I9Jft`V!!NEe%+#-_EdjoF>NSwg|BL4pX zMBG?dS)E;(>Fnest)&m=u%-R$`1ldxx9cqLSp2~DS~>8sFf_3;LF{E?LfC8bhLF9= z%*Nv8#>{+^mo%3@oWt^tvEnoM5-vu@cg)Y39_RhgBA!TSGzw1f6> zXZ)MZbo;-)02|XbQ2t?3|GR^E(|-d2b_QpLq#vh1VvKkH?qFd7icf7=)s8Lu(jV73OUV_;-fWb!Ct zOa;k;%w=L_{KxFaqAbA9l<=FM2ic%M0vsg!}4fdSO-VYdEfC&ze*@&2^` z{~52cYO;XtCSwELK==PYQ#q>(b1s{J02}yZd?v;ptePyc?0yW~4B`wK4g$=RMbB|g z=9gel;_+lt5|R+O^5)MQLk2Kq08T#M8+byZy*F@!6PN@zAxSVuKob&!_XhqD?+t<= z6+$3F7^^Zy6VTc|@TIzD<|3fgr=}*LgN~RNML0NwhdVe#R4*tloO^~86<`HxLFuE*qJ4T__zB(WMC8Hkbz~vD>i?w zya8SC0=j@!$Wl-UoH2MpK$#MhA!WcBQieeWnjsx*IT^UPxVX7^xOn-6`9=6e`NjCf zr5L0brI@6crC6l7q`9Seq6SGR-q4;h1NU#6$} z!peeL`W&@_MUmPrYWkuIf|`aLwSt9_I!>$!hQdPLejStK)%3*#{d_wo%Yw@M9W3uy zKzC2DF@e{%{hQ8sk2!{g16-%6f>*LwGqQt*qRmq5>}>2T=4R&LA_TNb22_(Xoo!N<{Pgduq{`F%os%DT z{wrQ9&D+)>Aj5p;=axoh=Jo?08TB7L_}8^=hOciA10&-cra8 z>mwOqgO{L!9kts7S;_(JutP_iKy?9gm$0s}k!6^H0Vlh(bfkKPmJYvQM0lr#jkTkw zwY80HP!b1+v_!UghPnoyU_d~VgSj~?Z=x7Cx44A9iioHXhlG~4Z@95B7ng9h96!I2 zu9monIESdFmS=>4Atz{=Hv=QXRi-)2?^yXkWd|oCxKw8Z1swCcf5*;s&imWR7<8ax z!gE&sf9L=0`}U2|gHikbeNcLDV4A~xfQ<=s>MN+wMRGUfG;!##GL|YV4qk(?M5EVW z63_~ak#RZ$1B(`G1gP{>1g!#PWSa5eAHNh+<-cz%7dn2e0J$L=s)n6`0jx&Yn2~A5 zmVf+Gj2~?}{(WPf)4^y0QVCKET5Ae2kDY;m5xneJ(VSVUqT}DUjtY>mADA+JtzgOk zodCed0J@6~O)b;AEg-cvAj9`C&-t~2(FCG)In)iTpfPM?Mn!X`O&>b`ef!%k)xmP% z*NP5M9deiXI7=m)h!7jwVNe;)aPS`&Q`3J?n+JT>5#v#ocgz8xHW_HV?f-u!dzN=B zptEGyK)V3{|A*D(0&GkvApMNcvPOUnd>c0-td3(~W)O4WWIDsZ!oJkQK1{DV`rezFgVGcb5cIcNk1`H0I4onWr0ZakREU}>R zbEXAnHP5mMoB_F+aSN*(i!P`xVgTK;%*eQc>-88xv?A zj)@UkPJ!<-_i*50V`^eyXyjmJXJqCOxN-;7@DTW7^Tx=)K~tVZo>iVro?V|spH-ht zpWTSTh|!3}h}DU~iP4G0i8YKNm@$+klvRW=meCkAJI$!fv|;bROYKZPNB`|<2Q{D= zEBuONrCvSl%&zV@m_Op8+(dtthO_%w*KkzMhGpv~wEFR>lf= zy?;kQjj0H1N-={0!x;uf#`&z8EaGe);PyDE_y=9S%B~DrOv=X2xIlf^go%#E%;k(h zq2YN_teX83JS@|sWqrK7d>9xRuQDHJPGwa9yIon>nCZy-f0LMxGe&~)<332cA2e^y z$fRs82HNDy^vLLwM80&s;YZfP|Nd7qcm4x;gb~(90IM|z&8HZ%D=~gB{AidjT_FC6 z_3*!cZJ@gVLHUMxHQ2uljK<8$Oc!on0JlvU{{JVk-Nwk+@RyP4+rQTgpmGAdLsi+F z$y=!-zC(F~)IY0@|HL+e^F8CWzl_X2P<7y4rpD|{jUaVO8>Ihk+Q|3{s;+~zjk%A# z091~F+gi#@um8=HVtf_f!S$4k2SzXZ`IU|#n>PX5XLFuCIRw# z7Tj#ioUP2vY!bP#2Jy@p<+|GDW(s!lYA$kB#ipPz)%(ZAWcB|bxE^I!QUe`CX$-nw zMN~wL@w;$rM3PUeu(7t8;lG@ueEafX`y^#OM`h6Veg;OyoWGlx3!(l2-_vSt%yeL* z^gl7_jY=K=tU5Y2LgHfK-%ZTRpz1&;%qp`hGX-yyVtggFQMuz^GF)BRUq{dYraRzoNfh%Xu z2%Irw*eb%!$ISxe8nB9h#;zf$z(|bU2)toki4Am#UsJMA3@ACo#76!!PBJn!PB3^= z9_#>46#35r9hL0@os?}sX_H~y-$zV#|E)ps!fMQ{%;^9A-=w4emV@QC{VQbx&D04q zs5uC7vT^ZFW@BIwVCLc!7GUNS5x8>Y&JobP!bojv(3w%7<~wAQ0?0+`Oxmi-z2!P_ z`jQ%+3eMiLvJSB-vAO*Gjl#kQ&ti-Gc^WnZZc*QH!?S7Vpn2{^(ncf##kzlk)~57n3<|u=6d+nu~4zC(X?Ke=-9bgNy?&xW5bTW+QcXuYkI{jF28Jz9}oq>^|^q(Zt z>;D$S*W2R8(0&xW-mXBYwof3}+Kdbi|D>6A{I>#^P0A*wCZO%!Z0z8k0H`Wp+ET8n z86KK1Q?9;i;si(If6{F1PD-j?K9HIKTxKvB{F7w*_TQ92nqfL+eItsyKjidq7+dl5 zaQ?+%_He*?13GSiqfK__je)o#yJ9Q2Np^7x=yZvHvMd+>K%*!F_W zvtfM0GL@MJ+};LP3+ignUKwPDPaM2x$BbnvX!}!Cx(JthlCl5HP^HMZ!KMi=+`^f$ zZc~|g)>)eybFnB&fcHd+$+L2q+cGdR^fDe{QDe#g<#9$)MN<~FKN(CJOTg!2FfcG4 zVYvvA6Esy6Wx2?BWXTc+M)(;u%nS_T>Wtz%zAQie5`0)L_%blU&(&dOU|?5g6xWYp zEe>;YV-xoR-IMo^i%A4pM;U<*w*_A*2f8>wnNiwU+uX=lI5slbC-z^Cims!wT~fYX zd9VWmBcsW`2Ijf{Pl56^qcFIFVrDdT=u~4ARqJ&4*TCp?=+M7y3`~sje>s^qfy)MV z(2ZD%!i>U-%*-3J{@%=D^fUYS+U(-rTTE*Ik{HGQy#nRGP5&&JUqH$MRx@KGW;Rh} zP}@=2OkIgxS;*XosRTfs+%6X6$Hv6L!LN_XWj!uqAQKSCl*c43!^OkTr;W-5wQU&~SWbi6 z`)Z)}z5qLj{4enTKO?jqCcwrt1Eh|XiPeSm2b+KZJ5w=e1PJ7}f1g=Du+C#Q2em60 zlvr8VmCaPmjKo>kmDN<4mgfDt_wW6zGCd}aS1<1~e$XpR`S+7;ouqi*2ODW=n-6{B z;4%O9t^dN9#TYz5@}NODX3>TF&UyUfWBm00 z|Noz$J*li$h1i%wKyC!xaLUrok|4y!3~Hw{GEV*%#uWK~33#87vXVV$GmJGOlTS;8 zitJPc5o3{mVcVxK$$*?g2|Y7Ih>h_(*sMAKAF~v)R12sxR5G;xZxLc+a081&)d{FE zRCcvMRD;D&|9i-+%%U#9#vljcgYSg*1Gx>fP7zDr4b*2j&wfKdo#_%oCS#ER8>sIB zJ@;6eEe$08&kkI--36J)c$`U}=^t}~02>43T-as?29~oBb$=nJ>pcXi`ya@_z;Y8R zE(F&97%UD_KLaWbQU4Sq4!)PR9x8qdto}7f{NEJ@238k{_@Aj@aqxM!|MxI3u(UwL z|3Xd>{Q^?Y*v`Pf0`iX<(`ArqW)@KN!u$h1*I5Om4s`Y)OFx*e3g){qFtDGjuDES108SFv6N^`F6Ku7dP} z&clM;{R!sVg3Jb;@yl`(%m-~eK-`!i4Mqq$Qi6)`*lEk zkb79Yz#xf%7K08KVpRs6t$37yft3fW#{g``FVOwy zU_R(3b>{!y85me@v0eqYEkWbF?2r|{!t9FXEH@SZI4Uy5{JpNor0ED^vtC`b>d&WD ze=S$70)-#=+(On5u=5aMW(lw{M}zDFts7w30=CN-?A~XP`$j-z87FAyz?>6&Xg{;i z-;?0$3ly2m{;g7E{;K%r9@Fc;`&X@Ea%6H?1s=il{ZxNrY$oNt5-!XsV0C_nxCC`7y^Zbni<>bwkShdT9ql;g^ zE{+l|S+%M}I10p$7A{-0>d#^UEtk3TT(kuKo@6o?&~lkK*F_5yCjT257+5XA?zRSn z3CJHTZ=m-XfEFo$HnB5-#v8zO5oqrkSVUY*T$nj-tG|7^z4K{jp9S^Xv>?vZTI~|% z<9yoL-ayuAE9=!i(MsVH8C@8||E>I2v46V4wN5`gdZ_zx%Cg*7z`b-h0N#`S1I)d;hlkfX;!1pRw*I06KpYeC9M0qznPa zB|EY>xU67s{r?WZm^h!mVPwqj+iRclFa^H{AVl9##q=Z zD#@tMC?&RvjnQB)FaN&>ptg+Tzc7}yED50f<-(xrJwUtI8I3{1vrk3i4CUPp$yYJH z-T${ScwaEHOWnK;e}kE0e=qnK#t2&a$-u-A586A+ro_MvI*W%9GHD8)fmH<$@2VIZ z$%DtS`5D>3M<9UOoFEK7TMK;j1=D1tn>YVufNtKDX5=}V2EKVSFbH(-rUEDI-pzRU z*4r6s%=fWfyeY^8x_MJVPf-|p^CoC3Cu}P&=;lpEa2oSs$px?B0$sZYS|Vp`WClJ4 ziXYUo14TM?LyVaAm-8-|wLwODtEeOsqb#c~E31~ixSW|Bmz2|DGdTfa1w9EF4OT`uxy=$1OFCj~ zjRbi>aX0y25cn=jSq27G@b(&ZHf1w&@J);AYRU@2LZDiVoq?H&X>p5#tGIY%;$nV2 z7h`pHE^!IVzgr`HnI`^yqr#k~@@Ji@ay_HBe?@UXxVI0hj|#FkV{a;rVahtCy=hJ(z7C zwa=W{{%FU8&RMfMSuFmQ|LgtN^{4ov(ivkr!mZL#CcmBJ(pL3Pk zoqziwVFy0r7<3;5=pFNY`Z1tg=ioJH%2QYjReIa_ zRL%Ky*`-u{RSTVzn*N1s+p?{nC1JW-7(IexKz9&pCA77&R5Q+- zi@45?`52>3+uT3*py%X*Dk;!7P!P*HmTJ%%b8PvJ33Svd;(}apF{b^HkWE^|$M0gS z#sSKH|Ngwp0iUrt$xRJ(S@bgvO%G4ZFa_Tm4LxY@VqQMTekO+M|BqQtgU{QM1)W0z z8r}rYs+g&(sX~uH1DCAEitJ2{ZPsxrkb8~QHaIYHY}B!sF#~jVfys>ik4(%e%*#35 z^LK*oFFstXB{}K&zem%jgO4rXoY}vFfsx?_0|WS+7C}%M16x7|np^|jrpmMso^8_q zO;=`~r2KDkmdqJQ&Jo(N~j?QB?vh(^F(O2IWCx(3C5vuWAU{ zg~-mvq?#iwDbxF}Naj+Wmc7FkMz(d!b>u`uO?CyavPzo-)y^@{o5*yv|L@T&NePUX zPd}VhTpiV1-jKGtY%?TmO8$khtYgVw-~#R9VN_yghHjlvHv%OIb~ezeR_Hkk=AeKB zmEy+2LduV+6KSA_U%Lpe7_Mg>>Kvi*O*M2OEZlym#{ z?-yg$-)qdAj8E(4ZTQ#1r1R&?Ke@Vjps=0&FO20WO9E(&2YeD9WM?+$bPZ7b3*v#A zm&QzUoV`*NYj)OY&70isx81KlK257`XN{t>k@ddqJz@^w%a|JfR@|7_&iF5%aUx^; z#2ZWP3Ehs2?-lBfnpQX1Q#|2ErABr zKtjwc_5KB3`MW~%*p#M3?oyL3*uHOzg$^s9Lzso8=PFN5o-lh?Ic*CMmV|#l{_d~d zneO9}y|bFhk&)xy+kX!q*-d0($`4|!{MR0o&%`v*?h&IrqcFHU0hQ(8IXyK{zgU0` z)}I8o`I^~4XRv31+LX-THXrm1c;q%B7bvOx{|{Ac_1L}uN z`Tvr|lud;Hz9$_Q#N%b$c@L0g^avWYu5H>`ZDfe z^#1pK!M}eW{G45#mao6W=qthdFUIq&j-t`B4IypJ1&-C73)xtgR{j0;uk#@f|FKPs z(;4eeUHR8^_P-q0zrUFaSy*O#1+`&2{=Z}i0=omW+XR$>)IiBtoJC#DTnMydju{+5 z>T1H`(2W?(3p8Z4(pKAbS^|kmZ}694yVxJ?v{45?9%r!CbJv zd>ISd!p>^PRb1XnelylxIq|RlU+uB0S5Gj$X8aeNHD@m5j4RNcBdb}jg3=u$8#5ay z!I`NusjIP@n~Ae93xSSL1~s0U_ct`TDb$^=Qx?<;$*NThoW#h+vj2UlSw^TqQ4p)3 z|G!_oOaGQJb#19*)Y3MQS|uTE@UMum(^SeZeoBah5U8&F2P!{SL&g>UxPoI=1|$yd zL$8MPE&l%k-Q~b61MV*t{tIKt1mD>#$Dj^6I|Q^H5>yRcjlwo1IwCtclv{Qzrin&bezh#S}ozk>a%%uN?F;14K1RV>) zx4cY>G4bDgi3-q>A)l64NG=t3&%3&(-A(e(US?-8&)jP}yIdHUKw}Clx4~t$9B2g< z8#|M+k+3n7xtXw;xfnZ>s+us9vI4Y5X5RRBgR_ZS$cFG$@f!ji4R;D_#r%8nRwVh| zzZWIOeoiVZ@hZ$KCj9-kn(^{KZ6-#>kiQcqe*b%)k&)5(-x(%__cM3w0PVm1_phE+ zj3oioXJ%zmWfwCy6J`UoWg%V%-2@C?LBh`n-o*e)$n0$9X2PK5)XZhw|6a(?S^i)` zfn^^XXVZd8KOV_>52jpl;NbgE9jgNpTvRM{hPL6L6mPAlR{3$%F{J1Aubam zYyN%DDd>5pBxw5pNsy5Aao z3uDO#pJ@zgCm{7#K&$J)r__QQp6qN)k9&4&YNhq`?$Xjs{qDEJZ;@x5g*l@kGK#wt%&39(3cYe7QX@>O|kfcx>aj7E&9imck@Gya|ZckbVX5Yz_y z>3NKE8S~C=Tm`BZj{FN^IRM%B&uFfwfMUBk8#}C41XU8C^{y-n<^Rq8_hrdiOS2cd zt;8j`+0~6)`1uznMu~~LIJ6{rdT44EMIK~6GN-ZQ-;IB7K&Stjsw(TS`gn&26j%6r zF)`)mUA&SL3K~0#0iACI9^cdi)gAxc|Any}fb0=a1n&z_Q)dUQ&jxKbQ8ZVC?6rk< ztJvAt86Ct@{KE}mwG}jzEZ0`7k?CY~l=-*cMl9N`LdQp5!64pnRq0i(&kGmHn6eg9ry+EB09vgF2ze*ypQ|LbIo`v$5^8UJ7V z|C8lCO9FUQg$Y!QfC?GV#2=_a04=XG7cw`46fxkz7EtA2Zf4GSe)5C)Qarv@3!1pt z`Ya1{;;P^Ca@t?QD#|$X-}joxi7p{6HK$i*T zqW_OsN?5AF=?}b_iXD7DJa|LBJtJt;LqS~)c0xBxu#$3I*7nLmW2U7tf1~+*gSR&X z`6~wHWdHk8SD&+c7b8zmYtNiG)>n=^+=W6m5g4jyotU@-sx zn1z$28g$N|umLDN7%Pa2F@ete)@L*arvfu`MRU;cYM`$F8wD-RqEtp6um%6VWT*Hj zx_UH#9Pu|=hG{9t5m_1P%8wgU6-Y!DY_^P#fX@ zzkgvY8Eo=GYzzlLe1_uxk6HGxeh^{{~uvsVC81L3f@p#OT)~o-j8C!p8v#S3~U|jI)Ca8{m@h^3a_TLMbH-WW-=1Q6VUxcPn2~dkt7`z7C z7%izXE3!*L4!C3!GdB7nwo@!qF|*aKebH5<)N0Q7P;oaRmHskOtO_^O0H1-Zoevl2v(AKdT<05Y!p8h`d zKso=ytau~oa3#Ofj7;AYnd=n)Ij8BGstUMIml9jx!NXy%8)nwj@I6?N@!vy1rm3eH z7fkQd5|xQr{V$(Ych#!DpS2_eIaRrsLU;uVp8RwB_oBR%i3!|S0iE^7$_n;R8AC1D zKcKlRM(|nbJ0M}t$R;ADV9w5_tiWVy0=cJ!T@6%YE3z~C3FIGY-8k_z9A3T3o4W7d> z1BW4~%{~J>KLMU|0=J)MutUPs3>>CTAa$_$NdY#{{3HX@e^7lsll3YCC#dvL1+C*Y zGf~rK6lOLCU0lJ$qRq&t%+AHgrfhCxCM3A zK>OdNeu$NSHJOgXE~NasqR^qzDd^5)aQ&>rz`$b5dL2|&F`}mz$W}h&B*pkXP0v(C zz(1|}CCF@_9nP4OxuIP7~krAAVSas1-h6Lj|l!WvDKZ7>|1M6I9`Un80 zkFa3S+#Y!T8Z7S2paK?$%wwy8?w11H4apo2$~9c=prV$6kwN_5K9(P>S3&b{#*D^{ zp!SF&v$C)_qtfYr|Cuxy8BhPa_pi)uwH@o#UsqYRe`){Q$LNGU2g|?&THD034}52d z7cr0I;QIXl01=Mt9(PU&)WX#HXzhRxUY|9EJm%pwNuNf;Gl;k!3o%{FmpBtkR za~spizjv#9Cv`HV{j=lWpR(}udB~isIOL8P0XEQS%nXc>yuo@Ew9e5OG-t>N(ha)l z`QLxmtE+xp1)UpK_-`M}bJnX2e4yE3W?^F^A!(53K!@KkGm021g0_A$^~d`f>@bO9 z4*B=LGJciapQCn+EZU40AN+H&)Yks}m zL-HuN%mL>M4NzM6U&p|}>IAvJSecO-wE32q(HJz!3+m;nGd3~aU3Gp%$?g)y3FrUi zG#^c>Ez z+;xaDcU%ma2L`RZU_{E7ij2yPOu>fsRX_hivLUnHzk8<{89}*k_dh0h?)#<9stqm& z(C3$bfYuLy!wD=8xeE{MC(vbljIcRkP@5R!A260;-Ve6q@AZHGPlKnfwSQgx52>f& z^T&vKLI7MZ|NqahfPn#gM zOi|1YG&eU8k+^iMpn>ek3u41;=+84jCPDdCTi*iqQ*ZNxg}0ZFmgtU8~^zCS@yK- zk5u6W>sA*tTCXZ`7Mahu{!Tt43u7=>RTbC2pEt|@{rR_sYsL&N#uM$mQq0v-cm7sO z-C+!G@0I%hAAPR)|Gj_vSoTBmuQD|M8Z#>kD%E{esOkhMCGN1PbYUfA&VF#kk8!#*|0@Tgj+&sxN3GRqFO#;Ows7>U< z`T;Z_#;T-l4nC$2)IK&*S5sg&Hv_evMMc<|7#Qs~bZOQyR@T-S{q0a>D&~-N`PaEo zbJYe$*$QuIkAEeyLFa2HPkFv7{+h##+VeqY8V(e9{+swO3v?&d|Hmxf!DB9cFt|God0Q)-dlbed85 zH0r<$(_Thr#>{^W|0==#k1R&tziFV=I{$YwFtGe%y~@B38U<5k)MEs#GFLHHWKeH6Xl5#)tia4BB4(_> zXr>?r4n+mfEh`}Z)){&SnaxM!w_#lH*xbZ09t zOUiK?8rARUWt1~k(^fV8k`jE!h)F-mhmq-DK*F+B%#GFGriEwyd-U(}j|q`81efoV zn(DbT)RBitppTbTf=jz(7O4N1!oa}7$CAJxz#s)`^)rI+|6+$+k_I|u6>^>{==L-a z%MP@YkUP7BJ85_?-An`#$zdr3;vk>^I??x_lWV77_-U0PbuFg{Qu98^#3tS8cVGJ8|WTa z2FCyA7#LVSuz=6%#8%fDG4?GuzB*(@2xIW^e}^hIM|8WaaB=;2i|GvGlz#z?8^Ac{ zuL+aD#(xVL<2U~O@c%#TZW{qM#{Z!D9JclkRM&EX&d^{6?et)t^tWcmtsQfjT6Wyp z!L0e`I!nTz>&%+J7eLwsVGIl`?V!7`LF)wtz&l$(bs__N9+&}i`32+ujUaX4v%DD? zK@BcNb~Ywxtzreu2$^q#|a)O*E3_b6IDVXu^j$1n>{Oj1UZ^DjSI~dn8ZT`K0>FGat#)p5U zL8nox#QLjCg#6?SrYzPG9HKd5q(}3>}Qq) zNc|0NVJS0j`X{+}$1UdYTRR|$1gaO(uLjTQ27|)|I_4n&UJJ><$Y{vGz)}J=3uKhJ zB0ICf-W_}Yos?x(11C7+E7+7|I z-4YE>JKFyqu|z}eseoT7$gC`^eQU>F#%FtX?ClAiX2Fv1#|#uYpyUq9XLlJGSUMp0 zHwr`QWKj`NuL*P}IQZ%kb+x-Z?mOJsc1D!>ChoYkBid?8cTb2lQ>TFyWB$L1a#Ecl z>Wp81&ttqKsvTqjc83511IrlH&sm5uFbFF$gUcy47G*_YWkvc0UT%de$3G=Bx=eLRp_57R8 zz`*?fHv_V44^9^K~*JaTL3#7i#p6yQ1Qgb^Y8twZ4uEI(|kD;{{1)rHaFOf zh5go!TOh-O9SW2+S1g$cF`M}~Xq^eDGsMIY!N9=6&yv6Z+KmY9JF00jfdYa(B!o-v&b|xQ9SX{wrLyCdH7*Z$OF&cx44`oJS z5ix5Ab}iV41;nc2)(K~RL9iPhXpNZ8EO1mq;<;(hyM_J!^UWjrAB&%w9z6QjIf{XaH^ zx+i8lJG#~@8Z%$)XWa77r~hB^;eXfN!u}S=FO_7JU=(w-Ub%hszu(|8hXGUA@X`tfMux-xAG5TxRD;SL(A^{oph;Z@MI&(W0~)1dS7nE+P%<-TJ{+_(=-;1` z5>v=+xzLpy#i2S(k}`iENjZ3cZp^jR)}AwmQG`*1(E_}Vqae7Gal(ca@Ey6(evc`* z91R19n=Jza^BXo10X7C77@vg^9A4lR)eKoz)`P{NW6A=MF=eLza~T*|mV?V%B?bmn z(8euoMrL+pVP%y12vn7W#%$PFm|k4a*u?9`xp(hVP~8-pfZfXi-CdpGaLAnV$5^_ z>R3P%h1b4)(vUqD@(vja#Rw6Y4+55M^@jO8S_ZBP#ygMsaNU?}?ch-ERPj0TmnpfM^?2o!

U%~+_gY;tSs6vnD6pq>v);F1RqmO#t!1U3-{ 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

`G1EV;*I&$Kl`zh+z-zTt;VUqb3 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

Xlj1Vs#F#@+fKz(me-d7Y=j9^g& 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

    ~ng|Iht(D>9i;h{AJB5LXVbi|=78jNj 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%0AMGg&LRyj!B!v@a3W~T6N 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 z uYGQ1}EUvC*Or%(~9LN$s}RcdU(#>2lIF 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� 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�{uO|7Avhy~ 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±ABKIWj$=p-8r*co@p3Xgk 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 F0|4Dl?mhqj diff --git a/rustc.sh b/rustc.sh deleted file mode 100755 index ecd5588..0000000 --- a/rustc.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -have_o=false -for arg in "$@"; do - if [[ "$arg" = "-o" ]]; then - have_o=true - break - fi -done - -args=() -for arg in "$@"; do - if [[ $have_o = true && "$arg" =~ ^extra-filename= ]]; then - unset args[${#args[@]}-1] - elif [[ $have_o = true && "$arg" =~ ^--emit= ]]; then - args+=("--emit=link") - else - args+=("$arg") - fi -done - -RUST_BACKTRACE=1 exec rustc -L build/userspace "${args[@]}" diff --git a/rustdoc.sh b/rustdoc.sh deleted file mode 100755 index f60c41b..0000000 --- a/rustdoc.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -RUST_BACKTRACE=1 rustdoc -L build/userspace $* diff --git a/rustfmt.toml b/rustfmt.toml deleted file mode 100644 index 6776cef..0000000 --- a/rustfmt.toml +++ /dev/null @@ -1,5 +0,0 @@ -max_width = 200 -ideal_width = 100 -fn_call_width = 80 -wrap_match_arms = false -write_mode = "Overwrite" diff --git a/schemes/ethernetd/Cargo.toml b/schemes/ethernetd/Cargo.toml deleted file mode 100644 index 835b07e..0000000 --- a/schemes/ethernetd/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "ethernetd" -version = "0.1.0" - -[dependencies] -netutils = { git = "https://github.com/redox-os/netutils.git" } -redox_event = { git = "https://github.com/redox-os/event.git" } -redox_syscall = "0.1" diff --git a/schemes/ethernetd/src/main.rs b/schemes/ethernetd/src/main.rs deleted file mode 100644 index 7185435..0000000 --- a/schemes/ethernetd/src/main.rs +++ /dev/null @@ -1,110 +0,0 @@ -extern crate event; -extern crate netutils; -extern crate syscall; - -use event::EventQueue; -use std::cell::RefCell; -use std::fs::File; -use std::io::{Result, Read, Write}; -use std::os::unix::io::FromRawFd; -use std::process; -use std::rc::Rc; - -use syscall::{Packet, SchemeMut, EWOULDBLOCK}; - -use scheme::EthernetScheme; - -mod scheme; - -fn daemon(network_fd: usize, socket_fd: usize) { - let network = unsafe { File::from_raw_fd(network_fd) }; - let socket = Rc::new(RefCell::new(unsafe { File::from_raw_fd(socket_fd) })); - let scheme = Rc::new(RefCell::new(EthernetScheme::new(network))); - let todo = Rc::new(RefCell::new(Vec::::new())); - - let mut event_queue = EventQueue::<()>::new().expect("ethernetd: failed to create event queue"); - - let socket_net = socket.clone(); - let scheme_net = scheme.clone(); - let todo_net = todo.clone(); - event_queue.add(network_fd, move |_count: usize| -> Result> { - if scheme_net.borrow_mut().input()? > 0 { - let mut todo = todo_net.borrow_mut(); - let mut i = 0; - while i < todo.len() { - let a = todo[i].a; - scheme_net.borrow_mut().handle(&mut todo[i]); - if todo[i].a == (-EWOULDBLOCK) as usize { - todo[i].a = a; - i += 1; - } else { - socket_net.borrow_mut().write(&mut todo[i])?; - todo.remove(i); - } - } - - for (id, handle) in scheme_net.borrow_mut().handles.iter() { - if let Some(frame) = handle.frames.get(0) { - socket_net.borrow_mut().write(&Packet { - id: 0, - pid: 0, - uid: 0, - gid: 0, - a: syscall::number::SYS_FEVENT, - b: *id, - c: syscall::flag::EVENT_READ, - d: frame.data.len() - })?; - } - } - } - Ok(None) - }).expect("ethernetd: failed to listen for network events"); - - event_queue.add(socket_fd, move |_count: usize| -> Result> { - loop { - let mut packet = Packet::default(); - if socket.borrow_mut().read(&mut packet)? == 0 { - break; - } - - let a = packet.a; - scheme.borrow_mut().handle(&mut packet); - if packet.a == (-EWOULDBLOCK) as usize { - packet.a = a; - todo.borrow_mut().push(packet); - } else { - socket.borrow_mut().write(&mut packet)?; - } - } - - Ok(None) - }).expect("ethernetd: failed to listen for scheme events"); - - event_queue.trigger_all(0).expect("ethernetd: failed to trigger events"); - - event_queue.run().expect("ethernetd: failed to run event loop"); -} - -fn main() { - match syscall::open("network:", syscall::O_RDWR | syscall::O_NONBLOCK) { - Ok(network_fd) => { - // Daemonize - if unsafe { syscall::clone(0).unwrap() } == 0 { - match syscall::open(":ethernet", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK) { - Ok(socket_fd) => { - daemon(network_fd, socket_fd); - }, - Err(err) => { - println!("ethernetd: failed to create ethernet scheme: {}", err); - process::exit(1); - } - } - } - }, - Err(err) => { - println!("ethernetd: failed to open network: {}", err); - process::exit(1); - } - } -} diff --git a/schemes/ethernetd/src/scheme.rs b/schemes/ethernetd/src/scheme.rs deleted file mode 100644 index 7b1b3bd..0000000 --- a/schemes/ethernetd/src/scheme.rs +++ /dev/null @@ -1,164 +0,0 @@ -use std::collections::{BTreeMap, VecDeque}; -use std::fs::File; -use std::io::{self, Read, Write}; -use std::os::unix::io::AsRawFd; -use std::{cmp, str, u16}; - -use netutils::{getcfg, MacAddr, EthernetII}; -use syscall; -use syscall::error::{Error, Result, EACCES, EBADF, EINVAL, EIO, EWOULDBLOCK}; -use syscall::flag::O_NONBLOCK; -use syscall::scheme::SchemeMut; - -#[derive(Clone)] -pub struct Handle { - /// The flags this handle was opened with - flags: usize, - /// The Host's MAC address - pub host_addr: MacAddr, - /// The ethernet type - pub ethertype: u16, - /// The data - pub frames: VecDeque, -} - -pub struct EthernetScheme { - network: File, - next_id: usize, - pub handles: BTreeMap -} - -impl EthernetScheme { - pub fn new(network: File) -> EthernetScheme { - EthernetScheme { - network: network, - next_id: 1, - handles: BTreeMap::new(), - } - } - - //TODO: Minimize allocation - //TODO: Reduce iteration cost (use BTreeMap of ethertype to handle?) - pub fn input(&mut self) -> io::Result { - let mut total = 0; - loop { - let mut bytes = [0; 65536]; - let count = self.network.read(&mut bytes)?; - if count == 0 { - break; - } - if let Some(frame) = EthernetII::from_bytes(&bytes[.. count]) { - for (_id, handle) in self.handles.iter_mut() { - if frame.header.ethertype.get() == handle.ethertype { - handle.frames.push_back(frame.clone()); - } - } - total += count; - } - } - Ok(total) - } -} - -impl SchemeMut for EthernetScheme { - fn open(&mut self, url: &[u8], flags: usize, uid: u32, _gid: u32) -> Result { - if uid == 0 { - let mac_addr = MacAddr::from_str(&getcfg("mac").map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?); - let path = try!(str::from_utf8(url).or(Err(Error::new(EINVAL)))); - - let ethertype = u16::from_str_radix(path, 16).unwrap_or(0); - - let next_id = self.next_id; - self.next_id += 1; - - self.handles.insert(next_id, Handle { - flags: flags, - host_addr: mac_addr, - ethertype: ethertype, - frames: VecDeque::new() - }); - - Ok(next_id) - } else { - Err(Error::new(EACCES)) - } - } - - fn dup(&mut self, id: usize, _buf: &[u8]) -> Result { - let next_id = self.next_id; - self.next_id += 1; - - let handle = { - let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; - handle.clone() - }; - - self.handles.insert(next_id, handle); - - Ok(next_id) - } - - fn read(&mut self, id: usize, buf: &mut [u8]) -> Result { - let handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?; - - if let Some(frame) = handle.frames.pop_front() { - let data = frame.to_bytes(); - for (b, d) in buf.iter_mut().zip(data.iter()) { - *b = *d; - } - - Ok(cmp::min(buf.len(), data.len())) - } else if handle.flags & O_NONBLOCK == O_NONBLOCK { - Ok(0) - } else { - Err(Error::new(EWOULDBLOCK)) - } - } - - fn write(&mut self, id: usize, buf: &[u8]) -> Result { - let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; - - if let Some(mut frame) = EthernetII::from_bytes(buf) { - frame.header.src = handle.host_addr; - frame.header.ethertype.set(handle.ethertype); - self.network.write(&frame.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO))) - } else { - Err(Error::new(EINVAL)) - } - } - - fn fevent(&mut self, id: usize, _flags: usize) -> Result { - let _handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; - - Ok(id) - } - - fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result { - let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; - - let path_string = format!("ethernet:{:X}", handle.ethertype); - let path = path_string.as_bytes(); - - let mut i = 0; - while i < buf.len() && i < path.len() { - buf[i] = path[i]; - i += 1; - } - - Ok(i) - } - - fn fsync(&mut self, id: usize) -> Result { - let _handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; - - syscall::fsync(self.network.as_raw_fd()) - } - - fn close(&mut self, id: usize) -> Result { - let handle = self.handles.remove(&id).ok_or(Error::new(EBADF))?; - - drop(handle); - - Ok(0) - } -} diff --git a/schemes/ipd/Cargo.toml b/schemes/ipd/Cargo.toml deleted file mode 100644 index 3192911..0000000 --- a/schemes/ipd/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "ipd" -version = "0.1.0" - -[dependencies] -netutils = { git = "https://github.com/redox-os/netutils.git" } -redox_event = { git = "https://github.com/redox-os/event.git" } -redox_syscall = "0.1" diff --git a/schemes/ipd/src/interface/ethernet.rs b/schemes/ipd/src/interface/ethernet.rs deleted file mode 100644 index d914a78..0000000 --- a/schemes/ipd/src/interface/ethernet.rs +++ /dev/null @@ -1,155 +0,0 @@ -use netutils::{getcfg, n16, Ipv4Addr, MacAddr, Ipv4, EthernetII, EthernetIIHeader, Arp}; -use std::collections::BTreeMap; -use std::fs::File; -use std::io::{Result, Read, Write}; -use std::os::unix::io::FromRawFd; - -use interface::Interface; - -pub struct EthernetInterface { - mac: MacAddr, - ip: Ipv4Addr, - router: Ipv4Addr, - subnet: Ipv4Addr, - arp_file: File, - ip_file: File, - arp: BTreeMap, - rarp: BTreeMap, -} - -impl EthernetInterface { - pub fn new(arp_fd: usize, ip_fd: usize) -> Self { - EthernetInterface { - mac: MacAddr::from_str(&getcfg("mac").unwrap()), - ip: Ipv4Addr::from_str(&getcfg("ip").unwrap()), - router: Ipv4Addr::from_str(&getcfg("ip_router").unwrap()), - subnet: Ipv4Addr::from_str(&getcfg("ip_subnet").unwrap()), - arp_file: unsafe { File::from_raw_fd(arp_fd) }, - ip_file: unsafe { File::from_raw_fd(ip_fd) }, - arp: BTreeMap::new(), - rarp: BTreeMap::new(), - } - } -} - -impl Interface for EthernetInterface { - fn ip(&self) -> Ipv4Addr { - self.ip - } - - fn routable(&self, dst: Ipv4Addr) -> bool { - dst != Ipv4Addr::LOOPBACK - } - - fn arp_event(&mut self) -> Result<()> { - loop { - let mut bytes = [0; 65536]; - let count = self.arp_file.read(&mut bytes)?; - if count == 0 { - break; - } - if let Some(frame) = EthernetII::from_bytes(&bytes[.. count]) { - if let Some(packet) = Arp::from_bytes(&frame.data) { - if packet.header.oper.get() == 1 { - if packet.header.dst_ip == self.ip { - if packet.header.src_ip != Ipv4Addr::BROADCAST && frame.header.src != MacAddr::BROADCAST { - self.arp.insert(packet.header.src_ip, frame.header.src); - self.rarp.insert(frame.header.src, packet.header.src_ip); - } - - let mut response = Arp { - header: packet.header, - data: packet.data.clone(), - }; - response.header.oper.set(2); - response.header.dst_mac = packet.header.src_mac; - response.header.dst_ip = packet.header.src_ip; - response.header.src_mac = self.mac; - response.header.src_ip = self.ip; - - let mut response_frame = EthernetII { - header: frame.header, - data: response.to_bytes() - }; - - response_frame.header.dst = response_frame.header.src; - response_frame.header.src = self.mac; - - self.arp_file.write(&response_frame.to_bytes())?; - } - } - } - } - } - - Ok(()) - } - - fn recv(&mut self) -> Result> { - let mut ips = Vec::new(); - - loop { - let mut bytes = [0; 65536]; - let count = self.ip_file.read(&mut bytes)?; - if count == 0 { - break; - } - if let Some(frame) = EthernetII::from_bytes(&bytes[.. count]) { - if let Some(ip) = Ipv4::from_bytes(&frame.data) { - if ip.header.dst == self.ip || ip.header.dst == Ipv4Addr::BROADCAST { - //TODO: Handle ping here - - if ip.header.src != Ipv4Addr::BROADCAST && frame.header.src != MacAddr::BROADCAST { - self.arp.insert(ip.header.src, frame.header.src); - self.rarp.insert(frame.header.src, ip.header.src); - } - - ips.push(ip); - } - } - } - } - - Ok(ips) - } - - fn send(&mut self, ip: Ipv4) -> Result { - let mut dst = MacAddr::BROADCAST; - if ip.header.dst != Ipv4Addr::BROADCAST { - let mut needs_routing = false; - - for octet in 0..4 { - let me = self.ip.bytes[octet]; - let mask = self.subnet.bytes[octet]; - let them = ip.header.dst.bytes[octet]; - if me & mask != them & mask { - needs_routing = true; - break; - } - } - - let route_addr = if needs_routing { - self.router - } else { - ip.header.dst - }; - - if let Some(mac) = self.arp.get(&route_addr) { - dst = *mac; - } else { - println!("ipd: need to arp {}", route_addr.to_string()); - } - } - - let frame = EthernetII { - header: EthernetIIHeader { - dst: dst, - src: self.mac, - ethertype: n16::new(0x800), - }, - data: ip.to_bytes() - }; - - self.ip_file.write(&frame.to_bytes()) - } -} diff --git a/schemes/ipd/src/interface/loopback.rs b/schemes/ipd/src/interface/loopback.rs deleted file mode 100644 index a957ef8..0000000 --- a/schemes/ipd/src/interface/loopback.rs +++ /dev/null @@ -1,50 +0,0 @@ -use netutils::{Ipv4Addr, Ipv4}; -use std::io::Result; - -use interface::Interface; - -pub struct LoopbackInterface { - packets: Vec -} - -impl LoopbackInterface { - pub fn new() -> Self { - LoopbackInterface { - packets: Vec::new() - } - } -} - -impl Interface for LoopbackInterface { - fn ip(&self) -> Ipv4Addr { - Ipv4Addr::LOOPBACK - } - - fn routable(&self, dst: Ipv4Addr) -> bool { - dst == Ipv4Addr::LOOPBACK - } - - fn recv(&mut self) -> Result> { - let mut ips = Vec::new(); - - for ip in self.packets.drain(..) { - ips.push(ip); - } - - Ok(ips) - } - - fn send(&mut self, ip: Ipv4) -> Result { - self.packets.push(ip); - - Ok(0) - } - - fn arp_event(&mut self) -> Result<()> { - Ok(()) - } - - fn has_loopback_data(&self) -> bool { - ! self.packets.is_empty() - } -} diff --git a/schemes/ipd/src/interface/mod.rs b/schemes/ipd/src/interface/mod.rs deleted file mode 100644 index 2fa89d9..0000000 --- a/schemes/ipd/src/interface/mod.rs +++ /dev/null @@ -1,19 +0,0 @@ -use netutils::{Ipv4, Ipv4Addr}; -use std::io::Result; - -pub use self::ethernet::EthernetInterface; -pub use self::loopback::LoopbackInterface; - -mod ethernet; -mod loopback; - -pub trait Interface { - fn ip(&self) -> Ipv4Addr; - fn routable(&self, dst: Ipv4Addr) -> bool; - fn recv(&mut self) -> Result>; - fn send(&mut self, ip: Ipv4) -> Result; - - fn arp_event(&mut self) -> Result<()>; - - fn has_loopback_data(&self) -> bool { false } -} diff --git a/schemes/ipd/src/main.rs b/schemes/ipd/src/main.rs deleted file mode 100644 index 49e332f..0000000 --- a/schemes/ipd/src/main.rs +++ /dev/null @@ -1,341 +0,0 @@ -extern crate event; -extern crate netutils; -extern crate syscall; - -use event::EventQueue; -use netutils::{Ipv4Addr, Ipv4, Tcp}; -use std::cell::RefCell; -use std::collections::{BTreeMap, VecDeque}; -use std::fs::File; -use std::io::{self, Read, Write}; -use std::os::unix::io::FromRawFd; -use std::{process, slice, str}; -use std::rc::Rc; -use syscall::data::Packet; -use syscall::error::{Error, Result, EACCES, EADDRNOTAVAIL, EBADF, EIO, EINVAL, ENOENT, EWOULDBLOCK}; -use syscall::flag::{EVENT_READ, O_NONBLOCK}; -use syscall::scheme::SchemeMut; - -use interface::{Interface, EthernetInterface, LoopbackInterface}; - -mod interface; - -struct Handle { - proto: u8, - flags: usize, - events: usize, - data: VecDeque>, - todo: VecDeque, -} - -struct Ipd { - scheme_file: File, - interfaces: Vec>, - next_id: usize, - handles: BTreeMap, -} - -impl Ipd { - fn new(scheme_file: File) -> Self { - Ipd { - scheme_file: scheme_file, - interfaces: Vec::new(), - next_id: 1, - handles: BTreeMap::new(), - } - } - - fn scheme_event(&mut self) -> io::Result<()> { - loop { - let mut packet = Packet::default(); - if self.scheme_file.read(&mut packet)? == 0 { - break; - } - - let a = packet.a; - self.handle(&mut packet); - if packet.a == (-EWOULDBLOCK) as usize { - packet.a = a; - if let Some(mut handle) = self.handles.get_mut(&packet.b) { - handle.todo.push_back(packet); - } - } else { - self.scheme_file.write(&packet)?; - } - } - - Ok(()) - } - - fn ip_event(&mut self, if_id: usize) -> io::Result<()> { - if let Some(mut interface) = self.interfaces.get_mut(if_id) { - for ip in interface.recv()? { - for (id, handle) in self.handles.iter_mut() { - if ip.header.proto == handle.proto { - handle.data.push_back(ip.to_bytes()); - - while ! handle.todo.is_empty() && ! handle.data.is_empty() { - let mut packet = handle.todo.pop_front().unwrap(); - let buf = unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }; - let data = handle.data.pop_front().unwrap(); - - let mut i = 0; - while i < buf.len() && i < data.len() { - buf[i] = data[i]; - i += 1; - } - packet.a = i; - - self.scheme_file.write(&packet)?; - } - - if handle.events & EVENT_READ == EVENT_READ { - if let Some(data) = handle.data.get(0) { - self.scheme_file.write(&Packet { - id: 0, - pid: 0, - uid: 0, - gid: 0, - a: syscall::number::SYS_FEVENT, - b: *id, - c: EVENT_READ, - d: data.len() - })?; - } - } - } - } - } - } - - Ok(()) - } - - fn loopback_event(&mut self, loopback_id: usize) -> io::Result<()> { - let handle_loopback = if let Some(interface) = self.interfaces.get(loopback_id) { - interface.has_loopback_data() - } else { - false - }; - - if handle_loopback { - self.ip_event(loopback_id)?; - } - - Ok(()) - } -} - -impl SchemeMut for Ipd { - fn open(&mut self, url: &[u8], flags: usize, uid: u32, _gid: u32) -> Result { - if uid == 0 { - let path = str::from_utf8(url).or(Err(Error::new(EINVAL)))?; - - let proto = u8::from_str_radix(path, 16).or(Err(Error::new(ENOENT)))?; - - let id = self.next_id; - self.next_id += 1; - - self.handles.insert(id, Handle { - proto: proto, - flags: flags, - events: 0, - data: VecDeque::new(), - todo: VecDeque::new(), - }); - - Ok(id) - } else { - Err(Error::new(EACCES)) - } - } - - fn dup(&mut self, file: usize, _buf: &[u8]) -> Result { - let handle = { - let handle = self.handles.get(&file).ok_or(Error::new(EBADF))?; - Handle { - proto: handle.proto, - flags: handle.flags, - events: 0, - data: handle.data.clone(), - todo: VecDeque::new(), - } - }; - - let id = self.next_id; - self.next_id += 1; - - self.handles.insert(id, handle); - - Ok(id) - } - - fn read(&mut self, file: usize, buf: &mut [u8]) -> Result { - let mut handle = self.handles.get_mut(&file).ok_or(Error::new(EBADF))?; - - if let Some(data) = handle.data.pop_front() { - let mut i = 0; - while i < buf.len() && i < data.len() { - buf[i] = data[i]; - i += 1; - } - - Ok(i) - } else if handle.flags & O_NONBLOCK == O_NONBLOCK { - Ok(0) - } else { - Err(Error::new(EWOULDBLOCK)) - } - } - - fn write(&mut self, file: usize, buf: &[u8]) -> Result { - let handle = self.handles.get(&file).ok_or(Error::new(EBADF))?; - - if let Some(mut ip) = Ipv4::from_bytes(buf) { - for mut interface in self.interfaces.iter_mut() { - let if_ip = interface.ip(); - if ip.header.src == if_ip || (ip.header.src == Ipv4Addr::NULL && interface.routable(ip.header.dst)) { - ip.header.src = if_ip; - ip.header.proto = handle.proto; - - if let Some(mut tcp) = Tcp::from_bytes(&ip.data) { - tcp.checksum(&ip.header.src, &ip.header.dst); - ip.data = tcp.to_bytes(); - } - - ip.checksum(); - - interface.send(ip).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?; - - return Ok(buf.len()); - } - } - - Err(Error::new(EADDRNOTAVAIL)) - } else { - Err(Error::new(EINVAL)) - } - } - - fn fevent(&mut self, file: usize, flags: usize) -> Result { - let mut handle = self.handles.get_mut(&file).ok_or(Error::new(EBADF))?; - - handle.events = flags; - - Ok(file) - } - - fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result { - let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; - - let path_string = format!("ip:{:X}", handle.proto); - let path = path_string.as_bytes(); - - let mut i = 0; - while i < buf.len() && i < path.len() { - buf[i] = path[i]; - i += 1; - } - - Ok(i) - } - - fn fsync(&mut self, file: usize) -> Result { - let _handle = self.handles.get(&file).ok_or(Error::new(EBADF))?; - - Ok(0) - } - - fn close(&mut self, file: usize) -> Result { - let handle = self.handles.remove(&file).ok_or(Error::new(EBADF))?; - - drop(handle); - - Ok(0) - } -} - -fn daemon(arp_fd: usize, ip_fd: usize, scheme_fd: usize) { - let scheme_file = unsafe { File::from_raw_fd(scheme_fd) }; - - let ipd = Rc::new(RefCell::new(Ipd::new(scheme_file))); - - let mut event_queue = EventQueue::<()>::new().expect("ipd: failed to create event queue"); - - //TODO: Multiple interfaces - { - let if_id = { - let mut ipd = ipd.borrow_mut(); - let if_id = ipd.interfaces.len(); - ipd.interfaces.push(Box::new(EthernetInterface::new(arp_fd, ip_fd))); - if_id - }; - - let arp_ipd = ipd.clone(); - event_queue.add(arp_fd, move |_count: usize| -> io::Result> { - if let Some(mut interface) = arp_ipd.borrow_mut().interfaces.get_mut(if_id) { - interface.arp_event()?; - } - - Ok(None) - }).expect("ipd: failed to listen to events on ethernet:806"); - - let ip_ipd = ipd.clone(); - event_queue.add(ip_fd, move |_count: usize| -> io::Result> { - ip_ipd.borrow_mut().ip_event(if_id)?; - - Ok(None) - }).expect("ipd: failed to listen to events on ethernet:800"); - } - - let loopback_id = { - let mut ipd = ipd.borrow_mut(); - let if_id = ipd.interfaces.len(); - ipd.interfaces.push(Box::new(LoopbackInterface::new())); - if_id - }; - - event_queue.add(scheme_fd, move |_count: usize| -> io::Result> { - let mut ipd = ipd.borrow_mut(); - - ipd.loopback_event(loopback_id)?; - ipd.scheme_event()?; - ipd.loopback_event(loopback_id)?; - - Ok(None) - }).expect("ipd: failed to listen to events on :ip"); - - // Make sure that all descriptors are at EOF - event_queue.trigger_all(0).expect("ipd: failed to trigger event queue"); - - event_queue.run().expect("ipd: failed to run event queue"); -} - -fn main() { - match syscall::open("ethernet:806", syscall::O_RDWR | syscall::O_NONBLOCK) { - Ok(arp_fd) => match syscall::open("ethernet:800", syscall::O_RDWR | syscall::O_NONBLOCK) { - Ok(ip_fd) => { - // Daemonize - if unsafe { syscall::clone(0).unwrap() } == 0 { - match syscall::open(":ip", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK) { - Ok(scheme_fd) => { - daemon(arp_fd, ip_fd, scheme_fd); - }, - Err(err) => { - println!("ipd: failed to create ip scheme: {}", err); - process::exit(1); - } - } - } - }, - Err(err) => { - println!("ipd: failed to open ethernet:800: {}", err); - process::exit(1); - } - }, - Err(err) => { - println!("ipd: failed to open ethernet:806: {}", err); - process::exit(1); - } - } -} diff --git a/schemes/orbital b/schemes/orbital deleted file mode 160000 index e8a7304..0000000 --- a/schemes/orbital +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e8a73040268708a5f8bde3e9d703f6cbbab2b85f diff --git a/schemes/ptyd/Cargo.toml b/schemes/ptyd/Cargo.toml deleted file mode 100644 index 093da85..0000000 --- a/schemes/ptyd/Cargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "ptyd" -version = "0.1.0" - -[dependencies] -redox_syscall = "0.1" diff --git a/schemes/ptyd/src/main.rs b/schemes/ptyd/src/main.rs deleted file mode 100644 index 2a982fa..0000000 --- a/schemes/ptyd/src/main.rs +++ /dev/null @@ -1,414 +0,0 @@ -#![deny(warnings)] - -extern crate syscall; - -use std::cell::RefCell; -use std::collections::{BTreeMap, VecDeque}; -use std::fs::File; -use std::io::{Read, Write}; -use std::rc::{Rc, Weak}; -use std::str; - -use syscall::data::Packet; -use syscall::error::{Error, Result, EBADF, EINVAL, ENOENT, EPIPE, EWOULDBLOCK}; -use syscall::flag::{F_GETFL, F_SETFL, O_ACCMODE, O_NONBLOCK}; -use syscall::scheme::SchemeMut; - -pub struct PtyScheme { - next_id: usize, - ptys: (BTreeMap, BTreeMap) -} - -impl PtyScheme { - fn new() -> Self { - PtyScheme { - next_id: 0, - ptys: (BTreeMap::new(), BTreeMap::new()) - } - } -} - -impl SchemeMut for PtyScheme { - fn open(&mut self, path: &[u8], flags: usize, _uid: u32, _gid: u32) -> Result { - let path = str::from_utf8(path).or(Err(Error::new(EINVAL)))?.trim_matches('/'); - - if path.is_empty() { - let id = self.next_id; - self.next_id += 1; - - self.ptys.0.insert(id, PtyMaster::new(id, flags)); - - Ok(id) - } else { - let master_id = path.parse::().or(Err(Error::new(EINVAL)))?; - let master = self.ptys.0.get(&master_id).map(|pipe| pipe.clone()).ok_or(Error::new(ENOENT))?; - - let id = self.next_id; - self.next_id += 1; - - self.ptys.1.insert(id, PtySlave::new(&master, flags)); - - Ok(id) - } - } - - fn dup(&mut self, id: usize, _buf: &[u8]) -> Result { - /* TODO CLOEXEC - Master cannot be cloned - let master_opt = self.ptys.0.get(&id).map(|pipe| pipe.clone()); - if let Some(pipe) = master_opt { - let pipe_id = self.next_id; - self.next_id += 1; - self.ptys.0.insert(pipe_id, pipe); - return Ok(pipe_id); - } - */ - - let slave_opt = self.ptys.1.get(&id).map(|pipe| pipe.clone()); - if let Some(pipe) = slave_opt { - let pipe_id = self.next_id; - self.next_id += 1; - self.ptys.1.insert(pipe_id, pipe); - return Ok(pipe_id); - } - - Err(Error::new(EBADF)) - } - - fn read(&mut self, id: usize, buf: &mut [u8]) -> Result { - let master_opt = self.ptys.0.get(&id).map(|pipe| pipe.clone()); - if let Some(pipe) = master_opt { - return pipe.read(buf); - } - - let slave_opt = self.ptys.1.get(&id).map(|pipe| pipe.clone()); - if let Some(pipe) = slave_opt { - return pipe.read(buf); - } - - Err(Error::new(EBADF)) - } - - fn write(&mut self, id: usize, buf: &[u8]) -> Result { - let master_opt = self.ptys.0.get(&id).map(|pipe| pipe.clone()); - if let Some(pipe) = master_opt { - return pipe.write(buf); - } - - let slave_opt = self.ptys.1.get(&id).map(|pipe| pipe.clone()); - if let Some(pipe) = slave_opt { - return pipe.write(buf); - } - - Err(Error::new(EBADF)) - } - - fn fcntl(&mut self, id: usize, cmd: usize, arg: usize) -> Result { - if let Some(pipe) = self.ptys.0.get_mut(&id) { - return pipe.fcntl(cmd, arg); - } - - if let Some(pipe) = self.ptys.1.get_mut(&id) { - return pipe.fcntl(cmd, arg); - } - - Err(Error::new(EBADF)) - } - - fn fevent(&mut self, id: usize, _flags: usize) -> Result { - if self.ptys.0.contains_key(&id) || self.ptys.1.contains_key(&id) { - Ok(id) - } else { - Err(Error::new(EBADF)) - } - } - - fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result { - let master_opt = self.ptys.0.get(&id).map(|pipe| pipe.clone()); - if let Some(pipe) = master_opt { - return pipe.path(buf); - } - - let slave_opt = self.ptys.1.get(&id).map(|pipe| pipe.clone()); - if let Some(pipe) = slave_opt { - return pipe.path(buf); - } - - Err(Error::new(EBADF)) - } - - fn fsync(&mut self, id: usize) -> Result { - let slave_opt = self.ptys.1.get(&id).map(|pipe| pipe.clone()); - if let Some(pipe) = slave_opt { - return pipe.sync(); - } - - Ok(0) - } - - fn close(&mut self, id: usize) -> Result { - drop(self.ptys.0.remove(&id)); - drop(self.ptys.1.remove(&id)); - - Ok(0) - } -} - -/// Read side of a pipe -#[derive(Clone)] -pub struct PtyMaster { - id: usize, - flags: usize, - read: Rc>>>, - write: Rc>>, -} - -impl PtyMaster { - pub fn new(id: usize, flags: usize) -> Self { - PtyMaster { - id: id, - flags: flags, - read: Rc::new(RefCell::new(VecDeque::new())), - write: Rc::new(RefCell::new(VecDeque::new())), - } - } - - fn path(&self, buf: &mut [u8]) -> Result { - let path_str = format!("pty:{}", self.id); - let path = path_str.as_bytes(); - - let mut i = 0; - while i < buf.len() && i < path.len() { - buf[i] = path[i]; - i += 1; - } - - Ok(i) - } - - fn read(&self, buf: &mut [u8]) -> Result { - let mut read = self.read.borrow_mut(); - - if let Some(packet) = read.pop_front() { - let mut i = 0; - - while i < buf.len() && i < packet.len() { - buf[i] = packet[i]; - i += 1; - } - - Ok(i) - } else if self.flags & O_NONBLOCK == O_NONBLOCK || Rc::weak_count(&self.read) == 0 { - Ok(0) - } else { - Err(Error::new(EWOULDBLOCK)) - } - } - - fn write(&self, buf: &[u8]) -> Result { - let mut write = self.write.borrow_mut(); - - let mut i = 0; - while i < buf.len() { - write.push_back(buf[i]); - i += 1; - } - - Ok(i) - } - - fn fcntl(&mut self, cmd: usize, arg: usize) -> Result { - match cmd { - F_GETFL => Ok(self.flags), - F_SETFL => { - self.flags = arg & ! O_ACCMODE; - Ok(0) - }, - _ => Err(Error::new(EINVAL)) - } - } -} - -/// Read side of a pipe -#[derive(Clone)] -pub struct PtySlave { - master_id: usize, - flags: usize, - read: Weak>>, - write: Weak>>>, -} - -impl PtySlave { - pub fn new(master: &PtyMaster, flags: usize) -> Self { - PtySlave { - master_id: master.id, - flags: flags, - read: Rc::downgrade(&master.write), - write: Rc::downgrade(&master.read), - } - } - - fn path(&self, buf: &mut [u8]) -> Result { - let path_str = format!("pty:{}", self.master_id); - let path = path_str.as_bytes(); - - let mut i = 0; - while i < buf.len() && i < path.len() { - buf[i] = path[i]; - i += 1; - } - - Ok(i) - } - - fn read(&self, buf: &mut [u8]) -> Result { - if let Some(read_lock) = self.read.upgrade() { - let mut read = read_lock.borrow_mut(); - - let mut i = 0; - - while i < buf.len() && ! read.is_empty() { - buf[i] = read.pop_front().unwrap(); - i += 1; - } - - if i > 0 || self.flags & O_NONBLOCK == O_NONBLOCK { - Ok(i) - } else { - Err(Error::new(EWOULDBLOCK)) - } - } else { - Ok(0) - } - } - - fn write(&self, buf: &[u8]) -> Result { - if let Some(write_lock) = self.write.upgrade() { - let mut vec = Vec::new(); - vec.push(0); - vec.extend_from_slice(buf); - - let mut write = write_lock.borrow_mut(); - write.push_back(vec); - - Ok(buf.len()) - } else { - Err(Error::new(EPIPE)) - } - } - - fn sync(&self) -> Result { - if let Some(write_lock) = self.write.upgrade() { - let mut vec = Vec::new(); - vec.push(1); - - let mut write = write_lock.borrow_mut(); - write.push_back(vec); - - Ok(0) - } else { - Err(Error::new(EPIPE)) - } - } - - fn fcntl(&mut self, cmd: usize, arg: usize) -> Result { - match cmd { - F_GETFL => Ok(self.flags), - F_SETFL => { - self.flags = arg & ! O_ACCMODE; - Ok(0) - }, - _ => Err(Error::new(EINVAL)) - } - } -} - -fn main(){ - // Daemonize - if unsafe { syscall::clone(0).unwrap() } == 0 { - let mut socket = File::create(":pty").expect("pty: failed to create pty scheme"); - let mut scheme = PtyScheme::new(); - let mut todo = Vec::new(); - loop { - let mut packet = Packet::default(); - socket.read(&mut packet).expect("pty: failed to read events from pty scheme"); - - let a = packet.a; - scheme.handle(&mut packet); - if packet.a == (-EWOULDBLOCK) as usize { - packet.a = a; - todo.push(packet); - } else { - socket.write(&packet).expect("pty: failed to write responses to pty scheme"); - } - - let mut i = 0; - while i < todo.len() { - let a = todo[i].a; - scheme.handle(&mut todo[i]); - if todo[i].a == (-EWOULDBLOCK) as usize { - todo[i].a = a; - i += 1; - } else { - let packet = todo.remove(i); - socket.write(&packet).expect("pty: failed to write responses to pty scheme"); - } - } - - for (id, master) in scheme.ptys.0.iter() { - let read = master.read.borrow(); - if let Some(data) = read.front() { - socket.write(&Packet { - id: 0, - pid: 0, - uid: 0, - gid: 0, - a: syscall::number::SYS_FEVENT, - b: *id, - c: syscall::flag::EVENT_READ, - d: data.len() - }).expect("pty: failed to write event"); - } else if Rc::weak_count(&master.read) == 0 { - socket.write(&Packet { - id: 0, - pid: 0, - uid: 0, - gid: 0, - a: syscall::number::SYS_FEVENT, - b: *id, - c: syscall::flag::EVENT_READ, - d: 0 - }).expect("pty: failed to write event"); - } - } - - for (id, slave) in scheme.ptys.1.iter() { - if let Some(read_lock) = slave.read.upgrade() { - let read = read_lock.borrow(); - if ! read.is_empty() { - socket.write(&Packet { - id: 0, - pid: 0, - uid: 0, - gid: 0, - a: syscall::number::SYS_FEVENT, - b: *id, - c: syscall::flag::EVENT_READ, - d: read.len() - }).expect("pty: failed to write event"); - } - } else { - socket.write(&Packet { - id: 0, - pid: 0, - uid: 0, - gid: 0, - a: syscall::number::SYS_FEVENT, - b: *id, - c: syscall::flag::EVENT_READ, - d: 0 - }).expect("pty: failed to write event"); - } - } - } - } -} diff --git a/schemes/randd/Cargo.toml b/schemes/randd/Cargo.toml deleted file mode 100644 index 3b7ebf2..0000000 --- a/schemes/randd/Cargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "randd" -version = "0.1.0" - -[dependencies] -raw-cpuid = "2.0" -redox_syscall = "0.1" diff --git a/schemes/randd/src/main.rs b/schemes/randd/src/main.rs deleted file mode 100644 index c15936d..0000000 --- a/schemes/randd/src/main.rs +++ /dev/null @@ -1,92 +0,0 @@ -#![feature(asm)] -#![feature(rand)] - -extern crate syscall; -extern crate raw_cpuid; -extern crate rand; - -use std::fs::File; -use std::io::{Read, Write}; - -use rand::chacha::ChaChaRng; -use rand::Rng; - -use raw_cpuid::CpuId; - -use syscall::{Packet, Result, SchemeMut}; - -//TODO: Use a CSPRNG, allow write of entropy -struct RandScheme { - prng: ChaChaRng -} - -impl SchemeMut for RandScheme { - fn open(&mut self, _path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result { - Ok(0) - } - - fn dup(&mut self, file: usize, _buf: &[u8]) -> Result { - Ok(file) - } - - fn read(&mut self, _file: usize, buf: &mut [u8]) -> Result { - let mut i = 0; - for chunk in buf.chunks_mut(8) { - let mut rand = self.prng.next_u64(); - for b in chunk.iter_mut() { - *b = rand as u8; - rand = rand >> 8; - i += 1; - } - } - Ok(i) - } - - fn fpath(&mut self, _file: usize, buf: &mut [u8]) -> Result { - let mut i = 0; - let scheme_path = b"rand"; - while i < buf.len() && i < scheme_path.len() { - buf[i] = scheme_path[i]; - i += 1; - } - Ok(i) - } - - fn close(&mut self, _file: usize) -> Result { - Ok(0) - } -} - -fn main(){ - let has_rdrand = CpuId::new().get_feature_info().unwrap().has_rdrand(); - - // Daemonize - if unsafe { syscall::clone(0).unwrap() } == 0 { - let mut socket = File::create(":rand").expect("rand: failed to create rand scheme"); - - let mut rng = ChaChaRng::new_unseeded(); - - if has_rdrand { - println!("rand: seeding with rdrand"); - let rand: u64; - unsafe { - asm!("rdrand rax" - : "={rax}"(rand) - : - : - : "intel", "volatile"); - } - rng.set_counter(0, rand); - } else { - println!("rand: unseeded"); - } - - let mut scheme = RandScheme{prng: rng}; - loop { - let mut packet = Packet::default(); - socket.read(&mut packet).expect("rand: failed to read events from rand scheme"); - scheme.handle(&mut packet); - socket.write(&packet).expect("rand: failed to write responses to rand scheme"); - } - } -} diff --git a/schemes/redoxfs b/schemes/redoxfs deleted file mode 160000 index 6c1d98c..0000000 --- a/schemes/redoxfs +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6c1d98cea83e2bb02b940959e6b07625ec12656f diff --git a/schemes/tcpd/Cargo.toml b/schemes/tcpd/Cargo.toml deleted file mode 100644 index f756ee2..0000000 --- a/schemes/tcpd/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "tcpd" -version = "0.1.0" - -[dependencies] -netutils = { git = "https://github.com/redox-os/netutils.git" } -rand = "0.3" -redox_event = { git = "https://github.com/redox-os/event.git" } -redox_syscall = "0.1" diff --git a/schemes/tcpd/src/main.rs b/schemes/tcpd/src/main.rs deleted file mode 100644 index 8878b00..0000000 --- a/schemes/tcpd/src/main.rs +++ /dev/null @@ -1,937 +0,0 @@ -extern crate event; -extern crate netutils; -extern crate rand; -extern crate syscall; - -use rand::{Rng, OsRng}; -use std::collections::{BTreeMap, VecDeque}; -use std::cell::RefCell; -use std::fs::File; -use std::io::{self, Read, Write}; -use std::{mem, process, slice, str}; -use std::ops::{Deref, DerefMut}; -use std::os::unix::io::FromRawFd; -use std::rc::Rc; - -use event::EventQueue; -use netutils::{n16, n32, Ipv4, Ipv4Addr, Ipv4Header, Tcp, TcpHeader, Checksum, TCP_FIN, TCP_SYN, TCP_RST, TCP_PSH, TCP_ACK}; -use syscall::data::{Packet, TimeSpec}; -use syscall::error::{Error, Result, EACCES, EADDRINUSE, EBADF, EIO, EINVAL, EISCONN, EMSGSIZE, ENOTCONN, ETIMEDOUT, EWOULDBLOCK}; -use syscall::flag::{CLOCK_MONOTONIC, EVENT_READ, F_GETFL, F_SETFL, O_ACCMODE, O_CREAT, O_RDWR, O_NONBLOCK}; -use syscall::scheme::SchemeMut; - -fn add_time(a: &TimeSpec, b: &TimeSpec) -> TimeSpec { - let mut secs = a.tv_sec + b.tv_sec; - - let mut nsecs = a.tv_nsec + b.tv_nsec; - while nsecs >= 1000000000 { - nsecs -= 1000000000; - secs += 1; - } - - TimeSpec { - tv_sec: secs, - tv_nsec: nsecs - } -} - -fn parse_socket(socket: &str) -> (Ipv4Addr, u16) { - let mut socket_parts = socket.split(":"); - let host = Ipv4Addr::from_str(socket_parts.next().unwrap_or("")); - let port = socket_parts.next().unwrap_or("").parse::().unwrap_or(0); - (host, port) -} - -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -enum State { - Listen, - SynSent, - SynReceived, - Established, - FinWait1, - FinWait2, - CloseWait, - Closing, - LastAck, - TimeWait, - Closed -} - -struct TcpHandle { - local: (Ipv4Addr, u16), - remote: (Ipv4Addr, u16), - flags: usize, - events: usize, - read_timeout: Option, - write_timeout: Option, - ttl: u8, - state: State, - seq: u32, - ack: u32, - data: VecDeque<(Ipv4, Tcp)>, - todo_dup: VecDeque, - todo_read: VecDeque<(Option, Packet)>, - todo_write: VecDeque<(Option, Packet)>, -} - -impl TcpHandle { - fn is_connected(&self) -> bool { - self.remote.0 != Ipv4Addr::NULL && self.remote.1 != 0 - } - - fn read_closed(&self) -> bool { - self.state == State::CloseWait || self.state == State::LastAck || self.state == State::TimeWait || self.state == State::Closed - } - - fn matches(&self, ip: &Ipv4, tcp: &Tcp) -> bool { - // Local address not set or IP dst matches or is broadcast - (self.local.0 == Ipv4Addr::NULL || ip.header.dst == self.local.0 || ip.header.dst == Ipv4Addr::BROADCAST) - // Local port matches UDP dst - && tcp.header.dst.get() == self.local.1 - // Remote address not set or is broadcast, or IP src matches - && (self.remote.0 == Ipv4Addr::NULL || self.remote.0 == Ipv4Addr::BROADCAST || ip.header.src == self.remote.0) - // Remote port not set or UDP src matches - && (self.remote.1 == 0 || tcp.header.src.get() == self.remote.1) - } - - fn create_tcp(&self, flags: u16, data: Vec) -> Tcp { - Tcp { - header: TcpHeader { - src: n16::new(self.local.1), - dst: n16::new(self.remote.1), - sequence: n32::new(self.seq), - ack_num: n32::new(self.ack), - flags: n16::new(((mem::size_of::() << 10) & 0xF000) as u16 | (flags & 0xFFF)), - window_size: n16::new(8192), - checksum: Checksum { data: 0 }, - urgent_pointer: n16::new(0), - }, - options: Vec::new(), - data: data - } - } - - fn create_ip(&self, id: u16, data: Vec) -> Ipv4 { - Ipv4 { - header: Ipv4Header { - ver_hlen: 0x45, - services: 0, - len: n16::new((data.len() + mem::size_of::()) as u16), - id: n16::new(id), - flags_fragment: n16::new(0), - ttl: self.ttl, - proto: 0x06, - checksum: Checksum { data: 0 }, - src: self.local.0, - dst: self.remote.0 - }, - options: Vec::new(), - data: data - } - } -} - -#[derive(Copy, Clone)] -enum SettingKind { - Ttl, - ReadTimeout, - WriteTimeout -} - -enum Handle { - Tcp(TcpHandle), - Setting(usize, SettingKind), -} - -struct Tcpd { - scheme_file: File, - tcp_file: File, - time_file: File, - ports: BTreeMap, - next_id: usize, - handles: BTreeMap, - rng: OsRng, -} - -impl Tcpd { - fn new(scheme_file: File, tcp_file: File, time_file: File) -> Self { - Tcpd { - scheme_file: scheme_file, - tcp_file: tcp_file, - time_file: time_file, - ports: BTreeMap::new(), - next_id: 1, - handles: BTreeMap::new(), - rng: OsRng::new().expect("tcpd: failed to open RNG") - } - } - - fn scheme_event(&mut self) -> io::Result<()> { - loop { - let mut packet = Packet::default(); - if self.scheme_file.read(&mut packet)? == 0 { - break; - } - - let a = packet.a; - self.handle(&mut packet); - if packet.a == (-EWOULDBLOCK) as usize { - if let Some(mut handle) = self.handles.get_mut(&packet.b) { - if let Handle::Tcp(ref mut handle) = *handle { - match a { - syscall::number::SYS_DUP => { - packet.a = a; - handle.todo_dup.push_back(packet); - }, - syscall::number::SYS_READ => { - packet.a = a; - - let timeout = match handle.read_timeout { - Some(read_timeout) => { - let mut time = TimeSpec::default(); - syscall::clock_gettime(CLOCK_MONOTONIC, &mut time).map_err(|err| io::Error::from_raw_os_error(err.errno))?; - - let timeout = add_time(&time, &read_timeout); - self.time_file.write(&timeout)?; - Some(timeout) - }, - None => None - }; - - handle.todo_read.push_back((timeout, packet)); - }, - syscall::number::SYS_WRITE => { - packet.a = a; - - let timeout = match handle.write_timeout { - Some(write_timeout) => { - let mut time = TimeSpec::default(); - syscall::clock_gettime(CLOCK_MONOTONIC, &mut time).map_err(|err| io::Error::from_raw_os_error(err.errno))?; - - let timeout = add_time(&time, &write_timeout); - self.time_file.write(&timeout)?; - Some(timeout) - }, - None => None - }; - - handle.todo_write.push_back((timeout, packet)); - }, - _ => { - self.scheme_file.write(&packet)?; - } - } - } - } - } else { - self.scheme_file.write(&packet)?; - } - } - - Ok(()) - } - - fn tcp_event(&mut self) -> io::Result<()> { - loop { - let mut bytes = [0; 65536]; - let count = self.tcp_file.read(&mut bytes)?; - if count == 0 { - break; - } - if let Some(ip) = Ipv4::from_bytes(&bytes[.. count]) { - if let Some(tcp) = Tcp::from_bytes(&ip.data) { - let mut closing = Vec::new(); - let mut found_connection = false; - for (id, handle) in self.handles.iter_mut() { - if let Handle::Tcp(ref mut handle) = *handle { - if handle.state != State::Listen && handle.matches(&ip, &tcp) { - found_connection = true; - - match handle.state { - State::SynReceived => if tcp.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_ACK && tcp.header.ack_num.get() == handle.seq { - handle.state = State::Established; - }, - State::SynSent => if tcp.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_SYN | TCP_ACK && tcp.header.ack_num.get() == handle.seq { - handle.state = State::Established; - handle.ack = tcp.header.sequence.get() + 1; - - let tcp = handle.create_tcp(TCP_ACK, Vec::new()); - let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes())?; - }, - State::Established => if tcp.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_ACK && tcp.header.ack_num.get() == handle.seq { - handle.ack = tcp.header.sequence.get(); - - if ! tcp.data.is_empty() { - handle.data.push_back((ip.clone(), tcp.clone())); - handle.ack += tcp.data.len() as u32; - - let tcp = handle.create_tcp(TCP_ACK, Vec::new()); - let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes())?; - } else if tcp.header.flags.get() & TCP_FIN == TCP_FIN { - handle.state = State::CloseWait; - - handle.ack += 1; - - let tcp = handle.create_tcp(TCP_ACK, Vec::new()); - let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes())?; - } - }, - //TODO: Time wait - State::FinWait1 => if tcp.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_ACK && tcp.header.ack_num.get() == handle.seq { - handle.ack = tcp.header.sequence.get() + 1; - - if tcp.header.flags.get() & TCP_FIN == TCP_FIN { - handle.state = State::TimeWait; - - let tcp = handle.create_tcp(TCP_ACK, Vec::new()); - let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes())?; - - closing.push(*id); - } else { - handle.state = State::FinWait2; - } - }, - State::FinWait2 => if tcp.header.flags.get() & (TCP_SYN | TCP_ACK | TCP_FIN) == TCP_ACK | TCP_FIN && tcp.header.ack_num.get() == handle.seq { - handle.ack = tcp.header.sequence.get() + 1; - - handle.state = State::TimeWait; - - let tcp = handle.create_tcp(TCP_ACK, Vec::new()); - let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes())?; - - closing.push(*id); - }, - State::LastAck => if tcp.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_ACK && tcp.header.ack_num.get() == handle.seq { - handle.state = State::Closed; - closing.push(*id); - }, - _ => () - } - - while ! handle.todo_read.is_empty() && (! handle.data.is_empty() || handle.read_closed()) { - let (_timeout, mut packet) = handle.todo_read.pop_front().unwrap(); - let buf = unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }; - if let Some((_ip, tcp)) = handle.data.pop_front() { - let mut i = 0; - while i < buf.len() && i < tcp.data.len() { - buf[i] = tcp.data[i]; - i += 1; - } - packet.a = i; - } else { - packet.a = 0; - } - - self.scheme_file.write(&packet)?; - } - - if ! handle.todo_write.is_empty() && handle.state == State::Established { - let (_timeout, mut packet) = handle.todo_write.pop_front().unwrap(); - let buf = unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }; - - let tcp = handle.create_tcp(TCP_ACK | TCP_PSH, buf.to_vec()); - let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); - let result = self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO))); - if result.is_ok() { - handle.seq += buf.len() as u32; - } - packet.a = Error::mux(result.and(Ok(buf.len()))); - - self.scheme_file.write(&packet)?; - } - - if handle.events & EVENT_READ == EVENT_READ { - if let Some(&(ref _ip, ref tcp)) = handle.data.get(0) { - self.scheme_file.write(&Packet { - id: 0, - pid: 0, - uid: 0, - gid: 0, - a: syscall::number::SYS_FEVENT, - b: *id, - c: EVENT_READ, - d: tcp.data.len() - })?; - } - } - } - } - } - - for file in closing { - if let Handle::Tcp(handle) = self.handles.remove(&file).unwrap() { - let remove = if let Some(mut port) = self.ports.get_mut(&handle.local.1) { - *port = *port + 1; - *port == 0 - } else { - false - }; - - if remove { - self.ports.remove(&handle.local.1); - } - } - } - - if ! found_connection && tcp.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_SYN { - let mut new_handles = Vec::new(); - - for (_id, handle) in self.handles.iter_mut() { - if let Handle::Tcp(ref mut handle) = *handle { - if handle.state == State::Listen && handle.matches(&ip, &tcp) { - handle.data.push_back((ip.clone(), tcp.clone())); - - while ! handle.todo_dup.is_empty() && ! handle.data.is_empty() { - let mut packet = handle.todo_dup.pop_front().unwrap(); - let (ip, tcp) = handle.data.pop_front().unwrap(); - - let mut new_handle = TcpHandle { - local: handle.local, - remote: (ip.header.src, tcp.header.src.get()), - flags: handle.flags, - events: 0, - read_timeout: handle.read_timeout, - write_timeout: handle.write_timeout, - ttl: handle.ttl, - state: State::SynReceived, - seq: self.rng.gen(), - ack: tcp.header.sequence.get() + 1, - data: VecDeque::new(), - todo_dup: VecDeque::new(), - todo_read: VecDeque::new(), - todo_write: VecDeque::new(), - }; - - let tcp = new_handle.create_tcp(TCP_SYN | TCP_ACK, Vec::new()); - let ip = new_handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes())?; - - new_handle.seq += 1; - - handle.data.retain(|&(ref ip, ref tcp)| { - if new_handle.matches(ip, tcp) { - false - } else { - true - } - }); - - if let Some(mut port) = self.ports.get_mut(&handle.local.1) { - *port = *port + 1; - } - - let id = self.next_id; - self.next_id += 1; - - packet.a = id; - - new_handles.push((packet, Handle::Tcp(new_handle))); - } - } - } - } - - for (packet, new_handle) in new_handles { - self.handles.insert(packet.a, new_handle); - self.scheme_file.write(&packet)?; - } - } - } - } - } - - Ok(()) - } - - fn time_event(&mut self) -> io::Result<()> { - let mut time = TimeSpec::default(); - if self.time_file.read(&mut time)? < mem::size_of::() { - return Err(io::Error::from_raw_os_error(EINVAL)); - } - - for (_id, handle) in self.handles.iter_mut() { - if let Handle::Tcp(ref mut handle) = *handle { - let mut i = 0; - while i < handle.todo_read.len() { - if let Some(timeout) = handle.todo_read.get(i).map(|e| e.0.clone()).unwrap_or(None) { - if time.tv_sec > timeout.tv_sec || (time.tv_sec == timeout.tv_sec && time.tv_nsec >= timeout.tv_nsec) { - let (_timeout, mut packet) = handle.todo_read.remove(i).unwrap(); - packet.a = (-ETIMEDOUT) as usize; - self.scheme_file.write(&packet)?; - } else { - i += 1; - } - } else { - i += 1; - } - } - - let mut i = 0; - while i < handle.todo_write.len() { - if let Some(timeout) = handle.todo_write.get(i).map(|e| e.0.clone()).unwrap_or(None) { - if time.tv_sec > timeout.tv_sec || (time.tv_sec == timeout.tv_sec && time.tv_nsec >= timeout.tv_nsec) { - let (_timeout, mut packet) = handle.todo_write.remove(i).unwrap(); - packet.a = (-ETIMEDOUT) as usize; - self.scheme_file.write(&packet)?; - } else { - i += 1; - } - } else { - i += 1; - } - } - } - } - - Ok(()) - } -} - -impl SchemeMut for Tcpd { - fn open(&mut self, url: &[u8], flags: usize, uid: u32, _gid: u32) -> Result { - let path = str::from_utf8(url).or(Err(Error::new(EINVAL)))?; - - let mut parts = path.split("/"); - let remote = parse_socket(parts.next().unwrap_or("")); - let mut local = parse_socket(parts.next().unwrap_or("")); - - if local.1 == 0 { - local.1 = self.rng.gen_range(32768, 65535); - } - - if local.1 <= 1024 && uid != 0 { - return Err(Error::new(EACCES)); - } - - if self.ports.contains_key(&local.1) { - return Err(Error::new(EADDRINUSE)); - } - - let mut handle = TcpHandle { - local: local, - remote: remote, - flags: flags, - events: 0, - read_timeout: None, - write_timeout: None, - ttl: 64, - state: State::Listen, - seq: 0, - ack: 0, - data: VecDeque::new(), - todo_dup: VecDeque::new(), - todo_read: VecDeque::new(), - todo_write: VecDeque::new(), - }; - - if handle.is_connected() { - handle.seq = self.rng.gen(); - handle.ack = 0; - handle.state = State::SynSent; - - let tcp = handle.create_tcp(TCP_SYN, Vec::new()); - let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?; - - handle.seq += 1; - } - - self.ports.insert(local.1, 1); - - let id = self.next_id; - self.next_id += 1; - - self.handles.insert(id, Handle::Tcp(handle)); - - Ok(id) - } - - fn dup(&mut self, file: usize, buf: &[u8]) -> Result { - let handle = match *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - Handle::Tcp(ref mut handle) => { - let mut new_handle = TcpHandle { - local: handle.local, - remote: handle.remote, - flags: handle.flags, - events: 0, - read_timeout: handle.read_timeout, - write_timeout: handle.write_timeout, - ttl: handle.ttl, - state: handle.state, - seq: handle.seq, - ack: handle.ack, - data: VecDeque::new(), - todo_dup: VecDeque::new(), - todo_read: VecDeque::new(), - todo_write: VecDeque::new(), - }; - - let path = str::from_utf8(buf).or(Err(Error::new(EINVAL)))?; - - if path == "ttl" { - Handle::Setting(file, SettingKind::Ttl) - } else if path == "read_timeout" { - Handle::Setting(file, SettingKind::ReadTimeout) - } else if path == "write_timeout" { - Handle::Setting(file, SettingKind::WriteTimeout) - } else if path == "listen" { - if handle.is_connected() { - return Err(Error::new(EISCONN)); - } else if let Some((ip, tcp)) = handle.data.pop_front() { - new_handle.remote = (ip.header.src, tcp.header.src.get()); - - new_handle.seq = self.rng.gen(); - new_handle.ack = tcp.header.sequence.get() + 1; - new_handle.state = State::SynReceived; - - let tcp = new_handle.create_tcp(TCP_SYN | TCP_ACK, Vec::new()); - let ip = new_handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO))).and(Ok(buf.len()))?; - - new_handle.seq += 1; - } else { - return Err(Error::new(EWOULDBLOCK)); - } - - handle.data.retain(|&(ref ip, ref tcp)| { - if new_handle.matches(ip, tcp) { - false - } else { - true - } - }); - - Handle::Tcp(new_handle) - } else if path.is_empty() { - new_handle.data = handle.data.clone(); - - Handle::Tcp(new_handle) - } else if handle.is_connected() { - return Err(Error::new(EISCONN)); - } else { - new_handle.remote = parse_socket(path); - - if new_handle.is_connected() { - new_handle.seq = self.rng.gen(); - new_handle.ack = 0; - new_handle.state = State::SynSent; - - handle.data.retain(|&(ref ip, ref tcp)| { - if new_handle.matches(ip, tcp) { - new_handle.data.push_back((ip.clone(), tcp.clone())); - false - } else { - true - } - }); - - let tcp = new_handle.create_tcp(TCP_SYN, Vec::new()); - let ip = new_handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO))).and(Ok(buf.len()))?; - - new_handle.seq += 1; - - Handle::Tcp(new_handle) - } else { - return Err(Error::new(EINVAL)); - } - } - }, - Handle::Setting(file, kind) => { - Handle::Setting(file, kind) - } - }; - - let id = self.next_id; - self.next_id += 1; - - self.handles.insert(id, handle); - - Ok(id) - } - - fn read(&mut self, file: usize, buf: &mut [u8]) -> Result { - let (file, kind) = match *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - Handle::Tcp(ref mut handle) => { - if ! handle.is_connected() { - return Err(Error::new(ENOTCONN)); - } else if let Some((ip, mut tcp)) = handle.data.pop_front() { - let len = std::cmp::min(buf.len(), tcp.data.len()); - for (i, c) in tcp.data.drain(0..len).enumerate() { - buf[i] = c; - } - if !tcp.data.is_empty() { - handle.data.push_front((ip, tcp)); - } - - return Ok(len); - } else if handle.flags & O_NONBLOCK == O_NONBLOCK || handle.read_closed() { - return Ok(0); - } else { - return Err(Error::new(EWOULDBLOCK)); - } - }, - Handle::Setting(file, kind) => { - (file, kind) - } - }; - - if let Handle::Tcp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - let get_timeout = |timeout: &Option, buf: &mut [u8]| -> Result { - if let Some(ref timespec) = *timeout { - timespec.deref().read(buf).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO))) - } else { - Ok(0) - } - }; - - match kind { - SettingKind::Ttl => { - if let Some(mut ttl) = buf.get_mut(0) { - *ttl = handle.ttl; - Ok(1) - } else { - Ok(0) - } - }, - SettingKind::ReadTimeout => { - get_timeout(&handle.read_timeout, buf) - }, - SettingKind::WriteTimeout => { - get_timeout(&handle.write_timeout, buf) - } - } - } else { - Err(Error::new(EBADF)) - } - } - - fn write(&mut self, file: usize, buf: &[u8]) -> Result { - let (file, kind) = match *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - Handle::Tcp(ref mut handle) => { - if ! handle.is_connected() { - return Err(Error::new(ENOTCONN)); - } else if buf.len() >= 65507 { - return Err(Error::new(EMSGSIZE)); - } else { - match handle.state { - State::Established => { - let tcp = handle.create_tcp(TCP_ACK | TCP_PSH, buf.to_vec()); - let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?; - handle.seq += buf.len() as u32; - return Ok(buf.len()); - }, - _ => { - return Err(Error::new(EWOULDBLOCK)); - } - } - } - }, - Handle::Setting(file, kind) => { - (file, kind) - } - }; - - if let Handle::Tcp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - let set_timeout = |timeout: &mut Option, buf: &[u8]| -> Result { - if buf.len() >= mem::size_of::() { - let mut timespec = TimeSpec::default(); - let count = timespec.deref_mut().write(buf).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?; - *timeout = Some(timespec); - Ok(count) - } else { - *timeout = None; - Ok(0) - } - }; - - match kind { - SettingKind::Ttl => { - if let Some(ttl) = buf.get(0) { - handle.ttl = *ttl; - Ok(1) - } else { - Ok(0) - } - }, - SettingKind::ReadTimeout => { - set_timeout(&mut handle.read_timeout, buf) - }, - SettingKind::WriteTimeout => { - set_timeout(&mut handle.write_timeout, buf) - } - } - } else { - Err(Error::new(EBADF)) - } - } - - fn fcntl(&mut self, file: usize, cmd: usize, arg: usize) -> Result { - if let Handle::Tcp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - match cmd { - F_GETFL => Ok(handle.flags), - F_SETFL => { - handle.flags = arg & ! O_ACCMODE; - Ok(0) - }, - _ => Err(Error::new(EINVAL)) - } - } else { - Err(Error::new(EBADF)) - } - } - - fn fevent(&mut self, file: usize, flags: usize) -> Result { - if let Handle::Tcp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - handle.events = flags; - Ok(file) - } else { - Err(Error::new(EBADF)) - } - } - - fn fpath(&mut self, file: usize, buf: &mut [u8]) -> Result { - if let Handle::Tcp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - let path_string = format!("udp:{}:{}/{}:{}", handle.remote.0.to_string(), handle.remote.1, handle.local.0.to_string(), handle.local.1); - let path = path_string.as_bytes(); - - let mut i = 0; - while i < buf.len() && i < path.len() { - buf[i] = path[i]; - i += 1; - } - - Ok(i) - } else { - Err(Error::new(EBADF)) - } - } - - fn fsync(&mut self, file: usize) -> Result { - let _handle = self.handles.get(&file).ok_or(Error::new(EBADF))?; - - Ok(0) - } - - fn close(&mut self, file: usize) -> Result { - let closed = { - if let Handle::Tcp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - handle.data.clear(); - - match handle.state { - State::SynReceived | State::Established => { - handle.state = State::FinWait1; - - let tcp = handle.create_tcp(TCP_FIN | TCP_ACK, Vec::new()); - let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?; - - handle.seq += 1; - - false - }, - State::CloseWait => { - handle.state = State::LastAck; - - let tcp = handle.create_tcp(TCP_FIN | TCP_ACK, Vec::new()); - let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?; - - handle.seq += 1; - - false - }, - _ => true - } - } else { - true - } - }; - - if closed { - if let Handle::Tcp(handle) = self.handles.remove(&file).ok_or(Error::new(EBADF))? { - let remove = if let Some(mut port) = self.ports.get_mut(&handle.local.1) { - *port = *port + 1; - *port == 0 - } else { - false - }; - - if remove { - self.ports.remove(&handle.local.1); - } - } - } - - Ok(0) - } -} - -fn daemon(scheme_fd: usize, tcp_fd: usize, time_fd: usize) { - let scheme_file = unsafe { File::from_raw_fd(scheme_fd) }; - let tcp_file = unsafe { File::from_raw_fd(tcp_fd) }; - let time_file = unsafe { File::from_raw_fd(time_fd) }; - - let tcpd = Rc::new(RefCell::new(Tcpd::new(scheme_file, tcp_file, time_file))); - - let mut event_queue = EventQueue::<()>::new().expect("tcpd: failed to create event queue"); - - let time_tcpd = tcpd.clone(); - event_queue.add(time_fd, move |_count: usize| -> io::Result> { - time_tcpd.borrow_mut().time_event()?; - Ok(None) - }).expect("tcpd: failed to listen to events on time:"); - - let tcp_tcpd = tcpd.clone(); - event_queue.add(tcp_fd, move |_count: usize| -> io::Result> { - tcp_tcpd.borrow_mut().tcp_event()?; - Ok(None) - }).expect("tcpd: failed to listen to events on ip:6"); - - event_queue.add(scheme_fd, move |_count: usize| -> io::Result> { - tcpd.borrow_mut().scheme_event()?; - Ok(None) - }).expect("tcpd: failed to listen to events on :tcp"); - - event_queue.trigger_all(0).expect("tcpd: failed to trigger event queue"); - - event_queue.run().expect("tcpd: failed to run event queue"); -} - -fn main() { - let time_path = format!("time:{}", CLOCK_MONOTONIC); - match syscall::open(&time_path, O_RDWR) { - Ok(time_fd) => { - match syscall::open("ip:6", O_RDWR | O_NONBLOCK) { - Ok(tcp_fd) => { - // Daemonize - if unsafe { syscall::clone(0).unwrap() } == 0 { - match syscall::open(":tcp", O_RDWR | O_CREAT | O_NONBLOCK) { - Ok(scheme_fd) => { - daemon(scheme_fd, tcp_fd, time_fd); - }, - Err(err) => { - println!("tcpd: failed to create tcp scheme: {}", err); - process::exit(1); - } - } - } - }, - Err(err) => { - println!("tcpd: failed to open ip:6: {}", err); - process::exit(1); - } - } - }, - Err(err) => { - println!("tcpd: failed to open {}: {}", time_path, err); - process::exit(1); - } - } -} diff --git a/schemes/udpd/Cargo.toml b/schemes/udpd/Cargo.toml deleted file mode 100644 index d7dc3e3..0000000 --- a/schemes/udpd/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "udpd" -version = "0.1.0" - -[dependencies] -netutils = { git = "https://github.com/redox-os/netutils.git" } -rand = "0.3" -redox_event = { git = "https://github.com/redox-os/event.git" } -redox_syscall = "0.1" diff --git a/schemes/udpd/src/main.rs b/schemes/udpd/src/main.rs deleted file mode 100644 index 23d6479..0000000 --- a/schemes/udpd/src/main.rs +++ /dev/null @@ -1,586 +0,0 @@ -extern crate event; -extern crate netutils; -extern crate rand; -extern crate syscall; - -use rand::{Rng, OsRng}; -use std::collections::{BTreeMap, VecDeque}; -use std::cell::RefCell; -use std::fs::File; -use std::io::{self, Read, Write}; -use std::{mem, process, slice, str}; -use std::ops::{Deref, DerefMut}; -use std::os::unix::io::FromRawFd; -use std::rc::Rc; - -use event::EventQueue; -use netutils::{n16, Ipv4, Ipv4Addr, Ipv4Header, Checksum}; -use netutils::udp::{Udp, UdpHeader}; -use syscall::data::{Packet, TimeSpec}; -use syscall::error::{Error, Result, EACCES, EADDRINUSE, EBADF, EIO, EINVAL, EMSGSIZE, ENOTCONN, ETIMEDOUT, EWOULDBLOCK}; -use syscall::flag::{CLOCK_MONOTONIC, EVENT_READ, F_GETFL, F_SETFL, O_ACCMODE, O_CREAT, O_RDWR, O_NONBLOCK}; -use syscall::number::{SYS_READ, SYS_WRITE}; -use syscall::scheme::SchemeMut; - -fn add_time(a: &TimeSpec, b: &TimeSpec) -> TimeSpec { - let mut secs = a.tv_sec + b.tv_sec; - - let mut nsecs = a.tv_nsec + b.tv_nsec; - while nsecs >= 1000000000 { - nsecs -= 1000000000; - secs += 1; - } - - TimeSpec { - tv_sec: secs, - tv_nsec: nsecs - } -} - -fn parse_socket(socket: &str) -> (Ipv4Addr, u16) { - let mut socket_parts = socket.split(":"); - let host = Ipv4Addr::from_str(socket_parts.next().unwrap_or("")); - let port = socket_parts.next().unwrap_or("").parse::().unwrap_or(0); - (host, port) -} - -struct UdpHandle { - local: (Ipv4Addr, u16), - remote: (Ipv4Addr, u16), - flags: usize, - events: usize, - read_timeout: Option, - write_timeout: Option, - ttl: u8, - data: VecDeque>, - todo: VecDeque<(Option, Packet)>, -} - -#[derive(Copy, Clone)] -enum SettingKind { - Ttl, - ReadTimeout, - WriteTimeout -} - -enum Handle { - Udp(UdpHandle), - Setting(usize, SettingKind), -} - -struct Udpd { - scheme_file: File, - udp_file: File, - time_file: File, - ports: BTreeMap, - next_id: usize, - handles: BTreeMap, - rng: OsRng, -} - -impl Udpd { - fn new(scheme_file: File, udp_file: File, time_file: File) -> Self { - Udpd { - scheme_file: scheme_file, - udp_file: udp_file, - time_file: time_file, - ports: BTreeMap::new(), - next_id: 1, - handles: BTreeMap::new(), - rng: OsRng::new().expect("udpd: failed to open RNG") - } - } - - fn scheme_event(&mut self) -> io::Result<()> { - loop { - let mut packet = Packet::default(); - if self.scheme_file.read(&mut packet)? == 0 { - break; - } - - let a = packet.a; - self.handle(&mut packet); - if packet.a == (-EWOULDBLOCK) as usize { - packet.a = a; - if let Some(mut handle) = self.handles.get_mut(&packet.b) { - if let Handle::Udp(ref mut handle) = *handle { - let timeout = match packet.a { - SYS_READ => match handle.read_timeout { - Some(read_timeout) => { - let mut time = TimeSpec::default(); - syscall::clock_gettime(CLOCK_MONOTONIC, &mut time).map_err(|err| io::Error::from_raw_os_error(err.errno))?; - - let timeout = add_time(&time, &read_timeout); - self.time_file.write(&timeout)?; - Some(timeout) - }, - None => None - }, - SYS_WRITE => match handle.write_timeout { - Some(write_timeout) => { - let mut time = TimeSpec::default(); - syscall::clock_gettime(CLOCK_MONOTONIC, &mut time).map_err(|err| io::Error::from_raw_os_error(err.errno))?; - - let timeout = add_time(&time, &write_timeout); - self.time_file.write(&timeout)?; - Some(timeout) - }, - None => None - }, - _ => None - }; - - handle.todo.push_back((timeout, packet)); - } - } - } else { - self.scheme_file.write(&packet)?; - } - } - - Ok(()) - } - - fn udp_event(&mut self) -> io::Result<()> { - loop { - let mut bytes = [0; 65536]; - let count = self.udp_file.read(&mut bytes)?; - if count == 0 { - break; - } - if let Some(ip) = Ipv4::from_bytes(&bytes[.. count]) { - if let Some(udp) = Udp::from_bytes(&ip.data) { - for (id, handle) in self.handles.iter_mut() { - if let Handle::Udp(ref mut handle) = *handle { - // Local address not set or IP dst matches or is broadcast - if (handle.local.0 == Ipv4Addr::NULL || ip.header.dst == handle.local.0 || ip.header.dst == Ipv4Addr::BROADCAST) - // Local port matches UDP dst - && udp.header.dst.get() == handle.local.1 - // Remote address not set or is broadcast, or IP src matches - && (handle.remote.0 == Ipv4Addr::NULL || handle.remote.0 == Ipv4Addr::BROADCAST || ip.header.src == handle.remote.0) - // Remote port not set or UDP src matches - && (handle.remote.1 == 0 || udp.header.src.get() == handle.remote.1) - { - handle.data.push_back(udp.data.clone()); - - while ! handle.todo.is_empty() && ! handle.data.is_empty() { - let (_timeout, mut packet) = handle.todo.pop_front().unwrap(); - let buf = unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }; - let data = handle.data.pop_front().unwrap(); - - let mut i = 0; - while i < buf.len() && i < data.len() { - buf[i] = data[i]; - i += 1; - } - packet.a = i; - - self.scheme_file.write(&packet)?; - } - - if handle.events & EVENT_READ == EVENT_READ { - if let Some(data) = handle.data.get(0) { - self.scheme_file.write(&Packet { - id: 0, - pid: 0, - uid: 0, - gid: 0, - a: syscall::number::SYS_FEVENT, - b: *id, - c: EVENT_READ, - d: data.len() - })?; - } - } - } - } - } - } - } - } - - Ok(()) - } - - fn time_event(&mut self) -> io::Result<()> { - let mut time = TimeSpec::default(); - if self.time_file.read(&mut time)? < mem::size_of::() { - return Err(io::Error::from_raw_os_error(EINVAL)); - } - - for (_id, handle) in self.handles.iter_mut() { - if let Handle::Udp(ref mut handle) = *handle { - let mut i = 0; - while i < handle.todo.len() { - if let Some(timeout) = handle.todo.get(i).map(|e| e.0.clone()).unwrap_or(None) { - if time.tv_sec > timeout.tv_sec || (time.tv_sec == timeout.tv_sec && time.tv_nsec >= timeout.tv_nsec) { - let (_timeout, mut packet) = handle.todo.remove(i).unwrap(); - packet.a = (-ETIMEDOUT) as usize; - self.scheme_file.write(&packet)?; - } else { - i += 1; - } - } else { - i += 1; - } - } - } - } - - Ok(()) - } -} - -impl SchemeMut for Udpd { - fn open(&mut self, url: &[u8], flags: usize, uid: u32, _gid: u32) -> Result { - let path = str::from_utf8(url).or(Err(Error::new(EINVAL)))?; - - let mut parts = path.split("/"); - let remote = parse_socket(parts.next().unwrap_or("")); - let mut local = parse_socket(parts.next().unwrap_or("")); - - if local.1 == 0 { - local.1 = self.rng.gen_range(32768, 65535); - } - - if local.1 <= 1024 && uid != 0 { - return Err(Error::new(EACCES)); - } - - if self.ports.contains_key(&local.1) { - return Err(Error::new(EADDRINUSE)); - } - - self.ports.insert(local.1, 1); - - let id = self.next_id; - self.next_id += 1; - - self.handles.insert(id, Handle::Udp(UdpHandle { - local: local, - remote: remote, - flags: flags, - events: 0, - ttl: 64, - read_timeout: None, - write_timeout: None, - data: VecDeque::new(), - todo: VecDeque::new(), - })); - - Ok(id) - } - - fn dup(&mut self, file: usize, buf: &[u8]) -> Result { - let handle = match *self.handles.get(&file).ok_or(Error::new(EBADF))? { - Handle::Udp(ref handle) => { - let mut handle = UdpHandle { - local: handle.local, - remote: handle.remote, - flags: handle.flags, - events: 0, - ttl: handle.ttl, - read_timeout: handle.read_timeout, - write_timeout: handle.write_timeout, - data: handle.data.clone(), - todo: VecDeque::new(), - }; - - let path = str::from_utf8(buf).or(Err(Error::new(EINVAL)))?; - - if path == "ttl" { - Handle::Setting(file, SettingKind::Ttl) - } else if path == "read_timeout" { - Handle::Setting(file, SettingKind::ReadTimeout) - } else if path == "write_timeout" { - Handle::Setting(file, SettingKind::WriteTimeout) - } else { - if handle.remote.0 == Ipv4Addr::NULL || handle.remote.1 == 0 { - handle.remote = parse_socket(path); - } - - if let Some(mut port) = self.ports.get_mut(&handle.local.1) { - *port = *port + 1; - } - - Handle::Udp(handle) - } - }, - Handle::Setting(file, kind) => { - Handle::Setting(file, kind) - } - }; - - let id = self.next_id; - self.next_id += 1; - - self.handles.insert(id, handle); - - Ok(id) - } - - fn read(&mut self, file: usize, buf: &mut [u8]) -> Result { - let (file, kind) = match *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - Handle::Udp(ref mut handle) => { - if handle.remote.0 == Ipv4Addr::NULL || handle.remote.1 == 0 { - return Err(Error::new(ENOTCONN)); - } else if let Some(data) = handle.data.pop_front() { - let mut i = 0; - while i < buf.len() && i < data.len() { - buf[i] = data[i]; - i += 1; - } - - return Ok(i); - } else if handle.flags & O_NONBLOCK == O_NONBLOCK { - return Ok(0); - } else { - return Err(Error::new(EWOULDBLOCK)); - } - }, - Handle::Setting(file, kind) => { - (file, kind) - } - }; - - if let Handle::Udp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - let get_timeout = |timeout: &Option, buf: &mut [u8]| -> Result { - if let Some(ref timespec) = *timeout { - timespec.deref().read(buf).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO))) - } else { - Ok(0) - } - }; - - match kind { - SettingKind::Ttl => { - if let Some(mut ttl) = buf.get_mut(0) { - *ttl = handle.ttl; - Ok(1) - } else { - Ok(0) - } - }, - SettingKind::ReadTimeout => { - get_timeout(&handle.read_timeout, buf) - }, - SettingKind::WriteTimeout => { - get_timeout(&handle.write_timeout, buf) - } - } - } else { - Err(Error::new(EBADF)) - } - } - - fn write(&mut self, file: usize, buf: &[u8]) -> Result { - let (file, kind) = match *self.handles.get(&file).ok_or(Error::new(EBADF))? { - Handle::Udp(ref handle) => { - if handle.remote.0 == Ipv4Addr::NULL || handle.remote.1 == 0 { - return Err(Error::new(ENOTCONN)); - } else if buf.len() >= 65507 { - return Err(Error::new(EMSGSIZE)); - } else { - let udp_data = buf.to_vec(); - - let udp = Udp { - header: UdpHeader { - src: n16::new(handle.local.1), - dst: n16::new(handle.remote.1), - len: n16::new((udp_data.len() + mem::size_of::()) as u16), - checksum: Checksum { data: 0 } - }, - data: udp_data - }; - - let ip_data = udp.to_bytes(); - - let ip = Ipv4 { - header: Ipv4Header { - ver_hlen: 0x45, - services: 0, - len: n16::new((ip_data.len() + mem::size_of::()) as u16), - id: n16::new(self.rng.gen()), - flags_fragment: n16::new(0), - ttl: handle.ttl, - proto: 0x11, - checksum: Checksum { data: 0 }, - src: handle.local.0, - dst: handle.remote.0 - }, - options: Vec::new(), - data: ip_data - }; - - return self.udp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO))).and(Ok(buf.len())); - } - }, - Handle::Setting(file, kind) => { - (file, kind) - } - }; - - if let Handle::Udp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - let set_timeout = |timeout: &mut Option, buf: &[u8]| -> Result { - if buf.len() >= mem::size_of::() { - let mut timespec = TimeSpec::default(); - let count = timespec.deref_mut().write(buf).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?; - *timeout = Some(timespec); - Ok(count) - } else { - *timeout = None; - Ok(0) - } - }; - - match kind { - SettingKind::Ttl => { - if let Some(ttl) = buf.get(0) { - handle.ttl = *ttl; - Ok(1) - } else { - Ok(0) - } - }, - SettingKind::ReadTimeout => { - set_timeout(&mut handle.read_timeout, buf) - }, - SettingKind::WriteTimeout => { - set_timeout(&mut handle.write_timeout, buf) - } - } - } else { - Err(Error::new(EBADF)) - } - } - - fn fcntl(&mut self, file: usize, cmd: usize, arg: usize) -> Result { - if let Handle::Udp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - match cmd { - F_GETFL => Ok(handle.flags), - F_SETFL => { - handle.flags = arg & ! O_ACCMODE; - Ok(0) - }, - _ => Err(Error::new(EINVAL)) - } - } else { - Err(Error::new(EBADF)) - } - } - - fn fevent(&mut self, file: usize, flags: usize) -> Result { - if let Handle::Udp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - handle.events = flags; - Ok(file) - } else { - Err(Error::new(EBADF)) - } - } - - fn fpath(&mut self, file: usize, buf: &mut [u8]) -> Result { - if let Handle::Udp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - let path_string = format!("udp:{}:{}/{}:{}", handle.remote.0.to_string(), handle.remote.1, handle.local.0.to_string(), handle.local.1); - let path = path_string.as_bytes(); - - let mut i = 0; - while i < buf.len() && i < path.len() { - buf[i] = path[i]; - i += 1; - } - - Ok(i) - } else { - Err(Error::new(EBADF)) - } - } - - fn fsync(&mut self, file: usize) -> Result { - let _handle = self.handles.get(&file).ok_or(Error::new(EBADF))?; - - Ok(0) - } - - fn close(&mut self, file: usize) -> Result { - let handle = self.handles.remove(&file).ok_or(Error::new(EBADF))?; - - if let Handle::Udp(ref handle) = handle { - let remove = if let Some(mut port) = self.ports.get_mut(&handle.local.1) { - *port = *port + 1; - *port == 0 - } else { - false - }; - - if remove { - drop(self.ports.remove(&handle.local.1)); - } - } - - drop(handle); - - Ok(0) - } -} -fn daemon(scheme_fd: usize, udp_fd: usize, time_fd: usize) { - let scheme_file = unsafe { File::from_raw_fd(scheme_fd) }; - let udp_file = unsafe { File::from_raw_fd(udp_fd) }; - let time_file = unsafe { File::from_raw_fd(time_fd) }; - - let udpd = Rc::new(RefCell::new(Udpd::new(scheme_file, udp_file, time_file))); - - let mut event_queue = EventQueue::<()>::new().expect("udpd: failed to create event queue"); - - let time_udpd = udpd.clone(); - event_queue.add(time_fd, move |_count: usize| -> io::Result> { - time_udpd.borrow_mut().time_event()?; - Ok(None) - }).expect("udpd: failed to listen to events on time:"); - - let udp_udpd = udpd.clone(); - event_queue.add(udp_fd, move |_count: usize| -> io::Result> { - udp_udpd.borrow_mut().udp_event()?; - Ok(None) - }).expect("udpd: failed to listen to events on ip:11"); - - event_queue.add(scheme_fd, move |_count: usize| -> io::Result> { - udpd.borrow_mut().scheme_event()?; - Ok(None) - }).expect("udpd: failed to listen to events on :udp"); - - event_queue.trigger_all(0).expect("udpd: failed to trigger event queue"); - - event_queue.run().expect("udpd: failed to run event queue"); -} - -fn main() { - let time_path = format!("time:{}", CLOCK_MONOTONIC); - match syscall::open(&time_path, O_RDWR) { - Ok(time_fd) => { - match syscall::open("ip:11", O_RDWR | O_NONBLOCK) { - Ok(udp_fd) => { - // Daemonize - if unsafe { syscall::clone(0).unwrap() } == 0 { - match syscall::open(":udp", O_RDWR | O_CREAT | O_NONBLOCK) { - Ok(scheme_fd) => { - daemon(scheme_fd, udp_fd, time_fd); - }, - Err(err) => { - println!("udpd: failed to create udp scheme: {}", err); - process::exit(1); - } - } - } - }, - Err(err) => { - println!("udpd: failed to open ip:11: {}", err); - process::exit(1); - } - } - }, - Err(err) => { - println!("udpd: failed to open {}: {}", time_path, err); - process::exit(1); - } - } -} From 5224a4cdca8d250c2ced65d8564ab60ef8ba6aad Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 10 May 2017 21:41:15 -0600 Subject: [PATCH 339/522] Remove flash.sh (it still needs work) --- flash.sh | 23 ----------------------- 1 file changed, 23 deletions(-) delete mode 100755 flash.sh diff --git a/flash.sh b/flash.sh deleted file mode 100755 index 5099457..0000000 --- a/flash.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash -set -e - -ISO="build/livedisk.iso" -DISK="/dev/disk/by-id/usb-Generic_USB_SD_Reader_12345678901234567890-0:0" - -if [ ! -f "$ISO" ] -then - echo "Did not find ISO $ISO" - exit 1 -fi - -if [ ! -b "$DISK" ] -then - echo "Did not find disk $DISK" - exit 1 -fi - -echo "Flashing $ISO to $DISK" -pv "$ISO" | sudo dd of="$DISK" -sync -sudo eject "$DISK" -echo "Successfully flashed $DISK" From 3338b39c6950e3ec98de1cd529a025da287fd2dd Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 10 May 2017 21:50:53 -0600 Subject: [PATCH 340/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index 0506e36..1fb6bec 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 0506e3602e7e59de94a0e6c200d9aef82fe8e82c +Subproject commit 1fb6beca6361c2642b8829b9ddf922299c1984d6 From 734e21cb562b8b63dd5bc2faeed77cc495d4e816 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 10 May 2017 21:55:04 -0600 Subject: [PATCH 341/522] Use pcid.toml from drivers --- filesystem.toml | 48 ------------------------------------------------ initfs.toml | 37 ------------------------------------- 2 files changed, 85 deletions(-) diff --git a/filesystem.toml b/filesystem.toml index d876abe..f3f85d3 100644 --- a/filesystem.toml +++ b/filesystem.toml @@ -12,7 +12,6 @@ acid = {} binutils = {} contain = {} coreutils = {} -drivers = {} extrautils = {} games = {} init = {} @@ -52,7 +51,6 @@ path = "/etc/init.d/00_base" data = """ randd ptyd -pcid /etc/pcid.toml """ [[files]] @@ -127,49 +125,3 @@ data = """ Welcome to Redox OS! """ - -[[files]] -path = "/etc/pcid.toml" -data = """ -[[drivers]] -name = "82543GC NIC" -class = 2 -vendor = 32902 -device = 4100 -command = ["e1000d", "$NAME", "$BAR0", "$IRQ"] - -[[drivers]] -name = "82540EM NIC" -class = 2 -vendor = 32902 -device = 4110 -command = ["e1000d", "$NAME", "$BAR0", "$IRQ"] - -[[drivers]] -name = "82545EM NIC" -class = 2 -vendor = 32902 -device = 4111 -command = ["e1000d", "$NAME", "$BAR0", "$IRQ"] - -[[drivers]] -name = "82579V NIC" -class = 2 -vendor = 32902 -device = 5379 -command = ["e1000d", "$NAME", "$BAR0", "$IRQ"] - -[[drivers]] -name = "RTL8168 NIC" -class = 2 -vendor = 4332 -device = 33128 -command = ["rtl8168d", "$NAME", "$BAR2", "$IRQ"] - -[[drivers]] -name = "XHCI" -class = 12 -subclass = 3 -interface = 48 -command = ["xhcid", "$NAME", "$BAR0", "$IRQ"] -""" diff --git a/initfs.toml b/initfs.toml index c64b788..dcb005b 100644 --- a/initfs.toml +++ b/initfs.toml @@ -25,40 +25,3 @@ cd file: export PATH file:/bin run.d /etc/init.d """ - -[[files]] -path="/etc/pcid.toml" -data=""" -[[drivers]] -name = "AHCI storage" -class = 1 -subclass = 6 -command = ["ahcid", "$NAME", "$BAR5", "$IRQ"] - -[[drivers]] -name = "NVME storage" -class = 1 -subclass = 8 -command = ["nvmed", "$NAME", "$BAR0", "$IRQ"] - -[[drivers]] -name = "QEMU Graphics Array" -class = 3 -vendor = 4660 -device = 4369 -command = ["bgad", "$NAME", "$BAR0"] - -[[drivers]] -name = "VirtualBox Graphics Array" -class = 3 -vendor = 33006 -device = 48879 -command = ["bgad", "$NAME", "$BAR0"] - -[[drivers]] -name = "VirtualBox Guest Device" -class = 8 -vendor = 33006 -device = 51966 -command = ["vboxd", "$NAME", "$BAR0", "$BAR1", "$IRQ"] -""" From 1103beb7b3067434af6e68623238b4c9da5aa1a9 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 10 May 2017 23:12:19 -0600 Subject: [PATCH 342/522] Remove update target --- Makefile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Makefile b/Makefile index 7eb8525..951f39b 100644 --- a/Makefile +++ b/Makefile @@ -12,16 +12,12 @@ clean: -$(FUMOUNT) build/filesystem/ || true rm -rf build -update: - cargo update - pull: git pull --rebase --recurse-submodules git submodule sync git submodule update --recursive --init git clean -X -f -d make clean - make update # Emulation recipes include mk/qemu.mk From d2363a06c6db4f478cc4ded13061d59d9316ca2d Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 11 May 2017 20:55:47 -0600 Subject: [PATCH 343/522] Update cookbook and installer --- cookbook | 2 +- installer | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cookbook b/cookbook index 1fb6bec..b3ad568 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 1fb6beca6361c2642b8829b9ddf922299c1984d6 +Subproject commit b3ad568eda0530ae94964d9e3210236478334414 diff --git a/installer b/installer index 318e7bb..31a60eb 160000 --- a/installer +++ b/installer @@ -1 +1 @@ -Subproject commit 318e7bb89f37228984bc92976ecdb28adb63dcf0 +Subproject commit 31a60eb8a32315e1f5f610f6c6d19d1cec61649c From 10d2e9c1f4e7d01f12bf2ffd59886cd5343e01f3 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 11 May 2017 21:16:24 -0600 Subject: [PATCH 344/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index 62d3f4b..32b0c06 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 62d3f4bd93c425b263bd9b762632f4601e0ec1c5 +Subproject commit 32b0c06314363a4993db4cd308010a63bd261b7c From 056f2f112be472548722bad3b1e24e57ca8d0333 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 11 May 2017 21:17:00 -0600 Subject: [PATCH 345/522] Update bootloader --- bootloader | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootloader b/bootloader index 787f018..155e86a 160000 --- a/bootloader +++ b/bootloader @@ -1 +1 @@ -Subproject commit 787f0184fa96a227e51a7ce083a29b06f8945fd8 +Subproject commit 155e86a846b05a7f416fc102d0046c3cb722dd8c From 737b9c4c60739c98fb57b89195875055628c2f83 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 11 May 2017 21:19:31 -0600 Subject: [PATCH 346/522] Update recipes --- mk/disk.mk | 6 +++--- mk/kernel.mk | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mk/disk.mk b/mk/disk.mk index d0a8972..ed926ba 100644 --- a/mk/disk.mk +++ b/mk/disk.mk @@ -1,8 +1,8 @@ -build/harddrive.bin: build/kernel bootloader/$(ARCH)/** build/filesystem.bin - nasm -f bin -o $@ -D ARCH_$(ARCH) -ibootloader/$(ARCH)/ bootloader/$(ARCH)/harddrive.asm +build/harddrive.bin: build/kernel build/filesystem.bin bootloader/$(ARCH)/** + nasm -f bin -o $@ -D ARCH_$(ARCH) -D KERNEL=$< -D FILESYSTEM=build/filesystem.bin -ibootloader/$(ARCH)/ bootloader/$(ARCH)/disk.asm build/livedisk.bin: build/kernel_live bootloader/$(ARCH)/** - nasm -f bin -o $@ -D ARCH_$(ARCH) -ibootloader/$(ARCH)/ bootloader/$(ARCH)/livedisk.asm + nasm -f bin -o $@ -D ARCH_$(ARCH) -D KERNEL=$< -ibootloader/$(ARCH)/ bootloader/$(ARCH)/disk.asm build/%.bin.gz: build/%.bin gzip -k -f $< diff --git a/mk/kernel.mk b/mk/kernel.mk index 6b9cc48..5293900 100644 --- a/mk/kernel.mk +++ b/mk/kernel.mk @@ -1,8 +1,8 @@ -build/libkernel.a: kernel/Cargo.toml kernel/src/** build/initfs.tag +build/libkernel.a: kernel/Cargo.toml kernel/src/* kernel/src/*/* kernel/src/*/*/* build/initfs.tag cd kernel && xargo rustc --lib --target $(KTARGET) --release -- -C soft-float --emit link=../$@ -build/libkernel_live.a: kernel/Cargo.toml kernel/src/** build/initfs.tag build/filesystem.bin - cd kernel && xargo rustc --lib --features live --target $(KTARGET) --release -- -C soft-float --emit link=../$@ +build/libkernel_live.a: kernel/Cargo.toml kernel/src/* kernel/src/*/* kernel/src/*/*/* build/initfs.tag build/filesystem.bin + cd kernel && FILESYSTEM="$(PWD)/build/filesystem.bin" xargo rustc --lib --features live --target $(KTARGET) --release -- -C soft-float --emit link=../$@ build/kernel: build/libkernel.a $(LD) --gc-sections -z max-page-size=0x1000 -T kernel/linkers/$(ARCH).ld -o $@ $< From 3679387fd209ab54434d854840d328b1c988db6e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 11 May 2017 21:44:18 -0600 Subject: [PATCH 347/522] Update bootloader and travis --- .travis.yml | 4 ++-- bootloader | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index d8e9d69..20d3c7f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,8 +24,8 @@ before_install: travis_wait 30 brew install redox-os/gcc_cross_compilers/x86_64-elf-gcc; fi script: -- make clean && - make update && +- cd cookbook && ./fetch.sh && cd .. && + make clean && make build/harddrive.bin.gz build/livedisk.bin.gz build/livedisk.iso notifications: email: false diff --git a/bootloader b/bootloader index 155e86a..76d3431 160000 --- a/bootloader +++ b/bootloader @@ -1 +1 @@ -Subproject commit 155e86a846b05a7f416fc102d0046c3cb722dd8c +Subproject commit 76d3431d89793ab13e1996ef4d3c6ec7c79acbc7 From d7511b8164574d5340010885575daaab43cabb68 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 11 May 2017 21:57:36 -0600 Subject: [PATCH 348/522] Install xargo --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 20d3c7f..a57c1fd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,6 +23,7 @@ before_install: brew install nasm pkg-config Caskroom/cask/osxfuse && travis_wait 30 brew install redox-os/gcc_cross_compilers/x86_64-elf-gcc; fi +- cargo install xargo script: - cd cookbook && ./fetch.sh && cd .. && make clean && From 2f481d536349cfc53d6ec48ffadb63453eda7c96 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 11 May 2017 21:58:02 -0600 Subject: [PATCH 349/522] Use cookbook setup.sh --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a57c1fd..fd2b81a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,7 @@ before_install: brew install nasm pkg-config Caskroom/cask/osxfuse && travis_wait 30 brew install redox-os/gcc_cross_compilers/x86_64-elf-gcc; fi -- cargo install xargo +- cd cookbook && ./setup.sh && cd .. script: - cd cookbook && ./fetch.sh && cd .. && make clean && From 01d728cbe08f892da9e3eb9f8823d48f3d999fd1 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 12 May 2017 20:36:25 -0600 Subject: [PATCH 350/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index b3ad568..b91b276 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit b3ad568eda0530ae94964d9e3210236478334414 +Subproject commit b91b2762d6360da65703631f4b733ea38c5b47e5 From aaa96bf3296258cc3ef5139eb4c8f13e383311d3 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 12 May 2017 20:37:59 -0600 Subject: [PATCH 351/522] Disable a few packages in default build, use partial filesystem to avoid incomplete build --- filesystem.toml | 8 ++++---- mk/filesystem.mk | 9 ++++---- mk/qemu.mk | 53 ++++++++++++++++++++++++++++++++---------------- 3 files changed, 44 insertions(+), 26 deletions(-) diff --git a/filesystem.toml b/filesystem.toml index f3f85d3..355a1bb 100644 --- a/filesystem.toml +++ b/filesystem.toml @@ -8,16 +8,16 @@ sysroot = "build/filesystem" # Package settings [packages] -acid = {} -binutils = {} +#acid = {} +#binutils = {} contain = {} coreutils = {} extrautils = {} -games = {} +#games = {} init = {} installer = {} ion = {} -lua = {} +#lua = {} netstack = {} netutils = {} orbdata = {} diff --git a/mk/filesystem.mk b/mk/filesystem.mk index cce220b..6516b10 100644 --- a/mk/filesystem.mk +++ b/mk/filesystem.mk @@ -1,11 +1,11 @@ build/filesystem.bin: filesystem.toml -$(FUMOUNT) build/filesystem/ || true - rm -rf $@ build/filesystem/ - dd if=/dev/zero of=$@ bs=1048576 count=128 - cargo run --manifest-path installer/redoxfs/Cargo.toml --quiet --release --bin redoxfs-mkfs $@ + rm -rf $@ $@.partial build/filesystem/ + dd if=/dev/zero of=$@.partial bs=1048576 count=128 + cargo run --manifest-path installer/redoxfs/Cargo.toml --quiet --release --bin redoxfs-mkfs $@.partial mkdir -p build/filesystem/ cargo build --manifest-path installer/redoxfs/Cargo.toml --quiet --release --bin redoxfs - cargo run --manifest-path installer/redoxfs/Cargo.toml --quiet --release --bin redoxfs -- $@ build/filesystem/ + cargo run --manifest-path installer/redoxfs/Cargo.toml --quiet --release --bin redoxfs -- $@.partial build/filesystem/ sleep 2 pgrep redoxfs cargo run --manifest-path installer/Cargo.toml -- --cookbook=cookbook $< @@ -27,6 +27,7 @@ build/filesystem.bin: filesystem.toml sync -$(FUMOUNT) build/filesystem/ || true rm -rf build/filesystem/ + mv $@.partial $@ mount: FORCE mkdir -p build/filesystem/ diff --git a/mk/qemu.mk b/mk/qemu.mk index c1a31da..a76d9f9 100644 --- a/mk/qemu.mk +++ b/mk/qemu.mk @@ -28,28 +28,45 @@ endif #,int,pcall #-device intel-iommu -qemu: build/harddrive.bin - $(QEMU) $(QEMUFLAGS) -drive file=$<,format=raw +build/extra.qcow2: + qemu-img create -f qcow2 $@ 256M -qemu_no_build: - $(QEMU) $(QEMUFLAGS) -drive file=build/harddrive.bin,format=raw +qemu: build/harddrive.bin build/extra.qcow2 + $(QEMU) $(QEMUFLAGS) \ + -drive file=build/harddrive.bin,format=raw \ + -drive file=build/extra.qcow2 -qemu_extra: build/harddrive.bin - if [ ! -e build/extra.bin ]; then dd if=/dev/zero of=build/extra.bin bs=1048576 count=1024; fi - $(QEMU) $(QEMUFLAGS) -drive file=$<,format=raw -drive file=build/extra.bin,format=raw,if=none,id=drv0 -device nvme,drive=drv0,serial=NVME_SERIAL +qemu_no_build: build/extra.qcow2 + $(QEMU) $(QEMUFLAGS) \ + -drive file=build/harddrive.bin,format=raw \ + -drive file=build/extra.qcow2 -qemu_extra_no_build: - if [ ! -e build/extra.bin ]; then dd if=/dev/zero of=build/extra.bin bs=1048576 count=1024; fi - $(QEMU) $(QEMUFLAGS) -drive file=$<,format=raw -drive file=build/extra.bin,format=raw +qemu_nvme: build/harddrive.bin build/extra.qcow2 + $(QEMU) $(QEMUFLAGS) \ + -drive file=build/harddrive.bin,format=raw -drive file=build/extra.qcow2,if=none,id=drv0 -device nvme,drive=drv0,serial=NVME_SERIAL \ + -drive file=build/extra.qcow2 -qemu_live: build/livedisk.bin - $(QEMU) $(QEMUFLAGS) -device usb-ehci,id=flash_bus -drive id=flash_drive,file=$<,format=raw,if=none -device usb-storage,drive=flash_drive,bus=flash_bus.0 +qemu_nvme_no_build: build/extra.qcow2 + $(QEMU) $(QEMUFLAGS) \ + -drive file=build/harddrive.bin,format=raw -drive file=build/extra.qcow2,if=none,id=drv0 -device nvme,drive=drv0,serial=NVME_SERIAL \ + -drive file=build/extra.qcow2 -qemu_live_no_build: - $(QEMU) $(QEMUFLAGS) -device usb-ehci,id=flash_bus -drive id=flash_drive,file=build/livedisk.bin,format=raw,if=none -device usb-storage,drive=flash_drive,bus=flash_bus.0 +qemu_live: build/livedisk.bin build/extra.qcow2 + $(QEMU) $(QEMUFLAGS) \ + -device usb-ehci,id=flash_bus -drive id=flash_drive,file=build/livedisk.bin,format=raw,if=none -device usb-storage,drive=flash_drive,bus=flash_bus.0 \ + -drive file=build/extra.qcow2 -qemu_iso: build/livedisk.iso - $(QEMU) $(QEMUFLAGS) -boot d -cdrom $< +qemu_live_no_build: build/extra.qcow2 + $(QEMU) $(QEMUFLAGS) \ + -device usb-ehci,id=flash_bus -drive id=flash_drive,file=build/livedisk.bin,format=raw,if=none -device usb-storage,drive=flash_drive,bus=flash_bus.0 \ + -drive file=build/extra.qcow2 -qemu_iso_no_build: - $(QEMU) $(QEMUFLAGS) -boot d -cdrom build/livedisk.iso +qemu_iso: build/livedisk.iso build/extra.qcow2 + $(QEMU) $(QEMUFLAGS) \ + -boot d -cdrom build/livedisk.iso \ + -drive file=build/extra.qcow2 + +qemu_iso_no_build: build/extra.qcow2 + $(QEMU) $(QEMUFLAGS) \ + -boot d -cdrom build/livedisk.iso \ + -drive file=build/extra.qcow2 From 952530efc8e6e582ad4b11f0c58e49565f89823b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 12 May 2017 21:05:05 -0600 Subject: [PATCH 352/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index 32b0c06..4d2808a 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 32b0c06314363a4993db4cd308010a63bd261b7c +Subproject commit 4d2808a012de5b6d4247a5eeb3ca510034911c7f From e970f79195e5b2c69ba575b3446dc90cb094d92a Mon Sep 17 00:00:00 2001 From: Oliver Jan Krylow Date: Wed, 24 May 2017 22:59:28 +0200 Subject: [PATCH 353/522] Added 'cd redox' in quick setup --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 8e0b8d9..97917f1 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,9 @@ $ cd path/to/your/projects/folder/ # Run bootstrap setup $ curl -sf https://raw.githubusercontent.com/redox-os/redox/master/bootstrap.sh -o bootstrap.sh && bash -e bootstrap.sh +#Change to project directory +$ cd redox + # Build Redox $ make all From 54eb934dfdfcbf2f4796611e18802de2ff69af5d Mon Sep 17 00:00:00 2001 From: Oliver Jan Krylow Date: Wed, 24 May 2017 23:09:32 +0200 Subject: [PATCH 354/522] Updated bootstrap for Solus Added build dependencies for Solus. --- bootstrap.sh | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/bootstrap.sh b/bootstrap.sh index 346d2b2..8a2c5d6 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -298,16 +298,7 @@ gentoo() solus() { echo "Detected SolusOS" - if [ -z "$(which nasm)" ]; then - echo "Installing nasm..." - sudo eopkg it nasm - fi - if [ -z "$(which git)" ]; then - echo "Installing git..." - sudo eopkg it git - fi - echo "Installing fuse..." - sudo eopkg it fuse-devel + if [ "$1" == "qemu" ]; then if [ -z "$(which qemu-system-x86_64)" ]; then sudo eopkg it qemu @@ -323,6 +314,10 @@ solus() echo "Virtualbox already installed!" fi fi + + echo "Installing necessary build tools..." + #if guards are not necessary with eopkg since it does nothing if latest version is already installed + sudo eopkg it fuse-devel git gcc g++ libgcc-32bit libstdc++-32bit nasm make } ###################################################################### From 008622844c0ce84a7bae7e9500fa2f7f0ff10d83 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Fri, 2 Jun 2017 19:22:39 -0700 Subject: [PATCH 355/522] Increase filesystem size to 1024 MB I needed to do this to fit gcc/binutils. --- mk/filesystem.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mk/filesystem.mk b/mk/filesystem.mk index d1eb674..330d92c 100644 --- a/mk/filesystem.mk +++ b/mk/filesystem.mk @@ -1,7 +1,7 @@ build/filesystem.bin: userspace -$(FUMOUNT) build/filesystem/ || true rm -rf $@ build/filesystem/ - dd if=/dev/zero of=$@ bs=1048576 count=128 + dd if=/dev/zero of=$@ bs=1048576 count=1024 cargo run --manifest-path schemes/redoxfs/Cargo.toml --quiet --release --bin redoxfs-mkfs $@ mkdir -p build/filesystem/ cargo build --manifest-path schemes/redoxfs/Cargo.toml --quiet --release --bin redoxfs From 9bef268e525cfd25e2a1cd936ec521acda370ed6 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 2 Jun 2017 20:31:27 -0600 Subject: [PATCH 356/522] Update rust --- rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust b/rust index b16c7a2..dd729f8 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit b16c7a235fa0f57fed6b7ec13ffd3cff1bcdd9ad +Subproject commit dd729f8960a9ffce86c497db8cd8a775d1604181 From 641110d1efcdee6cd2556e457e74880123b0690a Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 2 Jun 2017 20:58:18 -0600 Subject: [PATCH 357/522] Update rust --- rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust b/rust index dd729f8..f3286fd 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit dd729f8960a9ffce86c497db8cd8a775d1604181 +Subproject commit f3286fd4397a744a482613d661300b01c6721257 From 89246b1fab72933281bc42e27a7ce4e6507da281 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 2 Jun 2017 20:58:36 -0600 Subject: [PATCH 358/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index 4d2808a..138463b 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 4d2808a012de5b6d4247a5eeb3ca510034911c7f +Subproject commit 138463b74aa90d147f056156414b9b1864732bd4 From 7610acabf485c3f6a8e3a4f7a4a3496178dc515e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 2 Jun 2017 21:03:31 -0600 Subject: [PATCH 359/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index b91b276..f366a5d 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit b91b2762d6360da65703631f4b733ea38c5b47e5 +Subproject commit f366a5dc3d8e3a8affbd438ad46a38cf905aa56d From b9770e0d72fc7fa5bcfd1cd533b2f0cb7b9850fc Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 3 Jun 2017 19:24:13 -0600 Subject: [PATCH 360/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index f366a5d..7ee086d 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit f366a5dc3d8e3a8affbd438ad46a38cf905aa56d +Subproject commit 7ee086d593e590d92e9fd1abed56fa57016a214e From 94167bfd5639c3c87286770baffeba44c7a50e08 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 3 Jun 2017 19:28:01 -0600 Subject: [PATCH 361/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index 7ee086d..c4b0a27 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 7ee086d593e590d92e9fd1abed56fa57016a214e +Subproject commit c4b0a276b269616a2609409565ca03f33e442382 From 4d36fb9bae84fc52491bbdaf243112680ee4036f Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 4 Jun 2017 18:35:05 -0600 Subject: [PATCH 362/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index 138463b..8d89925 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 138463b74aa90d147f056156414b9b1864732bd4 +Subproject commit 8d899258424f121df196ef38f2d3988e59339828 From b0854369e555bd9382992e177c4f46e2879d47f1 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 5 Jun 2017 09:52:09 -0600 Subject: [PATCH 363/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index c4b0a27..96e276d 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit c4b0a276b269616a2609409565ca03f33e442382 +Subproject commit 96e276d04cb2c4b23f78fdbb575af2548eb4fcc7 From 27f3f32145841765e83b6e87b9a92d3ef19ba057 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 5 Jun 2017 09:59:21 -0600 Subject: [PATCH 364/522] Remove useless .cargo/config --- .cargo/config | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .cargo/config diff --git a/.cargo/config b/.cargo/config deleted file mode 100644 index f9f6b98..0000000 --- a/.cargo/config +++ /dev/null @@ -1,3 +0,0 @@ -[target.x86_64-unknown-redox] -linker = "libc-artifacts/gcc.sh" -rustflags = [] From 72c3c5a3b218b1162723d972b7acfd5346704355 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 5 Jun 2017 10:01:33 -0600 Subject: [PATCH 365/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index 96e276d..f39ad70 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 96e276d04cb2c4b23f78fdbb575af2548eb4fcc7 +Subproject commit f39ad7026868a97b3e803f3a72f705235ae033cc From f546328c5ff9f40bc2a3fd07950de26c20ee605e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 5 Jun 2017 20:12:56 -0600 Subject: [PATCH 366/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index c4b0a27..f39ad70 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit c4b0a276b269616a2609409565ca03f33e442382 +Subproject commit f39ad7026868a97b3e803f3a72f705235ae033cc From 717ac92e680b3484b3dbed426bb54b754ca04aae Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 5 Jun 2017 20:53:55 -0600 Subject: [PATCH 367/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index f39ad70..8acc259 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit f39ad7026868a97b3e803f3a72f705235ae033cc +Subproject commit 8acc25947d49555340ce8bf465955fc2cd4884aa From 1f8f95c80efe435bf7c788b4ff0a90f6b3969a10 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 6 Jun 2017 11:04:31 -0600 Subject: [PATCH 368/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index 8acc259..38e31db 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 8acc25947d49555340ce8bf465955fc2cd4884aa +Subproject commit 38e31db60fefa49630d2243569691cf243fb7da4 From 9bb84f90c1bbc79b04b3fdf77d56a246afc063c0 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 6 Jun 2017 19:54:12 -0600 Subject: [PATCH 369/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index 38e31db..a6195c6 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 38e31db60fefa49630d2243569691cf243fb7da4 +Subproject commit a6195c65b0e272da1054fce02b54fc3e7c7874db From fcdd2b8c0cb97abad5b95a4a7fe10f6c2dc7ea3a Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 6 Jun 2017 20:00:11 -0600 Subject: [PATCH 370/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index a6195c6..fe9e69d 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit a6195c65b0e272da1054fce02b54fc3e7c7874db +Subproject commit fe9e69d273b60a8a05b0152b9623bd152c282625 From 2af5588ccd8a2f1dda42545adf3e20eeaa1aecd7 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 6 Jun 2017 20:25:22 -0600 Subject: [PATCH 371/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index fe9e69d..c8a927f 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit fe9e69d273b60a8a05b0152b9623bd152c282625 +Subproject commit c8a927f64364c78d799ff7bcbc64d7f23ad7c35d From 0eba99659e6ef9d2184e64eaee045c4a720132db Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 6 Jun 2017 20:46:31 -0600 Subject: [PATCH 372/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index c8a927f..bd219d2 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit c8a927f64364c78d799ff7bcbc64d7f23ad7c35d +Subproject commit bd219d2088bd5ba9040f94cc5250109286c8d91e From 1efbefd7faf5b23e6b78be859845571b82f50270 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 8 Jun 2017 14:59:51 -0600 Subject: [PATCH 373/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index bd219d2..e87d8c0 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit bd219d2088bd5ba9040f94cc5250109286c8d91e +Subproject commit e87d8c0d93910c39f851105f15a0455e380e6c2a From 1ecb2f6b712bfdc8cb7453ce64ff9fe931a3a42f Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 8 Jun 2017 15:36:32 -0600 Subject: [PATCH 374/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index e87d8c0..3582d35 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit e87d8c0d93910c39f851105f15a0455e380e6c2a +Subproject commit 3582d358b7b39f0edea639ec4707821f0830772f From 7e2b84a2c660db9f8e1fb29fc55c8b3e7bd34a3b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 8 Jun 2017 19:15:18 -0600 Subject: [PATCH 375/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index 3582d35..d7d187b 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 3582d358b7b39f0edea639ec4707821f0830772f +Subproject commit d7d187b6373757fb9d6a62887fbafef6fba452ef From a05325df7f53ecf2d60812fa77b3c72615159cc5 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 9 Jun 2017 20:14:03 -0600 Subject: [PATCH 376/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index d7d187b..6506f88 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit d7d187b6373757fb9d6a62887fbafef6fba452ef +Subproject commit 6506f88a23e98ab8446dfb4285cea25a46563bcc From 0ef251dce41d1b27ab8354eb71c938b044a58f1b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 9 Jun 2017 20:37:06 -0600 Subject: [PATCH 377/522] Update rust --- rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust b/rust index f3286fd..60ac9f4 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit f3286fd4397a744a482613d661300b01c6721257 +Subproject commit 60ac9f467cbbf8481a6f09e3e90e470dec85cf65 From 5bf4994405870156c2b2f9480afc4e4b77fe7c41 Mon Sep 17 00:00:00 2001 From: Egor Karavaev Date: Sat, 10 Jun 2017 08:54:39 +0300 Subject: [PATCH 378/522] Change the default mac to a valid value. --- filesystem.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/filesystem.toml b/filesystem.toml index 355a1bb..d3bcdef 100644 --- a/filesystem.toml +++ b/filesystem.toml @@ -94,7 +94,7 @@ data = "255.255.255.0" [[files]] path = "/etc/net/mac" -data = "00.00.00.00.00.00" +data = "54-52-00-ab-cd-ef" [[files]] path = "/etc/pkg.d/50_redox" From 3cde6f4486956ce4cd88edbec94b2cded5eb6d37 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 11 Jun 2017 08:57:30 -0600 Subject: [PATCH 379/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index 8d89925..e3020db 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 8d899258424f121df196ef38f2d3988e59339828 +Subproject commit e3020db04f239ed6c01ab127d9319120f9802c72 From e5ebff617e7ac1c1cc44904f7b7569eaf12b46f7 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 13 Jun 2017 14:59:42 -0600 Subject: [PATCH 380/522] Autostart icmpd --- filesystem.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/filesystem.toml b/filesystem.toml index d3bcdef..f4e1d7e 100644 --- a/filesystem.toml +++ b/filesystem.toml @@ -58,6 +58,7 @@ path = "/etc/init.d/10_net" data = """ ethernetd ipd +icmpd tcpd udpd dhcpd -b From d183443c302c7aa8746c106c633bee63bb97089b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 13 Jun 2017 15:00:02 -0600 Subject: [PATCH 381/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index 6506f88..cbe3379 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 6506f88a23e98ab8446dfb4285cea25a46563bcc +Subproject commit cbe3379475f2f0c71da1123344197ccac0fd5c29 From a19d3d1229f60390622addce1e6de6ec5a3975ac Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 13 Jun 2017 19:10:44 -0600 Subject: [PATCH 382/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index e3020db..8b05863 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit e3020db04f239ed6c01ab127d9319120f9802c72 +Subproject commit 8b05863ebbfcc1d854438e2cfd722f817dc714f3 From 2158be3aee93b6628bc2337fbdfa5c70bf75bf32 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 13 Jun 2017 21:43:57 -0600 Subject: [PATCH 383/522] Update kernel and bootloader --- bootloader | 2 +- kernel | 2 +- mk/kernel.mk | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bootloader b/bootloader index 76d3431..2ad0410 160000 --- a/bootloader +++ b/bootloader @@ -1 +1 @@ -Subproject commit 76d3431d89793ab13e1996ef4d3c6ec7c79acbc7 +Subproject commit 2ad0410ebcb1d468cdb00f7f28640109af6b3ddb diff --git a/kernel b/kernel index 8b05863..acab23d 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 8b05863ebbfcc1d854438e2cfd722f817dc714f3 +Subproject commit acab23d1e1fc1779b40caff0e710b352857ca7e8 diff --git a/mk/kernel.mk b/mk/kernel.mk index 5293900..0475f12 100644 --- a/mk/kernel.mk +++ b/mk/kernel.mk @@ -4,8 +4,8 @@ build/libkernel.a: kernel/Cargo.toml kernel/src/* kernel/src/*/* kernel/src/*/*/ build/libkernel_live.a: kernel/Cargo.toml kernel/src/* kernel/src/*/* kernel/src/*/*/* build/initfs.tag build/filesystem.bin cd kernel && FILESYSTEM="$(PWD)/build/filesystem.bin" xargo rustc --lib --features live --target $(KTARGET) --release -- -C soft-float --emit link=../$@ -build/kernel: build/libkernel.a +build/kernel: build/libkernel.a kernel/linkers/$(ARCH).ld $(LD) --gc-sections -z max-page-size=0x1000 -T kernel/linkers/$(ARCH).ld -o $@ $< -build/kernel_live: build/libkernel_live.a +build/kernel_live: build/libkernel_live.a kernel/linkers/$(ARCH).ld $(LD) --gc-sections -z max-page-size=0x1000 -T kernel/linkers/$(ARCH).ld -o $@ $< From b808f501b93edb4893849399245ad767afdae203 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 13 Jun 2017 21:56:31 -0600 Subject: [PATCH 384/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index acab23d..9b19ab9 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit acab23d1e1fc1779b40caff0e710b352857ca7e8 +Subproject commit 9b19ab9439712778333d5cad3aff379b0818f92f From 0f285bd9628e783343b068f4d36fce0013376c6c Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 14 Jun 2017 20:26:22 -0600 Subject: [PATCH 385/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index 9b19ab9..85c0236 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 9b19ab9439712778333d5cad3aff379b0818f92f +Subproject commit 85c02365c96e9f2b551edeb8f7c4b306ea4feb04 From d26acee6bb9f0f94e02ef5e2022be9b0aec4854a Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 14 Jun 2017 20:26:33 -0600 Subject: [PATCH 386/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index cbe3379..7f7f3ef 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit cbe3379475f2f0c71da1123344197ccac0fd5c29 +Subproject commit 7f7f3efb243c1ab47b52010d4115ace0baaef17d From e4492a6cc44a03090da2f33d13105df8e8f0d5f7 Mon Sep 17 00:00:00 2001 From: Emanuele Antonio Faraone Date: Thu, 15 Jun 2017 17:25:20 +0200 Subject: [PATCH 387/522] TFS's link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 97917f1..561c7ed 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ The ecosystem and software Redox OS provides is listed below. | [TFS (ticki filesystem)](https://github.com/ticki/tfs) | [**@ticki**](https://github.com/ticki) | [The Redox book](https://github.com/redox-os/book) | [**@ticki**](https://github.com/ticki) | [The old kernel](https://github.com/redox-os/old) | **abandoned** -| [ZFS](https://github.com/redox-os/zfs) | **abandoned, superseded by TFS** +| [ZFS](https://github.com/redox-os/zfs) | **abandoned, superseded by [TFS](https://github.com/ticki/tfs)** ## Help! Redox won't compile! From 07915f1d4c8652f6fca4125d37f5739ea298876b Mon Sep 17 00:00:00 2001 From: Emanuele Antonio Faraone Date: Thu, 15 Jun 2017 22:13:07 +0200 Subject: [PATCH 388/522] screenshot --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 561c7ed..ae7f9c7 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Please make sure you use the **latest nightly** of `rustc` before building (for ## What it looks like Redox -Redox +Redox Redox Redox From 913687d1fba64bf3356dce0760b8e6074abc0b4e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 17 Jun 2017 13:23:12 -0600 Subject: [PATCH 389/522] Move kernel into filesystem --- bootloader | 2 +- mk/filesystem.mk | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/bootloader b/bootloader index 2ad0410..7ba99fc 160000 --- a/bootloader +++ b/bootloader @@ -1 +1 @@ -Subproject commit 2ad0410ebcb1d468cdb00f7f28640109af6b3ddb +Subproject commit 7ba99fce952558b0934ec38c5ffd2b21741426d4 diff --git a/mk/filesystem.mk b/mk/filesystem.mk index 519975b..b081288 100644 --- a/mk/filesystem.mk +++ b/mk/filesystem.mk @@ -1,4 +1,4 @@ -build/filesystem.bin: filesystem.toml +build/filesystem.bin: filesystem.toml build/kernel -$(FUMOUNT) build/filesystem/ || true rm -rf $@ $@.partial build/filesystem/ dd if=/dev/zero of=$@.partial bs=1048576 count=1024 @@ -8,6 +8,7 @@ build/filesystem.bin: filesystem.toml cargo run --manifest-path installer/redoxfs/Cargo.toml --quiet --release --bin redoxfs -- $@.partial build/filesystem/ sleep 2 pgrep redoxfs + cp build/kernel build/filesystem/kernel cargo run --manifest-path installer/Cargo.toml -- --cookbook=cookbook $< chown -R 0:0 build/filesystem chown -R 1000:1000 build/filesystem/home/user From 7625b3fb47be37eb9f53f4bac318d47d5efc138a Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 17 Jun 2017 14:32:47 -0600 Subject: [PATCH 390/522] Update kernel and bootloader --- bootloader | 2 +- kernel | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bootloader b/bootloader index 7ba99fc..a2cdf21 160000 --- a/bootloader +++ b/bootloader @@ -1 +1 @@ -Subproject commit 7ba99fce952558b0934ec38c5ffd2b21741426d4 +Subproject commit a2cdf21167ac12c314a719d2c90a5863256df354 diff --git a/kernel b/kernel index 85c0236..73a71a7 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 85c02365c96e9f2b551edeb8f7c4b306ea4feb04 +Subproject commit 73a71a7d85ee08566c6efbc6358db63f6d750958 From cc8b991b9916c7a8753378dc2cf3974179de764b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 17 Jun 2017 14:33:08 -0600 Subject: [PATCH 391/522] Reduce size to 512 --- mk/filesystem.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mk/filesystem.mk b/mk/filesystem.mk index b081288..8e9b0bc 100644 --- a/mk/filesystem.mk +++ b/mk/filesystem.mk @@ -1,7 +1,7 @@ build/filesystem.bin: filesystem.toml build/kernel -$(FUMOUNT) build/filesystem/ || true rm -rf $@ $@.partial build/filesystem/ - dd if=/dev/zero of=$@.partial bs=1048576 count=1024 + dd if=/dev/zero of=$@.partial bs=1048576 count=512 cargo run --manifest-path installer/redoxfs/Cargo.toml --quiet --release --bin redoxfs-mkfs $@.partial mkdir -p build/filesystem/ cargo build --manifest-path installer/redoxfs/Cargo.toml --quiet --release --bin redoxfs From 1aeec04da7ae680a9953c4824dd4082fd71a35dd Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 17 Jun 2017 14:33:22 -0600 Subject: [PATCH 392/522] Increase qemu memory size --- mk/qemu.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mk/qemu.mk b/mk/qemu.mk index a76d9f9..5dc1410 100644 --- a/mk/qemu.mk +++ b/mk/qemu.mk @@ -1,6 +1,6 @@ QEMU=SDL_VIDEO_X11_DGAMOUSE=0 qemu-system-$(ARCH) QEMUFLAGS=-serial mon:stdio -d cpu_reset -d guest_errors -QEMUFLAGS+=-smp 4 -m 1024 +QEMUFLAGS+=-smp 4 -m 2048 ifeq ($(iommu),yes) QEMUFLAGS+=-machine q35,iommu=on else From 74eb268f42f91a212f9543a3ca3a932f66283f11 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 17 Jun 2017 14:40:35 -0600 Subject: [PATCH 393/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index 7f7f3ef..287883e 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 7f7f3efb243c1ab47b52010d4115ace0baaef17d +Subproject commit 287883e58e28ee6596345d82002897ac12574dad From 77562700c751c2ad004d1a664413f3a2b612e0c3 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 17 Jun 2017 14:50:36 -0600 Subject: [PATCH 394/522] Set TMPDIR in init.rc --- initfs.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/initfs.toml b/initfs.toml index dcb005b..15553a9 100644 --- a/initfs.toml +++ b/initfs.toml @@ -15,13 +15,13 @@ redoxfs = {} [[files]] path="/etc/init.rc" data=""" -export PATH initfs:/bin +export PATH /bin +export TMPDIR /tmp vesad T T G stdio display:1 ps2d pcid /etc/pcid.toml redoxfs disk:0 file cd file: -export PATH file:/bin run.d /etc/init.d """ From 3af4415a4a9a868ccc089a5c9acc43f9c7563d28 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 17 Jun 2017 16:59:01 -0600 Subject: [PATCH 395/522] Add audio to makefile --- mk/qemu.mk | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mk/qemu.mk b/mk/qemu.mk index 5dc1410..bfc69a5 100644 --- a/mk/qemu.mk +++ b/mk/qemu.mk @@ -6,6 +6,9 @@ ifeq ($(iommu),yes) else QEMUFLAGS+=-machine q35 endif +ifneq ($(audio),no) + QEMUFLAGS+=-device ich9-intel-hda -device hda-duplex +endif ifeq ($(net),no) QEMUFLAGS+=-net none else From dc7f89cb221c9b9d4d5c6977ff9abbe4be90546d Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 17 Jun 2017 18:48:54 -0600 Subject: [PATCH 396/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index 73a71a7..bbcd519 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 73a71a7d85ee08566c6efbc6358db63f6d750958 +Subproject commit bbcd5197a456b198750e35b085189e3e4b800c57 From 88800adc2653cd15650ee461fe5f1a4fdc4aa8d1 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 18 Jun 2017 15:11:25 -0600 Subject: [PATCH 397/522] Add all recipes to filesystem.toml, commented out where not default. Update cookbook Increase VirtualBox RAM, use Intel HDA for audio --- cookbook | 2 +- filesystem.toml | 6 ++++++ mk/virtualbox.mk | 6 +++--- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/cookbook b/cookbook index 287883e..20db74b 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 287883e58e28ee6596345d82002897ac12574dad +Subproject commit 20db74be75c121814528c597a57e72cd94904376 diff --git a/filesystem.toml b/filesystem.toml index f4e1d7e..323fea8 100644 --- a/filesystem.toml +++ b/filesystem.toml @@ -12,14 +12,19 @@ sysroot = "build/filesystem" #binutils = {} contain = {} coreutils = {} +#dash = {} extrautils = {} #games = {} +#gcc = {} +#gnu-binutils = {} +#gnu-make = {} init = {} installer = {} ion = {} #lua = {} netstack = {} netutils = {} +#newlib = {} orbdata = {} orbital = {} orbterm = {} @@ -29,6 +34,7 @@ pkgutils = {} ptyd = {} randd = {} redoxfs = {} +#rust = {} smith = {} #sodium = {} userutils = {} diff --git a/mk/virtualbox.mk b/mk/virtualbox.mk index b87e591..b764b2f 100644 --- a/mk/virtualbox.mk +++ b/mk/virtualbox.mk @@ -15,8 +15,8 @@ virtualbox: build/harddrive.bin echo "Create VM" $(VBM) createvm --name Redox --register echo "Set Configuration" - $(VBM) modifyvm Redox --memory 1024 - $(VBM) modifyvm Redox --vram 16 + $(VBM) modifyvm Redox --memory 2048 + $(VBM) modifyvm Redox --vram 32 if [ "$(net)" != "no" ]; \ then \ $(VBM) modifyvm Redox --nic1 nat; \ @@ -31,7 +31,7 @@ virtualbox: build/harddrive.bin $(VBM) modifyvm Redox --keyboard ps2 $(VBM) modifyvm Redox --mouse ps2 $(VBM) modifyvm Redox --audio $(VB_AUDIO) - $(VBM) modifyvm Redox --audiocontroller ac97 + $(VBM) modifyvm Redox --audiocontroller hda $(VBM) modifyvm Redox --nestedpaging on echo "Create Disk" $(VBM) convertfromraw $< build/harddrive.vdi From 81bfb044381fea1c167142e42c4b23c19c8013cf Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 18 Jun 2017 15:15:02 -0600 Subject: [PATCH 398/522] Update installer --- installer | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installer b/installer index 31a60eb..af1dd3b 160000 --- a/installer +++ b/installer @@ -1 +1 @@ -Subproject commit 31a60eb8a32315e1f5f610f6c6d19d1cec61649c +Subproject commit af1dd3b9fdb7d339c8cf992d1d8cc911d1df3094 From 557e8a8046c932c1af3acc5d427ae5fb5f97f37c Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 18 Jun 2017 15:18:31 -0600 Subject: [PATCH 399/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index 20db74b..9f7b51d 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 20db74be75c121814528c597a57e72cd94904376 +Subproject commit 9f7b51d77d735d474839de633fe0df2ca22c36bb From fad1e6f717652188c1a4bc019c154b2b0b770b03 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 18 Jun 2017 15:24:25 -0600 Subject: [PATCH 400/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index 9f7b51d..eb2a044 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 9f7b51d77d735d474839de633fe0df2ca22c36bb +Subproject commit eb2a044d813225876f384b8bf7ac92f534d8ada1 From 862f6ddbff9dd737767e12956801ec8da6351668 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 18 Jun 2017 15:57:21 -0600 Subject: [PATCH 401/522] Update rust --- rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust b/rust index 60ac9f4..247a018 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 60ac9f467cbbf8481a6f09e3e90e470dec85cf65 +Subproject commit 247a0184ff972f1205017185f6917a03b15e7be4 From 44e4d9262c7f264272b4bb7828b5e58a9f077c0e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 18 Jun 2017 15:59:43 -0600 Subject: [PATCH 402/522] Improve clean target, add update --- Makefile | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Makefile b/Makefile index 951f39b..1306e77 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,9 @@ live: build/livedisk.bin iso: build/livedisk.iso clean: + cargo clean --manifest-path cookbook/pkgutils/Cargo.toml + cargo clean --manifest-path installer/Cargo.toml + cargo clean --manifest-path installer/redoxfs/Cargo.toml cargo clean --manifest-path kernel/Cargo.toml -$(FUMOUNT) build/filesystem/ || true rm -rf build @@ -18,6 +21,13 @@ pull: git submodule update --recursive --init git clean -X -f -d make clean + make update + +update: + cargo update --manifest-path cookbook/pkgutils/Cargo.toml + cargo update --manifest-path installer/Cargo.toml + cargo update --manifest-path installer/redoxfs/Cargo.toml + cargo update --manifest-path kernel/Cargo.toml # Emulation recipes include mk/qemu.mk From 26772483d68382e1c750508ad6271e0201a3445b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 18 Jun 2017 16:43:00 -0600 Subject: [PATCH 403/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index eb2a044..18fec4b 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit eb2a044d813225876f384b8bf7ac92f534d8ada1 +Subproject commit 18fec4b46a90a112fb6ba2d90c28c8a088a32467 From c646b7040dee0e6040d6ad47e7afb11ed67cc1cd Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 18 Jun 2017 16:51:10 -0600 Subject: [PATCH 404/522] Update .travis.yml and cookbook --- .travis.yml | 6 +++--- cookbook | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index fd2b81a..fe76347 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,8 +12,9 @@ os: dist: trusty before_install: - if [ "$TRAVIS_OS_NAME" == "linux" ]; then + sudo add-apt-repository 'deb https://static.redox-os.org/toolchain/apt /' && sudo apt-get update -qq && - sudo apt-get install -qq nasm pkg-config fuse libfuse-dev genisoimage syslinux && + sudo apt-get install -qq nasm pkg-config fuse libfuse-dev genisoimage syslinux x86-64-elf-redox-gcc && sudo modprobe fuse && sudo chmod 666 /dev/fuse && sudo chown root:$USER /etc/fuse.conf; @@ -25,8 +26,7 @@ before_install: fi - cd cookbook && ./setup.sh && cd .. script: -- cd cookbook && ./fetch.sh && cd .. && - make clean && +- make clean && make build/harddrive.bin.gz build/livedisk.bin.gz build/livedisk.iso notifications: email: false diff --git a/cookbook b/cookbook index 18fec4b..a371b3e 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 18fec4b46a90a112fb6ba2d90c28c8a088a32467 +Subproject commit a371b3e54c6380ceb8817921991493323ffa3adc From b10ce242f134c21afe629d26a4885f7bfc1ba0f7 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 18 Jun 2017 17:19:27 -0600 Subject: [PATCH 405/522] Install repository for toolchain --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index fe76347..5a6db26 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,8 @@ os: dist: trusty before_install: - if [ "$TRAVIS_OS_NAME" == "linux" ]; then - sudo add-apt-repository 'deb https://static.redox-os.org/toolchain/apt /' && + sudo apt-key adv -q --batch --yes --keyserver keyserver.ubuntu.com --recv-keys AA12E97F0881517F && + sudo add-apt-repository -q -y 'deb https://static.redox-os.org/toolchain/apt ./' && sudo apt-get update -qq && sudo apt-get install -qq nasm pkg-config fuse libfuse-dev genisoimage syslinux x86-64-elf-redox-gcc && sudo modprobe fuse && From 789286627bd83197228f122708c5a5b739eae0ee Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 18 Jun 2017 17:22:39 -0600 Subject: [PATCH 406/522] Remove quiet and yes from add-apt-repository --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 5a6db26..11d77c2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ dist: trusty before_install: - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-key adv -q --batch --yes --keyserver keyserver.ubuntu.com --recv-keys AA12E97F0881517F && - sudo add-apt-repository -q -y 'deb https://static.redox-os.org/toolchain/apt ./' && + sudo add-apt-repository 'deb https://static.redox-os.org/toolchain/apt ./' && sudo apt-get update -qq && sudo apt-get install -qq nasm pkg-config fuse libfuse-dev genisoimage syslinux x86-64-elf-redox-gcc && sudo modprobe fuse && From c3bced4e38d04d5e3e4dc34550b53c318dbcd252 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 18 Jun 2017 19:22:23 -0600 Subject: [PATCH 407/522] Purge binutils-doc to avoid conflict (to be fixed later) --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 11d77c2..e830624 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,7 @@ before_install: sudo apt-key adv -q --batch --yes --keyserver keyserver.ubuntu.com --recv-keys AA12E97F0881517F && sudo add-apt-repository 'deb https://static.redox-os.org/toolchain/apt ./' && sudo apt-get update -qq && + sudo apt-get purge -qq binutils-doc && sudo apt-get install -qq nasm pkg-config fuse libfuse-dev genisoimage syslinux x86-64-elf-redox-gcc && sudo modprobe fuse && sudo chmod 666 /dev/fuse && From cb658df1ab819c44f8b1759614d70b331dd03e7d Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 18 Jun 2017 20:07:14 -0600 Subject: [PATCH 408/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index bbcd519..cd67aab 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit bbcd5197a456b198750e35b085189e3e4b800c57 +Subproject commit cd67aabd5aa1a16f1468c1f97eaf776425deb60a From 30359765765ea468c362f8f48c22892c56108f93 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 19 Jun 2017 16:31:31 -0600 Subject: [PATCH 409/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index a371b3e..ae2fb42 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit a371b3e54c6380ceb8817921991493323ffa3adc +Subproject commit ae2fb4217c356ed8b526d95b4ad753adab2d7a3d From 54f4078a8937b90d6f3b946a124d2583e9dd0029 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 19 Jun 2017 18:03:40 -0600 Subject: [PATCH 410/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index ae2fb42..8da4935 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit ae2fb4217c356ed8b526d95b4ad753adab2d7a3d +Subproject commit 8da49359fe6402c24446c9b8042530dfccde28d3 From 672f8b82973e28489a330c028d204951b8157a9d Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 19 Jun 2017 20:15:56 -0600 Subject: [PATCH 411/522] Upgrade cookbook, revert Rust, clean cookbook in make clean, put xargo build in subfolder --- Makefile | 1 + cookbook | 2 +- mk/config.mk | 1 + rust | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 1306e77..7c3d6f1 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,7 @@ live: build/livedisk.bin iso: build/livedisk.iso clean: + cd cookbook && ./clean.sh cargo clean --manifest-path cookbook/pkgutils/Cargo.toml cargo clean --manifest-path installer/Cargo.toml cargo clean --manifest-path installer/redoxfs/Cargo.toml diff --git a/cookbook b/cookbook index 8da4935..ae09d5a 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 8da49359fe6402c24446c9b8042530dfccde28d3 +Subproject commit ae09d5afbcf8b875f4bce30ffe9de70286832efb diff --git a/mk/config.mk b/mk/config.mk index db36a11..43bdf72 100644 --- a/mk/config.mk +++ b/mk/config.mk @@ -25,6 +25,7 @@ endif ROOT=$(PWD) export INITFS_FOLDER=$(ROOT)/build/initfs export RUST_TARGET_PATH=$(ROOT)/kernel/targets +export XARGO_HOME=$(ROOT)/build/xargo export XARGO_RUST_SRC=$(ROOT)/rust/src # Kernel variables diff --git a/rust b/rust index 247a018..4bf5c99 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 247a0184ff972f1205017185f6917a03b15e7be4 +Subproject commit 4bf5c99afc75f411a4e064150781eefc749c10df From 497b6fde96aa7d730565a8926c6fea171b6fb80e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 19 Jun 2017 20:52:42 -0600 Subject: [PATCH 412/522] Remove init from filesystem, as it is in the initfs --- filesystem.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/filesystem.toml b/filesystem.toml index 323fea8..afcc1c5 100644 --- a/filesystem.toml +++ b/filesystem.toml @@ -18,7 +18,6 @@ extrautils = {} #gcc = {} #gnu-binutils = {} #gnu-make = {} -init = {} installer = {} ion = {} #lua = {} From 87ed4e1ec55e67b5c1cc17d83f1efd745ccd3e07 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 20 Jun 2017 13:45:18 -0600 Subject: [PATCH 413/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index ae09d5a..2833d16 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit ae09d5afbcf8b875f4bce30ffe9de70286832efb +Subproject commit 2833d16c17d5dc57a6e263c0fa9e5e469c739744 From ba3089e9ec4d8718d559f6690be2b996c5782e70 Mon Sep 17 00:00:00 2001 From: Hunter Goldstein Date: Tue, 20 Jun 2017 17:28:34 -0400 Subject: [PATCH 414/522] Add 'pkg-config' to list of Ubuntu packages --- bootstrap.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap.sh b/bootstrap.sh index 8a2c5d6..07fe288 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -174,7 +174,7 @@ ubuntu() echo "Updating system..." sudo "$2" update echo "Installing required packages..." - sudo "$2" install build-essential libc6-dev-i386 nasm curl file git libfuse-dev fuse + sudo "$2" install build-essential libc6-dev-i386 nasm curl file git libfuse-dev fuse pkg-config if [ "$1" == "qemu" ]; then if [ -z "$(which qemu-system-x86_64)" ]; then echo "Installing QEMU..." From 93c8b92b758d84f6c77dd2bac8bece5dbbedfff0 Mon Sep 17 00:00:00 2001 From: Egor Karavaev Date: Wed, 21 Jun 2017 10:30:31 +0300 Subject: [PATCH 415/522] Add Dockerfile for build system. --- docker/Dockerfile | 31 +++++++++++++++++++++++++++++++ docker/entrypoint.sh | 17 +++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100755 docker/Dockerfile create mode 100755 docker/entrypoint.sh diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100755 index 0000000..5717fee --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,31 @@ +FROM ubuntu:17.04 + +ENV REDOX_TOOLCHAIN_APT http://static.redox-os.org/toolchain/apt/ +ENV SRC_PATH /src +ENV CARGO_HOME /cargo +ENV RUSTUP_HOME /rustup +ENV PATH $CARGO_HOME/bin:$PATH + +RUN apt-get update \ + && apt-get install -y git gosu gcc fuse nasm qemu-utils pkg-config \ + libfuse-dev make curl file sudo apt-transport-https \ + && mkdir -p $CARGO_HOME \ + && mkdir -p $RUSTUP_HOME \ + && curl https://sh.rustup.rs > sh.rustup.rs \ + && sh sh.rustup.rs -y \ + && rustup update \ + && rustup component add rust-src \ + && rustup default nightly \ + && echo "deb $REDOX_TOOLCHAIN_APT /" >> /etc/apt/sources.list.d/redox.list \ + && apt-get update \ + && apt-get install -y --force-yes x86-64-elf-redox-newlib x86-64-elf-redox-binutils x86-64-elf-redox-gcc \ + && cargo install xargo \ + && mkdir -p "$SRC_PATH" + +WORKDIR $SRC_PATH + +COPY entrypoint.sh /usr/local/bin/entrypoint.sh + +RUN chmod +x /usr/local/bin/entrypoint.sh + +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh new file mode 100755 index 0000000..2270106 --- /dev/null +++ b/docker/entrypoint.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +# Add local user +# Either use the LOCAL_USER_ID if passed in at runtime or +# fallback + +USER_ID=${LOCAL_USER_ID:-9001} + +echo "Starting with UID : $USER_ID " +echo "CARGO_HOME is $CARGO_HOME" +echo "RUSTUP_HOME is $RUSTUP_HOME" +useradd --shell /bin/bash -u $USER_ID -o -c "" -m user +export HOME=/home/user +chown user:user -R $CARGO_HOME +chown user:user -R $RUSTUP_HOME + +exec gosu user:user "$@" From 3eab4439e698d840fd8c45f3197f02da1b7736a0 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 23 Jun 2017 17:39:19 -0600 Subject: [PATCH 416/522] Update cookbook, kernel, and rust --- cookbook | 2 +- kernel | 2 +- rust | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cookbook b/cookbook index 2833d16..d787767 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 2833d16c17d5dc57a6e263c0fa9e5e469c739744 +Subproject commit d787767260c8b7d17f9a29350c44c1879740219f diff --git a/kernel b/kernel index cd67aab..0478e5f 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit cd67aabd5aa1a16f1468c1f97eaf776425deb60a +Subproject commit 0478e5f7fb352a26edb480bb6470777a8a29e1f8 diff --git a/rust b/rust index 4bf5c99..e0ad691 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 4bf5c99afc75f411a4e064150781eefc749c10df +Subproject commit e0ad69168cac0dd9d31bdd2206bd659777c0db5c From 9ab6b054ecf4ba0f19e9665851996420a5479add Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 23 Jun 2017 17:59:27 -0600 Subject: [PATCH 417/522] Update installer --- installer | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installer b/installer index af1dd3b..f99fac3 160000 --- a/installer +++ b/installer @@ -1 +1 @@ -Subproject commit af1dd3b9fdb7d339c8cf992d1d8cc911d1df3094 +Subproject commit f99fac30ea7bd69f04e6f2ac67bf4d197c7b91de From 12f419e6d26a3444a5b0de3fa9566e305003372e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 23 Jun 2017 18:10:44 -0600 Subject: [PATCH 418/522] Create .ionrc --- filesystem.toml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/filesystem.toml b/filesystem.toml index afcc1c5..c8da673 100644 --- a/filesystem.toml +++ b/filesystem.toml @@ -131,3 +131,11 @@ data = """ Welcome to Redox OS! """ + +[[files]] +path = "/home/user/.ionrc" +data = "" + +[[files]] +path = "/root/.ionrc" +data = "" From 84fdf1fd8f6b0f4c5f87d3fbc203a7a287694997 Mon Sep 17 00:00:00 2001 From: Egor Karavaev Date: Sat, 24 Jun 2017 12:45:21 +0300 Subject: [PATCH 419/522] Add README.md on how to build Redox using docker images. --- docker/README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 docker/README.md diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 0000000..e5144ac --- /dev/null +++ b/docker/README.md @@ -0,0 +1,18 @@ +### Building Redox using Docker images with the toolchain + +*All you need is git, make, qemu, fuse and docker. The method requires a non-privileged user able to run the `docker` command, which is usually achieved by adding the user to the `docker` group.* + +```shell +git clone https://github.com/redox-os/redox.git ; cd redox #1 +make pull #2 +docker build -t redox docker/ #3 +docker run --cap-add MKNOD --cap-add SYS_ADMIN --device \ + /dev/fuse -e LOCAL_USER_ID=`id -u` -v `pwd`:/src --rm redox make all #4 +make qemu #5 +``` +To unpack: +1. Creates a local copy of the repository. +2. Updates all the submodules in the repository. +3. Creates a new image in the local image repository named `redox` with Redox toolchain installed. You only need to rebuild the image if you want to update the toolchain. +4. Builds Redox using the `redox` image. The arguments allow the container to use `fuse` and ensure the resulting files are owned by the current user. +5. Runs Redox. From 39d34d47f5bfa5e3f6aa90ae6ca2fb05c3aced08 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 25 Jun 2017 20:05:01 -0600 Subject: [PATCH 420/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index d787767..c76d410 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit d787767260c8b7d17f9a29350c44c1879740219f +Subproject commit c76d4105b41e743005a1a3bdd7c5d8960a7c4e1e From 125c575d2893bd9bb958403eda80bd9b9345ca88 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 25 Jun 2017 20:17:21 -0600 Subject: [PATCH 421/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index c76d410..7d4bdb0 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit c76d4105b41e743005a1a3bdd7c5d8960a7c4e1e +Subproject commit 7d4bdb0f29db7b52fca0e134d7330a711c182139 From 1efa0c9c371486e8654d4eacea35a84888e01c91 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 25 Jun 2017 20:20:54 -0600 Subject: [PATCH 422/522] Update README.md --- docker/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docker/README.md b/docker/README.md index e5144ac..f0e4c28 100644 --- a/docker/README.md +++ b/docker/README.md @@ -6,8 +6,7 @@ git clone https://github.com/redox-os/redox.git ; cd redox #1 make pull #2 docker build -t redox docker/ #3 -docker run --cap-add MKNOD --cap-add SYS_ADMIN --device \ - /dev/fuse -e LOCAL_USER_ID=`id -u` -v `pwd`:/src --rm redox make all #4 +docker run --cap-add MKNOD --cap-add SYS_ADMIN --device /dev/fuse -e LOCAL_USER_ID="$(id -u)" -v "$(pwd):/src" --rm redox make all #4 make qemu #5 ``` To unpack: From cbd126aa5cc1d5e878fc83d132f41dc1a882c09a Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 25 Jun 2017 20:21:19 -0600 Subject: [PATCH 423/522] Update README.md --- docker/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docker/README.md b/docker/README.md index f0e4c28..352c392 100644 --- a/docker/README.md +++ b/docker/README.md @@ -6,7 +6,9 @@ git clone https://github.com/redox-os/redox.git ; cd redox #1 make pull #2 docker build -t redox docker/ #3 -docker run --cap-add MKNOD --cap-add SYS_ADMIN --device /dev/fuse -e LOCAL_USER_ID="$(id -u)" -v "$(pwd):/src" --rm redox make all #4 +docker run --cap-add MKNOD --cap-add SYS_ADMIN \ + --device /dev/fuse -e LOCAL_USER_ID="$(id -u)" \ + -v "$(pwd):/src" --rm redox make all #4 make qemu #5 ``` To unpack: From ba06b3cd98594262070b3406ad46edbd004b144a Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 29 Jun 2017 11:56:45 -0600 Subject: [PATCH 424/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index 0478e5f..a4c3afb 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 0478e5f7fb352a26edb480bb6470777a8a29e1f8 +Subproject commit a4c3afb446a1956e0a15a20c840600e8375db91b From e9a176531189f4ff19a7aca22b351c39e77bc17f Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 29 Jun 2017 18:14:28 -0600 Subject: [PATCH 425/522] Move installer/redoxfs submodule to redoxfs --- .gitmodules | 3 +++ Makefile | 4 ++-- installer | 2 +- mk/filesystem.mk | 10 +++++----- redoxfs | 1 + 5 files changed, 12 insertions(+), 8 deletions(-) create mode 160000 redoxfs diff --git a/.gitmodules b/.gitmodules index 16b9f4f..ffbef5c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,3 +16,6 @@ [submodule "rust"] path = rust url = https://github.com/redox-os/rust.git +[submodule "redoxfs"] + path = redoxfs + url = https://github.com/redox-os/redoxfs.git diff --git a/Makefile b/Makefile index 7c3d6f1..001d0ad 100644 --- a/Makefile +++ b/Makefile @@ -11,8 +11,8 @@ clean: cd cookbook && ./clean.sh cargo clean --manifest-path cookbook/pkgutils/Cargo.toml cargo clean --manifest-path installer/Cargo.toml - cargo clean --manifest-path installer/redoxfs/Cargo.toml cargo clean --manifest-path kernel/Cargo.toml + cargo clean --manifest-path redoxfs/Cargo.toml -$(FUMOUNT) build/filesystem/ || true rm -rf build @@ -27,8 +27,8 @@ pull: update: cargo update --manifest-path cookbook/pkgutils/Cargo.toml cargo update --manifest-path installer/Cargo.toml - cargo update --manifest-path installer/redoxfs/Cargo.toml cargo update --manifest-path kernel/Cargo.toml + cargo update --manifest-path redoxfs/Cargo.toml # Emulation recipes include mk/qemu.mk diff --git a/installer b/installer index f99fac3..d6f2936 160000 --- a/installer +++ b/installer @@ -1 +1 @@ -Subproject commit f99fac30ea7bd69f04e6f2ac67bf4d197c7b91de +Subproject commit d6f2936a5337b3c613483ea428dc6c4571e5357c diff --git a/mk/filesystem.mk b/mk/filesystem.mk index 8e9b0bc..71c5b61 100644 --- a/mk/filesystem.mk +++ b/mk/filesystem.mk @@ -2,10 +2,10 @@ build/filesystem.bin: filesystem.toml build/kernel -$(FUMOUNT) build/filesystem/ || true rm -rf $@ $@.partial build/filesystem/ dd if=/dev/zero of=$@.partial bs=1048576 count=512 - cargo run --manifest-path installer/redoxfs/Cargo.toml --quiet --release --bin redoxfs-mkfs $@.partial + cargo run --manifest-path redoxfs/Cargo.toml --quiet --release --bin redoxfs-mkfs $@.partial mkdir -p build/filesystem/ - cargo build --manifest-path installer/redoxfs/Cargo.toml --quiet --release --bin redoxfs - cargo run --manifest-path installer/redoxfs/Cargo.toml --quiet --release --bin redoxfs -- $@.partial build/filesystem/ + cargo build --manifest-path redoxfs/Cargo.toml --quiet --release --bin redoxfs + cargo run --manifest-path redoxfs/Cargo.toml --quiet --release --bin redoxfs -- $@.partial build/filesystem/ sleep 2 pgrep redoxfs cp build/kernel build/filesystem/kernel @@ -32,8 +32,8 @@ build/filesystem.bin: filesystem.toml build/kernel mount: FORCE mkdir -p build/filesystem/ - cargo build --manifest-path installer/redoxfs/Cargo.toml --quiet --release --bin redoxfs - cargo run --manifest-path installer/redoxfs/Cargo.toml --quiet --release --bin redoxfs -- build/harddrive.bin build/filesystem/ + cargo build --manifest-path redoxfs/Cargo.toml --quiet --release --bin redoxfs + cargo run --manifest-path redoxfs/Cargo.toml --quiet --release --bin redoxfs -- build/harddrive.bin build/filesystem/ sleep 2 pgrep redoxfs diff --git a/redoxfs b/redoxfs new file mode 160000 index 0000000..97652cc --- /dev/null +++ b/redoxfs @@ -0,0 +1 @@ +Subproject commit 97652cc6f85bc31a556706d882554a8b71299807 From 8de042727124ae25a629d9c7324c071e49611f2f Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 29 Jun 2017 18:14:41 -0600 Subject: [PATCH 426/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index 7d4bdb0..04b112d 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 7d4bdb0f29db7b52fca0e134d7330a711c182139 +Subproject commit 04b112dca09e97a3ede9977791d2430c5e96ff30 From b6ac4d62b9c38075119a31849db15928dfe35b6d Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 29 Jun 2017 18:15:02 -0600 Subject: [PATCH 427/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index 04b112d..a74b421 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 04b112dca09e97a3ede9977791d2430c5e96ff30 +Subproject commit a74b421189355ff9244592b3d7735dbeaa644fb0 From bf9cbb5eaa10b79dc2fd43d2a9b324788883ae8a Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 29 Jun 2017 18:32:48 -0600 Subject: [PATCH 428/522] Update rust --- rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust b/rust index e0ad691..0dab316 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit e0ad69168cac0dd9d31bdd2206bd659777c0db5c +Subproject commit 0dab31601fc2ef5b025bd2ba3372cf5c2d0cbb2c From cb0dd7ffd5429d659a1972e1028c4726e0af5e6b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 29 Jun 2017 20:06:16 -0600 Subject: [PATCH 429/522] Make travis build use packages from static.redox-os.org --- .travis.yml | 9 +++------ Makefile | 8 ++++++++ mk/config.mk | 1 + mk/filesystem.mk | 2 +- mk/initfs.mk | 2 +- 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index e830624..335da2e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,8 +28,7 @@ before_install: fi - cd cookbook && ./setup.sh && cd .. script: -- make clean && - make build/harddrive.bin.gz build/livedisk.bin.gz build/livedisk.iso +- make travis notifications: email: false webhooks: http://37.139.9.28:54863/travis @@ -37,10 +36,8 @@ deploy: provider: releases api_key: secure: E5w3mgFbW4fAFNJn0FGcvwGKK33d+StC4izDX7dsGPxX/gwAsMnZqabDWpsrj8n/jFI5NdPzuyz4Ojkip4AXrEs0DWfX96d9CSWvJmWIirwwKhALnxZ5cqnHnBXY3wpk9k8MKpdODzKs3ZjM3pPug2jjjp2EHdrEV6iyc8LlnLAJutbtPpNJv0rJrx/TfCZRx70YWKQyx2Lfx5P6Vj+5yoYsKk+SHmKZlIQfj2E1cfC8+/w+fzc9CRTNhM9XFBisKnu9qql3nNhEW8VUNQ9FnltGpunmcTnCmsKzHPfs8Zv6kM/6y3wuoqxwPnIwRu+zsntkjM/eT7Zy3DtTBqJDjq+L5jov50QWOxzjUuFYMv0lAMeMC0PIGn0ECpFs546M+Wqvd7HKgabac0UhilEBPbinOdW+6aOOhbo+Fe2I2ec0XIGxlQpccQeWQUsjjOQ+6QuvnpPE+CbvQaVyrx27rVAkqD44cOP8xqOq2Es651J+Dt0O1OIhLdPB3FxOLCDpEIHU5Ojci1QbUxZgGKjShpo44nNqcTv7v71JrfzFSVG2pF9a35Mpo6bFEkzyQprOyrwH2fcnN+4jyxdJXzdNsgraXsQopWAB5cL/8i7SXMwHy9ivpFaX/zgoHQqpc1a4VjrmTtPA08rLORIllw9CplfvJNsmNmCi2aSeTXR06Xk= - file: - - build/harddrive.bin.gz - - build/livedisk.bin.gz - - build/livedisk.iso + file_glob: true + file: build/travis/* on: repo: redox-os/redox tags: true diff --git a/Makefile b/Makefile index 001d0ad..5cc5260 100644 --- a/Makefile +++ b/Makefile @@ -45,6 +45,14 @@ include mk/filesystem.mk # Disk images include mk/disk.mk +# Travis target +travis: FORCE + make clean + INSTALLER_FLAGS= make build/harddrive.bin.gz build/livedisk.iso + mkdir build/travis + mv build/harddrive.bin.gz build/travis/redox_$(TRAVIS_TAG).bin.gz + mv build/livedisk.iso build/travis/redox_$(TRAVIS_TAG).iso + # An empty target FORCE: diff --git a/mk/config.mk b/mk/config.mk index 43bdf72..2bcb528 100644 --- a/mk/config.mk +++ b/mk/config.mk @@ -1,5 +1,6 @@ # Configuration ARCH?=x86_64 +INSTALLER_FLAGS?=--cookbook=cookbook # Per host variables UNAME := $(shell uname) diff --git a/mk/filesystem.mk b/mk/filesystem.mk index 71c5b61..9918a76 100644 --- a/mk/filesystem.mk +++ b/mk/filesystem.mk @@ -9,7 +9,7 @@ build/filesystem.bin: filesystem.toml build/kernel sleep 2 pgrep redoxfs cp build/kernel build/filesystem/kernel - cargo run --manifest-path installer/Cargo.toml -- --cookbook=cookbook $< + cargo run --manifest-path installer/Cargo.toml -- $(INSTALLER_FLAGS) $< chown -R 0:0 build/filesystem chown -R 1000:1000 build/filesystem/home/user chmod -R uog+rX build/filesystem diff --git a/mk/initfs.mk b/mk/initfs.mk index d335f12..aee0d2e 100644 --- a/mk/initfs.mk +++ b/mk/initfs.mk @@ -1,3 +1,3 @@ build/initfs.tag: initfs.toml - cargo run --manifest-path installer/Cargo.toml -- --cookbook=cookbook $< + cargo run --manifest-path installer/Cargo.toml -- $(INSTALLER_FLAGS) $< touch $@ From 0a882d17639dc4615c8dac285252ded66b064d17 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 29 Jun 2017 20:29:51 -0600 Subject: [PATCH 430/522] Update travis build script --- .travis.yml | 2 +- Makefile | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 335da2e..fde6e0b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,7 +28,7 @@ before_install: fi - cd cookbook && ./setup.sh && cd .. script: -- make travis +- make clean && make travis notifications: email: false webhooks: http://37.139.9.28:54863/travis diff --git a/Makefile b/Makefile index 5cc5260..db14fbf 100644 --- a/Makefile +++ b/Makefile @@ -47,11 +47,12 @@ include mk/disk.mk # Travis target travis: FORCE - make clean INSTALLER_FLAGS= make build/harddrive.bin.gz build/livedisk.iso + rm -rf build/travis mkdir build/travis mv build/harddrive.bin.gz build/travis/redox_$(TRAVIS_TAG).bin.gz mv build/livedisk.iso build/travis/redox_$(TRAVIS_TAG).iso + cd build/travis && sha256sum -b redox_$(TRAVIS_TAG).bin.gz redox_$(TRAVIS_TAG).iso > SHA256SUM # An empty target FORCE: From 36930203004954eb1a83ffe2e3a0f1b3866c1a18 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 5 Jul 2017 21:47:01 -0600 Subject: [PATCH 431/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index a4c3afb..d4e295a 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit a4c3afb446a1956e0a15a20c840600e8375db91b +Subproject commit d4e295a385e33c9bd1272f1a35775deb6425fb8c From 701ac963b55b33dfe83ca458fc7ed41c524cfc9e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 6 Jul 2017 19:00:16 -0600 Subject: [PATCH 432/522] Update cookbook and kernel --- cookbook | 2 +- kernel | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cookbook b/cookbook index a74b421..5f50922 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit a74b421189355ff9244592b3d7735dbeaa644fb0 +Subproject commit 5f5092271b8f7e6a66758ce40ba4e4573ec84369 diff --git a/kernel b/kernel index d4e295a..ae5a32c 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit d4e295a385e33c9bd1272f1a35775deb6425fb8c +Subproject commit ae5a32cf98d7cda37b5144d2b30840161d1720ba From 288ed686b77b04038e78737f9fe547d312ac1eaf Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 6 Jul 2017 19:13:06 -0600 Subject: [PATCH 433/522] Update redoxfs and rust --- redoxfs | 2 +- rust | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/redoxfs b/redoxfs index 97652cc..4820210 160000 --- a/redoxfs +++ b/redoxfs @@ -1 +1 @@ -Subproject commit 97652cc6f85bc31a556706d882554a8b71299807 +Subproject commit 4820210cca19cabfce71d64721449b51525c93be diff --git a/rust b/rust index 0dab316..aadefb4 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 0dab31601fc2ef5b025bd2ba3372cf5c2d0cbb2c +Subproject commit aadefb4b5c97491dafb5c7419f1ff4d3f56036f1 From 77357b74e1c67f7f49933d737f3496cdb3366ea1 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 7 Jul 2017 17:54:08 -0600 Subject: [PATCH 434/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index 5f50922..5d9b254 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 5f5092271b8f7e6a66758ce40ba4e4573ec84369 +Subproject commit 5d9b2543b11661a320547a06abeadd95221069fe From de9ab36cdb122dd2a5f0b2e585149211880e6c78 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 8 Jul 2017 17:12:36 -0600 Subject: [PATCH 435/522] Update Rust --- rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust b/rust index aadefb4..120a7de 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit aadefb4b5c97491dafb5c7419f1ff4d3f56036f1 +Subproject commit 120a7de92a72f22851c441c16006b01e3bcf9707 From b6cf4ae44dc5393d4302c609f1a318aaf455b56d Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 8 Jul 2017 17:19:34 -0600 Subject: [PATCH 436/522] Update cookbook, kernel --- cookbook | 2 +- kernel | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cookbook b/cookbook index 5d9b254..9e9ed9b 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 5d9b2543b11661a320547a06abeadd95221069fe +Subproject commit 9e9ed9b7b4f32a0a79d72b97e7f67323ce44632a diff --git a/kernel b/kernel index ae5a32c..22e87d9 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit ae5a32cf98d7cda37b5144d2b30840161d1720ba +Subproject commit 22e87d94d4bddedd5d5148a4507f2fc31cd41033 From a5da9f51ef227ce87670d244eff78093166f1735 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 8 Jul 2017 17:27:52 -0600 Subject: [PATCH 437/522] Update Rust --- rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust b/rust index 120a7de..3120d71 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 120a7de92a72f22851c441c16006b01e3bcf9707 +Subproject commit 3120d7169eb4cb3c6e6ac005c1171181878d51e4 From ee9f12d2e613a092129f9242a451077c162e2fd5 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 8 Jul 2017 19:03:35 -0600 Subject: [PATCH 438/522] Update rust --- rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust b/rust index 3120d71..f2eacbe 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 3120d7169eb4cb3c6e6ac005c1171181878d51e4 +Subproject commit f2eacbe39586ca5ae673ee838759c0cc74f4f152 From 2827076b247c3cdf45a9035d45011e1c82b294c8 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 8 Jul 2017 19:24:56 -0600 Subject: [PATCH 439/522] Update redoxfs --- redoxfs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redoxfs b/redoxfs index 4820210..dcce0d9 160000 --- a/redoxfs +++ b/redoxfs @@ -1 +1 @@ -Subproject commit 4820210cca19cabfce71d64721449b51525c93be +Subproject commit dcce0d9e6e0519c486e1210ba792a9af13601c91 From 31671ae3d95b0aa88bc3793b9961578b28ca4b6b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 8 Jul 2017 19:51:10 -0600 Subject: [PATCH 440/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index 22e87d9..3f40af0 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 22e87d94d4bddedd5d5148a4507f2fc31cd41033 +Subproject commit 3f40af0687086a52f21587730ac87a87d7956a7e From c6cd2396c005f3838f38b7911458549b1da8c5a0 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 9 Jul 2017 08:41:20 -0600 Subject: [PATCH 441/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index 9e9ed9b..1a67b4b 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 9e9ed9b7b4f32a0a79d72b97e7f67323ce44632a +Subproject commit 1a67b4b2ff9b083c24633327998680b3d941824e From d7876faec94f467c2c04078d8634c28761971eb2 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 9 Jul 2017 10:25:46 -0600 Subject: [PATCH 442/522] Update RedoxFS --- bootloader | 2 +- redoxfs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bootloader b/bootloader index a2cdf21..5edf299 160000 --- a/bootloader +++ b/bootloader @@ -1 +1 @@ -Subproject commit a2cdf21167ac12c314a719d2c90a5863256df354 +Subproject commit 5edf2995f427b0a10b6c2ee9e5cee9392219c89f diff --git a/redoxfs b/redoxfs index dcce0d9..1f97d82 160000 --- a/redoxfs +++ b/redoxfs @@ -1 +1 @@ -Subproject commit dcce0d9e6e0519c486e1210ba792a9af13601c91 +Subproject commit 1f97d8220cd48cd3ddcb917d23337f15104234cf From 108014e8f7c9ffb19f6bd4a2e38562251032abb8 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Sun, 9 Jul 2017 14:18:59 -0700 Subject: [PATCH 443/522] 'user' and 'root' groups --- filesystem.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/filesystem.toml b/filesystem.toml index c8da673..645a61d 100644 --- a/filesystem.toml +++ b/filesystem.toml @@ -108,7 +108,9 @@ data = "https://static.redox-os.org/pkg" [[files]] path = "/etc/group" -data = "sudo;1;user" +data = """root;0;root +user;1000;user +sudo;1;user""" [[files]] path = "/etc/hostname" From 57aaf04a651d4dc6ceb9a2ed724554fabe558a89 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 9 Jul 2017 15:43:59 -0600 Subject: [PATCH 444/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index 3f40af0..7e52541 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 3f40af0687086a52f21587730ac87a87d7956a7e +Subproject commit 7e52541f39be01a011a9cc470d01c35f318fc78c From c1c9442ec97d65a60c6db45420b7c72ead28c815 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 9 Jul 2017 15:54:21 -0600 Subject: [PATCH 445/522] Update redoxfs --- redoxfs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redoxfs b/redoxfs index 1f97d82..8d66d9c 160000 --- a/redoxfs +++ b/redoxfs @@ -1 +1 @@ -Subproject commit 1f97d8220cd48cd3ddcb917d23337f15104234cf +Subproject commit 8d66d9ce54490cf92b69aef12e2409dec448bf40 From e9fd36bcdd6587f510005026e87d9c7713ff8d3e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 9 Jul 2017 18:51:38 -0600 Subject: [PATCH 446/522] Update redoxfs --- redoxfs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redoxfs b/redoxfs index 8d66d9c..6965d67 160000 --- a/redoxfs +++ b/redoxfs @@ -1 +1 @@ -Subproject commit 8d66d9ce54490cf92b69aef12e2409dec448bf40 +Subproject commit 6965d67efd390919bb9f7102314b7f80745713d4 From ca4159b1eca9173d13c5c626ac2ec0b6087bfd7f Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 9 Jul 2017 21:34:49 -0600 Subject: [PATCH 447/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index 7e52541..b5ff0aa 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 7e52541f39be01a011a9cc470d01c35f318fc78c +Subproject commit b5ff0aabd561c1befcc583aa0d7139fddabda27b From eef05d902a4a7530934e6002493c781df284b3e9 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 10 Jul 2017 20:33:41 -0600 Subject: [PATCH 448/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index b5ff0aa..a03457a 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit b5ff0aabd561c1befcc583aa0d7139fddabda27b +Subproject commit a03457a9ebc373d4ddc5094a1ff166c1e3a72022 From 60e83318e9582ec0ec4bc0ad7ff5d6a0a6953117 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 10 Jul 2017 20:36:40 -0600 Subject: [PATCH 449/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index 1a67b4b..55eaf12 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 1a67b4b2ff9b083c24633327998680b3d941824e +Subproject commit 55eaf12d3ae044025807a0c72f582f9daa6878bf From 90e5b64905078f217c6bfbe9952449ec5c2cfa66 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Mon, 10 Jul 2017 20:04:40 -0700 Subject: [PATCH 450/522] "make fetch" target --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index db14fbf..6297fc6 100644 --- a/Makefile +++ b/Makefile @@ -30,6 +30,10 @@ update: cargo update --manifest-path kernel/Cargo.toml cargo update --manifest-path redoxfs/Cargo.toml +fetch: + cd cookbook; \ + ./fetch.sh "$$(cargo run --manifest-path ../installer/Cargo.toml -- --list-packages ../initfs.toml ../filesystem.toml)" + # Emulation recipes include mk/qemu.mk include mk/bochs.mk From f4100d40bd71b8f3f6a2ee31ff58e0ebf3c5c3b1 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 12 Jul 2017 18:28:05 -0600 Subject: [PATCH 451/522] Update submodules --- cookbook | 2 +- installer | 2 +- kernel | 2 +- redoxfs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cookbook b/cookbook index 55eaf12..387c662 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 55eaf12d3ae044025807a0c72f582f9daa6878bf +Subproject commit 387c662281bb2b0d1859259ca90246ed768e6827 diff --git a/installer b/installer index d6f2936..15d37ce 160000 --- a/installer +++ b/installer @@ -1 +1 @@ -Subproject commit d6f2936a5337b3c613483ea428dc6c4571e5357c +Subproject commit 15d37cea36ee7b7ea86f7d91d2ecd67cdac888f0 diff --git a/kernel b/kernel index a03457a..687f991 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit a03457a9ebc373d4ddc5094a1ff166c1e3a72022 +Subproject commit 687f991ab4ac827e1d5d76a97d22e3cd12116b8b diff --git a/redoxfs b/redoxfs index 6965d67..bc2e8c2 160000 --- a/redoxfs +++ b/redoxfs @@ -1 +1 @@ -Subproject commit 6965d67efd390919bb9f7102314b7f80745713d4 +Subproject commit bc2e8c29239665987c61f8af54d1398905b49770 From 18c2211db47010a471178805fef435a68362085b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 12 Jul 2017 20:46:32 -0600 Subject: [PATCH 452/522] Update rust --- rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust b/rust index f2eacbe..5ae1a3e 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit f2eacbe39586ca5ae673ee838759c0cc74f4f152 +Subproject commit 5ae1a3ed605f273409e7189ada10dbccd925ad83 From 8a43b5a3e5bcab8a914d36520edc13a9f8f798a4 Mon Sep 17 00:00:00 2001 From: Jose Narvaez Date: Thu, 13 Jul 2017 21:00:55 +0100 Subject: [PATCH 453/522] Small fixes to Makefiles to be able to build the kernel on macOS again. Details - We are using the toolchain compiler and archiver in order to generate a proper ELF file when building the 'raw-cpuid' crate C code which is currently being compiled by the macOS toolchain. - I added the 'findutils' and 'coreutils' Homebrew/MacPorts packages to the bootstrap script in order to setup the proper environment for the cookbook scripts (as the assume GNU tools). This should be temporary until the cookbook scripts get migrated to Rust. --- bootstrap.sh | 8 ++++++-- mk/kernel.mk | 5 +++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/bootstrap.sh b/bootstrap.sh index 07fe288..696f8d0 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -93,6 +93,8 @@ osx_macports() install_macports_pkg "virtualbox" fi + install_macports_pkg "coreutils" + install_macports_pkg "findutils" install_macports_pkg "gcc49" "gcc-4.9" install_macports_pkg "nasm" install_macports_pkg "pkgconfig" @@ -120,6 +122,8 @@ osx_homebrew() install_brew_pkg "virtualbox" fi + install_macports_pkg "coreutils" + install_macports_pkg "findutils" install_brew_pkg "gcc49" "gcc-4.9" install_brew_pkg "nasm" install_brew_pkg "pkg-config" @@ -298,7 +302,7 @@ gentoo() solus() { echo "Detected SolusOS" - + if [ "$1" == "qemu" ]; then if [ -z "$(which qemu-system-x86_64)" ]; then sudo eopkg it qemu @@ -314,7 +318,7 @@ solus() echo "Virtualbox already installed!" fi fi - + echo "Installing necessary build tools..." #if guards are not necessary with eopkg since it does nothing if latest version is already installed sudo eopkg it fuse-devel git gcc g++ libgcc-32bit libstdc++-32bit nasm make diff --git a/mk/kernel.mk b/mk/kernel.mk index 0475f12..32491e3 100644 --- a/mk/kernel.mk +++ b/mk/kernel.mk @@ -1,5 +1,10 @@ build/libkernel.a: kernel/Cargo.toml kernel/src/* kernel/src/*/* kernel/src/*/*/* build/initfs.tag +# Temporary fix for https://github.com/redox-os/redox/issues/963 allowing to build on macOS +ifeq ($(UNAME),Darwin) + cd kernel && CC=$(ARCH)-elf-gcc AR=$(ARCH)-elf-ar CFLAGS=-ffreestanding xargo rustc --lib --target $(KTARGET) --release -- -C soft-float --emit link=../$@ +else cd kernel && xargo rustc --lib --target $(KTARGET) --release -- -C soft-float --emit link=../$@ +endif build/libkernel_live.a: kernel/Cargo.toml kernel/src/* kernel/src/*/* kernel/src/*/*/* build/initfs.tag build/filesystem.bin cd kernel && FILESYSTEM="$(PWD)/build/filesystem.bin" xargo rustc --lib --features live --target $(KTARGET) --release -- -C soft-float --emit link=../$@ From 227f006b777a422d9c29cb19534e95d2ea17e8af Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 13 Jul 2017 20:03:38 -0600 Subject: [PATCH 454/522] Update rust --- rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust b/rust index 5ae1a3e..ba5b8bc 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 5ae1a3ed605f273409e7189ada10dbccd925ad83 +Subproject commit ba5b8bc791df909755b31c2152ebbbb1e60e62be From b3101072319c33f46c2ca9fab7616f29708fe273 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 13 Jul 2017 20:04:16 -0600 Subject: [PATCH 455/522] Update cookbook, kernel --- cookbook | 2 +- kernel | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cookbook b/cookbook index 387c662..11e400b 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 387c662281bb2b0d1859259ca90246ed768e6827 +Subproject commit 11e400bd12042b2f4a50274f19a1165cd8f4d6dc diff --git a/kernel b/kernel index 687f991..56ba795 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 687f991ab4ac827e1d5d76a97d22e3cd12116b8b +Subproject commit 56ba7958450d4b69720ca52f30b085f25bf98e54 From 5f67443619923875ea1af7513b24d84bafdc518f Mon Sep 17 00:00:00 2001 From: Jose Narvaez Date: Fri, 14 Jul 2017 11:21:34 +0100 Subject: [PATCH 456/522] Fixing copy-paste error on boostrap scripts for macOS. --- bootstrap.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bootstrap.sh b/bootstrap.sh index 696f8d0..dc7d65c 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -122,8 +122,8 @@ osx_homebrew() install_brew_pkg "virtualbox" fi - install_macports_pkg "coreutils" - install_macports_pkg "findutils" + install_brew_pkg "coreutils" + install_brew_pkg "findutils" install_brew_pkg "gcc49" "gcc-4.9" install_brew_pkg "nasm" install_brew_pkg "pkg-config" From 527ee09c94b83303fdbbbd4f86b81421a08db2d0 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 14 Jul 2017 19:18:19 -0600 Subject: [PATCH 457/522] Update cookbook and kernel --- cookbook | 2 +- kernel | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cookbook b/cookbook index 11e400b..d47ac85 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 11e400bd12042b2f4a50274f19a1165cd8f4d6dc +Subproject commit d47ac8541a6d8ee0322ddb66987810fa7a0d0a5b diff --git a/kernel b/kernel index 56ba795..1085fa3 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 56ba7958450d4b69720ca52f30b085f25bf98e54 +Subproject commit 1085fa38382b2837e6746189209b9a302e32e6ee From 6376797a35fa2b6f70b97e3f14c91e36c0623635 Mon Sep 17 00:00:00 2001 From: Richard Palethorpe Date: Sun, 16 Jul 2017 17:18:40 +0200 Subject: [PATCH 458/522] bootstrap.sh: Use correct FUSE package for SUSE --- bootstrap.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap.sh b/bootstrap.sh index dc7d65c..7180e6f 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -262,7 +262,7 @@ suse() fi fi echo "Installing necessary build tools..." - sudo zypper install gcc gcc-c++ glibc-devel-32bit nasm make libfuse + sudo zypper install gcc gcc-c++ glibc-devel-32bit nasm make fuse-devel } ############################################################################## From 7dd922b0f017b940cb09e5b5a833e273f8cb5c7a Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 17 Jul 2017 16:34:07 -0600 Subject: [PATCH 459/522] Update Rust --- rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust b/rust index ba5b8bc..16399bd 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit ba5b8bc791df909755b31c2152ebbbb1e60e62be +Subproject commit 16399bd10bd76c4430b09e30cc75996e48128867 From 58f69731aeb4b05afcfc028dc4d52a646f513b52 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 17 Jul 2017 19:36:47 -0600 Subject: [PATCH 460/522] Update cookbook and redoxfs --- cookbook | 2 +- redoxfs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cookbook b/cookbook index d47ac85..3d993e2 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit d47ac8541a6d8ee0322ddb66987810fa7a0d0a5b +Subproject commit 3d993e2408b109310f002e5f274bb996076a6c87 diff --git a/redoxfs b/redoxfs index bc2e8c2..3342778 160000 --- a/redoxfs +++ b/redoxfs @@ -1 +1 @@ -Subproject commit bc2e8c29239665987c61f8af54d1398905b49770 +Subproject commit 3342778968f30c7725493f18114b5fca495f08b9 From ea324f529e8725ec3dfb72ed1ca5d3c6c30c1967 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 17 Jul 2017 20:28:08 -0600 Subject: [PATCH 461/522] Update Rust --- rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust b/rust index 16399bd..b2bb247 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 16399bd10bd76c4430b09e30cc75996e48128867 +Subproject commit b2bb2476f005b5014c8c30b837c4d83232d94607 From 704f9b9ff3878a58775d12ee9df353c51e634214 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 18 Jul 2017 18:51:16 -0600 Subject: [PATCH 462/522] Update bootloader and kernel --- bootloader | 2 +- kernel | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bootloader b/bootloader index 5edf299..59fd6fb 160000 --- a/bootloader +++ b/bootloader @@ -1 +1 @@ -Subproject commit 5edf2995f427b0a10b6c2ee9e5cee9392219c89f +Subproject commit 59fd6fbcfe9adc7e5d0c0df58fe4e2e07df5f31b diff --git a/kernel b/kernel index 1085fa3..76aa311 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 1085fa38382b2837e6746189209b9a302e32e6ee +Subproject commit 76aa3116d7ee903071088a4f49939abc3135bfec From 21adea7382ea9cf06455e810300399e39cc4ee48 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 18 Jul 2017 19:02:27 -0600 Subject: [PATCH 463/522] Update rust --- rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust b/rust index b2bb247..865e5c2 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit b2bb2476f005b5014c8c30b837c4d83232d94607 +Subproject commit 865e5c2c4f650ac7f1a98ca4ab27dad9750ef280 From ee218c9996d347bf5ada644d9c367cf1e0befaad Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 18 Jul 2017 20:55:52 -0600 Subject: [PATCH 464/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index 76aa311..b4d502c 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 76aa3116d7ee903071088a4f49939abc3135bfec +Subproject commit b4d502c7639f54be0c4c27e7c86c6396dc617c5d From 8dc0810d20ba94494776ec8dad81722d2d848012 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 18 Jul 2017 22:02:50 -0600 Subject: [PATCH 465/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index b4d502c..f7b961d 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit b4d502c7639f54be0c4c27e7c86c6396dc617c5d +Subproject commit f7b961ddff32ac7d75d81624331cfbce91839089 From e6edc09f28bcd01282b4f54b42caaf57ddb853d6 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 19 Jul 2017 14:53:59 -0600 Subject: [PATCH 466/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index f7b961d..4ae6ed9 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit f7b961ddff32ac7d75d81624331cfbce91839089 +Subproject commit 4ae6ed9d4c341b7102fd2480c61c9eac48511a46 From 708085615226fb79d4afd1d309132e77bc775b55 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 19 Jul 2017 19:20:33 -0600 Subject: [PATCH 467/522] Add all recipes, enable findutils, gawk, pastel, and sed --- filesystem.toml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/filesystem.toml b/filesystem.toml index 645a61d..c7d3278 100644 --- a/filesystem.toml +++ b/filesystem.toml @@ -10,17 +10,23 @@ sysroot = "build/filesystem" [packages] #acid = {} #binutils = {} +#ca-certificates = {} contain = {} coreutils = {} +#curl = {} #dash = {} extrautils = {} +findutils = {} #games = {} +gawk = {} #gcc = {} +#git = {} #gnu-binutils = {} #gnu-make = {} installer = {} ion = {} #lua = {} +#nasm = {} netstack = {} netutils = {} #newlib = {} @@ -28,12 +34,15 @@ orbdata = {} orbital = {} orbterm = {} orbutils = {} +pastel = {} #pixelcannon = {} pkgutils = {} ptyd = {} +#python = {} randd = {} redoxfs = {} #rust = {} +sed = {} smith = {} #sodium = {} userutils = {} @@ -72,7 +81,7 @@ dhcpd -b [[files]] path = "/etc/init.d/20_orbital" data = """ -orbital display:3/activate /ui/bin/orblogin /ui/bin/launcher +orbital display:3/activate orblogin launcher """ [[files]] From 0e2d12b246a11903aba2cbaa1247490547e634ad Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 19 Jul 2017 19:35:26 -0600 Subject: [PATCH 468/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index 3d993e2..3d2010b 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 3d993e2408b109310f002e5f274bb996076a6c87 +Subproject commit 3d2010b26a2b9cd966cb7982b7e50b150a5f530b From 8bdb365b619cd198b596bf809110c93c50e74971 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 20 Jul 2017 19:25:38 -0600 Subject: [PATCH 469/522] Update rust --- rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust b/rust index 865e5c2..5ebe07d 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 865e5c2c4f650ac7f1a98ca4ab27dad9750ef280 +Subproject commit 5ebe07d93ae68377d8b8a4f21a0470b5920d8473 From d6b51ca3c262da8cfb8b71ecfa2900d8a9da0e66 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 20 Jul 2017 19:42:30 -0600 Subject: [PATCH 470/522] Update for new network config --- filesystem.toml | 32 ++++++++++++++++++++++++-------- initfs.toml | 2 +- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/filesystem.toml b/filesystem.toml index c7d3278..64ebcab 100644 --- a/filesystem.toml +++ b/filesystem.toml @@ -15,6 +15,7 @@ contain = {} coreutils = {} #curl = {} #dash = {} +drivers = {} extrautils = {} findutils = {} #games = {} @@ -63,6 +64,7 @@ password = "" [[files]] path = "/etc/init.d/00_base" data = """ +pcid /etc/pcid/filesystem.toml randd ptyd """ @@ -93,23 +95,33 @@ getty debug: -J [[files]] path = "/etc/net/dns" -data = "208.67.222.222" +data = """ +208.67.222.222 +""" [[files]] path = "/etc/net/ip" -data = "10.0.2.15" +data = """ +10.0.2.15 +""" [[files]] path = "/etc/net/ip_router" -data = "10.0.2.2" +data = """ +10.0.2.2 +""" [[files]] path = "/etc/net/ip_subnet" -data = "255.255.255.0" +data = """ +255.255.255.0 +""" [[files]] path = "/etc/net/mac" -data = "54-52-00-ab-cd-ef" +data = """ +54-52-00-ab-cd-ef +""" [[files]] path = "/etc/pkg.d/50_redox" @@ -117,13 +129,17 @@ data = "https://static.redox-os.org/pkg" [[files]] path = "/etc/group" -data = """root;0;root +data = """ +root;0;root user;1000;user -sudo;1;user""" +sudo;1;user +""" [[files]] path = "/etc/hostname" -data = "redox" +data = """ +redox +""" [[files]] path = "/etc/issue" diff --git a/initfs.toml b/initfs.toml index 15553a9..1f23e58 100644 --- a/initfs.toml +++ b/initfs.toml @@ -20,7 +20,7 @@ export TMPDIR /tmp vesad T T G stdio display:1 ps2d -pcid /etc/pcid.toml +pcid /etc/pcid/initfs.toml redoxfs disk:0 file cd file: run.d /etc/init.d From e881aa5cc60b5b4423f27a222bddea88c1a15561 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 20 Jul 2017 19:42:47 -0600 Subject: [PATCH 471/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index 3d2010b..36f8f5b 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 3d2010b26a2b9cd966cb7982b7e50b150a5f530b +Subproject commit 36f8f5b5f7dd94384c498e781416cc738fbe783f From 3c395f11f881c3d9839ae0e39943972c4a5a2d0d Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 20 Jul 2017 19:47:59 -0600 Subject: [PATCH 472/522] Clean kernel on initfs regen --- mk/initfs.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/mk/initfs.mk b/mk/initfs.mk index aee0d2e..6d762b1 100644 --- a/mk/initfs.mk +++ b/mk/initfs.mk @@ -1,3 +1,4 @@ build/initfs.tag: initfs.toml + cd kernel && xargo clean cargo run --manifest-path installer/Cargo.toml -- $(INSTALLER_FLAGS) $< touch $@ From c8d7b6d773a70170c312da7d21f2a506b578305b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 20 Jul 2017 20:04:34 -0600 Subject: [PATCH 473/522] Clean initfs before installing --- mk/initfs.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/mk/initfs.mk b/mk/initfs.mk index 6d762b1..dc25325 100644 --- a/mk/initfs.mk +++ b/mk/initfs.mk @@ -1,4 +1,5 @@ build/initfs.tag: initfs.toml cd kernel && xargo clean + rm -rf build/initfs cargo run --manifest-path installer/Cargo.toml -- $(INSTALLER_FLAGS) $< touch $@ From 25ae3ad4e8608c0285d4d2c31154630ab3256e0e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 21 Jul 2017 20:44:45 -0600 Subject: [PATCH 474/522] Do not include kernel in bootloader --- mk/disk.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mk/disk.mk b/mk/disk.mk index ed926ba..f78bbab 100644 --- a/mk/disk.mk +++ b/mk/disk.mk @@ -1,5 +1,5 @@ build/harddrive.bin: build/kernel build/filesystem.bin bootloader/$(ARCH)/** - nasm -f bin -o $@ -D ARCH_$(ARCH) -D KERNEL=$< -D FILESYSTEM=build/filesystem.bin -ibootloader/$(ARCH)/ bootloader/$(ARCH)/disk.asm + nasm -f bin -o $@ -D ARCH_$(ARCH) -D FILESYSTEM=build/filesystem.bin -ibootloader/$(ARCH)/ bootloader/$(ARCH)/disk.asm build/livedisk.bin: build/kernel_live bootloader/$(ARCH)/** nasm -f bin -o $@ -D ARCH_$(ARCH) -D KERNEL=$< -ibootloader/$(ARCH)/ bootloader/$(ARCH)/disk.asm From 47ac868fe37cb76ab2040acf0e343bd2eb55b6fb Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 22 Jul 2017 13:08:41 -0600 Subject: [PATCH 475/522] Update kernel and redoxfs --- kernel | 2 +- redoxfs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel b/kernel index 4ae6ed9..fc914e0 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 4ae6ed9d4c341b7102fd2480c61c9eac48511a46 +Subproject commit fc914e0cae8c865ed260af7286314c7dc8e63f19 diff --git a/redoxfs b/redoxfs index 3342778..f40f692 160000 --- a/redoxfs +++ b/redoxfs @@ -1 +1 @@ -Subproject commit 3342778968f30c7725493f18114b5fca495f08b9 +Subproject commit f40f6921e87af58ed4d18f06bd3736b7db76bd20 From 7aa9c32180d95eca8408fc006dad46ce57b6c87b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 22 Jul 2017 13:47:54 -0600 Subject: [PATCH 476/522] Update kernel and cookbook --- cookbook | 2 +- kernel | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cookbook b/cookbook index 36f8f5b..943fe8a 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 36f8f5b5f7dd94384c498e781416cc738fbe783f +Subproject commit 943fe8ae8c99250b2ee0ffe2f4dc9edfe782e328 diff --git a/kernel b/kernel index fc914e0..6a06166 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit fc914e0cae8c865ed260af7286314c7dc8e63f19 +Subproject commit 6a061665e47febfff53e356363cfb7c13873dbec From 7bb40a9f324d8742ddd5e13c8ceecaafcce93d17 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 22 Jul 2017 14:00:32 -0600 Subject: [PATCH 477/522] Simplify filesystem --- filesystem.toml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/filesystem.toml b/filesystem.toml index 64ebcab..53fcaeb 100644 --- a/filesystem.toml +++ b/filesystem.toml @@ -11,7 +11,8 @@ sysroot = "build/filesystem" #acid = {} #binutils = {} #ca-certificates = {} -contain = {} +#cargo = {} +#contain = {} coreutils = {} #curl = {} #dash = {} @@ -19,12 +20,12 @@ drivers = {} extrautils = {} findutils = {} #games = {} -gawk = {} +#gawk = {} #gcc = {} #git = {} #gnu-binutils = {} #gnu-make = {} -installer = {} +#installer = {} ion = {} #lua = {} #nasm = {} @@ -35,15 +36,16 @@ orbdata = {} orbital = {} orbterm = {} orbutils = {} -pastel = {} +#pastel = {} #pixelcannon = {} pkgutils = {} ptyd = {} #python = {} randd = {} -redoxfs = {} +#redoxfs = {} #rust = {} -sed = {} +#rustual-boy = {} +#sed = {} smith = {} #sodium = {} userutils = {} From dbaa2f370e38ce0fd8d97cd640949c390a04b8f1 Mon Sep 17 00:00:00 2001 From: Agoston Szepessy Date: Sat, 22 Jul 2017 19:56:20 -0400 Subject: [PATCH 478/522] Add dependencies to Dockerfile to build Redox --- docker/Dockerfile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 5717fee..62ba20f 100755 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -8,7 +8,8 @@ ENV PATH $CARGO_HOME/bin:$PATH RUN apt-get update \ && apt-get install -y git gosu gcc fuse nasm qemu-utils pkg-config \ - libfuse-dev make curl file sudo apt-transport-https \ + libfuse-dev make curl file sudo apt-transport-https autoconf flex \ + bison texinfo \ && mkdir -p $CARGO_HOME \ && mkdir -p $RUSTUP_HOME \ && curl https://sh.rustup.rs > sh.rustup.rs \ @@ -19,7 +20,10 @@ RUN apt-get update \ && echo "deb $REDOX_TOOLCHAIN_APT /" >> /etc/apt/sources.list.d/redox.list \ && apt-get update \ && apt-get install -y --force-yes x86-64-elf-redox-newlib x86-64-elf-redox-binutils x86-64-elf-redox-gcc \ + && curl -O https://ftp.gnu.org/gnu/automake/automake-1.15.1.tar.gz \ + && tar -xvpf automake-1.15.1.tar.gz; cd automake-1.15.1; ./configure; make; make install; cd .. \ && cargo install xargo \ + && cargo install cargo-config \ && mkdir -p "$SRC_PATH" WORKDIR $SRC_PATH From 2800c0964f128f564e357e4e1910ff10dba23eb2 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 23 Jul 2017 11:58:28 -0600 Subject: [PATCH 479/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index 943fe8a..3863dc9 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 943fe8ae8c99250b2ee0ffe2f4dc9edfe782e328 +Subproject commit 3863dc9b4243ecd7c80f1f6984bcb1083f37c359 From 1562da71b04eea50057faf2183196128c72527b3 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 23 Jul 2017 14:47:56 -0600 Subject: [PATCH 480/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index 6a06166..d6848a1 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 6a061665e47febfff53e356363cfb7c13873dbec +Subproject commit d6848a19951ef67f768f5f8f68aebcd3d42765e5 From f85263b43a2cce2ef1c96df312703d0a415aaaf8 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 23 Jul 2017 16:03:41 -0600 Subject: [PATCH 481/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index d6848a1..ef8c120 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit d6848a19951ef67f768f5f8f68aebcd3d42765e5 +Subproject commit ef8c120533b941399c55f3ac5871a8324ed90897 From ff30f866642bc2a296d5b8a87dbbdc45f9d11207 Mon Sep 17 00:00:00 2001 From: fengalin Date: Mon, 24 Jul 2017 00:29:33 +0200 Subject: [PATCH 482/522] Add a mention for selinux systems in Docker README Selinux blocks the following: - gosu execution labeling (no selinux policy). - permission is denied to the container's user on the tree source binding under /src. Using a different location doesn't solve the issue. The workaround consists in disabling selinux labeling when running the container. --- docker/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docker/README.md b/docker/README.md index 352c392..ee5a351 100644 --- a/docker/README.md +++ b/docker/README.md @@ -17,3 +17,11 @@ To unpack: 3. Creates a new image in the local image repository named `redox` with Redox toolchain installed. You only need to rebuild the image if you want to update the toolchain. 4. Builds Redox using the `redox` image. The arguments allow the container to use `fuse` and ensure the resulting files are owned by the current user. 5. Runs Redox. + +On selinux systems, replace #4 with: +``` +docker run --cap-add MKNOD --cap-add SYS_ADMIN \ + --device /dev/fuse -e LOCAL_USER_ID="$(id -u)" \ + -v "$(pwd):/src" --security-opt label=disable \ + --rm redox make all +``` From 3aaa500b0766e7259f3ce9a22a60b66459911a2f Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 23 Jul 2017 16:59:28 -0600 Subject: [PATCH 483/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index 3863dc9..2067c82 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 3863dc9b4243ecd7c80f1f6984bcb1083f37c359 +Subproject commit 2067c8292e1f7e2af2f794ff7d445bd4772ff1c6 From a4dfbecf3411ea12ec63d716eb91984215bc782c Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 23 Jul 2017 20:23:58 -0600 Subject: [PATCH 484/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index ef8c120..a3b0c8e 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit ef8c120533b941399c55f3ac5871a8324ed90897 +Subproject commit a3b0c8ebff47520e5dc6ded4763b26b11af09db5 From 72674a6e6a7653996ff31e4af1cffce2a35ce189 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 24 Jul 2017 21:17:28 -0600 Subject: [PATCH 485/522] Update redoxfs --- redoxfs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redoxfs b/redoxfs index f40f692..e635648 160000 --- a/redoxfs +++ b/redoxfs @@ -1 +1 @@ -Subproject commit f40f6921e87af58ed4d18f06bd3736b7db76bd20 +Subproject commit e635648ed7e779f52c2af2365ce6f2269ccbdbc6 From 95915513ee83ffee8b933753ae50c33ca4cdbfe5 Mon Sep 17 00:00:00 2001 From: fengalin Date: Mon, 24 Jul 2017 17:15:45 +0200 Subject: [PATCH 486/522] Build docker container with ready to use user env Prepare user environment at build time and update user and group id at runtime if necessary. Update submodule sync step to avoid a dependency on cargo Run `make update all` instead of just `make all`. The target `update` didn't update the container environment since it was executed on the host. --- docker/Dockerfile | 47 ++++++++++++++++++++++++++------------------ docker/README.md | 16 ++++++++------- docker/entrypoint.sh | 25 ++++++++++++----------- 3 files changed, 50 insertions(+), 38 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 62ba20f..4cde57b 100755 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,35 +1,44 @@ FROM ubuntu:17.04 ENV REDOX_TOOLCHAIN_APT http://static.redox-os.org/toolchain/apt/ -ENV SRC_PATH /src -ENV CARGO_HOME /cargo -ENV RUSTUP_HOME /rustup -ENV PATH $CARGO_HOME/bin:$PATH -RUN apt-get update \ +ENV USER user +ARG LOCAL_UID=local +ARG LOCAL_GID=local +ENV BUILD_UID=${LOCAL_UID:-9001} +ENV BUILD_GID=${LOCAL_GID:-9001} + +RUN apt-get update \ && apt-get install -y git gosu gcc fuse nasm qemu-utils pkg-config \ - libfuse-dev make curl file sudo apt-transport-https autoconf flex \ - bison texinfo \ - && mkdir -p $CARGO_HOME \ - && mkdir -p $RUSTUP_HOME \ - && curl https://sh.rustup.rs > sh.rustup.rs \ + libfuse-dev make curl file sudo apt-transport-https autoconf flex \ + bison texinfo \ + && echo "deb $REDOX_TOOLCHAIN_APT /" >> /etc/apt/sources.list.d/redox.list \ + && apt-get update -o Dir::Etc::sourcelist="redox.list" \ + && apt-get install -y --force-yes x86-64-elf-redox-newlib x86-64-elf-redox-binutils x86-64-elf-redox-gcc \ + && groupadd -g $BUILD_GID user \ + && useradd --shell /bin/bash -u $BUILD_UID -g $BUILD_GID -o -c "" -m $USER \ + && echo "$USER ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/user-no-sudo-password + +COPY entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chmod +x /usr/local/bin/entrypoint.sh + +USER $USER +ENV HOME /home/$USER +ENV PATH $HOME/.cargo/bin:$PATH +ENV SRC_PATH $HOME/src +WORKDIR $HOME +RUN curl https://sh.rustup.rs > sh.rustup.rs \ && sh sh.rustup.rs -y \ && rustup update \ && rustup component add rust-src \ && rustup default nightly \ - && echo "deb $REDOX_TOOLCHAIN_APT /" >> /etc/apt/sources.list.d/redox.list \ - && apt-get update \ - && apt-get install -y --force-yes x86-64-elf-redox-newlib x86-64-elf-redox-binutils x86-64-elf-redox-gcc \ && curl -O https://ftp.gnu.org/gnu/automake/automake-1.15.1.tar.gz \ - && tar -xvpf automake-1.15.1.tar.gz; cd automake-1.15.1; ./configure; make; make install; cd .. \ + && tar -xvpf automake-1.15.1.tar.gz; cd automake-1.15.1; ./configure; make; sudo make install; cd .. \ && cargo install xargo \ && cargo install cargo-config \ - && mkdir -p "$SRC_PATH" + && mkdir -p $SRC_PATH WORKDIR $SRC_PATH - -COPY entrypoint.sh /usr/local/bin/entrypoint.sh - -RUN chmod +x /usr/local/bin/entrypoint.sh +USER root ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] diff --git a/docker/README.md b/docker/README.md index ee5a351..fe8333c 100644 --- a/docker/README.md +++ b/docker/README.md @@ -4,11 +4,13 @@ ```shell git clone https://github.com/redox-os/redox.git ; cd redox #1 -make pull #2 -docker build -t redox docker/ #3 +git pull --rebase --recurse-submodules && git submodule sync \ + && git submodule update --recursive --init #2 +docker build --build-arg LOCAL_UID="$(id -u)" --build-arg LOCAL_GID="$(id -g)" \ + -t redox docker/ #3 docker run --cap-add MKNOD --cap-add SYS_ADMIN \ - --device /dev/fuse -e LOCAL_USER_ID="$(id -u)" \ - -v "$(pwd):/src" --rm redox make all #4 + -e LOCAL_UID="$(id -u)" -e LOCAL_GID="$(id -g)" \ + --device /dev/fuse -v "$(pwd):/home/user/src" --rm redox make update all #4 make qemu #5 ``` To unpack: @@ -21,7 +23,7 @@ To unpack: On selinux systems, replace #4 with: ``` docker run --cap-add MKNOD --cap-add SYS_ADMIN \ - --device /dev/fuse -e LOCAL_USER_ID="$(id -u)" \ - -v "$(pwd):/src" --security-opt label=disable \ - --rm redox make all + -e LOCAL_UID="$(id -u)" -e LOCAL_GID="$(id -g)" \ + --device /dev/fuse -v "$(pwd):/home/user/src" --security-opt label=disable \ + --rm redox make update all ``` diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 2270106..d47300e 100755 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -1,17 +1,18 @@ -#!/bin/bash +#!/usr/bin/env bash -# Add local user -# Either use the LOCAL_USER_ID if passed in at runtime or -# fallback +# Use -e LOCAL_UID="$(id -u)" -e LOCAL_GID="$(id -g)" +# on the docker run command line if the container build user is different +# from the run user -USER_ID=${LOCAL_USER_ID:-9001} +CONT_UID=`id -u user` +CONT_GID=`id -g user` +RUN_UID=${LOCAL_UID:-$CONT_UID} +RUN_GID=${LOCAL_GID:-$CONT_GID} -echo "Starting with UID : $USER_ID " -echo "CARGO_HOME is $CARGO_HOME" -echo "RUSTUP_HOME is $RUSTUP_HOME" -useradd --shell /bin/bash -u $USER_ID -o -c "" -m user -export HOME=/home/user -chown user:user -R $CARGO_HOME -chown user:user -R $RUSTUP_HOME +if [ $RUN_UID != $CONT_UID ] || [ $RUN_GID != $CONT_GID ]; then + echo -e "\033[01;38;5;155mChanging user id:group to ${RUN_UID}:${RUN_GID}. Please wait...\033[0m" + groupmod -g $RUN_GID user + usermod -u $RUN_UID -g $RUN_GID user +fi exec gosu user:user "$@" From 3d12947b7227d1873af2116e38f50ff770757d36 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 26 Jul 2017 08:20:43 -0600 Subject: [PATCH 487/522] Update submodules --- cookbook | 2 +- installer | 2 +- kernel | 2 +- redoxfs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cookbook b/cookbook index 2067c82..742340a 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 2067c8292e1f7e2af2f794ff7d445bd4772ff1c6 +Subproject commit 742340a220a8d36506d9ee6ebf0b1e7e39655c51 diff --git a/installer b/installer index 15d37ce..2c0e14c 160000 --- a/installer +++ b/installer @@ -1 +1 @@ -Subproject commit 15d37cea36ee7b7ea86f7d91d2ecd67cdac888f0 +Subproject commit 2c0e14cadf2b088564eefa57ae49924896819774 diff --git a/kernel b/kernel index a3b0c8e..b474136 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit a3b0c8ebff47520e5dc6ded4763b26b11af09db5 +Subproject commit b474136af4cb617c47834d188983e7e1ff701da4 diff --git a/redoxfs b/redoxfs index e635648..c6c9399 160000 --- a/redoxfs +++ b/redoxfs @@ -1 +1 @@ -Subproject commit e635648ed7e779f52c2af2365ce6f2269ccbdbc6 +Subproject commit c6c9399305df1bc93459911f0c147e0daaea6caf From 8383299751465445baeefc16869c92ad8c049d5e Mon Sep 17 00:00:00 2001 From: Michel Boaventura Date: Wed, 26 Jul 2017 21:14:18 -0300 Subject: [PATCH 488/522] Skip fuse install on gentoo if already installed The bootstrap.sh script always installs fuse on gentoo. This small change just checks if it is already installed and skip it if so. --- bootstrap.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bootstrap.sh b/bootstrap.sh index 7180e6f..0278387 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -281,8 +281,10 @@ gentoo() echo "Installing git..." sudo emerge dev-vcs/git fi - echo "Installing fuse..." - sudo emerge sys-fs/fuse + if [ -z "$(which fusermount)" ]; then + echo "Installing fuse..." + sudo emerge sys-fs/fuse + fi if [ "$2" == "qemu" ]; then if [ -z "$(which qemu-system-x86_64)" ]; then echo "Please install QEMU and re-run this script" From 7d319b50f9071b6d218b779bcd6955f6349a580e Mon Sep 17 00:00:00 2001 From: Michel Boaventura Date: Wed, 26 Jul 2017 22:53:23 -0300 Subject: [PATCH 489/522] Fix directions on how to install qemu on Gentoo In order to have ``qemu-system-x86_64`` we need to enable ``x86_64`` on ``QEMU_SOFTMMU_TARGETS``, not ``i386`` --- bootstrap.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap.sh b/bootstrap.sh index 0278387..3f892e4 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -288,7 +288,7 @@ gentoo() if [ "$2" == "qemu" ]; then if [ -z "$(which qemu-system-x86_64)" ]; then echo "Please install QEMU and re-run this script" - echo "Step1. Add QEMU_SOFTMMU_TARGETS=\"i386\" to /etc/portage/make.conf" + echo "Step1. Add QEMU_SOFTMMU_TARGETS=\"x86_64\" to /etc/portage/make.conf" echo "Step2. Execute \"sudo emerge app-emulation/qemu\"" else echo "QEMU already installed!" From 03c1f21e73b21baeb8fe22fea8935fbf1be91a69 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 26 Jul 2017 20:33:40 -0600 Subject: [PATCH 490/522] Update rust, installer --- installer | 2 +- rust | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/installer b/installer index 2c0e14c..c0bc46b 160000 --- a/installer +++ b/installer @@ -1 +1 @@ -Subproject commit 2c0e14cadf2b088564eefa57ae49924896819774 +Subproject commit c0bc46b954eac7ee6f85b9ef716e91a6990dfe8b diff --git a/rust b/rust index 5ebe07d..9e0b455 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 5ebe07d93ae68377d8b8a4f21a0470b5920d8473 +Subproject commit 9e0b455afca6f81257ac80fa0ade64a5d7ddadf9 From a4353ca2745ec98e4563b3b34107b6d70ae8f7a1 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 26 Jul 2017 20:35:49 -0600 Subject: [PATCH 491/522] make update will update cookbook --- Makefile | 1 + cookbook | 2 +- installer | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 6297fc6..580e850 100644 --- a/Makefile +++ b/Makefile @@ -25,6 +25,7 @@ pull: make update update: + cd cookbook && ./update.sh cargo update --manifest-path cookbook/pkgutils/Cargo.toml cargo update --manifest-path installer/Cargo.toml cargo update --manifest-path kernel/Cargo.toml diff --git a/cookbook b/cookbook index 742340a..3e0bc79 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 742340a220a8d36506d9ee6ebf0b1e7e39655c51 +Subproject commit 3e0bc79bb96cf33ffa374925abc882175742c95a diff --git a/installer b/installer index c0bc46b..3efca19 160000 --- a/installer +++ b/installer @@ -1 +1 @@ -Subproject commit c0bc46b954eac7ee6f85b9ef716e91a6990dfe8b +Subproject commit 3efca1947374f3187f34dab47d92635c9243469f From feb1abcbcaa7a405ba9dd03f13815769003b4bac Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 26 Jul 2017 21:14:47 -0600 Subject: [PATCH 492/522] Update kernel, update rustc version in README --- README.md | 3 +-- kernel | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ae7f9c7..ef66df2 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Please make sure you use the **latest nightly** of `rustc` before building (for [![Travis Build Status](https://travis-ci.org/redox-os/redox.svg?branch=master)](https://travis-ci.org/redox-os/redox) [![Downloads](https://img.shields.io/github/downloads/redox-os/redox/total.svg)](https://github.com/redox-os/redox/releases) [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE.md) -![Rust Version](https://img.shields.io/badge/rust-nightly%202017--04--22-lightgrey.svg) +![Rust Version](https://img.shields.io/badge/rust-nightly%202017--07--26-lightgrey.svg) ## Contents @@ -158,4 +158,3 @@ $ make qemu kvm=no # Launch using QEMU without using KVM (Kernel Virtual Machine) nor Graphics make qemu kvm=no vga=no ``` - diff --git a/kernel b/kernel index b474136..2261452 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit b474136af4cb617c47834d188983e7e1ff701da4 +Subproject commit 226145249294c1ff82629f4b8be4024e7e938cad From d420cd6363c6cb782bcd4416f9e5aa3fde0a4731 Mon Sep 17 00:00:00 2001 From: garasubo Date: Fri, 28 Jul 2017 21:22:48 +0900 Subject: [PATCH 493/522] add instruction about docker image In some Linux distribution, it is hard to install redox's toolchain. I think it is kind if README tell us the way to setup with docker. --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index ef66df2..d31e421 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ Please make sure you use the **latest nightly** of `rustc` before building (for * [Cloning, Building and running](#cloning-building-running) * [Quick Setup](#quick-setup) * [Manual Setup](#manual-setup) + * [Setup Using Docker](#setup-using-docker) ## What it looks like @@ -158,3 +159,6 @@ $ make qemu kvm=no # Launch using QEMU without using KVM (Kernel Virtual Machine) nor Graphics make qemu kvm=no vga=no ``` + +### Setup using Docker +We also provide docker image. After cloning this repository, please follow README under the `docker` directory. From 40b8c921a60def767ce1a153ddb13a6e407e5441 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 29 Jul 2017 08:18:07 -0600 Subject: [PATCH 494/522] Update kernel and rust --- kernel | 2 +- rust | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel b/kernel index 2261452..21d033a 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 226145249294c1ff82629f4b8be4024e7e938cad +Subproject commit 21d033a1a85e91dd9dd502f2ddfae08230639ef8 diff --git a/rust b/rust index 9e0b455..71f7231 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 9e0b455afca6f81257ac80fa0ade64a5d7ddadf9 +Subproject commit 71f72311e4fd43f59369317dc4e4a5b64b714136 From 4af0d2bd840275c60710802ff2d348cece74ac24 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 29 Jul 2017 08:19:47 -0600 Subject: [PATCH 495/522] Only update packages in toml --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 580e850..1ccb277 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,8 @@ pull: make update update: - cd cookbook && ./update.sh + cd cookbook; \ + ./update.sh "$$(cargo run --manifest-path ../installer/Cargo.toml -- --list-packages ../initfs.toml ../filesystem.toml)" cargo update --manifest-path cookbook/pkgutils/Cargo.toml cargo update --manifest-path installer/Cargo.toml cargo update --manifest-path kernel/Cargo.toml From 2b0d014d903bab70a10f4a6b5b67a48b76a51207 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 29 Jul 2017 08:27:48 -0600 Subject: [PATCH 496/522] Update submodules --- cookbook | 2 +- installer | 2 +- redoxfs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cookbook b/cookbook index 3e0bc79..a7065f4 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 3e0bc79bb96cf33ffa374925abc882175742c95a +Subproject commit a7065f4a90ec4e04471a24db84e95be42cbcba09 diff --git a/installer b/installer index 3efca19..ed468af 160000 --- a/installer +++ b/installer @@ -1 +1 @@ -Subproject commit 3efca1947374f3187f34dab47d92635c9243469f +Subproject commit ed468af4c3c7922dd2f45ada8edbe8854b3e432c diff --git a/redoxfs b/redoxfs index c6c9399..3b78720 160000 --- a/redoxfs +++ b/redoxfs @@ -1 +1 @@ -Subproject commit c6c9399305df1bc93459911f0c147e0daaea6caf +Subproject commit 3b7872016755858deeab958a4d81cce98b2fe51e From f7e2de5629286cd8a8e00697b106ce27237e4e09 Mon Sep 17 00:00:00 2001 From: garasubo Date: Tue, 1 Aug 2017 23:09:05 +0900 Subject: [PATCH 497/522] improve README Add an instruction about redox toolchain --- README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index d31e421..56b838c 100644 --- a/README.md +++ b/README.md @@ -78,13 +78,14 @@ The ecosystem and software Redox OS provides is listed below. Sometimes things go wrong when compiling. Try the following before opening an issue: +1. Make sure you have a redox toolchain (`x86_64-elf-redox-gcc`). + * You can install from .deb packages(`https://static.redox-os.org/toolchain/apt/`) or build [redox-os/libc](https://github.com/redox-os/libc) manually. 1. Run `rustup update` -2. Run `make clean`. -3. Run `git clean -Xfd`. -4. Make sure you have **the latest version of Rust nightly!** ([rustup.rs](https://www.rustup.rs) is recommended for managing Rust versions. If you already have it, run `rustup`). -5. Update **GNU Make**, **NASM** and **QEMU/VirtualBox**. -6. Pull the upstream master branch (`git remote add upstream git@github.com:redox-os/redox.git; git pull upstream master`). -7. Update submodules (`git submodule update --recursive --init`). +1. Run `make clean pull`. +1. Make sure you have **the latest version of Rust nightly!** ([rustup.rs](https://www.rustup.rs) is recommended for managing Rust versions. If you already have it, run `rustup`). +1. Update **GNU Make**, **NASM** and **QEMU/VirtualBox**. +1. Pull the upstream master branch (`git remote add upstream git@github.com:redox-os/redox.git; git pull upstream master`). +1. Update submodules (`git submodule update --recursive --init`). and then rebuild! From cded5264bfae71a593bd8416027dcebd9943cedf Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 1 Aug 2017 19:46:22 -0600 Subject: [PATCH 498/522] Update cookbook and redoxfs --- cookbook | 2 +- redoxfs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cookbook b/cookbook index a7065f4..ebcdd86 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit a7065f4a90ec4e04471a24db84e95be42cbcba09 +Subproject commit ebcdd869ddd50127ae3c3dedb868f47bd1ef4caa diff --git a/redoxfs b/redoxfs index 3b78720..1e9cec6 160000 --- a/redoxfs +++ b/redoxfs @@ -1 +1 @@ -Subproject commit 3b7872016755858deeab958a4d81cce98b2fe51e +Subproject commit 1e9cec60924ca1d52727c846e02ee63a2c096bc2 From 6e0c0a08948ed8332cc2d360b8fbf6a4d929afdc Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 2 Aug 2017 19:00:13 -0600 Subject: [PATCH 499/522] Update kernel and redoxfs --- kernel | 2 +- redoxfs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel b/kernel index 21d033a..8932daf 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 21d033a1a85e91dd9dd502f2ddfae08230639ef8 +Subproject commit 8932daf04ac8726cea79594a002874a062a7cc15 diff --git a/redoxfs b/redoxfs index 1e9cec6..e270ce1 160000 --- a/redoxfs +++ b/redoxfs @@ -1 +1 @@ -Subproject commit 1e9cec60924ca1d52727c846e02ee63a2c096bc2 +Subproject commit e270ce117f6fd9ee90f0d24d6e48ef57caf54a8c From 98a2e0f58ce3a7d812e296a312439eab8a9647f8 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 2 Aug 2017 19:07:09 -0600 Subject: [PATCH 500/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index 8932daf..d8d78ff 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 8932daf04ac8726cea79594a002874a062a7cc15 +Subproject commit d8d78ffbef9897c538e5f2c9660ce9b5e5bf3918 From 183f2d51267524d377be7de30e49268275a60438 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 2 Aug 2017 19:56:07 -0600 Subject: [PATCH 501/522] Update submodules --- cookbook | 2 +- installer | 2 +- redoxfs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cookbook b/cookbook index ebcdd86..1e2cf8a 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit ebcdd869ddd50127ae3c3dedb868f47bd1ef4caa +Subproject commit 1e2cf8a2b3ee25dd2d66831e740f5266f6223891 diff --git a/installer b/installer index ed468af..a9a1f0e 160000 --- a/installer +++ b/installer @@ -1 +1 @@ -Subproject commit ed468af4c3c7922dd2f45ada8edbe8854b3e432c +Subproject commit a9a1f0e76d2fa8204f397180ab1bf4824347e5f5 diff --git a/redoxfs b/redoxfs index e270ce1..a830383 160000 --- a/redoxfs +++ b/redoxfs @@ -1 +1 @@ -Subproject commit e270ce117f6fd9ee90f0d24d6e48ef57caf54a8c +Subproject commit a830383220461c226755517f55a7e42850e8f8e4 From 785ef9a210acc4f7a471f424a5bd0e6731062b64 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 2 Aug 2017 21:17:23 -0600 Subject: [PATCH 502/522] Update cookbook, installer --- cookbook | 2 +- installer | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cookbook b/cookbook index 1e2cf8a..072917c 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 1e2cf8a2b3ee25dd2d66831e740f5266f6223891 +Subproject commit 072917c5df6cf00deac7dbddd94b2869fdcb800d diff --git a/installer b/installer index a9a1f0e..a76c8df 160000 --- a/installer +++ b/installer @@ -1 +1 @@ -Subproject commit a9a1f0e76d2fa8204f397180ab1bf4824347e5f5 +Subproject commit a76c8df8675ac5a173f40aef129fbc075867a48f From 95101b7dfe28340e4c7fbe80bb09a9cf83461ef7 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 6 Aug 2017 15:42:46 -0600 Subject: [PATCH 503/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index d8d78ff..64d7d24 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit d8d78ffbef9897c538e5f2c9660ce9b5e5bf3918 +Subproject commit 64d7d2417498cb7f3286832f542183fca206f668 From 1dcfd892508f9b4561e0a14447648fa1487085cf Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 9 Aug 2017 20:36:13 -0600 Subject: [PATCH 504/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index 072917c..8eba300 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 072917c5df6cf00deac7dbddd94b2869fdcb800d +Subproject commit 8eba3003c6749b7108a9d6e511b59369976206d7 From 7ff5b3448094f09ea9cbde1d1a522d312b0c2cc8 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 9 Aug 2017 20:36:39 -0600 Subject: [PATCH 505/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index 64d7d24..b43f150 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 64d7d2417498cb7f3286832f542183fca206f668 +Subproject commit b43f1503b77759a9132a152d049da76952763e53 From 9179e2d3e006ce23493b3983dfc3bfe9450d052e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 9 Aug 2017 20:48:48 -0600 Subject: [PATCH 506/522] Update Rust --- rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust b/rust index 71f7231..fc23917 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 71f72311e4fd43f59369317dc4e4a5b64b714136 +Subproject commit fc2391721c85816ed82cfc9574b59c00d5ef666a From 2a9817e5e689deed85bc8a40e652e4cd1baa6ec8 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 9 Aug 2017 20:49:42 -0600 Subject: [PATCH 507/522] Revert rust to upstream master --- rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust b/rust index fc23917..875bcf5 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit fc2391721c85816ed82cfc9574b59c00d5ef666a +Subproject commit 875bcf5c5f7efcbf72e000d256b24293555edf53 From a2f26717ecd9fba75acc0da55f145986300c6e64 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 9 Aug 2017 21:06:11 -0600 Subject: [PATCH 508/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index b43f150..5c5e5da 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit b43f1503b77759a9132a152d049da76952763e53 +Subproject commit 5c5e5da7c2503dc68cd254259fe7992ce29df8d6 From 9175dec21e4e7b19e1113b08799f7f059b67c20b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 12 Aug 2017 06:45:14 -0600 Subject: [PATCH 509/522] Update rust --- rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust b/rust index 875bcf5..c7d206e 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 875bcf5c5f7efcbf72e000d256b24293555edf53 +Subproject commit c7d206ed9544e3ee6b56d14d89f848c4b1251ce8 From a61450e16acb7eee8f6cc0e342f36049056439aa Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 12 Aug 2017 06:45:31 -0600 Subject: [PATCH 510/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index 8eba300..5a746d5 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 8eba3003c6749b7108a9d6e511b59369976206d7 +Subproject commit 5a746d52f3fa458d1e4c09aa96326455bb7ef36b From c323f81b8c7fea679010757f63c05e55ffa04a87 Mon Sep 17 00:00:00 2001 From: fengalin Date: Sat, 12 Aug 2017 01:53:51 +0200 Subject: [PATCH 511/522] Update docker container build script and README - Use https for redox apt repository - Import the repository's key - Update [toolchain packages' names](https://github.com/redox-os/cookbook/pull/59) - Install `wget` which is needed by [coobook/recipes/xz](https://github.com/redox-os/cookbook/blob/master/recipes/xz/recipe.sh) - Update README file to reflect the [discussion about when the submodules are needed](https://github.com/redox-os/redox/pull/1005#discussion_r129432929) - Update README file to suggest using `make fetch all` in place of `make update all` since `Cargo.lock` files come with the sources now. See this [comment](https://github.com/redox-os/redox/issues/1021#issuecomment-320946322) Note: current source tree generation requires runing the docker container with `bash -c RUSTFLAGS=\"-A unused_mut\" make fetch all` in place of `make fetch all` --- docker/Dockerfile | 9 +++++---- docker/README.md | 14 +++++++------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 4cde57b..c3c0905 100755 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,6 +1,6 @@ FROM ubuntu:17.04 -ENV REDOX_TOOLCHAIN_APT http://static.redox-os.org/toolchain/apt/ +ENV REDOX_TOOLCHAIN_APT https://static.redox-os.org/toolchain/apt/ ENV USER user ARG LOCAL_UID=local @@ -9,12 +9,13 @@ ENV BUILD_UID=${LOCAL_UID:-9001} ENV BUILD_GID=${LOCAL_GID:-9001} RUN apt-get update \ - && apt-get install -y git gosu gcc fuse nasm qemu-utils pkg-config \ - libfuse-dev make curl file sudo apt-transport-https autoconf flex \ + && apt-get install -y dirmngr git gosu gcc fuse nasm qemu-utils pkg-config \ + libfuse-dev make curl wget file sudo apt-transport-https autoconf flex \ bison texinfo \ + && apt-key adv --fetch-keys https://static.redox-os.org/toolchain/apt/keyFile \ && echo "deb $REDOX_TOOLCHAIN_APT /" >> /etc/apt/sources.list.d/redox.list \ && apt-get update -o Dir::Etc::sourcelist="redox.list" \ - && apt-get install -y --force-yes x86-64-elf-redox-newlib x86-64-elf-redox-binutils x86-64-elf-redox-gcc \ + && apt-get install -y x86-64-unknown-redox-newlib x86-64-unknown-redox-binutils x86-64-unknown-redox-gcc \ && groupadd -g $BUILD_GID user \ && useradd --shell /bin/bash -u $BUILD_UID -g $BUILD_GID -o -c "" -m $USER \ && echo "$USER ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/user-no-sudo-password diff --git a/docker/README.md b/docker/README.md index fe8333c..93cc9d7 100644 --- a/docker/README.md +++ b/docker/README.md @@ -4,19 +4,19 @@ ```shell git clone https://github.com/redox-os/redox.git ; cd redox #1 -git pull --rebase --recurse-submodules && git submodule sync \ - && git submodule update --recursive --init #2 docker build --build-arg LOCAL_UID="$(id -u)" --build-arg LOCAL_GID="$(id -g)" \ - -t redox docker/ #3 + -t redox docker/ #2 +git pull --rebase --recurse-submodules && git submodule sync \ + && git submodule update --recursive --init #3 docker run --cap-add MKNOD --cap-add SYS_ADMIN \ -e LOCAL_UID="$(id -u)" -e LOCAL_GID="$(id -g)" \ - --device /dev/fuse -v "$(pwd):/home/user/src" --rm redox make update all #4 + --device /dev/fuse -v "$(pwd):/home/user/src" --rm redox make fetch all #4 make qemu #5 ``` To unpack: 1. Creates a local copy of the repository. -2. Updates all the submodules in the repository. -3. Creates a new image in the local image repository named `redox` with Redox toolchain installed. You only need to rebuild the image if you want to update the toolchain. +2. Creates a new image in the local image repository named `redox` with Redox toolchain installed. You only need to rebuild the image if you want to update the toolchain. +3. Updates all the submodules in the repository. 4. Builds Redox using the `redox` image. The arguments allow the container to use `fuse` and ensure the resulting files are owned by the current user. 5. Runs Redox. @@ -25,5 +25,5 @@ On selinux systems, replace #4 with: docker run --cap-add MKNOD --cap-add SYS_ADMIN \ -e LOCAL_UID="$(id -u)" -e LOCAL_GID="$(id -g)" \ --device /dev/fuse -v "$(pwd):/home/user/src" --security-opt label=disable \ - --rm redox make update all + --rm redox make fetch all ``` From 3c5116424bdc2330d247fa31c9497446e3898ef5 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 12 Aug 2017 11:25:28 -0600 Subject: [PATCH 512/522] Update redoxfs --- redoxfs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redoxfs b/redoxfs index a830383..801cbd9 160000 --- a/redoxfs +++ b/redoxfs @@ -1 +1 @@ -Subproject commit a830383220461c226755517f55a7e42850e8f8e4 +Subproject commit 801cbd9072086b97ddff8605230bab5ee2b2b6d9 From e6296278054d4f150dfaea760488684c4cd70a85 Mon Sep 17 00:00:00 2001 From: Michel Boaventura Date: Sun, 13 Aug 2017 14:39:04 -0300 Subject: [PATCH 513/522] Update README The toolchain now is called ``x86_64-unknown-redox`` --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 56b838c..ec19e21 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ The ecosystem and software Redox OS provides is listed below. Sometimes things go wrong when compiling. Try the following before opening an issue: -1. Make sure you have a redox toolchain (`x86_64-elf-redox-gcc`). +1. Make sure you have a redox toolchain (`x86_64-unknown-redox-gcc`). * You can install from .deb packages(`https://static.redox-os.org/toolchain/apt/`) or build [redox-os/libc](https://github.com/redox-os/libc) manually. 1. Run `rustup update` 1. Run `make clean pull`. From c436d81a09e455b3ccb22ec39e948eb2e16cefa9 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 13 Aug 2017 15:04:29 -0600 Subject: [PATCH 514/522] Update Rust --- rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust b/rust index c7d206e..a80a873 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit c7d206ed9544e3ee6b56d14d89f848c4b1251ce8 +Subproject commit a80a873209a79499290201f8657618703a51b73e From b4e614d7a7bc408fd7824bec67dbf48077e39d5f Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Mon, 14 Aug 2017 11:13:33 -0700 Subject: [PATCH 515/522] Add uutils to filesystem.toml --- filesystem.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/filesystem.toml b/filesystem.toml index 53fcaeb..8344c12 100644 --- a/filesystem.toml +++ b/filesystem.toml @@ -49,6 +49,7 @@ randd = {} smith = {} #sodium = {} userutils = {} +uutils = {} # User settings [users.root] From 361588261f386c396fcbda29b858b286dff14c26 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 15 Aug 2017 20:09:10 -0600 Subject: [PATCH 516/522] Update rust --- rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust b/rust index a80a873..1e60a47 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit a80a873209a79499290201f8657618703a51b73e +Subproject commit 1e60a477a3f28ec5dc6e93e2714320d829bd7942 From d86227bbd4d249fc47da9ac11356c80041d4ea89 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Tue, 15 Aug 2017 19:45:10 -0700 Subject: [PATCH 517/522] Update cookbook submodule --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index 5a746d5..5f961f8 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 5a746d52f3fa458d1e4c09aa96326455bb7ef36b +Subproject commit 5f961f888b8cc32266f63713073ad13c1983e3e0 From b03748cd66bd653d5c0ae243a127063e291b8466 Mon Sep 17 00:00:00 2001 From: Agoston Szepessy Date: Tue, 15 Aug 2017 23:46:25 -0400 Subject: [PATCH 518/522] Update README to describe Makefile options --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index ec19e21..c36693b 100644 --- a/README.md +++ b/README.md @@ -163,3 +163,12 @@ make qemu kvm=no vga=no ### Setup using Docker We also provide docker image. After cloning this repository, please follow README under the `docker` directory. + +### Updating the codebase using the Makefile +To update the codebase run: + +``` +make pull; make fetch +``` + +`make pull` pulls and updates the submodules, and `make fetch` updates the sources for cookbook recipes. From 2583d6c1704b096fa144907c9cdb5fa857159fb7 Mon Sep 17 00:00:00 2001 From: Agoston Szepessy Date: Tue, 15 Aug 2017 23:49:22 -0400 Subject: [PATCH 519/522] Remove link to Magnet from README The link for Magnet led to a page that displayed a 404 error. --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index c36693b..20cdb98 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,6 @@ The ecosystem and software Redox OS provides is listed below. | [libextra](https://github.com/redox-os/libextra) | [**@ticki**](https://github.com/ticki) | [libpager](https://github.com/redox-os/libpager) | [**@ticki**](https://github.com/ticki) | [libstd (Redox standard library)](https://github.com/redox-os/libstd) | [**@jackpot51**](https://github.com/jackpot51) -| [Magnet (future package manager)](https://github.com/redox-os/magnet) | [**@ticki**](https://github.com/ticki) | [netutils](https://github.com/redox-os/netutils) | [**@jackpot51**](https://github.com/jackpot51) | [orbclient (Orbital client)](https://github.com/redox-os/orbclient) | [**@jackpot51**](https://github.com/jackpot51) | [orbdata](https://github.com/redox-os/orbdata) | [**@jackpot51**](https://github.com/jackpot51) From 5f8fa86ccec05b08ae4dae88e5e976b4634323c2 Mon Sep 17 00:00:00 2001 From: fengalin Date: Wed, 16 Aug 2017 15:23:15 +0200 Subject: [PATCH 520/522] Docker: align APT key retrieval with Cookbook README Use the same command as the Cookbook README for Redox OS APT key retrieval. Keep adding the Redox OS repository in a dedicated file. This allows updating it specifically without updating the other repositories one more time. --- docker/Dockerfile | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index c3c0905..b59fae3 100755 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,7 +1,5 @@ FROM ubuntu:17.04 -ENV REDOX_TOOLCHAIN_APT https://static.redox-os.org/toolchain/apt/ - ENV USER user ARG LOCAL_UID=local ARG LOCAL_GID=local @@ -12,8 +10,8 @@ RUN apt-get update \ && apt-get install -y dirmngr git gosu gcc fuse nasm qemu-utils pkg-config \ libfuse-dev make curl wget file sudo apt-transport-https autoconf flex \ bison texinfo \ - && apt-key adv --fetch-keys https://static.redox-os.org/toolchain/apt/keyFile \ - && echo "deb $REDOX_TOOLCHAIN_APT /" >> /etc/apt/sources.list.d/redox.list \ + && apt-key adv --keyserver keyserver.ubuntu.com --recv-keys AA12E97F0881517F \ + && echo "deb https://static.redox-os.org/toolchain/apt/ /" >> /etc/apt/sources.list.d/redox.list \ && apt-get update -o Dir::Etc::sourcelist="redox.list" \ && apt-get install -y x86-64-unknown-redox-newlib x86-64-unknown-redox-binutils x86-64-unknown-redox-gcc \ && groupadd -g $BUILD_GID user \ From 0e60d15297d9de84320c612a44369da423c9946f Mon Sep 17 00:00:00 2001 From: fengalin Date: Wed, 16 Aug 2017 15:49:23 +0200 Subject: [PATCH 521/522] Attempt to fix travis build --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index fde6e0b..c438058 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ before_install: sudo add-apt-repository 'deb https://static.redox-os.org/toolchain/apt ./' && sudo apt-get update -qq && sudo apt-get purge -qq binutils-doc && - sudo apt-get install -qq nasm pkg-config fuse libfuse-dev genisoimage syslinux x86-64-elf-redox-gcc && + sudo apt-get install -qq nasm pkg-config fuse libfuse-dev genisoimage syslinux x86-64-unknown-redox-gcc && sudo modprobe fuse && sudo chmod 666 /dev/fuse && sudo chown root:$USER /etc/fuse.conf; From aaf85163578c2b72cadbf049f97747eb8ae6447a Mon Sep 17 00:00:00 2001 From: Mihal Malostanidis Date: Wed, 16 Aug 2017 23:20:12 +0300 Subject: [PATCH 522/522] Fix logo src redox-os/assets were rearranged. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 20cdb98..8c0b53f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

    -Redox +Redox

    **Redox** is an operating system written in Rust, a language with focus on safety and high performance. Redox, following the microkernel design, aims to be secure, usable, and free. Redox is inspired by previous kernels and operating systems, such as SeL4, Minix, Plan 9, and BSD.

*`v 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 From d8aded02d5e4080f74eac9d8001ffded1b28b5d2 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 5 Jan 2017 13:28:57 -0700 Subject: [PATCH 051/522] Update gcc.sh --- libc-artifacts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libc-artifacts b/libc-artifacts index 92eb10e..67098b3 160000 --- a/libc-artifacts +++ b/libc-artifacts @@ -1 +1 @@ -Subproject commit 92eb10e3a30a2a422d46bd16651071f8d2d0f1fd +Subproject commit 67098b38c671d7804c3b9b7b856090099d4cecda From 099e4e7fa0918aa5ca16663190f551bc177c3e68 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 5 Jan 2017 13:30:09 -0700 Subject: [PATCH 052/522] Use cargo to build kernel dependencies --- Makefile | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/Makefile b/Makefile index 9592719..e448fed 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,6 @@ export CFLAGS=-fno-stack-protector -U_FORTIFY_SOURCE KTARGET=$(ARCH)-unknown-none KBUILD=build/kernel KRUSTC=./krustc.sh -KRUSTCFLAGS=--target $(KTARGET) -C opt-level=2 -C debuginfo=0 -C soft-float KRUSTDOC=./krustdoc.sh KCARGO=RUSTC="$(KRUSTC)" RUSTDOC="$(KRUSTDOC)" cargo KCARGOFLAGS=--target $(KTARGET) --release -- -C soft-float @@ -20,10 +19,9 @@ KCARGOFLAGS=--target $(KTARGET) --release -- -C soft-float export TARGET=$(ARCH)-unknown-redox BUILD=build/userspace RUSTC=./rustc.sh -RUSTCFLAGS=--target $(TARGET) -C opt-level=2 -C debuginfo=0 RUSTDOC=./rustdoc.sh CARGO=RUSTC="$(RUSTC)" RUSTDOC="$(RUSTDOC)" cargo -CARGOFLAGS=--target $(TARGET) --release -- +CARGOFLAGS=--target $(TARGET) --release -- -C codegen-units=`nproc` # Default targets .PHONY: all live iso clean doc ref test update pull qemu bochs drivers schemes binutils coreutils extrautils netutils userutils wireshark FORCE @@ -38,6 +36,7 @@ FORCE: clean: cargo clean + cargo clean --manifest-path rust/src/libcollections/Cargo.toml cargo clean --manifest-path rust/src/libstd/Cargo.toml -$(FUMOUNT) build/filesystem/ || true rm -rf initfs/bin @@ -227,26 +226,15 @@ virtualbox: build/harddrive.bin $(VBM) startvm Redox # Kernel recipes -$(KBUILD)/libcore.rlib: rust/src/libcore/lib.rs +$(KBUILD)/libcollections.rlib: rust/src/libcollections/Cargo.toml rust/src/libcollections/** mkdir -p $(KBUILD) - $(KRUSTC) $(KRUSTCFLAGS) -o $@ $< + $(KCARGO) rustc --verbose --manifest-path $< $(KCARGOFLAGS) -o $@ + cp rust/src/target/$(KTARGET)/release/deps/*.rlib $(KBUILD) -$(KBUILD)/librand.rlib: rust/src/librand/lib.rs $(KBUILD)/libcore.rlib - $(KRUSTC) $(KRUSTCFLAGS) -o $@ $< - -$(KBUILD)/liballoc.rlib: rust/src/liballoc/lib.rs $(KBUILD)/libcore.rlib - $(KRUSTC) $(KRUSTCFLAGS) -o $@ $< - -$(KBUILD)/libstd_unicode.rlib: rust/src/libstd_unicode/lib.rs $(KBUILD)/libcore.rlib - $(KRUSTC) $(KRUSTCFLAGS) -o $@ $< - -$(KBUILD)/libcollections.rlib: rust/src/libcollections/lib.rs $(KBUILD)/libcore.rlib $(KBUILD)/liballoc.rlib $(KBUILD)/libstd_unicode.rlib - $(KRUSTC) $(KRUSTCFLAGS) -o $@ $< - -$(KBUILD)/libkernel.a: kernel/Cargo.toml kernel/arch/** kernel/src/** $(KBUILD)/libcore.rlib $(KBUILD)/liballoc.rlib $(KBUILD)/libcollections.rlib $(BUILD)/initfs.rs +$(KBUILD)/libkernel.a: kernel/Cargo.toml kernel/arch/** kernel/src/** $(KBUILD)/libcollections.rlib $(BUILD)/initfs.rs $(KCARGO) rustc --manifest-path $< --lib $(KCARGOFLAGS) -C lto --emit obj=$@ -$(KBUILD)/libkernel_live.a: kernel/Cargo.toml kernel/arch/** kernel/src/** $(KBUILD)/libcore.rlib $(KBUILD)/liballoc.rlib $(KBUILD)/libcollections.rlib $(BUILD)/initfs.rs build/filesystem.bin +$(KBUILD)/libkernel_live.a: kernel/Cargo.toml kernel/arch/** kernel/src/** $(KBUILD)/libcollections.rlib $(BUILD)/initfs.rs build/filesystem.bin $(KCARGO) rustc --manifest-path $< --lib --features live $(KCARGOFLAGS) -C lto --emit obj=$@ $(KBUILD)/kernel: $(KBUILD)/libkernel.a From b7a19200a893a129abfe3eb6447cb645a33fba9d Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 5 Jan 2017 14:02:41 -0700 Subject: [PATCH 053/522] Update docgen --- crates/docgen | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/docgen b/crates/docgen index 2e1bcf2..d2e0e0d 160000 --- a/crates/docgen +++ b/crates/docgen @@ -1 +1 @@ -Subproject commit 2e1bcf2ab5a03d176e7c66ae79c31ffccdcda77a +Subproject commit d2e0e0d24006628609fb5d77b60f0a83299f4937 From e3f3f27fbc8d0e4cb8b4ddab44100675b2939f14 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 5 Jan 2017 14:07:20 -0700 Subject: [PATCH 054/522] Modularise makefiles --- Cargo.toml | 63 ++--- Makefile | 511 ++----------------------------------- mk/bochs.mk | 2 + mk/config.mk | 51 ++++ mk/disk.mk | 18 ++ mk/doc.mk | 13 + mk/filesystem.mk | 41 +++ mk/initfs.mk | 28 ++ mk/kernel.mk | 16 ++ mk/qemu.mk | 48 ++++ mk/userspace/binutils.mk | 9 + mk/userspace/coreutils.mk | 43 ++++ mk/userspace/drivers.mk | 14 + mk/userspace/extrautils.mk | 16 ++ mk/userspace/games.mk | 11 + mk/userspace/ion.mk | 11 + mk/userspace/mod.mk | 42 +++ mk/userspace/netutils.mk | 14 + mk/userspace/orbutils.mk | 15 ++ mk/userspace/pkgutils.mk | 7 + mk/userspace/schemes.mk | 25 ++ mk/userspace/userutils.mk | 12 + mk/virtualbox.mk | 41 +++ 23 files changed, 525 insertions(+), 526 deletions(-) create mode 100644 mk/bochs.mk create mode 100644 mk/config.mk create mode 100644 mk/disk.mk create mode 100644 mk/doc.mk create mode 100644 mk/filesystem.mk create mode 100644 mk/initfs.mk create mode 100644 mk/kernel.mk create mode 100644 mk/qemu.mk create mode 100644 mk/userspace/binutils.mk create mode 100644 mk/userspace/coreutils.mk create mode 100644 mk/userspace/drivers.mk create mode 100644 mk/userspace/extrautils.mk create mode 100644 mk/userspace/games.mk create mode 100644 mk/userspace/ion.mk create mode 100644 mk/userspace/mod.mk create mode 100644 mk/userspace/netutils.mk create mode 100644 mk/userspace/orbutils.mk create mode 100644 mk/userspace/pkgutils.mk create mode 100644 mk/userspace/schemes.mk create mode 100644 mk/userspace/userutils.mk create mode 100644 mk/virtualbox.mk diff --git a/Cargo.toml b/Cargo.toml index d6329de..e12b7df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,34 +1,35 @@ [workspace] members = [ - "drivers/ahcid", - "drivers/bgad", - "drivers/e1000d", - "drivers/pcid", - "drivers/ps2d", - "drivers/rtl8168d", - "drivers/vesad", - "kernel", - "programs/acid", - "programs/binutils", - "programs/contain", - "programs/coreutils", - "programs/extrautils", - "programs/games", - "programs/init", - "programs/ion", - "programs/netutils", - "programs/orbutils", - "programs/pkgutils", - "programs/smith", - "programs/tar", - "programs/userutils", - "schemes/ethernetd", - "schemes/example", - "schemes/ipd", - "schemes/orbital", - "schemes/ptyd", - "schemes/randd", - "schemes/redoxfs", - "schemes/tcpd", - "schemes/udpd" + "crates/docgen", + "drivers/ahcid", + "drivers/bgad", + "drivers/e1000d", + "drivers/pcid", + "drivers/ps2d", + "drivers/rtl8168d", + "drivers/vesad", + "kernel", + "programs/acid", + "programs/binutils", + "programs/contain", + "programs/coreutils", + "programs/extrautils", + "programs/games", + "programs/init", + "programs/ion", + "programs/netutils", + "programs/orbutils", + "programs/pkgutils", + "programs/smith", + "programs/tar", + "programs/userutils", + "schemes/ethernetd", + "schemes/example", + "schemes/ipd", + "schemes/orbital", + "schemes/ptyd", + "schemes/randd", + "schemes/redoxfs", + "schemes/tcpd", + "schemes/udpd" ] diff --git a/Makefile b/Makefile index e448fed..eb7df63 100644 --- a/Makefile +++ b/Makefile @@ -1,30 +1,5 @@ -# Configuration -ARCH?=x86_64 - -# Automatic variables -ROOT=$(PWD) -export RUST_TARGET_PATH=$(ROOT)/targets -export CC=$(ROOT)/libc-artifacts/gcc.sh -export CFLAGS=-fno-stack-protector -U_FORTIFY_SOURCE - -# Kernel variables -KTARGET=$(ARCH)-unknown-none -KBUILD=build/kernel -KRUSTC=./krustc.sh -KRUSTDOC=./krustdoc.sh -KCARGO=RUSTC="$(KRUSTC)" RUSTDOC="$(KRUSTDOC)" cargo -KCARGOFLAGS=--target $(KTARGET) --release -- -C soft-float - -# Userspace variables -export TARGET=$(ARCH)-unknown-redox -BUILD=build/userspace -RUSTC=./rustc.sh -RUSTDOC=./rustdoc.sh -CARGO=RUSTC="$(RUSTC)" RUSTDOC="$(RUSTDOC)" cargo -CARGOFLAGS=--target $(TARGET) --release -- -C codegen-units=`nproc` - -# Default targets -.PHONY: all live iso clean doc ref test update pull qemu bochs drivers schemes binutils coreutils extrautils netutils userutils wireshark FORCE +# Configuration and variables +include mk/config.mk all: build/harddrive.bin @@ -32,8 +7,6 @@ live: build/livedisk.bin iso: build/livedisk.iso -FORCE: - clean: cargo clean cargo clean --manifest-path rust/src/libcollections/Cargo.toml @@ -43,25 +16,6 @@ clean: rm -rf filesystem/bin filesystem/sbin filesystem/ui/bin rm -rf build -doc: \ - doc-kernel \ - doc-std - -#FORCE to let cargo decide if docs need updating -doc-kernel: $(KBUILD)/libkernel.a FORCE - $(KCARGO) doc --target $(KTARGET).json --manifest-path kernel/Cargo.toml - -doc-std: $(BUILD)/libstd.rlib FORCE - $(CARGO) doc --target $(TARGET).json --manifest-path rust/src/libstd/Cargo.toml - -ref: FORCE - rm -rf filesystem/ref/ - mkdir -p filesystem/ref/ - cargo run --manifest-path crates/docgen/Cargo.toml -- programs/binutils/src/bin/ filesystem/ref/ - cargo run --manifest-path crates/docgen/Cargo.toml -- programs/coreutils/src/bin/ filesystem/ref/ - cargo run --manifest-path crates/docgen/Cargo.toml -- programs/extrautils/src/bin/ filesystem/ref/ - cargo run --manifest-path crates/docgen/Cargo.toml -- programs/netutils/src/ filesystem/ref/ - update: cargo update @@ -73,460 +27,27 @@ pull: make clean make update -# Emulation -QEMU=SDL_VIDEO_X11_DGAMOUSE=0 qemu-system-$(ARCH) -QEMUFLAGS=-serial mon:stdio -d cpu_reset -d guest_errors -ifeq ($(ARCH),arm) - QEMUFLAGS+=-cpu arm1176 -machine integratorcp - QEMUFLAGS+=-nographic - - export CC=$(ARCH)-none-eabi-gcc - export LD=$(ARCH)-none-eabi-ld - -%.list: % - $(ARCH)-none-eabi-objdump -C -D $< > $@ - -build/harddrive.bin: $(KBUILD)/kernel - cp $< $@ - -qemu: build/harddrive.bin - $(QEMU) $(QEMUFLAGS) -kernel $< -else - QEMUFLAGS+=-smp 4 -m 1024 - ifeq ($(iommu),yes) - QEMUFLAGS+=-machine q35,iommu=on - else - QEMUFLAGS+=-machine q35 - endif - ifeq ($(net),no) - QEMUFLAGS+=-net none - else - QEMUFLAGS+=-net nic,model=e1000 -net user -net dump,file=build/network.pcap - ifeq ($(net),redir) - QEMUFLAGS+=-redir tcp:8023::8023 -redir tcp:8080::8080 - endif - endif - ifeq ($(vga),no) - QEMUFLAGS+=-nographic -vga none - endif - #,int,pcall - #-device intel-iommu - - UNAME := $(shell uname) - ifeq ($(UNAME),Darwin) - ECHO=/bin/echo - FUMOUNT=sudo umount - export LD=$(ARCH)-elf-ld - export LDFLAGS=--gc-sections - export STRIP=$(ARCH)-elf-strip - VB_AUDIO=coreaudio - VBM="/Applications/VirtualBox.app/Contents/MacOS/VBoxManage" - else - ECHO=echo - FUMOUNT=fusermount -u - export LD=ld - export LDFLAGS=--gc-sections - export STRIP=strip - ifneq ($(kvm),no) - QEMUFLAGS+=-enable-kvm -cpu host - endif - VB_AUDIO="pulse" - VBM=VBoxManage - endif - -%.list: % - objdump -C -M intel -D $< > $@ - -build/harddrive.bin: $(KBUILD)/kernel bootloader/$(ARCH)/** build/filesystem.bin - nasm -f bin -o $@ -D ARCH_$(ARCH) -ibootloader/$(ARCH)/ bootloader/$(ARCH)/harddrive.asm - -build/livedisk.bin: $(KBUILD)/kernel_live bootloader/$(ARCH)/** - nasm -f bin -o $@ -D ARCH_$(ARCH) -ibootloader/$(ARCH)/ bootloader/$(ARCH)/livedisk.asm - -build/%.bin.gz: build/%.bin - gzip -k -f $< - -build/livedisk.iso: build/livedisk.bin.gz - rm -rf build/iso/ - mkdir -p build/iso/ - cp -RL isolinux build/iso/ - cp $< build/iso/livedisk.gz - genisoimage -o $@ -b isolinux/isolinux.bin -c isolinux/boot.cat \ - -no-emul-boot -boot-load-size 4 -boot-info-table \ - build/iso/ - isohybrid $@ - -qemu: build/harddrive.bin - $(QEMU) $(QEMUFLAGS) -drive file=$<,format=raw - -qemu_extra: build/harddrive.bin - if [ ! -e build/extra.bin ]; then dd if=/dev/zero of=build/extra.bin bs=1048576 count=1024; fi - $(QEMU) $(QEMUFLAGS) -drive file=$<,format=raw -drive file=build/extra.bin,format=raw - -qemu_no_build: - $(QEMU) $(QEMUFLAGS) -drive file=build/harddrive.bin,format=raw - -qemu_live: build/livedisk.bin - $(QEMU) $(QEMUFLAGS) -device usb-ehci,id=flash_bus -drive id=flash_drive,file=$<,format=raw,if=none -device usb-storage,drive=flash_drive,bus=flash_bus.0 - -qemu_live_no_build: - $(QEMU) $(QEMUFLAGS) -device usb-ehci,id=flash_bus -drive id=flash_drive,file=build/livedisk.bin,format=raw,if=none -device usb-storage,drive=flash_drive,bus=flash_bus.0 - -qemu_iso: build/livedisk.iso - $(QEMU) $(QEMUFLAGS) -boot d -cdrom $< - -qemu_iso_no_build: - $(QEMU) $(QEMUFLAGS) -boot d -cdrom build/livedisk.iso - -endif - -bochs: build/harddrive.bin - bochs -f bochs.$(ARCH) - -virtualbox: build/harddrive.bin - echo "Delete VM" - -$(VBM) unregistervm Redox --delete; \ - if [ $$? -ne 0 ]; \ - then \ - if [ -d "$$HOME/VirtualBox VMs/Redox" ]; \ - then \ - echo "Redox directory exists, deleting..."; \ - $(RM) -rf "$$HOME/VirtualBox VMs/Redox"; \ - fi \ - fi - echo "Delete Disk" - -$(RM) harddrive.vdi - echo "Create VM" - $(VBM) createvm --name Redox --register - echo "Set Configuration" - $(VBM) modifyvm Redox --memory 1024 - $(VBM) modifyvm Redox --vram 16 - if [ "$(net)" != "no" ]; \ - then \ - $(VBM) modifyvm Redox --nic1 nat; \ - $(VBM) modifyvm Redox --nictype1 82540EM; \ - $(VBM) modifyvm Redox --cableconnected1 on; \ - $(VBM) modifyvm Redox --nictrace1 on; \ - $(VBM) modifyvm Redox --nictracefile1 build/network.pcap; \ - fi - $(VBM) modifyvm Redox --uart1 0x3F8 4 - $(VBM) modifyvm Redox --uartmode1 file build/serial.log - $(VBM) modifyvm Redox --usb off # on - $(VBM) modifyvm Redox --keyboard ps2 - $(VBM) modifyvm Redox --mouse ps2 - $(VBM) modifyvm Redox --audio $(VB_AUDIO) - $(VBM) modifyvm Redox --audiocontroller ac97 - $(VBM) modifyvm Redox --nestedpaging off - echo "Create Disk" - $(VBM) convertfromraw $< build/harddrive.vdi - echo "Attach Disk" - $(VBM) storagectl Redox --name ATA --add sata --controller IntelAHCI --bootable on --portcount 1 - $(VBM) storageattach Redox --storagectl ATA --port 0 --device 0 --type hdd --medium build/harddrive.vdi - echo "Run VM" - $(VBM) startvm Redox +# Emulation recipes +include mk/qemu.mk +include mk/bochs.mk +include mk/virtualbox.mk # Kernel recipes -$(KBUILD)/libcollections.rlib: rust/src/libcollections/Cargo.toml rust/src/libcollections/** - mkdir -p $(KBUILD) - $(KCARGO) rustc --verbose --manifest-path $< $(KCARGOFLAGS) -o $@ - cp rust/src/target/$(KTARGET)/release/deps/*.rlib $(KBUILD) - -$(KBUILD)/libkernel.a: kernel/Cargo.toml kernel/arch/** kernel/src/** $(KBUILD)/libcollections.rlib $(BUILD)/initfs.rs - $(KCARGO) rustc --manifest-path $< --lib $(KCARGOFLAGS) -C lto --emit obj=$@ - -$(KBUILD)/libkernel_live.a: kernel/Cargo.toml kernel/arch/** kernel/src/** $(KBUILD)/libcollections.rlib $(BUILD)/initfs.rs build/filesystem.bin - $(KCARGO) rustc --manifest-path $< --lib --features live $(KCARGOFLAGS) -C lto --emit obj=$@ - -$(KBUILD)/kernel: $(KBUILD)/libkernel.a - $(LD) $(LDFLAGS) -z max-page-size=0x1000 -T kernel/arch/$(ARCH)/src/linker.ld -o $@ $< - -$(KBUILD)/kernel_live: $(KBUILD)/libkernel_live.a - $(LD) $(LDFLAGS) -z max-page-size=0x1000 -T kernel/arch/$(ARCH)/src/linker.ld -o $@ $< +include mk/kernel.mk # Userspace recipes -$(BUILD)/libstd.rlib: rust/src/libstd/Cargo.toml rust/src/libstd/** - mkdir -p $(BUILD) - $(CARGO) rustc --verbose --manifest-path $< --features "panic-unwind" $(CARGOFLAGS) -L native=libc-artifacts/usr/lib -o $@ - cp rust/src/target/$(TARGET)/release/deps/*.rlib $(BUILD) +include mk/userspace/mod.mk -$(BUILD)/libtest.rlib: rust/src/libtest/Cargo.toml rust/src/libtest/** $(BUILD)/libstd.rlib - mkdir -p $(BUILD) - $(CARGO) rustc --verbose --manifest-path $< $(CARGOFLAGS) -L native=libc-artifacts/usr/lib -o $@ - cp rust/src/target/$(TARGET)/release/deps/*.rlib $(BUILD) +# Documentation +include mk/doc.mk -initfs/bin/%: drivers/%/Cargo.toml drivers/%/src/** $(BUILD)/libstd.rlib - mkdir -p initfs/bin - $(CARGO) rustc --manifest-path $< $(CARGOFLAGS) -o $@ - $(STRIP) $@ +# Filesystem recipes +include mk/initfs.mk +include mk/filesystem.mk -initfs/bin/%: programs/%/Cargo.toml programs/%/src/** $(BUILD)/libstd.rlib - mkdir -p initfs/bin - $(CARGO) rustc --manifest-path $< $(CARGOFLAGS) -o $@ - $(STRIP) $@ - -initfs/bin/%: schemes/%/Cargo.toml schemes/%/src/** $(BUILD)/libstd.rlib - mkdir -p initfs/bin - $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - $(STRIP) $@ - -$(BUILD)/initfs.rs: \ - initfs/bin/init \ - initfs/bin/ahcid \ - initfs/bin/bgad \ - initfs/bin/pcid \ - initfs/bin/ps2d \ - initfs/bin/redoxfs \ - initfs/bin/vesad \ - initfs/etc/** - echo 'use collections::BTreeMap;' > $@ - echo 'pub fn gen() -> BTreeMap<&'"'"'static [u8], (&'"'"'static [u8], bool)> {' >> $@ - echo ' let mut files: BTreeMap<&'"'"'static [u8], (&'"'"'static [u8], bool)> = BTreeMap::new();' >> $@ - for folder in `find initfs -type d | sort`; do \ - name=$$(echo $$folder | sed 's/initfs//' | cut -d '/' -f2-) ; \ - $(ECHO) -n ' files.insert(b"'$$name'", (b"' >> $@ ; \ - ls -1 $$folder | sort | awk 'NR > 1 {printf("\\n")} {printf("%s", $$0)}' >> $@ ; \ - echo '", true));' >> $@ ; \ - done - find initfs -type f -o -type l | cut -d '/' -f2- | sort | awk '{printf(" files.insert(b\"%s\", (include_bytes!(\"../../initfs/%s\"), false));\n", $$0, $$0)}' >> $@ - echo ' files' >> $@ - echo '}' >> $@ - -filesystem/sbin/%: drivers/%/Cargo.toml drivers/%/src/** $(BUILD)/libstd.rlib - mkdir -p filesystem/sbin - $(CARGO) rustc --manifest-path $< $(CARGOFLAGS) -o $@ - $(STRIP) $@ - -filesystem/bin/%: programs/%/Cargo.toml programs/%/src/** $(BUILD)/libstd.rlib - mkdir -p filesystem/bin - $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - $(STRIP) $@ - -# Example of compiling tests - still TODO -filesystem/test/%: programs/%/Cargo.toml programs/%/src/** $(BUILD)/libstd.rlib $(BUILD)/libtest.rlib - mkdir -p filesystem/test - $(CARGO) test --no-run --manifest-path $< $(CARGOFLAGS) - cp programs/$*/target/$(TARGET)/release/deps/$*-* $@ - -filesystem/bin/sh: filesystem/bin/ion - cp $< $@ - -filesystem/bin/%: programs/binutils/Cargo.toml programs/binutils/src/bin/%.rs $(BUILD)/libstd.rlib - mkdir -p filesystem/bin - $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - $(STRIP) $@ - -filesystem/bin/%: programs/coreutils/Cargo.toml programs/coreutils/src/bin/%.rs $(BUILD)/libstd.rlib - mkdir -p filesystem/bin - $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - $(STRIP) $@ - -filesystem/bin/%: programs/extrautils/Cargo.toml programs/extrautils/src/bin/%.rs $(BUILD)/libstd.rlib - mkdir -p filesystem/bin - $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - $(STRIP) $@ - -filesystem/bin/%: programs/games/Cargo.toml programs/games/src/%/**.rs $(BUILD)/libstd.rlib - mkdir -p filesystem/bin - $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - $(STRIP) $@ - -filesystem/bin/%: programs/netutils/Cargo.toml programs/netutils/src/%/**.rs $(BUILD)/libstd.rlib - mkdir -p filesystem/bin - $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - $(STRIP) $@ - -filesystem/ui/bin/%: programs/orbutils/Cargo.toml programs/orbutils/src/%/**.rs $(BUILD)/libstd.rlib - mkdir -p filesystem/ui/bin - $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - $(STRIP) $@ - -filesystem/bin/%: programs/pkgutils/Cargo.toml programs/pkgutils/src/%/**.rs $(BUILD)/libstd.rlib - mkdir -p filesystem/bin - $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - $(STRIP) $@ - -filesystem/bin/%: programs/userutils/Cargo.toml programs/userutils/src/bin/%.rs $(BUILD)/libstd.rlib - mkdir -p filesystem/bin - $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - $(STRIP) $@ - -filesystem/sbin/%: schemes/%/Cargo.toml schemes/%/src/** $(BUILD)/libstd.rlib - mkdir -p filesystem/sbin - $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ - $(STRIP) $@ - -filesystem/sbin/redoxfs-mkfs: schemes/redoxfs/Cargo.toml schemes/redoxfs/src/** $(BUILD)/libstd.rlib - mkdir -p filesystem/bin - $(CARGO) rustc --manifest-path $< --bin redoxfs-mkfs $(CARGOFLAGS) -o $@ - $(STRIP) $@ - -drivers: \ - filesystem/sbin/pcid \ - filesystem/sbin/e1000d \ - filesystem/sbin/rtl8168d - -binutils: \ - filesystem/bin/hex \ - filesystem/bin/hexdump \ - filesystem/bin/strings - -coreutils: \ - filesystem/bin/basename \ - filesystem/bin/cat \ - filesystem/bin/chmod \ - filesystem/bin/clear \ - filesystem/bin/cp \ - filesystem/bin/cut \ - filesystem/bin/date \ - filesystem/bin/dd \ - filesystem/bin/df \ - filesystem/bin/du \ - filesystem/bin/echo \ - filesystem/bin/env \ - filesystem/bin/false \ - filesystem/bin/free \ - filesystem/bin/head \ - filesystem/bin/kill \ - filesystem/bin/ls \ - filesystem/bin/mkdir \ - filesystem/bin/mv \ - filesystem/bin/printenv \ - filesystem/bin/ps \ - filesystem/bin/pwd \ - filesystem/bin/realpath \ - filesystem/bin/reset \ - filesystem/bin/rmdir \ - filesystem/bin/rm \ - filesystem/bin/seq \ - filesystem/bin/sleep \ - filesystem/bin/sort \ - filesystem/bin/tail \ - filesystem/bin/tee \ - filesystem/bin/time \ - filesystem/bin/touch \ - filesystem/bin/true \ - filesystem/bin/wc \ - filesystem/bin/yes - #filesystem/bin/shutdown filesystem/bin/test - -extrautils: \ - filesystem/bin/calc \ - filesystem/bin/cksum \ - filesystem/bin/cur \ - filesystem/bin/grep \ - filesystem/bin/less \ - filesystem/bin/man \ - filesystem/bin/mdless \ - filesystem/bin/mtxt \ - filesystem/bin/rem \ - #filesystem/bin/dmesg filesystem/bin/info filesystem/bin/watch - -games: \ - filesystem/bin/ice \ - filesystem/bin/minesweeper \ - filesystem/bin/reblox \ - filesystem/bin/rusthello \ - filesystem/bin/snake - -netutils: \ - filesystem/bin/dhcpd \ - filesystem/bin/dns \ - filesystem/bin/httpd \ - filesystem/bin/irc \ - filesystem/bin/nc \ - filesystem/bin/ntp \ - filesystem/bin/telnetd \ - filesystem/bin/wget - -orbutils: \ - filesystem/ui/bin/browser \ - filesystem/ui/bin/calculator \ - filesystem/ui/bin/character_map \ - filesystem/ui/bin/editor \ - filesystem/ui/bin/file_manager \ - filesystem/ui/bin/launcher \ - filesystem/ui/bin/orblogin \ - filesystem/ui/bin/terminal \ - filesystem/ui/bin/viewer - -pkgutils: \ - filesystem/bin/pkg - -userutils: \ - filesystem/bin/getty \ - filesystem/bin/id \ - filesystem/bin/login \ - filesystem/bin/passwd \ - filesystem/bin/su \ - filesystem/bin/sudo - -schemes: \ - filesystem/sbin/ethernetd \ - filesystem/sbin/ipd \ - filesystem/sbin/orbital \ - filesystem/sbin/ptyd \ - filesystem/sbin/randd \ - filesystem/sbin/redoxfs \ - filesystem/sbin/redoxfs-mkfs \ - filesystem/sbin/tcpd \ - filesystem/sbin/udpd - -build/filesystem.bin: \ - drivers \ - coreutils \ - extrautils \ - games \ - netutils \ - orbutils \ - pkgutils \ - userutils \ - schemes \ - filesystem/bin/acid \ - filesystem/bin/contain \ - filesystem/bin/ion \ - filesystem/bin/sh \ - filesystem/bin/smith \ - filesystem/bin/tar - -$(FUMOUNT) build/filesystem/ || true - rm -rf $@ build/filesystem/ - dd if=/dev/zero of=$@ bs=1048576 count=64 - cargo run --manifest-path schemes/redoxfs/Cargo.toml --release --bin redoxfs-mkfs $@ - mkdir -p build/filesystem/ - cargo build --manifest-path schemes/redoxfs/Cargo.toml --release --bin redoxfs - cargo run --manifest-path schemes/redoxfs/Cargo.toml --release --bin redoxfs -- $@ build/filesystem/ - sleep 2 - pgrep redoxfs - cp -RL filesystem/* build/filesystem/ - chown -R 0:0 build/filesystem - chown -R 1000:1000 build/filesystem/home/user - chmod -R uog+rX build/filesystem - chmod -R u+w build/filesystem - chmod -R og-w build/filesystem - chmod -R 755 build/filesystem/bin - chmod -R u+rwX build/filesystem/root - chmod -R og-rwx build/filesystem/root - chmod -R u+rwX build/filesystem/home/user - chmod -R og-rwx build/filesystem/home/user - chmod +s build/filesystem/bin/passwd - chmod +s build/filesystem/bin/su - chmod +s build/filesystem/bin/sudo - mkdir build/filesystem/tmp - chmod 1777 build/filesystem/tmp - sync - -$(FUMOUNT) build/filesystem/ || true - rm -rf build/filesystem/ - -mount: FORCE - mkdir -p build/filesystem/ - cargo build --manifest-path schemes/redoxfs/Cargo.toml --release --bin redoxfs - cargo run --manifest-path schemes/redoxfs/Cargo.toml --release --bin redoxfs -- build/harddrive.bin build/filesystem/ - sleep 2 - pgrep redoxfs - -unmount: FORCE - sync - -$(FUMOUNT) build/filesystem/ || true - rm -rf build/filesystem/ +# Disk images +include mk/disk.mk +# Misc wireshark: FORCE wireshark build/network.pcap diff --git a/mk/bochs.mk b/mk/bochs.mk new file mode 100644 index 0000000..964dba5 --- /dev/null +++ b/mk/bochs.mk @@ -0,0 +1,2 @@ +bochs: build/harddrive.bin + bochs -f bochs.$(ARCH) diff --git a/mk/config.mk b/mk/config.mk new file mode 100644 index 0000000..0b1b9c9 --- /dev/null +++ b/mk/config.mk @@ -0,0 +1,51 @@ +# Configuration +ARCH?=x86_64 + +# Automatic variables +ROOT=$(PWD) +export RUST_TARGET_PATH=$(ROOT)/targets +export CC=$(ROOT)/libc-artifacts/gcc.sh +export CFLAGS=-fno-stack-protector -U_FORTIFY_SOURCE + +# Kernel variables +KTARGET=$(ARCH)-unknown-none +KBUILD=build/kernel +KRUSTC=./krustc.sh +KRUSTDOC=./krustdoc.sh +KCARGO=RUSTC="$(KRUSTC)" RUSTDOC="$(KRUSTDOC)" cargo +KCARGOFLAGS=--target $(KTARGET) --release -- -C soft-float + +# Userspace variables +export TARGET=$(ARCH)-unknown-redox +BUILD=build/userspace +RUSTC=./rustc.sh +RUSTDOC=./rustdoc.sh +CARGO=RUSTC="$(RUSTC)" RUSTDOC="$(RUSTDOC)" cargo +CARGOFLAGS=--target $(TARGET) --release -- -C codegen-units=`nproc` + +# Per host variables +UNAME := $(shell uname) +ifeq ($(UNAME),Darwin) + ECHO=/bin/echo + FUMOUNT=sudo umount + export LD=$(ARCH)-elf-ld + export LDFLAGS=--gc-sections + export STRIP=$(ARCH)-elf-strip + VB_AUDIO=coreaudio + VBM="/Applications/VirtualBox.app/Contents/MacOS/VBoxManage" +else + ECHO=echo + FUMOUNT=fusermount -u + export LD=ld + export LDFLAGS=--gc-sections + export STRIP=strip + VB_AUDIO="pulse" + VBM=VBoxManage +endif + +# An empty target +FORCE: + +# A method of creating a listing for any binary +%.list: % + objdump -C -M intel -D $< > $@ diff --git a/mk/disk.mk b/mk/disk.mk new file mode 100644 index 0000000..bf4996e --- /dev/null +++ b/mk/disk.mk @@ -0,0 +1,18 @@ +build/harddrive.bin: $(KBUILD)/kernel bootloader/$(ARCH)/** build/filesystem.bin + nasm -f bin -o $@ -D ARCH_$(ARCH) -ibootloader/$(ARCH)/ bootloader/$(ARCH)/harddrive.asm + +build/livedisk.bin: $(KBUILD)/kernel_live bootloader/$(ARCH)/** + nasm -f bin -o $@ -D ARCH_$(ARCH) -ibootloader/$(ARCH)/ bootloader/$(ARCH)/livedisk.asm + +build/%.bin.gz: build/%.bin + gzip -k -f $< + +build/livedisk.iso: build/livedisk.bin.gz + rm -rf build/iso/ + mkdir -p build/iso/ + cp -RL isolinux build/iso/ + cp $< build/iso/livedisk.gz + genisoimage -o $@ -b isolinux/isolinux.bin -c isolinux/boot.cat \ + -no-emul-boot -boot-load-size 4 -boot-info-table \ + build/iso/ + isohybrid $@ diff --git a/mk/doc.mk b/mk/doc.mk new file mode 100644 index 0000000..2cb7bfd --- /dev/null +++ b/mk/doc.mk @@ -0,0 +1,13 @@ +doc: $(KBUILD)/libkernel.a $(BUILD)/libstd.rlib FORCE + $(KCARGO) doc --target $(KTARGET) --manifest-path kernel/Cargo.toml + $(CARGO) doc --target $(TARGET) --manifest-path rust/src/libstd/Cargo.toml + +ref: FORCE + rm -rf filesystem/ref/ + mkdir -p filesystem/ref/ + #cargo run --manifest-path crates/docgen/Cargo.toml -- programs/binutils/src/bin/ filesystem/ref/ + cargo run --manifest-path crates/docgen/Cargo.toml -- programs/coreutils/src/bin/ filesystem/ref/ + cargo run --manifest-path crates/docgen/Cargo.toml -- programs/extrautils/src/bin/ filesystem/ref/ + cargo run --manifest-path crates/docgen/Cargo.toml -- programs/netutils/src/ filesystem/ref/ + cargo run --manifest-path crates/docgen/Cargo.toml -- programs/pkgutils/src/ filesystem/ref/ + cargo run --manifest-path crates/docgen/Cargo.toml -- programs/userutils/src/ filesystem/ref/ diff --git a/mk/filesystem.mk b/mk/filesystem.mk new file mode 100644 index 0000000..956c31f --- /dev/null +++ b/mk/filesystem.mk @@ -0,0 +1,41 @@ +build/filesystem.bin: userspace + -$(FUMOUNT) build/filesystem/ || true + rm -rf $@ build/filesystem/ + dd if=/dev/zero of=$@ bs=1048576 count=64 + cargo run --manifest-path schemes/redoxfs/Cargo.toml --release --bin redoxfs-mkfs $@ + mkdir -p build/filesystem/ + cargo build --manifest-path schemes/redoxfs/Cargo.toml --release --bin redoxfs + cargo run --manifest-path schemes/redoxfs/Cargo.toml --release --bin redoxfs -- $@ build/filesystem/ + sleep 2 + pgrep redoxfs + cp -RL filesystem/* build/filesystem/ + chown -R 0:0 build/filesystem + chown -R 1000:1000 build/filesystem/home/user + chmod -R uog+rX build/filesystem + chmod -R u+w build/filesystem + chmod -R og-w build/filesystem + chmod -R 755 build/filesystem/bin + chmod -R u+rwX build/filesystem/root + chmod -R og-rwx build/filesystem/root + chmod -R u+rwX build/filesystem/home/user + chmod -R og-rwx build/filesystem/home/user + chmod +s build/filesystem/bin/passwd + chmod +s build/filesystem/bin/su + chmod +s build/filesystem/bin/sudo + mkdir build/filesystem/tmp + chmod 1777 build/filesystem/tmp + sync + -$(FUMOUNT) build/filesystem/ || true + rm -rf build/filesystem/ + +mount: FORCE + mkdir -p build/filesystem/ + cargo build --manifest-path schemes/redoxfs/Cargo.toml --release --bin redoxfs + cargo run --manifest-path schemes/redoxfs/Cargo.toml --release --bin redoxfs -- build/harddrive.bin build/filesystem/ + sleep 2 + pgrep redoxfs + +unmount: FORCE + sync + -$(FUMOUNT) build/filesystem/ || true + rm -rf build/filesystem/ diff --git a/mk/initfs.mk b/mk/initfs.mk new file mode 100644 index 0000000..57983bb --- /dev/null +++ b/mk/initfs.mk @@ -0,0 +1,28 @@ +initfs: \ + initfs/bin/init \ + initfs/bin/ahcid \ + initfs/bin/bgad \ + initfs/bin/pcid \ + initfs/bin/ps2d \ + initfs/bin/redoxfs \ + initfs/bin/vesad \ + initfs/etc/** + +$(BUILD)/initfs.rs: initfs + echo 'use collections::BTreeMap;' > $@ + echo 'pub fn gen() -> BTreeMap<&'"'"'static [u8], (&'"'"'static [u8], bool)> {' >> $@ + echo ' let mut files: BTreeMap<&'"'"'static [u8], (&'"'"'static [u8], bool)> = BTreeMap::new();' >> $@ + for folder in `find initfs -type d | sort`; do \ + name=$$(echo $$folder | sed 's/initfs//' | cut -d '/' -f2-) ; \ + $(ECHO) -n ' files.insert(b"'$$name'", (b"' >> $@ ; \ + ls -1 $$folder | sort | awk 'NR > 1 {printf("\\n")} {printf("%s", $$0)}' >> $@ ; \ + echo '", true));' >> $@ ; \ + done + find initfs -type f -o -type l | cut -d '/' -f2- | sort | awk '{printf(" files.insert(b\"%s\", (include_bytes!(\"../../initfs/%s\"), false));\n", $$0, $$0)}' >> $@ + echo ' files' >> $@ + echo '}' >> $@ + +initfs/bin/%: programs/%/Cargo.toml programs/%/src/** $(BUILD)/libstd.rlib + mkdir -p initfs/bin + $(CARGO) rustc --manifest-path $< $(CARGOFLAGS) -o $@ + $(STRIP) $@ diff --git a/mk/kernel.mk b/mk/kernel.mk new file mode 100644 index 0000000..814fed7 --- /dev/null +++ b/mk/kernel.mk @@ -0,0 +1,16 @@ +$(KBUILD)/libcollections.rlib: rust/src/libcollections/Cargo.toml rust/src/libcollections/** + mkdir -p $(KBUILD) + $(KCARGO) rustc --verbose --manifest-path $< $(KCARGOFLAGS) -o $@ + cp rust/src/target/$(KTARGET)/release/deps/*.rlib $(KBUILD) + +$(KBUILD)/libkernel.a: kernel/Cargo.toml kernel/arch/** kernel/src/** $(KBUILD)/libcollections.rlib $(BUILD)/initfs.rs + $(KCARGO) rustc --manifest-path $< --lib $(KCARGOFLAGS) -C lto --emit obj=$@ + +$(KBUILD)/libkernel_live.a: kernel/Cargo.toml kernel/arch/** kernel/src/** $(KBUILD)/libcollections.rlib $(BUILD)/initfs.rs build/filesystem.bin + $(KCARGO) rustc --manifest-path $< --lib --features live $(KCARGOFLAGS) -C lto --emit obj=$@ + +$(KBUILD)/kernel: $(KBUILD)/libkernel.a + $(LD) $(LDFLAGS) -z max-page-size=0x1000 -T kernel/arch/$(ARCH)/src/linker.ld -o $@ $< + +$(KBUILD)/kernel_live: $(KBUILD)/libkernel_live.a + $(LD) $(LDFLAGS) -z max-page-size=0x1000 -T kernel/arch/$(ARCH)/src/linker.ld -o $@ $< diff --git a/mk/qemu.mk b/mk/qemu.mk new file mode 100644 index 0000000..ef50bf7 --- /dev/null +++ b/mk/qemu.mk @@ -0,0 +1,48 @@ +QEMU=SDL_VIDEO_X11_DGAMOUSE=0 qemu-system-$(ARCH) +QEMUFLAGS=-serial mon:stdio -d cpu_reset -d guest_errors +QEMUFLAGS+=-smp 4 -m 1024 +ifeq ($(iommu),yes) + QEMUFLAGS+=-machine q35,iommu=on +else + QEMUFLAGS+=-machine q35 +endif +ifeq ($(net),no) + QEMUFLAGS+=-net none +else + QEMUFLAGS+=-net nic,model=e1000 -net user -net dump,file=build/network.pcap + ifeq ($(net),redir) + QEMUFLAGS+=-redir tcp:8023::8023 -redir tcp:8080::8080 + endif +endif +ifeq ($(vga),no) + QEMUFLAGS+=-nographic -vga none +endif +ifeq ($(UNAME),Linux) + ifneq ($(kvm),no) + QEMUFLAGS+=-enable-kvm -cpu host + endif +endif +#,int,pcall +#-device intel-iommu + +qemu: build/harddrive.bin + $(QEMU) $(QEMUFLAGS) -drive file=$<,format=raw + +qemu_extra: build/harddrive.bin + if [ ! -e build/extra.bin ]; then dd if=/dev/zero of=build/extra.bin bs=1048576 count=1024; fi + $(QEMU) $(QEMUFLAGS) -drive file=$<,format=raw -drive file=build/extra.bin,format=raw + +qemu_no_build: + $(QEMU) $(QEMUFLAGS) -drive file=build/harddrive.bin,format=raw + +qemu_live: build/livedisk.bin + $(QEMU) $(QEMUFLAGS) -device usb-ehci,id=flash_bus -drive id=flash_drive,file=$<,format=raw,if=none -device usb-storage,drive=flash_drive,bus=flash_bus.0 + +qemu_live_no_build: + $(QEMU) $(QEMUFLAGS) -device usb-ehci,id=flash_bus -drive id=flash_drive,file=build/livedisk.bin,format=raw,if=none -device usb-storage,drive=flash_drive,bus=flash_bus.0 + +qemu_iso: build/livedisk.iso + $(QEMU) $(QEMUFLAGS) -boot d -cdrom $< + +qemu_iso_no_build: + $(QEMU) $(QEMUFLAGS) -boot d -cdrom build/livedisk.iso diff --git a/mk/userspace/binutils.mk b/mk/userspace/binutils.mk new file mode 100644 index 0000000..0a25ab4 --- /dev/null +++ b/mk/userspace/binutils.mk @@ -0,0 +1,9 @@ +binutils: \ + filesystem/bin/hex \ + filesystem/bin/hexdump \ + filesystem/bin/strings + +filesystem/bin/%: programs/binutils/Cargo.toml programs/binutils/src/bin/%.rs $(BUILD)/libstd.rlib + mkdir -p filesystem/bin + $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ + $(STRIP) $@ diff --git a/mk/userspace/coreutils.mk b/mk/userspace/coreutils.mk new file mode 100644 index 0000000..a75f307 --- /dev/null +++ b/mk/userspace/coreutils.mk @@ -0,0 +1,43 @@ +coreutils: \ + filesystem/bin/basename \ + filesystem/bin/cat \ + filesystem/bin/chmod \ + filesystem/bin/clear \ + filesystem/bin/cp \ + filesystem/bin/cut \ + filesystem/bin/date \ + filesystem/bin/dd \ + filesystem/bin/df \ + filesystem/bin/du \ + filesystem/bin/echo \ + filesystem/bin/env \ + filesystem/bin/false \ + filesystem/bin/free \ + filesystem/bin/head \ + filesystem/bin/kill \ + filesystem/bin/ls \ + filesystem/bin/mkdir \ + filesystem/bin/mv \ + filesystem/bin/printenv \ + filesystem/bin/ps \ + filesystem/bin/pwd \ + filesystem/bin/realpath \ + filesystem/bin/reset \ + filesystem/bin/rmdir \ + filesystem/bin/rm \ + filesystem/bin/seq \ + filesystem/bin/sleep \ + filesystem/bin/sort \ + filesystem/bin/tail \ + filesystem/bin/tee \ + filesystem/bin/time \ + filesystem/bin/touch \ + filesystem/bin/true \ + filesystem/bin/wc \ + filesystem/bin/yes + #filesystem/bin/shutdown filesystem/bin/test + +filesystem/bin/%: programs/coreutils/Cargo.toml programs/coreutils/src/bin/%.rs $(BUILD)/libstd.rlib + mkdir -p filesystem/bin + $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ + $(STRIP) $@ diff --git a/mk/userspace/drivers.mk b/mk/userspace/drivers.mk new file mode 100644 index 0000000..122285f --- /dev/null +++ b/mk/userspace/drivers.mk @@ -0,0 +1,14 @@ +drivers: \ + filesystem/sbin/pcid \ + filesystem/sbin/e1000d \ + filesystem/sbin/rtl8168d + +initfs/bin/%: drivers/%/Cargo.toml drivers/%/src/** $(BUILD)/libstd.rlib + mkdir -p initfs/bin + $(CARGO) rustc --manifest-path $< $(CARGOFLAGS) -o $@ + $(STRIP) $@ + +filesystem/sbin/%: drivers/%/Cargo.toml drivers/%/src/** $(BUILD)/libstd.rlib + mkdir -p filesystem/sbin + $(CARGO) rustc --manifest-path $< $(CARGOFLAGS) -o $@ + $(STRIP) $@ diff --git a/mk/userspace/extrautils.mk b/mk/userspace/extrautils.mk new file mode 100644 index 0000000..c161d87 --- /dev/null +++ b/mk/userspace/extrautils.mk @@ -0,0 +1,16 @@ +extrautils: \ + filesystem/bin/calc \ + filesystem/bin/cksum \ + filesystem/bin/cur \ + filesystem/bin/grep \ + filesystem/bin/less \ + filesystem/bin/man \ + filesystem/bin/mdless \ + filesystem/bin/mtxt \ + filesystem/bin/rem \ + #filesystem/bin/dmesg filesystem/bin/info filesystem/bin/watch + +filesystem/bin/%: programs/extrautils/Cargo.toml programs/extrautils/src/bin/%.rs $(BUILD)/libstd.rlib + mkdir -p filesystem/bin + $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ + $(STRIP) $@ diff --git a/mk/userspace/games.mk b/mk/userspace/games.mk new file mode 100644 index 0000000..ae0dda7 --- /dev/null +++ b/mk/userspace/games.mk @@ -0,0 +1,11 @@ +games: \ + filesystem/bin/ice \ + filesystem/bin/minesweeper \ + filesystem/bin/reblox \ + filesystem/bin/rusthello \ + filesystem/bin/snake + +filesystem/bin/%: programs/games/Cargo.toml programs/games/src/%/**.rs $(BUILD)/libstd.rlib + mkdir -p filesystem/bin + $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ + $(STRIP) $@ diff --git a/mk/userspace/ion.mk b/mk/userspace/ion.mk new file mode 100644 index 0000000..48161a4 --- /dev/null +++ b/mk/userspace/ion.mk @@ -0,0 +1,11 @@ +ion: \ + filesystem/bin/ion \ + filesystem/bin/sh + +filesystem/test/ion: programs/ion/Cargo.toml programs/ion/src/** $(BUILD)/libstd.rlib $(BUILD)/libtest.rlib + mkdir -p filesystem/test + $(CARGO) test --no-run --manifest-path $< $(CARGOFLAGS) + cp programs/ion/target/$(TARGET)/release/deps/ion-* $@ + +filesystem/bin/sh: filesystem/bin/ion + cp $< $@ diff --git a/mk/userspace/mod.mk b/mk/userspace/mod.mk new file mode 100644 index 0000000..b399ca2 --- /dev/null +++ b/mk/userspace/mod.mk @@ -0,0 +1,42 @@ +userspace: \ + drivers \ + coreutils \ + extrautils \ + games \ + ion \ + netutils \ + orbutils \ + pkgutils \ + userutils \ + schemes \ + filesystem/bin/acid \ + filesystem/bin/contain \ + filesystem/bin/smith \ + filesystem/bin/tar + +include mk/userspace/binutils.mk +include mk/userspace/coreutils.mk +include mk/userspace/drivers.mk +include mk/userspace/extrautils.mk +include mk/userspace/games.mk +include mk/userspace/ion.mk +include mk/userspace/netutils.mk +include mk/userspace/orbutils.mk +include mk/userspace/pkgutils.mk +include mk/userspace/schemes.mk +include mk/userspace/userutils.mk + +$(BUILD)/libstd.rlib: rust/src/libstd/Cargo.toml rust/src/libstd/** + mkdir -p $(BUILD) + $(CARGO) rustc --verbose --manifest-path $< --features "panic-unwind" $(CARGOFLAGS) -L native=libc-artifacts/usr/lib -o $@ + cp rust/src/target/$(TARGET)/release/deps/*.rlib $(BUILD) + +$(BUILD)/libtest.rlib: rust/src/libtest/Cargo.toml rust/src/libtest/** $(BUILD)/libstd.rlib + mkdir -p $(BUILD) + $(CARGO) rustc --verbose --manifest-path $< $(CARGOFLAGS) -L native=libc-artifacts/usr/lib -o $@ + cp rust/src/target/$(TARGET)/release/deps/*.rlib $(BUILD) + +filesystem/bin/%: programs/%/Cargo.toml programs/%/src/** $(BUILD)/libstd.rlib + mkdir -p filesystem/bin + $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ + $(STRIP) $@ diff --git a/mk/userspace/netutils.mk b/mk/userspace/netutils.mk new file mode 100644 index 0000000..eda3602 --- /dev/null +++ b/mk/userspace/netutils.mk @@ -0,0 +1,14 @@ +netutils: \ + filesystem/bin/dhcpd \ + filesystem/bin/dns \ + filesystem/bin/httpd \ + filesystem/bin/irc \ + filesystem/bin/nc \ + filesystem/bin/ntp \ + filesystem/bin/telnetd \ + filesystem/bin/wget + +filesystem/bin/%: programs/netutils/Cargo.toml programs/netutils/src/%/**.rs $(BUILD)/libstd.rlib + mkdir -p filesystem/bin + $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ + $(STRIP) $@ diff --git a/mk/userspace/orbutils.mk b/mk/userspace/orbutils.mk new file mode 100644 index 0000000..df60cf4 --- /dev/null +++ b/mk/userspace/orbutils.mk @@ -0,0 +1,15 @@ +orbutils: \ + filesystem/ui/bin/browser \ + filesystem/ui/bin/calculator \ + filesystem/ui/bin/character_map \ + filesystem/ui/bin/editor \ + filesystem/ui/bin/file_manager \ + filesystem/ui/bin/launcher \ + filesystem/ui/bin/orblogin \ + filesystem/ui/bin/terminal \ + filesystem/ui/bin/viewer + +filesystem/ui/bin/%: programs/orbutils/Cargo.toml programs/orbutils/src/%/**.rs $(BUILD)/libstd.rlib + mkdir -p filesystem/ui/bin + $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ + $(STRIP) $@ diff --git a/mk/userspace/pkgutils.mk b/mk/userspace/pkgutils.mk new file mode 100644 index 0000000..c2fad81 --- /dev/null +++ b/mk/userspace/pkgutils.mk @@ -0,0 +1,7 @@ +pkgutils: \ + filesystem/bin/pkg + +filesystem/bin/%: programs/pkgutils/Cargo.toml programs/pkgutils/src/%/**.rs $(BUILD)/libstd.rlib + mkdir -p filesystem/bin + $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ + $(STRIP) $@ diff --git a/mk/userspace/schemes.mk b/mk/userspace/schemes.mk new file mode 100644 index 0000000..b28485f --- /dev/null +++ b/mk/userspace/schemes.mk @@ -0,0 +1,25 @@ +schemes: \ + filesystem/sbin/ethernetd \ + filesystem/sbin/ipd \ + filesystem/sbin/orbital \ + filesystem/sbin/ptyd \ + filesystem/sbin/randd \ + filesystem/sbin/redoxfs \ + filesystem/sbin/redoxfs-mkfs \ + filesystem/sbin/tcpd \ + filesystem/sbin/udpd + +initfs/bin/%: schemes/%/Cargo.toml schemes/%/src/** $(BUILD)/libstd.rlib + mkdir -p initfs/bin + $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ + $(STRIP) $@ + +filesystem/sbin/%: schemes/%/Cargo.toml schemes/%/src/** $(BUILD)/libstd.rlib + mkdir -p filesystem/sbin + $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ + $(STRIP) $@ + +filesystem/sbin/redoxfs-mkfs: schemes/redoxfs/Cargo.toml schemes/redoxfs/src/** $(BUILD)/libstd.rlib + mkdir -p filesystem/bin + $(CARGO) rustc --manifest-path $< --bin redoxfs-mkfs $(CARGOFLAGS) -o $@ + $(STRIP) $@ diff --git a/mk/userspace/userutils.mk b/mk/userspace/userutils.mk new file mode 100644 index 0000000..397ae4a --- /dev/null +++ b/mk/userspace/userutils.mk @@ -0,0 +1,12 @@ +userutils: \ + filesystem/bin/getty \ + filesystem/bin/id \ + filesystem/bin/login \ + filesystem/bin/passwd \ + filesystem/bin/su \ + filesystem/bin/sudo + +filesystem/bin/%: programs/userutils/Cargo.toml programs/userutils/src/bin/%.rs $(BUILD)/libstd.rlib + mkdir -p filesystem/bin + $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ + $(STRIP) $@ diff --git a/mk/virtualbox.mk b/mk/virtualbox.mk new file mode 100644 index 0000000..6a0aa5b --- /dev/null +++ b/mk/virtualbox.mk @@ -0,0 +1,41 @@ +virtualbox: build/harddrive.bin + echo "Delete VM" + -$(VBM) unregistervm Redox --delete; \ + if [ $$? -ne 0 ]; \ + then \ + if [ -d "$$HOME/VirtualBox VMs/Redox" ]; \ + then \ + echo "Redox directory exists, deleting..."; \ + $(RM) -rf "$$HOME/VirtualBox VMs/Redox"; \ + fi \ + fi + echo "Delete Disk" + -$(RM) harddrive.vdi + echo "Create VM" + $(VBM) createvm --name Redox --register + echo "Set Configuration" + $(VBM) modifyvm Redox --memory 1024 + $(VBM) modifyvm Redox --vram 16 + if [ "$(net)" != "no" ]; \ + then \ + $(VBM) modifyvm Redox --nic1 nat; \ + $(VBM) modifyvm Redox --nictype1 82540EM; \ + $(VBM) modifyvm Redox --cableconnected1 on; \ + $(VBM) modifyvm Redox --nictrace1 on; \ + $(VBM) modifyvm Redox --nictracefile1 build/network.pcap; \ + fi + $(VBM) modifyvm Redox --uart1 0x3F8 4 + $(VBM) modifyvm Redox --uartmode1 file build/serial.log + $(VBM) modifyvm Redox --usb off # on + $(VBM) modifyvm Redox --keyboard ps2 + $(VBM) modifyvm Redox --mouse ps2 + $(VBM) modifyvm Redox --audio $(VB_AUDIO) + $(VBM) modifyvm Redox --audiocontroller ac97 + $(VBM) modifyvm Redox --nestedpaging off + echo "Create Disk" + $(VBM) convertfromraw $< build/harddrive.vdi + echo "Attach Disk" + $(VBM) storagectl Redox --name ATA --add sata --controller IntelAHCI --bootable on --portcount 1 + $(VBM) storageattach Redox --storagectl ATA --port 0 --device 0 --type hdd --medium build/harddrive.vdi + echo "Run VM" + $(VBM) startvm Redox From cda17ce4c14a10fbb0db13ce9dd98631bb3ae98a Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 5 Jan 2017 15:02:54 -0700 Subject: [PATCH 055/522] Update init to handle directories --- filesystem/etc/init.d/00_base | 3 +++ filesystem/etc/init.d/10_net | 5 ++++ filesystem/etc/init.d/20_console | 2 ++ filesystem/etc/init.d/30_orbital | 1 + filesystem/etc/init.d/40_serial | 1 + filesystem/etc/init.rc | 12 ---------- initfs/etc/init.rc | 2 +- libc-artifacts | 2 +- programs/init/src/main.rs | 39 ++++++++++++++++++++++++++++---- 9 files changed, 49 insertions(+), 18 deletions(-) create mode 100644 filesystem/etc/init.d/00_base create mode 100644 filesystem/etc/init.d/10_net create mode 100644 filesystem/etc/init.d/20_console create mode 100644 filesystem/etc/init.d/30_orbital create mode 100644 filesystem/etc/init.d/40_serial delete mode 100644 filesystem/etc/init.rc diff --git a/filesystem/etc/init.d/00_base b/filesystem/etc/init.d/00_base new file mode 100644 index 0000000..d34f472 --- /dev/null +++ b/filesystem/etc/init.d/00_base @@ -0,0 +1,3 @@ +/sbin/randd +/sbin/ptyd +/sbin/pcid /etc/pcid.toml diff --git a/filesystem/etc/init.d/10_net b/filesystem/etc/init.d/10_net new file mode 100644 index 0000000..21de468 --- /dev/null +++ b/filesystem/etc/init.d/10_net @@ -0,0 +1,5 @@ +/sbin/ethernetd +/sbin/ipd +/sbin/tcpd +/sbin/udpd +dhcpd -b diff --git a/filesystem/etc/init.d/20_console b/filesystem/etc/init.d/20_console new file mode 100644 index 0000000..ca6aeb0 --- /dev/null +++ b/filesystem/etc/init.d/20_console @@ -0,0 +1,2 @@ +getty display:2 +getty display:3 diff --git a/filesystem/etc/init.d/30_orbital b/filesystem/etc/init.d/30_orbital new file mode 100644 index 0000000..b1e505b --- /dev/null +++ b/filesystem/etc/init.d/30_orbital @@ -0,0 +1 @@ +/sbin/orbital display:4/activate /ui/bin/orblogin /ui/bin/launcher diff --git a/filesystem/etc/init.d/40_serial b/filesystem/etc/init.d/40_serial new file mode 100644 index 0000000..730fa10 --- /dev/null +++ b/filesystem/etc/init.d/40_serial @@ -0,0 +1 @@ +getty debug: -J diff --git a/filesystem/etc/init.rc b/filesystem/etc/init.rc deleted file mode 100644 index ca4b860..0000000 --- a/filesystem/etc/init.rc +++ /dev/null @@ -1,12 +0,0 @@ -/sbin/randd -/sbin/ptyd -/sbin/pcid /etc/pcid.toml -/sbin/ethernetd -/sbin/ipd -/sbin/tcpd -/sbin/udpd -dhcpd -b -getty display:2 -getty display:3 -/sbin/orbital display:4/activate /ui/bin/orblogin /ui/bin/launcher -getty debug: -J diff --git a/initfs/etc/init.rc b/initfs/etc/init.rc index 1bfc59d..97b35c2 100644 --- a/initfs/etc/init.rc +++ b/initfs/etc/init.rc @@ -6,4 +6,4 @@ pcid /etc/pcid.toml redoxfs disk:0 file cd file: export PATH file:/bin -run /etc/init.rc +run.d /etc/init.d diff --git a/libc-artifacts b/libc-artifacts index 67098b3..a3b7f7a 160000 --- a/libc-artifacts +++ b/libc-artifacts @@ -1 +1 @@ -Subproject commit 67098b38c671d7804c3b9b7b856090099d4cecda +Subproject commit a3b7f7af5e2695c309eb5d87158deb50cbbab2a6 diff --git a/programs/init/src/main.rs b/programs/init/src/main.rs index 1b010ce..56aa80e 100644 --- a/programs/init/src/main.rs +++ b/programs/init/src/main.rs @@ -1,11 +1,12 @@ extern crate syscall; use std::env; -use std::fs::File; +use std::fs::{File, read_dir}; use std::io::{BufRead, BufReader, Result}; +use std::path::Path; use std::process::Command; -pub fn run(file: &str) -> Result<()> { +pub fn run(file: &Path) -> Result<()> { let file = File::open(file)?; let reader = BufReader::new(file); @@ -46,12 +47,42 @@ pub fn run(file: &str) -> Result<()> { println!("init: failed to export: no argument"); }, "run" => if let Some(new_file) = args.next() { - if let Err(err) = run(&new_file) { + if let Err(err) = run(&Path::new(new_file)) { println!("init: failed to run '{}': {}", new_file, err); } } else { println!("init: failed to run: no argument"); }, + "run.d" => if let Some(new_dir) = args.next() { + match read_dir(new_dir) { + Ok(list) => { + let mut entries = vec![]; + for entry_res in list { + match entry_res { + Ok(entry) => { + entries.push(entry.path()); + }, + Err(err) => { + println!("init: failed to run.d: '{}': {}", new_dir, err); + } + } + } + + entries.sort(); + + for entry in entries { + if let Err(err) = run(&entry) { + println!("init: failed to run '{}': {}", entry.display(), err); + } + } + }, + Err(err) => { + println!("init: failed to run.d: '{}': {}", new_dir, err); + } + } + } else { + println!("init: failed to run.d: no argument"); + }, "stdio" => if let Some(stdio) = args.next() { let _ = syscall::close(2); let _ = syscall::close(1); @@ -86,7 +117,7 @@ pub fn run(file: &str) -> Result<()> { } pub fn main() { - if let Err(err) = run("initfs:etc/init.rc") { + if let Err(err) = run(&Path::new("initfs:etc/init.rc")) { println!("init: failed to run initfs:etc/init.rc: {}", err); } From 23fce2aed3c6746542b84a23b44371b788ed34e8 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 6 Jan 2017 14:36:28 -0700 Subject: [PATCH 056/522] Update libc artifacts --- libc-artifacts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libc-artifacts b/libc-artifacts index a3b7f7a..cde8ab5 160000 --- a/libc-artifacts +++ b/libc-artifacts @@ -1 +1 @@ -Subproject commit a3b7f7af5e2695c309eb5d87158deb50cbbab2a6 +Subproject commit cde8ab5477e5b44307645b5c799a6de0c80ad1ff From 46b56cd312f63a0c563cb1b6e3dc1ebdc204abc9 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 7 Jan 2017 07:56:18 -0700 Subject: [PATCH 057/522] Update kernel and libc-artifacts --- kernel | 2 +- libc-artifacts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel b/kernel index 06118a2..375e8ad 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 06118a23ddf578424c35c2a0f9b704acbc5648f0 +Subproject commit 375e8addd20d39cd8a40bf39160532c15bd55c17 diff --git a/libc-artifacts b/libc-artifacts index cde8ab5..2e29f24 160000 --- a/libc-artifacts +++ b/libc-artifacts @@ -1 +1 @@ -Subproject commit cde8ab5477e5b44307645b5c799a6de0c80ad1ff +Subproject commit 2e29f24818cf458a3827dc0d20fb0420a035adff From ae11b307176d3cdc35cbfe66404216cdf7c271f2 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 7 Jan 2017 19:20:53 -0700 Subject: [PATCH 058/522] Update libc-artifacts --- libc-artifacts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libc-artifacts b/libc-artifacts index 2e29f24..9452ef5 160000 --- a/libc-artifacts +++ b/libc-artifacts @@ -1 +1 @@ -Subproject commit 2e29f24818cf458a3827dc0d20fb0420a035adff +Subproject commit 9452ef560a3c1c85a715dcc140ac932bf857fff5 From 4708d34a564b1d4d7e1dd1e9693120e52f15ba27 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 8 Jan 2017 10:24:02 -0700 Subject: [PATCH 059/522] Update libc artifacts --- libc-artifacts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libc-artifacts b/libc-artifacts index 9452ef5..8278a62 160000 --- a/libc-artifacts +++ b/libc-artifacts @@ -1 +1 @@ -Subproject commit 9452ef560a3c1c85a715dcc140ac932bf857fff5 +Subproject commit 8278a6252ca84ffef684bf3c371d8ab819c47ba4 From 2b35288f8c6f1213a7fbe0d010bbbd2461ea1538 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 8 Jan 2017 17:44:33 -0700 Subject: [PATCH 060/522] Update rust --- rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust b/rust index d40d01b..82a3f9f 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit d40d01bd0e7d9d20bb3454a3d0870f00b805a01c +Subproject commit 82a3f9fbecd3b4cfac2ac4821ce330227dbdedb0 From 29815a38e81f81c3233358725f3784fbbe192d74 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 8 Jan 2017 20:48:51 -0700 Subject: [PATCH 061/522] Add screenfetch --- filesystem/etc/hostname | 1 + mk/userspace/extrautils.mk | 1 + programs/extrautils | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 filesystem/etc/hostname diff --git a/filesystem/etc/hostname b/filesystem/etc/hostname new file mode 100644 index 0000000..5e07ae0 --- /dev/null +++ b/filesystem/etc/hostname @@ -0,0 +1 @@ +redox diff --git a/mk/userspace/extrautils.mk b/mk/userspace/extrautils.mk index c161d87..7a7774b 100644 --- a/mk/userspace/extrautils.mk +++ b/mk/userspace/extrautils.mk @@ -8,6 +8,7 @@ extrautils: \ filesystem/bin/mdless \ filesystem/bin/mtxt \ filesystem/bin/rem \ + filesystem/bin/screenfetch #filesystem/bin/dmesg filesystem/bin/info filesystem/bin/watch filesystem/bin/%: programs/extrautils/Cargo.toml programs/extrautils/src/bin/%.rs $(BUILD)/libstd.rlib diff --git a/programs/extrautils b/programs/extrautils index 4a5ee6e..616aa63 160000 --- a/programs/extrautils +++ b/programs/extrautils @@ -1 +1 @@ -Subproject commit 4a5ee6e845bc3dd2180b505a303da6ee1e5021d1 +Subproject commit 616aa63408e439c56a59e4096f044b3157657a05 From c67ba667ca2711986db0cd2706899756fefafb94 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 8 Jan 2017 21:06:20 -0700 Subject: [PATCH 062/522] Update screenfetch --- programs/extrautils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/extrautils b/programs/extrautils index 616aa63..f371a06 160000 --- a/programs/extrautils +++ b/programs/extrautils @@ -1 +1 @@ -Subproject commit 616aa63408e439c56a59e4096f044b3157657a05 +Subproject commit f371a0684e816d8ebf12446c3f6c799bd276efa6 From 2d882b7d004e5c4ec035ef8680c405e29a7be3c7 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 9 Jan 2017 10:16:25 -0700 Subject: [PATCH 063/522] Add installer repo --- installer | 1 + 1 file changed, 1 insertion(+) create mode 160000 installer diff --git a/installer b/installer new file mode 160000 index 0000000..1abfd39 --- /dev/null +++ b/installer @@ -0,0 +1 @@ +Subproject commit 1abfd39b8da12b5fa40d48fec66016e981d58f42 From 5e050cd7ae21fcf750f96ba781765fd6f3d20841 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 9 Jan 2017 16:01:34 -0700 Subject: [PATCH 064/522] Move orbital.conf into orbdata --- filesystem/etc/orbital.conf | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 filesystem/etc/orbital.conf diff --git a/filesystem/etc/orbital.conf b/filesystem/etc/orbital.conf deleted file mode 100644 index 8d46aba..0000000 --- a/filesystem/etc/orbital.conf +++ /dev/null @@ -1,2 +0,0 @@ -background=/ui/background.png -cursor=/ui/cursor.png From f0dc4cdbd13fc970a9887ecceead4f983ab74632 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 9 Jan 2017 16:02:29 -0700 Subject: [PATCH 065/522] Update orbital, orbdata --- filesystem/ui | 2 +- schemes/orbital | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/filesystem/ui b/filesystem/ui index e8c057a..9d16c60 160000 --- a/filesystem/ui +++ b/filesystem/ui @@ -1 +1 @@ -Subproject commit e8c057a343c2f55c38a134ac9db65f3c7f5c8eb2 +Subproject commit 9d16c600c1fb7ac3899961d9caefd1abb3a41cea diff --git a/schemes/orbital b/schemes/orbital index 3dd11a7..baa69a2 160000 --- a/schemes/orbital +++ b/schemes/orbital @@ -1 +1 @@ -Subproject commit 3dd11a7cfa8282204ad55356c39d04278267fceb +Subproject commit baa69a2fa69b827645e59abc389f5a162d76f035 From 9fbeec7a7a377510860dfc4305f5371bf0aa519c Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 9 Jan 2017 16:32:12 -0700 Subject: [PATCH 066/522] Update orbutils --- programs/orbutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/orbutils b/programs/orbutils index abd1fe5..ddd928a 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit abd1fe55e92143668a973b99dc5031b2d8c7ab92 +Subproject commit ddd928acecda3188a833736f28782be9b0c5205b From e50576b28c4c6643f2134cc72ead62590af36468 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 9 Jan 2017 20:37:34 -0700 Subject: [PATCH 067/522] Updates to use absolute URLs --- crates/dma/Cargo.toml | 6 -- crates/dma/src/lib.rs | 78 ----------------------- crates/event | 1 + crates/event/Cargo.toml | 6 -- crates/event/src/lib.rs | 83 ------------------------- crates/hole_list_allocator/Cargo.toml | 8 --- crates/hole_list_allocator/src/lib.rs | 62 ------------------- crates/io/Cargo.toml | 3 - crates/io/src/io.rs | 67 -------------------- crates/io/src/lib.rs | 14 ----- crates/io/src/mmio.rs | 31 ---------- crates/io/src/pio.rs | 89 --------------------------- schemes/ethernetd/Cargo.toml | 5 +- schemes/example/Cargo.toml | 2 +- schemes/ipd/Cargo.toml | 5 +- schemes/ptyd/Cargo.toml | 2 +- schemes/randd/Cargo.toml | 2 +- schemes/tcpd/Cargo.toml | 7 +-- schemes/udpd/Cargo.toml | 7 +-- 19 files changed, 14 insertions(+), 464 deletions(-) delete mode 100644 crates/dma/Cargo.toml delete mode 100644 crates/dma/src/lib.rs create mode 160000 crates/event delete mode 100644 crates/event/Cargo.toml delete mode 100644 crates/event/src/lib.rs delete mode 100644 crates/hole_list_allocator/Cargo.toml delete mode 100644 crates/hole_list_allocator/src/lib.rs delete mode 100644 crates/io/Cargo.toml delete mode 100644 crates/io/src/io.rs delete mode 100644 crates/io/src/lib.rs delete mode 100644 crates/io/src/mmio.rs delete mode 100644 crates/io/src/pio.rs diff --git a/crates/dma/Cargo.toml b/crates/dma/Cargo.toml deleted file mode 100644 index 24c1b8e..0000000 --- a/crates/dma/Cargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "dma" -version = "0.1.0" - -[dependencies] -redox_syscall = { path = "../../syscall/" } diff --git a/crates/dma/src/lib.rs b/crates/dma/src/lib.rs deleted file mode 100644 index 557b60a..0000000 --- a/crates/dma/src/lib.rs +++ /dev/null @@ -1,78 +0,0 @@ -extern crate syscall; - -use std::{mem, ptr}; -use std::ops::{Deref, DerefMut}; - -use syscall::Result; - -struct PhysBox { - address: usize, - size: usize -} - -impl PhysBox { - fn new(size: usize) -> Result { - let address = unsafe { syscall::physalloc(size)? }; - Ok(PhysBox { - address: address, - size: size - }) - } -} - -impl Drop for PhysBox { - fn drop(&mut self) { - let _ = unsafe { syscall::physfree(self.address, self.size) }; - } -} - -pub struct Dma { - phys: PhysBox, - virt: *mut T -} - -impl Dma { - pub fn new(value: T) -> Result> { - let phys = PhysBox::new(mem::size_of::())?; - let virt = unsafe { syscall::physmap(phys.address, phys.size, syscall::MAP_WRITE)? } as *mut T; - unsafe { ptr::write(virt, value); } - Ok(Dma { - phys: phys, - virt: virt - }) - } - - pub fn zeroed() -> Result> { - let phys = PhysBox::new(mem::size_of::())?; - let virt = unsafe { syscall::physmap(phys.address, phys.size, syscall::MAP_WRITE)? } as *mut T; - unsafe { ptr::write_bytes(virt as *mut u8, 0, phys.size); } - Ok(Dma { - phys: phys, - virt: virt - }) - } - - pub fn physical(&self) -> usize { - self.phys.address - } -} - -impl Deref for Dma { - type Target = T; - fn deref(&self) -> &T { - unsafe { &*self.virt } - } -} - -impl DerefMut for Dma { - fn deref_mut(&mut self) -> &mut T { - unsafe { &mut *self.virt } - } -} - -impl Drop for Dma { - fn drop(&mut self) { - unsafe { drop(ptr::read(self.virt)); } - let _ = unsafe { syscall::physunmap(self.virt as usize) }; - } -} diff --git a/crates/event b/crates/event new file mode 160000 index 0000000..d8d4724 --- /dev/null +++ b/crates/event @@ -0,0 +1 @@ +Subproject commit d8d472487f5e666b8c61a54326d3f89e4a816fec diff --git a/crates/event/Cargo.toml b/crates/event/Cargo.toml deleted file mode 100644 index d382ece..0000000 --- a/crates/event/Cargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "event" -version = "0.1.0" - -[dependencies] -redox_syscall = { path = "../../syscall/" } diff --git a/crates/event/src/lib.rs b/crates/event/src/lib.rs deleted file mode 100644 index a3662a0..0000000 --- a/crates/event/src/lib.rs +++ /dev/null @@ -1,83 +0,0 @@ -extern crate syscall; - -use std::collections::BTreeMap; -use std::fs::File; -use std::io::{Read, Error, Result}; -use std::os::unix::io::RawFd; - -pub struct EventQueue { - /// The file to read events from - file: File, - /// A map of registered file descriptors to their handler callbacks - callbacks: BTreeMap Result>>> -} - -impl EventQueue { - /// Create a new event queue - pub fn new() -> Result> { - Ok(EventQueue { - file: File::open("event:")?, - callbacks: BTreeMap::new() - }) - } - - /// Add a file to the event queue, calling a callback when an event occurs - /// - /// The callback is given a mutable reference to the file and the event data - /// (typically the length of data available for read) - /// - /// The callback returns Ok(None) if it wishes to continue the event loop, - /// or Ok(Some(R)) to break the event loop and return the value. - /// Err can be used to allow the callback to return an I/O error, and break the - /// event loop - pub fn add Result> + 'static>(&mut self, fd: RawFd, callback: F) -> Result<()> { - syscall::fevent(fd, syscall::EVENT_READ).map_err(|x| Error::from_raw_os_error(x.errno))?; - - self.callbacks.insert(fd, Box::new(callback)); - - Ok(()) - } - - /// Remove a file from the event queue, returning its callback if found - pub fn remove(&mut self, fd: RawFd) -> Result Result>>>> { - if let Some(callback) = self.callbacks.remove(&fd) { - syscall::fevent(fd, 0).map_err(|x| Error::from_raw_os_error(x.errno))?; - - Ok(Some(callback)) - } else { - Ok(None) - } - } - - /// Send an event to a descriptor callback - pub fn trigger(&mut self, fd: RawFd, count: usize) -> Result> { - if let Some(callback) = self.callbacks.get_mut(&fd) { - callback(count) - } else { - Ok(None) - } - } - - /// Send an event to all descriptor callbacks, useful for cleaning out buffers after init - pub fn trigger_all(&mut self, count: usize) -> Result> { - let mut rets = Vec::new(); - for (_fd, callback) in self.callbacks.iter_mut() { - if let Some(ret) = callback(count)? { - rets.push(ret); - } - } - Ok(rets) - } - - /// Process the event queue until a callback returns Some(R) - pub fn run(&mut self) -> Result { - loop { - let mut event = syscall::Event::default(); - if self.file.read(&mut event)? > 0 { - if let Some(ret) = self.trigger(event.id, event.data)? { - return Ok(ret); - } - } - } - } -} diff --git a/crates/hole_list_allocator/Cargo.toml b/crates/hole_list_allocator/Cargo.toml deleted file mode 100644 index 5ef3a50..0000000 --- a/crates/hole_list_allocator/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -authors = ["Philipp Oppermann "] -name = "hole_list_allocator" -version = "0.1.0" - -[dependencies] -linked_list_allocator = { git = "https://github.com/phil-opp/linked-list-allocator.git" } -spin = "*" diff --git a/crates/hole_list_allocator/src/lib.rs b/crates/hole_list_allocator/src/lib.rs deleted file mode 100644 index df90843..0000000 --- a/crates/hole_list_allocator/src/lib.rs +++ /dev/null @@ -1,62 +0,0 @@ -#![feature(allocator)] -#![feature(const_fn)] - -#![allocator] -#![no_std] - -use spin::Mutex; -use linked_list_allocator::Heap; - -extern crate spin; -extern crate linked_list_allocator; - -static HEAP: Mutex> = Mutex::new(None); - -pub unsafe fn init(offset: usize, size: usize) { - *HEAP.lock() = Some(Heap::new(offset, size)); -} - -#[no_mangle] -pub extern fn __rust_allocate(size: usize, align: usize) -> *mut u8 { - if let Some(ref mut heap) = *HEAP.lock() { - heap.allocate_first_fit(size, align).expect("out of memory") - } else { - panic!("__rust_allocate: heap not initialized"); - } -} - -#[no_mangle] -pub extern fn __rust_deallocate(ptr: *mut u8, size: usize, align: usize) { - if let Some(ref mut heap) = *HEAP.lock() { - unsafe { heap.deallocate(ptr, size, align) }; - } else { - panic!("__rust_deallocate: heap not initialized"); - } -} - -#[no_mangle] -pub extern fn __rust_usable_size(size: usize, _align: usize) -> usize { - size -} - -#[no_mangle] -pub extern fn __rust_reallocate_inplace(_ptr: *mut u8, size: usize, - _new_size: usize, _align: usize) -> usize -{ - size -} - -#[no_mangle] -pub extern fn __rust_reallocate(ptr: *mut u8, size: usize, new_size: usize, - align: usize) -> *mut u8 { - use core::{ptr, cmp}; - - // from: https://github.com/rust-lang/rust/blob/ - // c66d2380a810c9a2b3dbb4f93a830b101ee49cc2/ - // src/liballoc_system/lib.rs#L98-L101 - - let new_ptr = __rust_allocate(new_size, align); - unsafe { ptr::copy(ptr, new_ptr, cmp::min(size, new_size)) }; - __rust_deallocate(ptr, size, align); - new_ptr -} diff --git a/crates/io/Cargo.toml b/crates/io/Cargo.toml deleted file mode 100644 index b0ee40b..0000000 --- a/crates/io/Cargo.toml +++ /dev/null @@ -1,3 +0,0 @@ -[package] -name = "io" -version = "0.1.0" diff --git a/crates/io/src/io.rs b/crates/io/src/io.rs deleted file mode 100644 index fb866b5..0000000 --- a/crates/io/src/io.rs +++ /dev/null @@ -1,67 +0,0 @@ -use core::cmp::PartialEq; -use core::ops::{BitAnd, BitOr, Not}; - -pub trait Io { - type Value: Copy + PartialEq + BitAnd + BitOr + Not; - - fn read(&self) -> Self::Value; - fn write(&mut self, value: Self::Value); - - #[inline(always)] - fn readf(&self, flags: Self::Value) -> bool { - (self.read() & flags) as Self::Value == flags - } - - #[inline(always)] - fn writef(&mut self, flags: Self::Value, value: bool) { - let tmp: Self::Value = match value { - true => self.read() | flags, - false => self.read() & !flags, - }; - self.write(tmp); - } -} - -pub struct ReadOnly { - inner: I -} - -impl ReadOnly { - pub const fn new(inner: I) -> ReadOnly { - ReadOnly { - inner: inner - } - } - - #[inline(always)] - pub fn read(&self) -> I::Value { - self.inner.read() - } - - #[inline(always)] - pub fn readf(&self, flags: I::Value) -> bool { - self.inner.readf(flags) - } -} - -pub struct WriteOnly { - inner: I -} - -impl WriteOnly { - pub const fn new(inner: I) -> WriteOnly { - WriteOnly { - inner: inner - } - } - - #[inline(always)] - pub fn write(&mut self, value: I::Value) { - self.inner.write(value) - } - - #[inline(always)] - pub fn writef(&mut self, flags: I::Value, value: bool) { - self.inner.writef(flags, value) - } -} diff --git a/crates/io/src/lib.rs b/crates/io/src/lib.rs deleted file mode 100644 index 22f8eb7..0000000 --- a/crates/io/src/lib.rs +++ /dev/null @@ -1,14 +0,0 @@ -//! I/O functions - -#![feature(asm)] -#![feature(const_fn)] -#![feature(core_intrinsics)] -#![no_std] - -pub use self::io::*; -pub use self::mmio::*; -pub use self::pio::*; - -mod io; -mod mmio; -mod pio; diff --git a/crates/io/src/mmio.rs b/crates/io/src/mmio.rs deleted file mode 100644 index 1a1d199..0000000 --- a/crates/io/src/mmio.rs +++ /dev/null @@ -1,31 +0,0 @@ -use core::intrinsics::{volatile_load, volatile_store}; -use core::mem::uninitialized; -use core::ops::{BitAnd, BitOr, Not}; - -use super::io::Io; - -#[repr(packed)] -pub struct Mmio { - value: T, -} - -impl Mmio { - /// Create a new Mmio without initializing - pub fn new() -> Self { - Mmio { - value: unsafe { uninitialized() } - } - } -} - -impl Io for Mmio where T: Copy + PartialEq + BitAnd + BitOr + Not { - type Value = T; - - fn read(&self) -> T { - unsafe { volatile_load(&self.value) } - } - - fn write(&mut self, value: T) { - unsafe { volatile_store(&mut self.value, value) }; - } -} diff --git a/crates/io/src/pio.rs b/crates/io/src/pio.rs deleted file mode 100644 index 91ae310..0000000 --- a/crates/io/src/pio.rs +++ /dev/null @@ -1,89 +0,0 @@ -use core::marker::PhantomData; - -use super::io::Io; - -/// Generic PIO -#[derive(Copy, Clone)] -pub struct Pio { - port: u16, - value: PhantomData, -} - -impl Pio { - /// Create a PIO from a given port - pub const fn new(port: u16) -> Self { - Pio:: { - port: port, - value: PhantomData, - } - } -} - -/// Read/Write for byte PIO -impl Io for Pio { - type Value = u8; - - /// Read - #[inline(always)] - fn read(&self) -> u8 { - let value: u8; - unsafe { - asm!("in $0, $1" : "={al}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile"); - } - value - } - - /// Write - #[inline(always)] - fn write(&mut self, value: u8) { - unsafe { - asm!("out $1, $0" : : "{al}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile"); - } - } -} - -/// Read/Write for word PIO -impl Io for Pio { - type Value = u16; - - /// Read - #[inline(always)] - fn read(&self) -> u16 { - let value: u16; - unsafe { - asm!("in $0, $1" : "={ax}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile"); - } - value - } - - /// Write - #[inline(always)] - fn write(&mut self, value: u16) { - unsafe { - asm!("out $1, $0" : : "{ax}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile"); - } - } -} - -/// Read/Write for doubleword PIO -impl Io for Pio { - type Value = u32; - - /// Read - #[inline(always)] - fn read(&self) -> u32 { - let value: u32; - unsafe { - asm!("in $0, $1" : "={eax}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile"); - } - value - } - - /// Write - #[inline(always)] - fn write(&mut self, value: u32) { - unsafe { - asm!("out $1, $0" : : "{eax}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile"); - } - } -} diff --git a/schemes/ethernetd/Cargo.toml b/schemes/ethernetd/Cargo.toml index 6e10ca0..eb68975 100644 --- a/schemes/ethernetd/Cargo.toml +++ b/schemes/ethernetd/Cargo.toml @@ -3,6 +3,5 @@ name = "ethernetd" version = "0.1.0" [dependencies] -event = { path = "../../crates/event/" } -netutils = { path = "../../programs/netutils/" } -redox_syscall = { path = "../../syscall/" } +netutils = { git = "https://github.com/redox-os/netutils.git" } +redox_syscall = { git = "https://github.com/redox-os/syscall.git" } diff --git a/schemes/example/Cargo.toml b/schemes/example/Cargo.toml index dcd504b..9ddf8dd 100644 --- a/schemes/example/Cargo.toml +++ b/schemes/example/Cargo.toml @@ -3,4 +3,4 @@ name = "example" version = "0.1.0" [dependencies] -redox_syscall = { path = "../../syscall/" } +redox_syscall = { git = "https://github.com/redox-os/syscall.git" } diff --git a/schemes/ipd/Cargo.toml b/schemes/ipd/Cargo.toml index 23d2f3d..63e9e70 100644 --- a/schemes/ipd/Cargo.toml +++ b/schemes/ipd/Cargo.toml @@ -3,6 +3,5 @@ name = "ipd" version = "0.1.0" [dependencies] -event = { path = "../../crates/event/" } -netutils = { path = "../../programs/netutils/" } -redox_syscall = { path = "../../syscall/" } +netutils = { git = "https://github.com/redox-os/netutils.git" } +redox_syscall = { git = "https://github.com/redox-os/syscall.git" } diff --git a/schemes/ptyd/Cargo.toml b/schemes/ptyd/Cargo.toml index c8001df..69b4365 100644 --- a/schemes/ptyd/Cargo.toml +++ b/schemes/ptyd/Cargo.toml @@ -3,4 +3,4 @@ name = "ptyd" version = "0.1.0" [dependencies] -redox_syscall = { path = "../../syscall/" } +redox_syscall = { git = "https://github.com/redox-os/syscall.git" } diff --git a/schemes/randd/Cargo.toml b/schemes/randd/Cargo.toml index 5ecdeff..2222cf5 100644 --- a/schemes/randd/Cargo.toml +++ b/schemes/randd/Cargo.toml @@ -4,4 +4,4 @@ version = "0.1.0" [dependencies] raw-cpuid = "2.*" -redox_syscall = { path = "../../syscall/" } +redox_syscall = { git = "https://github.com/redox-os/syscall.git" } diff --git a/schemes/tcpd/Cargo.toml b/schemes/tcpd/Cargo.toml index a9c4202..b575718 100644 --- a/schemes/tcpd/Cargo.toml +++ b/schemes/tcpd/Cargo.toml @@ -3,7 +3,6 @@ name = "tcpd" version = "0.1.0" [dependencies] -event = { path = "../../crates/event/" } -netutils = { path = "../../programs/netutils/" } -rand = { git = "https://github.com/rust-lang-nursery/rand.git" } -redox_syscall = { path = "../../syscall/" } +netutils = { git = "https://github.com/redox-os/netutils.git" } +rand = "0.3" +redox_syscall = { git = "https://github.com/redox-os/syscall.git" } diff --git a/schemes/udpd/Cargo.toml b/schemes/udpd/Cargo.toml index a62ffb0..c609ec9 100644 --- a/schemes/udpd/Cargo.toml +++ b/schemes/udpd/Cargo.toml @@ -3,7 +3,6 @@ name = "udpd" version = "0.1.0" [dependencies] -event = { path = "../../crates/event/" } -netutils = { path = "../../programs/netutils/" } -rand = { git = "https://github.com/rust-lang-nursery/rand.git" } -redox_syscall = { path = "../../syscall/" } +netutils = { git = "https://github.com/redox-os/netutils.git" } +rand = "0.3" +redox_syscall = { git = "https://github.com/redox-os/syscall.git" } From 0ed5bd31b2526c58ca76e6ee07e82f9d443a6d22 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 9 Jan 2017 20:38:42 -0700 Subject: [PATCH 068/522] Update submodules --- Cargo.toml | 3 ++- crates/event | 1 - drivers | 2 +- kernel | 2 +- programs/contain/Cargo.toml | 2 +- programs/games | 2 +- programs/init/Cargo.toml | 2 +- syscall | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) delete mode 160000 crates/event diff --git a/Cargo.toml b/Cargo.toml index e12b7df..5670627 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,5 +31,6 @@ members = [ "schemes/randd", "schemes/redoxfs", "schemes/tcpd", - "schemes/udpd" + "schemes/udpd", + "syscall" ] diff --git a/crates/event b/crates/event deleted file mode 160000 index d8d4724..0000000 --- a/crates/event +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d8d472487f5e666b8c61a54326d3f89e4a816fec diff --git a/drivers b/drivers index 9eeade8..6084037 160000 --- a/drivers +++ b/drivers @@ -1 +1 @@ -Subproject commit 9eeade88606095a03ee3c285972b45d1c499a971 +Subproject commit 608403765d1d290045ddc14d10c6f5442cb2452d diff --git a/kernel b/kernel index 375e8ad..e201355 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 375e8addd20d39cd8a40bf39160532c15bd55c17 +Subproject commit e20135575c6392dfbf43e117cafee03e00ae8f0c diff --git a/programs/contain/Cargo.toml b/programs/contain/Cargo.toml index ad46eb0..baf2a4e 100644 --- a/programs/contain/Cargo.toml +++ b/programs/contain/Cargo.toml @@ -3,4 +3,4 @@ name = "contain" version = "0.1.0" [dependencies] -redox_syscall = { path = "../../syscall" } +redox_syscall = { git = "https://github.com/redox-os/syscall.git" } diff --git a/programs/games b/programs/games index 15374e8..3478af8 160000 --- a/programs/games +++ b/programs/games @@ -1 +1 @@ -Subproject commit 15374e8a8ae5db6982e7d265ad088f790e38a3b8 +Subproject commit 3478af86d9bb413dc918ead3029eff65bf44e099 diff --git a/programs/init/Cargo.toml b/programs/init/Cargo.toml index b045ad6..0ababa4 100644 --- a/programs/init/Cargo.toml +++ b/programs/init/Cargo.toml @@ -3,4 +3,4 @@ name = "init" version = "0.1.0" [dependencies] -redox_syscall = { path = "../../syscall" } +redox_syscall = { git = "https://github.com/redox-os/syscall.git" } diff --git a/syscall b/syscall index 1193791..6188e4d 160000 --- a/syscall +++ b/syscall @@ -1 +1 @@ -Subproject commit 1193791d642795840d7f22967249bad8bdef1a32 +Subproject commit 6188e4d040c14d221aebebb942d424edada47671 From 9068b9dcf29bf03558ba60708f14373f7c9d1c7e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 9 Jan 2017 21:01:23 -0700 Subject: [PATCH 069/522] Add event dependency --- schemes/ethernetd/Cargo.toml | 1 + schemes/ipd/Cargo.toml | 1 + schemes/ptyd/src/main.rs | 2 +- schemes/tcpd/Cargo.toml | 1 + schemes/udpd/Cargo.toml | 1 + 5 files changed, 5 insertions(+), 1 deletion(-) diff --git a/schemes/ethernetd/Cargo.toml b/schemes/ethernetd/Cargo.toml index eb68975..c99cae5 100644 --- a/schemes/ethernetd/Cargo.toml +++ b/schemes/ethernetd/Cargo.toml @@ -4,4 +4,5 @@ version = "0.1.0" [dependencies] netutils = { git = "https://github.com/redox-os/netutils.git" } +redox_event = { git = "https://github.com/redox-os/event.git" } redox_syscall = { git = "https://github.com/redox-os/syscall.git" } diff --git a/schemes/ipd/Cargo.toml b/schemes/ipd/Cargo.toml index 63e9e70..16f947a 100644 --- a/schemes/ipd/Cargo.toml +++ b/schemes/ipd/Cargo.toml @@ -4,4 +4,5 @@ version = "0.1.0" [dependencies] netutils = { git = "https://github.com/redox-os/netutils.git" } +redox_event = { git = "https://github.com/redox-os/event.git" } redox_syscall = { git = "https://github.com/redox-os/syscall.git" } diff --git a/schemes/ptyd/src/main.rs b/schemes/ptyd/src/main.rs index 28f058d..d03bd4f 100644 --- a/schemes/ptyd/src/main.rs +++ b/schemes/ptyd/src/main.rs @@ -1,4 +1,4 @@ -#![feature(rc_counts)] +#![deny(warnings)] extern crate syscall; diff --git a/schemes/tcpd/Cargo.toml b/schemes/tcpd/Cargo.toml index b575718..8d9c55f 100644 --- a/schemes/tcpd/Cargo.toml +++ b/schemes/tcpd/Cargo.toml @@ -5,4 +5,5 @@ version = "0.1.0" [dependencies] netutils = { git = "https://github.com/redox-os/netutils.git" } rand = "0.3" +redox_event = { git = "https://github.com/redox-os/event.git" } redox_syscall = { git = "https://github.com/redox-os/syscall.git" } diff --git a/schemes/udpd/Cargo.toml b/schemes/udpd/Cargo.toml index c609ec9..b33c74e 100644 --- a/schemes/udpd/Cargo.toml +++ b/schemes/udpd/Cargo.toml @@ -5,4 +5,5 @@ version = "0.1.0" [dependencies] netutils = { git = "https://github.com/redox-os/netutils.git" } rand = "0.3" +redox_event = { git = "https://github.com/redox-os/event.git" } redox_syscall = { git = "https://github.com/redox-os/syscall.git" } From 8e78f80c950c4f71843b43ad07455d523453edd4 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 9 Jan 2017 21:06:38 -0700 Subject: [PATCH 070/522] Remove verbose from cargo config --- .cargo/config | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.cargo/config b/.cargo/config index 4336324..f9f6b98 100644 --- a/.cargo/config +++ b/.cargo/config @@ -1,6 +1,3 @@ [target.x86_64-unknown-redox] linker = "libc-artifacts/gcc.sh" -rustflags = [ - "--verbose", - "-Z", "print-link-args" -] +rustflags = [] From 0bb45d85d1071a9ac5af6f3bdcdb19b0a21278cd Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 9 Jan 2017 21:20:36 -0700 Subject: [PATCH 071/522] Remove unifont --- res/fonts/unifont-license.txt | 371 ---------------------------------- res/fonts/unifont.font | Bin 884736 -> 0 bytes res/fonts/unifont.rs | 26 --- 3 files changed, 397 deletions(-) delete mode 100644 res/fonts/unifont-license.txt delete mode 100644 res/fonts/unifont.font delete mode 100644 res/fonts/unifont.rs diff --git a/res/fonts/unifont-license.txt b/res/fonts/unifont-license.txt deleted file mode 100644 index 6b540a8..0000000 --- a/res/fonts/unifont-license.txt +++ /dev/null @@ -1,371 +0,0 @@ -LICENSE -------- -The source code for everything except the compiled fonts in this current -release is licensed as follows: - - License for this current distribution of program source - files (i.e., everything except the fonts) is released under - the terms of the GNU General Public License version 2, - or (at your option) a later version. - - See the section below for a copy of the GNU General Public License - version 2. - -The license for the compiled fonts is covered by the above GPL terms -with the GNU font embedding exception, as follows: - - As a special exception, if you create a document which uses this font, - and embed this font or unaltered portions of this font into the document, - this font does not by itself cause the resulting document to be covered - by the GNU General Public License. This exception does not however - invalidate any other reasons why the document might be covered by the - GNU General Public License. If you modify this font, you may extend - this exception to your version of the font, but you are not obligated - to do so. If you do not wish to do so, delete this exception statement - from your version. - -See "http://www.gnu.org/licenses/gpl-faq.html#FontException" for more details. - - -GPL VERSION 2 -------------- - - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/res/fonts/unifont.font b/res/fonts/unifont.font deleted file mode 100644 index aee9d933a3cf9886d0bde40c632b05ea749a1336..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 884736 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�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\_DZN*Xa89Uk?396z); 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ⅈ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 z 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 diff --git a/res/fonts/unifont.rs b/res/fonts/unifont.rs deleted file mode 100644 index 9297f33..0000000 --- a/res/fonts/unifont.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::fs::File; -use std::io::{BufRead, BufReader, Read, Write}; - -fn main() { - let mut input = File::open("unifont.hex").unwrap(); - let mut output = File::create("unifont.font").unwrap(); - let mut count = 0; - for line_res in BufReader::new(input).lines() { - let line = line_res.unwrap(); - - let mut parts = line.split(":"); - let num = u32::from_str_radix(parts.next().unwrap(), 16).unwrap(); - assert_eq!(num, count); - - let mut data = [0; 16]; - let data_part = parts.next().unwrap(); - for i in 0..data.len() { - data[i] = u8::from_str_radix(&data_part[i * 2 .. i * 2 + 2], 16).unwrap(); - } - println!("{:>04X}:{:?}", num, data); - - output.write(&data).unwrap(); - - count += 1; - } -} From 15fa0ae7a6e598b9cb73d1b90ca171dae0e64e29 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 9 Jan 2017 21:21:07 -0700 Subject: [PATCH 072/522] Update drivers --- drivers | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers b/drivers index 6084037..cc29946 160000 --- a/drivers +++ b/drivers @@ -1 +1 @@ -Subproject commit 608403765d1d290045ddc14d10c6f5442cb2452d +Subproject commit cc299464fc11e01649ad8a09b127397e68901b77 From 68b33156730f8d376b3afbce3472d1504f899af7 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 9 Jan 2017 21:39:01 -0700 Subject: [PATCH 073/522] Compile with opt-level 3, lto --- Cargo.toml | 12 ++++++++++++ mk/config.mk | 2 +- mk/kernel.mk | 2 +- mk/userspace/mod.mk | 4 ++-- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5670627..77c2678 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,3 +34,15 @@ members = [ "schemes/udpd", "syscall" ] + +[profile.dev] +debug = true +debug-assertions = true +lto = false +opt-level = 0 + +[profile.release] +debug = false +debug-assertions = false +lto = true +opt-level = 3 diff --git a/mk/config.mk b/mk/config.mk index 0b1b9c9..5b11f72 100644 --- a/mk/config.mk +++ b/mk/config.mk @@ -21,7 +21,7 @@ BUILD=build/userspace RUSTC=./rustc.sh RUSTDOC=./rustdoc.sh CARGO=RUSTC="$(RUSTC)" RUSTDOC="$(RUSTDOC)" cargo -CARGOFLAGS=--target $(TARGET) --release -- -C codegen-units=`nproc` +CARGOFLAGS=--target $(TARGET) --release -- # Per host variables UNAME := $(shell uname) diff --git a/mk/kernel.mk b/mk/kernel.mk index 814fed7..6a716f6 100644 --- a/mk/kernel.mk +++ b/mk/kernel.mk @@ -1,6 +1,6 @@ $(KBUILD)/libcollections.rlib: rust/src/libcollections/Cargo.toml rust/src/libcollections/** mkdir -p $(KBUILD) - $(KCARGO) rustc --verbose --manifest-path $< $(KCARGOFLAGS) -o $@ + $(KCARGO) rustc --manifest-path $< $(KCARGOFLAGS) -o $@ cp rust/src/target/$(KTARGET)/release/deps/*.rlib $(KBUILD) $(KBUILD)/libkernel.a: kernel/Cargo.toml kernel/arch/** kernel/src/** $(KBUILD)/libcollections.rlib $(BUILD)/initfs.rs diff --git a/mk/userspace/mod.mk b/mk/userspace/mod.mk index b399ca2..7a7e503 100644 --- a/mk/userspace/mod.mk +++ b/mk/userspace/mod.mk @@ -28,12 +28,12 @@ include mk/userspace/userutils.mk $(BUILD)/libstd.rlib: rust/src/libstd/Cargo.toml rust/src/libstd/** mkdir -p $(BUILD) - $(CARGO) rustc --verbose --manifest-path $< --features "panic-unwind" $(CARGOFLAGS) -L native=libc-artifacts/usr/lib -o $@ + $(CARGO) rustc --manifest-path $< --features "panic-unwind" $(CARGOFLAGS) -L native=libc-artifacts/usr/lib -o $@ cp rust/src/target/$(TARGET)/release/deps/*.rlib $(BUILD) $(BUILD)/libtest.rlib: rust/src/libtest/Cargo.toml rust/src/libtest/** $(BUILD)/libstd.rlib mkdir -p $(BUILD) - $(CARGO) rustc --verbose --manifest-path $< $(CARGOFLAGS) -L native=libc-artifacts/usr/lib -o $@ + $(CARGO) rustc --manifest-path $< $(CARGOFLAGS) -L native=libc-artifacts/usr/lib -o $@ cp rust/src/target/$(TARGET)/release/deps/*.rlib $(BUILD) filesystem/bin/%: programs/%/Cargo.toml programs/%/src/** $(BUILD)/libstd.rlib From e519d215d81e98d3b2cf2e1127b29e6a2ef441b0 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 9 Jan 2017 21:51:41 -0700 Subject: [PATCH 074/522] Revert "Compile with opt-level 3, lto" This reverts commit 68b33156730f8d376b3afbce3472d1504f899af7. --- Cargo.toml | 12 ------------ mk/config.mk | 2 +- mk/kernel.mk | 2 +- mk/userspace/mod.mk | 4 ++-- 4 files changed, 4 insertions(+), 16 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 77c2678..5670627 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,15 +34,3 @@ members = [ "schemes/udpd", "syscall" ] - -[profile.dev] -debug = true -debug-assertions = true -lto = false -opt-level = 0 - -[profile.release] -debug = false -debug-assertions = false -lto = true -opt-level = 3 diff --git a/mk/config.mk b/mk/config.mk index 5b11f72..0b1b9c9 100644 --- a/mk/config.mk +++ b/mk/config.mk @@ -21,7 +21,7 @@ BUILD=build/userspace RUSTC=./rustc.sh RUSTDOC=./rustdoc.sh CARGO=RUSTC="$(RUSTC)" RUSTDOC="$(RUSTDOC)" cargo -CARGOFLAGS=--target $(TARGET) --release -- +CARGOFLAGS=--target $(TARGET) --release -- -C codegen-units=`nproc` # Per host variables UNAME := $(shell uname) diff --git a/mk/kernel.mk b/mk/kernel.mk index 6a716f6..814fed7 100644 --- a/mk/kernel.mk +++ b/mk/kernel.mk @@ -1,6 +1,6 @@ $(KBUILD)/libcollections.rlib: rust/src/libcollections/Cargo.toml rust/src/libcollections/** mkdir -p $(KBUILD) - $(KCARGO) rustc --manifest-path $< $(KCARGOFLAGS) -o $@ + $(KCARGO) rustc --verbose --manifest-path $< $(KCARGOFLAGS) -o $@ cp rust/src/target/$(KTARGET)/release/deps/*.rlib $(KBUILD) $(KBUILD)/libkernel.a: kernel/Cargo.toml kernel/arch/** kernel/src/** $(KBUILD)/libcollections.rlib $(BUILD)/initfs.rs diff --git a/mk/userspace/mod.mk b/mk/userspace/mod.mk index 7a7e503..b399ca2 100644 --- a/mk/userspace/mod.mk +++ b/mk/userspace/mod.mk @@ -28,12 +28,12 @@ include mk/userspace/userutils.mk $(BUILD)/libstd.rlib: rust/src/libstd/Cargo.toml rust/src/libstd/** mkdir -p $(BUILD) - $(CARGO) rustc --manifest-path $< --features "panic-unwind" $(CARGOFLAGS) -L native=libc-artifacts/usr/lib -o $@ + $(CARGO) rustc --verbose --manifest-path $< --features "panic-unwind" $(CARGOFLAGS) -L native=libc-artifacts/usr/lib -o $@ cp rust/src/target/$(TARGET)/release/deps/*.rlib $(BUILD) $(BUILD)/libtest.rlib: rust/src/libtest/Cargo.toml rust/src/libtest/** $(BUILD)/libstd.rlib mkdir -p $(BUILD) - $(CARGO) rustc --manifest-path $< $(CARGOFLAGS) -L native=libc-artifacts/usr/lib -o $@ + $(CARGO) rustc --verbose --manifest-path $< $(CARGOFLAGS) -L native=libc-artifacts/usr/lib -o $@ cp rust/src/target/$(TARGET)/release/deps/*.rlib $(BUILD) filesystem/bin/%: programs/%/Cargo.toml programs/%/src/** $(BUILD)/libstd.rlib From e111e173cf0f6770c105825c460972c29fcd8eb3 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 9 Jan 2017 21:52:36 -0700 Subject: [PATCH 075/522] Remove verbose --- mk/kernel.mk | 2 +- mk/userspace/mod.mk | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mk/kernel.mk b/mk/kernel.mk index 814fed7..6a716f6 100644 --- a/mk/kernel.mk +++ b/mk/kernel.mk @@ -1,6 +1,6 @@ $(KBUILD)/libcollections.rlib: rust/src/libcollections/Cargo.toml rust/src/libcollections/** mkdir -p $(KBUILD) - $(KCARGO) rustc --verbose --manifest-path $< $(KCARGOFLAGS) -o $@ + $(KCARGO) rustc --manifest-path $< $(KCARGOFLAGS) -o $@ cp rust/src/target/$(KTARGET)/release/deps/*.rlib $(KBUILD) $(KBUILD)/libkernel.a: kernel/Cargo.toml kernel/arch/** kernel/src/** $(KBUILD)/libcollections.rlib $(BUILD)/initfs.rs diff --git a/mk/userspace/mod.mk b/mk/userspace/mod.mk index b399ca2..7a7e503 100644 --- a/mk/userspace/mod.mk +++ b/mk/userspace/mod.mk @@ -28,12 +28,12 @@ include mk/userspace/userutils.mk $(BUILD)/libstd.rlib: rust/src/libstd/Cargo.toml rust/src/libstd/** mkdir -p $(BUILD) - $(CARGO) rustc --verbose --manifest-path $< --features "panic-unwind" $(CARGOFLAGS) -L native=libc-artifacts/usr/lib -o $@ + $(CARGO) rustc --manifest-path $< --features "panic-unwind" $(CARGOFLAGS) -L native=libc-artifacts/usr/lib -o $@ cp rust/src/target/$(TARGET)/release/deps/*.rlib $(BUILD) $(BUILD)/libtest.rlib: rust/src/libtest/Cargo.toml rust/src/libtest/** $(BUILD)/libstd.rlib mkdir -p $(BUILD) - $(CARGO) rustc --verbose --manifest-path $< $(CARGOFLAGS) -L native=libc-artifacts/usr/lib -o $@ + $(CARGO) rustc --manifest-path $< $(CARGOFLAGS) -L native=libc-artifacts/usr/lib -o $@ cp rust/src/target/$(TARGET)/release/deps/*.rlib $(BUILD) filesystem/bin/%: programs/%/Cargo.toml programs/%/src/** $(BUILD)/libstd.rlib From ddcdba3acc85fddfbd921c9926804aa9311e0451 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 9 Jan 2017 21:54:38 -0700 Subject: [PATCH 076/522] Make all at top of makefile --- Makefile | 9 ++++++++- mk/config.mk | 7 ------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index eb7df63..461c1fa 100644 --- a/Makefile +++ b/Makefile @@ -48,6 +48,13 @@ include mk/filesystem.mk # Disk images include mk/disk.mk -# Misc +# An empty target +FORCE: + +# A method of creating a listing for any binary +%.list: % + objdump -C -M intel -D $< > $@ + +# Wireshark wireshark: FORCE wireshark build/network.pcap diff --git a/mk/config.mk b/mk/config.mk index 0b1b9c9..acc8921 100644 --- a/mk/config.mk +++ b/mk/config.mk @@ -42,10 +42,3 @@ else VB_AUDIO="pulse" VBM=VBoxManage endif - -# An empty target -FORCE: - -# A method of creating a listing for any binary -%.list: % - objdump -C -M intel -D $< > $@ From 3357b57fa86df256bfac2074f44005f9b6fb0bfc Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 9 Jan 2017 22:18:35 -0700 Subject: [PATCH 077/522] Update installer, build installer with Redox --- Cargo.toml | 1 + installer | 2 +- mk/userspace/installer.mk | 7 +++++++ mk/userspace/mod.mk | 3 +++ 4 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 mk/userspace/installer.mk diff --git a/Cargo.toml b/Cargo.toml index 5670627..5683e19 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ members = [ "drivers/ps2d", "drivers/rtl8168d", "drivers/vesad", + "installer", "kernel", "programs/acid", "programs/binutils", diff --git a/installer b/installer index 1abfd39..be092f3 160000 --- a/installer +++ b/installer @@ -1 +1 @@ -Subproject commit 1abfd39b8da12b5fa40d48fec66016e981d58f42 +Subproject commit be092f37546dfb2ec297635c0f8e4b040189ca55 diff --git a/mk/userspace/installer.mk b/mk/userspace/installer.mk new file mode 100644 index 0000000..448da59 --- /dev/null +++ b/mk/userspace/installer.mk @@ -0,0 +1,7 @@ +installer: \ + filesystem/bin/redox_installer + +filesystem/bin/redox_installer: installer/Cargo.toml installer/src/** $(BUILD)/libstd.rlib + mkdir -p filesystem/bin + $(CARGO) rustc --manifest-path $< --bin redox_installer $(CARGOFLAGS) -o $@ + $(STRIP) $@ diff --git a/mk/userspace/mod.mk b/mk/userspace/mod.mk index 7a7e503..2d6fc28 100644 --- a/mk/userspace/mod.mk +++ b/mk/userspace/mod.mk @@ -3,6 +3,7 @@ userspace: \ coreutils \ extrautils \ games \ + installer \ ion \ netutils \ orbutils \ @@ -11,6 +12,7 @@ userspace: \ schemes \ filesystem/bin/acid \ filesystem/bin/contain \ + filesystem/bin/redox_installer \ filesystem/bin/smith \ filesystem/bin/tar @@ -19,6 +21,7 @@ include mk/userspace/coreutils.mk include mk/userspace/drivers.mk include mk/userspace/extrautils.mk include mk/userspace/games.mk +include mk/userspace/installer.mk include mk/userspace/ion.mk include mk/userspace/netutils.mk include mk/userspace/orbutils.mk From 9238ee48a35bb3348beb6473b03edaa18db563f8 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 9 Jan 2017 22:29:15 -0700 Subject: [PATCH 078/522] Update installer --- installer | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installer b/installer index be092f3..cfdb2a4 160000 --- a/installer +++ b/installer @@ -1 +1 @@ -Subproject commit be092f37546dfb2ec297635c0f8e4b040189ca55 +Subproject commit cfdb2a49686c7bc64d2040dfdbb0650f792b4270 From b734a16e0efb09dea86b5adfb78ed47fd8101ced Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 10 Jan 2017 09:19:16 -0700 Subject: [PATCH 079/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index e201355..433746e 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit e20135575c6392dfbf43e117cafee03e00ae8f0c +Subproject commit 433746e13cce721c01da543850e046cc249ca739 From 5175b39656facb500a728673c291e87718e26026 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 10 Jan 2017 09:20:39 -0700 Subject: [PATCH 080/522] Fix initfs target --- mk/initfs.mk | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/mk/initfs.mk b/mk/initfs.mk index 57983bb..7e9267b 100644 --- a/mk/initfs.mk +++ b/mk/initfs.mk @@ -1,14 +1,12 @@ -initfs: \ - initfs/bin/init \ - initfs/bin/ahcid \ - initfs/bin/bgad \ - initfs/bin/pcid \ - initfs/bin/ps2d \ - initfs/bin/redoxfs \ - initfs/bin/vesad \ - initfs/etc/** - -$(BUILD)/initfs.rs: initfs +$(BUILD)/initfs.rs: \ + initfs/bin/init \ + initfs/bin/ahcid \ + initfs/bin/bgad \ + initfs/bin/pcid \ + initfs/bin/ps2d \ + initfs/bin/redoxfs \ + initfs/bin/vesad \ + initfs/etc/** echo 'use collections::BTreeMap;' > $@ echo 'pub fn gen() -> BTreeMap<&'"'"'static [u8], (&'"'"'static [u8], bool)> {' >> $@ echo ' let mut files: BTreeMap<&'"'"'static [u8], (&'"'"'static [u8], bool)> = BTreeMap::new();' >> $@ From 27392dd69fa898826169f4bd0d5944b4fcf1b5e1 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 10 Jan 2017 09:23:14 -0700 Subject: [PATCH 081/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index 433746e..ba4588e 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 433746e13cce721c01da543850e046cc249ca739 +Subproject commit ba4588e84fdb8260867a346dd7a92ae2e9454e77 From 10bd3e860c2d6aebca84d5032059ebb2e53cfd44 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 10 Jan 2017 09:36:16 -0700 Subject: [PATCH 082/522] Update ion --- programs/ion | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/ion b/programs/ion index ffd29c8..41360f0 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit ffd29c8e5c655f047bf22f5250b422161864cdfa +Subproject commit 41360f0381b341e4cc7bb07a411fe25d98a1f985 From 4bff540aad9ab6469f6fe839f023b862c438d115 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 10 Jan 2017 09:51:04 -0700 Subject: [PATCH 083/522] Correctly set environment, use SHELL in contain --- programs/contain/src/main.rs | 2 +- programs/orbutils | 2 +- programs/userutils | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/programs/contain/src/main.rs b/programs/contain/src/main.rs index 2e60062..9dde7ed 100644 --- a/programs/contain/src/main.rs +++ b/programs/contain/src/main.rs @@ -132,7 +132,7 @@ pub fn main() { usage(); }, "enter" => if let Some(root) = args.next() { - let cmd = args.next().unwrap_or("sh".to_string()); + let cmd = args.next().unwrap_or(env::var("SHELL").unwrap_or("sh".to_string())); let args: Vec = args.collect(); enter(Path::new(&root), &cmd, &args); } else { diff --git a/programs/orbutils b/programs/orbutils index ddd928a..cf1e1f8 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit ddd928acecda3188a833736f28782be9b0c5205b +Subproject commit cf1e1f8e6406e9b01a2c62e46260e82a7aa33395 diff --git a/programs/userutils b/programs/userutils index 901caaf..ccae9c0 160000 --- a/programs/userutils +++ b/programs/userutils @@ -1 +1 @@ -Subproject commit 901caafce3d3d9cb9c772f4a8415e9f78a3a0da3 +Subproject commit ccae9c0b0abb9b6d2708655bdd4ef2f25be42d67 From 80bf9568f6988aa2e83e35dc05e0674979d68053 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 10 Jan 2017 10:00:07 -0700 Subject: [PATCH 084/522] Simplify contain program, update kernel --- kernel | 2 +- programs/contain/src/main.rs | 60 +++--------------------------------- 2 files changed, 6 insertions(+), 56 deletions(-) diff --git a/kernel b/kernel index ba4588e..ed69fac 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit ba4588e84fdb8260867a346dd7a92ae2e9454e77 +Subproject commit ed69fac232744d1aff4fb02ba6be196c74e9d2f0 diff --git a/programs/contain/src/main.rs b/programs/contain/src/main.rs index 9dde7ed..a9866ea 100644 --- a/programs/contain/src/main.rs +++ b/programs/contain/src/main.rs @@ -13,48 +13,10 @@ use self::chroot::ChrootScheme; mod chroot; fn usage() -> ! { - write!(stderr(), "contain [create|enter] root cmd args..\n").unwrap(); + write!(stderr(), "contain root cmd args..\n").unwrap(); process::exit(1); } -fn create(root: &Path) { - let root = Path::new(root); - - println!("{}", root.display()); - fs::create_dir(root).unwrap(); - - let mut bin = root.to_path_buf(); - bin.push("bin"); - println!("{}", bin.display()); - fs::create_dir(&bin).unwrap(); - - for entry in fs::read_dir("/bin").unwrap() { - let entry = entry.unwrap(); - let mut dest = bin.clone(); - dest.push(entry.file_name()); - println!("{} -> {}", entry.path().display(), dest.display()); - fs::copy(entry.path(), dest).unwrap(); - } - - let mut etc = root.to_path_buf(); - etc.push("etc"); - println!("{}", etc.display()); - fs::create_dir(&etc).unwrap(); - - let mut net = etc.clone(); - net.push("net"); - println!("{}", net.display()); - fs::create_dir(&net).unwrap(); - - for entry in fs::read_dir("/etc/net").unwrap() { - let entry = entry.unwrap(); - let mut dest = net.clone(); - dest.push(entry.file_name()); - println!("{} -> {}", entry.path().display(), dest.display()); - fs::copy(entry.path(), dest).unwrap(); - } -} - fn enter(root: &Path, cmd: &str, args: &[String]) { let names = [ "rand", @@ -124,22 +86,10 @@ fn enter(root: &Path, cmd: &str, args: &[String]) { pub fn main() { let mut args = env::args().skip(1); - if let Some(op) = args.next() { - match op.as_str() { - "create" => if let Some(root) = args.next() { - create(Path::new(&root)); - } else { - usage(); - }, - "enter" => if let Some(root) = args.next() { - let cmd = args.next().unwrap_or(env::var("SHELL").unwrap_or("sh".to_string())); - let args: Vec = args.collect(); - enter(Path::new(&root), &cmd, &args); - } else { - usage(); - }, - _ => usage() - } + if let Some(root) = args.next() { + let cmd = args.next().unwrap_or(env::var("SHELL").unwrap_or("sh".to_string())); + let args: Vec = args.collect(); + enter(Path::new(&root), &cmd, &args); } else { usage(); } From efec22ba9d0cd10bc836f4c0eb4c8f1772760dae Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 10 Jan 2017 10:06:52 -0700 Subject: [PATCH 085/522] Pass through more schemes - display and pty --- programs/contain/src/main.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/programs/contain/src/main.rs b/programs/contain/src/main.rs index a9866ea..caefc16 100644 --- a/programs/contain/src/main.rs +++ b/programs/contain/src/main.rs @@ -19,6 +19,8 @@ fn usage() -> ! { fn enter(root: &Path, cmd: &str, args: &[String]) { let names = [ + "display", + "pty", "rand", "tcp", "udp" From 1127c771ce95b2f3eed9f7c6f2498d49c0cb4321 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 10 Jan 2017 20:49:18 -0700 Subject: [PATCH 086/522] WIP: XHCI --- Cargo.toml | 1 + drivers | 2 +- filesystem/etc/pcid.toml | 7 +++++++ filesystem/home/user/minimal.toml | 21 +++++++++++++++++++++ mk/qemu.mk | 3 +++ mk/userspace/drivers.mk | 3 ++- 6 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 filesystem/home/user/minimal.toml diff --git a/Cargo.toml b/Cargo.toml index 5683e19..4ec2cc3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ members = [ "drivers/ps2d", "drivers/rtl8168d", "drivers/vesad", + "drivers/xhcid", "installer", "kernel", "programs/acid", diff --git a/drivers b/drivers index cc29946..778852f 160000 --- a/drivers +++ b/drivers @@ -1 +1 @@ -Subproject commit cc299464fc11e01649ad8a09b127397e68901b77 +Subproject commit 778852f92d835c17327819bde28c19db8096a4b1 diff --git a/filesystem/etc/pcid.toml b/filesystem/etc/pcid.toml index da177da..b68865e 100644 --- a/filesystem/etc/pcid.toml +++ b/filesystem/etc/pcid.toml @@ -11,3 +11,10 @@ class = 2 vendor = 4332 device = 33128 command = ["/sbin/rtl8168d", "$NAME", "$BAR2", "$IRQ"] + +[[drivers]] +name = "XHCI" +class = 12 +subclass = 3 +interface = 48 +command = ["/sbin/xhcid", "$NAME", "$BAR0", "$IRQ"] diff --git a/filesystem/home/user/minimal.toml b/filesystem/home/user/minimal.toml new file mode 100644 index 0000000..535dc4d --- /dev/null +++ b/filesystem/home/user/minimal.toml @@ -0,0 +1,21 @@ +# This is the default configuration file + +# General settings +[general] +# Do not prompt if settings are not defined +prompt = false + +# Package settings +[packages] +coreutils = {} +extrautils = {} +ion = {} + +# User settings +[users.root] +# Password is set to "password" +password = "$argon2i$m=4096,t=10,p=1$Tnc4UVV0N00$ML9LIOujd3nmAfkAwEcSTMPqakWUF0OUiLWrIy0nGLk" +uid = 0 +gid = 0 +name = "root" +home = "/root" diff --git a/mk/qemu.mk b/mk/qemu.mk index ef50bf7..c723bcb 100644 --- a/mk/qemu.mk +++ b/mk/qemu.mk @@ -17,6 +17,9 @@ endif ifeq ($(vga),no) QEMUFLAGS+=-nographic -vga none endif +ifneq ($(usb),no) + QEMUFLAGS+=-device nec-usb-xhci,id=xhci -device usb-tablet,bus=xhci.0 +endif ifeq ($(UNAME),Linux) ifneq ($(kvm),no) QEMUFLAGS+=-enable-kvm -cpu host diff --git a/mk/userspace/drivers.mk b/mk/userspace/drivers.mk index 122285f..b3d06bc 100644 --- a/mk/userspace/drivers.mk +++ b/mk/userspace/drivers.mk @@ -1,7 +1,8 @@ drivers: \ filesystem/sbin/pcid \ filesystem/sbin/e1000d \ - filesystem/sbin/rtl8168d + filesystem/sbin/rtl8168d \ + filesystem/sbin/xhcid initfs/bin/%: drivers/%/Cargo.toml drivers/%/src/** $(BUILD)/libstd.rlib mkdir -p initfs/bin From eb4b5a26218ea32f2f3275b236467bec09996288 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 11 Jan 2017 13:59:25 -0700 Subject: [PATCH 087/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index ed69fac..35c2297 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit ed69fac232744d1aff4fb02ba6be196c74e9d2f0 +Subproject commit 35c22977240597d656979fd5d9bdb25a755bb372 From 6a5acfd9a1291976b9ca66355124bdd576d9069c Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 12 Jan 2017 18:41:11 -0700 Subject: [PATCH 088/522] Fix issue with init script stdio failing on vga=no --- programs/init/src/main.rs | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/programs/init/src/main.rs b/programs/init/src/main.rs index 56aa80e..9c4c4d4 100644 --- a/programs/init/src/main.rs +++ b/programs/init/src/main.rs @@ -1,11 +1,26 @@ +#![deny(warnings)] + extern crate syscall; use std::env; -use std::fs::{File, read_dir}; -use std::io::{BufRead, BufReader, Result}; +use std::fs::{File, OpenOptions, read_dir}; +use std::io::{BufRead, BufReader, Error, Result}; +use std::os::unix::io::AsRawFd; use std::path::Path; use std::process::Command; +fn switch_stdio(stdio: &str) -> Result<()> { + let stdin = OpenOptions::new().read(true).open(stdio)?; + let stdout = OpenOptions::new().write(true).open(stdio)?; + let stderr = OpenOptions::new().write(true).open(stdio)?; + + syscall::dup2(stdin.as_raw_fd(), 0, &[]).map_err(|err| Error::from_raw_os_error(err.errno))?; + syscall::dup2(stdout.as_raw_fd(), 0, &[]).map_err(|err| Error::from_raw_os_error(err.errno))?; + syscall::dup2(stderr.as_raw_fd(), 0, &[]).map_err(|err| Error::from_raw_os_error(err.errno))?; + + Ok(()) +} + pub fn run(file: &Path) -> Result<()> { let file = File::open(file)?; let reader = BufReader::new(file); @@ -84,13 +99,9 @@ pub fn run(file: &Path) -> Result<()> { println!("init: failed to run.d: no argument"); }, "stdio" => if let Some(stdio) = args.next() { - let _ = syscall::close(2); - let _ = syscall::close(1); - let _ = syscall::close(0); - - let _ = syscall::open(&stdio, syscall::flag::O_RDWR); - let _ = syscall::open(&stdio, syscall::flag::O_RDWR); - let _ = syscall::open(&stdio, syscall::flag::O_RDWR); + if let Err(err) = switch_stdio(&stdio) { + println!("init: failed to switch stdio to '{}': {}", stdio, err); + } } else { println!("init: failed to set stdio: no argument"); }, From da62b38adcbb4d62cfbaa53d2c0a550b7eb05ad5 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 12 Jan 2017 19:13:38 -0700 Subject: [PATCH 089/522] Mistake in init using wrong fd in dup2, update userutils --- programs/init/src/main.rs | 4 ++-- programs/userutils | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/programs/init/src/main.rs b/programs/init/src/main.rs index 9c4c4d4..d4c3ebd 100644 --- a/programs/init/src/main.rs +++ b/programs/init/src/main.rs @@ -15,8 +15,8 @@ fn switch_stdio(stdio: &str) -> Result<()> { let stderr = OpenOptions::new().write(true).open(stdio)?; syscall::dup2(stdin.as_raw_fd(), 0, &[]).map_err(|err| Error::from_raw_os_error(err.errno))?; - syscall::dup2(stdout.as_raw_fd(), 0, &[]).map_err(|err| Error::from_raw_os_error(err.errno))?; - syscall::dup2(stderr.as_raw_fd(), 0, &[]).map_err(|err| Error::from_raw_os_error(err.errno))?; + syscall::dup2(stdout.as_raw_fd(), 1, &[]).map_err(|err| Error::from_raw_os_error(err.errno))?; + syscall::dup2(stderr.as_raw_fd(), 2, &[]).map_err(|err| Error::from_raw_os_error(err.errno))?; Ok(()) } diff --git a/programs/userutils b/programs/userutils index ccae9c0..2fdef17 160000 --- a/programs/userutils +++ b/programs/userutils @@ -1 +1 @@ -Subproject commit ccae9c0b0abb9b6d2708655bdd4ef2f25be42d67 +Subproject commit 2fdef17559bd25d7f6cd5c2a0a4d1b7897e0beaf From ae1abca0f57254c3d809c482cf90af564a29b0dd Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 12 Jan 2017 19:35:44 -0700 Subject: [PATCH 090/522] Use only one virtual terminal until init issue is fixed. Compile baduk, do not compile snake until issue is fixed --- filesystem/etc/init.d/20_orbital | 1 + filesystem/etc/init.d/{20_console => 30_console} | 2 +- filesystem/etc/init.d/30_orbital | 1 - filesystem/etc/init.d/40_serial | 1 - initfs/etc/init.rc | 2 +- mk/userspace/games.mk | 6 ++++-- programs/games | 2 +- 7 files changed, 8 insertions(+), 7 deletions(-) create mode 100644 filesystem/etc/init.d/20_orbital rename filesystem/etc/init.d/{20_console => 30_console} (50%) delete mode 100644 filesystem/etc/init.d/30_orbital delete mode 100644 filesystem/etc/init.d/40_serial diff --git a/filesystem/etc/init.d/20_orbital b/filesystem/etc/init.d/20_orbital new file mode 100644 index 0000000..583ebd1 --- /dev/null +++ b/filesystem/etc/init.d/20_orbital @@ -0,0 +1 @@ +/sbin/orbital display:3/activate /ui/bin/orblogin /ui/bin/launcher diff --git a/filesystem/etc/init.d/20_console b/filesystem/etc/init.d/30_console similarity index 50% rename from filesystem/etc/init.d/20_console rename to filesystem/etc/init.d/30_console index ca6aeb0..c981568 100644 --- a/filesystem/etc/init.d/20_console +++ b/filesystem/etc/init.d/30_console @@ -1,2 +1,2 @@ getty display:2 -getty display:3 +getty debug: -J diff --git a/filesystem/etc/init.d/30_orbital b/filesystem/etc/init.d/30_orbital deleted file mode 100644 index b1e505b..0000000 --- a/filesystem/etc/init.d/30_orbital +++ /dev/null @@ -1 +0,0 @@ -/sbin/orbital display:4/activate /ui/bin/orblogin /ui/bin/launcher diff --git a/filesystem/etc/init.d/40_serial b/filesystem/etc/init.d/40_serial deleted file mode 100644 index 730fa10..0000000 --- a/filesystem/etc/init.d/40_serial +++ /dev/null @@ -1 +0,0 @@ -getty debug: -J diff --git a/initfs/etc/init.rc b/initfs/etc/init.rc index 97b35c2..bd7548b 100644 --- a/initfs/etc/init.rc +++ b/initfs/etc/init.rc @@ -1,5 +1,5 @@ export PATH initfs:/bin -vesad T T T G +vesad T T G stdio display:1 ps2d pcid /etc/pcid.toml diff --git a/mk/userspace/games.mk b/mk/userspace/games.mk index ae0dda7..e65b00a 100644 --- a/mk/userspace/games.mk +++ b/mk/userspace/games.mk @@ -1,9 +1,11 @@ games: \ + filesystem/bin/baduk \ filesystem/bin/ice \ filesystem/bin/minesweeper \ filesystem/bin/reblox \ - filesystem/bin/rusthello \ - filesystem/bin/snake + filesystem/bin/rusthello + +#filesystem/bin/snake filesystem/bin/%: programs/games/Cargo.toml programs/games/src/%/**.rs $(BUILD)/libstd.rlib mkdir -p filesystem/bin diff --git a/programs/games b/programs/games index 3478af8..c4984dc 160000 --- a/programs/games +++ b/programs/games @@ -1 +1 @@ -Subproject commit 3478af86d9bb413dc918ead3029eff65bf44e099 +Subproject commit c4984dc276bf5776f544b5f9f6996330e3ca4b51 From 08a05a8afa04a6f41bd97801039fda129b84d3af Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 13 Jan 2017 09:42:43 -0700 Subject: [PATCH 091/522] More installer config to more logical location --- filesystem/{home/user => etc/installer}/minimal.toml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename filesystem/{home/user => etc/installer}/minimal.toml (100%) diff --git a/filesystem/home/user/minimal.toml b/filesystem/etc/installer/minimal.toml similarity index 100% rename from filesystem/home/user/minimal.toml rename to filesystem/etc/installer/minimal.toml From 032b012dbb7f02e006b59009d2850ac2dc6662ab Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 13 Jan 2017 09:43:54 -0700 Subject: [PATCH 092/522] Add cookbook submodule --- .gitmodules | 3 +++ cookbook | 1 + 2 files changed, 4 insertions(+) create mode 160000 cookbook diff --git a/.gitmodules b/.gitmodules index f706dda2..c3e65f6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -70,3 +70,6 @@ [submodule "isolinux"] path = isolinux url = https://github.com/redox-os/isolinux.git +[submodule "cookbook"] + path = cookbook + url = https://github.com/redox-os/cookbook.git diff --git a/cookbook b/cookbook new file mode 160000 index 0000000..5356f08 --- /dev/null +++ b/cookbook @@ -0,0 +1 @@ +Subproject commit 5356f081e41ff85285b3208bc3aeb86b4447acfe From 8a50c2451a9aff6ad01076b8fa597dcc829e3c34 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 13 Jan 2017 11:08:34 -0700 Subject: [PATCH 093/522] Update redoxfs --- schemes/redoxfs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schemes/redoxfs b/schemes/redoxfs index 5ab8c05..665120f 160000 --- a/schemes/redoxfs +++ b/schemes/redoxfs @@ -1 +1 @@ -Subproject commit 5ab8c050d86d73bc8d6b57f6a4a5ac2435fb5876 +Subproject commit 665120f0639d367d8f254a1df407bfaf65f5ef47 From 279451c3038c080c64b73ecec2d947d83663d1db Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 13 Jan 2017 11:08:44 -0700 Subject: [PATCH 094/522] Add qemu_extra_no_build target --- mk/qemu.mk | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/mk/qemu.mk b/mk/qemu.mk index c723bcb..940b27e 100644 --- a/mk/qemu.mk +++ b/mk/qemu.mk @@ -31,12 +31,16 @@ endif qemu: build/harddrive.bin $(QEMU) $(QEMUFLAGS) -drive file=$<,format=raw +qemu_no_build: + $(QEMU) $(QEMUFLAGS) -drive file=build/harddrive.bin,format=raw + qemu_extra: build/harddrive.bin if [ ! -e build/extra.bin ]; then dd if=/dev/zero of=build/extra.bin bs=1048576 count=1024; fi $(QEMU) $(QEMUFLAGS) -drive file=$<,format=raw -drive file=build/extra.bin,format=raw -qemu_no_build: - $(QEMU) $(QEMUFLAGS) -drive file=build/harddrive.bin,format=raw +qemu_extra_no_build: + if [ ! -e build/extra.bin ]; then dd if=/dev/zero of=build/extra.bin bs=1048576 count=1024; fi + $(QEMU) $(QEMUFLAGS) -drive file=$<,format=raw -drive file=build/extra.bin,format=raw qemu_live: build/livedisk.bin $(QEMU) $(QEMUFLAGS) -device usb-ehci,id=flash_bus -drive id=flash_drive,file=$<,format=raw,if=none -device usb-storage,drive=flash_drive,bus=flash_bus.0 From 343375758759623c6344e84fb9471789707a5a6a Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 13 Jan 2017 11:08:59 -0700 Subject: [PATCH 095/522] Update cookbook --- cookbook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook b/cookbook index 5356f08..9befc60 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 5356f081e41ff85285b3208bc3aeb86b4447acfe +Subproject commit 9befc6053eb133d045cdab81c1a0b11651b066eb From 8a6d99e3f45203b3a4fa513f4826ccf4a81ebb8f Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 13 Jan 2017 14:39:21 -0700 Subject: [PATCH 096/522] Update to use upstream --- programs/netutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/netutils b/programs/netutils index d098d98..b4a1d37 160000 --- a/programs/netutils +++ b/programs/netutils @@ -1 +1 @@ -Subproject commit d098d9857177e06762bd1a42bc8d15842822cd37 +Subproject commit b4a1d3731d915e32c4f0c4bf844b6cc14e0097d9 From fc0e54ac680fde318b303b903d5de1a6502245b0 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 13 Jan 2017 15:10:43 -0700 Subject: [PATCH 097/522] Specify crates.io versions, update rust, cleanup modules --- .gitmodules | 3 --- Cargo.toml | 4 +--- drivers | 2 +- kernel | 2 +- programs/contain/Cargo.toml | 2 +- programs/coreutils | 2 +- programs/extrautils | 2 +- programs/init/Cargo.toml | 2 +- programs/orbutils | 2 +- programs/userutils | 2 +- rust | 2 +- schemes/ethernetd/Cargo.toml | 2 +- schemes/example/Cargo.toml | 6 ------ schemes/example/src/main.rs | 39 ------------------------------------ schemes/ipd/Cargo.toml | 2 +- schemes/orbital | 2 +- schemes/ptyd/Cargo.toml | 2 +- schemes/randd/Cargo.toml | 4 ++-- schemes/tcpd/Cargo.toml | 2 +- schemes/udpd/Cargo.toml | 2 +- syscall | 1 - 21 files changed, 18 insertions(+), 69 deletions(-) delete mode 100644 schemes/example/Cargo.toml delete mode 100644 schemes/example/src/main.rs delete mode 160000 syscall diff --git a/.gitmodules b/.gitmodules index c3e65f6..c22c07c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -43,9 +43,6 @@ [submodule "installer"] path = installer url = https://github.com/redox-os/installer.git -[submodule "syscall"] - path = syscall - url = https://github.com/redox-os/syscall.git [submodule "crates/docgen"] path = crates/docgen url = https://github.com/redox-os/docgen.git diff --git a/Cargo.toml b/Cargo.toml index 4ec2cc3..f191a7f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,13 +26,11 @@ members = [ "programs/tar", "programs/userutils", "schemes/ethernetd", - "schemes/example", "schemes/ipd", "schemes/orbital", "schemes/ptyd", "schemes/randd", "schemes/redoxfs", "schemes/tcpd", - "schemes/udpd", - "syscall" + "schemes/udpd" ] diff --git a/drivers b/drivers index 778852f..4bb2299 160000 --- a/drivers +++ b/drivers @@ -1 +1 @@ -Subproject commit 778852f92d835c17327819bde28c19db8096a4b1 +Subproject commit 4bb229959e7c662a0686c7986f5ad28c8fb4de12 diff --git a/kernel b/kernel index 35c2297..04d9d6b 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 35c22977240597d656979fd5d9bdb25a755bb372 +Subproject commit 04d9d6b40a8fbd5e21200dabfdaa128a4c809727 diff --git a/programs/contain/Cargo.toml b/programs/contain/Cargo.toml index baf2a4e..a11d6d0 100644 --- a/programs/contain/Cargo.toml +++ b/programs/contain/Cargo.toml @@ -3,4 +3,4 @@ name = "contain" version = "0.1.0" [dependencies] -redox_syscall = { git = "https://github.com/redox-os/syscall.git" } +redox_syscall = "0.1" diff --git a/programs/coreutils b/programs/coreutils index 30dae30..86464b0 160000 --- a/programs/coreutils +++ b/programs/coreutils @@ -1 +1 @@ -Subproject commit 30dae30ee0c4d4628f08b04db9d7f986cc975763 +Subproject commit 86464b0b198c490b8e958c587e179c7aa8f24065 diff --git a/programs/extrautils b/programs/extrautils index f371a06..2a770bd 160000 --- a/programs/extrautils +++ b/programs/extrautils @@ -1 +1 @@ -Subproject commit f371a0684e816d8ebf12446c3f6c799bd276efa6 +Subproject commit 2a770bdf6b2979a89e7b128830083fa1d049357a diff --git a/programs/init/Cargo.toml b/programs/init/Cargo.toml index 0ababa4..955abf7 100644 --- a/programs/init/Cargo.toml +++ b/programs/init/Cargo.toml @@ -3,4 +3,4 @@ name = "init" version = "0.1.0" [dependencies] -redox_syscall = { git = "https://github.com/redox-os/syscall.git" } +redox_syscall = "0.1" diff --git a/programs/orbutils b/programs/orbutils index cf1e1f8..44027c2 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit cf1e1f8e6406e9b01a2c62e46260e82a7aa33395 +Subproject commit 44027c23b7cb58d03e3408ff7a87a76d57a47ff8 diff --git a/programs/userutils b/programs/userutils index 2fdef17..2011976 160000 --- a/programs/userutils +++ b/programs/userutils @@ -1 +1 @@ -Subproject commit 2fdef17559bd25d7f6cd5c2a0a4d1b7897e0beaf +Subproject commit 2011976381b9eb1264ae90218106fa36a19427c8 diff --git a/rust b/rust index 82a3f9f..ca2ade1 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 82a3f9fbecd3b4cfac2ac4821ce330227dbdedb0 +Subproject commit ca2ade1d36d0b33d60ff1973ab6c8f3b09bc4c41 diff --git a/schemes/ethernetd/Cargo.toml b/schemes/ethernetd/Cargo.toml index c99cae5..835b07e 100644 --- a/schemes/ethernetd/Cargo.toml +++ b/schemes/ethernetd/Cargo.toml @@ -5,4 +5,4 @@ version = "0.1.0" [dependencies] netutils = { git = "https://github.com/redox-os/netutils.git" } redox_event = { git = "https://github.com/redox-os/event.git" } -redox_syscall = { git = "https://github.com/redox-os/syscall.git" } +redox_syscall = "0.1" diff --git a/schemes/example/Cargo.toml b/schemes/example/Cargo.toml deleted file mode 100644 index 9ddf8dd..0000000 --- a/schemes/example/Cargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "example" -version = "0.1.0" - -[dependencies] -redox_syscall = { git = "https://github.com/redox-os/syscall.git" } diff --git a/schemes/example/src/main.rs b/schemes/example/src/main.rs deleted file mode 100644 index 1ba8d59..0000000 --- a/schemes/example/src/main.rs +++ /dev/null @@ -1,39 +0,0 @@ -extern crate syscall; - -use std::fs::File; -use std::io::{Read, Write}; -use std::str; - -use syscall::{Packet, Result, Scheme}; - -struct ExampleScheme; - -impl Scheme for ExampleScheme { - fn open(&self, path: &[u8], _flags: usize, uid: u32, gid: u32) -> Result { - println!("{} from {}:{}", unsafe { str::from_utf8_unchecked(path) }, uid, gid); - Ok(0) - } - - fn dup(&self, file: usize, _buf: &[u8]) -> Result { - Ok(file) - } - - fn close(&self, _file: usize) -> Result { - Ok(0) - } -} - -fn main(){ - // Daemonize - if unsafe { syscall::clone(0).unwrap() } == 0 { - let mut socket = File::create(":example").expect("example: failed to create example scheme"); - let scheme = ExampleScheme; - loop { - let mut packet = Packet::default(); - socket.read(&mut packet).expect("example: failed to read events from example scheme"); - println!("{:?}", packet); - scheme.handle(&mut packet); - socket.write(&packet).expect("example: failed to write responses to example scheme"); - } - } -} diff --git a/schemes/ipd/Cargo.toml b/schemes/ipd/Cargo.toml index 16f947a..3192911 100644 --- a/schemes/ipd/Cargo.toml +++ b/schemes/ipd/Cargo.toml @@ -5,4 +5,4 @@ version = "0.1.0" [dependencies] netutils = { git = "https://github.com/redox-os/netutils.git" } redox_event = { git = "https://github.com/redox-os/event.git" } -redox_syscall = { git = "https://github.com/redox-os/syscall.git" } +redox_syscall = "0.1" diff --git a/schemes/orbital b/schemes/orbital index baa69a2..c70e11f 160000 --- a/schemes/orbital +++ b/schemes/orbital @@ -1 +1 @@ -Subproject commit baa69a2fa69b827645e59abc389f5a162d76f035 +Subproject commit c70e11f9e94a0bf445aa1c96243a514ee5b46d3e diff --git a/schemes/ptyd/Cargo.toml b/schemes/ptyd/Cargo.toml index 69b4365..093da85 100644 --- a/schemes/ptyd/Cargo.toml +++ b/schemes/ptyd/Cargo.toml @@ -3,4 +3,4 @@ name = "ptyd" version = "0.1.0" [dependencies] -redox_syscall = { git = "https://github.com/redox-os/syscall.git" } +redox_syscall = "0.1" diff --git a/schemes/randd/Cargo.toml b/schemes/randd/Cargo.toml index 2222cf5..3b7ebf2 100644 --- a/schemes/randd/Cargo.toml +++ b/schemes/randd/Cargo.toml @@ -3,5 +3,5 @@ name = "randd" version = "0.1.0" [dependencies] -raw-cpuid = "2.*" -redox_syscall = { git = "https://github.com/redox-os/syscall.git" } +raw-cpuid = "2.0" +redox_syscall = "0.1" diff --git a/schemes/tcpd/Cargo.toml b/schemes/tcpd/Cargo.toml index 8d9c55f..f756ee2 100644 --- a/schemes/tcpd/Cargo.toml +++ b/schemes/tcpd/Cargo.toml @@ -6,4 +6,4 @@ version = "0.1.0" netutils = { git = "https://github.com/redox-os/netutils.git" } rand = "0.3" redox_event = { git = "https://github.com/redox-os/event.git" } -redox_syscall = { git = "https://github.com/redox-os/syscall.git" } +redox_syscall = "0.1" diff --git a/schemes/udpd/Cargo.toml b/schemes/udpd/Cargo.toml index b33c74e..d7dc3e3 100644 --- a/schemes/udpd/Cargo.toml +++ b/schemes/udpd/Cargo.toml @@ -6,4 +6,4 @@ version = "0.1.0" netutils = { git = "https://github.com/redox-os/netutils.git" } rand = "0.3" redox_event = { git = "https://github.com/redox-os/event.git" } -redox_syscall = { git = "https://github.com/redox-os/syscall.git" } +redox_syscall = "0.1" diff --git a/syscall b/syscall deleted file mode 160000 index 6188e4d..0000000 --- a/syscall +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6188e4d040c14d221aebebb942d424edada47671 From 7dfd0f89944a14d844cd9494ddad303ed169b4cc Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 13 Jan 2017 15:13:26 -0700 Subject: [PATCH 098/522] Update pkgutils --- programs/pkgutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/pkgutils b/programs/pkgutils index a196bd3..95e846a 160000 --- a/programs/pkgutils +++ b/programs/pkgutils @@ -1 +1 @@ -Subproject commit a196bd36ff9f95025b95f5e68c4671cc64c14b09 +Subproject commit 95e846a59a6f07650e532fe43978eba894cc75c4 From 0770946254467d2856fcc175d94a800984d7bd0d Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 13 Jan 2017 15:14:50 -0700 Subject: [PATCH 099/522] Update pkgutils --- programs/pkgutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/pkgutils b/programs/pkgutils index 95e846a..e612859 160000 --- a/programs/pkgutils +++ b/programs/pkgutils @@ -1 +1 @@ -Subproject commit 95e846a59a6f07650e532fe43978eba894cc75c4 +Subproject commit e6128591b27924718d727a5b6c5da495ba066111 From 89691053c924b355ccfeb3a9da95587321dee090 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 13 Jan 2017 15:53:24 -0700 Subject: [PATCH 100/522] Fix pkgutils target --- mk/userspace/pkgutils.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mk/userspace/pkgutils.mk b/mk/userspace/pkgutils.mk index c2fad81..7bf80cc 100644 --- a/mk/userspace/pkgutils.mk +++ b/mk/userspace/pkgutils.mk @@ -1,7 +1,7 @@ pkgutils: \ filesystem/bin/pkg -filesystem/bin/%: programs/pkgutils/Cargo.toml programs/pkgutils/src/%/**.rs $(BUILD)/libstd.rlib +filesystem/bin/%: programs/pkgutils/Cargo.toml programs/pkgutils/src/bin/%.rs $(BUILD)/libstd.rlib mkdir -p filesystem/bin $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ $(STRIP) $@ From e9a96c545f7a2704f2032c5d0a57916966959af4 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 13 Jan 2017 15:53:29 -0700 Subject: [PATCH 101/522] Update Rust --- rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust b/rust index ca2ade1..b10e061 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit ca2ade1d36d0b33d60ff1973ab6c8f3b09bc4c41 +Subproject commit b10e06166ef8a71edf5cf1d61a94b6639880eb05 From db4b43d10f6fb30b6f495863c5463d13cc4f3158 Mon Sep 17 00:00:00 2001 From: xTibor Date: Mon, 16 Jan 2017 00:22:29 +0100 Subject: [PATCH 102/522] Implement whoami --- mk/userspace/userutils.mk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mk/userspace/userutils.mk b/mk/userspace/userutils.mk index 397ae4a..9b144e0 100644 --- a/mk/userspace/userutils.mk +++ b/mk/userspace/userutils.mk @@ -4,7 +4,8 @@ userutils: \ filesystem/bin/login \ filesystem/bin/passwd \ filesystem/bin/su \ - filesystem/bin/sudo + filesystem/bin/sudo \ + filesystem/bin/whoami filesystem/bin/%: programs/userutils/Cargo.toml programs/userutils/src/bin/%.rs $(BUILD)/libstd.rlib mkdir -p filesystem/bin From 98ce48ebe42343898aa8da97f14e35ccf51a8785 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 16 Jan 2017 10:07:37 -0700 Subject: [PATCH 103/522] Update submodules --- cookbook | 2 +- programs/coreutils | 2 +- programs/userutils | 2 +- rust | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cookbook b/cookbook index 9befc60..4dc1cc2 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 9befc6053eb133d045cdab81c1a0b11651b066eb +Subproject commit 4dc1cc23ba0d5d4cd2f2ffdf46aa28646c56e5c3 diff --git a/programs/coreutils b/programs/coreutils index 86464b0..faea312 160000 --- a/programs/coreutils +++ b/programs/coreutils @@ -1 +1 @@ -Subproject commit 86464b0b198c490b8e958c587e179c7aa8f24065 +Subproject commit faea31206a403eb1f3e1b5eea272019f3e25fcfb diff --git a/programs/userutils b/programs/userutils index 2011976..bb463a8 160000 --- a/programs/userutils +++ b/programs/userutils @@ -1 +1 @@ -Subproject commit 2011976381b9eb1264ae90218106fa36a19427c8 +Subproject commit bb463a8f02f359545041fe1fed677e2a7e6612f5 diff --git a/rust b/rust index b10e061..47410b2 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit b10e06166ef8a71edf5cf1d61a94b6639880eb05 +Subproject commit 47410b23aa85255ae2dc021498a2e54806f4bb0a From ca3043d9912d70f458bd58f632ed0fe391852eef Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 16 Jan 2017 10:10:56 -0700 Subject: [PATCH 104/522] Move targets into kernel repo --- kernel | 2 +- mk/config.mk | 2 +- targets/arm-unknown-none.json | 25 ------------------------- targets/x86_64-unknown-none.json | 25 ------------------------- 4 files changed, 2 insertions(+), 52 deletions(-) delete mode 100644 targets/arm-unknown-none.json delete mode 100644 targets/x86_64-unknown-none.json diff --git a/kernel b/kernel index 04d9d6b..0d3aa23 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 04d9d6b40a8fbd5e21200dabfdaa128a4c809727 +Subproject commit 0d3aa234ff5243b72b6b4e8eee8c0837c5848972 diff --git a/mk/config.mk b/mk/config.mk index acc8921..b8e049a 100644 --- a/mk/config.mk +++ b/mk/config.mk @@ -3,7 +3,7 @@ ARCH?=x86_64 # Automatic variables ROOT=$(PWD) -export RUST_TARGET_PATH=$(ROOT)/targets +export RUST_TARGET_PATH=$(ROOT)/kernel/targets export CC=$(ROOT)/libc-artifacts/gcc.sh export CFLAGS=-fno-stack-protector -U_FORTIFY_SOURCE diff --git a/targets/arm-unknown-none.json b/targets/arm-unknown-none.json deleted file mode 100644 index 292fa64..0000000 --- a/targets/arm-unknown-none.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "llvm-target": "arm-unknown-none", - "target-endian": "little", - "target-pointer-width": "32", - "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64", - "arch": "arm", - "os": "none", - "env": "", - "vendor": "unknown", - "target-family": "redox", - "pre-link-args": ["-nostdlib", "-static"], - "features": "+soft-float", - "dynamic-linking": false, - "executables": false, - "relocation-model": "static", - "code-model": "kernel", - "disable-redzone": true, - "eliminate-frame-pointer": false, - "exe-suffix": "", - "has-rpath": false, - "no-compiler-rt": true, - "no-default-libraries": true, - "position-independent-executables": false, - "has-elf-tls": true -} diff --git a/targets/x86_64-unknown-none.json b/targets/x86_64-unknown-none.json deleted file mode 100644 index 10ff541..0000000 --- a/targets/x86_64-unknown-none.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "llvm-target": "x86_64-unknown-none", - "target-endian": "little", - "target-pointer-width": "64", - "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128", - "arch": "x86_64", - "os": "none", - "env": "", - "vendor": "unknown", - "target-family": "redox", - "pre-link-args": ["-m64", "-nostdlib", "-static"], - "features": "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float", - "dynamic-linking": false, - "executables": false, - "relocation-model": "pic", - "code-model": "kernel", - "disable-redzone": true, - "eliminate-frame-pointer": false, - "exe-suffix": "", - "has-rpath": false, - "no-compiler-rt": true, - "no-default-libraries": true, - "position-independent-executables": false, - "has-elf-tls": true -} From b50adc425f7d32bd944c4fe5bad51568ab82a482 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 16 Jan 2017 10:23:52 -0700 Subject: [PATCH 105/522] Update bootstrap.sh --- bootstrap.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bootstrap.sh b/bootstrap.sh index dc24ee0..7170a3d 100644 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -154,7 +154,7 @@ archLinux() fi if [ "$1" == "qemu" ]; then - if [ -z "$(which qemu-system-i386)" ]; then + if [ -z "$(which qemu-system-x86_64)" ]; then echo "Installing QEMU..." sudo pacman -S qemu else @@ -180,7 +180,7 @@ ubuntu() echo "Installing required packages..." sudo "$2" install build-essential libc6-dev-i386 nasm curl file git libfuse-dev if [ "$1" == "qemu" ]; then - if [ -z "$(which qemu-system-i386)" ]; then + if [ -z "$(which qemu-system-x86_64)" ]; then echo "Installing QEMU..." sudo "$2" install qemu-system-x86 qemu-kvm else @@ -209,7 +209,7 @@ fedora() sudo dnf install git-all fi if [ "$1" == "qemu" ]; then - if [ -z "$(which qemu-system-i386)" ]; then + if [ -z "$(which qemu-system-x86_64)" ]; then echo "Installing QEMU..." sudo dnf install qemu-system-x86 qemu-kvm else @@ -246,7 +246,7 @@ suse() zypper install git fi if [ "$1" == "qemu" ]; then - if [ -z "$(which qemu-system-i386)" ]; then + if [ -z "$(which qemu-system-x86_64)" ]; then echo "Installing QEMU..." sudo zypper install qemu-x86 qemu-kvm else @@ -284,7 +284,7 @@ gentoo() echo "Installing fuse..." sudo emerge sys-fs/fuse if [ "$2" == "qemu" ]; then - if [ -z "$(which qemu-system-i386)" ]; then + if [ -z "$(which qemu-system-x86_64)" ]; then echo "Please install QEMU and re-run this script" echo "Step1. Add QEMU_SOFTMMU_TARGETS=\"i386\" to /etc/portage/make.conf" echo "Step2. Execute \"sudo emerge app-emulation/qemu\"" @@ -313,7 +313,7 @@ solus() echo "Installing fuse..." sudo eopkg it fuse-devel if [ "$1" == "qemu" ]; then - if [ -z "$(which qemu-system-i386)" ]; then + if [ -z "$(which qemu-system-x86_64)" ]; then sudo eopkg it qemu else echo "QEMU already installed!" From 24168a9fd78b05e2d97104c1a7afa12caf61d7f7 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 16 Jan 2017 10:32:25 -0700 Subject: [PATCH 106/522] Update and move docgen --- .gitmodules | 2 +- crates/docgen | 1 - docgen | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) delete mode 160000 crates/docgen create mode 160000 docgen diff --git a/.gitmodules b/.gitmodules index c22c07c..b3282f5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -44,7 +44,7 @@ path = installer url = https://github.com/redox-os/installer.git [submodule "crates/docgen"] - path = crates/docgen + path = docgen url = https://github.com/redox-os/docgen.git [submodule "programs/binutils"] path = programs/binutils diff --git a/crates/docgen b/crates/docgen deleted file mode 160000 index d2e0e0d..0000000 --- a/crates/docgen +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d2e0e0d24006628609fb5d77b60f0a83299f4937 diff --git a/docgen b/docgen new file mode 160000 index 0000000..52fb886 --- /dev/null +++ b/docgen @@ -0,0 +1 @@ +Subproject commit 52fb8863efdd0862b2439f87faff2457b43cac62 From 58f02984ca6ec0821906eb53f5edc9756b508f7d Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 16 Jan 2017 10:33:09 -0700 Subject: [PATCH 107/522] Update and move docgen --- .gitmodules | 2 +- Cargo.toml | 2 +- mk/doc.mk | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.gitmodules b/.gitmodules index b3282f5..9cbca81 100644 --- a/.gitmodules +++ b/.gitmodules @@ -43,7 +43,7 @@ [submodule "installer"] path = installer url = https://github.com/redox-os/installer.git -[submodule "crates/docgen"] +[submodule "docgen"] path = docgen url = https://github.com/redox-os/docgen.git [submodule "programs/binutils"] diff --git a/Cargo.toml b/Cargo.toml index f191a7f..1201b64 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [workspace] members = [ - "crates/docgen", + "docgen", "drivers/ahcid", "drivers/bgad", "drivers/e1000d", diff --git a/mk/doc.mk b/mk/doc.mk index 2cb7bfd..78371f7 100644 --- a/mk/doc.mk +++ b/mk/doc.mk @@ -5,9 +5,9 @@ doc: $(KBUILD)/libkernel.a $(BUILD)/libstd.rlib FORCE ref: FORCE rm -rf filesystem/ref/ mkdir -p filesystem/ref/ - #cargo run --manifest-path crates/docgen/Cargo.toml -- programs/binutils/src/bin/ filesystem/ref/ - cargo run --manifest-path crates/docgen/Cargo.toml -- programs/coreutils/src/bin/ filesystem/ref/ - cargo run --manifest-path crates/docgen/Cargo.toml -- programs/extrautils/src/bin/ filesystem/ref/ - cargo run --manifest-path crates/docgen/Cargo.toml -- programs/netutils/src/ filesystem/ref/ - cargo run --manifest-path crates/docgen/Cargo.toml -- programs/pkgutils/src/ filesystem/ref/ - cargo run --manifest-path crates/docgen/Cargo.toml -- programs/userutils/src/ filesystem/ref/ + #cargo run --manifest-path docgen/Cargo.toml -- programs/binutils/src/bin/ filesystem/ref/ + cargo run --manifest-path docgen/Cargo.toml -- programs/coreutils/src/bin/ filesystem/ref/ + cargo run --manifest-path docgen/Cargo.toml -- programs/extrautils/src/bin/ filesystem/ref/ + cargo run --manifest-path docgen/Cargo.toml -- programs/netutils/src/ filesystem/ref/ + cargo run --manifest-path docgen/Cargo.toml -- programs/pkgutils/src/ filesystem/ref/ + cargo run --manifest-path docgen/Cargo.toml -- programs/userutils/src/ filesystem/ref/ From 686ac3646dbf8708c02631bd015deeca4037f44d Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 16 Jan 2017 21:19:59 -0700 Subject: [PATCH 108/522] Update coreutils, add which --- cookbook | 2 +- mk/userspace/coreutils.mk | 1 + programs/coreutils | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cookbook b/cookbook index 4dc1cc2..cfa1711 160000 --- a/cookbook +++ b/cookbook @@ -1 +1 @@ -Subproject commit 4dc1cc23ba0d5d4cd2f2ffdf46aa28646c56e5c3 +Subproject commit cfa1711df81e5d8b7ceff6c3ccc1d3870435177e diff --git a/mk/userspace/coreutils.mk b/mk/userspace/coreutils.mk index a75f307..117644c 100644 --- a/mk/userspace/coreutils.mk +++ b/mk/userspace/coreutils.mk @@ -34,6 +34,7 @@ coreutils: \ filesystem/bin/touch \ filesystem/bin/true \ filesystem/bin/wc \ + filesystem/bin/which \ filesystem/bin/yes #filesystem/bin/shutdown filesystem/bin/test diff --git a/programs/coreutils b/programs/coreutils index faea312..cdd9b8d 160000 --- a/programs/coreutils +++ b/programs/coreutils @@ -1 +1 @@ -Subproject commit faea31206a403eb1f3e1b5eea272019f3e25fcfb +Subproject commit cdd9b8dc7200dfcd382a2ba8debfc213e5180654 From 2664c14e23497c285f8dbeef9913c83062c947cd Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 20 Jan 2017 18:55:18 -0700 Subject: [PATCH 109/522] Update Rust --- rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust b/rust index 47410b2..0deea25 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 47410b23aa85255ae2dc021498a2e54806f4bb0a +Subproject commit 0deea257782a1d36239b6a8866e2382ef4185f48 From 2b10433193ada5cbebb563f81ad2a00a95bfc312 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 20 Jan 2017 19:08:01 -0700 Subject: [PATCH 110/522] Link native directory --- rustc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rustc.sh b/rustc.sh index ecd5588..3392968 100755 --- a/rustc.sh +++ b/rustc.sh @@ -18,4 +18,4 @@ for arg in "$@"; do fi done -RUST_BACKTRACE=1 exec rustc -L build/userspace "${args[@]}" +RUST_BACKTRACE=1 exec rustc -L build/userspace -L native=libc-artifacts/usr/lib "${args[@]}" From 0ad6620943c81fba44766d9cf5f71b0f55a730af Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 20 Jan 2017 19:13:01 -0700 Subject: [PATCH 111/522] Revert last commit --- rustc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rustc.sh b/rustc.sh index 3392968..ecd5588 100755 --- a/rustc.sh +++ b/rustc.sh @@ -18,4 +18,4 @@ for arg in "$@"; do fi done -RUST_BACKTRACE=1 exec rustc -L build/userspace -L native=libc-artifacts/usr/lib "${args[@]}" +RUST_BACKTRACE=1 exec rustc -L build/userspace "${args[@]}" From e894b206647c8a3f24cc4d1db30e94622c51e06e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 20 Jan 2017 19:14:08 -0700 Subject: [PATCH 112/522] Go back to master --- rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust b/rust index 0deea25..fe791d7 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 0deea257782a1d36239b6a8866e2382ef4185f48 +Subproject commit fe791d78866941da4996e14b43706fead913b447 From 5988210bf98fd55596f3cdc782871e1d31bd9dbd Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 21 Jan 2017 10:24:17 -0700 Subject: [PATCH 113/522] Move init to submodule --- .gitmodules | 3 + programs/init | 1 + programs/init/Cargo.toml | 6 -- programs/init/src/main.rs | 139 -------------------------------------- 4 files changed, 4 insertions(+), 145 deletions(-) create mode 160000 programs/init delete mode 100644 programs/init/Cargo.toml delete mode 100644 programs/init/src/main.rs diff --git a/.gitmodules b/.gitmodules index 9cbca81..8d3eafd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -70,3 +70,6 @@ [submodule "cookbook"] path = cookbook url = https://github.com/redox-os/cookbook.git +[submodule "programs/init"] + path = programs/init + url = https://github.com/redox-os/init.git diff --git a/programs/init b/programs/init new file mode 160000 index 0000000..1b684e2 --- /dev/null +++ b/programs/init @@ -0,0 +1 @@ +Subproject commit 1b684e24064c911705112ecc9a92a7f5e17c0418 diff --git a/programs/init/Cargo.toml b/programs/init/Cargo.toml deleted file mode 100644 index 955abf7..0000000 --- a/programs/init/Cargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "init" -version = "0.1.0" - -[dependencies] -redox_syscall = "0.1" diff --git a/programs/init/src/main.rs b/programs/init/src/main.rs deleted file mode 100644 index d4c3ebd..0000000 --- a/programs/init/src/main.rs +++ /dev/null @@ -1,139 +0,0 @@ -#![deny(warnings)] - -extern crate syscall; - -use std::env; -use std::fs::{File, OpenOptions, read_dir}; -use std::io::{BufRead, BufReader, Error, Result}; -use std::os::unix::io::AsRawFd; -use std::path::Path; -use std::process::Command; - -fn switch_stdio(stdio: &str) -> Result<()> { - let stdin = OpenOptions::new().read(true).open(stdio)?; - let stdout = OpenOptions::new().write(true).open(stdio)?; - let stderr = OpenOptions::new().write(true).open(stdio)?; - - syscall::dup2(stdin.as_raw_fd(), 0, &[]).map_err(|err| Error::from_raw_os_error(err.errno))?; - syscall::dup2(stdout.as_raw_fd(), 1, &[]).map_err(|err| Error::from_raw_os_error(err.errno))?; - syscall::dup2(stderr.as_raw_fd(), 2, &[]).map_err(|err| Error::from_raw_os_error(err.errno))?; - - Ok(()) -} - -pub fn run(file: &Path) -> Result<()> { - let file = File::open(file)?; - let reader = BufReader::new(file); - - for line_result in reader.lines() { - let line = line_result?; - let line = line.trim(); - if ! line.is_empty() && ! line.starts_with('#') { - let mut args = line.split(' '); - if let Some(cmd) = args.next() { - match cmd { - "cd" => if let Some(dir) = args.next() { - if let Err(err) = env::set_current_dir(dir) { - println!("init: failed to cd to '{}': {}", dir, err); - } - } else { - println!("init: failed to cd: no argument"); - }, - "echo" => { - if let Some(arg) = args.next() { - print!("{}", arg); - } - for arg in args { - print!(" {}", arg); - } - print!("\n"); - }, - "export" => if let Some(var) = args.next() { - let mut value = String::new(); - if let Some(arg) = args.next() { - value.push_str(&arg); - } - for arg in args { - value.push(' '); - value.push_str(&arg); - } - env::set_var(var, value); - } else { - println!("init: failed to export: no argument"); - }, - "run" => if let Some(new_file) = args.next() { - if let Err(err) = run(&Path::new(new_file)) { - println!("init: failed to run '{}': {}", new_file, err); - } - } else { - println!("init: failed to run: no argument"); - }, - "run.d" => if let Some(new_dir) = args.next() { - match read_dir(new_dir) { - Ok(list) => { - let mut entries = vec![]; - for entry_res in list { - match entry_res { - Ok(entry) => { - entries.push(entry.path()); - }, - Err(err) => { - println!("init: failed to run.d: '{}': {}", new_dir, err); - } - } - } - - entries.sort(); - - for entry in entries { - if let Err(err) = run(&entry) { - println!("init: failed to run '{}': {}", entry.display(), err); - } - } - }, - Err(err) => { - println!("init: failed to run.d: '{}': {}", new_dir, err); - } - } - } else { - println!("init: failed to run.d: no argument"); - }, - "stdio" => if let Some(stdio) = args.next() { - if let Err(err) = switch_stdio(&stdio) { - println!("init: failed to switch stdio to '{}': {}", stdio, err); - } - } else { - println!("init: failed to set stdio: no argument"); - }, - _ => { - let mut command = Command::new(cmd); - for arg in args { - command.arg(arg); - } - - match command.spawn() { - Ok(mut child) => match child.wait() { - Ok(_status) => (), //println!("init: waited for {}: {:?}", line, status.code()), - Err(err) => println!("init: failed to wait for '{}': {}", line, err) - }, - Err(err) => println!("init: failed to execute '{}': {}", line, err) - } - } - } - } - } - } - - Ok(()) -} - -pub fn main() { - if let Err(err) = run(&Path::new("initfs:etc/init.rc")) { - println!("init: failed to run initfs:etc/init.rc: {}", err); - } - - loop { - let mut status = 0; - syscall::waitpid(0, &mut status, 0).unwrap(); - } -} From aeac3baa48cf0afb6629b257cab6fd67950d9e5c Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 25 Jan 2017 15:17:26 -0700 Subject: [PATCH 114/522] Update submodules --- drivers | 2 +- kernel | 2 +- programs/coreutils | 2 +- rust | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers b/drivers index 4bb2299..911e20c 160000 --- a/drivers +++ b/drivers @@ -1 +1 @@ -Subproject commit 4bb229959e7c662a0686c7986f5ad28c8fb4de12 +Subproject commit 911e20c177adddeb20ac9ea997e7e0c614b6d47a diff --git a/kernel b/kernel index 0d3aa23..be43673 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 0d3aa234ff5243b72b6b4e8eee8c0837c5848972 +Subproject commit be43673df68ec8e7e955f2991e94233e134234ca diff --git a/programs/coreutils b/programs/coreutils index cdd9b8d..330e6a7 160000 --- a/programs/coreutils +++ b/programs/coreutils @@ -1 +1 @@ -Subproject commit cdd9b8dc7200dfcd382a2ba8debfc213e5180654 +Subproject commit 330e6a7ec26640173107d4948c6cc77e457a431f diff --git a/rust b/rust index fe791d7..fc57e40 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit fe791d78866941da4996e14b43706fead913b447 +Subproject commit fc57e40ce703cb70a39249f5cfb661020a1549b6 From 7c76522a95b0fdfac3a97749e87e1e8a3ac4d7a3 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 26 Jan 2017 21:42:24 -0700 Subject: [PATCH 115/522] Orbutils update --- programs/orbutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/orbutils b/programs/orbutils index 44027c2..0625378 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 44027c23b7cb58d03e3408ff7a87a76d57a47ff8 +Subproject commit 0625378daaa3fab76626e997080399cab25ce4ee From 59d13bd2ea2b1b25ba7f7c2ad2656a1469ebe9f4 Mon Sep 17 00:00:00 2001 From: polymetric Date: Fri, 27 Jan 2017 16:12:32 -0500 Subject: [PATCH 116/522] README.md - minor consistency fixes - clarify and rewrite some statements - provide more quick info that wasn't implicit before on some items in the ecosystem - change tag "what-it-looks-like" to "screenshots" --- README.md | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index dbacc4b..97c5c22 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Please make sure you use the **latest nightly** of `rustc` before building (for ## Contents -* [What it looks like](#what-it-looks-like) +* [What it looks like](#screenshots) * [Ecosystem](#ecosystem) * [Help! Redox won't compile](#compile-help) * [Contributing to Redox](#contributing) @@ -24,7 +24,7 @@ Please make sure you use the **latest nightly** of `rustc` before building (for * [Quick Setup](#quick-setup) * [Manual Setup](#manual-setup) -## What it looks like +## What it looks like Redox Redox @@ -40,9 +40,9 @@ The ecosystem and software Redox OS provides is listed below. | Name (lexicographic order) | Maintainer |-----------------------------------------------------------------------------|--------------------------- -| [acid tests](https://github.com/redox-os/acid) | [**@jackpot51**](https://github.com/jackpot51) (co.: [**@ticki**](https://github.com/ticki), [**@nilset](https://github.com/nilset)) +| [acid (kernel integration tests)](https://github.com/redox-os/acid) | [**@jackpot51**](https://github.com/jackpot51) (co.: [**@ticki**](https://github.com/ticki), [**@nilset](https://github.com/nilset)) | [binutils](https://github.com/redox-os/binutils) | [**@ticki**](https://github.com/ticki) -| [bots (other internal bots)](https://github.com/redox-os/bots) | [**@ticki**](https://github.com/ticki) +| [bots (custom Mattermost bots)](https://github.com/redox-os/bots) | [**@ticki**](https://github.com/ticki) | [cookbook](https://github.com/redox-os/cookbook) | [**@jackpot51**](https://github.com/jackpot51) | [coreutils](https://github.com/redox-os/coreutils) | [**@ticki**](https://github.com/ticki) (co.: [**@stratact**](https://github.com/stratact)) | [extrautils](https://github.com/redox-os/extrautils) | [**@ticki**](https://github.com/ticki) @@ -51,23 +51,23 @@ The ecosystem and software Redox OS provides is listed below. | [kernel](https://github.com/redox-os/kernel) | [**@jackpot51**](https://github.com/jackpot51) | [libextra](https://github.com/redox-os/libextra) | [**@ticki**](https://github.com/ticki) | [libpager](https://github.com/redox-os/libpager) | [**@ticki**](https://github.com/ticki) -| [magnet (future package manager)](https://github.com/redox-os/magnet) | [**@ticki**](https://github.com/ticki) +| [Magnet (future package manager)](https://github.com/redox-os/magnet) | [**@ticki**](https://github.com/ticki) | [netutils](https://github.com/redox-os/netutils) | [**@jackpot51**](https://github.com/jackpot51) -| [orbclient](https://github.com/redox-os/orbclient) | [**@jackpot51**](https://github.com/jackpot51) +| [orbclient (orbital client)](https://github.com/redox-os/orbclient) | [**@jackpot51**](https://github.com/jackpot51) | [orbdata](https://github.com/redox-os/orbdata) | [**@jackpot51**](https://github.com/jackpot51) -| [orbital](https://github.com/redox-os/orbital) | [**@jackpot51**](https://github.com/jackpot51) -| [orbtk](https://github.com/redox-os/orbtk) | [**@stratact**](https://github.com/stratact) -| [orbutils](https://github.com/redox-os/orbutils) | [**@jackpot51**](https://github.com/jackpot51) +| [Orbital (windowing and compositing system](https://github.com/redox-os/orbital) | [**@jackpot51**](https://github.com/jackpot51) +| [orbtk (orbital toolkit)](https://github.com/redox-os/orbtk) | [**@stratact**](https://github.com/stratact) +| [orbutils (orbital utilities))](https://github.com/redox-os/orbutils) | [**@jackpot51**](https://github.com/jackpot51) | [pkgutils (current package manager)](https://github.com/redox-os/pkgutils) | [**@jackpot51**](https://github.com/jackpot51) | [playbot (internal REPL bot)](https://github.com/redox-os/playbot) | [**@ticki**](https://github.com/ticki) | [ralloc](https://github.com/redox-os/ralloc) | [**@ticki**](https://github.com/ticki) -| [RANSID](https://github.com/redox-os/ransid) | [**@jackpot51**](https://github.com/jackpot51) +| [RANSID (rust ANSI driver)](https://github.com/redox-os/ransid) | [**@jackpot51**](https://github.com/jackpot51) | [redoxfs (old filesystem)](https://github.com/redox-os/redoxfs) | [**@jackpot51**](https://github.com/jackpot51) | [syscall](https://github.com/redox-os/syscall) | [**@jackpot51**](https://github.com/jackpot51) -| [Sodium (editor)](https://github.com/redox-os/sodium) | [**@ticki**](https://github.com/ticki) -| [Standard library](https://github.com/redox-os/libstd) | [**@jackpot51**](https://github.com/jackpot51) +| [Sodium (vim-inspired text editor)](https://github.com/redox-os/sodium) | [**@ticki**](https://github.com/ticki) +| [libstd (Redox standard library](https://github.com/redox-os/libstd) | [**@jackpot51**](https://github.com/jackpot51) | [userutils](https://github.com/redox-os/userutils) | [**@jackpot51**](https://github.com/jackpot51) -| [TFS (filesystem)](https://github.com/ticki/tfs) | [**@ticki**](https://github.com/ticki) +| [TFS (ticki filesystem)](https://github.com/ticki/tfs) | [**@ticki**](https://github.com/ticki) | [The Redox book](https://github.com/redox-os/book) | [**@ticki**](https://github.com/ticki) | [The old kernel](https://github.com/redox-os/old) | **abandoned** | [ZFS](https://github.com/redox-os/zfs) | **abandoned, superseded by TFS** @@ -77,8 +77,8 @@ The ecosystem and software Redox OS provides is listed below. Sometimes things go wrong when compiling. Try the following before opening an issue: 1. Run `make clean`. -2. Run `git clean -X -f -d`. -3. Make sure you have **the latest version of Rust nightly!** ([rustup.rs](https://www.rustup.rs) is recommended for managing Rust versions). +2. Run `git clean -Xfd`. +3. Make sure you have **the latest version of Rust nightly!** ([rustup.rs](https://www.rustup.rs) is recommended for managing Rust versions. If you already have it, run `rustup`). 4. Update **GNU Make**, **NASM** and **QEMU/VirtualBox**. 5. Pull the upstream master branch (`git remote add upstream git@github.com:redox-os/redox.git; git pull upstream master`). 6. Update submodules (`git submodule update --recursive --init`). @@ -91,7 +91,7 @@ If you're interested in this project, and you'd like to help us out, [here](CONT ## Cloning, Building, and Running -Redox is big (even compressed)! So cloning Redox takes a lot of bandwidth, and (depending on your data plan) can be costly, so clone at your own risk! +Redox is big, even compressed. Downloading the full history may take a lot of bandwidth, and can even be costly on some data plans. Clone at your own risk! ### Quick Setup @@ -112,11 +112,11 @@ $ make qemu kvm=no #### QEMU with KVM -To use QEMU with KVM (kernel-based virtual Machine), which is faster than without KVM, you need a CPU with Intel® Virtualization Technology (Intel® VT) or AMD Virtualization™ (AMD-V™) support. Most systems have this disabled in the BIOS by default, so you may need to reboot and enable the feature in the BIOS. +To use QEMU with KVM (kernel-based virtual Machine), which is faster than without KVM, you need a CPU with Intel® Virtualization Technology (Intel® VT) or AMD Virtualization™ (AMD-V™) support. Most systems have this disabled by default, so you may need to reboot, go into the BIOS, and enable it. ### Manual Setup -To manually clone, build and run Redox using a Linux host, run the following commands (with exceptions, be sure to read the comments): +To manually clone, build and run Redox using a Unix-based host, run the following commands (with exceptions, be sure to read the comments): ```bash $ cd path/to/your/projects/folder/ @@ -128,7 +128,7 @@ $ git clone git@github.com:redox-os/redox.git --origin upstream --recursive $ cd redox/ # Install/update dependencies -$ bash bootstrap.sh -d +$ ./bootstrap.sh -d # Install rustup.rs $ curl https://sh.rustup.rs -sSf | sh @@ -149,3 +149,4 @@ $ make qemu # Launch using QEMU without using KVM (Kernel Virtual Machine). Try if QEMU gives an error. $ make qemu kvm=no ``` + From a9ecbe65b824b53976f89bad2ad9622f5ba5fbfc Mon Sep 17 00:00:00 2001 From: polymetric Date: Fri, 27 Jan 2017 19:01:22 -0500 Subject: [PATCH 117/522] Major refactor of CONTRIBUTING.md - minor tweaks to a lot of things - rewrote and clarified some statements - added more communication methods - added patreon section --- CONTRIBUTING.md | 120 +++++++++++++++++++++++++++++------------------- 1 file changed, 74 insertions(+), 46 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a73625f..83a3844 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,17 +1,18 @@ # Contributing to Redox -Thank you for your interest in contributing to Redox! This document is a guide to help newcomers contribute! -There are many ways to help us out and we appreciate all of them. +Thank you for your interest in contributing to Redox! This document will outline the basics of where to start if you wish to contribute to the project. There are many ways to help us out and and we appreciate all of them. We look forward to your contribution! ## Index * [Communication](#communication) * [Chat](#chat) - * [Reddit](#reddit) -* [Direct Contributing](#direct-contributing) - * [Low-Hanging Fruit - Easy Targets for Newbies](#easy-targets) - * [GitHub Issues](#gh-issues) + * [GitHub Issues](#issues) * [Pull Requests](#prs) + * [Discourse](#discourse) + * [Reddit](#reddit) + * [News](#news) +* [Code Contributions](#code-contributions) + * [Low-Hanging Fruit - Easy Targets for Newbies](#easy-targets) * [Creating a Pull Request](#creating-a-pr) * [Best Practices/Guidelines](#best-practices) * [General](#general) @@ -22,10 +23,11 @@ There are many ways to help us out and we appreciate all of them. * [Git](#git-style-guidelines) * [Other Ways to Contribute](#other) * [Graphic Design](#graphic-design) + * [Patreon](#patreon) ## Other External Links -* [redox-os.org](http://redox-os.org) +* [redox-os.org](https://redox-os.org) * [rust-os-comparison](https://github.com/flosse/rust-os-comparison) * [rust-lang.org](http://rust-lang.org) @@ -33,13 +35,29 @@ There are many ways to help us out and we appreciate all of them. ### Chat -The quickest and most open way to communicate with the Redox team is on our chat server. Currently, the only way to join it is by sending an email to [info@redox-os.org](mailto:info@redox-os.org), which might take a little while, since it's not automated. We're currently working on an easier way to do this, but this is the most convenient way right now. +The quickest and most open way to communicate with the Redox team is on our chat server. Currently, you can only get an invite by sending an email request to [info@redox-os.org](mailto:info@redox-os.org), which might take a little while, since it's not automated. Simply say you'd like to join the chat. We're working on an better way to do this, but this is the best way right now. + +### GitHub Issues + +A bit more formal way of communication with fellow Redox devs, but a little less quick and convenient like the chat. Submit an issue when you run into problems compiling, testing, or just would like to discuss a certain topic, be it features, code style, code inconsistencies, minor changes and fixes, etc. + +### Pull Requests + +It's fine to just submit a small pull request without first making an issue or asking in the chat, but if it's a significant change that will require a lot of planning and reviewing. Also see [Creating a Pull Request](#creating-a-pr) and [Git Style Guidelines](#git-style-guidelines). + +### Discourse + +We have a discourse forum at [discourse.redox-os.org](https://discourse.redox-os.org). This is the best way to discuss more general topics that aren't about specific things that need to be addressed one way or another. You can sign up like any other website. ### Reddit -You can find Redox on Reddit in [/r/rust/](https://www.reddit.com/r/rust) and [/r/redox/](https://www.reddit.com/r/redox). The weekly update news is posted on the former. +You can also find Redox on Reddit in [/r/rust/](https://www.reddit.com/r/rust) and [/r/redox/](https://www.reddit.com/r/redox). Redox news and discussion is posted on the latter, and Rust news and discussion, as well as some Redox posts, is on the former. -## Direct Contributing +### News + +News and updates for Redox are posted at [redox-os.org/news](https://redox-os.org/news). It's more one-way than the other things on this list, but it should provide a good summary of what's been going on with the project lately. It's usually updated weekly, but with some exceptions. A mailing list may be included eventually, but it's not set up right now. + +## Code Contributions ### Low-Hanging Fruit - Easy Targets for Newbies @@ -63,40 +81,31 @@ You can find Redox on Reddit in [/r/rust/](https://www.reddit.com/r/rust) and [/ * Grep for `TODO`, `FIXME`, `BUG`, `UNOPTIMIZED`, `REWRITEME`, `DOCME`, and `PRETTYFYME` and fix the code you find. * Improve and optimize code, especially in the kernel -### GitHub Issues - -A bit more formal way of communication with fellow Redox devs, but a little less quick and convenient like the chat (unless of course you aren't in it yet, which if you're going to be involved in this project really at all, it is recommended that you request to join). These are for more specific topics. - -### Pull Requests - -It's completely okay to just submit a small pull request without first making an issue or something, but if it's a significant change that will require a lot of planning and reviewing, it's best you start with writing an issue first. Also see [git guidelines](#git-style-guidelines) - ### Creating a Pull Request 1. Fork the repository 2. Clone the original repository to your local PC using one of the following commands based on the protocol you are using: * HTTPS:`git clone https://github.com/redox-os/redox.git --origin upstream --recursive` * SSH:`git clone git@github.com:redox-os/redox.git --origin upstream --recursive` - * Then rebase: `git rebase upstream master` - Use HTTPS if you don't know which one to use. (Recommended: learn about SSH if you don't want to have to log in every time you push/pull!) + * Then rebase: `git rebase upstream master` + If you use HTTPS, you will have to log in each time when pushing to your fork. (Recommended: learn about git SSH support, it logs in automatically using SSH keys) 3. Add your fork with * HTTPS:`git remote add origin https://github.com/your-username/redox.git` * SSH:`git remote add origin git@github.com:your-username/redox.git` 4. Alternatively, if you already have a fork and copy of the repo, you can simply check to make sure you're up-to-date - * Fetch the upstream:`git fetch upstream master` - * Rebase with local commits:`git rebase upstream/master` - * Update the submodules:`git submodule update --init` -5. Optionally create a separate branch (recommended if you're making multiple changes simultaneously) (`git checkout -b my-branch`) + * Pull the upstream:`git pull upstream --rebase` + * Update the submodules:`git submodule update --recursive --init` +5. Create a separate branch (recommended if you're making multiple changes simultaneously) (`git checkout -b my-branch`) 6. Make changes -7. Commit (`git add . --all; git commit -m "my commit"`) +7. Commit (`git add ; git commit`) and write your commit message 8. Optionally run [rustfmt](https://github.com/rust-lang-nursery/rustfmt) on the files you changed and commit again if it did anything (check with `git diff` first) -9. Test your changes with `make qemu` or `make virtualbox` (you might have to use `make qemu kvm=no`, formerly `make qemu_no_kvm`) +9. Test your changes by cleaning (`make clean; git clean -Xfd`) and building with `make qemu` (you might have to use `make qemu kvm=no`) or `make virtualbox`. (see [Best Practices and Guidelines](#best-practices)) -10. Pull from upstream (`git fetch upstream; git rebase upstream/master`) (Note: try not to use `git pull`, it is equivalent to doing `git fetch upstream; git merge master upstream/master`, which is not usually preferred for local/fork repositories, although it is fine in some cases.) +10. Pull from upstream (`git pull upstream --rebase`) (Note: Make sure to include `--rebase`, as it will apply your changes on top of the changes you just pulled, allowing for a much cleaner merge) 11. Repeat step 9 to make sure the rebase still builds and starts -12. Push to your fork (`git push origin my-branch`) +12. Push to your fork (`git push origin `), `` being the branch you created earlier 13. Create a pull request -14. Describe your changes +14. If your changes are minor, you can just describe them in a paragraph or less. If they're major, please fill out the provided form. 15. Submit! ## Best Practices and Guidelines @@ -105,36 +114,36 @@ It's completely okay to just submit a small pull request without first making an * **Remember to do a `git rebase -i upstream/master` before you send your patch!** * **Make sure your code is readable, commented, and well-documented.** -* **Don't hesitate to ask for help!** -* **Before implementing something, discuss it! Open an issue, or join the chat.** +* **Don't hesitate to ask for help, comments or suggestions!** +* **Before implementing something, discuss it! Open an issue, or ask in the chat.** ##### On the more technical side: * Test, test, and test! -* Follow the style conventions +* Follow the style conventions (See [rust style guidelines](#rust-style-guidelines)) * Use `std::mem::replace` and `std::mem::swap` when you can. * `libredox` should be 1-to-1 with the official `libstd`. -* Use `.into()` and `.to_owned()` over `.to_string()`. +* Prefer `.into()` and `.to_owned()` over `.to_string()`. * Prefer passing references to the data over owned data. (Don't take `String`, take `&str`. Don't take `Vec` take `&[T]`). * Use generics, traits, and other abstractions Rust provides. * Avoid using lossy conversions (for example: don't do `my_u32 as u16 == my_u16`, prefer `my_u32 == my_u16 as my_u32`). * Prefer in place (`box` keyword) when doing heap allocations. * Prefer platform independently sized integer over pointer sized integer (`u32` over `usize`, for example). * Follow the usual idioms of programming, such as "composition over inheritance", "let your program be divided in smaller pieces", and "resource acquisition is initialization". -* When `unsafe` is unnecessary, don't use it. 10 lines longer safe code is better than more compact unsafe code! -* Be sure to mark parts that need work with `TODO`, `FIXME`, `BUG`, `UNOPTIMIZED`, `REWRITEME`, `DOCME`, and `PRETTYFYME`. +* When `unsafe` is unnecessary, don't use it. **Longer safe code is better than shorter unsafe code!** +* Be sure to mark parts that need work with `TODO`, `FIXME`, `BUG`, `UNOPTIMIZED`, `REWRITEME`, `DOCME`, and `PRETTYFYME`. Always elaborate on these messages, too. Nothing is more annoying than seeing a `TODO` and not knowing how to actually fix it. * Use the compiler hint attributes, such as `#[inline]`, `#[cold]`, etc. when it makes sense to do so. -* Check the [chat](#chat), [the Website](http://redox-os.org), and [the Rust subreddit](https://www.reddit.com/r/rust) frequently. +* Check the [chat](#chat), [the website](http://redox-os.org/news), and [the Rust subreddit](https://www.reddit.com/r/rust) frequently. ### Kernel -* When trying to access a slice, **always** use the `common::GetSlice` trait and the `.get_slice()` method to get a slice without causing the kernel to panic. - The problem with slicing in regular Rust, e.g. `foo[a..b]`, is that if someone tries to access with a range that is out of bounds of an array/string/slice, it will cause a panic at runtime, as a safety measure. Same thing when accessing an element. +* When trying to access a slice, **always** use the `common::GetSlice` trait and the `.get_slice()` method to get a slice without causing the kernel to panic. + The problem with slicing in regular Rust, e.g. `foo[a..b]`, is that if someone tries to access with a range that is out of bounds of an array/string/slice, it will cause a panic at runtime, as a safety measure. Same thing when accessing an element. Always use `foo.get(n)` instead of `foo[n]` and try to cover for the possibility of `Option::None`. Doing the regular way may work fine for applications, but never in the kernel. No possible panics should ever exist in kernel space, because then the whole OS would just stop working. ### Testing Practices -* It's always better to test boot (`make qemu` or `make virtualbox`) every time you make a change, because it is important to see how the OS boots and works after it compiles. - Even though Rust is a safety-oriented language, something as unstable as an in-dev operating system will have problems in many cases and may completely break on even the slightest critical change. +* It's always better to test boot (`make qemu` or `make virtualbox`) every time you make a change, because it is important to see how the OS boots and works after it compiles. + Even though Rust is a safety-oriented language, something as unstable and low-level as an in-dev operating system will almost certainly have problems in many cases and may completely break on even the slightest critical change. Also, make sure you check how the unmodified version runs on your machine before making any changes. Else, you won't have anything to compare to, and it will generally just lead to confusion. TLDR: Rebuild and test boot often. * To run the ZFS tests: @@ -150,14 +159,33 @@ Since Rust is a relatively small and new language compared to others like C, the ### Git -* Commit messages should describe their changes in present tense, e.g. "`Add stuff to file.ext`" instead of "`added stuff to file.ext`". -* Try to remove useless duplicate/merge commits from PRs as these clutter up history, and may make it hard to read. -* Usually, when syncing your local copy with the master branch, you will want to rebase instead of merge. This is because it will create duplicate commits that don't actually do anything when merged into the master branch. -* When you start to make changes, you will want to create a separate branch, and keep the `master` branch of your fork identical to the main repository, so that you can compare your changes with the main branch and test out a more stable build if you need to. * You should have a fork of the repository on GitHub and a local copy on your computer. The local copy should have two remotes; `upstream` and `origin`, `upstream` should be set to the main repository and `origin` should be your fork. +* When you start to make changes, you will want to create a separate branch, and keep the `master` branch of your fork identical to the main repository, so that you can compare your changes with the main branch and test out a more stable build if you need to. +* Usually, when syncing your local copy with the master branch, you'll want to rebase instead of merge. This is because it will create duplicate commits that don't actually do anything when merged into the master branch. You can do this in one command with `git pull upstream --rebase`. This will pull from the upstream, then roll back to the current state of the upstream, and "replay" your changes on top of it. Make sure you commit before doing this, though. Git won't be able to rebase if you don't. +* Prefer to omit the `-m` when using `git commit`. This opens your editor and should help get you in the habit of writing longer commit messages. +* Commit messages should describe their changes in present tense, e.g. "`Add stuff to file.ext`" instead of "`added stuff to file.ext`". This makes sense as sometimes when you revert back, then run through commits one-by-one, you want to see what a commit will do, instead of just what the person did when they made the commit. It's also just being consistent. +* Try to remove useless duplicate/merge commits from PRs as these don't do anything except clutter up history and make it harder to read. ## Other Ways to Contribute -### Graphic Design +If you're not big on coding, but you still want to help keep the project going, you can still contribute/support in a variety of ways! We'll try to find a way to use anything you have to offer. + +### Design + +If you're a good designer, whether it's 2D graphics, 3D graphics, interfaces, web design, you can help. We need logos, UI design, UI skins, app icons, desktop backgrounds, etc. More information to come on this in the future, for now just join [the chat](#chat) and ask about graphic design. + +### Patreon + +Our BDFL, [jackpot51](https://github.com/jackpot51), has a [Patreon campaign](https://www.patreon.com/redox_os)! All money recieved will go towards Redox OS development. If you donate, you will be listed in the Redox credits as one of the people that made Redox OS possible. You'll also get other rewards the more you donate. However, please don't donate if you can't afford it. + + -If you're a good designer, you can help with logos, UI design, app icons, other graphics (e.g. stock desktop backgrounds), etc. More information to come on this, for now just join [the chat](#chat) and ask about graphic design. From b64ce1a67f228dc0e95378f7a8cd59d64669c7e7 Mon Sep 17 00:00:00 2001 From: Ahmed Charles Date: Sun, 29 Jan 2017 17:24:54 -0800 Subject: [PATCH 118/522] fuse is also a dependency on debian based systems fusermount is in the fuse package. --- bootstrap.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap.sh b/bootstrap.sh index 7170a3d..5ea24b2 100644 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -178,7 +178,7 @@ ubuntu() echo "Updating system..." sudo "$2" update echo "Installing required packages..." - sudo "$2" install build-essential libc6-dev-i386 nasm curl file git libfuse-dev + sudo "$2" install build-essential libc6-dev-i386 nasm curl file git libfuse-dev fuse if [ "$1" == "qemu" ]; then if [ -z "$(which qemu-system-x86_64)" ]; then echo "Installing QEMU..." From 71eda949bc25a34e4d652c0052e94ef1e7e0891d Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 30 Jan 2017 20:45:00 -0700 Subject: [PATCH 119/522] Update rust and redoxfs --- rust | 2 +- schemes/redoxfs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rust b/rust index fc57e40..b13d9ce 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit fc57e40ce703cb70a39249f5cfb661020a1549b6 +Subproject commit b13d9ce2220a9769b526fb65e7d411ada8db34c9 diff --git a/schemes/redoxfs b/schemes/redoxfs index 665120f..fa6c19f 160000 --- a/schemes/redoxfs +++ b/schemes/redoxfs @@ -1 +1 @@ -Subproject commit 665120f0639d367d8f254a1df407bfaf65f5ef47 +Subproject commit fa6c19f79bf685db9022e2c4758fb3adb5c450dd From 1097edcab782363c934aad61a2a630d01260888a Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 1 Feb 2017 14:15:48 -0700 Subject: [PATCH 120/522] Add nproc fix for macOS --- mk/config.mk | 44 +++++++++++++++++++++++--------------------- programs/coreutils | 2 +- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/mk/config.mk b/mk/config.mk index b8e049a..19dfe52 100644 --- a/mk/config.mk +++ b/mk/config.mk @@ -1,6 +1,28 @@ # Configuration ARCH?=x86_64 +# Per host variables +UNAME := $(shell uname) +ifeq ($(UNAME),Darwin) + ECHO=/bin/echo + FUMOUNT=sudo umount + export LD=$(ARCH)-elf-ld + export LDFLAGS=--gc-sections + export NPROC=sysctl -n hw.ncpu + export STRIP=$(ARCH)-elf-strip + VB_AUDIO=coreaudio + VBM="/Applications/VirtualBox.app/Contents/MacOS/VBoxManage" +else + ECHO=echo + FUMOUNT=fusermount -u + export LD=ld + export LDFLAGS=--gc-sections + export NPROC=nproc + export STRIP=strip + VB_AUDIO="pulse" + VBM=VBoxManage +endif + # Automatic variables ROOT=$(PWD) export RUST_TARGET_PATH=$(ROOT)/kernel/targets @@ -21,24 +43,4 @@ BUILD=build/userspace RUSTC=./rustc.sh RUSTDOC=./rustdoc.sh CARGO=RUSTC="$(RUSTC)" RUSTDOC="$(RUSTDOC)" cargo -CARGOFLAGS=--target $(TARGET) --release -- -C codegen-units=`nproc` - -# Per host variables -UNAME := $(shell uname) -ifeq ($(UNAME),Darwin) - ECHO=/bin/echo - FUMOUNT=sudo umount - export LD=$(ARCH)-elf-ld - export LDFLAGS=--gc-sections - export STRIP=$(ARCH)-elf-strip - VB_AUDIO=coreaudio - VBM="/Applications/VirtualBox.app/Contents/MacOS/VBoxManage" -else - ECHO=echo - FUMOUNT=fusermount -u - export LD=ld - export LDFLAGS=--gc-sections - export STRIP=strip - VB_AUDIO="pulse" - VBM=VBoxManage -endif +CARGOFLAGS=--target $(TARGET) --release -- -C codegen-units=`$(NPROC)` diff --git a/programs/coreutils b/programs/coreutils index 330e6a7..e589e09 160000 --- a/programs/coreutils +++ b/programs/coreutils @@ -1 +1 @@ -Subproject commit 330e6a7ec26640173107d4948c6cc77e457a431f +Subproject commit e589e0963036dcd782af438be38aca14f8691370 From f6f8de68f6cd307539d75a4a2ce3085b5e913fc6 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 2 Feb 2017 10:21:25 -0700 Subject: [PATCH 121/522] Update Rust --- rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust b/rust index b13d9ce..75a7eac 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit b13d9ce2220a9769b526fb65e7d411ada8db34c9 +Subproject commit 75a7eacd087db51f1ea06c71bba2451c53aed62c From 822f57402775ec3b85ff0d1de61a23c28b1a1feb Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 2 Feb 2017 10:32:23 -0700 Subject: [PATCH 122/522] Update README and ion --- README.md | 2 +- programs/ion | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 97c5c22..8c42dd3 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Please make sure you use the **latest nightly** of `rustc` before building (for [![Travis Build Status](https://travis-ci.org/redox-os/redox.svg?branch=master)](https://travis-ci.org/redox-os/redox) [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE.md) -![Rust Version](https://img.shields.io/badge/rust-1.16.0--nightly%20(4ecc85beb%202016--12--28)-lightgrey.svg) +![Rust Version](https://img.shields.io/badge/rust-rustc%201.16.0--nightly%20(24055d0f2%202017--01--31)-lightgrey.svg) ## Contents diff --git a/programs/ion b/programs/ion index 41360f0..fc9c7c1 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit 41360f0381b341e4cc7bb07a411fe25d98a1f985 +Subproject commit fc9c7c11f41b94970a44eef90d38909adc2270ed From 20f0003e01739b61c33819f5b7cf17f984c4987a Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 4 Feb 2017 16:13:44 -0700 Subject: [PATCH 123/522] Incremental compilation --- mk/config.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mk/config.mk b/mk/config.mk index 19dfe52..c20f426 100644 --- a/mk/config.mk +++ b/mk/config.mk @@ -34,7 +34,7 @@ KTARGET=$(ARCH)-unknown-none KBUILD=build/kernel KRUSTC=./krustc.sh KRUSTDOC=./krustdoc.sh -KCARGO=RUSTC="$(KRUSTC)" RUSTDOC="$(KRUSTDOC)" cargo +KCARGO=RUSTC="$(KRUSTC)" RUSTDOC="$(KRUSTDOC)" CARGO_INCREMENTAL=1 cargo KCARGOFLAGS=--target $(KTARGET) --release -- -C soft-float # Userspace variables @@ -42,5 +42,5 @@ export TARGET=$(ARCH)-unknown-redox BUILD=build/userspace RUSTC=./rustc.sh RUSTDOC=./rustdoc.sh -CARGO=RUSTC="$(RUSTC)" RUSTDOC="$(RUSTDOC)" cargo +CARGO=RUSTC="$(RUSTC)" RUSTDOC="$(RUSTDOC)" CARGO_INCREMENTAL=1 cargo CARGOFLAGS=--target $(TARGET) --release -- -C codegen-units=`$(NPROC)` From 2d25d5848243d9fce29fd1f3862c61eec185f394 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 7 Feb 2017 19:48:50 -0700 Subject: [PATCH 124/522] Fix kernel output --- mk/kernel.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mk/kernel.mk b/mk/kernel.mk index 6a716f6..054c419 100644 --- a/mk/kernel.mk +++ b/mk/kernel.mk @@ -4,10 +4,10 @@ $(KBUILD)/libcollections.rlib: rust/src/libcollections/Cargo.toml rust/src/libco cp rust/src/target/$(KTARGET)/release/deps/*.rlib $(KBUILD) $(KBUILD)/libkernel.a: kernel/Cargo.toml kernel/arch/** kernel/src/** $(KBUILD)/libcollections.rlib $(BUILD)/initfs.rs - $(KCARGO) rustc --manifest-path $< --lib $(KCARGOFLAGS) -C lto --emit obj=$@ + $(KCARGO) rustc --manifest-path $< --lib $(KCARGOFLAGS) -C lto -o $@ $(KBUILD)/libkernel_live.a: kernel/Cargo.toml kernel/arch/** kernel/src/** $(KBUILD)/libcollections.rlib $(BUILD)/initfs.rs build/filesystem.bin - $(KCARGO) rustc --manifest-path $< --lib --features live $(KCARGOFLAGS) -C lto --emit obj=$@ + $(KCARGO) rustc --manifest-path $< --lib --features live $(KCARGOFLAGS) -C lto -o $@ $(KBUILD)/kernel: $(KBUILD)/libkernel.a $(LD) $(LDFLAGS) -z max-page-size=0x1000 -T kernel/arch/$(ARCH)/src/linker.ld -o $@ $< From 1346d8a1812452b6670ef046f2cdecf51e2a97dc Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 7 Feb 2017 20:03:32 -0700 Subject: [PATCH 125/522] Fixes for build - do not use LTO on kernel --- mk/kernel.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mk/kernel.mk b/mk/kernel.mk index 054c419..9760d0d 100644 --- a/mk/kernel.mk +++ b/mk/kernel.mk @@ -4,10 +4,10 @@ $(KBUILD)/libcollections.rlib: rust/src/libcollections/Cargo.toml rust/src/libco cp rust/src/target/$(KTARGET)/release/deps/*.rlib $(KBUILD) $(KBUILD)/libkernel.a: kernel/Cargo.toml kernel/arch/** kernel/src/** $(KBUILD)/libcollections.rlib $(BUILD)/initfs.rs - $(KCARGO) rustc --manifest-path $< --lib $(KCARGOFLAGS) -C lto -o $@ + $(KCARGO) rustc --manifest-path $< --lib $(KCARGOFLAGS) -o $@ $(KBUILD)/libkernel_live.a: kernel/Cargo.toml kernel/arch/** kernel/src/** $(KBUILD)/libcollections.rlib $(BUILD)/initfs.rs build/filesystem.bin - $(KCARGO) rustc --manifest-path $< --lib --features live $(KCARGOFLAGS) -C lto -o $@ + $(KCARGO) rustc --manifest-path $< --lib --features live $(KCARGOFLAGS) -o $@ $(KBUILD)/kernel: $(KBUILD)/libkernel.a $(LD) $(LDFLAGS) -z max-page-size=0x1000 -T kernel/arch/$(ARCH)/src/linker.ld -o $@ $< From 7785ddd99be162a08385b35af3e84ae8af647793 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 7 Feb 2017 20:23:41 -0700 Subject: [PATCH 126/522] Cleanup of panics in network schemes --- schemes/ethernetd/src/main.rs | 148 +++++++++++++++++++--------------- schemes/ipd/src/main.rs | 117 ++++++++++++++++----------- schemes/tcpd/src/main.rs | 69 +++++++++------- schemes/udpd/src/main.rs | 68 +++++++++------- 4 files changed, 233 insertions(+), 169 deletions(-) diff --git a/schemes/ethernetd/src/main.rs b/schemes/ethernetd/src/main.rs index 66357b6..8444081 100644 --- a/schemes/ethernetd/src/main.rs +++ b/schemes/ethernetd/src/main.rs @@ -7,6 +7,7 @@ use std::cell::RefCell; use std::fs::File; use std::io::{Result, Read, Write}; use std::os::unix::io::FromRawFd; +use std::process; use std::rc::Rc; use syscall::{Packet, SchemeMut, EWOULDBLOCK}; @@ -15,80 +16,93 @@ use scheme::EthernetScheme; mod scheme; -fn main() { - // Daemonize - if unsafe { syscall::clone(0).unwrap() } == 0 { - let network_fd = syscall::open("network:", syscall::O_RDWR | syscall::O_NONBLOCK).expect("ethernetd: failed to open network"); - let network = unsafe { File::from_raw_fd(network_fd) }; +fn daemon(network_fd: usize, socket_fd: usize) { + let network = unsafe { File::from_raw_fd(network_fd) }; + let socket = Rc::new(RefCell::new(unsafe { File::from_raw_fd(socket_fd) })); + let scheme = Rc::new(RefCell::new(EthernetScheme::new(network))); + let todo = Rc::new(RefCell::new(Vec::::new())); - let socket_fd = syscall::open(":ethernet", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK).expect("ethernetd: failed to create ethernet scheme"); - let socket = Rc::new(RefCell::new(unsafe { File::from_raw_fd(socket_fd) })); + let mut event_queue = EventQueue::<()>::new().expect("ethernetd: failed to create event queue"); - let scheme = Rc::new(RefCell::new(EthernetScheme::new(network))); - - let todo = Rc::new(RefCell::new(Vec::::new())); - - let mut event_queue = EventQueue::<()>::new().expect("ethernetd: failed to create event queue"); - - let socket_net = socket.clone(); - let scheme_net = scheme.clone(); - let todo_net = todo.clone(); - event_queue.add(network_fd, move |_count: usize| -> Result> { - if scheme_net.borrow_mut().input()? > 0 { - let mut todo = todo_net.borrow_mut(); - let mut i = 0; - while i < todo.len() { - let a = todo[i].a; - scheme_net.borrow_mut().handle(&mut todo[i]); - if todo[i].a == (-EWOULDBLOCK) as usize { - todo[i].a = a; - i += 1; - } else { - socket_net.borrow_mut().write(&mut todo[i])?; - todo.remove(i); - } - } - - for (id, handle) in scheme_net.borrow_mut().handles.iter() { - if let Some(frame) = handle.frames.get(0) { - socket_net.borrow_mut().write(&Packet { - id: 0, - pid: 0, - uid: 0, - gid: 0, - a: syscall::number::SYS_FEVENT, - b: *id, - c: syscall::flag::EVENT_READ, - d: frame.data.len() - })?; - } - } - } - Ok(None) - }).expect("ethernetd: failed to listen for network events"); - - event_queue.add(socket_fd, move |_count: usize| -> Result> { - loop { - let mut packet = Packet::default(); - if socket.borrow_mut().read(&mut packet)? == 0 { - break; - } - - let a = packet.a; - scheme.borrow_mut().handle(&mut packet); - if packet.a == (-EWOULDBLOCK) as usize { - packet.a = a; - todo.borrow_mut().push(packet); + let socket_net = socket.clone(); + let scheme_net = scheme.clone(); + let todo_net = todo.clone(); + event_queue.add(network_fd, move |_count: usize| -> Result> { + if scheme_net.borrow_mut().input()? > 0 { + let mut todo = todo_net.borrow_mut(); + let mut i = 0; + while i < todo.len() { + let a = todo[i].a; + scheme_net.borrow_mut().handle(&mut todo[i]); + if todo[i].a == (-EWOULDBLOCK) as usize { + todo[i].a = a; + i += 1; } else { - socket.borrow_mut().write(&mut packet)?; + socket_net.borrow_mut().write(&mut todo[i])?; + todo.remove(i); } } - Ok(None) - }).expect("ethernetd: failed to listen for scheme events"); + for (id, handle) in scheme_net.borrow_mut().handles.iter() { + if let Some(frame) = handle.frames.get(0) { + socket_net.borrow_mut().write(&Packet { + id: 0, + pid: 0, + uid: 0, + gid: 0, + a: syscall::number::SYS_FEVENT, + b: *id, + c: syscall::flag::EVENT_READ, + d: frame.data.len() + })?; + } + } + } + Ok(None) + }).expect("ethernetd: failed to listen for network events"); - event_queue.trigger_all(0).expect("ethernetd: failed to trigger events"); + event_queue.add(socket_fd, move |_count: usize| -> Result> { + loop { + let mut packet = Packet::default(); + if socket.borrow_mut().read(&mut packet)? == 0 { + break; + } - event_queue.run().expect("ethernetd: failed to run event loop"); + let a = packet.a; + scheme.borrow_mut().handle(&mut packet); + if packet.a == (-EWOULDBLOCK) as usize { + packet.a = a; + todo.borrow_mut().push(packet); + } else { + socket.borrow_mut().write(&mut packet)?; + } + } + + Ok(None) + }).expect("ethernetd: failed to listen for scheme events"); + + event_queue.trigger_all(0).expect("ethernetd: failed to trigger events"); + + event_queue.run().expect("ethernetd: failed to run event loop"); +} + +fn main() { + match syscall::open("network:", syscall::O_RDWR | syscall::O_NONBLOCK) { + Ok(network_fd) => match syscall::open(":ethernet", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK) { + Ok(socket_fd) => { + // Daemonize + if unsafe { syscall::clone(0).unwrap() } == 0 { + daemon(network_fd, socket_fd); + } + }, + Err(err) => { + println!("ethernetd: failed to create ethernet scheme: {}", err); + process::exit(1); + } + }, + Err(err) => { + println!("ethernetd: failed to open network: {}", err); + process::exit(1); + } } } diff --git a/schemes/ipd/src/main.rs b/schemes/ipd/src/main.rs index 52ae0cb..019a5e1 100644 --- a/schemes/ipd/src/main.rs +++ b/schemes/ipd/src/main.rs @@ -9,8 +9,8 @@ use std::collections::{BTreeMap, VecDeque}; use std::fs::File; use std::io::{self, Read, Write}; use std::os::unix::io::FromRawFd; +use std::{process, slice, str}; use std::rc::Rc; -use std::{slice, str}; use syscall::data::Packet; use syscall::error::{Error, Result, EACCES, EADDRNOTAVAIL, EBADF, EIO, EINVAL, ENOENT, EWOULDBLOCK}; use syscall::flag::{EVENT_READ, O_NONBLOCK}; @@ -255,64 +255,85 @@ impl SchemeMut for Ipd { } } -fn main() { - // Daemonize - if unsafe { syscall::clone(0).unwrap() } == 0 { - let scheme_fd = syscall::open(":ip", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK).expect("ipd: failed to create :ip"); - let scheme_file = unsafe { File::from_raw_fd(scheme_fd) }; +fn daemon(arp_fd: usize, ip_fd: usize, scheme_fd: usize) { + let scheme_file = unsafe { File::from_raw_fd(scheme_fd) }; - let ipd = Rc::new(RefCell::new(Ipd::new(scheme_file))); + let ipd = Rc::new(RefCell::new(Ipd::new(scheme_file))); - let mut event_queue = EventQueue::<()>::new().expect("ipd: failed to create event queue"); + let mut event_queue = EventQueue::<()>::new().expect("ipd: failed to create event queue"); - //TODO: Multiple interfaces - { - let arp_fd = syscall::open("ethernet:806", syscall::O_RDWR | syscall::O_NONBLOCK).expect("ipd: failed to open ethernet:806"); - let ip_fd = syscall::open("ethernet:800", syscall::O_RDWR | syscall::O_NONBLOCK).expect("ipd: failed to open ethernet:800"); - let if_id = { - let mut ipd = ipd.borrow_mut(); - let if_id = ipd.interfaces.len(); - ipd.interfaces.push(Box::new(EthernetInterface::new(arp_fd, ip_fd))); - if_id - }; - - let arp_ipd = ipd.clone(); - event_queue.add(arp_fd, move |_count: usize| -> io::Result> { - if let Some(mut interface) = arp_ipd.borrow_mut().interfaces.get_mut(if_id) { - interface.arp_event()?; - } - - Ok(None) - }).expect("ipd: failed to listen to events on ethernet:806"); - - let ip_ipd = ipd.clone(); - event_queue.add(ip_fd, move |_count: usize| -> io::Result> { - ip_ipd.borrow_mut().ip_event(if_id)?; - - Ok(None) - }).expect("ipd: failed to listen to events on ethernet:800"); - } - - let loopback_id = { + //TODO: Multiple interfaces + { + let if_id = { let mut ipd = ipd.borrow_mut(); let if_id = ipd.interfaces.len(); - ipd.interfaces.push(Box::new(LoopbackInterface::new())); + ipd.interfaces.push(Box::new(EthernetInterface::new(arp_fd, ip_fd))); if_id }; - event_queue.add(scheme_fd, move |_count: usize| -> io::Result> { - let mut ipd = ipd.borrow_mut(); - - ipd.loopback_event(loopback_id)?; - ipd.scheme_event()?; - ipd.loopback_event(loopback_id)?; + let arp_ipd = ipd.clone(); + event_queue.add(arp_fd, move |_count: usize| -> io::Result> { + if let Some(mut interface) = arp_ipd.borrow_mut().interfaces.get_mut(if_id) { + interface.arp_event()?; + } Ok(None) - }).expect("ipd: failed to listen to events on :ip"); + }).expect("ipd: failed to listen to events on ethernet:806"); - // Make sure that all descriptors are at EOF - event_queue.trigger_all(0).expect("ipd: failed to trigger event queue"); + let ip_ipd = ipd.clone(); + event_queue.add(ip_fd, move |_count: usize| -> io::Result> { + ip_ipd.borrow_mut().ip_event(if_id)?; - event_queue.run().expect("ipd: failed to run event queue"); + Ok(None) + }).expect("ipd: failed to listen to events on ethernet:800"); + } + + let loopback_id = { + let mut ipd = ipd.borrow_mut(); + let if_id = ipd.interfaces.len(); + ipd.interfaces.push(Box::new(LoopbackInterface::new())); + if_id + }; + + event_queue.add(scheme_fd, move |_count: usize| -> io::Result> { + let mut ipd = ipd.borrow_mut(); + + ipd.loopback_event(loopback_id)?; + ipd.scheme_event()?; + ipd.loopback_event(loopback_id)?; + + Ok(None) + }).expect("ipd: failed to listen to events on :ip"); + + // Make sure that all descriptors are at EOF + event_queue.trigger_all(0).expect("ipd: failed to trigger event queue"); + + event_queue.run().expect("ipd: failed to run event queue"); +} + +fn main() { + match syscall::open("ethernet:806", syscall::O_RDWR | syscall::O_NONBLOCK) { + Ok(arp_fd) => match syscall::open("ethernet:800", syscall::O_RDWR | syscall::O_NONBLOCK) { + Ok(ip_fd) => match syscall::open(":ip", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK) { + Ok(scheme_fd) => { + // Daemonize + if unsafe { syscall::clone(0).unwrap() } == 0 { + daemon(arp_fd, ip_fd, scheme_fd); + } + }, + Err(err) => { + println!("ipd: failed to create ip scheme: {}", err); + process::exit(1); + } + }, + Err(err) => { + println!("ipd: failed to open ethernet:800: {}", err); + process::exit(1); + } + }, + Err(err) => { + println!("ipd: failed to open ethernet:806: {}", err); + process::exit(1); + } } } diff --git a/schemes/tcpd/src/main.rs b/schemes/tcpd/src/main.rs index 9fb5935..9dfbd02 100644 --- a/schemes/tcpd/src/main.rs +++ b/schemes/tcpd/src/main.rs @@ -8,7 +8,7 @@ use std::collections::{BTreeMap, VecDeque}; use std::cell::RefCell; use std::fs::File; use std::io::{self, Read, Write}; -use std::{mem, slice, str}; +use std::{mem, process, slice, str}; use std::ops::{Deref, DerefMut}; use std::os::unix::io::FromRawFd; use std::rc::Rc; @@ -783,32 +783,47 @@ impl SchemeMut for Tcpd { } } +fn daemon(tcp_fd: usize, scheme_fd: usize) { + let tcp_file = unsafe { File::from_raw_fd(tcp_fd) }; + let scheme_file = unsafe { File::from_raw_fd(scheme_fd) }; + + let tcpd = Rc::new(RefCell::new(Tcpd::new(scheme_file, tcp_file))); + + let mut event_queue = EventQueue::<()>::new().expect("tcpd: failed to create event queue"); + + let tcp_tcpd = tcpd.clone(); + event_queue.add(tcp_fd, move |_count: usize| -> io::Result> { + tcp_tcpd.borrow_mut().tcp_event()?; + Ok(None) + }).expect("tcpd: failed to listen to events on ip:6"); + + event_queue.add(scheme_fd, move |_count: usize| -> io::Result> { + tcpd.borrow_mut().scheme_event()?; + Ok(None) + }).expect("tcpd: failed to listen to events on :tcp"); + + event_queue.trigger_all(0).expect("tcpd: failed to trigger event queue"); + + event_queue.run().expect("tcpd: failed to run event queue"); +} + fn main() { - // Daemonize - if unsafe { syscall::clone(0).unwrap() } == 0 { - let scheme_fd = syscall::open(":tcp", O_RDWR | O_CREAT | O_NONBLOCK).expect("tcpd: failed to create :tcp"); - let scheme_file = unsafe { File::from_raw_fd(scheme_fd) }; - - let tcp_fd = syscall::open("ip:6", O_RDWR | O_NONBLOCK).expect("tcpd: failed to open ip:6"); - let tcp_file = unsafe { File::from_raw_fd(tcp_fd) }; - - let tcpd = Rc::new(RefCell::new(Tcpd::new(scheme_file, tcp_file))); - - let mut event_queue = EventQueue::<()>::new().expect("tcpd: failed to create event queue"); - - let tcp_tcpd = tcpd.clone(); - event_queue.add(tcp_fd, move |_count: usize| -> io::Result> { - tcp_tcpd.borrow_mut().tcp_event()?; - Ok(None) - }).expect("tcpd: failed to listen to events on ip:6"); - - event_queue.add(scheme_fd, move |_count: usize| -> io::Result> { - tcpd.borrow_mut().scheme_event()?; - Ok(None) - }).expect("tcpd: failed to listen to events on :tcp"); - - event_queue.trigger_all(0).expect("tcpd: failed to trigger event queue"); - - event_queue.run().expect("tcpd: failed to run event queue"); + match syscall::open("ip:6", O_RDWR | O_NONBLOCK) { + Ok(tcp_fd) => match syscall::open(":tcp", O_RDWR | O_CREAT | O_NONBLOCK) { + Ok(scheme_fd) => { + // Daemonize + if unsafe { syscall::clone(0).unwrap() } == 0 { + daemon(tcp_fd, scheme_fd); + } + }, + Err(err) => { + println!("tcpd: failed to create tcp scheme: {}", err); + process::exit(1); + } + }, + Err(err) => { + println!("tcpd: failed to open ip:6: {}", err); + process::exit(1); + } } } diff --git a/schemes/udpd/src/main.rs b/schemes/udpd/src/main.rs index bd51751..2c9396a 100644 --- a/schemes/udpd/src/main.rs +++ b/schemes/udpd/src/main.rs @@ -8,7 +8,7 @@ use std::collections::{BTreeMap, VecDeque}; use std::cell::RefCell; use std::fs::File; use std::io::{self, Read, Write}; -use std::{mem, slice, str}; +use std::{mem, process, slice, str}; use std::ops::{Deref, DerefMut}; use std::os::unix::io::FromRawFd; use std::rc::Rc; @@ -450,33 +450,47 @@ impl SchemeMut for Udpd { Ok(0) } } +fn daemon(udp_fd: usize, scheme_fd: usize) { + let udp_file = unsafe { File::from_raw_fd(udp_fd) }; + let scheme_file = unsafe { File::from_raw_fd(scheme_fd) }; + + let udpd = Rc::new(RefCell::new(Udpd::new(scheme_file, udp_file))); + + let mut event_queue = EventQueue::<()>::new().expect("udpd: failed to create event queue"); + + let udp_udpd = udpd.clone(); + event_queue.add(udp_fd, move |_count: usize| -> io::Result> { + udp_udpd.borrow_mut().udp_event()?; + Ok(None) + }).expect("udpd: failed to listen to events on ip:11"); + + event_queue.add(scheme_fd, move |_count: usize| -> io::Result> { + udpd.borrow_mut().scheme_event()?; + Ok(None) + }).expect("udpd: failed to listen to events on :udp"); + + event_queue.trigger_all(0).expect("udpd: failed to trigger event queue"); + + event_queue.run().expect("udpd: failed to run event queue"); +} fn main() { - // Daemonize - if unsafe { syscall::clone(0).unwrap() } == 0 { - let scheme_fd = syscall::open(":udp", O_RDWR | O_CREAT | O_NONBLOCK).expect("udpd: failed to create :udp"); - let scheme_file = unsafe { File::from_raw_fd(scheme_fd) }; - - let udp_fd = syscall::open("ip:11", O_RDWR | O_NONBLOCK).expect("udpd: failed to open ip:11"); - let udp_file = unsafe { File::from_raw_fd(udp_fd) }; - - let udpd = Rc::new(RefCell::new(Udpd::new(scheme_file, udp_file))); - - let mut event_queue = EventQueue::<()>::new().expect("udpd: failed to create event queue"); - - let udp_udpd = udpd.clone(); - event_queue.add(udp_fd, move |_count: usize| -> io::Result> { - udp_udpd.borrow_mut().udp_event()?; - Ok(None) - }).expect("udpd: failed to listen to events on ip:11"); - - event_queue.add(scheme_fd, move |_count: usize| -> io::Result> { - udpd.borrow_mut().scheme_event()?; - Ok(None) - }).expect("udpd: failed to listen to events on :udp"); - - event_queue.trigger_all(0).expect("udpd: failed to trigger event queue"); - - event_queue.run().expect("udpd: failed to run event queue"); + match syscall::open("ip:11", O_RDWR | O_NONBLOCK) { + Ok(udp_fd) => match syscall::open(":udp", O_RDWR | O_CREAT | O_NONBLOCK) { + Ok(scheme_fd) => { + // Daemonize + if unsafe { syscall::clone(0).unwrap() } == 0 { + daemon(udp_fd, scheme_fd); + } + }, + Err(err) => { + println!("udpd: failed to create udp scheme: {}", err); + process::exit(1); + } + }, + Err(err) => { + println!("udpd: failed to open ip:11: {}", err); + process::exit(1); + } } } From 49cbbb72ebb5e436c2c2724367a9fe465217232c Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 7 Feb 2017 20:53:54 -0700 Subject: [PATCH 127/522] Update submodules --- drivers | 2 +- programs/netutils | 2 +- programs/userutils | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers b/drivers index 911e20c..bd146da 160000 --- a/drivers +++ b/drivers @@ -1 +1 @@ -Subproject commit 911e20c177adddeb20ac9ea997e7e0c614b6d47a +Subproject commit bd146da9bcc96ccdb94d61163de83f31b21c0b4e diff --git a/programs/netutils b/programs/netutils index b4a1d37..852d860 160000 --- a/programs/netutils +++ b/programs/netutils @@ -1 +1 @@ -Subproject commit b4a1d3731d915e32c4f0c4bf844b6cc14e0097d9 +Subproject commit 852d860d41ebeac6e0c11669dbf3fc8c34d1b5fb diff --git a/programs/userutils b/programs/userutils index bb463a8..b1e0ae8 160000 --- a/programs/userutils +++ b/programs/userutils @@ -1 +1 @@ -Subproject commit bb463a8f02f359545041fe1fed677e2a7e6612f5 +Subproject commit b1e0ae872289385da79ed9856904161fde2128ec From 43ebfe06fbf00b00a7c7ead20444c7df59c9aa13 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 7 Feb 2017 22:16:11 -0700 Subject: [PATCH 128/522] Update kernel --- kernel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel b/kernel index be43673..571b2aa 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit be43673df68ec8e7e955f2991e94233e134234ca +Subproject commit 571b2aa2e700d37989e6df8e8f4fa1d55b76ba39 From 9de8be3c045939faa4a08b7d8335aa3e69ca34de Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 7 Feb 2017 22:18:13 -0700 Subject: [PATCH 129/522] Virtualbox fix --- mk/virtualbox.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mk/virtualbox.mk b/mk/virtualbox.mk index 6a0aa5b..a7d5d9d 100644 --- a/mk/virtualbox.mk +++ b/mk/virtualbox.mk @@ -31,7 +31,7 @@ virtualbox: build/harddrive.bin $(VBM) modifyvm Redox --mouse ps2 $(VBM) modifyvm Redox --audio $(VB_AUDIO) $(VBM) modifyvm Redox --audiocontroller ac97 - $(VBM) modifyvm Redox --nestedpaging off + $(VBM) modifyvm Redox --nestedpaging on echo "Create Disk" $(VBM) convertfromraw $< build/harddrive.vdi echo "Attach Disk" From 6fa887ff1812d87bb381f8ccdc752511bc498eae Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 7 Feb 2017 22:34:23 -0700 Subject: [PATCH 130/522] Update to fix network stack --- schemes/ethernetd/src/main.rs | 20 +++++++++++--------- schemes/ipd/src/main.rs | 20 +++++++++++--------- schemes/tcpd/src/main.rs | 20 +++++++++++--------- schemes/udpd/src/main.rs | 20 +++++++++++--------- 4 files changed, 44 insertions(+), 36 deletions(-) diff --git a/schemes/ethernetd/src/main.rs b/schemes/ethernetd/src/main.rs index 8444081..7185435 100644 --- a/schemes/ethernetd/src/main.rs +++ b/schemes/ethernetd/src/main.rs @@ -88,16 +88,18 @@ fn daemon(network_fd: usize, socket_fd: usize) { fn main() { match syscall::open("network:", syscall::O_RDWR | syscall::O_NONBLOCK) { - Ok(network_fd) => match syscall::open(":ethernet", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK) { - Ok(socket_fd) => { - // Daemonize - if unsafe { syscall::clone(0).unwrap() } == 0 { - daemon(network_fd, socket_fd); + Ok(network_fd) => { + // Daemonize + if unsafe { syscall::clone(0).unwrap() } == 0 { + match syscall::open(":ethernet", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK) { + Ok(socket_fd) => { + daemon(network_fd, socket_fd); + }, + Err(err) => { + println!("ethernetd: failed to create ethernet scheme: {}", err); + process::exit(1); + } } - }, - Err(err) => { - println!("ethernetd: failed to create ethernet scheme: {}", err); - process::exit(1); } }, Err(err) => { diff --git a/schemes/ipd/src/main.rs b/schemes/ipd/src/main.rs index 019a5e1..49e332f 100644 --- a/schemes/ipd/src/main.rs +++ b/schemes/ipd/src/main.rs @@ -314,16 +314,18 @@ fn daemon(arp_fd: usize, ip_fd: usize, scheme_fd: usize) { fn main() { match syscall::open("ethernet:806", syscall::O_RDWR | syscall::O_NONBLOCK) { Ok(arp_fd) => match syscall::open("ethernet:800", syscall::O_RDWR | syscall::O_NONBLOCK) { - Ok(ip_fd) => match syscall::open(":ip", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK) { - Ok(scheme_fd) => { - // Daemonize - if unsafe { syscall::clone(0).unwrap() } == 0 { - daemon(arp_fd, ip_fd, scheme_fd); + Ok(ip_fd) => { + // Daemonize + if unsafe { syscall::clone(0).unwrap() } == 0 { + match syscall::open(":ip", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK) { + Ok(scheme_fd) => { + daemon(arp_fd, ip_fd, scheme_fd); + }, + Err(err) => { + println!("ipd: failed to create ip scheme: {}", err); + process::exit(1); + } } - }, - Err(err) => { - println!("ipd: failed to create ip scheme: {}", err); - process::exit(1); } }, Err(err) => { diff --git a/schemes/tcpd/src/main.rs b/schemes/tcpd/src/main.rs index 9dfbd02..5344abf 100644 --- a/schemes/tcpd/src/main.rs +++ b/schemes/tcpd/src/main.rs @@ -809,16 +809,18 @@ fn daemon(tcp_fd: usize, scheme_fd: usize) { fn main() { match syscall::open("ip:6", O_RDWR | O_NONBLOCK) { - Ok(tcp_fd) => match syscall::open(":tcp", O_RDWR | O_CREAT | O_NONBLOCK) { - Ok(scheme_fd) => { - // Daemonize - if unsafe { syscall::clone(0).unwrap() } == 0 { - daemon(tcp_fd, scheme_fd); + Ok(tcp_fd) => { + // Daemonize + if unsafe { syscall::clone(0).unwrap() } == 0 { + match syscall::open(":tcp", O_RDWR | O_CREAT | O_NONBLOCK) { + Ok(scheme_fd) => { + daemon(tcp_fd, scheme_fd); + }, + Err(err) => { + println!("tcpd: failed to create tcp scheme: {}", err); + process::exit(1); + } } - }, - Err(err) => { - println!("tcpd: failed to create tcp scheme: {}", err); - process::exit(1); } }, Err(err) => { diff --git a/schemes/udpd/src/main.rs b/schemes/udpd/src/main.rs index 2c9396a..0715105 100644 --- a/schemes/udpd/src/main.rs +++ b/schemes/udpd/src/main.rs @@ -476,16 +476,18 @@ fn daemon(udp_fd: usize, scheme_fd: usize) { fn main() { match syscall::open("ip:11", O_RDWR | O_NONBLOCK) { - Ok(udp_fd) => match syscall::open(":udp", O_RDWR | O_CREAT | O_NONBLOCK) { - Ok(scheme_fd) => { - // Daemonize - if unsafe { syscall::clone(0).unwrap() } == 0 { - daemon(udp_fd, scheme_fd); + Ok(udp_fd) => { + // Daemonize + if unsafe { syscall::clone(0).unwrap() } == 0 { + match syscall::open(":udp", O_RDWR | O_CREAT | O_NONBLOCK) { + Ok(scheme_fd) => { + daemon(udp_fd, scheme_fd); + }, + Err(err) => { + println!("udpd: failed to create udp scheme: {}", err); + process::exit(1); + } } - }, - Err(err) => { - println!("udpd: failed to create udp scheme: {}", err); - process::exit(1); } }, Err(err) => { From ac1cd89b5cc5db76d4054d64463c6b0d599e5d43 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 8 Feb 2017 20:02:27 -0700 Subject: [PATCH 131/522] Update submodules --- programs/orbutils | 2 +- programs/smith | 2 +- rust | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/programs/orbutils b/programs/orbutils index 0625378..750b7ec 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 0625378daaa3fab76626e997080399cab25ce4ee +Subproject commit 750b7ec8c67cf16e454659258f5ef5589410d412 diff --git a/programs/smith b/programs/smith index 59f4a27..334ecdc 160000 --- a/programs/smith +++ b/programs/smith @@ -1 +1 @@ -Subproject commit 59f4a27981eb39292abb01220e10b1c7a0afbf5e +Subproject commit 334ecdcfd0cb1dc9c5b9af3e08377ab934de2b15 diff --git a/rust b/rust index 75a7eac..cbafac5 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 75a7eacd087db51f1ea06c71bba2451c53aed62c +Subproject commit cbafac5ba188f118d895bb075060081be3aa2800 From d56f6f0cd9a361755d922b8e3980459246eee9a9 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 11 Feb 2017 21:09:40 -0700 Subject: [PATCH 132/522] Update bootloader and kernel to fix IRQ issues --- bootloader | 2 +- kernel | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bootloader b/bootloader index 7639aef..eb3de28 160000 --- a/bootloader +++ b/bootloader @@ -1 +1 @@ -Subproject commit 7639aef32ed5ffd272701d955147b8b50aad53e0 +Subproject commit eb3de2861b532b31e633b10fbf14ae87d5980155 diff --git a/kernel b/kernel index 571b2aa..473a7b6 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 571b2aa2e700d37989e6df8e8f4fa1d55b76ba39 +Subproject commit 473a7b6832b9921b3353a6068773139bf6f13671 From 26c9dbced7782481493773880551cdfe405c8590 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 12 Feb 2017 10:40:34 -0700 Subject: [PATCH 133/522] Update ion and orbutils --- programs/ion | 2 +- programs/orbutils | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/programs/ion b/programs/ion index fc9c7c1..f2598f2 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit fc9c7c11f41b94970a44eef90d38909adc2270ed +Subproject commit f2598f2e23db7b11745dd95edaf1b1144ca2ac6a diff --git a/programs/orbutils b/programs/orbutils index 750b7ec..297f39a 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 750b7ec8c67cf16e454659258f5ef5589410d412 +Subproject commit 297f39a918f92759254fce12bc610dbdfc29fa33 From 52d640b591ef981dbe88d4585d80fee86cb2500d Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 13 Feb 2017 19:50:03 -0700 Subject: [PATCH 134/522] Update ion --- programs/ion | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/ion b/programs/ion index f2598f2..962c3ec 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit f2598f2e23db7b11745dd95edaf1b1144ca2ac6a +Subproject commit 962c3ec9e004a48bad9ed6913c7097a4286ba3e5 From 7bbceaeefd54b6be375632193b96cd247a5c1862 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 13 Feb 2017 22:17:11 -0700 Subject: [PATCH 135/522] Update drivers and kernel --- drivers | 2 +- kernel | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers b/drivers index bd146da..5b223c0 160000 --- a/drivers +++ b/drivers @@ -1 +1 @@ -Subproject commit bd146da9bcc96ccdb94d61163de83f31b21c0b4e +Subproject commit 5b223c06d0bcd4c936bad3ad6ec8324fd0ba16a6 diff --git a/kernel b/kernel index 473a7b6..b9793de 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit 473a7b6832b9921b3353a6068773139bf6f13671 +Subproject commit b9793deb59c7650f0805dea96adb6b773ad99336 From 4987b70e9772658a9e05dd6f7f2accd8482e13b4 Mon Sep 17 00:00:00 2001 From: Konrad Lipner Date: Wed, 15 Feb 2017 22:47:10 +0100 Subject: [PATCH 136/522] Change way to generate initfs for kernel this change should be merged along with corresponding PR in kernel --- mk/config.mk | 1 + mk/initfs.mk | 12 ------------ 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/mk/config.mk b/mk/config.mk index c20f426..2645973 100644 --- a/mk/config.mk +++ b/mk/config.mk @@ -40,6 +40,7 @@ KCARGOFLAGS=--target $(KTARGET) --release -- -C soft-float # Userspace variables export TARGET=$(ARCH)-unknown-redox BUILD=build/userspace +export INITFS_FOLDER=$(ROOT)/initfs RUSTC=./rustc.sh RUSTDOC=./rustdoc.sh CARGO=RUSTC="$(RUSTC)" RUSTDOC="$(RUSTDOC)" CARGO_INCREMENTAL=1 cargo diff --git a/mk/initfs.mk b/mk/initfs.mk index 7e9267b..6262de8 100644 --- a/mk/initfs.mk +++ b/mk/initfs.mk @@ -7,18 +7,6 @@ $(BUILD)/initfs.rs: \ initfs/bin/redoxfs \ initfs/bin/vesad \ initfs/etc/** - echo 'use collections::BTreeMap;' > $@ - echo 'pub fn gen() -> BTreeMap<&'"'"'static [u8], (&'"'"'static [u8], bool)> {' >> $@ - echo ' let mut files: BTreeMap<&'"'"'static [u8], (&'"'"'static [u8], bool)> = BTreeMap::new();' >> $@ - for folder in `find initfs -type d | sort`; do \ - name=$$(echo $$folder | sed 's/initfs//' | cut -d '/' -f2-) ; \ - $(ECHO) -n ' files.insert(b"'$$name'", (b"' >> $@ ; \ - ls -1 $$folder | sort | awk 'NR > 1 {printf("\\n")} {printf("%s", $$0)}' >> $@ ; \ - echo '", true));' >> $@ ; \ - done - find initfs -type f -o -type l | cut -d '/' -f2- | sort | awk '{printf(" files.insert(b\"%s\", (include_bytes!(\"../../initfs/%s\"), false));\n", $$0, $$0)}' >> $@ - echo ' files' >> $@ - echo '}' >> $@ initfs/bin/%: programs/%/Cargo.toml programs/%/src/** $(BUILD)/libstd.rlib mkdir -p initfs/bin From 639ed082aa59016c77817cb787fecbfa94a1d382 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 18 Feb 2017 11:31:05 -0700 Subject: [PATCH 137/522] Update submodules --- programs/coreutils | 2 +- schemes/orbital | 2 +- schemes/redoxfs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/programs/coreutils b/programs/coreutils index e589e09..3b04c66 160000 --- a/programs/coreutils +++ b/programs/coreutils @@ -1 +1 @@ -Subproject commit e589e0963036dcd782af438be38aca14f8691370 +Subproject commit 3b04c661b576fec6f29b3a91593c9e26840b8016 diff --git a/schemes/orbital b/schemes/orbital index c70e11f..6e34870 160000 --- a/schemes/orbital +++ b/schemes/orbital @@ -1 +1 @@ -Subproject commit c70e11f9e94a0bf445aa1c96243a514ee5b46d3e +Subproject commit 6e348708975e91ee9ceb33be1bcfb71aa31f34bf diff --git a/schemes/redoxfs b/schemes/redoxfs index fa6c19f..aff13c0 160000 --- a/schemes/redoxfs +++ b/schemes/redoxfs @@ -1 +1 @@ -Subproject commit fa6c19f79bf685db9022e2c4758fb3adb5c450dd +Subproject commit aff13c0d66bf885b6d2fe9cc33f06c49b77e709c From c4c8d6c35751a588166dcd88f26872120a2b3b72 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 18 Feb 2017 14:05:24 -0700 Subject: [PATCH 138/522] WIP: NVME support --- Cargo.toml | 1 + drivers | 2 +- initfs/etc/pcid.toml | 6 ++++++ mk/initfs.mk | 1 + mk/qemu.mk | 2 +- 5 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1201b64..1320928 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ members = [ "drivers/ahcid", "drivers/bgad", "drivers/e1000d", + "drivers/nvmed", "drivers/pcid", "drivers/ps2d", "drivers/rtl8168d", diff --git a/drivers b/drivers index 5b223c0..28dbc45 160000 --- a/drivers +++ b/drivers @@ -1 +1 @@ -Subproject commit 5b223c06d0bcd4c936bad3ad6ec8324fd0ba16a6 +Subproject commit 28dbc45637364b6ac68d2d091b6c5fa2420f3546 diff --git a/initfs/etc/pcid.toml b/initfs/etc/pcid.toml index 65813a7..9b7e348 100644 --- a/initfs/etc/pcid.toml +++ b/initfs/etc/pcid.toml @@ -4,6 +4,12 @@ class = 1 subclass = 6 command = ["ahcid", "$NAME", "$BAR5", "$IRQ"] +[[drivers]] +name = "NVME storage" +class = 1 +subclass = 8 +command = ["nvmed", "$NAME", "$BAR0", "$IRQ"] + [[drivers]] name = "Bochs Graphics Array" class = 3 diff --git a/mk/initfs.mk b/mk/initfs.mk index 7e9267b..b4e295c 100644 --- a/mk/initfs.mk +++ b/mk/initfs.mk @@ -2,6 +2,7 @@ $(BUILD)/initfs.rs: \ initfs/bin/init \ initfs/bin/ahcid \ initfs/bin/bgad \ + initfs/bin/nvmed \ initfs/bin/pcid \ initfs/bin/ps2d \ initfs/bin/redoxfs \ diff --git a/mk/qemu.mk b/mk/qemu.mk index 940b27e..c1a31da 100644 --- a/mk/qemu.mk +++ b/mk/qemu.mk @@ -36,7 +36,7 @@ qemu_no_build: qemu_extra: build/harddrive.bin if [ ! -e build/extra.bin ]; then dd if=/dev/zero of=build/extra.bin bs=1048576 count=1024; fi - $(QEMU) $(QEMUFLAGS) -drive file=$<,format=raw -drive file=build/extra.bin,format=raw + $(QEMU) $(QEMUFLAGS) -drive file=$<,format=raw -drive file=build/extra.bin,format=raw,if=none,id=drv0 -device nvme,drive=drv0,serial=NVME_SERIAL qemu_extra_no_build: if [ ! -e build/extra.bin ]; then dd if=/dev/zero of=build/extra.bin bs=1048576 count=1024; fi From fcc87b260d3b3e3dfe80ee645f93fa06b39afb57 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 18 Feb 2017 15:07:34 -0700 Subject: [PATCH 139/522] Update drivers --- drivers | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers b/drivers index 28dbc45..7be81d7 160000 --- a/drivers +++ b/drivers @@ -1 +1 @@ -Subproject commit 28dbc45637364b6ac68d2d091b6c5fa2420f3546 +Subproject commit 7be81d7837ee17d383402809ca4f904f4b5016a9 From 5b154111e0ec9fa14eb20f586bffed08c9a8071b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 18 Feb 2017 19:07:25 -0700 Subject: [PATCH 140/522] Update drivers --- drivers | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers b/drivers index 7be81d7..63dd228 160000 --- a/drivers +++ b/drivers @@ -1 +1 @@ -Subproject commit 7be81d7837ee17d383402809ca4f904f4b5016a9 +Subproject commit 63dd2286fe99535fd7eaca9c99f3c1e951f69dda From 2a4d57e16c102653677ff3b911c0a1a1fc94e085 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 18 Feb 2017 19:42:21 -0700 Subject: [PATCH 141/522] Update orbutils and orbital --- programs/orbutils | 2 +- schemes/orbital | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/programs/orbutils b/programs/orbutils index 297f39a..1fe9e49 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 297f39a918f92759254fce12bc610dbdfc29fa33 +Subproject commit 1fe9e4972911a31336ef47b04400c9e4dd46abde diff --git a/schemes/orbital b/schemes/orbital index 6e34870..0bcc947 160000 --- a/schemes/orbital +++ b/schemes/orbital @@ -1 +1 @@ -Subproject commit 6e348708975e91ee9ceb33be1bcfb71aa31f34bf +Subproject commit 0bcc9476afe5d1de8e8d6fcdd9b235b3776f9749 From 11bc60d3ca2cd9214a0b6e03e1727251f297f15f Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 19 Feb 2017 09:04:43 -0700 Subject: [PATCH 142/522] Update netutils, orbutils --- programs/netutils | 2 +- programs/orbutils | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/programs/netutils b/programs/netutils index 852d860..09214cc 160000 --- a/programs/netutils +++ b/programs/netutils @@ -1 +1 @@ -Subproject commit 852d860d41ebeac6e0c11669dbf3fc8c34d1b5fb +Subproject commit 09214ccb66813b67a9c939b2151d8c36b2194b3e diff --git a/programs/orbutils b/programs/orbutils index 1fe9e49..6d6690d 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 1fe9e4972911a31336ef47b04400c9e4dd46abde +Subproject commit 6d6690da59ba62ab6e0b0ba481eb75f21dd5d56e From 50e12475383caf5846be2ff23b8d4ade3e6796fe Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 20 Feb 2017 22:28:04 -0700 Subject: [PATCH 143/522] Use arc theme --- programs/orbutils | 2 +- schemes/orbital | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/programs/orbutils b/programs/orbutils index 6d6690d..3b0193c 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 6d6690da59ba62ab6e0b0ba481eb75f21dd5d56e +Subproject commit 3b0193c62f966baa46f2fb5c2bff6067196f6278 diff --git a/schemes/orbital b/schemes/orbital index 0bcc947..342e219 160000 --- a/schemes/orbital +++ b/schemes/orbital @@ -1 +1 @@ -Subproject commit 0bcc9476afe5d1de8e8d6fcdd9b235b3776f9749 +Subproject commit 342e21999a371fd480d428ddeabbaea6e80700b3 From 673e45560f56e650ebbc54d601d87a22b4a53936 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 21 Feb 2017 09:21:09 -0700 Subject: [PATCH 144/522] Update calculator --- programs/orbutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/orbutils b/programs/orbutils index 3b0193c..62d04cc 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 3b0193c62f966baa46f2fb5c2bff6067196f6278 +Subproject commit 62d04cccf9b54819dad3863c32c4247194b214aa From f520a9ff2e8c643671735c004780e5c6f129552c Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 22 Feb 2017 18:42:07 -0700 Subject: [PATCH 145/522] Update orbutils --- programs/orbutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/orbutils b/programs/orbutils index 62d04cc..ae19b3b 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 62d04cccf9b54819dad3863c32c4247194b214aa +Subproject commit ae19b3b6b60ff9dc1864eca2a8f732b5c4b0fefc From 6bfc4b233b1cafc6a8138b24e675a9e31f35902e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 22 Feb 2017 19:56:29 -0700 Subject: [PATCH 146/522] Update orbital --- filesystem/ui | 2 +- schemes/orbital | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/filesystem/ui b/filesystem/ui index 9d16c60..e865595 160000 --- a/filesystem/ui +++ b/filesystem/ui @@ -1 +1 @@ -Subproject commit 9d16c600c1fb7ac3899961d9caefd1abb3a41cea +Subproject commit e865595f8a47d970eaee2aabd4b027eb997cef8e diff --git a/schemes/orbital b/schemes/orbital index 342e219..a70688a 160000 --- a/schemes/orbital +++ b/schemes/orbital @@ -1 +1 @@ -Subproject commit 342e21999a371fd480d428ddeabbaea6e80700b3 +Subproject commit a70688a06c360105c46dacf51b5f637c2e78b006 From 44b4b842066e53bbc8ab9df4108d587dfac0db60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20K=C3=B6ppl?= Date: Thu, 23 Feb 2017 12:38:50 +0100 Subject: [PATCH 147/522] Fix typos in description --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8c42dd3..c2039de 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ **Redox** is an operating system written in Rust, a language with focus on safety and high performance. Redox, following the microkernel design, aims to be secure, usable, and free. Redox is inspired by previous kernels and operating systems, such as SeL4, Minix, Plan 9, and BSD. -Redox _is not_ just a kernel, it's a full-featured Operating System, providing packages (memory allocator, file system, display manager, core utilities, etc.) that together makes up a functional and convenient operating system. You can loosly think of it as the GNU or BSD ecosystem, but in a memory safe language and with modern technology. See [this list](#ecosystem) for overview of the ecosystem. +Redox _is not_ just a kernel, it's a full-featured Operating System, providing packages (memory allocator, file system, display manager, core utilities, etc.) that together make up a functional and convenient operating system. You can loosely think of it as the GNU or BSD ecosystem, but in a memory safe language and with modern technology. See [this list](#ecosystem) for overview of the ecosystem. The website can be found at https://www.redox-os.org. From f397c57e7baaeb8eac35045a12ff8923a6d4da31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20DESBRI=C3=88RES?= Date: Thu, 23 Feb 2017 16:36:03 +0100 Subject: [PATCH 148/522] + how to run redox-os from remote with qemu without graphic support --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index c2039de..3282255 100644 --- a/README.md +++ b/README.md @@ -146,7 +146,11 @@ $ make all # Launch using QEMU $ make qemu + # Launch using QEMU without using KVM (Kernel Virtual Machine). Try if QEMU gives an error. $ make qemu kvm=no + +# Launch using QEMU without using KVM (Kernel Virtual Machine) nor Graphics +make qemu kvm=no vga=no display=no ``` From 592c21b9c3e7b2b2983c174ae4930546e8e29070 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20DESBRI=C3=88RES?= Date: Thu, 23 Feb 2017 17:07:03 +0100 Subject: [PATCH 149/522] improvement on the qemu without graphic support --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3282255..7e28f81 100644 --- a/README.md +++ b/README.md @@ -151,6 +151,6 @@ $ make qemu $ make qemu kvm=no # Launch using QEMU without using KVM (Kernel Virtual Machine) nor Graphics -make qemu kvm=no vga=no display=no +make qemu kvm=no vga=no ``` From e6725019cd605f68dc6a31fe6c268c4a4b27a55d Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 23 Feb 2017 18:11:58 -0700 Subject: [PATCH 150/522] Update submodules --- programs/coreutils | 2 +- programs/orbutils | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/programs/coreutils b/programs/coreutils index 3b04c66..2648ad4 160000 --- a/programs/coreutils +++ b/programs/coreutils @@ -1 +1 @@ -Subproject commit 3b04c661b576fec6f29b3a91593c9e26840b8016 +Subproject commit 2648ad46174d69c778b42f09812b86a1ca74cf44 diff --git a/programs/orbutils b/programs/orbutils index ae19b3b..cedf46c 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit ae19b3b6b60ff9dc1864eca2a8f732b5c4b0fefc +Subproject commit cedf46ced8cbbb37bb8696e349e324a3af4b9049 From db2a1f647d0fd865b3e5263ac2cbb3f120509bae Mon Sep 17 00:00:00 2001 From: Adrian Neumann Date: Fri, 24 Feb 2017 19:25:39 +0100 Subject: [PATCH 151/522] Update bootstrap.sh On my OS X El Capitan machine `which` returns 1 if it can't find the binary. This kills the bootstrap script at the crucial moment when it detects that something needs to be installed. This change ignores unsuccessful exit codes from `which`. The man page for my `which` speaks of a `-s` switch that could be used instead of the `if [ -z`, but I don't know how portable this is. This fixes Issue 850. --- bootstrap.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap.sh b/bootstrap.sh index 5ea24b2..8d81ff7 100644 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -26,7 +26,7 @@ install_macos_pkg() BIN_NAME=$PKG_NAME fi - BIN_LOCATION=$(which $BIN_NAME) + BIN_LOCATION=$(which $BIN_NAME || true) if [ -z "$BIN_LOCATION" ]; then echo "$PKG_MANAGER install $PKG_NAME" $PKG_MANAGER install "$PKG_NAME" From f129f86aa83dd3330f9a17a42382d3da97091e79 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 24 Feb 2017 12:11:57 -0700 Subject: [PATCH 152/522] Update orbital and ui data --- filesystem/ui | 2 +- schemes/orbital | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/filesystem/ui b/filesystem/ui index e865595..c56caa7 160000 --- a/filesystem/ui +++ b/filesystem/ui @@ -1 +1 @@ -Subproject commit e865595f8a47d970eaee2aabd4b027eb997cef8e +Subproject commit c56caa736fe946766b79cfbe6513b3ffe706f59e diff --git a/schemes/orbital b/schemes/orbital index a70688a..9740671 160000 --- a/schemes/orbital +++ b/schemes/orbital @@ -1 +1 @@ -Subproject commit a70688a06c360105c46dacf51b5f637c2e78b006 +Subproject commit 9740671176626aa8fa9362b3b810078d27df3e8b From c33dcd81b45c9949bd4ef53155e7460dbdae05fd Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 24 Feb 2017 13:15:35 -0700 Subject: [PATCH 153/522] Use patched jpeg-decoder to work around threading issue --- Cargo.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 1320928..4f53a37 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,3 +35,6 @@ members = [ "schemes/tcpd", "schemes/udpd" ] + +[replace] +"jpeg-decoder:0.1.11" = { git = "https://github.com/redox-os/jpeg-decoder", branch="single_thread" } From b6bcdba5e7e30b3573ae95bb315ff13acbc276fe Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 24 Feb 2017 13:21:41 -0700 Subject: [PATCH 154/522] Update drivers --- drivers | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers b/drivers index 63dd228..975082c 160000 --- a/drivers +++ b/drivers @@ -1 +1 @@ -Subproject commit 63dd2286fe99535fd7eaca9c99f3c1e951f69dda +Subproject commit 975082c18abfc7c48ab24ba9a30da6a9ebad8717 From 189706362654f441f4f876935e37e2c796c122fe Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 24 Feb 2017 13:26:27 -0700 Subject: [PATCH 155/522] Update drivers --- drivers | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers b/drivers index 975082c..96fbf16 160000 --- a/drivers +++ b/drivers @@ -1 +1 @@ -Subproject commit 975082c18abfc7c48ab24ba9a30da6a9ebad8717 +Subproject commit 96fbf1658fcc45fa82c0eefd7c67dd7ac6b59dba From b95d5380bd8ed421d689d0e4e5697b64f0f8d073 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 24 Feb 2017 16:07:27 -0700 Subject: [PATCH 156/522] Update ui and orbutils to use moka icons --- filesystem/ui | 2 +- programs/orbutils | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/filesystem/ui b/filesystem/ui index c56caa7..0657ad3 160000 --- a/filesystem/ui +++ b/filesystem/ui @@ -1 +1 @@ -Subproject commit c56caa736fe946766b79cfbe6513b3ffe706f59e +Subproject commit 0657ad3d1179b9177374bb58291df923f8d8ddf4 diff --git a/programs/orbutils b/programs/orbutils index cedf46c..eccca9d 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit cedf46ced8cbbb37bb8696e349e324a3af4b9049 +Subproject commit eccca9d4781abbcd9aa104fea078f4e7bb869dcd From f76a822a28b6be6efe21498294255b78d4a7d2ea Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 24 Feb 2017 16:58:05 -0700 Subject: [PATCH 157/522] Update icon sizes --- programs/orbutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/orbutils b/programs/orbutils index eccca9d..59165e4 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit eccca9d4781abbcd9aa104fea078f4e7bb869dcd +Subproject commit 59165e4f340b09537d4437b48c186082bed7bcb9 From fddde2824c3eacfaa156c2590b1482f7bbdce067 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 24 Feb 2017 17:54:56 -0700 Subject: [PATCH 158/522] Update orbital and orbutils --- programs/orbutils | 2 +- schemes/orbital | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/programs/orbutils b/programs/orbutils index 59165e4..ea64b96 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 59165e4f340b09537d4437b48c186082bed7bcb9 +Subproject commit ea64b969b04755cea800914b010b05d7e8f6e786 diff --git a/schemes/orbital b/schemes/orbital index 9740671..e8a880b 160000 --- a/schemes/orbital +++ b/schemes/orbital @@ -1 +1 @@ -Subproject commit 9740671176626aa8fa9362b3b810078d27df3e8b +Subproject commit e8a880b708c74b1fb3220fcc8a9bbbd1d5eae2c1 From 61f1892a02016aee335cce29cba1e17aef25db3a Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 24 Feb 2017 18:07:52 -0700 Subject: [PATCH 159/522] Update extrautils --- programs/extrautils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/extrautils b/programs/extrautils index 2a770bd..e3d0154 160000 --- a/programs/extrautils +++ b/programs/extrautils @@ -1 +1 @@ -Subproject commit 2a770bdf6b2979a89e7b128830083fa1d049357a +Subproject commit e3d01545626229ccc5ede0908ca6c6862f571c4b From 6ed622ff02eec5dd7d6af7e97c4d8da26e496db5 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 24 Feb 2017 19:08:20 -0700 Subject: [PATCH 160/522] Update terminal --- programs/orbutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/orbutils b/programs/orbutils index ea64b96..483e35e 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit ea64b969b04755cea800914b010b05d7e8f6e786 +Subproject commit 483e35e74ec020063a8f6eb6d1aa48fdd624fdf0 From 6d63f9bba79bbc499d95b73a36af473a5f77dd7b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 24 Feb 2017 19:34:29 -0700 Subject: [PATCH 161/522] Replace liner to fix tab completion --- Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 4f53a37..db3c91b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,4 +37,5 @@ members = [ ] [replace] -"jpeg-decoder:0.1.11" = { git = "https://github.com/redox-os/jpeg-decoder", branch="single_thread" } +"jpeg-decoder:0.1.11" = { git = "https://github.com/redox-os/jpeg-decoder.git", branch = "single_thread" } +"liner:0.1.3" = { git = "https://github.com/redox-os/liner.git", branch = "redox" } From f796adee3fcb2ebbf5c773f2473025f2e2571a68 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 25 Feb 2017 08:15:55 -0700 Subject: [PATCH 162/522] Update viewer --- programs/orbutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/orbutils b/programs/orbutils index 483e35e..6d78211 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 483e35e74ec020063a8f6eb6d1aa48fdd624fdf0 +Subproject commit 6d782112f1a4612983efa51d19c1aa34f69b2ecf From 9069ddf59b70ff8562bdbf2d97e8ceab942b6b8a Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 25 Feb 2017 09:02:42 -0700 Subject: [PATCH 163/522] Update orbital and orbutils --- programs/orbutils | 2 +- schemes/orbital | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/programs/orbutils b/programs/orbutils index 6d78211..2dd58f5 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 6d782112f1a4612983efa51d19c1aa34f69b2ecf +Subproject commit 2dd58f579510960344a7675588f4852a182f96e2 diff --git a/schemes/orbital b/schemes/orbital index e8a880b..cad6327 160000 --- a/schemes/orbital +++ b/schemes/orbital @@ -1 +1 @@ -Subproject commit e8a880b708c74b1fb3220fcc8a9bbbd1d5eae2c1 +Subproject commit cad63270ed2b617aa0d180b1fd400341eb17385a From 4c4991e57193466f7f3674e8186cf2982de8a9c0 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 25 Feb 2017 10:18:32 -0700 Subject: [PATCH 164/522] Update orbutils --- programs/orbutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/orbutils b/programs/orbutils index 2dd58f5..483e35e 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 2dd58f579510960344a7675588f4852a182f96e2 +Subproject commit 483e35e74ec020063a8f6eb6d1aa48fdd624fdf0 From 640fc4be5ef958811ce62450610324573ab7b316 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 25 Feb 2017 10:20:15 -0700 Subject: [PATCH 165/522] Update orbutils --- programs/orbutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/orbutils b/programs/orbutils index 483e35e..2dd58f5 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 483e35e74ec020063a8f6eb6d1aa48fdd624fdf0 +Subproject commit 2dd58f579510960344a7675588f4852a182f96e2 From 3fcd9d7526361714d6a410a7aa76e175353147b5 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 25 Feb 2017 10:22:16 -0700 Subject: [PATCH 166/522] Update orbutils --- programs/orbutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/orbutils b/programs/orbutils index 2dd58f5..9a0b108 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 2dd58f579510960344a7675588f4852a182f96e2 +Subproject commit 9a0b108b5ebf45e103c52a14835903372468b035 From c7ad8bff68824291e6153ed717fdb486066dd480 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 25 Feb 2017 10:38:19 -0700 Subject: [PATCH 167/522] Update file manager --- programs/orbutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/orbutils b/programs/orbutils index 9a0b108..a535cb2 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 9a0b108b5ebf45e103c52a14835903372468b035 +Subproject commit a535cb285206e50cb2e8cb369193487a39022f15 From edbd4c3152d266562d630b3322d1bf5e37106d85 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 25 Feb 2017 11:03:36 -0700 Subject: [PATCH 168/522] Update orbital --- schemes/orbital | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schemes/orbital b/schemes/orbital index cad6327..32e045f 160000 --- a/schemes/orbital +++ b/schemes/orbital @@ -1 +1 @@ -Subproject commit cad63270ed2b617aa0d180b1fd400341eb17385a +Subproject commit 32e045f95ea77cd27c19392566089920b79086b7 From 7e72e0e80f54cd4d48579df045069e2b795f2498 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 25 Feb 2017 11:31:22 -0700 Subject: [PATCH 169/522] Update orbutils --- programs/orbutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/orbutils b/programs/orbutils index a535cb2..efcc1fa 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit a535cb285206e50cb2e8cb369193487a39022f15 +Subproject commit efcc1faa2c52ac5408dadb52c4a65b09c522265e From c0862fc2991d453f5c8c25448039c90aa62a1e88 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 25 Feb 2017 12:42:07 -0700 Subject: [PATCH 170/522] Update orbital to add multiple backgrounds --- schemes/orbital | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schemes/orbital b/schemes/orbital index 32e045f..693407e 160000 --- a/schemes/orbital +++ b/schemes/orbital @@ -1 +1 @@ -Subproject commit 32e045f95ea77cd27c19392566089920b79086b7 +Subproject commit 693407e4822012434835722606e807c1f82964da From 57316be4c84f5bbd977337959388c5b0c06ca0b4 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 25 Feb 2017 14:48:09 -0700 Subject: [PATCH 171/522] Update orbital to add resize, rename, reposition --- schemes/orbital | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schemes/orbital b/schemes/orbital index 693407e..edea153 160000 --- a/schemes/orbital +++ b/schemes/orbital @@ -1 +1 @@ -Subproject commit 693407e4822012434835722606e807c1f82964da +Subproject commit edea1531bc0c402b93bdb24a88c18997113b2334 From db8f6c558515790c00e87450244738bb76f9b5f7 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 27 Feb 2017 12:20:29 -0700 Subject: [PATCH 172/522] Update submodules and rust --- kernel | 2 +- programs/orbutils | 2 +- rust | 2 +- schemes/orbital | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel b/kernel index b9793de..7dd8de7 160000 --- a/kernel +++ b/kernel @@ -1 +1 @@ -Subproject commit b9793deb59c7650f0805dea96adb6b773ad99336 +Subproject commit 7dd8de777dca78c6608e8215d10d936edf8f5322 diff --git a/programs/orbutils b/programs/orbutils index efcc1fa..7177553 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit efcc1faa2c52ac5408dadb52c4a65b09c522265e +Subproject commit 71775532c4c68a5fbf1a0a7efd15764526ab1830 diff --git a/rust b/rust index cbafac5..0ed75e1 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit cbafac5ba188f118d895bb075060081be3aa2800 +Subproject commit 0ed75e1f47d099a17de22eb2c1d2b43ce89ea390 diff --git a/schemes/orbital b/schemes/orbital index edea153..bec45fe 160000 --- a/schemes/orbital +++ b/schemes/orbital @@ -1 +1 @@ -Subproject commit edea1531bc0c402b93bdb24a88c18997113b2334 +Subproject commit bec45fed0695275d5170fba91323d8a52d38236b From 44c75654d3b38c91c9a91bfdeabe5fff1e1e3d37 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 27 Feb 2017 15:35:01 -0700 Subject: [PATCH 173/522] Update userutils --- programs/userutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/userutils b/programs/userutils index b1e0ae8..1ee223f 160000 --- a/programs/userutils +++ b/programs/userutils @@ -1 +1 @@ -Subproject commit b1e0ae872289385da79ed9856904161fde2128ec +Subproject commit 1ee223f9267113c8fb9e7db10c3704e768c2e9c4 From 59933df503b60b1d7fec31c80d2a0a3148fa88bf Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 27 Feb 2017 21:50:51 -0700 Subject: [PATCH 174/522] Update submodules --- drivers | 2 +- programs/orbutils | 2 +- schemes/orbital | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers b/drivers index 96fbf16..f4d6fbb 160000 --- a/drivers +++ b/drivers @@ -1 +1 @@ -Subproject commit 96fbf1658fcc45fa82c0eefd7c67dd7ac6b59dba +Subproject commit f4d6fbb4a2db985947e421718147d1956d62767c diff --git a/programs/orbutils b/programs/orbutils index 7177553..dfdd4fd 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 71775532c4c68a5fbf1a0a7efd15764526ab1830 +Subproject commit dfdd4fd07bcb00aa93429a72f1b38b6c715bfc5c diff --git a/schemes/orbital b/schemes/orbital index bec45fe..b3f1386 160000 --- a/schemes/orbital +++ b/schemes/orbital @@ -1 +1 @@ -Subproject commit bec45fed0695275d5170fba91323d8a52d38236b +Subproject commit b3f1386cc77670098f63003c854c4cf917fe7cd9 From a0ec4212caeba2ae28599fbaed1e63fc7b6cdb1e Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Tue, 28 Feb 2017 11:14:47 -0800 Subject: [PATCH 175/522] Set $(RUSTC) to full path This fixes builds of crates that use rustc_version to test the Rust version in their build scripts. --- mk/config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mk/config.mk b/mk/config.mk index 2645973..b6567e9 100644 --- a/mk/config.mk +++ b/mk/config.mk @@ -41,7 +41,7 @@ KCARGOFLAGS=--target $(KTARGET) --release -- -C soft-float export TARGET=$(ARCH)-unknown-redox BUILD=build/userspace export INITFS_FOLDER=$(ROOT)/initfs -RUSTC=./rustc.sh +RUSTC=$(PWD)/rustc.sh RUSTDOC=./rustdoc.sh CARGO=RUSTC="$(RUSTC)" RUSTDOC="$(RUSTDOC)" CARGO_INCREMENTAL=1 cargo CARGOFLAGS=--target $(TARGET) --release -- -C codegen-units=`$(NPROC)` From 3b9a9fa3fe14e64716a7f16f3271c1a43f94616b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 1 Mar 2017 10:57:00 -0700 Subject: [PATCH 176/522] Update orbutils --- programs/orbutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/orbutils b/programs/orbutils index dfdd4fd..d3fe5ff 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit dfdd4fd07bcb00aa93429a72f1b38b6c715bfc5c +Subproject commit d3fe5ffca3f7601fd029ace1e8d8caad2af5d0b7 From 3f7db32ccf78d1a6af5387c6cada34560fd6c9ca Mon Sep 17 00:00:00 2001 From: Clint Byrum Date: Fri, 3 Mar 2017 20:38:34 -0800 Subject: [PATCH 177/522] Remove erroneous -b option from bootstrap.sh help The help also tells you to use './bootstrap.sh' but the file wasn't +x in the repo, so I've set that +x as well. This closes issue #852 --- bootstrap.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 bootstrap.sh diff --git a/bootstrap.sh b/bootstrap.sh old mode 100644 new mode 100755 index 8d81ff7..643634f --- a/bootstrap.sh +++ b/bootstrap.sh @@ -350,7 +350,7 @@ usage() echo " -d Only install the dependencies, skip boot step" echo "EXAMPLES:" echo - echo "./bootstrap.sh -b buddy -e qemu" + echo "./bootstrap.sh -e qemu" exit } From 9a536df40c8b676d2433e478d9b73966af51623e Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Sat, 4 Mar 2017 21:36:23 -0800 Subject: [PATCH 178/522] Correction to pkgutils.mk --- mk/userspace/pkgutils.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mk/userspace/pkgutils.mk b/mk/userspace/pkgutils.mk index 7bf80cc..156c532 100644 --- a/mk/userspace/pkgutils.mk +++ b/mk/userspace/pkgutils.mk @@ -1,7 +1,7 @@ pkgutils: \ filesystem/bin/pkg -filesystem/bin/%: programs/pkgutils/Cargo.toml programs/pkgutils/src/bin/%.rs $(BUILD)/libstd.rlib +filesystem/bin/%: programs/pkgutils/Cargo.toml programs/pkgutils/src/*.rs programs/pkgutils/src/bin/%.rs $(BUILD)/libstd.rlib mkdir -p filesystem/bin $(CARGO) rustc --manifest-path $< --bin $* $(CARGOFLAGS) -o $@ $(STRIP) $@ From 7fb69e275fda52d78e2ee8941fdb823398f1eda9 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 5 Mar 2017 10:05:32 -0700 Subject: [PATCH 179/522] Update submodules --- drivers | 2 +- programs/ion | 2 +- programs/netutils | 2 +- programs/orbutils | 2 +- programs/pkgutils | 2 +- schemes/orbital | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers b/drivers index f4d6fbb..8b14b58 160000 --- a/drivers +++ b/drivers @@ -1 +1 @@ -Subproject commit f4d6fbb4a2db985947e421718147d1956d62767c +Subproject commit 8b14b587b9ebbb6986ccb2b354eecc12e19505b6 diff --git a/programs/ion b/programs/ion index 962c3ec..ec26f98 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit 962c3ec9e004a48bad9ed6913c7097a4286ba3e5 +Subproject commit ec26f983da952e8682e4287ab6279bebb81979b3 diff --git a/programs/netutils b/programs/netutils index 09214cc..b252355 160000 --- a/programs/netutils +++ b/programs/netutils @@ -1 +1 @@ -Subproject commit 09214ccb66813b67a9c939b2151d8c36b2194b3e +Subproject commit b252355a9838d3be06d9446e6443c59c6d0a3305 diff --git a/programs/orbutils b/programs/orbutils index d3fe5ff..57fa206 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit d3fe5ffca3f7601fd029ace1e8d8caad2af5d0b7 +Subproject commit 57fa2065c46d83bebd00684e0ef824d66ac0f1bf diff --git a/programs/pkgutils b/programs/pkgutils index e612859..ffb3069 160000 --- a/programs/pkgutils +++ b/programs/pkgutils @@ -1 +1 @@ -Subproject commit e6128591b27924718d727a5b6c5da495ba066111 +Subproject commit ffb30696a86de68c0c26563957fadaab8f9f657c diff --git a/schemes/orbital b/schemes/orbital index b3f1386..ed8d56d 160000 --- a/schemes/orbital +++ b/schemes/orbital @@ -1 +1 @@ -Subproject commit b3f1386cc77670098f63003c854c4cf917fe7cd9 +Subproject commit ed8d56d6ca62977cfb1a58d640ed95ce1434cd3f From 0ee9caac260972571fa1f8b136ca15716df6c8b7 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 6 Mar 2017 07:36:35 -0700 Subject: [PATCH 180/522] Update ion and orbutils --- programs/ion | 2 +- programs/orbutils | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/programs/ion b/programs/ion index ec26f98..9f16359 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit ec26f983da952e8682e4287ab6279bebb81979b3 +Subproject commit 9f16359d7372dd5e435f50a25e3f8dd242ced52c diff --git a/programs/orbutils b/programs/orbutils index 57fa206..6226ee6 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 57fa2065c46d83bebd00684e0ef824d66ac0f1bf +Subproject commit 6226ee6ed6adf2a8708c0b36d62695d48b895ae6 From 18e4319eb2f850fbcfacdfc33c54820498ad3676 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 6 Mar 2017 16:56:34 -0700 Subject: [PATCH 181/522] Update ion --- programs/ion | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/ion b/programs/ion index 9f16359..92c13c2 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit 9f16359d7372dd5e435f50a25e3f8dd242ced52c +Subproject commit 92c13c28cbb637a0c0cc5ecea75360bcf9a1b051 From e71211f7778b532899addd96b4f790272b9b5895 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 6 Mar 2017 20:57:09 -0700 Subject: [PATCH 182/522] Update to add resize cursors --- filesystem/ui | 2 +- schemes/orbital | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/filesystem/ui b/filesystem/ui index 0657ad3..fc6e179 160000 --- a/filesystem/ui +++ b/filesystem/ui @@ -1 +1 @@ -Subproject commit 0657ad3d1179b9177374bb58291df923f8d8ddf4 +Subproject commit fc6e179e7f897aba90f1d7e51409c77830647f9a diff --git a/schemes/orbital b/schemes/orbital index ed8d56d..baa6fda 160000 --- a/schemes/orbital +++ b/schemes/orbital @@ -1 +1 @@ -Subproject commit ed8d56d6ca62977cfb1a58d640ed95ce1434cd3f +Subproject commit baa6fdac85e2df29c22f455ab5406a71b2a6ce97 From 33a61073d59f8b9bbff8f388fa27a0be3ba286cd Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 7 Mar 2017 17:30:01 -0700 Subject: [PATCH 183/522] Update ion --- programs/ion | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/ion b/programs/ion index 92c13c2..7356513 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit 92c13c28cbb637a0c0cc5ecea75360bcf9a1b051 +Subproject commit 7356513e65e8f416eae34e8a1a705fb5810177e7 From ff378af2cea4302d99c265928d3ee6251f0f2137 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 7 Mar 2017 20:25:29 -0700 Subject: [PATCH 184/522] Update app definitions --- filesystem/ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/filesystem/ui b/filesystem/ui index fc6e179..638f87f 160000 --- a/filesystem/ui +++ b/filesystem/ui @@ -1 +1 @@ -Subproject commit fc6e179e7f897aba90f1d7e51409c77830647f9a +Subproject commit 638f87fe766b84d635f19806f52d041fe88e1743 From e396cf18e7d66f122fe62d5f478e76e77e5b7d94 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 8 Mar 2017 15:01:54 -0700 Subject: [PATCH 185/522] Update ion, orbutils to add title to terminal --- drivers | 2 +- programs/ion | 2 +- programs/orbutils | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers b/drivers index 8b14b58..fe65978 160000 --- a/drivers +++ b/drivers @@ -1 +1 @@ -Subproject commit 8b14b587b9ebbb6986ccb2b354eecc12e19505b6 +Subproject commit fe65978ac46cbfd33851f09c985a212d01084499 diff --git a/programs/ion b/programs/ion index 7356513..19c2f02 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit 7356513e65e8f416eae34e8a1a705fb5810177e7 +Subproject commit 19c2f026d500e5335e985966ddb407d44524be65 diff --git a/programs/orbutils b/programs/orbutils index 6226ee6..db89789 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit 6226ee6ed6adf2a8708c0b36d62695d48b895ae6 +Subproject commit db897893e79462a71b2e14b8d3ff723c41efd345 From a4ae555b2b1d5ad69e83f8c2287034e58d195781 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 9 Mar 2017 20:37:13 -0700 Subject: [PATCH 186/522] Enable test command --- mk/userspace/coreutils.mk | 3 ++- programs/coreutils | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/mk/userspace/coreutils.mk b/mk/userspace/coreutils.mk index 117644c..672df07 100644 --- a/mk/userspace/coreutils.mk +++ b/mk/userspace/coreutils.mk @@ -30,13 +30,14 @@ coreutils: \ filesystem/bin/sort \ filesystem/bin/tail \ filesystem/bin/tee \ + filesystem/bin/test \ filesystem/bin/time \ filesystem/bin/touch \ filesystem/bin/true \ filesystem/bin/wc \ filesystem/bin/which \ filesystem/bin/yes - #filesystem/bin/shutdown filesystem/bin/test + #filesystem/bin/shutdown filesystem/bin/%: programs/coreutils/Cargo.toml programs/coreutils/src/bin/%.rs $(BUILD)/libstd.rlib mkdir -p filesystem/bin diff --git a/programs/coreutils b/programs/coreutils index 2648ad4..6637651 160000 --- a/programs/coreutils +++ b/programs/coreutils @@ -1 +1 @@ -Subproject commit 2648ad46174d69c778b42f09812b86a1ca74cf44 +Subproject commit 66376514f0b2ba55657b17549a7b02cffc7786af From a227bb50c939b9d47ed8da6764694d9fa1e54eca Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 9 Mar 2017 20:37:21 -0700 Subject: [PATCH 187/522] Update ion --- programs/ion | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/ion b/programs/ion index 19c2f02..2c20f84 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit 19c2f026d500e5335e985966ddb407d44524be65 +Subproject commit 2c20f84a85fc74977db31a7d02eb94b21822cbb6 From 388a4fe56e00a3bde62326c7e325272307f4490a Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 14 Mar 2017 21:14:37 -0600 Subject: [PATCH 188/522] Update programs --- programs/acid | 2 +- programs/extrautils | 2 +- programs/ion | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/programs/acid b/programs/acid index 2b029b4..99b7633 160000 --- a/programs/acid +++ b/programs/acid @@ -1 +1 @@ -Subproject commit 2b029b432b32070b94c443dfdd064a9dc5e25ab0 +Subproject commit 99b7633a0a8b23befecb3703f1b7c06603cf7ba4 diff --git a/programs/extrautils b/programs/extrautils index e3d0154..a2dc3d7 160000 --- a/programs/extrautils +++ b/programs/extrautils @@ -1 +1 @@ -Subproject commit e3d01545626229ccc5ede0908ca6c6862f571c4b +Subproject commit a2dc3d7d0e6337645aad070ee2895bbb96d2e3d2 diff --git a/programs/ion b/programs/ion index 2c20f84..b7340c5 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit 2c20f84a85fc74977db31a7d02eb94b21822cbb6 +Subproject commit b7340c5edf811e1369b562e6f39a7decd10ab029 From ec545767c17c8b83c1e67596758125a17281e37b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 15 Mar 2017 19:42:29 -0600 Subject: [PATCH 189/522] Update redoxfs --- schemes/redoxfs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schemes/redoxfs b/schemes/redoxfs index aff13c0..3db0c2a 160000 --- a/schemes/redoxfs +++ b/schemes/redoxfs @@ -1 +1 @@ -Subproject commit aff13c0d66bf885b6d2fe9cc33f06c49b77e709c +Subproject commit 3db0c2a4b1011a90b9d790f8be89436d07318166 From 404cec085c470f216a89d2516252978a9281ddf2 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 15 Mar 2017 21:09:31 -0600 Subject: [PATCH 190/522] Update submodules, fix issue with nightly rust --- Cargo.toml | 1 + programs/ion | 2 +- programs/orbutils | 2 +- programs/smith | 2 +- rust | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index db3c91b..7e38736 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,3 +39,4 @@ members = [ [replace] "jpeg-decoder:0.1.11" = { git = "https://github.com/redox-os/jpeg-decoder.git", branch = "single_thread" } "liner:0.1.3" = { git = "https://github.com/redox-os/liner.git", branch = "redox" } +"rustls:0.5.7" = { git = "https://github.com/ctz/rustls.git" } diff --git a/programs/ion b/programs/ion index b7340c5..5a6a5b9 160000 --- a/programs/ion +++ b/programs/ion @@ -1 +1 @@ -Subproject commit b7340c5edf811e1369b562e6f39a7decd10ab029 +Subproject commit 5a6a5b9dde4629844adfee6cbfc970b4c9711046 diff --git a/programs/orbutils b/programs/orbutils index db89789..e4d585d 160000 --- a/programs/orbutils +++ b/programs/orbutils @@ -1 +1 @@ -Subproject commit db897893e79462a71b2e14b8d3ff723c41efd345 +Subproject commit e4d585dba61513eed760941f07d1475759a86be5 diff --git a/programs/smith b/programs/smith index 334ecdc..41596f2 160000 --- a/programs/smith +++ b/programs/smith @@ -1 +1 @@ -Subproject commit 334ecdcfd0cb1dc9c5b9af3e08377ab934de2b15 +Subproject commit 41596f26c0d19278cf2c953569740048fe72011e diff --git a/rust b/rust index 0ed75e1..0aeb9c1 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 0ed75e1f47d099a17de22eb2c1d2b43ce89ea390 +Subproject commit 0aeb9c12979e6da753701a798d04105b6b1a8c28 From b6b1b44b205a855c130bde1628a8edd85198641c Mon Sep 17 00:00:00 2001 From: xTibor Date: Thu, 16 Mar 2017 21:48:35 +0100 Subject: [PATCH 191/522] Update README.md Fixed the squashed logo on mobile Fixed the capitalization of Vim, Rust and Orbital Added missing, removed surplus parentheses --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 7e28f81..9962e4f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@