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 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

B5T#Xf9$tvoyc6`w% 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 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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

{TRS<6G*5Y~{=pK^&( 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�^m8Q=9x7t+gX8$M*cIpjsIjQ!3JDZn$ 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%0D#z`kA+{Sx*nm86W7V_QBd za-Krn_X~Bg3|@{q^&NR!QfA!9OLb53AGMzlzetM_w#yxPNauYeT|h$7sTV#zRUJRn zDf2t_v@i50&!aVRC!B0KAFw_H$U_^C6iq?*j^!%b0g=9>9Uoqocor3tEC6LFerbt7#y;#KF%$mv-7DpVbx-}0q zDht~N@rH&}`$+c0f;fZ&7x-@#+Z)E#8DB3M9XCO#lu`LP&NcP$3cbL`^SabykZ0|K zmrCOC*cc%1y*MHkf@sGVeq>>e3Ov@{=M#h*C8Pnmd|i{uaNzP#w$_&Js@!w}j| z(|O9Vmu-m$Lq;9v6L&muHl;(J*~=L_W1G$RDQvp!Y4-aIaB==}$^4=G*1XFe5jCbx z=}%oD;*aoe)QA3Psr18;C==XQFGw_6a?<{=go01%E$W9${tsnct?lnRJyn5cx_}_Y z|8?FkAwkfr%NFg|oAsxZ{9oI6d4tXEs9AlgO4N$y;a@IqBl6Z0&6%eR8zs8tUUuyP zJ7^kDF&f5mIV9SU-}Ij%A0F(w`!lBpe)jv;*WgNe98LSLu`}y5zTf!jdrre?AWylR zrM-Q0P_|RT-(SGq-X8~Efs6JOztaq#V$N;!hL?T&K=)kJeJW!g?EWs`nD$R3*u_)R z-9`L^>5q)Q*1wCs=19i#kH))z9)XwOBh9~j>J1RQP8*|vZ|nyWy_R?tY&^7QO8iC3nQS?m zjk88<8YyefTPfCZ%KF$_cNl-lj@D(|@^+Uc+W3#n?}k5x^4QB&es-c_aX;pCusmd` zlztC;Vrf}q=O{y~P6K|)!xk=1YsWM*!t=mD0^?#EfX?9$kYqrwM>QlgP&FKK zfGwCahR*^vJjh$Hy>ZRr7;7pLeV0W$?B-+e(qc0tH+HdwIf{K0HYZq7adKc!HOBvV zE@_`Wj{h#3fqGCj1LU;>CGe%oLYGvoA?0VuOC-NS| z1lAZ)b_4%tEcSmQs}@=Jr?&j>>$J&evM{;#{qXtV`G>F==XrduXz7Uf{2bLO!>0t| zt;RR)ZC#q9ed{P%j(p+hw^aX$H`Jo|^r5^zw--D5qkZ|ly{C@`(*E9`29x5OP-q?_ zUR(rkUKmo|MAfmPHoJ72>Q8)(1b*Pnrvhv+iP{{EO|_qY{wN-g0iKU|cU1G2^L@vf zc|VvsdQ2lYF*V{H22X#C^LHrGy{958$R`}9-;sav{>RAQ^JPna>pBgGOQT=b0iXWZsW=td6Jr7G z4((TBhqHzDlr19^02SchZ}j)~%q8tR^q}eYTv81?_gw1Hd+;yquQ*YUwq5IQNjtnB z_qg)8M}4>9iF@n;M_NhB>|FK!6Fqj1MVdAbIFM)z=tR->HSM^}1pc1*55E#jt&GR& z_ZXj-lx3vJIC)>uClm^O_K@#P`Q^fI6P`-^E8638fJ^mn_9NZERcpF`2K+Jqz@6Yj z{Z{zY9lhsDzxwX<--EY`?1!uPAntl+JRuffLH{nwte5^u5Au{AyodO$srSLFgZIvM z2@fc6tnCl)Wnv4M`S>{b4)eR!^8xL}{TZ2Mykph+O8k|@|FGXnBBu9GIWs**#~WGv zYh_(3{P}r4$EJcA8GqvU3I%F;;zD)F{MQotU_4fre)PutuDtco9Q_RBpVX{-9H-9w z5W`B%Zw<-`od#@V;{1-Lc(dm$Q)85K2$^X=?#H(E%vVW&8(wzAN(!v|5h=y%R@K z@FVA;6M+XX`B8scRUakzhDsR!aq*6>fDb2ly6`>lp>`JFV}B9&SjnlvCkj73W*6|g zRq)At8Uq^Z=tpbd*Lu935XBC81q1FQ__u1}->v8$Sx)~e}KM!woFo4%Jw=j*g zvOUiBpvUQ-cBa+*E4;4YgZbyVpx}qoK=xN@r$J5xwZF-&1P)+oe5|L~6MW`LyzwjeCHwi((JR4J-d$P$GCpQT zn}YrVp)mGEAS1c}vZlh&1L6;@2g!O?J1*n(9L@{i<%XSCUe*EU`?dEqfnWGG<_GF! z__NG6ex;w`#AJNcv)m~BS>a9fyx@PupIPun&V$0S5%8GozwB4r zP1TO`QT>VFll8}rCHo!gSMXmgH1H>`7VxL)%qM4=rsh}ZR5(by9o2bZfj80YbJhly z_=m9`IYF8K7_32W{1!~W52^jDLi^9>k;ff>C;0uq>&!3bK}-CF)p#WXmh@w>A9!Qz zPWZ1kmDl`X%{+dtP+s*nzWcSDarbMT=zLzP%RBY}e#HLX2k>^P?>((mWk2qT?@Zk$ zyNs-Vp?7}dJY&4dn;!T|obb$Zm*AcC&Hhm#K1`qu9e+jWurPCM<^d>y`8-nCU-$|5 zDarSo_a|{(`-5l}JK?(i2QYwRVWE@{^O9!9-y0^;3Gx?c|AOq7tNzFANBB#vDI+t= zzd*Er2Z+RCJQNc(0RO54zQn&hmIc`YjxZtJb%p|HoOU?QU5H;YpM&AbKt8|5s|UHFSO} zeiwosZ2e2)+pTZ&Q`P!&jb>$cPU5{ueTHLPon)TlW%KJp zIebnt7#;bVjN8pVH2AT_{j4SNPo5+`YDqkgHH&+yUwg79Q4k~aL8iXPKq7AS_&xfv z0k35Z6z$^e)m!~O%($^r5`9E)d(cVHrRaJB0D&@~;`6 zF%|;R#)R>(_LMbhjo!9&L;`mYpq0BlCi*LpbJn!4_bnoR!m@ur!xEiXpnXi6Q8bGK z#qN>Y&-d-`E5`eQUklIp)hCTdj8S7L0Dc({p4G%u+>Qjxu&QBgIC|14Iit~%rTVMc zuij29`diWSp)+BH6;fZ*Kda@5ysY{ku&vu8tm7giQk=eF(Xalx{s_UJm+)jVePT=c zw@ZXrpPMAws`1qDv0qP(9xG{bVPZT)n7Tb=JkmZQx$$@y&)QM6-b-cLm-@-uksZ7Gi6%h7%>WSa&;&ymxfA6P(2jURk995as5P{ zliHFSTc#R^4)s3mQB(bn`Ipff_31j1P-ku8FO60wLanrXo&}`-A)bWxVE?Towvzl` z?C;i=k(jNmhZ7Nt-sJi9mdFdc*48H(;(3PmJme4(hiFZ`E;o<)&iiCK_{jTGM&{aX zpL;fPiXpvI#$Qa6$fTXJhH`n`<6V_bS>O?i@J?CTJ|a8ll%-zse09pm@09&& zs2z$r<>Y;_30;dHYXv_d2V6UT@jDdWqVv3h2kC_1Yy}^!+)6!@Fn^1BULsF*?sTj8 zXJ)W8hnu~o|JC_YcR!HSsaNvIRAtThC*q;hB>9q({+V6m;yV>TDe&x>hp^uoU#S;8 zU5sbwYJ0N(bMb8VFSCcmoz^KMw`fJk3_9gxyt!5UsL`#(M@nQa!P@6n=VODy0QSk1 z4!raf8gR6o=jHEf-xq4NjJ`&vegpF>lATT&>1^tEudL4BN9RAWc3y=qd0*2y{ogV# zG2&M7?Q1Uf&b=$`W4WvBpF7Vp6_l4&>O1YPsYj1FxQZY04kBj(A2Ryh7->z?T#Q!g;AMjFMwu~=|!iH!s zB#xfor$b+z^&@57+wp*N$Qjx>)PZNcVbqW{u8dbx9_u;w+vI&&Ta1tPJAV;~SLsje zewOisY1hx@v`qg@Wl-z1Z)oLKhO;WE$Iqv7Bi8MI^*2dtvQA|;SeiXXks{0V(wokiYiixa$4-;LEvjuqT_U*x>V0Gy;X!{0gP z4(%McqRIPe{@6c#e`htR*Q|}+p=gt_7N3cIc&9zMlR3+pXya=&hFAj6b$Y*}I}`Pr zR@Rp$dTJ~5l6vrg@8dGrzB}!~okSUA)qnqe8K3A3u*s?&TgAWN{S0PYYW%WNyR=?6 zz0#hB^y`LrOJ{b#ztEHHPqN!hM1y*^mUX+|>)^}YXdfabd>cN=Vwp9wF)^^(&wJ4J zTKenQXLsJ$YKebdXFR66&AAAVpJ>C2XD7-e`AOi{7`@ngru9x4-M2}Y zPsStMMi)?s$IY%SNqzg)j6Hi&kBqRAZ;fE*nba%llY3K}9!1NRaYpLjagzG(miXsR z5~HP4mRR?T{3PY1)jec^>x_r}g=_1;P^Uf&b(P~UDU&ta%;2vg`-$4`Jc+@$w>7%1 zT~@wR<8S}Y(xkq98o}xBY{R1wZ$!oP8%y4olS1}{ zWd9LuNW#y^d8O#Z6RlCkDzEI{8)pyIusK)sknk#c^%IAFwxu(FU1Z$zTYj7VWuHj) zoKC%1+C(j*vp%q*HT@nZtS0cvY1g5T&VE>&e3g4i0#8mG+&WpwdbgfQ%4vL&B(7?A z8$NI2&Of6*f9=7W>$#c55{`76_@{0X@yS?`FA>)-)p4gj$>Ug_O8Vn&KvWaa za&+oD{s77Q+U&;KGfh9kc+-mcfQ zj=wpt|(e1CT}$Xr$Qy@CBz ztXZBm<-WSMf3w}6T3h%rPi2$wNsO>uY2iXct(QLc=Wq5HUw`F)JGkQy?3dXBsbBi6@Od=s|ys9sSzpEzvJ;Lopps zPfx!>;7H;xNiMi?Y=zUi({oF4bZbjhPnp_*;)mQC}G$-onRB;6wlQ;0fZ6j&18Vtupyh zKlj?K4Ak{%ZX8Y)RKE}dVZW}@X3dkS_9RgYQ3=qiyJExzxFN<-f?P6 z^@$4Y^EQ?*&ZvB%k|jMOznLn@Cn`-zSu*F5e}pV4C3rO6a6_YH(0^%k#Hbk6PuAR7 z_bqqolT-7YnD7c@-<1q0NZ@EsS=Ol5r4MxHXwT)gD0I1Ni-O-9=jO-f$Y@EhA~)gA zZxer-^c)#g){TzIhyC*RdQ`XbguGYCzdV_2yjoFmfj~oM7gBy!u zj#09z^11rkjVd4QWTg6M9{Xxvef;FhpCrbG^bfv*(iAyXQesb<+je#OWJW%J^v-oy z9_YbDuratP=rMe^126evT9RYtqy8}#|HMzFgS^#XI)Qu(YZWJGD>OZCsJ$#_igm*k5n z*)rc`F01f-1$uy*#6pAjc~&6i{S)SiaR=O1AJutY*>A}Fi#;#x$^7eTexa^W3y(_+ zIf=I%Z#2Jd{qkE1|HZHf{Nzj@ElGdOpIyQSNZN#xigQ-~Y3It0x_`QKLc!0@m{4cQ z!h@99gIA+QjnDMyX^S;!VQbwy-}wH?+nPS3dDEO4H%8+}MS>j)r&`npT0_+n&Fu7+ zvP4?!j#~}>X_A!&yDf6JExF{s(a3sJQ}{&!3hXiTKP5LUe@Nm#BsU82PXIp&{+R#mI!xNnz| zm&Ou%6C1Hv|INf6Xrce4MUJ0J11?qUX~sjO|HPz!6#gRF@kRReu{li>YLvW+WYCHE z33Cpa;80kfES)Sgr~eRfvlH4=3jv{te)NZCGi=iXD=T?}`S8rvxbcXoD9o`oS{p3l zk2MX#=O1hqkXvAfD3*w})jh|(E1@Sm!1%1*Cl+WO4=yr9a?MdKArr0LT`9R87c$PD<=(Y%keprTvo@t4c@KrsB&-4kx{TQ z1pQoWj#yiBa~7v-!#WwAJbm(r*fbBvN8vTB?v{x>2|G=h;f%GX{-pCKF1yhS-S4;9jd(vebx^RCJDuQHaD1(G+5d$t z{m}m9C%T5p14CN*fuX~SPq)Weo2*x;Sk{MO-SF1O$-%H53flQzZ*c2-3kMn-$Y)JX z>x3)Uy-vNXmL9h?bt-D&^>r#r{Ignyg68Ry1@v3i&Q_1mhqhzB&rGN@@l{Tn6OrS) z?|t&d=u(rI#EseJ`^ZgEFHOka?8^R385QFMndbO>b@ZUI3;!%_;t+fPCq{oV`Z=@! zrfH!cz-Nq%D<@QW+l0-#9?v|*dN9rM#1Q}A%HK*EEv@CYKJ-?FbFKT#6VL-z_FM0L z>znfTfq!}~t!?&t9=xA=?BusS>2n8~8@%!Ux1Qs^E##%_NMAWO?$q(%y79W#<~dbzZtjy`X~=q1 zl35iU>94r4f-fCWKJc5`KVm-se(W08tNgZiShkUIQ|^cEEp@C=OaDadH|2Sv+n9P5 zcvab$H#0WbDh?lHKU&kjz*{lB8{!WveEIrq|DQZ5_>kL-#IM|3y4z05AEvUptmLO< zzNEggUT0rP5${ozKTK`b;R7xn91+RXbyzBI&^O^f^{aYPznI#ni$vp2MCqHzQ2JpC zuNCss9t7S^L>yJVJ{Ro~-j^K92bSgx*UXp)@BFUJcbD-&knx@AobeUu&r|&qO=C0u zsv>vpnq%wW6gRCqW~F_t*ed=KR+%>uAJQ^6o!9m+j;wz{&F`YBx1cv7nx%=Km($W? zUB-uG{@U*Kc?Uz<+bS8Ip>NKWJ3|W_fBGYyrtGZ0+Qx?(5A%`4yCmi}(RyU3fj+fO zi`vFk;g_oEzV!AxZHwrfU3N5s9=e*Izk~hXbZ9SGFT@L1@My#{)zkWBiRY>2W1dxG z6W#2f(Z)A{7R zE90MI7u%iSH<`bx!EO2``|d?6Yi2a_7jf3adhMOB%6u?C_;#6g$=-div?|%ezF#zk z?f2I^nIW@wC;k`NFg5i-fNu%;Y7fGH2>q5VqqXd2-HC&ib#q;7d^nxPbh_ut)A(E5 z9O?ewUdhggANSX;P)1Drckbq3$7N^wt5eV?>vw@Yn)w93IbCv46A#tSG&6^9$KVN$@#*y+>Y=d{K7CmH>SPg+v=MY1BdLACx) z-+3g*F0p3*8p-p#pGrqr?bF2h%^8blEaUJiC;RLw@dsu$y{t_y{q}~6+Fzn>{DUMz z@-OlG=8Jc|fSfnhr}15?At9~(Q+#Kn|Em`_jBL7?o!wotveehEoM-%tJg3LmJm2|C z7YtGi3)dU>VjIycHjAs0AJL!bLn{A_F%*-9#u%!W1CiumSB7Pod@nQSvQMSq9zLt@ z(_a(~WB5zhg>yy2UKpLVNdBfWQ#SSq{#1qYRVW};ae^(o_O#xQZ{yzUD%Deoxcz-#}`dLQ8>B={9 z?(lE@9{(F*kN>xRFYjj&+)elzPuW0)eM>0z{sZc-gY-xKR)3H;`SDH4%d}jk|7B9C zmK8kwo#*jsIBQcbgtr0zGVta7YUq*w@%QL&DcnK-721!Z=2R2RXkdx>X5d5MUsnC) zRXzSCQ%&SMJi+=GNzbIZF}%$8vxt75r6saT(u>Sbtng13RGz;q3N4lSr{;49u8-Oo zZBxa0C9nPSx8MuPzi|%y#8@nA0Y)r>KjFXoi%v+43hZI}6hE%Y#WOWkwoDJpWKsp6 z!RxH=gz$Gq;{bmsY$QsLDE?P01Z!4u2bcN8auJ*1Gm&I87XDY_w!g?7S9nxa#?qUz z@JJZ1=TyFx7s-jh4H>RRy^rnp8HpDq^c41&98%w&k&MkUznA;*HwiAEsrFU-E;HW# zqi^T8z9@Hu(&&ELzkuALRQn+w4sOY}GP(0(LE-rq^>S+TLaAhJ$<3iFiEGvIBae)f z4k>t$o4knpRyby)9af=SK5M$mrbR{@;m^mguB(x){SkZAkZ258(rPbW7%$OYmHE-g zH-&66476f+z$9w0p)c1pX9B)qLe5`4%q3Pq+HCliobMtILch?^$g#wE1cOJ}3#+m; z+WZSV#u(2WRr4?FOK3qThUdi-E#O&PheGZbs()#ZpYb?3PnV389;V3rR8jpEnrQDkFz(i-y*M}KN(*z z&OvPUr{@&>oXerLrkwPjv=;(vwF{W2-`X{|q;+XWqb~m_=UcL0Xj4c)lkq%#9kG$c zu25{}lJP_uWUi4}t2U(BTB`qQJykzk*Xu{>vi~Fbce)&IAIN<=_(UQpf8)HB8$N;f z7)#f>vhbH4{v}Zt^C~z}?-Sb@eKda?rz{kw@GCf;O8C9V>f(+gwxH^L>bvyv6>TP* zN%+&Nkw$(iG9w9pO1tD;PldXsjn!7i$9z@7S-Br;#>6?z*n`|ON6}=#1>MD(wWW3iAD>r2yk5l$B)*m_V z@iPHd@Nv|^-jLjIOcnd~kTxXzMpb)d=}?z>+`OL5SPA?~W*7GDly{3>*a!xQ8(VIy zr+>jmI#T#K(&xlALqsv({9(0ZLp{>E^6m6KfDf4M3wQLh(lq^9SwFMp3O- z_+x>cpV0EsugLwX>jLm$6D;e!Ypy+h3;bW(zbEu6J~oP8m_HA`w5zaCxbCrU9PBC_ z{!8KiQnFsOV;1Y@qvQAFeu)_)v8J?I$WI%e0!yiDH}nU;%Xo=~bu_*Xxw6P_5>3ai zl5mmWIfzKED>Ol^*odCr=t53 z->IWf2HwarZhbz;{QON*@2<-Gl7XeGG)C^|W5m13G*cJouXGGw!Q-)K?Xa$om%Qu4 ze^$G`{0&XAX$6&itpXP2Pgh4;3O~iA3kp9Mz&E>-TF=-^GoObOeiC?t<1x0yOsE;B zyrqz_lxaT{dSm?6mGKC^(e$UV-xheitd$|7gL(biN3z$S|Hl5Is$IR|y~Uco?b%B@ zDdZFWU-m27H;#??njNQ_t)>?S>ctfH*t&H*x|bR1 zYAqODt!Ky_b!155{ipEDW4~z0d8a|)>A5s}Uzhd)H?%Hnq(laG1G@gd<~IlpcltT_ z!IXc=-{E)hx0`t`MV_N8`ld@7^p?hR{kq4lKlni*^OqVFCMQN0J#g!>rM(?d&Lj_& z@zeLWpVq|w(<@*djXg#%2!HHoHnUab_GMdxtaFFo1?;OgJKfHp16(bUp^9~z+~cV? z?YJ=c?JPD7<-wwAuT0s_avvYGH7g)C$4lJqd-dU{;%Rs$3>z&1iy*k^e>};9g>@Z&Ws=i;I+j zgP012p)Ss^!_Wk)X;PaEW543R;D1k^?}ED^H)b^K48sV@VbK)}yH8d_dKS)O zo$qsyHE|=)IlRwpvIxCkh2eC^UvzjM&uY!QTC?M!*%N1O4(>iPQjvOW)Qew=XEb^L zy7{F~rhl62`{JdS?)dck#oN1_#UO`U-M@)$nz{Q)#!H+It9tLn6Wl&`&lcII7Kogc zBNy|(yzw8Cb_9Xs*1wovU))#B6@Og(cyS|``47??N zq)`vYR_g8Q$9-x4PopdzpP$nIPh5gwSgrE|1`!x?_K$aee9o*`ul~pPjpz6MzN7s}M8dN`_ZhB#re6zd@N5;{kH@`X?>;YN@8fxG zSZv7oz++H9Ou0-Vy5URX%s&@DqHm~rKb%tU<8M&5hKb2Fenj=hT9f+wx&Dg01%`i@ zc*)-<@Fe+J8+|14m^XsnH?i$M(_l((CONk8( z_;}Nw8aBq``@zUK4d5L>#KB`zg{UxfjJ-};_C5L|`qFqwGY%P#o*OX_Z!6UwJ^xJB zTG5}~kM^uuR{d-FGTxKe@8e(0z0+rG9jFarP8+QWx9{oC_Zg22Op5;-p27{~{bz8# zsOOmvPp|^ddQJAoV~v#dO#h?xqI2ZUhn+|3&-8Q8>K{fATe7$v^4-CQ=$hres44G{ zL{}*KM1?>0)kNDgN`Hbs(M*&)o@ajfgk>&$WURqPj8be&mM4ujjLGH6>>H}Al}C*F zdUtsyTUe=&jmq*1+3(5Q%vfwp8ztT^8EAJU9=h?l^>eXjc!@r~Y|!eKc#Glk7mxlb z>*+UcL3!{C=-b&rm3O)$a2T}H4Q)NLv+}I*rhz|_5z!xip`Kkge%g3a%EV`< zB=I7RsI8xlOw@Pmd`0;?@!BJUcwO<7ysz5hZ$=oOUGKNwr`F(B#kasmgmGhby%qQK zE(u4BImuW{_?8+rvGCvM%i+UJed$tK!3#XnUL;Z=)n7mImuOFtpO%8wQpwlx{TU4ZF%9-zo}0ks0xgY4FMKcyhhSU*6rsy^^>{ zG2S&Z3PK{_fEoB;@t#tVLyqvxEg^jb_=xWiHraHVOShv9f|E!a~&p><)~IlPY7=KA2;?%#cXujBV@Zx%aW-uQ!*=>xa1Q7fn`^>W@Boz8`tl z7h12;Kx9g+Jahbn=gQ172TwAm}4Dg2E4Xf5z8{ z8k=HcX8o4+7t1s2A6tJhoUtvB6XkYAWT4Z1n zEmbJ`c0AtvrRj9YY(J1*3SIz%N#S8c>{}v@go`J&ysN^(cd0Ny1eOPYZl#7avrI(hG*HY z%ifUslpmM1&i;axVUj-_Nl-C4U*HTm3xrZMJ=``tul8;vJ+xPmY~uIB3xab_5%y1Z z&m{kM`kk9I>ip5T%8MK#K)1)vAb%TA6;_q3TBA(qkJU6TjYvUSgO7NM$>y3LEXoXwqj6Xe`88#=%o5A=s@TmC% z|E~;d_raH#XVO){r(jo3EQJrRjc??CX>@MLpDzv7;h}S4~OmkSMbUF zSmwV~^V0zT4QR^dZn`FZ09mn~RP~{McGwMT=Hux~d%X5=hCQdk@gs7gDL%3%uq&wN z;g5!qm$GwUP#bRa-}g88oZyN+fEVm}evLH}naI43FR<7_1csCAzV)zL~kK}`fbE^0)ADbYvBKTAFDd^2ik3cWTq3{z%fpR>SKog7) zZf!VqpU(5#rI|nYuKQnw_d*h|=@sa$lH82c{P;X?-~WAuU-In-ZBp=qSmKj*n zAJhSTna9ru`|;;~LE_P5fKSn%@Mi4GvR;%wJ^b_W?Xo9BPp?8h?~oe$RU*^81HTsd zMJR-E%U;F!xLL_f4tn*|4gArk3+D?j7p9NBbMuX|UdAo|462f;30dzh@Or`t4#NTS zzP?f}u^vjQ%=o$45doMOSB_Sh_awXYi{^(&(!1Yo$5YS?{!!u~W-Q?!dA_Rl2fFGtdZTQ?%Vgr!~Qt=2C26`=qEdUTr=mhSgx3w4=4J5;lTp(49P-v z-Tcu{=6{;+%U?Qr$ENqq+qKzWJow^cFQNMQaBI&`+zrzIzxdIMnHQa3kdLtEfMj2X zzR)NfWj$=RHE(|QMUqYbtG}DqK6$yXxz-=toHdoq4*z)K_Z=gCUxxU_miYT3xg2)N z8K3Ky1&1oTIX~=Dq7dMQ0ag1Ncls#;!NQ$zvpF+7Ri5(kSGAy6?mO0f>?}NAw4j{f zk?_1vJTia3YA;glt2=wrp1Q9%w8NU={R8a2_!N&9h6_?JD+nr_8c+F9DDBB^z{H+^Od@mfc%!3&Ys6=HxdPd8&ORHCBxsL&e*X-*B9| z(&wRF6aNO;!^Qgmo{8vRp%4EukDWDZGpvmCpYz_c~y_RX^FiZ8!CTX*(bs&DIU4R9-Y7wdDzH# zr3%k8BSg32Y!sV1IYZ=>z}sRnoGc+_Aq&(wkuRIU__6s{kUH8!XV+#;N;j3 zMp?TFyi1&n0zYdMNOD`nUgzewl)g@S2#I$UguCcZ-fx*^WSP!*qx3x@(sjlw<8wl5 zoHIUM`-dYR-grH?zb;MqXKce$=~Q{K)P!#oc;LLz(MF{y_%7tninA1WxIea`#doB{ zKRih2pZHdMk8^wBe(5Ruu2he{pq)f7e#^Y*nUkMoW>?xX<4EQwW`0h{`#7NUt@;y7 znGBp5`IyJ2M?cA#=+VA{ZybO1aYh5jWP@M!yHO|!ueY~Tk1xkt&Hpx!Z8A1^a%#sZ zHJ?sc%(W2J9a?w+8%nIz7G9vfvN9f4jo7ry4H~O?@bTB0zyoK=n9xV^Lz#15@T2;N zKg$rmAgY^N!oPXc97ky+UQi3_r=eXHtv0y_U?-XXQD{QW@Qf2-k1<|&bXv`~;L}Nm z<1dV|=Net{$ zM5cP+D~(2>E7%tLh906)9sP2(`=V7{xPVRY#YUA(*vMCM&caOY0kOerS)v~m`#;-W zINh)oPWQMw&h!S$|ipV=(ms(xmuu?r#OFwzd&1aFBI^5>>o}%QZp5$qk^PQNq>?j(adHL-j;l?*Z>d7qVYwVXMHXuqq&8=(g^Socv zkVmWcxgdTZ{2=rrH#DTioE&NNE>^!}08a5i9?ki$JO|Owq>L+Bo@afr0#Z8Kpm{Ju zc{Xikj9>mc9M;9w&PCwth|Y(+-B2F&cp93)4MYZvuZ0;d`iXGBGkeZ!WA|6cyccy@Df2(S*Sq}&t0&&hbEx&-PqbUx z=|Wp^Db;7B4ACE0czOywSkTY?l*m&#blv_rG7_hJKd`>ny>a6Z`iVyOmK)x*fF=Vp zUDk&xx23?(JmR~3rG9gC!<$b1<~OtT8{X{lh!73^^~;4x7}lbE^ISMaHe){A{+7>) zJq(vMWcJHw%7``&gU%fri+r*j2U~d_*}E+fxQY3OT)I;x7n3Wt)9_elP&7&9zISdr@iMuv4FrLL zZ-Vp57%=SRdZnIrO=lT-iW%3}a_AuWQXEfWX=bdRc?>Mx#Aw48qI0U+U|CQmi8v>Joq)-W!}eLiSbM@GlN)4YxJMTl1RogSRCX#nV$(YKQc?u zgJ@8KV62Q;Za{k`?G4hNyl=|;1AS^fh~E#?y5=A7M<(9Uvd7O87pa7`>p-4*AiyIK zDAf42I=4FK8Zt`c(ah&WJ*YqE9(C@gzdaYN5o=`6dHar?@7gmmpEDc6PlZkG9$ za?bue=NI)ax&N+?wW5~ZcKn@mX8B4w+xN0x8YCw8@(I-w8u3)JR@PP)((dT4cG<$dOYDgp z%D|m>8dhvl%b4`!38E0LV0?)_1fqWw-c9Uzxans_{&-}fq`gcbA6+Fx*@LCEUd(>{j z8)ET2CH_JR9*=NPSbR10Ci5FduI}nsiRpZBLm$St`u)W33SzRCQ>tX~()yr#y8 zCe`>|%F}pAgiRgzzz)Z+Mu{l6tNI02Wyp4w)K4z!Nxf} z?*_dEo}W5}BD(`m>;mm{)208(-jMe_84YDK-pG74v!k9E=4X9cNFujq~kzbwsRFaq*Don7TXVAQ5_#I|3hg5H`a8 z!MWG?A0Ifn-dB4vgPGSeaPk@WH?ZRbp7%PjbNRs0_7bn~-qf4;J#a$tkAr|y|IM2D zDx8sOuO}LGUPoq|MnEW<@g99pe?7TtVPDca=U9WzYjv}sdgT3{c*uIwLFO&_6^O6Y zqYoLcbDKv#+c4{Hy~i5-DY)pV%5aIuDB~W_nX)s zK?k#Hd^P7)ul5=ed|FFw`f0D<6AXH<52c4TU6T73+6&(dw$A>wx$a!M{fPcm{2Ccy zFFq!o^%{Ji8CdW$kH&fHIqO)z?Qefl_-_tAl42ago&fhQcv82vL-i-}DtZ4_;x&5J z*OBf^Mvv}z1pV41x-}cCUD`uenr~IG_n{LcSn~XK+pE9s%J>B0TQ4{@ulBl`zPL&J z*F4&*3`TEYf6sR5S(SZ61AGqqB;oDVd=bfcu*7^>U?1;B*Y3%9Gp|(`+mDdJU38!C z`GNQRAHQS%KDX}#pOI(%v0#V$M7NCR?TU3gw#gTu;7vUcRj^&5FBN|a_@)_8yvf`Q z1FXgqOa_bx#w5{)j)&qCmL_CUm)z{o(S@C#WqIGxh9c-6DS`OMOhlgEj|a2-d{n+Ax4Dt1p#5fi zY{qWbXF1P)yYzm(P$?WP^t^vt0s9Hoqp>^wvpy?`Fw#iotKl_X7kTZWu%%b^R%i`! z_q#sQU6D!Bf7NTfCRxp^GX7#QDAGRkM-+Davqpoxwdb}ytK?rI-H`boj9xFLUq~O3 z`bW>@jpw!Ud`MsXL?bhWncs|#65qS~0`QAqNeKL1YT_m97Ay~2v1$KBjn2eA)4VXFK{L@>1g`%SuHM`Hi#XAc=Hok7EE&QKBD z?c3hH@mOV+zf1pjr<^ITG8WBNavCds>pgSCtI+;E((p9veaD--r>rTzehfB|tOj@! z-<8?%&S3Uv_7C38q2ITxPe&4I?s#-U17EDyPsdinvyU#$!s81J{m2vtoqrGZ+2638 zp`P_JX8oHu=ZM$Kr}??};@IrJj=SOa29SVSL4Vb%-$T9x4P7C95c$C((lPf<4Plfp zYV98ldjbCS_w&Uw*opFH_0w-#uYUTHHM4{BQKGCQKZBeqt0fN$ko&K!EkAVD)31Gg zXliYltJ9^`=Z6^cLuXgZp8kbPYulIJ2Cr$~(;r&%zNZIH2Qv9B&wpXf^MlgP@QDP~ve zi&MeWmo9b6WmUfxUQd7UQlZ|d4@2I?*uxbwfOjG zIca|_K7IYb6~DBmeXzCK-gqe3xE9|NC~n631Ls)(-g@}vLuW_*`_HbvKX~bYGrR_V zh3_@x5&h94Ut8&KA}Z8BitjI6$vfC{MkXU=uKeQELzj}W2V{c%QT9KHs`JpLyp#NJ zy+%tQ8nz-jHm=*q!H1Q`jYY#pZppsRbsR;4itmfw(kJ(B5EQxN2i#9Y|4IQvUEUY} zdN>5p5FqbQd9_aa`Dh>g=aEmz`=TEy67`#SxXONth|hXS&jXd}4?F?AAIt<*1rKql z^G^GH(YLZ6?lnuZffvl8KO{~TIa6B2;7hF$Ly4 zP7R~yVEpLth=;9-rKIF4D2hc=N{u(7rU?Gt-Md}nnfIe7QSG5K5%|cUk}BzsYwYVH z?qEJ-Cfeiez;}c)e3z=1p8OFzPo#8>b2Km?jf>{v=EK~JIVFAnKz=T8i<#hH{<~co z(oZa`J|pn+ei!l83&z9qMe{e}B2m{h?^sX>MuLZ1k9$R8EYUvtK*UKA>#qY}w9hEk zz66vH_(?ssUg5qhuI zeOO4!h&0hI(ON#ckJiNBN$kN!!V#bNDPciV^g#ZGe2Li-c#6kH@}*+&;rQ{YoU@7k zv`C9zbm-C1Zah98FgyDUr~$olm!8BO-xn3FFU7@D@_xYk#p>gHWA~0N4-KE`sWSlhrt@B53{-D~Nk+aFFSVZgDPPPN5hJKqE z#bhHQwhnrknzHA@_9T*&Odkc!hG`xnBv4@-o|m8Mq#o>>AO5XdhvSQ}&#)b8Zk7 z7wNwg?XHoXa9~TY+)&vG?^~~}vvylXz1;Y?bz8B3ohk9LoguGW9y*6ikoFCvO176T zpE-BEl+Vd!GWN`J^W1PSSsoAa*JQUFyw62yT8{s`Rt9(Sqx=aflf*81r1o+Y)-?B7 zJnNq=kDhxr7%e{=NM5U5mA?XWw?tWYPZ{}EOKg}VH+Gly4-b8`{6DY#=+j>1+UJv~ zFcYyvE|Qx|r~E(ajpgtWc&=@4ZEX@CcD0^YiJG{!EPA@t@_%o1L~Hn;j(%-_65VG{ zYxQ}`t+oA0`&PR>8E>K`Tz&qd{Uf=E+ELRK_CH!y?Rl&3ugCKHQ)}Rr_?TTjqH4A|d&+ua zpj~gq+eH5O2KqGFEv(A2NH3q{{VcBUbgAT}({D`EKLfTVkqRP|uslWBumjABU>!0-usczHwP|paZxv6eRpa%(hG@#Mf=)v*(N9n?K^p& z=NUn7yc?`zVKIfQdE3%_uXz``N}_bduIJ*N=o-5X=A8Ig?e_6?NGudw!`;gB#k-KD zNtCWm{q6y=Dkg6zpCu$JcSTqzVBt{IitDbvR;(VXqD3D#Rh9aP8@==|77zRMeK#)b z+GjmGm$McIPClvX$q#&&%8y5To$;VGW;{_*FW%U0&t3TBsRk!r^kuVIb02qW-5YgJ z;HQ6WH+p6)JT&!w#cl1bn60n^-{cjot8g~o&~w@X76bH0w!hxg-8%KvQnd(I*5VNT zIvVdq`_%0MkBnz`WO`x&p~{h4WIptXxI`w=UV?YH#$D)0Lxc9Uhocrr0}ff;f4F#} ziNLu%f5_hDefpnWFh`7U5c%Wk*=8w$w>P*8s{-+WZkO%d=+7id7WD9HG~N5o?rHPY zaC-C|S0jsn?OLCX!5{i8bQ#VPac_5v#e}Bt&v=-BX)pDN<3c->tGm&Q%lLqYW$a?3 z$!4XM;$p2>UC>8{j*u0$r8mG=Z@h#=@-Czu<3yZt$=a|Ky7k>#%)gm1N6UhrMfkPD zJ{Anfr`!0{$X6Z^1t<{RN@Tg*;jzfUqJ(n1oC5zyvxve4=6Xk>^KS7j>WP{ak6==~ zd}hQrZ0tO<$clmUtX@4=G{1h)CYpaEtKg4>{*x$Gz=z#zZwdOUjK_}*(Vmo}yRZ!u z3ker(LR59}d*J8oCa;1UU85@QBD4RsEzkg=MeE1I@C=^9V<=aA0c_4|K8y^dmV$moEIy zIGJAX+KPnp7I{pF{2H-iQzk*~U*)pR{-*imkoL6ng>m8yEc;y-xCv-9%Rb;tiC343 zH$XfP+GCH`{(t7)J~*!9I`q68T~QYxBVG)L2A#){7sCs206WG9>4;7c-~zgohOlG} zMgvLCqezefP1#CTlubQB_F!g=OgSTM${CKai8rN^A!ua5us2F=dA%-$p&1od%hhHb zM#WXUue1uv%krx9QhbQR$Rq0NVt=Q5E&wuq$^Nrdi{=3A>F?90&pCbi^l2<~eD3Fn zB}}K>_yvA0Kbm-96@M|v(_qdeXN^SsBxqbYBYza;!1pL02%*uecvzpClIc!V%L z@ybno&?}@u)Ntc}n9F>`YviltFxBs5Gk^Stq&hp!o*c={PFMFW9J;e=#GPLol=yx2 zSZeyt1h=@_25sJ%*orM<{?1$`wXs26$RXebvS$g9ch0p+m-;|Gm`r!^<1$Vy(e36??QU6BD3vGaZY&RAt4N_ZbWMIJi6ta73P= zKJdiI`t`09SF}bYzubcH6&}Y-;x_kE@pa4@4u4hs;RYUvOkE2{4D9#2>-VI@pRvf0 z-?~b=!>toEmV223ZXsf)5;&%Jb8xeHGd5R9X)p|^3a^S1RJ>rvop`W<*Nu3kgS>K)^Sj88c81}SzgQ54epu87elhRE zP*bu?Wd>z@*caecdAJFWV%{`v9z=s~7tb<@$tMQ6?-sshZ+9NXY|Qw) z1A3fTO8TpI0$qG>`9e9tctYTT=N)#Sr=f|wL7^D@{vcPbl?~u;(;hopPHeH0$R`jW z680~g1Xc+Nyl`;dU1+n%oh1G^o~FFw=T$t)DX%BI7z)3~-o*JuAYMg2mzVL<0Q2nw zPm}gHh8&a8zqEhAzYo*}{}`{&{Ne|M`RpnDv)$=L{z@c0ROzJRb%pw&9Z6>}kIxdu zXBbZw#_Ta?3@;%-khtInItK8=0sb;S;*}cDDav1o=tHG{zp4DGDE}yf9oV=WIeUTQ zmV3`yM)zR1wOIY@v;XJ(%KYM4-WOH)vy$K8cLR@Te!v{?2cHK`eB^(sf7^|Ta5LO+ zGp`N_zTj`Az==HYEBf2~mEa~LU$_f=I|BUf_YdW7HJ0g5jsBuDE;p!erSMh8E3^$9 zV?Ni-2bL>huTaFLnpkBx$>Bk=DuGe(MQ)WS`xR`>;U4&T49?m{lKdm~?Ac$;Tgl%b zzn+g*nD1A}k39tVvN9+0t^KQD&tSc1|KjY!$^T)#gZ!`);Mw#ULH~+{4fc?;f&2#e zFl=<}+;aIJt&!)jviN!Cu;ILqf4@8MF!i+iO!9s7Ma8q0Rji^;pU=$?pN*Abhl}S& ztiwA;YKLnN?3DWO^#(pTSi_zc{2Ba3C22o7xHz9YX3#$N8rE_9KCCv1h;>e>`?-I< z++BJ6?JxZI^;-9Hz>E6-Q+4s|e`0*tk{HFez0o^H4`CyHWON(_OYxjnxFdZCmD>?~ z9I_s<68~^t+xa%X<7yZBG4f~c$R5i2hmT~(v$EeAw(rS5o)}9^r& z=)0!(k8@s*xs!8G@Ps4Q64RW|lWx$SG3Fy5ri=vS*}f-y!p5ItV)_#8Vc&jt`BZs4 zb-z7r8UA$HpS^qb$*Z~9@!9E1KKDJl%nkdd&mZs)TsD}`;+S{IAlJT87nOnd<*E90P9O*gw zW8kp{{hH_-@6MdUdYAriKZNq(y7KBZsC&#)+$|hGPyM1FH1FB>1lr_j>5rnd#wq3P6n=AS@#Juv{7{JLD&v*F;zkxk+prnl8 z9+&Yis|?4WP7=VkpG34F_Up)#6x2VIN%Ah<9nba{o+{J}$U=LHVgfI-c%I7ryp_F(~v+>NC2Gg7HE)m=Sp?Rq90I z4`%$C>7RlR!3N`|iC@|NxEU*{@@h-i1rMBe1|Pv1eWzS$=&BZ~^VLD5NU?wD4DLh9 zR`+dz7sn2Mes+T;<=IxHyHcI0`%)iT+;SC4WFunPT{{b$r?KmT-X^%o(ghosA01TZ zzt~ftJq=F!3%oDkSze+P2WJcB{MEr(X|D@Aw(LRx+@UkN{V>a}N$$`PSN0IZU3$@= zemHr&+{OK!`7+}d_~nVG3%!gd4c{|&rjm9p)#CS;{uf89}doNN5}`>Na3ozGUv;vo;!mq0tt6c9HA#- z&v9Syp>bfx^hxOJR5$P$OYs=M)K^mWX1rRLc7)57Hmkn^{F?R`Sx7zQT{T`j2aNgG z(05N^KcMUz9O_fI3Yzu1%!j)FTy*dnkQ#CEdgByiK4iYJ|HyKC^R6Jzg$m%6--EXK z{lsYg%SygxOYdca5A8dV^yGY;^Ye;^x3a&_clo#ZSuCQsgMzTP0{axsQ}knhNd5Fj z>@|Q-L){@uw}E?m!m;%G>4Q^GiM))Y*cls(y&oPlo-%+hd#*j9yy4E9nA{h{Ud8|) zGam+ijyqLK7I4eiAV9hidwgwwa$gV_a)W~Rx1BD0m1X=!{?p!5p1_ZL2<#+Rthm5W zw`ZvKd4o{Jx$&OCCy2bq+=LhU?Dx^xer7DPi12Y{@+ve^ZsMjVLVQeU7b2Fr#~Nr2k~Db z=eOOJ+o=CqhFjk`UR65R<-7Hh>_9Z`gN-U#_Y4n2&7w+CO~ycfOpKJ3XmtXLujG zV!5w=W4hSabnsU00p6D`@qdq-QJ)Pb9PV5OgGel1?ST7PccO-e3glGeGTA>fXHHYz z9x|QnE60+XizjWQDr`}lDQ0kmTLIcXvWf?xXE*j^*Hf*S&Qq>k4;O4SB;)RBx0#M5 z&ZkV$Ep8Nm>5}$g;6C#2pr87k8F_1l5AsIS-cxKoA4xwb^0l)6l(?MFS;ZaclSK{< zqE>y(M{$Q*SlUJPK58l{w)A2F1M`HveEAmnY^imwhkspOWpGraAS>^s(aUg9J z4L${BZ)z1WKjbsW2cuugWByfeIXpn7<~)d9tSX-`@QO0+d%S-MtvHDPEYA04$&W`A z`id-?HfaxiKjob?ce*)$98l$L4i2OqF4BlRkhW+WIYhOeD8$oo(!xSDjaND~e)b*d zeT6LNedy~)03({g+l3|QP`1Q;ye+4KNj){@|-7)IR=hp z?)z!}nanf!cQcD)-A1)hovXfYKOcTzzi2wkMw^~jX}=i$}0b| z8m~CahyQ=@_T0$(_#=6LbUs^m5T7|aEg)p^H_v&QU7!{|A@j+rqqOg&e@y!`g)6i_ zgFnd4>DB`N`U}7{{jP#{q1nEh9x)OhV5f1dK7aOF{e{W-@6$h8Wehp~9^(8{##2-M zQEvRDztkl#_wYN0{ieWSI+>|Yr#N&4-xO}G^-u5t_yZs1V{&zTf`ecV`2)tXpU)Kx zT#=8Y{$ds!#|q|PbzOao7WfMO%2;)M&`a1O+E}y{Rp@E8nLe-J>!(wcm%bpbQr}Ek z{M3~*Z%_MUxx(8h1*>`uN9uR-|w9pZT#uCKR$mq_@AQh ztSQogs4?)t((`U(;RSXK&%5(6=I2s6UF3c(Yv{|&FET&|%^7XVDWz*<=v!FitdRA< zd6$CEB5%xwz?pM`)>7a8WMw~}Pw_#XbKW0#9u4T6-AKF;&a*xn*wN5u=HJI1eA?>^bep zeNfb^qPdXO0IUtXLfPd^kde>Vz7oj!$*{xQ&De#P=8C94kl&H+b3y3NxOwag*a;e^ z&;*C!Oa^)16UD+QULFZ6Gjr3_C-x7g%$ylsoxu--oX7grwgp&9E`USk-D>%cu3)oL&eB%lBUMs;2^3QtzZMR=b!cW+b$nFDPI%80ujd{9%>XmVs zzgiyuR%$-N+zfFa1++`tWq!qAdNChzIz}J#StGoQ_zF0*8b|hz;>AGhspP&`D6^>a z1%`|dc%w`eSxns{4Xj zwEu6V|BL*T*YXNGt7Xm$*W%lUmRO6|wb%A+o>*ZTV8ZJ4zyL25+@9UQ2JDcdw?4r>I1AUAi$im0aInaCs^D4a zue#`h0y!@<@F##xXF8b~bc~$56GeSCI^I$AcG-gk>Kou3GR)2Af0(hPoEOSV72K%EeW%9l?L*V$@dtAkrU%DgzaM^@_n;%Qwb>l) z!HDNFV%_yNFue}O$H zUfDR1fCCs$!|$^M;_N^UhE?cv&dCKZ)9d^}qs)LS`cCB&g=MaBx#(7I&7btWibr`w z=w^Qg%V;0bch_}&X^siGU+%B>_bm6bxlc!br?_`k#g}o8p!!=#mrgtRx!m`1-*1)= zR?}7g@TUwfM#JVZ{LEA)U9Iw>*!ZQ~EO8qSfrwM6-Y4V7zui;I2Q#NL`b{WZpZJ@W z@o9h3n2e{ZU(e5sfBAmwxq%@w3v6SC|{aFvrv=v>cC6-#|5rRs&FOCBR$vqkNcaYwU;zIO@H&2B~|{} z^wlb|&I4C-z^el-OWLa9uO(*zPn2&{*dbKGs_{3*#V8VZ5NC4%{u_YHn_>r0RrmXI z^9p_;_(;X_ivpw&Ky&LNT`?3P|Wx1;M*PV7w2YL3} z%OFS<2%_mykr;^jq?8zJ`N z_MeQkMEB$}!%IIu$M7Y>^OyZAUsm(eg4gJ0oX$jmu2C-l~ve(pg0 zX|YavV>~YT<%FQZdW3$^nv=#qO;~~cvmSCAnlE$i34hzVt?XXA5q~`djxR&q5}{a! zEG#1NEg^O%f4Wo4^zdusi($NP@j>~?zmlA2DIXv~8}`;lXa z2fiTXHJV_Xxi=7tc3%F)PW(eY{AKpEzjJQf5Pw?qvn8>Hp5}A93D5V@m`eInaQk!^mr`-2Pme>)3wVM#kpg4TZCE+5$$$ zN=W@!VB<{z`ES@Qa{dwb3Y_R9zyZ8#mNpvuQHTuik@sJAE#K-a1K%33Fu*?xc;H`Y zPEL~K#Lrt;55KJc^v7xLC;v2Con5YeBV4YQW)Z(RTgKCp`hcCD_&XCz4E)p6U%}sz zKrA(sPdM;V?%VoU8pwXwE`h$l)8MQkB{*Nw^)=r=36h?{`gm7fI0^o&%->SX-r`JQ zdm-KM()dyXMUx@9X(j`+M*Uaf$JWWrg$+{805_ z+rpTbmr|>J%Gs9BVoA~A59iN{Jz?oXPPDLpWDSf1pDP}cKV{$Lvq*jD3zqW91K-at z9B}WS-{G9}#5O>zu5$Fpw%V(SGj82IbD};!!1G2}GOWK3+7`AMALiSPUkm>+7f$ z6zi)HT(}Ni59LdqYv1O4lKDE4KjqKnCt2`v{x&?8N5QBH8uYNPd(p8Y1m5ID`)UWF~BN3v(0ggJA$9HTl=S=YWzZ~ zL;i(UVgJnOF{IuAAoBK(yhn|E#uw3BfJ2S$1uV8zeMxt4VAy?V;D2ATtd(l{%#&{S z0G~4}bG(#mV+TxIi*-K4xdD5oQh${8A02?WVS8eUt=A;`W&hya0x#h$Mjd>gov9Q} z%ioD55ickE{hR-ODWWI&IxxdqxL&`7@<^S}Y@u=!wkmgl97iU3t;aufcg%XqJ~;U4 z`E>u67l)H~{Y)Uf(_v+^@2^e0CinGgJF^JF=r3zCugws5c81F58dl-2VJ~Q-;FK*V z0-EtZqdaJPYp2gW`@dev)iST8)$I~_Ezy;i6Zf3?7jblQF)yBO&B(i(Ltwc68|4T8 zcIK9IcCiM2=Zf}?>Hlgxx#z64qj(ZIJ}mA>8m?jK#JLp*7@6WB(IylRtuOB&4Xlr+ z443otVqTT6k>4)n*c$mOez(_s_@SkWw?p|?Ua`8Z?(iY2vVF&PIqzSwc`2#(P_0ti zQIqrh6};1SFFwTcL_0=rDDQJVFZsjnnTJg3OE=4h-S$K5`FG^6OE-3;R_ouX(rv7) zICOv$reEQ>V85LAg5T_N$(Xbn)e&xk9Z}C`@-Bqs9twia-P4U zUQ&99?Q65We7Di_eaSy9>@Ch-O8F^*Kp4lIAqdUEFc>D|Fxxctz zXZAzy1k=#8q^NIZe+^UW6uctUoqC8p%8tB^7t9qbPsk6Beky>PIM(1G{+^4R^z6J- z9TJAjF!i_P87~eWiWjl?8^oi{rGt3X+P&nZHwA6R-sN%IUXuA0FF|aYiUcKwB zyx)~eu^uoy@FhNty>i!Ep@CfBVqeJL(B1Fm(3zy_#AzqQUO!i^Lcy?=v&G-x{xDZP z%~957=OicSp*}4Rx+woRoM;7pG;W{9j-S&k6Z;376C`f?Y%nC9wcOZ`Zll^r5m)sG z)DK1L3W+-a+}}Sl?o{)s%I2MqFWJeJ`2N{ksp@q7nDSTJMpxebRQLGh(|*_J<_zuS zR6O+@o7JNCBt^|K|6cBK18&YiaV5FY1+3+ z-`2mctorvK-{j^=t%k=f_%~0vUwhMiCG`zv1==j*_31w>n8WH2bDtfxr8n_*QFG{j zo&FYTrN7hZ&`nie2z;QPVyGy}K2_eRT@jZ#q^F3#@)t%80&H{MAy-}ATzut94bL+6 zqT>w}($#M@64iL7trs~7`LY9D!GX8RnJ3;tUkY}$5pR3T&hW}iE^o8RpWV+(Xy5vI zyt;GQ*)e_Lbm7AbsqIIWYsAI7VMn90^`EbGwsu}~V>_^F-En2ye@K0XebYnAUHI*c znZjzk;zO^*UxTv7Ou5^`pIN-V(r^DQkP*6OVH?Wtpnz@}o0(KWsH4tr7Sitio&IW^ zGhWv(%s9@EQPEuCxsRE0DE8U*k8$yNB{h?p5pDFmWBfQEZqLke1oxl;5|Dr3ia)b3 z1EdVhzJKh_cvlKD7k*zI1FQ1kmD&uaMan)q@#FaK1Gr|qM)|jAp1Jb+%;L-&;kOMK zE|MWbl#k)E3y`=kXMp*Pafpqphb|m>3=gQh{{@HjQ1@0+4ZjjJ62RKV#w(e^x0cUa z1NowKNF5$w9gLV<1x4iiD*ws>CYmYb{i8f~L!5Epe^~7EKt-1b0PNZiu056g_n()l*F` z-us#z%l!1vdW7P$-+b1lFU09j7v7@YWIi(Xp+W`{m+}{{yovo6@f7`;NpXnx zCjLD$_CwqYURg+e@4Jg{F4%XET|1N>3qvdQ$l~w3d2K6qJC3}aVOF}0#S3qK#xOVz zpf>oJZF%@sGVt2V|FL1tC-6^WdM4C~*JLL;%J-TjtQ6(l(>-UF=k7n7oqym5wz2ZH z(hq-8NmzgPYjr2eI0baTA_E>zI_qx&WJ@6ml_f`U%@rR63 z2^og>8@lu9*@WGZy7T;Y-n53j4SsCt&Vg5)81!%PhX(T0?|uFEesJ^$(?6L0x}2B) z|1ECtBWJSFN8;*Sox@}K8^t9(ibwyC;_^58PVz@}$zS=A^ym}Ce_8&hzJIIyjp@HE z9`z||@5c6TOpof2{PO=_mS4V$(xW_4e0_aU+WP$eZ|akB>+Ad1%1hoTf7JGk`EN{L zACJmJ?cG@4jp^&-^8e_wzPx-F#c#|n^+)MZ*{DBJT9h93C5p@6=)0)?_3<0iB_4ew z|1V3A+WckdQJVaX(xW;g9;M57Q9Sxi;!)fGR{1Dh{@z$V`tH9}|N8t<-l#vntoOfCQVjC>!YrPVk+FH1YSX7_-){8k37YQ^9sx);|tQPBLD`wrqo=bx6myAPOAqe*oy{P!_m61pu zX}!gcIouUfVFho(+@6zH0GdJkanre}T_xR1>1Wg*k#ofZ5d2F8pGP-%84dqt>q8== zp@Y0`v>2Riv%iwtQnr)yN6Ppvvt&FB+(XN5-png(Yx65|{syC2KN6LhF(*v#`u4G( zw2j6P`DD!UThetIbu8+y#f!*gK5?u*l>Q**Az2urU(z0FrIhbW9fD!J;$gQq61zT# z##8ppQIOPF$@JJ?*d5kiZ8Qx2gAU#-tuNQc=v&Bn6CWMK)(SccwX^Fox7d1fjrLpb>e^5Fl6Ka ztodVt$pSz1!z2P34lg3?E-neCv^o(!;rouj+n~&88v&?cuR&0CME%`B8#;(@hE}JA z^3pPPNDVxxNwCmIg8Z^d&^p@?mPt+vbHaS7)g|-U;=aGXB`NqS;}RMoR5PLs(O@VYZxB}H@i3EExpBM=j;j`v&C6Av`!Kzao7P#_`n!|3ETcH;22TQj12Z6_o>~7FQZ-ce#;s!@7@3t)OxBo`o zV_;q3pU5Z}evr4M_ifJ8a&w(N<{i`6vSfQh%VY2_dBd>Texc|Mm&EI%Ti zR7u^n#G!!qBgJ>6Op#Y9S{&#vd|2W#cN(4>C@(+4*Q1}c|4TkelQL1cwY-8SLcSsy zV=W%lB$A8Zhh9@#mW7h7FE6l?bWO`R`GzuTtY!Y7$2xs|3GrD2MOU0D>L>WekCq;Q z#dYnq%KC(^=pZtH{Ll6Gq}`J^&L8O+SxeVk3EYQxqLqVU<7tVyqw)h&(jj`I=*x!E zQv;mH`kD@Eo+16vaal!r0@tT+S+blcuBnUgFAZ4;tt@$0;?kzjF5v)Cy6QK+pCm3L zhB`R-mjS{upKIff@=IT2j&-`}B`BNrTU32gUf?CripobdNc_fhiA&$NEUo4L<>f`b zmHr48Zf(S^e$~Frlu$EGGuGE$1jBBO%V;cbnpfL5Uzi%zqZ9fh?^*~hqTvoqFrIT2 z4=z#Rox+Uv9l`BRSLg5fhqU|X_vE87SO4ZNa!Gn7q~A7r2^o63mL@P>9}`S4N)m(@ zVOirP9Vxvj0Fmupr`OArG?ogB?{#huGb)|2BQNXvg$4@6-x~D#z1(tB<aq7Pz{@S{D@Ah*Ww=79(mPjT*6F=_Z+IWXT;Hz3|_2Li4AL+laH+@*0 zCrS3LVJ}RZ@vC5?rImO_>|F>BYkZPW_t*DF`bYk$P3I(!w3jK!c$qI|M9;_i{El^Q zqk>1k6$ihckVT)kzC8V9zBEUd`i}6{rd48okf8P%eT|IOjKcx@&3)!)O{;3b=iroQ zZ$Ah8yr{iaC0(A|Xdq*Y%~*$^2-@H^{OU{fxns}=39^%upjR6B*u>|t#v1(SPagP{ ztaNKSZpE!8z6eC&(``nd-EZfd7K0pT=Y_|7BD*>i1ne`VjDdj14H?ZG~OpPcF=$fMcy~l)iBB-f6jd#=}mUW_RG0lRE}Z_tl@ zvl<`JvOTFUo0ioMJ_YgmzItzc%w1dG{kQHj?vwk`^vIU=Pk+Wu-9Jr#`jARgd)xuG zE4PP2Pi&)|_j&}sjygvNo@c%{g{{nPywT5$Gr#Nbd2b`4KkcE0=L3RY;;x-@S?ZJZ zc|AV+y8rTm5b$5hU>{)ZXjzgurGKIHM_N?$kNL@5)bV&MVfGrTzX}5MU(Fx$S(0Fv zsILUP^?pauGmb}77jBE%Cw&fjH5auXm-WiIc(lH_hOzx`egK7OxBUw zH!X|T`M!8xJo_2dpXPdEepc6~l>e)ZZRp4)Xn5=mBK+p%3FsmDORMRn-nl+*bt`y+ z9YT-$?fZmYG+J4Wab{QMSK4pV3x%)DHo6k>JAGas_KB)Ky`D6_OZ%*@xV6vxt)FLY zg&$CtxcNzQe>qd8KItD4U$ov^y%w*H6?i)w2>#>AiV`pJ{jq&!26(KlKeI0YzjS$- z?^2(YwPoeU^GV)&nIzQJeSWL7Rnap=FQh-zuI9T*ubb=NQtMyfP4D7Zm)e{4rT5*IarAnU7o9YHSLuv50d?8uKLEU2 z8o-axr`N0CGaK&qtG#BgdEaG$zw|er?o0P&XpfwBMXs_=T9a0tvkA42A83xZuIA4H zUj-j8jtRY^#`W~FIiJWn&__e{2YiJdShsW1x(?qJe{PNsNmTm(QXsP}{cR8XEJa@w zJlEm>y7u-4&}TJ&a;CD66~p|g{NSU)w=sB;1SN0C`cka|pfvca#}7SF z`8k<$!(Rom3DHIRC%|Cg2eO+}^l@3_x$FC{<&Q0_M&KjxjQD$A!%Nf07Az)M|5y9) zVWa9dU9+*Wv5c{@LuT^tT1ce47oul>Q6+{jFE+bZ0f1E26i-6ix03Ze2V`nk2y&x)h{Re9`o#g7D%Td`7e?MK67#=M5t zTK|P#5fZidZ0|RFt7G33?6RRIj&YP3tDC}^uox^PM<&V>_VY-W=vkrH3G=tE^|Kx% z_b#}(12>oXv&~)S6Wr8rXD10SUlMGKgKe(&2ps<(tQZzrVc_NrF z=D}~U-D7t_>nDP_CViIgddq$IwHA2F9!WI5ZFW~m+Ha@*J;8+ka4_$QWYX41;z4WT z+(h*SN2LcE|9+CdIbDgZGGNYwBOp< z{ziYcKby^}{zmC}2ts4CkAC%|IVE5zpQRWj~l}8@1y^+FP2*$$MERQ{FJQ9 zrgxA(=D=T}m$F{YY&~aZdfnbj_ia}77i3oVg7Mk3%pUZE7ix|ZUc^2k+K*6v4*5#@ z)5Q0_W!6hc<|B?oA?tnY&n3P~<0BL)Q<9nm|K0Kl64I0#%_0tWU$<+GcY{psq@uSNkK|kGt&84C$Yx;ITSh z{4H%-Vm(-Umno0@uwGuEzEoSi-IZG{kA+8_=Uofw8u=Ow>-GBmvB|ah{N#IzpBtOK z*0XKMuls~Po?Tmy`}KMhct8`j%6#FkRh7q=EA%whi`Sv3ec)l-9$v45{z+dE>>+y3?=zpn=+V=!U&7=5vQ1BIc(A=*P7kmOE`;eg2`h(v_{PZyU zi)g%}A9?`!4}Cxtdh7PO$ajwPNBB$BU)?_k?es+HL^xL!d=+|XL*06@4Whols>WyA z;AVTnEbZSGs=+AlQehuXhe zpL{Q4X#Ub+byt6P;yd5`gtEV7ehjxVSvhXKSg?(@QoGTyvm^f48%N_W#Mj2BXE$e8_deU)pOmnUwZXSLk4llv}K=Z?hj!^1X2Jtv^ZT-0T;sN9}oJA0RT( z_RWvL9pTSH{XNm=sQuys>$AxZH9mZMGFl(q<}u^pGxh7{Q}$CDUt68N?SKECXm|zQ z$XDsOzpsWoq1KbgpSnKHKcn>-={KZ(^hIclpdU(JV!sD>@1LbSw51KbauXl!6nNOY z;QYx<&YAs5`$qbECc*Aa-%l(_q>HS$>2K~v`)Ot?G;fPv(K~hS^Q^{0M{g{6&_wCx+ zdVMTJel9C`>iI-IgMK&ZndS#;alt?6t+X!k;#?c8L2o?ZzkSmsJ7L@KTRT%-H$L4z z$={q$p-)ZvAMsyDjYr8pO@68K3w==VfF8b`sBuAe_QdSuH|w*iebq~uU*s3^Yxzl+ zXXf#T>vAWK{vt20u1~AC3Vc0T&+P&7MrHzvg*-ple$FntKKzFrLfzN&9sXeKJ>Sp$ zUB(lle+uH|{-B>5`~okL|AB|-SL&eOK>Im)aaos-;4AbWekMDwGwe4A;J;Cq`DZ^Q zGUZp#8M0gm(Obbfjr7oGa=2;?&sO zUrGJz=3n6-yJOkEsP@5EMX!Jd{09T_o<_<_Kk{jO5L~Ey`knRt>xDiNkMI@wGwTt5 zyEPlnZhag5U%>v-X>~U(#CzlOdz1Z#*U4Y(PT|KTSsk2YC*$3{y}joiXpSGORQeai zZ#Df?^OGBq)h6pLIS9VGFR#Ma@g4)h$Ok3i|J*`uH0ANCRon8cU2UuV#@CT2;H|BM z_Ap-Uud;tLzz*Q6;UoKD`XAyBKZ8Dv{lR_E^A=0d7m>djW7gK{PTEJ^oqg=mu?N3h zRrEyDS6k5!#s9$%xFPUR{s`^h6YlQtm^&HN9aVo4t;Il}(;w!bL+C=mx1{yEUpw0P zHhRJ~ciTc|Z>M{_{$K6T{8IXtuz!mct?9ij`t;_0L+~|jyZJ7g{ciYeOYN5fclKkm zM<>}2mKFa5D$oPj&!InP>eEDC4B79L)Ov-=YIz%eH?ZYWTVm_1@aHiX>|IJY+>8pL z=fR62&vQRC?kj%j(;rX#N(=v)fS%2HcC7u?#E6^S^TuR$GW*gS;5*bv$v>KYus+uK zm7-U3EoeWty$61u&*oarS!?mvv!k+p*YhKx*PDJ4&n2?ISw&t%SJC2HSe+veFZ8+D zm|E|O{`I2&L|^B%qAx{;tstLpCpcPv$+XZn*-s;`W6Pv7AFKMDa+~*& zL#n@rw0;l%H`u;}JmDM^C+206r0YG1$*6WTBsH^C$FO;DNr$W`AJc9;p3Pz<$0F zm;I%eZLWtTCj=+L$=E_U8oyp2^CJH`$bWc@opeuxb@A5^EY{YKti-Kn-Aebu(Lwk@ z+8Wq$4*f&QF7?@amomD3BbsawMPkZU5Vkh<-#)*O0&Uc}Hn1i1@8Dc-)_?FNnN^e9nFZ z?%F?@5q$_0JL#hjOdT^`5csXqQ<2|S<#Uhy3;GMVJ$uN+*FI{qKd>@JT%FbSoOcFK zlqbxW>a+(0dd@n=#LOe}3-by-&`ZZao-MJzUYma}hN5cu{4EssjZTC6~9Tz^IK3;e+ExQ%; zVYXX;?CiwIoXAhCr#)coiQuR)kD|3T3A{M*>I?Vsez?qTg4uPM-AVVwz?!q>gg=9i zb?{N(S3(~4<5%}4`s-O=uV>MpX?ct{ERmI6w<~va^jPiN(3-ft>tfRBIeX0iQQdU~ z+m*h7_C^1#`oq0M*-uP1;AhN^1-G)Dy>PIx07-!B2z$8GHd&o~qh5pF1g&Tzkgr6) z&$)}D-(F|#So(Mlc>?@^|8c$szhFN|etXkf@!Yl?=b0AtO!t2_KG{Eu{-dh+H}8&i zEI0W#E3eIV=HS1~82HXvt}XmOm@JK1luO8$I;bNH@^W^sl|g z{t^AHnxCr7&lk>rq5g8c?Ls>eLC-rKJ5RiReDtN)mArv8?>dw9ho7A@fah{663?%? z{l4grSZ^88pR@(N%oy~4Kf0^Z9!7Y~I{w~ww7eR0CX#5oCMu#26?p;~9qOm%hy4%u z#SWPH*nzw|$JiExo*lI(=0si;`Dk}T*3U7E{dT2wvGuJ4Z~gWsDIX@S{&aVGv^ui$ z$mNUNt5NeQ@|Z3BUCW#B_qoo5=vNn8w{fRso843G96XUc?!Qz8-+6~SS?eJE_|=6N ztHXqz8=Z|wC}7=Lr4K39ejq1T+j4sjCBe26hvw53r_bm|Gwp$rm(_Vgw0~FghcsvV zNw>pdJ;fH~WY2CtBkLV{zo5>8*U3M?uZho+e&WpYb|Mjv@2auL3y)PFsV-E}k5|NA zf%BZj{x4>e8a}!{!PoZZ61Dc{+}fV!CS#L7uh)eCqEG6D-(`De@5@B{q+3b`-jJKpO4QWABp~>hnu92Az{4Kko6H~bwu=u?po~? z_pDoDKU%35&_6IX_N&O>vi@wr|L%^D_gpw?JzPP*iuHrV?xKy|UDMyr_{YG{ z6T$N`o6s|P)mWtGJ*fzudx9@G=;s})iu^Mx`{%ttP~;!c$1pzg_|@YH__ffhfHO#T z6FObN7Y@n!6Z09b#4GLZB&+Vu6PG7(S+C@&**Gd{(mGikEj^a?@X!ec1ipDnADv>0_Cu{1F2`nSbbQR?RoNnbgR` z4?_PQjOf2!&&;o<);Iiv^%{FY^S7YGcIuBkh<-bZWzWTJcpq{zC*C=3zH~leY|DSd zbQgA4C-Retm)O6dFHSQDY0=j`04DMPS}n=FMEIfcXJI4{h% zm|tk}XXLMAvy-QU{%*@{`(c-zT$uD_e=Plv^AK@QIO%`xA70Ff^tUBU#MF^54%*5c!b4vdD za!=ezJXV;nUbcmMY~eHpc)5Fj*rZ>^?jI%>9{%A`8+fB#idUSIyTAU3@p(K#iFCsG zP`K6pB>JDRu>CAOI^))F`~GBI&evpq6nzMgpBCz8x24+8el)%3>~5&n=kI(W*tUIJ zVi(kYPwLnskDXmy(EWGKj%8WDFXlvB)qV#3DAMThYW+EpjzpgC3BRyNe%`l|`Gbmxffhn=ZaMS37flJe# zlo2E?AM3FwEH6kEG4wcSLLZ7f(#lDd z&O0QM9ydigw0S~XKMlGdpeJ+Q431GU34*`Oxjmxbt!!SYhrEX5lfG*VG3EA2~0 zCbwB6j+HR^#V(nEjjsAD-%D?_75NJE8Mrxu^}3gGYXXeb-+Hup!~GCxTib$fS(5)p zm?iinA3Y9jyDj#?+Af-Q9Km5X9YN;&ZR%FWoM30HqHh$4{Um7QVc}geOIV**S;?ep z+jzNeU>N@*&S)jqV8cocE?S>6c|*q>*)e#T5lIQ3w=cS4(=j}hh)>soj2{rLhPC*S ztMcvI`d{HPgrn?P^xWwgmi+QR9ki{yrVm?|EqlANZ`ZZMq=;*6MeJgoaJdO8VWkhVPF?4>HJmB z0l04jGRcqR|EeiD)qOT%GbXnU8gl1PmoEk*=8Sc-aWg&CwKqqNg}g2;Hz;nVHHi;X zKEl5!|DX`gu+S|3t*d;G4gasK)+e!z)<aB zUNhah1^-*3`7@wnXuI)~ZlI&FD+d0k9Cm9P&`VJt_;*(W0}j;IriG=dqsn6)6SHm! z*o)B}+GGE)!H%U9x1nzKM*I%We+*g>+1IFg6{q5qZV8PNoDulk5hTr|88eZ?kxg`e z_K=DuN5w}xu?~ZRQMx@eSd%^HlPIWes>kbzx^7R}Pi$n@s@g{yNK?Ps#fk^K-S}BF zMAGu{cS8Tf+E@A`E=Zc;lRX;0U$ zCBLZto3F}zw5$0O>4yFy$Hgma`CHS-rD=(aHBrnmH@2beG!kCiVgJCfp1tj2A};mG ze9&K@rQy{aPf0W>%ukw!_R@?GNe%d2mtVI}{nZ$w|5Y>@s()z9ZfeTK!(NATQ`ic0 z-*t8eNyk7MV)x0du$wq@`-o$f{2BMzo{MJnmTKa;_E}Y)-JAhLMRwbO46uj&;Y~lh zIrq`H%-_9eEB6GZdGpn6iEUSJjGM-R{B7(nZo*-1BGEo;8UOX$qqWi6rZ>6|cV|9! zQRN4shQa*S>A#`*l3tI(pQ5;u4~7BKqHR!AbMb4C`U_Juuek z?j_r>m+k6KUYAc2vQ?d5XmbY?w~Kk#avbI9!q7X{r)&C8imVBOTan%jaX-v;l5_al z0p88>?@0MQ7v%iUR+c1H)`P6~C>@!Tbla%mSEq&tC!D`jW2!&$y~u0wv5bSp!Kq@} zNU!kWFXcsI9pXN1&pXKlqgt3V{f{k(b>@ZJwk)aj$sSI0&`IzA0-pLu^E40sXxJig z2yYXKN7JVb#=Vy{M_hw9-FK!2#CL$d?nhI74KHMlCV!2j56$byV?X5bo?iK&@UvwA z?~TnK&kJB9LxzbtT2MABxAT*RXCH3X% zv#f5nE<)W%3 zOAbZo&7v#!Qzb;uG%X8zQGna5zk|_qH0zh~?4mA-+osg8Qjc++FX<+veG|;UTbB+| z{J40B<~zwvk0|NY&r%{DlTe(A*W$HeEenINdBrxs`=G#hpZ`nRH@Tff`A%9axkl_O zua1t4Hh)&$HK@yzKy5y1^0oHT^)m34xCK0<2Sxnzo2FlO%blbY>n6XW{tn}9%m89K zzjz+g^QTZNSc}ViGXw6h` zIV$}J1Dm}!)Oc3P36=kBUGS%9Vjb-61{S0Br&WFMYZn6?!l0{%B0kX>&t>2f8+z3l zaYlyT;7paE_IHlHgDU%k4dyZC*8&rgGTY7eqX+*b0^*H z?rrX0xg(^y=87x0zT#HMFYt8h2Qf)F=(_dm;oCv|rkdY%_^UFn;Tq8^wzRx(}kvkfyzp6jd7pXrFzq%sZt&}yc$ZzQ%9tyxd zjelm$jIF$C#)h!@7^<0Z*5|9<$k@new)h6-e_4TVvFz0y_qXcZ1YW)|N6frnTiuco ztM)a%u3VP+{R$Rc-SsxNyY4f?dVXm%g0I;E#7CJ~je*hnNV(_hzvAAn>WlD8;B_N@ z7-oSk4??-u+SlvlAoHo_yNoAiy!Xo#4ArH7GJgVnDRE0|3P!Xt(;e@w{U<)M%hGen znA)VhJNbK0F9q>N>E$FXQ9ZlzK5FiJJb&UVSNfc6(9Qt$szD#4bC_<2Y4Fs zn`Q=paPie`@on*yH@0E_Cr`d5jn?0Ox3jym+XjD%=7>96{{^G}4d~0tPg@z!XjU-9(D)L& zcP7oNbNAM~_(8Kqf2F6oMS)M;+zezA^-lK^_}d1BO2&@Gf21fB@cOwI8-qU_`Lh3~ zem8wJTg;Vui;R_0BVgNC&L40W>KezSKB3n|*I_+Z>&({AQ!|~dL+^IB_Pj3ibc;zH z^>m##0NuNg59B>7zmm_~fp<>MYhzEonjIM(8P87ETH|eTGqx$#`|95(jd+pQE`~cl)0CoyFNN481P!ac73!b)Wgf>z`b7pV<}b zhz)|{#W%Lsj>mtsCab+D5UFLeM}R;ie{1bk41W?jtT=5d7@mZH_v=mG9ZdPF`Ip6~ zQGB~j4?Qh|AtMO?FvNQ|%${Jv9JefQcieL~8Jo}b_aaN;^?{$jaRp-P9)|_L_BWJn zHU80HU+C;_rVp{A5%UNu4*v1o0pilW@{7P3+=OQ%e%@l z(TDQK!B>ULHd667UL`O4l~l%dQV&Y)>dlHkO0T%mw8I+~Bf*UOWp~sy_@ zQtKzpBPWF*4NapxH6CCVC?i?=i>Ro|<4%Eqf9i{}aX3;CmD0U&sZTU-+p#DZalfkS z6aATio?|37V@CdUwAMnjyV_TUj9d7*jQ6C2iUFC&BP8it0`DFc{T~zvP&Y9Z7ycsf z6Nnql_SihYs7DGb@fM}xqJOfnDQM~JNLSB2BZ>qWQpAJ+qg0 zMGK;Q6Qn>+ye zqe4f#E8eO4BmPS)#w!$8+Glo{pMrw#(DKHK4W)G&O3bBV_CDJx6ypa8GMj_Uf2CQz zIl8z=t;*82_;9kBl%GB*+g% zpgx)30^<{3nUY__Q)G~C<|~P36KPL+aM1N_zxsrIC;pNrYoD&!;D?Ns*8%b(pFZT` zO<&5-p+6@#bc(t8s`Ho5SA)L-jr4G`&gTNc#@(O-3zeB7?nP1@;GTS3SfcGItx7{r5XPv`py%=EhMth1C zuu{e2W_-4`Bff=$n}c>Yt#^YhrJ5x%`egG>lJ|0D{);v~;|tQegK^7lzE~0#h}{J~ zu(tSoHUF1bYp)1>!2z(GxOPLKOCer$q%}@o4yy8k>nlxcmKnW;{wND;@axg|LsEa0 z7OOb7ji+lzYO+2@0<=QABMO${;C9_i}N%mHeM>Q9>$pPK+GUGk%^Hcy-Ja+E$|ewE%1VQ(qE zm)L*XN2*mc?h;>X?^(rf@IH^!@CTQLQb}rae3eS2GZoe6nLoN5Gvm$t4*6?-YdK~{ z>1p$i&LbQ&<4N;?St;B8W8atbU1+99+#g+ynM0R#+%=1rE9JOfH}i^ zBgU*wcSz@S?Y!oPLqWfTu*cOP@eyMLEjCx5l>ZgdOJ2z@`O9}z524S}aj$f5L%%1j%ir6O zTwY1nH*9#NBh-7xQnUX3cb)SMAKhj%Zs`1XL8Xd;N@*NSjirvI*V3i-d(pq?`l+oX zZAyH^pl=r6n7-(P0^#RJ=F(Hy)R6_1pPZ84ullOLBfOL+YyOU4#L?-xZpo$U^F};8 zTJ!txl&a6Tmz(~_e1Czr8bUc&9C7a6{-yUkX-k(sLeK8r{^Wc9`u2V%C5vI&yEmV!KGsNE zl(TesspDY!-iGA&?IVF-y*GHUL>_v;_fyfwXFd#0tOSd6Q2pn1$0(@wQSJNoh%@Zz z`IGs$m%Dutd^7}n```bAhg71*q55)fW0=|*uZ&2(0dB-YxUnN68a9q7_)=mS)w_M~ zvS&p4N%^bKx3qrG6h#ehhSANYKS-TJeFR?0;|surJuUroYI;xDX-uvwaSU7mLH=Q(NQ<~4_?dd!9vnziDP{!_T&NQ z2Cm;>-gTi8|EDvK_32t;@TO8E-}AQ=^J2m#Rzss;dD8z43ddAVMM&_NE@1+98fi%- zaFVHmZS{jfc!@f}pN?na^>(|3Bqid=Qf+hYDb^i)ND2yi!-of#o=*|DdW7@8;=b>QJSUF5YTUuMzq80)`T)QmgSZS(}mW;!16=Th^jdTK$ZOJ6v> zi^?-DIU|%?PR;f?krN*Xavmc6=_ylI>Ek3WVh+En?wor;rI%EB11rHfonKbA+$nLH zFUm{J)V~@x_Hd@GKRUm&x#wh;C!rbNzvrCfPo^aJ>Yk-NPaa(AQ66#pKoRr~)T?EQn|IL|xJ2H2vSG9wKj zcnxP6vN33oL)dH5K5vf6(O?TZQW^uw8bSj?_9~|0Qq}3Q`-kk4OArMCW8PeL!gK8n zAt+K3MM4;OGXUwxcjdcM?XhU?9yiN%ZFzYr)t>)QF^HDuV^l5&k`ZeNHJbPNzHj$n zNZsw>tr_4&cfb9<&+qqnpZ9qOb{}~ANK&XDI8E;_^1EJG;0n24*}vH;HcItxBTa1) z-w+d*)@%d}5elLF+4e^>edV{sU$UxPsc1+Pkd?}}Ogw{RfUR$7LfxOm+VvovJL?Y7 z&5Uo&>h2>A{qBrEQUsFPlb+8s5UqutuRMs-dg{+@^@iSstR{+Y7OB1c(*IxGxp&*z zbg?_=^0p<(DC@Dz_Me+Uj3rLrM>7NSz<13I+-O+EVX4lpYkvp-G4)lWeSy_Z*3>OD zE&T2y783-KA=a%)qH_#o9r1^KB8kDet=!W<2mhkEj*w;jSpF!R-y5j17GSd-&+#{T zi;3#Oe)00qtgWj*j=wwXs&0Rxzkk)e6JC;^_r|I8FFFP6cl1-f-pBm?i&y`5==oOF zM#|*jAL3;^G*X>B1Pv^;?y4&d%VJJB~r`^_vc=cwl37f!RBd4Rcf7@P>gLYH%w^BdDz zPyUkm-m~f|ZYG@Nox2Ww9fN%j`bYlJIlLc}1+5m#-zAGnRHq-S`3=ILI9sxnX!Spx z&v~z#_!wz+{fMT3x6$;rZW`n31(P}4E_zetG?z~OoIP(EF#$ifU!Nn(IrCb6IJ?s4 zdH*>)4q2h@JfB#LL*L?eI+)v&TB%$7;(K$k?>eFUk;PGZ6JZ}cVMk}VLl#{p{b{U* zp5Rx@tp|70eoPY-&CmcRNSikHPUPc{;r-co-R`E1tP=WYn~d+Nkxv`%^@3TI?d zgkR22);WwSi)xzlhQslgBXB6#NAWascS;{iM%263I6h z*26EXX0_jq!Zm4~aGm+FiqCFiI!#;ij8bsrqs7v`%EINL9AhhxsB ztSP#4v}VSyo->0U^Tugmo6fUl?yB)TVk|}2Ak6aH-A+xwrUPEOrjATAR{@rMNASOm zH#x8_6zsb$eB8aJQxm@qdzt%NP_%k)W?5>((yGO222azQI10t}SVVE?hOQzE1)t|H z>8dHS;K!UVZfcyfZ1D@VeRk}NV^5ARZS_|aFKBdkKj$)^En6C7{A=oeilJEWoYo1i zcWM_Y~?N$>V>no_DHy6p2USw`1QAKWX&UsA2IbPE{ErH~6;e(*c|nj9u4CANXH&@!)@I z)zB0WvHWat4L;0x#-gzzQ5B;{BkI26f0UfgQ@(Jzl#aJ0kn2bM{+#7?e~gUGmL8&* zcX_4oXt>4CrF)M$;|7x-g#ZLb0>U1*55Y0h*}>(mUrcJ-n%$T5&3F?^S{A<SF?I%o2h;DQMH&n=skq}V%}%@SNygH zb%mVEYsc3&=5gIm>#=yk$a6Px$JeDJ#?~!<47G>iGSi+Q2?s{2(W>b`xG%ZDgg)O^ zcS<4ciC&|z0vzfAe~sVvCpx+p{ib?2-V!(K+wr^nZ^*yL-rFfwrGWq8=T}pBpkFj< z8w;p!$usm%8++21z|-_cJ<9kK-W;(U>hSY?Tw2JA6Lm*czC4ns54zrl4^T4gi?f4h zN$Vtt`H-2{W5E;3rq0n6>fhB;BP+u9v}*IEw@a^-8tM21ElYpMZ^Mu7Q5OjTK8^hI zB5&*lFe-@m-kmv1<_7cAgudhT;sWL6Sl=3-(YI>v>R6=qPlhE?B;1cYw(thlXj>?{ z6TX75h3D3IGWqEFHshT7(;h!`V&xkrY8v?__#1qh_JvU*3_b7*W>teeM8CO`N}@Q@ zF24)=szVFn{38UWF?6~(ZbZy!nVf^ZDYX7WbzXD-%!aa$t%Q+TWJZ%>jLVf4Z)?<<}x!vAF>^Mo(PoA&3> z_@%V{3r(R@Cnz{x^pHs?=7VCojnbFe9>!WUqSD8!jrnCPjN5&>vzag z=(bz@kfT2-$7{T6{>zN0Q9I+kxTgM@l~!yAv@q+lj*osQivmjMo z^J5FqE8PDIDH`B;yaw|5V1}#x6rM#{B?g|{VzFiD19=4HCF8k=b7P0v_`@W#`&*DN zt|W_VCL4IxBd;-8DKk03YDzEVdSZKX=;u z&i3C|egjT)#uLhXANirHqMzy+=S=*f`;yDdz5LDc#N#KPnRt7Gd_;ophnHB$V^;i< z|B|7%=_-9Sy(=xKfAA|kjHH#JXY5aYqnpgP;46EEC#0dF@HW59ADw5s@>l3-<{RU= zv4WwW3*(o-a1gyczLWNQpX(d@32*2fn;84&(3_1lv-D!^d+gGZEMn=ehO@x^{b274 z+<&jyd+so^DP)0Ukj9I>i@hrC4tzT1bEPk14_0UD#qSp{7i&7d4gU!A@_aIu%`kqV z=fw{TwO8tA!ZV_$5PI>T-vIf7b>HoO;4d70srY(vzBUiN8~#Yl=~d8ZhW{;l#L5e+ zF$_H#{cNQJ@+Jp=IA{wb!q}7OFQf>wYeS8D8g#$Vwe(?d#y{h~p71UH>cqe7gJ9Zd z;!GY{{b;r0%lI$uyY@};mQGZr-kx|2d}sEPYkOqqEfKcAyl&|;+kbg@ntLUmi_eSt zBdFgu`qbKA@HR#A1^6LN1s!bWlz$DsO2&G3obSV`#IA2XF%h1)G!ahBPFw+h;qxgi z8T#tp_U_4iX}B~z{@&O##TK{>u#wyRzT{s zVEv-xXCp*<7UzrU_|NsLrJ`^B~McM$@3lZ z&o`@8$o-MR*K=nJ_y=%F0rIBrk<0Y9Z;X7&*?OdWsGcwSWIRUWLhs-celH{4%II{~hn(B_ zvr|8s@u|J{*XDBz{vWplHHTT|$wH|R702d{{gBGfqZPHL`PtnUo?$lz)`|JHb;V8{ z=X~PI(jD|T+A-cLG-2s!OFjY(2jLm(VX1iUguHLqAn(pBnko<`?*VjU6}jY44G@OMQ4?obfBx zUa+)N!a_FVHM6zUUs9!iNP;m>)}7Js+uuKQ#(#McX*=>F{sCwD7njt#mt)~a`1(b> zu<**lnP9%SP&4|^TK9ZQzFYbG(z>-EoE!If?-rH|-;EZ%KfkhAhaP-Rj`GKRjfVb+ zUhtgY?+Bu&O5Zp9%G}Jz8z@Bfh4n|-_2JICc7W-A%MS)dW$Ej0kVhWdmG4InIe6FK zBTRAS#!B-%CtBYjFMYu?wU-v~n7Ao?k+fDqvc8`v#%wIs3hNHWCwtz0wEW@#Kllmj z5$V=sK1P2me@6j53JiR(W#ERK=07Zr&uHgF| z^zksW!4f`CC+seMP+W*4J^#RK6nUSq=S#Vx4pjT9d4ICd{YUP+^WuetrOx@NJ>M(y zFUfD&?R>m{cVBqAHnDKblg0m72>(}~b&l;m)_dZuW4({|g3ru;GxW>6jQG2Okpb4T zj}-l-?K=;d@YEx-ft*~C=xwd>@@x3__<8YFgI}u+@d=K9LGzhsuYH9`JNpLU4ZW9$ zyoE*sBfnGo<>6myPSnLtNANj2RXxUT{$rOr`Y);8IUZ9N{y)4bY@F$TeZA4Em6~t* z6Ei0+v)Q3Iahdm7eQvDTs493%{weBK^G$Pq?!<)&a)C|GPBpkc{9tB2RC%3Ee;xRg zk8{J+kxZL_sd?P2)M;)#M=a;->)M}c_{TxMNMcKWFFuF$2=uWYuy^ZSSDxkEpJT(vhNsRS zi`w#0(vgpzm;J;16PZ_P5bL4wr`pZDrLa>Few- zRw?m7`myJ;%VO1Tzh^H)3w={>PgW)?*rUPo_?b&*$MdDH8GKGNfAuDkd)QJesHXJqVG}c%i|UCV~0F-4E}#MHe4z^9ARV38h&VNN8zW9 zFU=vqpIINMrV@Ky@B0SupSpO=d(?ZhZs;vb_8M@{-!u)t^O!ApKo)`6|@gDa5 zq7-qTwMR8S6>Zx7$bN}x_A34&*V+9%*CWY$KU&P>oAq|le?PT%QVLD!NwgyW+jQrA zf{Y=>jNW)&T1)dI&F`@E<~?jEr|VJ&{r;%L`FVDPUz#3@zBCQ@RN)`&xUnBar^nxm z=H;zb9t=0UZ}p3h{oB7Z?W<+J(!NI6oxT5o?la_k7=T|gePVYSvx+gTrL>vI`8|%`WW57?ua$PE{=QdI zee0H>IaVD6FEc-2YzBjOgTY@I+zEg4n!i>xKd=;t`~hBTi)R}1(aXsnafijHGF?7c zl)UZ=&LH+mBvce{%SZ#WOO*&!NTsZeRICtJN4GF z-R$3);Q7S*f9Nq*OB+8;Y}~r|&&ogMe|RMXzYco@E6wO5>`o+}aN=!S>&mUIzSz$j z(bg~aYkZQ2mVOyO_7MIAY(uE8i98LrKW_N@@zkEO@(5|f^={s`d)w-BdAy(Un5`Ll z^syf;^~xRxp6&SrD_q!zjcMAB7UBOT<9{zc*OKg~h1S?9GhZ>>WckUdImKys(XPLa zm5hDakT;9@Q8=F5i?<*@Jzt+Jv-76x)sdg|=Ui5<>c9h?1^m+anXGxuFKs-+$hxDQ zUeAc$q%RD`Ii~*|^w6kg@R3L25Bpza)ogaUHyVx}oIXXij{ou}4)M{~lRtG<;-%Ws z(&9o!zlOd<&u#cNs>c3D-lq0>YwX@fS_VG})`Byi%zJ;}S!p2}w;u+O{JgNDlB}%! z#Y$%18vnx5OMOH;#@{kKH?-qnQu3@kT_1Y}jc7Ea(_sF)(0Jm^D}V4%BYu%!k8Q-W zFnjmF-zfGC_&{G^=?I?GW6!%@Uh@Am{!?}|e;2KU{sBH{pP2QArqu^iSC8$US~wP* zc-!oznVl_qOScMSJSjN7=YK1ya5BQN;J4`!>#=$4QLTs?k00=mzIKc@M#8q~S<(i0 z8U1zz{kHq%w_bYkrH~U^{cnz(2rG*ff9fz;w)R1Uec*%tmXW`r??pl6rS%Sd+o-&S zJPW7478(1fG;#84-MszoS7x|YlcT6 z^id9Zky}`L{bFOZv8eUkXOr^cl-7s%WYI`gPT_@O{3ngB0^a_3jQ=J2zoWB_v#-5z z{ZH{Ci{4ik|D4RBOG|$qFFMMb@j--T7NJexO39~Ac|`VscN90XS>!h>q4f8{T5Vxz zeqmv$Q9dJkXh!~AY`y96%ca9kecLtY;hm^HeoYcv@4GSF-1|n-%%59Xfu0P%&&U^2 znklJ0`~maRvNq+jRbx+nm@G6@z!>)J-SIcd$I25oD#h~ZqmQwD(S5d7S@_D%smqg3 zVqcNt;@PVcjYlt7i;MO~{`Tu&ITWo-$s8(Hre?z&(aFlx72;86 zr+y@RZow7jK*e5d3_%uX$GX_cP_MJWh|w$CIzJW}uU~*$+atGsQ(4 zdSkxx%0i=zhBfQq&&K8AiKMJnL*UIx+R~lk7Gqx}C#`jEC>(m~d+se(R%ahBvwqZ+ zy@S1!S`V)$#=gA4+|il3Tz03fIQ8z8lkXtSDy6(EaM8yax~O631!>n@PR23YW4ih`MKtPqx^@1MO=&P}~mS(sWX z_fgNSq5Y9vW=vgSm;Z}o-v0ytk7KrYqs>$P1NTPXBLCj+|AU`q@XOYd3=ENG;1By( zm@)PZ&&!@lN1MkUzJp(phf8bC`S~;8>!tNqy0J(79ig)082!We@4NVc_wufJ4|#_T z;VimKA2cOxt;{v@#91jUN9TUtoNv}7pWnB(-y;4R(Kr4-^tC?D_yt2>hsRR?i{_Kt z*4A^cGk(F~Wh4LJ?K``$bm0x}PjhDj+LQfdsOJ@I7DkA_Gam)XKWO}V95ggvJvoB` zm_)@d7fOo9V*bF|d3{_K3U_xoA6n?@4cF;U>twUkw6lw&H6!0IoXNfT=1Y}7>}7u4 zU_PXkTt1qk0Kdb}Y3`7V`e-kg=_}!0pDp-zVF}A3lr=1C-`e}y4Iuuu_7?M>s^({@ zw~O{AZ+>y@rNS#UV*{d(yP=OtdFoo_NmdNd59*KY4ZU!n-%C#yCjw?d;}GN~#bl#yqa znnY3E%qO00lt(IOA1$6}lqKIs-t~TX_3X&XS;|Gn`WGZ2U2zcpvhHW!Dd#HXiN@5m zV|^O`hsjI5e+>N?dx#Z;XX}-Vl`8yDugrSREiyRHV%EtsKxSPu-Ywr!KorcXDziTG4vg zmn$XaJMdSNmCR(^XOzC=%PM)go1=gB*dqCIyS%%T_q~RX#C6WJ&S<>|e~|U=ok%92 zZ}h2m?#jy1b3a;%&Ry%Sb=Tfo`WKg_-(eNzH=XjG^&sTm)8V7iKS{a!QKL_ujgRHZ zOD7(~pMZa6TkGkFYn)YACZ8_%Cu`=-XGBA)BR^jTzQ_l3Kv&>21s`nZovi40Yks{Z zPf?iS+t3I0%(Y5=@}1)=fdGf;Q9VcKcyG z7CryMXe*09>EHj?Q=EJygJ8;Eaj7`IhQ(z0;TrV)wTV+x{B}v`^Eb&#?te}$%r7O) z`EA#_C*;3CLyeYBmQF)|hyQkIF=$@+E-^J{4)K1@>hEofH(ZJF#5-jgW<=|_$mEI$fl_Dv+=KDKmY6-_dx4~ z$!k-E%6mTc;%23*^1?es;%2*o-+Xhx`^`7=_1`$8{nTN1TmP~T;d6feaMxNl|E?|*)#JV5;x&MP?>Fm;* zKYVxTwXS$ad#Dtk_nUZ3&gzKiTgf^&}lpt2JAGw^xb7$Ad>O-;D$zWp&@zngx-4-uz@7HzZVrjQ`oh^Q~ z2dLZl=zZ5o#=#Hz1`|!s*nF#HSxsvX@P6~Yw9fhlb-i29 zg5$tmA2t8cC~aML{C3}iOZflH^Tnb~3H?NR-L%a;|EOlKhwdZS^)zz^98mU+(ZYiq zw4>`qx9I-XIvPvyAF7+5EFY}y&Ymus_8xQ}q;Fp-{x>!3H`|)&?*rVYx`nMq@Q-Tt zeH#C7tw((m_I;-P6YKhApMStD)<%~mg2>df@hhia*4}7MIc6)b+WYnQvA*nmjO_X& zj8;&y*ELer$F6riUkZ-x%IfyI?JsvrtTgY+ZQ}i^XxQciX-)6{-d8h|R_;SPJ68j{eq1eKq4-3K#gh z_BGCfw)Y?FJJzQ@&yj!E_T+@2f+!HRSjgBu=>9w3r+!V)md3>Uf^2Nr`0U#)Ow@<1 z(UkkL{;B`P;v?5BHPKtO5~!ZtZ`!7Pd!K5fyjS<%`99%e>TSKXv}D^Kqb1#^@z~zl zXDm$Adpml;=T=hfKGXZ+d~^7J`faceZOP@VQ*?A9!_-A6hCr82|opNQ`uI7>+HjJ^e$)gpI&A04PCTqwu?ADEj<_W;V;@J{~={l-|4%0{GQKlezE7t`c!0r8&H~|m8hbSdyb_lk+C@WOF_80ONAI=$5yjmO zj~x4)^&IM5v1RO_6TCmUA-F0R>*X{*I=$0)y`E^Z&{N=C5<}H`AMYprH>GEq5q;&J zGW-2BQdT5}kVD*05ASD$wm;BR-T(f`C4SfT)(*`8WQxrQpzQ15_xAk^(|Z=7CKW-& z6Mj(H(4rf_dWv;dZ5h4n`YEzcL9Fu;$m@eGB-v-1^v)w zeuLacgN8q#BF-3!eQ|_cX@{n&kJ@$RTErq|gX~tvwoAMi2Na4>@Mjj~V zHGk{8mDq)Dg*j6`1-cZs83+`9^#E?q*DTrgZ~z z=pCx+hW|`^hCi?N5TFJZb*pTi>?!q>Z2LeggP)0H7@*if@SMqbtf!Da;#wbs7J4AZ>bV;Q_1~lBtyN z{v@S;$-h-)I7|32qR#gr4^00pe+Rw2^yl{W9H^N>k7hsOOzeS(=V`A4zM@a@XD094 z`99`iWgO?4?f{B}d4eCP+P{@>BE8>pX^^NF@uqg3(qEi_Mz(6k%@JtLis^lJ3Z z_bkM(a7rhi+(K@?r?-cURiA_-P5)AUlYHHxFX=PzX{4l;&%IxkJR_?+8BTH+#NWM8 z3PteqHqn_qGwLtg-0eH9LxY$65Dru}B8Tx?NM!ulGW^!!yu1eZh^MNJ2-@q^H)_w( zla{Ab_==j*PRM`G6lYVZ@J+t;4KLWPQ>$bzkRi@|IF+$su2+TA4L84@U!b>8G3Ocf zNwh0}zTnBO<1|Zk*595a7G2c|*}5%%o&KkiT^GIh4VBh>FrQ!0`{(3IN8Y2S>y-a8tA*(x9=wded5oa zOF6fv7&pQFmi-c2_~%-F{Q>VZb_J(3*BfPjXV2QVoiS$zvf!`D0Kqd*gFc(;g`@r& zjp1x0>?$wV-EOz==IjV=9@>G%ZjaZOm054=jUO!RP+u&UkMlA1~#Ky#e+F)MM+6*%SwOk`^FiI`=di(0=cj!B)b7oNcJR024{$S?{1|`0_*3ll z#PE;CXX&kb$i3+dAoqoTqv0iQ_{)q5?#z3eaOb|*$p4gHasef@En*)mKt(S4H}IGI zrq7;Qq<*)a2TI{!Yr~vcrn=6zXhmR!C2lA;&uPm+t{m6zcQLByuTFQ&NAW|-=y3;r zedyU4cxRyR{l0;|eQ*1H9pe!<*Tw%n8hs-dFt)*0v-hLl&@#Lkdt_kM=jWruOqP`kW#<=bo@PdiQD3tE6u)C*CDF<&Zc1>EJJG z@5$PGecjM5BsB|n?mjFXoG+r!fr2Q-(#zaT#O@t3a~I|gVz?9rLfK159PEkDput72 zvXt&y)jVxL{S_Wh=O@4?Ka7XFkufgwx$c43>Vw16dhqbH3;kQ`f%}aWVfex1&WZUR zS~vJx%jY)yeep2-C`>Rzu7Yte!kKRTgT<46DGb|z~+adn({ zRlm1>(@XIKtW$ZrB_AbUj6MW@6PiznRTIhc)9ROU%Zp>ppp3Zjz3uA3y-~F=X3|>b6 znzp6!EPwF6YrPXXpWWzhC$pzSgPeio8~SsYIn_4!(rz%`Fi%l8d~f8l&3RQETu1(ttzAU_LPO8-hCd|hziQ-_llN|t)rh*a6QBBs z+%<*zXKomMzq*BQ$tdL=%14rKP)2xvt3kAI7~PLP_)kO|X|=;k63>ff3*9Azma>H{0~rhLstXNi?H^!8BZ;b1#9CFkF=iH*?(~RC22~@{r61{CM-Cs z&!QGOm3b%q=lKPdkCed+={k5w=lcvcHy+~pj2SOfxUmqh7>|D-rT;#oA9cQwvXQ*t zKbXvvqlwDA1O|4S&%;P>(DQ^=d%s5YdhhOy~%E5B1c#Yv-xkc_euVvwaXp$ zjVQ5$e~i8g^G@FkJBi7#HfFNA`4H5;+|bNW?(cF#$vz8TW|5Y@dRXtZ@L@h+v>4J3 zT^9V_{v7fb>E;`&8wi$fR`xwMQ1S7Bo#C9ihdDiIA1kFm3`puc@;KnP(Rb=sM!%Bb zoR;nGOOPKm$=go(z~AQj{&oCcEu^OGZy!IA=QpGugQD4QkrYQ?H_)$*Zc-P~fY_%xCXs^>P#q!l~!xZz{+xyBE&qGBirF}W{pIf4{6QNvp7Eu@s+5bqB_Swk(&mj_yS zqgHeIo?hnPRdDxX#+TCb2HKYAHGW^`%Wt~!lx+3K&S(7EfQwux4qn?R^7~1s=_2QD z%p*Tm1_M7F0Mhf$gRKXmp2A@A*XU!z@iS!5Lz5MY^d?qs2E3bmkehxmldla#{=wFd z_vWB)Us_9Jw)&{cG4T~XIc@{;!W#Ud;mY|k_+Y;4>t{q?!q4Dd!ApE13Cp+RxpUK; z=ogO7&Jp20hdbz1Sdtk_$iio+vJnl5+QI~z{DoFg z5x!Rl^ze1>{R#4$XSp9tm`rbe+zg)PT-sEcVejdR(LcE|&s31tvNx(gurC~(*uRzpXOKm;hRzZ6|TDbE(fxAuEp-q<$&EMGvx<~ zKP{gfuN2?>uPdS~**k;DO>gj3X?A43Fj?HJ1lI$}hZ$+4{OHCs{BZbo{fLA#xDl2l z53x6b!KOby)c1k+S$E&R#O_`Umh$F&^P6NZw3TAk zPl%p`FP}N0IZvJbtrxn%AsTLPbGZ3|p<^>XUo?Y0fqpajKal${5#}VhjfI!rJkP!7 zk*|^xEG4vxdkcB!%~&(s#e5#9r23Qt!al-k@XO%p0;hTNxphJFJ7l`S-cZHlf4y$$ zL)1Q0k^Mlt1L?Go6~8xU&MnLHJ~AJ29(IeI<3ZncrxllKL42t8@8e%T`=bRz3roVA z=9By;GL!k|#r0~i!0%c7!MB~qab$WRIuiN6H#~iWsO=*K*%TV1FOC}i%lELBx9RsLeeL$Qp0~S+wBqD+vsUYPv$yb>3hxeCi&OcIM!!|* z`A*L>R_dzXJjV_p3qAE*EBN?gS)ElzWc=T`gTPV#Tvx{hum&e0KjulYO7434ukZcO*H=GwUE|kUSzkGbqRV~e?XGiRjm;6}{h2@BAyTRr`%(92 z8SYfaq9ThCJ_>ZU%kyQuRR^6YRG6^dlBiO}8qu9&u1aX%Eg)otOcz(1NVXm!KT1pJ^?2>osU*9~oa@riBKUo$I$ zKa6!=4*MXAvrQt({n@Kpv$-V?RFiz>e*UWPWsBt+20`&Db5+F}tKHl0_X)})|I6)%TG@4IkL#RGNg<1>fgTd-w)XzRPq*ZyGObDuIMw?& zx8X#rGYs_m_VK3hGXE9#T7KUFz1sJBe)fL#??3!>3mRGb8lNP9P7BS~gGlwc8GAMp zS%@mx^U62*SHC3sG##(!f1&^1{RJ0{zO5B3a_j#-(F7iA>xFoS`>UK^75VjW ztN-u~Em&RjB~F`?|tg(R{dcAzuWFrx9TI)Z+*EpQY??)e56%~4j$TfN75V8E%_9jWoBqI!p~wkm<4+d7LrL*h&we(J@JE>IPaSCL z`XB+Oz)05MFlwUg`K{U7G7=^_SUqEa(gVW`4!$lxo0N_m}1U8*=w{ zb3N35Gk9aflZ(O`>(7<+vPy=~=W``h-2)oJrE)7Cun4Mvp7_s&}xrQT*+b#@381-@RjnLo{yP9N0jg*WmF`O zt*BA!!p1x3428BoT76FOWBDuD42QzKydU~8>&J0z$Q|n2>!tXy{2d3ilpjS8?q0^k z_0~vzw7%5rU&z&bBK~*-G-$_b@C^tVpT=M0dEnhc;r)L4yeJla8oHqo+WyJ=B7CRx z+W|kTKdk+LoHOgYxq{(G!i|Tto~t*oT5raOwX1tI50ab*AC%ddUSn^TNTe=o>j?u- zKX_W>1Kx4s2JX;x=wI=GtKbX#Lcc~HWb$pu7kzfXS9J>ho+Z4A*q{bJg6C4afPAd& zOFRhdQ^`S2wUad=e>}zVXRw!LT2oKQ%RDkL_0RRJZPGR+lV>6HT%$jy?EUF@b-((< zy3%H4h?2pt4G;OZOxZ+RSb1Un*U)zh3G3PR6b)kdP4WlNa8F^gpsV(JC;ptL_f#z> z+WcEOZ>Z4t++yKUq4v4j8uVo7*MXn#P8J?<7qKe|SA!V&0Q~4dDESS(;dkKaD_XS;PwrMU zBWpCA(4*NM>JPe_jeCP())%2xXdZq8`skOCSdJpmq2(Zy1TyrFgh&jvTYBROt1mVJ zhyL+{_laB#%9miqr~7S0Ci`9ImeTV!Ir;Y>@oFYM!~MJU3K?f7*A4uLqd}i`!w-VL z&xp{ujIK6RV?6JOB2#^J&Bzb#*z89C_7AOcw@SQeq=mH?kY`puW&AM%exl$Y_%iVY zCb|~iHu#viB45Pv}5?2oZ$BI2Yh zj~IN@XT6O*RwLua9?>0k^~%Tx(d+zXus6c{HP1Chm&vyvv&DY$6oS_8v*%SoQUU5JSwYM+MQd{dR@%wiPLURh=<;BQc}jO zJtq2c6%7$J%~bh^jMUC4FtBmBRb|C*v(&G}jt=GQZw@i&IvR*imXLUB#;7yT3e zx1^8!9Db)ds|AhmhUl06T=Pc$tziOo6IEwXJ69eP*?|!i}JR!-UN5d=STfe4d1 zk;k+?W!m3#$DA>CEoS2tzl*U|SG=aNR}T%X4mcDOuciDJWfQMOe~kQw0zGWS2K1W9 zeqaT_H~f4XeOV4`%a2_Ht3E%_kMbLg^0u?NvqYaGtM<7;Ui0mE*3Px{+v?|iuOaU! z1jcs{q<%f0zDL%Hi8Nf}AU>Da}ebRhq=*O~< zI_^*DKY<6dGxW(PE0tnVwx`y&t-UzJ?%)~!u6QO4>o2Ui9E#h)pJnuwDLv%^YAsbJn zr1&nQZ`=Hmy{|6nK^~$jGX4<-a(}*uV9mIow*_#|7JcbI;vd31IREunc!DDxC7&b# z7@xtIU7sh~Ik$g}GwIf7FO0fJf9rxj)&A$gnYO?RD^1-Hi9jA~XDG`4jqO6;J%c z?wFIzcTWy60~qlA#b7#LXf?-%9~mBdsH1;|;tjnd1Kl^f$+7E=En9_SK zUJn+6g(23zQ~XML0z;(VYq|ORKj8TJ*Mj+>x3=sRn}3Y<&3=-P;z$s5k^X6X;+JPw zamallIq3f@{H>o4{!OqWI9TRx6Mtdo9|~gqI2;J~wV>yQPPvhNN`z1GW@T)h6RHZS zesVX`e0M3nEAVqg@Pq%tEq%!I{J;^S7sD@i#-C;D`z^p_ z=Vgr0u{PKIVm`R(@%$+MD5IUV zn*nH4hQ5=*EAAUx6}=mHggrBx4Ov?{&m3;b^a~Q+@B{H)8%3KhEae~R3oHO|X#Btj zX4k6~XKH4W`J}Pei6>A#^YM6&WJo8DK3P3M62ww;?4Y4O6Rl+F4|>Jh#C&)L|6DTE zXRzr*Z_4Hql#t|L7YahZM9MEq6zr_GG*{TgYX6u{>lD0*lx`_!6!t++>je|1uibq6 zTR}tfTX<-C1MeK;RSb=_Ut99`Ab-KOERNJ(fHMXHzp44N%_o*!H~uCh_MOigez`)t z>F%lP!U*rX;MansjfJC2QF*MM#oHkNOvcC*{?104ag_Ru{M#F8{x;b@ii_AhPyfyb z*b{TU*O6~8eV@ns-XdQb)M|SudjkF7sC|An)*F=uIW`&|JT*L`*u39v{u9oF$i}1j zn;>B1NivB4$>#IIKCDB}xsP%WlXD#Y^7kQUhr+*`Io_C@opeOMR^Cc~13%zNpP3Ix zI}OFyiVOOD^eQ>WIpIL`PaMoO<`>swaX}x_;OB2Xlj?8Z;IF)KS{cS4Mm|~iBd^Ks zFL{NuB0{QVwEcL3Z8jo}@_ymb7WqQJmyLhA*+&lH^{AWZv4z36{N4@D7Sjyt6ZkHE z2l?6)|BibXzs=id6MUHbT3LJ(@`l-s(T$4({d<49=9u<1f7gr_|E8d8nzdrQL-ihGp4td!(b-mn& ztn~)z$;}Zm*hQ0%GaFtNM3C1ef0^(tjg5Z>jcxHwe+>QW4fbl!GYQ@sX+%ZT?Yj~n zk8OS_(|*0({;c6=A|RiHS9Zh5en4LMb#b%e zfsmf)gaP6YJLG9aG4+%d@P0=Yn)MdsgZIOUirqu zu2oM(5E0cplFzSSoXQ^?nUH^85N7uR*0AV3wDDbScnQDV!LE;1$4pi|b{75&Khx4L zf2Qn;$A2bitff50i?c{53|t z{dl1F{b1@E`Eb9M$l`TR`-y~y~H=g2MoCqxGQ+S87c&kbH1Dli`~(zayr zNxauabNtP*+#|7-MrJ;UwkYNCrW_?&l^om0qDP-PR_eHJ@*lxJ3xn78{s8^GfCO7G zvD1x#B$bcQs_50qH{~lb^bZ7(?__5x5hrXVz(-$&zJSS{>$UqXD0))Sc#OYMc}>ve zGrvKuvQko7>1 ztDN_QJ44o!*KohESt;j!>avgjXEyG3i3Q?+_xQhphaSs<-BeX~&nj!L)zm*u)B&r+ zL^x@_r_*F8X+`;;PURPRdbT~%A7|Ds)Q?uw%`xa&un>HBpGQ|%MU&Qm&HUUHsX3+tck`*dHn z-Z2-a=Z$!+!=Jd?%O0bAW4Q5!2KFev(tPpB0{;ENzy3?|Pj_a(UiFZ-`FIBBRBv&v zLN-8+s@*&KH2c!A143K&Q0d!UJ)(1*5~&Vp+-igCw`^>8!ovB zm`m$4=(}9$rylo{?x&g0$He*FWBdSpPCw(FB?@7-h^)k4GW(Z0&*4@G7F(myEV<>C zEs2kV)h91_NPCGJ>A>2aAAhp@)7^Hxr8hdf#+kR}k(O{GSZ>3o;CZ_f|K1<3ozAb! zuT*~Stjw$srKZ)7t^4n^x9*IO9m(aBk)mIiP0r>!)1SUOKKj{x*(N+`3yOj$8rgNdPwQ}59mc+`{i-`l@(D`&c_aWm-n!qe z$Y*tpPue7_t3C03R&ThwTZ$pf>S_&Nd%OSk{ag3fYi`xWx0u~;+uyog3tafl!dvqH z+pf`N?f2K+`|y2yHq4%{a$T_mopr@7+4?B(=Ui^*zT2)3I0Nne^SrT@x1M*yVic5Z zoow}eJN&!Ct^R%6wWro@-G9e;$#ka{x324)}Uc-LdLXR#*Q!uUB2s>aVonSzSM3R?f2f1y9y;+U?Z?GQiZy zvy@Vs-F>_Dz8~_wC(GrtGplD1vUNNDt?@q4 zy|B<%7`&nQNh=MpCcHB(@y6rO?A=PakitVf7=T+8|E}kMNZvi&Eu5%c zbMa2Q!OUT#ruolkEnvRuDE`mh@!!k)+d3TC+J%@59)+Q3`z2c!v~DGN@_?vrdfQZQ z#Y1x)yA!2JP5)!d9b0u{1^Ihc?e$acE_%1S&2L-qu zkMeiOK2q1APW!swAAw?LmsF4Pf5L42x6Mad&uYH(FEMEjU6FL>f?Qui+Qx7q-&m)< zwbvYPkI|;;^N}@8VfkjcVh{O5yW-g_0*jVSxCbpJq}y_HQA1i)k_c|4J+@DxljrIf zL9-`xN>GGO=V#7rD!%18;8X9lx=0#9I(W{=2D?vKhV2M*;*o?8zx8uVU&)-OEC9sA zw03xgdW}!yTw<((%R_~rad^>KmKd>p{z^klD!82JWo)=_5{CT^;Y+YpLh7$!K5dl-l~nquv9Ibr8msQ`FdYj^7886b66}O62Fq4 z7@2Syw@A^J&)sVO$L7yE<4(F?F)<1I)BPW!71MAu2B)j?PqTLoV@e$YV-8=XZrp?d~TJ?do{G;V!yY9Ab>}IC!f_6C{d{ zC9XYD#LE=I{cDAgamES%m$Ww5eSXMyvgr}n73u4p#7LwW){RII*LDm-2_Z`=(Ts3q7FG7I_R=KVT6Gb%1ac}MRXpLwf?#G(;&78(x zJHYkqd4s8XN8Rzcx3gXV=G3>IcMj-!M}1#s9Z%5#=Et4wA5nel{%WDtS=X-A&ijSG zj(UUj+(t*;P*&&j2jT&Zr`^6HuR7~Kd-Xc%)u54Iq@Kc$eVP6N$xoi=14Zp;?P%+| zpWSb-D^COX?Pw2Alit^z96sf%BqP;eG3$+@x!D7*_RRAGj$b{{BAmrL;^C8-J>vP% zVBv6q>$3yh11@!MaQ3j5-A^{@c-R}hu~la_TJ3~Co|N2y8GBtL$QJ_EpttI*0{I6H zZ#~bMtMniptrKwCsaA~I*Q2<>Ne z-W3lo>|e6=0cU^m1w3<#Pe@yEhJr%#^RcZ3thjt8`G>4PrggaQ^LV9)0$XRtJ$vW> z3woG74P_NhDGxGprO^H--n*t%D9WmyBZU1?^Gz4N;MBlWKR02S5~IFsjs>RO|y zq{XaXAG=soDNnI|vpE z&G_+Xt374F&!zF}wCx^uCpXM>V9x4VB8XY&+@DzZ>pUa%&&;&Zb@y245g|hFipTR6 z#RDsTQLw94k_t04JX#(3N4MZ*=|tn}ae7=}QJ_GNwtbBY6&0yJicin*L)XmyHRGM2 z?XCM|kLSv?YAo~KTu+(4r}#4Cm+#rw3+lhMQdrMt&QD1u!^!Y?Sedco?J;Lv8G67p z)E%M);ZI%*lN&rBCW3s(Tkn^3?BsMWhGN0A*uCii?5b2wgo@Yn`}c1FRjJ85%D+{Bkbn45Hs)#dZ29k zA9LN}D>&X;$x*lc>88ik3h^k=8$Sl$PgRy^u0ht3-16+o#JTzA{KxW9X86G-nv5%D z`9H;TXjco_PI`bM+Wku@%G5*Pt>-CieAC*bKiPp_BpEs;rEf67-F?T~_!KqmeBulJ zXnK>M7uc#0*(m9e^L2JICvLUd6Zgu$mG!4GVkta>C%z6=P@}Z{jQ2b7Bkl}qMqUtK zJXt?prUlO5v3onfjhR=ezdghNRdn?yQ+w@rb9K%N;Y(Ka{@F{K0aNrq3f4mW1hWe0a!Y45~@TWVORM`LSV}bd> zxuh8^$IUi8;I}o+lIX9&Q6&WatS|E{KZgHDfjRTht^OI_7XK1&KY4Ppn{tx-%?dYT z5ykOl3i0lhh!awhN|-$_YKLDOt@ot-QEZ0i+VSJZk#)$(8Pgx=iMB)^2A5hR6}D)v zjemJ^G>6UFcgTb4;YH8tR@!vR3(1!QH?r$?m*a^oesXjQfM@ArMDiKvAr&<~`+iGN zlDYfd9k^%tp5^zJhgXIT)nB;(68H`(Z%^$+9;Wi0-XbNcV_r*Lx+uQ~U|vT5~#Yu-y!`-_d$fjDHBKu7nEV?mG+H{(_BdL&Cqvuv%Xwpyed%QaYHc{e^#IA ziI3+4r9FBMc91cgztPbj^)ss*JjO4uT5MO$nhrf=RObDxpEkplXgOMz4ibM$Kf1>^ zpdayrn*&t3Bj9R`gbVjtF7+!NMmO!<(n({+-~ysrmg3ri|+20zP@gOaru*&iL)^*7@ zaY!bwt(PjRBR5PY$E=>&ksa{vuC%b{=E=Ss^hU@RsC7#}albnd91;D5q7cL1=r6`& z;t9X^OE}{4N~PUC`(~J-`KdiD?&9vrHh*D{$*V@BKhlhdA7ojXHtqf--eKD3E#epO z?Lh5i(OA|#eu*$qWFPrjn0?JG=azGvXT$v9|C4_4PWR+QFZf5))&v%g>;<#`Z1Nq0 z(KbC`4`6N1A_;8-53s50lfB;|@1P(3mUJi9UCv>A5gN=JNaIPGzO-$JzD?n=GkO}C zulT$}SlefMy=Yf)jXDwf<=p(C`7E9lXvWQIv#RlT(rcDKZ@Ii&dE>EV<%>*+nC&&% zb9QpH-9N?6DGnyQJ^y4D-@F`9j6GoWOArm#<@0SnZ=^JNi7h-O4dP055)E$bZam>O zYW$A-k(ai;EQ^ot*!+}0`}7K2n$q{vMxN!j_!|$Cjkdd8zP9zb05Gj zWG1X-^-Mn4_h;I~74;C^{NiuV2i zui1d&(N`(_k%z+Qq-*yt-5+EBwJIU=LlZyR13%Kk%2XQvi2jzgdXo9fZTvsk)?eAa zOJX6(kDQOrFD>`~#dg^jsl5=Af0Ddx@ZUAXtDd`tyw07wrfA=M5CqGWJ0%axE>_PF7ljqTx=h5H3r1$-aUEV zkL}@{c;`Xzspq?#=hjM%@)N)FieFWB=fUKAz03LKq!~)Ssn2bFco=<1K0B;sSt#9E z|2)nX$wP%3X(^-4?`iNjA#~DAeKh7n~-nmzoQ~0qCg1w^^vtiSkI15mKC>D!(?62! z{I9K#$+~Uw*a=?g{1fZ6VzAA+Q6V3U1dh*&r?Qflg45^TTlrsCmd>qP?Z^953bW(O zM%$>`netq`-TALP_xqo|bbGdw{p_c+@tJ5dydiJAmccXcmljW7+;cgr2kCm^o%CR| z9}pL9G`p8meub*>hd$VPF@--oR`3E&SMsxX$#X|nIFaw%`HY^N+(iF@g>s*b?j0zc zYc<0+Xf=zMgtpG3v$Q$X|7y5*IfDC3?BQP7g$mG z&EmjXo-A^C7g-UUdvhh9#SbDsC(d14{*Jvr$K6GD22YjxLyVdH!uI?{Gak-x3KfI? z8~j%>$oZe6ZQkSf_ZwOKpIU1!HXGUa=g5vGi*u;3@8bSw-^FwN-&oG(kR4@q(4IJTDTav!SnQ!fu5=(QIZnJJB)a&|pi z<=$%F-b4QAHS<^Rul2rrZ_y#%I>bZF$x6Fwf894q{GH8@pxLx~;*g@_E+h%Tf3*jb zQ{9fA;6fex039FNnG>GOS`xOhW zHM_p6vB0(10_vaU1i;79I-kAY-aRrSf02syp{tjw+0_pF-z{v}dlWw~*YS+#rSqOG zeC}|1Xjgt_*817mV2da*qS)Pz>>vGq_wde+@*n{DK(jT%O{T`F(*{?QQuU{D;hrpN*(VOVGk|8{fl(#GeqKDxK zqAk}e|Dj585w4e&V!2W-6^py;KU7?l!`-KHxwJ5ih(oZ^*x$K#1|M{4*_s($boc!@ z_uTV!&pB6}S93;NE6XGBcV*YW*JK0O1RpUTiRJm`8(J?c$X-ChUN0QujOdf3k7+kf~qwU;W>Xn8+RbXJ5Wr_AT5oQja$4Q}2s>r2bKV!``j#`)7oIs7pUz zaGLg4Wz7l;J~-!d6{Npn2Pu*IL}o{xPmvED*+yA(L<%;n$NBKflgRTcvX1QTOMih+ zqqPy`pCi_Fh4*;cX!{ZE`y##R`yxv;^OGeE@ubndG-9Dj3B4#4&|F31ZrX2|kB0pg zUj)1nL_(K6f3d#+FX-k#aFDF&2kE~<08Rk!ebGDP9ronRD1CC2^q&664D{0<8DVn7 zYqW>8un8}*-xaWA>%TC%IAxr{QaWOAF+ZJnwFasMsUQ63L}k{JqQg&sQAUyT%^SO~ zoHrraTthQE9-6^&-U^%jd3;Xy$22w(MM$`?ipL}#2Am-`xevcAVlylYC9z6pKGDzs z9O`W5B?+G9fARWd0W;Fxa|`?XS|O*Py4>; zJxJN3l>CugT$oAD@Tmzt5&v57@);y}umE{yl+#O0YzO{~KT~*MKG=^F>k;^==L7mI zeQSC*B7Z`==?|7etq(NX6Ml^bKjX`MSnVrlS$4cAZM3zhWUuLE|u;hIWk{JO(vdZ zSkgi>({FCdOyH%DwTNsBO?g?Lwp15flpO+PPh&j>A1urSGoQ`irN#BxVx=~~8>~;Q z{R;fW8aUF3XA$^`b$7-U`l5NL=A5htCEaK`sOj$$%9GhgI<|^pB@%k7|8b~{CH@8S zmaJ|r{>kao%_kcC5H6tg8?_#@F*{~wl1CN`j__OLCLVX3iK|Xg_$?4hy2*hgM^z_f zJqk^Dk!-zn{Bxx~p>e~(NdC;iAYQ~B&Wpj=Xv*sH&Jn73~Y^V&I5e*dgH#XZ*@GpFWyiO zj2EAqmHOB_KzCXxi_F(W4!-7n$yvj8Ao790OZwMY-(~G?z=N5vTt?(J`XjzgWH9GB z{k-@>t%GOL@x|Y$dEYSv9?YoKsNd;uc6(i!j{UmKeYmFJVY4iA?>T!L{gD#z;=6I5 z_T}oSHOmd}qsH^J>>{1)HcDd?gl<`N&<0v;$PIbujU#YYxakc$@6a5yx*bb3;#Esp>+$`^1brB zA-KXhq0Rb?CIp)A%WMMSlDsb?(Iwd*YSt+AcFs4;UTHVU&$^rUf#h0vW{llY#@XlZ zURhsYb4fmp_6)bU=OgVODfJ8XF#GHdH13Ok)c|pmKW;wXJDHixRC}wt}W zx#eYanV&XVA1Akm)tlX&m9ob?lFgEHz*gs@w@i&y*OU9Map;QU@pi4Z)~H|MqWH%( z%2sb?chEDnr_iXsz-meFu6CTz_vKU+ForWxn(u>O(QcYX9t?)-Yc$*;EGWs9>L5J zTRZeFr^+|x1IosXJd^FpHu~rHuA6W1oYWLUwO?$mM%^D~Xa67k8j3+?|Hk{4oH5}Q zyDzBcS$C3ypo{2SDbrTpQ)&A1k3B_wpS7mO)V1(0mW_R%^|&}A{PDgSeIEglC}nRz zkDnY`g?*g5(Mv3yy039Z@Ml){$1}R!-RT4Uy{tdvTVgK72Jls+H2r)}?HR9Uw)gej zuQ%W4tco3S;)Z(Ony_;5Yx0>vIp*X~{3y5_W0cYcVz)Q3qiBa-`BccQzI$^f%qHb@ z^o=>IWeY3csKZOR6mP=jp7J`pu}GDD%1O=^NmBL=a&wsBRy2*y`lyfngxK-TNqfO2 z3j7qi<`0uA%q(;El9ch6<9=mxW%a)3g3SvVL*x;4>Hl9NneddvKOk*jS3rlvb|R8X z)AAxZ^%I)Di1vpUIQAn9I$9pmQj)f5toMgg`aaT))GHcm)4xIQ?<82UYxPkj7p%!A z*OV`t`4+?lP@?D(@iLMT_7V2cxP11DfE3sNZ+YT@`~8&r*T0_*>5EA=tsomZ2sEiTMABPWyl27ColMhak0s1nu<1$4O&l(;MSaR}W&E_~lm zI@Zy3Jx_mS9S zKg=&31`-l4yt%x&e2O!g2FiwUKQbrf8cQA)dmZ+$RB#~kC_w+(5rcn>&&0;LzYzM9 zFC-|(UvT6)6CK9-tIF0FtS@BGym~k|98h0O@3_Y5ht0z(b^`nY|B#@~|Lb$XH^EXl zUxH|2;CaSNR+F{lN_`Tqok)%=XpW=*-Xng6t3GPH5Dm~C{pGCO&0(QD5FYkqe2fk& z0{xGCDy&Bm^I{f9vDg96#(mQm)BSboKJZIE5|6sT6L{ahwK*r(>01N2f!u~9@Xc-_ zzG#fuqkiKa(bt=x1itg1;1 zxfhwlFPol>XaM@D$N$K!QA3Rv{Mr7u@1+Qo`^zD&o6l@iE-;L}r z9Xt^)1aJQO&+>*p?`)0JrPgSn^q=ENr^EcpjrqRLQfS|wO%y+v(ecomiHRPaJ{-T` zP=Q4Ji(17cQBm4X{rJ4-T%ZhpJ}MR>bqzxQ@PAb61xN~wG#;N5>WLXA(r04_I zI#>cUR{R*PC*}-CXzRbCQqc)T|C3+H#k%_g)@oVXU37g?n=VW3Qd*9uuvjmjT76#s zh4P&44P`Gsy5@OGv26szv*$5*#a}2Vbq2u5^2S zlbt2no0LrZ`^w&hLuZ{y>ns-*%ljW&XZN4|{cFrua(Pme>+<4Tayx4hq8 z^r8CQFJ3e3WjI6&N{)nsld9~y{?IF%U$?J68(PLz>_dko+co_EYf164v9MW$P)Rvw zU1&LXu%2%Y?GPKPv5EZ*RemgOJgw~OoZ^XnT;AL7NQ{pg4R}+WzS~*-AK0_g^$oe3 zIn49vh>^2H&2A&vCMZL9>EE9^*qSn1KX?2SKKtKJ)5vt>NpwEsP#$-3hcq3pGFSYL|3XEd}ESf%1#`p?q%V)|*`?|0pl;Y|LlX zs|x%dspF+LeH2V*JRxx%R`-x^tyZFnam&P=NJ znV~jzjBsOgR2k3QHsYbO<}uzC4ri>{|CIe8_!ZVLm_U|$DxOB9KCz9$(??sbT7Db5 zZ(09kc(Pop5xF`BJmD)n!%VExFH9t9vA0`LCf%Q7G5d$mvsB#9_=oFRnIA5x{aBp! z%RcR?f7|0cTR&M#`mllX2GuWGmhi{se!Pk*LHFXH!Slr|m$W6idTG# zqxOLMsX>=5pZ-dH(;7a&kG-a0E_GjzuarMh_642-c{wlYf8B^IW(daU@g0lH4rM5U zRcg;2&q*R>)qfzO=i_B~0)JVH?+U(Fv@JPe=D;fYzaur5GPW5b#&A3=@mTb6t7>6* zei-^oY(w1+-7tXiLwyXcsDYhE+0fAK{q)){GFqb~eW#^hd6A z*3P={5jFoStEcQs**0vmo%opge9SV$V#6W+vU>Kfp)E14UeiFM^M2;5q!`BTopawWh7YXi&~G3^>OSr<5Pdt(1YGK@Kxwx9_-E<>VB||c(`m9{E_)n zJQDmD{0#-3vi`S6LVt4#H^|R#Qlls92l|mrabm-mrjtUmDN+7=&A#Ah%+W+i~o-A-kW?2l{>s z^!0c$M~}69rC?Gb|3Hb+u)b|`d;Pdc{#lXd6#eS`v;i;Se`ucD6^GAG>wN()`OLy) z%yt(Sgq}%!Is8~bK;#GP4}3Rl(bE6vl+}*(ajc$&-mdkZg5IvbujT{(6~h0ghRKJU zN{Y0jtW;=GK-8+tS0)KOK`~>o{!TQ1&+lJ90YmdrNhqvrfLI^SdQDDup1p>K>fWip-<*%QO> zK%q;DA9#6>{yGi*A^aC=#QJhla>eb?r>w|(Kughkp;yRnfs=8pYNi_2{+j;_CDt_1 z+<@AGso(*4P+pI(vYJG`QrtN_myw-IXYMI$#+=4~>^*H1U+|sX zsQCl>2RnkEU{Lytw1j+TzD$1T z9P_Eq(v_VY!6HrH$hC3Z3wxk(tLs5VW*`}gGzdRb>l^uPGIechGDRlQ5zcEFPAh#s zI*`nVf1OQ*c0lZg3&tnm-$rh8?k&B3gn~-6miV&@b(EUL9{QKJg%37A;z45-?Z~d$ z)%M!)a;}#B2mGP1F1T2hYJ`+ric*F(YoE0f?E}YMW@Jjk+fKCMZ>8{s^}>pIS15e8 zeC)hXl0reg<%Cr@FZ-27@!>jW>!^={57IZsFbAgXuZ*9draSt}F z5}Fzp^tauDzWB$^%ljh#NP9V2MBY<*0r9cS^z0v0@__VjIC{l-dAVW;zF|3b+ZRRt zRQSet8vGQ9b02NR4#5wk@ngsXrtgnCe78j3q#fzMJTLRpkf$lziGQ6$|GAaR3BC!$ zBp)XHwI*Y0();20tWTr_+VA6Y`a`@2)+@Q5z4E^Gp7n$0H1&agTCB($xg1M~sB^>b z_lXe681_bERF6-uhk~MaHK6Bbi!aB_hc9O-rbE$ikDJ-%derm>{k@5sPt1#4>4q!t zE>(}zj2~!yC}F?Vo}%{kWi5CCPT8=v{*zQy)B@$uD1jiR1E^gYqH`-MKQ(oe|jLs&XY4zF?xgyja)zCAj_%!B zD6*eI9#T17e(td+=7E=->*72UU3M;d)f(DaqGLzz#|MbEySVexP55_7Vv4qT=<85W zsHG?IZMqD+z!&hVxD9y}34)W?BpNv7wN1$kgRh3*ua@WKedMdUSsE{y^|sQEdJq1% z;bD}7DmNASG~ZShtY`v%+tY;L`?%^taf1!7U- ztGdhT&sYumuJH+okd5J|oZOgu_QvI0HFxPo1HOs&1oI7rr@yRE8 zvHo($-^wLqJPm%)kZ18`z21#o|NWl#dM;glFMP~l>OHd>*S0x(vO`(+Q4p~v#t+;5 zEc?f8-JYUHjOLv1lXdG?)|U8DJvCqRe^9>=+D1oTXjF`j@qcUn2s+IBz{8qk1tHH2 zC$)U=>@TivBzs`kA95dQ%{Kq_=g1$|a!Q_&K5KoK`RUtw75P3R(h2g7P^SicQuHBj zI1|p{{)r&0PIzJFMN9E#taIvabdL6jS#b1zreKwl=UHV9`E^0yCm194FZhG2#;2sy zWA$OqhCeslgFdn zWKQNs=|7AI?HKyjh|BJ+;=xqQyaQ~Z?kRIc-Vk^Sy}6nH$?zWNjo=d$4)_GQK*6F*k_r{z(>p9X*Pp?5{sAkQX|2ZO<2VFI~@`vLi~m_OEUefX^C2Q62v zWIOqnhDAPv{-xsWBCW!s&OwjVdT6dM(cg)$#k$5?8|nLAw$c8l+r)o9F^t?HQDUnf z=_}gY^%3t_Jd#xF;g&UE4Q#)4oHK5Z-BQ>dSe0$&%eRJyhKJx6kW#E&^(+>!vH_WO zCJH@XkM~v2^md5L1iOQ7;vn(I7fwzqYbi5WYVg0vc$9O=@E}M*1$P9$jqOKU?%0WK zYBh}{zaLqRd?@Ivn%)_#041MhIf0`r`={WnmR&@KSy@lTVe8mj*;iR(!0^2p_xj$N z`;LRX;GE^NBa#lfquW6TdzG$v@Xhxvu-jDl&VGqAjl5Z{Rz==ysdK`Vvezj4fi5@}j=zIgxi2leUN zB`CG`&iI@$IbIkr#@`v36I&PYcHw^K!}x-6f%V7w4Bgt(ZF+?YzwKr}Ot07rrdl6~ zru;EXmQA6^+MXixfcM!=>Zn5z>+d~w2~1Mwvj{!NK@W0xwZ+bKcXY6NnbA%gO?=-^ zeD4Kl!h`<*YJK*2yPl0NyO(DEc1GrVdDaXjs)HVg5heeOAgVhgbrw68|*^M4G z{Rw|?T+W!82=TjA@zw_#@z$1OyWm3^`+>3;IL@JIzyI%p-PJB{;?vz3a`)kz*Tvqu zi&oLYfLKq8o@sh3)V_nfKu_)b@Mjl?F8xg42LwN+TzSv?@MaTU&*W#qi}`6^s9h)f zY(O9Buv%5?Me|SS|8QiE;)@^lziIG$I6M!-!cttY%g9r3)8ocwXOlC*c)woV;c>zc z1b40fgT(%I&x#%3+1h2O*QHs_U40{VC+2r#enP9USm; zg(>!Yb;K?bH|rVxoHp$VYbf4BR#Q0v4f#g&g}5WpyMWJbT~>o_wALH;)VhiaA16~% z=w$v)EkM2&dZ{TE`c@+zL)qu+Lc!?oC-?&1JedFR`bG0%n*Oog?c6rv&9ehphxluC zZqGsQ!?@~Qj6`2hzPggxP}UynTb@8(@hi@VfP1v3`Ni zz43vN8Gxb+{YYim|0uqU^p-ODcETb>xwgVyD8^+t6njrDV|KRw`9 z4qLMsH}e9$>16Mo-FWAp;tu%R)+^Rzy4qgJSF_pS67;hu6u*7pBoddakr7Mt(wq>Myy{ zUO^-<^s!O+eV>It$5x`S8Q(9niDS2gdx|gc*WjkR!YAR~%A+V4tbR4~4e+TMcmL-> z{~j~Vd8yBJUWLBJqS0LZ{C#ykq2Lhq*O}Zmb1w3s)%l5w{bZ)}o_S$Ge7ZZb-O*D- zyHtY<<_nR_j_hWiJ!$`+B9hzke>OXzZNhD!pt3&16I}Fb)&aM@bOJRJ`HS|{c~Z|5epJ3Vev$q33Evp+FLeq}&GuvP1bQDk*0ZzFtDDnl z@OK@(ZpQh$ZqLo0a&H+wAFJh7Yo@I#7NM+gH=!W#;}P@N`C+wtCNm0ut)Y)3^j*#W zMV=!c2z%sd_KGHm&Q6H*Ib(m4E^Q-s5AaiKYYjc}3Qp2l?uVmR-AsR`v%JH4!@)v3 zX%S-^7|s&}eW^dI@E`wH~(N_Da-@(H*n)&;Tdy)EktjC7`-0sfbw zna#3a(;59585sg;m!M;iD>O-Jh^P;Sk_H<;P>EI`^P^l zSGi<9Bo}itKfQV$`MQn$C&qI{;MtJ(rY~KoR(~hnsR#x|+f2!CmPLM4{Nl<})(0P5 z%)f8LKk2X5zb}$e=+YIjW!V*xMvqbd_o5W?nT@AMd+B8)jGQ6XFTsKK#PP-4TgSk> zzR))r!U^T_zG54Q_in?_SWT-mu_B2 zOY5C&dq3ZAd>CEKS8ogdbMdqJ0N!>9c~;`lg+uKpdw|d%)t=-sSF3x%<7}!@@276* z>Dl);UxK4NxSoZ7XzPnWr&`^Jf8-Enojy1DkJ0a4_*um@I^Xr)+P(SN8$bNxi~gmX z8_+kQn4uT%EgvKgt;C>+y!cFBt+(6V>_INhc9`G(#W!BP*hBti1%D)PA~vV}OK^Ja zJAN?v!-b3Ki>zR;(^VDQ zao+U~gdfh%Tp(VrDbJY5g9Ev$ZVzgJEn3-na10pM|TG%tzC2xYnyyiSt=Z zYp5Xe-?Tm;u@HuaFZ|5p|KlSKrh|W~r+oV*`y}%AOUF;d!j^EY6>VswHpLVZNz z5P9Q6$zOx^FY8a_ldQoRQ-xj0gS8LJ(}imKQbpetd=dNBu{hnxjy}PD(L}~X{*c-_ zto_vwU%{T7175xV0QxA>7W^jxJq#%uQtpkP8~ETA@aGlXo);XbVc+_GtKj}p6U6~*WcTG;jI*FErpb*^}%DrEa|)*PW4Z{ z=}d18c;2!~+lU7~b}L(AJwq?LZ#+e&mrL=5^55Rj@1uWLgg(4XCJ3Y}&fj{<`|#Gq z+{M>q{DPq(FGG*Qe&UqKlo4?LnAPvOYHnGBA04QD@X>pW7`x|7Jv001`-RevKE3dk zRcUz#8^vF=7tvslPc$_YeUtjGyyxikuj%7^{(BDDIXQPiNjs0dTrVTvEIZb0AuzIW z`9GBlwFmQCWXOJ=iGLp(Mj_6Z3uTQB%zx>JU_-T}xuutUYF_5!VqUnDeBe*h!|^fn zskokTVkBzGTTnngh{?(v@89rq%J^76SYGGPZzfEmY?Qc)*!1vb_e-h_MF4I^$^E1} za~v|rvya2oZzz9KC0F^li7_tmFKw3h2b2QsZ_3UK`XLC120ZT3ZhzNY+FSp8e~|Pa z%Z?(^aw?SgPOf?1R+hfi`tXzu`gMPz32VcNhbDKNoFkvTmm#i^(?t6Ezc82d);`}K zxPeLDmNcH49sB(GS;rN96OC=B{PwetpXiod0Ftcjoz~%#wCQhU}ci=hj;* zkBMBS``@rw(jOx;j(KRn8Q(WB&-d>P$69F;6Zk^P^ZaF=` z_DMFiLvyZoC?grG4mpN{?bJEsZO(klYh@?f-PbXH*qJ54@Oav_iJ00lGCF9F*oHHn z834Yt-M?ur^vayFXwcf=zQK9ES#yu#xw_j4e)RYAQlE@B;hl1Z_MMui4OMo%5$Enc zV}98&#Q!og!S^!$e~i8=_SzT?-Ld+tt{Z;@L!7ACcCP&N7JGF0hQUsfnO>eMmW?gw zQTBvwSl>>QEzWwH{yl0xZCe>&O@D^>y*mF*=gai}ZiQ{!^4-5egRuu~(|TMqh;sN> zUmhK^zhs-4$I;8B|1ZstIbUKfJ|lO~jQ7V5xn1TwdIlBsfE;!wk$AtI8S%bN|G&L& zWd7Uq7=v8>3BHK`Fy#_^HL^sbgu4#bYn--L{v!9$6xioe{?hE`;b3P1o$0mZ4ukWO%!hY8H^?$^VGWX z1NVs!r8W3B{bx7J=$zlPu6@ho}l`9{2^e%}E<`d9CxC6;%KLuSLDPy4x9 z{6Q``#7~{?Ry5Rww_h>ArR;-z$Ljy=mGaWO?DM3{@PBoY4K1*Obg<@mEJb#Sx}6l) zlKO6Sq%HU@=WUB*oYrMBSVz=mO{cFk>m$bvZKaF0kuv1}RL&beJuPp^CGX1#Zs3GS z6n^9WI0~}*w?uS+WwlzWJ}h!evKNwUO-lPBkFx-{Q1w(v*C*$}sWQ(*(o1rZ{qFr1 zHFDM8GXJmqLF`hDR+*CaRK1LMPwHUms=l6mHQS2INot&6&Ujrr_jK7A}a z^d$1hTais;?_)IV_($w2Tj$f0s=w3L^pa(l(nlyY{O{;r)aWnvKeAb}Cu=8=#vFA? zcFR(0vK{?MU*H%2w;moX&@{%Xt|i7S<874fB|DW){et;W8kfy{vlB0}Ke)sNKBP>W z`9)TUu@M=I?0&hNL84nDlN@??3Q8?w=PE{5TCReRr6=Z8ghz5L^Z2~%udhBY{|CHe zeu{D)F8Gs3mleF%;=8Zj;8a9;GJQh7&-vq3>q5$HbyV-jH@}pyv4W=0@)Y&T`MlDP zw5%s~JW`1zBA8MM=0jnV!Y8l_d{X$)Qm-rQXahfhGb35z!+4l)Rig#I0S9|hw-3Gu z6VmW~U3R3Ty);s>YLB-f+EwsY_}eT49eO9%Qk-(>zsvK*mOk5y;ZnA@#iMhRvtNGm_ z{+tTmV?Ez`y~rvDKLj6nL+FF79?{Ra3XAEj6|uu>cv=2^Fe6=TL)t}S>hDM_4!8r| zKh2z717G~~}y9_-#cVmaEa8 ztQW9K=-VRaor;%&^cT3Bk=b(H4!3B0l<@&g#^*bsL^5+eFVPWh*b}Z_ufi#)oogvd z3AJ|AeDW*vnf`d2e*P->=(9?MzREMeO7oY-_~@T5>-yyWB75pvTutvA>w|UDoL}In zR?V8S>WRiD*}spmVc5DEc@T_}_igt@KpnY3xzes3x=6z#pIaWK1jcMB_8@PtsTA&%1Iy?V9nk&R7qs zJ@83s)@kUK&}FqgHGSfJnFU!tJg@UPv1{2}f3%?SGXcMb-U>c(Hm?yoDJQk3^;-^7 z4S6A)MXW~M-foR=%)w$ZolM={rq*YZ-nB+;dcCgVH~mrkX)>B*d}-TE8atzTV1Ug` zeK*&e<~QKaTKF5SU@{{N?aX3Eyzbgf=K47|bH64T2@ckFk&md+e=O}v9%%3n#y6dw zZmY_uw?^=jV#}PuXqhqaK+oTHv5#Y|@!-GmyC(pC(qdW3BSzZbS^BxMKBbJ;kG%pv z-bdT-u;!;7zvIWdzN}WC&`)I-+ft!Ey?)hqtI%fU|0ncC(Mz-`E{Fa)$V1c8T5~;t zAIu)~#!*v9efC?;MZ7N4;kL4r zMS_VYt;yC*yW-Cp--Hjco>%J!Dy?=ZX(6px!jI{Bx+MLPC!wFK^kB7r$lDt^_2B>g zY-PtQDH*fC?~SQZ#m^MHG`*o+MUR9+3;m%i@B^~&Bjg?Uhf99~J4l5~S;e1_7x4F% z`M$#HOScQXoEJ<&zOn2tr+wCv^6wRXVa4eOyj4x?1$w@q-|&|0T3##&|I@7te%nye z7-}gJA@f%h3+WP`EzpnY=KJthC6Q_SpELa%b}jdQ?x_BYr?m}P-VWnl)K1QUHZiKV)MLg<;!L{pIXKH^HzCVdA^d$=N|QLi~hAHetn+ykiKPo zSX1dKyW(MOby1q@@jerN#D1Jal%*gK$S+oFM%oh$5&6)nD*Q*jZn=uQ>RC5i9!0`X zlK2udjdh;n;Zb%}{5m#0XL`4#;5~0!b>MFWZ2@KEk|zAO{aDQpbH{u^CDPNXe@QFJ zc=@JAwO?ipEap-}twU`C%nv)Du6Z{iikQ7ys83nwJ^XhOuLP6zul7F{^ILD)ue4)t zbl9_)z5w6C}e^34i;Q#}nF!+Es(jSlOc;(EOnP<*WABav^B*7j|$ z3H@tfhkenbY`{Mo>mjljXRsv@Sgg=Lp&v+_3O+zdF0 zC9TMs;{$Fpf0NcE{F?rXW(9o>(gFQ#&|Bya@1_5n&~L};m7S-g=w>26teFof>+vNQgA}mcuIT-m@mfw&`$I>0&BzlCxFNNXnvR=#R6NbQ6C>8KbuuG=qOWJG5Z_+>7g`TVLHT^|;O4WHE z_{kGZdf(s&7SC(>2d+SUCE>rUkAU%M{e<2y|4HE6)IZ4PxnBNn{hX)4C-MJWMAlAu z+dNsXVvk=eu?pLI47FdBbd&cZB#E}3Il&-l3HTc+R_>blO;~m2lS_|Jr24etSL^0q z-iNX;BA;$C+A~dmNA%yRmd*A?;LrY_S6x=$y;tau>{l33$t!i4d&gL>ZytI7*ZFvQr0e;f;wCaug4g9IKdhG)m{^%3TduzU3__Lai2>fg6I}P~L zV%pl240_?+X8!ar7;+87lc)-ba3g>-IP7O-U=FK5&!Bcg7=`_3kL{%6Sr0 z*r=ah@RMh3{9EH3zi2Enf8yVI&vYwZHRH?tvfhFve1^!|q3tF83jbN1$p7?TTH>Ub za)TC8Fa6nJ&)elKWhISaFZ{}<;^C|4v%>ra{)@cDO4Rx+qcIgegA?&t>rQGQE$|X8 zW^&224eTF3hg<0NQj&E7ezH!*AH1%9x1X2&yimA=aiH29;~o9sU5!O1o9?0J!26n#v3$-DUNbdeKH`(vdttk*hT#mG+rO_^Wu zqTYT$_3u+{-`M)=^k(MEXGcu*IaQy9ecS?)!brE?XlMP2UBmXo9@Uam@|wUef&Gk{ z!7t!T3)n}5E-HGkmY+C{{#D^WCK;D~FL|gMc+1tKM;?w!SBY9Qe^$Fdv{zK{R`aE> zN7bwJF_8zjt1$%msUlG#R>L1z$=~=%a$nY&6^H2~E%hy-j8|r)&bLIluwQu9W9=_g zyP*PJEoE>)FR&lx)3@8;m!0f4vc8a3I;LqKnC`1np?b7^ zvB}SnT{L`=SD{I^w>9Q8>0fN$rMW{(tlv+Iwk7K%68<6*A=nDF?wqenUisqgKtq%FYclWX zyH0bx(*EVvZ%LUWqQPH<5BS14WV`4l#~6A3IpI~yQ{b1;a?QpoU9W!5Q%1H19{Hu% z3H|U)e2w_YGp6w=Qs+(U6+5@|T_ukz_y|TTd(c~3a%%nrAJ1;RVPoKecH-ZnM&vf~VWEp|t|&j>ZXi}r`SqOeJ=A8OL@ z7EZZJFH+}K`4h!IBixz#y041-EBo%deetJZhkAA~-K5W~i^WMh+A`T5 zt>x#;x8LlK@Pk&OM76)W7u@AZfykQme?y{h>7UTs#`=f8ia*yK>umH^%dfV~w9h1y z6W5>}tldM^)}*K6CuN44<40GqQ#Vs>OS#lkY9IFPlJ;1<*VEC{eR+4d(Rt1>tK-@` zy|n4}O8-RLbCE`sKTu0OCYwl#bs*yv|9vH>%rk?4`QSeaF4BE9l9y)|CAK{^6P=V>OyylnW8M8Zt|hri`}$j zAOuRcNY;bA*j@47VZ5vI_cZpPCcl3}@q3rGowaf;pI~pk(Sq$m*>8j%EBP0Dkb_99 z{COga-Lk1Y%0Chq6qk@!@#91OApYQ8yS8}EDk^+f!9USTTk$fGt8-TK`yLDWFwc2n z4)Pnj(@#dO(NXA1dXozaUFls_FMwVm|7iIl<+UgD`bWOOhA43cyx+&ixOb)NWS6(M z&zqzkB%3IaNp{wuzm4^V{s0wEJBnVk?RvBBch0l*J-sr2g2i}4Qudj#3sG6Dh1<2h z86h9!v6@V_X3&3jw#?f*W43|qsV(oU!B@1x9_G7gA7bVs`0K{rQC6(87(lPB9uEu= zNlVMu-~;w@G!>_K4;ty5*gYvw5;?DK$oDp7j}RXU>`$z>bkH0>`$gO%6AU^l8OyEu zwAicmeVOTZR``Dre#+dypTed6*3}j$4)@orckoH`~_zy83N-72a zfFo-P_}aNGIq0X7Zfx&fCS|1k?dKcq-(CVM#DXW|70kXL*}m;;m;DscWRpt%>3j0y z6?}zT3&p@ca9ut+Wj{1Tgn)M543+>>ThM7Qf}ZMCGcaVEO;;cLS}0Xze7Gk zcM*Jbc;5LP`yKWP@dvIKw<0~EFE!R1{GAmAeeo6ldkgxH9lF&|8Na{rmmd)+hrH8S zazs8VD*i)nQrIVyyodc3c{CtDFZ#6hAX57!k8M?2qx4zkTho{I_qBY~9WM-cZ-{0t z;}J^=&qKQ4ziae);u65t27gYA6;iDS;DbDX{*xw3o}gT>+wU0v&Gp@3*LWBHe%`BY zr6avq@$wzJcFX#4R{4#tPxJ`()6n3yi2RDa;Z=FQ>STA99)!0(k8Q!*o$nZOr+yE5 z4YuL0e>e8r?wMUPYv_yNPO`t_qzm?BDvb79Ki^`tW0}ypj0V-$Pz$ zg?_?sAM5?rojlgMo89^S`DXkA_A8~4EBrv#fu85>=eDT)yLb~7c0IQ@f6#{6m))}a zu6tqeW@pW*WUADMwYEE0tF3LkM~1=SLH3}Ec{T%U)*ter^yIhRsAI% zAr9EJC~RT03V+?D%Ru&W+7SLM{`b(wvUdai3^ohQkA&1^XMeSy{QF z@8ReBFU60n;_oE-vRI2`zW{wYo!wSqzEnH{_OI*MKV-c^?`SVCr>M~%18D@`p?d|Q zK&?Fm@E^L+azx~N^xN!e{8j&GPuRa-^*6NUm3%&c{nHS!a6{1iTE(TSG08pdZXoa_GxAV+9~!%@xSqk-dXQ_@5c+}?y~o8cf~QqW4XgxzU4uIy79-A z`4jy^@S-&mTN4^|W+`BQn=BRRTWDKO8F{SIxuYiuKTCJqaI=f!U0H{G`LwR>QP4*$ zKuNfxiZ{5IcFnGZOal8>fA>{4xR((t9rh?S&sG-sm!858ME+zwtNn<@G(FQEtoQKo z_1?hq9S+KymcSQ%A6Y~2iS-G-Df-gT_wV0Q^xtEz&ICTz!n?gUos*2$W1UWQrSF(~ zlHGsj)WBC?@Ox3|^KDt-&+ZPlx^TU>zk?*+XsJ+wly%?2eo9s|_y_dRnf_j1K}j<2{o%k18C(u)7yA|ELqq9|RFdik3{do`=J70M*ky?6SKP%#c25idE9 z(*qXNerb1P2hjD5(0ffkHGk+zFLGEk@^q;9L%|XL5bVnI#7%wRpFj4}T{pW{{QK|T z@=l6H+=5o&S@o?bZ{@ed_F2JSp#bbxqA{ioS&tp*-kZO1yRUk$c3;=>mXlfZ+;Q(Z zQBkaa@mQ`8biU&FPrf3yO&d>un2*rMCO?P=SciewS6Y@Ctyo=8A+MfVk*9+ec0Jp& zihhDiLVuLM+5_Ro4z^AFv7_U4;svE&AT5eEbE_*; zzb0~J#+TWa`PTC5o~q}Nk7j)Q+S$x0YbbN-AJlsO)GbFlyKi$SQeNnRSZeRfXs|Dd zy+X+=ABz>OJqtXrBe@~=jcFv#8t{m{%r0+f9MA0Qd&c2E=;!d$0DUz^etAG%)AO(C zgX}i|ekg)ByHLdbT=K^I;r5)8m>G{RSpA$K0X&OvZkOYM+?IIDH&@{+{C7*=3O|UWj@_-A?S_0VArpo z$v5SX`D*VgUHLBj|8;!9yjnNnslF;dbvQk&Pr(N{p$aOMcoHkiy7h(M_qZR9kC$IC z$K!Bj9GjEOiEBv> zlQR{1-y)J?mfuo_^J8_qz~W0!{;Vf_@|KQwSg3WDor0HsR>wQkI9VK-S>$D*Z{0Vb zzp-2Pvc2#N;Rx(cM5%B~7I{>cUHIjY{Y6Xo=yCFz42mm3RsClM?!gqqLP$_pOCe*C)GXyzlC0DzPuCJUj;Le|%;A2Tq|W z51?;Uww!FQAnla9KX%`}Kh@!OU*D_NpX_(sB@%)8{79%RdfWUzzt(-5k==Zdejv5q z&eVEl;?IEg%)ZZnrkbJOvMzw!SvqKWu^TMnr0-1a!{e9Jz-Aruo9Ex}k@?W^7c2I& zkl7VUs(wd(vwz;y=PlXYY0Xn#zl=F@yXv017h0G41RT8uf62q2;B*o%(Q*sy+SWy8;UIQ4E}7tkl6=c2JXMg@2k5-eg{*#-id&zSK9lD!gt~+?s?s} zx^jD8qqfA8i#;><7v(pT@QV{sXndtU$0szuBKms)N-y&7Job07Fqi3(wfI`USl3uyQO`f9(YTvvq%M5p)Gj$ z%&u+UGxkPJe2o;o?kRa~Zo0SJ)xTKV`)Ovjx28wmJ$qkCQ%_da4 z-aFe<)703RM1HBd`6nZypwx=`{3qyN%q;l7ll?dIuE=#$-n)ViJ)6CQzr70Pmv~1- zW1?@*iypr>?_P#Z@%j9+my{=0;fdvgIDYo5c6Qgi$>rIup6=OHJ8%@6p-O+vPemulONLfn8tr-~x~3!L@`xzZky%T=ws*nE&KFh&W0H zU^Kg5G14Af?p83R>ya2^U7zHbOp@~&6TY=yvQU%B27`Dpl+)$NsDt;dAB)xpW(|}I zC6jjWBkH$<1LRkjs>*%x?8jd)zhG|UzLX1oPz>T1%_F5im8n5|%1pe|DHlX1Xq4lU zRzU22k@@{#7MNSoqH3?d|CnX&lwYEX0+A2oRp=FOsQR1|ucHwb``NJr-b0LMLaOY44QTm9 zQHl?s-RQqnnktEWZX>Vt%zpja*Q*~gUiQHJfnqT}qvr!?0wd}ZeU!)=W^;L3`os8$ zGLteoC}naTaKAa5XE;6MNMrtqYyrNry8k>qKE0`bvl`EMHK4VOZ*XFyo`0zg6_fe( zugwOAs$bq8=8)L&Ai?+tImxJJ1-=q5y_+)_q(7XGQBCu9n*MMeH`hd!_!l(L5oTz_ z0^0-Pc_e+sPW2s)2gLK>0+sAvR^#hOp7Qt$hiB72BN*p>b@uB{^&OFcgOfl8t)ZPI zHX_|<5c@Ika0~@+YE$zwv6Fk&;b=KXsQVM#ckw2n#_F*29yYu@TfDY`I3mNj>!h3! z?vDh2t;TE7{y?KXt17m9iGXG97~gl8Pwo2`*V*O801nnWMh{zMXXT8Yp>S!#QcNr8@_{FxFNa3c>tS|gUR*T-3kTCZ+@?z z3>nv*l2=-UzVdv$fp`VZv@r&`dzk%^WUxg3{MH4Le~87I{=%MrkM(``<^SD#=#~q= zPvn+wZFV;=4!L@C594$B-+%6f&;G)IS`xzujTFvc_yPy3yfbTC@V{)%B58SP2tV>Y z{Km5XPyJpv9=U-;iUk9pW2rCn!qA*8_3#|ehv|%)Ic(07fz8b5{4~UqG7@>-G&AAR z%wT5F{6@%k2JI*$>NV5PZ$H1PTyrxM^7opVk@l=?%x+r24$6hB+@Da-Eng=RFT?pp z;YenL=bdn(R<0S1_%_*DWH-Wpu$(X+PLlCO$gY0~ok{Xfw`IN3L&l?5_wT>@S(2nT z-W*nwVjo;DSpp??bj&RohmB$5T)c!m7StFW_s;^eQ{zLSVH!K4Irv@CDfY!DOTc4? zH3vT|7K-_}P=@;^M@GL4F`w{*@h^u2A122~J&A7gjq&ji`GX8AWZ0DqZ{u!A0$s`m z<+Q&%Zc?_AXGU!)`PR4-8pgM&Z^ZvLe@TyjTi#DBUvb51$SNV8(HKmin@;yYXG^oh zQyPDoe39q>y?>PVm#-Vfzl#3H{NX%j0~OCiLxFiVd;Y80!H@Ihuigss6E`P*>c2Yi zaV|Sl&b{_;ZjR&yUzLX^QUqt8%nN=ItDD7!l}z7=nPOXFw0=lO3no{z=nywB;18utwZoXAP`ao{lThw)?w+FT#BUE0?fvN#tm z@tx$#^N%{5ht~(xRsH(?$-e4JnOSq3zP^>RJYVi3et)GuG54L7`+{h3-xTdz8)9yS z&gApxi5o1P|3YV@BL~LX_Tc=hW&8xZKKAca{ZMtMOnqzGQxIw1Z}xX`<$XrtM19j8 z1{S3_VMIXC%|HK&z=Koi@we(ocE){X+r+Z=FK>UZdGwy(5O<`iM4)K~AYh^v5pEoM8g`#onleJyh-)? zQS0#f6FeW=#)de`c0?Wd=b86Le|L1wb$ER>b>B%6Pt*~2B%VLT_~O+5L>T>qJb3Z* zGb`i8#^A=!tNs9Qqsw<+`r^qaUm{-tG*Vyqxfh$|0b>BVEafv%Kw$M5=SAm5PTuBh z6ix!uK;csQpZs5QKZUbqxzM2u=Z(%Hc*ykx*|nO_ z>$iBH2c$i@zC`=-1U+i}D+J`@BfmQ`IbMCZoUnhv0cj-%`>I!$yh1XvLvu;TboaYg zcgow%nx#+DKSPa2w{Rx@ox2Y{56wnej$TY2Ne0O?NwPApys!KBKn-+I5=g!ni+D#m zdLI*|GZ+uTOUC%{e!XDPIx;QrMW0X>IdUfo6_EZu9F2+w!8Ph1jn>zmFr>Z$kYVUt z=nDW~)Hxc5L?aJ+W1glaQY$qkHY5zFN1@2+?9LG&3Ov`2XR-kQZ@y0r(U_;R&^Wwp z7>^onL>hk53xVCC2=MovzB**cb-F%OlJf^gCqp!yupFKrofLdxNvVv<^1c53hiT0~ zK}VT5D_4OC^u~CK2s>n&T>m_^0hfgGfHx%`W8->w2)s5#XOb^At~0#P{7wdPsb6FC zkgR-(QT8+L{&x5kSq_5Ii>A!znMH+faxh8h#o&lra0GtLQ#4e4sTx+tyvOH7!)Sg( zqv7YxeACi8MEkMAy!4$bW`4 zbWSre1>bn6I8=OzGxH4aan%1xtTF!dy7@;>wgi9Gd?a5=4&EN~1S14H^^ESJtnhC# zoE%IJra2yMP5V;!@8Zi^`01x*E;MyW7)DvEFH-L&n#tU)Eb-%-SFV)kHR0X zuOIlW9gm^bM;(NelNMk_kZ1B|jF!S86ks}>9F6} z^4L57!t+oGP8SCspl|Eo3I160H#ijxhJ)FVSsN`Yd^18;jKDyjXR0}fdf$-wKOJ*$ zOKC89YB4lqyo!Dqf>YxOq}B-AiIRB}Nx&)ii~R(h(mWcC0zbHtzj`Ji@B5=gW`h&L zh89j$)cQ!gn0WCNpTwC{oUWk8c{FN_cMbdmQ|S-z5PBI7gp*@XxmA3S+}3iwD(jbv zHspL&@Ne|W(W{KW3vZr&6!=xf(t~YBtv@_4m>VM_t;Qaqjv_%x|4$`e3PLa@ERIgA z{&E`IQ0b*3gY%!bU_>qnEJ58S8M^sfXBEJ}WnQBSDDkaNl#Qu#`F4sN5{ z)A^uR^RI76Zg^~L|Df}gxj|>FfAC~uetcFmYwon7->2iD1gn!1GebkI?`X*Q!}_2( z7>;EOXM;1w`XA(kI^k1m`XhNSjNch=WBmsxhN7@}p|8Lj zIyZ#wb;>;o1=8_*f-%BRSKHJ475U)NJ8w++f8$U2Q{$h9^v@l0hdja1(@DgAX5{pF z!LFm{Pw}ncv6>&dfzOJf9gRl~3$3ny+%0uxF^j))_|3=XM6_vsuWjG-pE%)WSNmh2 zc_;g^B(iEW{TMX{slLAuiYAVI#D&~4-r{L+c_@78$kF<#5P11_<4WScCZ~+=U0J9K zzW)Ym!P{4`7+Al3ZUsJSMUEwL^q$n2)f7h*`c@h@yB7w zdNfAv4~yfmS$eE=Z{7MA-C5VK<~s^GLyd#+Fh}qU=+)_kFbuQ8V@83V;WOSz+5!6pQ*M|C-IVh`x^>S3!kAF8RbKYLL_;&Og)KihK!sHNjj73Av1{3-&{Ky}y z%Ze8L331*C0?*529^?On-Zbbht3L!m*TReOkPl7vXb;VHxApwwK+bsV zq508Z$Qv|~M+QP)cmujcT*!vG{L~*kM*Y_5Plob;m>(*QnL`UJ^H&P%LN7#HH<^QG zepKvF%74er41T>I51zICkr~sge|3~A^{LtBJXddncL&#uzs{chExudsab;){I58nsvaWcQ7HF`_l zr6G4Lnc&>$yVuLs+wWE?Z&&AWkkIXGY^VK|GV_rbWLIOHt(R&laX+Jgg7o zSEw8PHmrm-Rv>W;0UAdOW89}c-~c|=!rJLI^jt%pOk76CclW)~#DL~Zh-5oKKGC)C zRpV>WpQG%ToIXEDJ}~s33cRR%G#;~$F3S9jG8;gI)kA;kg;LP?Bx)OwM^@p39EQ9^ zIWO|2V8dE|(_wVq%IAbK>yPA5DioUin?T2uzic2U+1=|E&X25|eEa5|^r}9TLP|WG zOq3F(yPr;#D?8u5UCGz;;4l37EAde2s0SZ3jJ}7i&IeQ8IrHtfGH|DAWD~hD4o6~! zN-_@VpY&_U9lQ*DFDv|$`Hn-dV>GkDdKfD3c2r415jg8u=*hhQH=L~WcJ%%H!fm0a z^OKe8RHafq=iIS4$<-W&R z3+M88UVAWK-Q%;I0DYxW{i~l;s%3hT2sdQ!00Da^8<%M@2 ziW3ROGc}YSnmQE^%|L*W0#V}BH32-OhjPj3CLLzuhA;4vf6OnJz9-+JbFKZ$26dj- z>V4DD=RO1>IlD71^RYTYxkp{|8}LrpfNm`HN_!IDEhnDHN9vXqq(=FyzHJzyqpYn@ z$<9!`=Ch)+i~J+y-I*@xlQR2D(5V>jLAP{R>Cd`O8HtOuAy)M9D4p?!j=Z_PcJ4c? z`T7slrA}0PcJK@2Qy=lpTpszB_J=#8eBy{oi1q$eJU%t^fA;)c&(x4*VH}J9ZpxU7 zUIs*qi{=tAGHYO4Fsd%H*xBxQ-S>++uWx`??muxWM~UD2*&U$X0V7xJ%A zf4L^$0N9)5ee9;{`Fz)RjjXiSmGf@)y+XaO3>a>~Lpl@V4*Pw9A=ddUUMZ2hNBzE7 zUAvN9$>-HK480(GkL*tsw@V{xa9Y954)NxX$r?qob10BCiGsOh9BCZ z(4w%Wxf1X$4dsxZbEn?=|7d&v*f_2$-?P{*%O%<)RX2+!ljTUoR#9v*S@Vaa2}vX#vLv*@IDweVQ>co*9d|^Ffamv zPZMY!v=0wiK@c8-2SZ>y!aT#6HTbeh(x%(3{hWKdn@t6n#s0Bw*m9}6s_s4a{P>=8 z@BQA%i1?>@@TatOjz8x!1~pIWYU%FE2=DCjwwUna!Q|ov(8&*0CqDu`fW^T);4eXu z__qjAgzF|7^m04o{Mon^u2%BAvKXGvhHLCLP?%_ihL;aaw^`S&q%mY zKEemr?+&>Zcwash-%7WK9gLsIT0Ugsd;S6Mauhx0dc>wi36FpwCnQ@Gye!xgIs*N4 zwZA^-3kGGssQL&$U0-pqh&^r8_%r(LA={Gk*Yj4s!oTf#*2n4o<|_rO*uK;uY{;oXjgHg6(*rz5P$kCWGfme`>!^*XpNoWL|X7 zpBl1Wj`gn0pV`dL4;H9BsQpv2u&vKMf~K-Eg8%?l$CG3Xzf(_=64+sT=T z9iVglkAB{ey=Bj0(M_Ts%)?aK9;r)OA)bWVUFEr*>+ODr(mk2s5dOWs@}OF8ESkjr z-Ev=cFe|dI$@^esuzH1l!r#~b;*n+5ekw#|l(5el;*B-y(c@q3Uv<0&UF~_>-4~gU z{o|Qm3m)GlzuNm`zo{M%rE%~9$!Ye3dHKDzOLk_%lvCAb*}rJ@+rx~Cl81pjva0>$ z7yONjeP#PAgR-A(Lw+HAG3dL}CGJuDa{Y1a4T1A1RyZ%c{oM|+4}4-(pTu6WqW!Gr z;_v!5hU9&GWWA}JCNKJ<+AICVnh)KmwO60N$$6aH z;VUxU$U%102!BQ&D^s@KUz3;Y1E}k>v|U!73!lf10qm9aqkQE1mc-${A(!uco?(~i zSzmTIkM}5{BfxKq+2KDf(SND`rRk5&_zOQ>)gGheLC!rzlvsv(KI1j4`RmrB2K!^m z{b;n{4XLZv&s!F2Vn-MJ0mZ&|26-Q*hz_cGunf{`}xV z=eqW%U#XxU)erjb_RS2==xgCGjK|8YL4~IhiJlezhr2*}4JMe&tf3QD2 zloo_060QArOW&lwL#%hypQ=68{2Bh&Hk7}hy=YL#cwg>s9^Q{U>imgn{LlyXBg)#Y z^gw#pt=Wfok9~!%5Pt{%t>xAH9rJsFG2Bh&o8#rv9_^>cYW=g>Z=&Dmhl(FH|B*%8 zMBiXf?aLlfSbDzvpu5xVxBe0BRQ<;y;NP?k?HJn7>-po>7YW&Eb(;D5>Uf6H#8Bd} zC9^|ft+4o{IYUp}p88Z+LDtSvfo<{^`xJepg~Xrbz75q?nN&K`qr=7Em zl_wDWlpct_(;u_`e)c={8H4hz?AKQOf_=u3ip1af*`110scROrs6LzQ{)%%P#mll^ zTKfz39QNPAKdCFtKiKaKIropJ-j5957VE!7KiEYMs+0e=tm}xPy)SEk)Eb+{`<1^| z`ltQj;L4!__QOA#PqFH6^)>u;*jGWduM#yjUGUD=ht8y^)7}}2#a`Sc_7`!Rd}bx` z?S((f%J`#jHGlkP$VdEXUikX@onfXnw14C&E}z zLBj?F-^qCKk^QIx+J5T#F8);e2RX|+iq+hBRP zs`tG#xU9zKvFJuMzfgEuPj*ZZk0d^^15w#ymhoKb zTS7j*eAxe8~)PfNj+K#b5i}VMo_l9)IZI zhl4*AEZ&`W^QAS9D#Gbyu^#dFtoXiDw?DmqDx&-q`aQ4D+a^24H;FyU`)lnHZ9`*a zf5E`wF!Pf#f2r#`QsGhU7yrf?G}v1R9%5Y*doqgd3!QI&e?M&vk&#iyFZ7-f4$AnH z{)EEQjDEHMk{{La7WozOHK^x`cO$<+GOimnMLT$2)xTNnpQF%Abx!08r+~=Ajk46* zF7%tj5$&CLK5td>&2slUnlJM(`KU{cL)PGy20H)F{n_c2Ci3Raax>^>oqbdLEf(7@ z$fwM|1OH|C@72@sWwIYu$rA%7R*!xew}V0Z5cF|);0NrVWc<}=;_vW3D!-(a zdi=>3X2EZAjR)GatIxyQ#>%N!!Ghe z|KwAX4^OZ2bz*;6^*;Wl%&4HBzV@!fN9?38kA6n%NZZHJ=Fgj>pZ50*vy>TsX2t^9 zFO0tmYVt>)>5s~9kbv?xslL3#1K9^0v%cWJ1J;pJ)WG_QnZlRZS3zIlui)eA`;RQC z_tXC`Y-fq~Es>9evU1n*neFsh|BkYxl$A91|_wy$9o5Hox=L;UJ@vX}05z%4!R^p-U z;lEt*FS7fB^$)TJLbaFg6<^xGChgVwp!iB@ANU0Rkl&z>#E-tW2l3}>e9X$-m^ok$ z-`%^u!*9y&@~O2^eQocn`LCT-oS>e^Q}Hhv&sJL`^1&bQ4fgp?9Up!q?WIpyeos75 z`Y8FH;zu2F{zQCVRuH4gk4r<`&4&zz{fM6USIHG?{IQbnD116vtuGiI@_TrtDTJ6Z83bL^L8U(}JShkO|y{w749!+~&UQt8tb z%?H|d>&PRj{i9X?VqzZ(t!cbQeuclS)@O*^^#4A-&{u5Hx2O|sXMfT_|Mbu<^}MS8 z94s9&ELIvMSc(1BLLwc$@J5#J`3F48xGVi+d=$RpzkTKr#H<;Z?q(!D%@k$5y}#lu z?~I>LP_VhG#?#RJo&&}aT7@=%`pYlb%LgStGphLq_*CKbjx9c>f#MPP)Oeo}_1Ldm zL>}~4>zm-);m9GuquHp5y~dS2q?NzD3jPeJUl~I(cQCT=stX@yXQI=X@!9=U+Tz1J zqw9OhU$rX#7tPx*(eCSC@MQFJiRTkJl>TUcEA1D&oo=};c!SX_?X$dMiRiHZ*o?3B zQ_xnY^^3fm*R1iuSNeXv%W|o|(BB$gXJ1gyza(GR{jc{=`%i=Y$aXQeIKAL4{MwGE zYyJj*NW2|{-*bzPbYS)`Y$adXSJQ9&6>rphs6*jlWFUN}y*K}xBYdZ?IO_MjQ^zy# z1pTFlia!M1dIrR$qRee5ui+v^P zZ@!EV_@$uyzwnc4yj=l5%_{pw-qGO8AeJ9ol=?xnegX!jexmh}XCg1b^P+3CjPaKC zNq)?C{Edo_sz3N);WrjO*MVS|^{u_^Fo;iYX1Z?;oO(H<+J^+i{|tGDJ*h{5*b0Z! z8F%qlZTm%Dv{Cj08WO+FhWRJ*MR~uLCo=6XAs_lD`(w-SMGhK=3|fPC*Zip(U)Akh zQPns3cdvki1&qm zmMALm1K;2PKx}?*Q%_NNL6{aR?7k+S{WHD?fl588b+d{eTw3JAPsOR__`e1|-u}mq ztZeTu`9w9ou)o(BXdhmuFXcV3ig8Mk4QJ#vH{W@!+pO_PVjneq!Y_;eyZ?Fdw0yeC zcQaql94^0_mi}WuVo%~fbbedahbq2MzW^V5eanL@3T@fZIrJs*jc{mA$*WplIsCgp z(1yZ?ia%D3H+V$rkJOKklpe{>DD8}SgFz<$ql6l7s&KOEEK1Emvqe|;_l9TH_|)xF z>YGJXpMx*eS?IU$&s*)+_`h2@wrQ1ulVkNf?Y75Hfn zHV^Np+Yj$i@rCi`o>G~Ab$v^(j@?)IqZj(9Hp}zH7uxP@DYKGUQTKxwg|BkJ7{(rC z$E)Oz+W+h4gC~eVeUTwD1y;LT-M2QKcsy==?|QZWTliY{|Erac@o#b3TbH-k%aEt> zm1J-4-9^`xKdUxfnpW<&FNKxP6e){hTU+tiGsEU{IKVar>fDdKYlpy;b|ABLfj>?-qaQ zK@DA*J+0>>@dAI2zmvbH z@td8h0 zm-r(XP)hK0NxcF8eRYe!^vnwRATzR~COfk1eJhnfwQp3#2jUg^iNEEKMc;L`%6!4H zzwya0JacKAfAFN1zvXZL4=<8!yuQ9){1I8+JDM*Ryjy=hc);ktjXc%+s`ysn*;@Qi z_OIp^?OEz8Wp*sj9Jwm?ARZcfC^G&&^(5FK+$G^l>#ocwf34;_&M1A`s+SUV`l+x- z4L<05IqxhEEDz?Z^J6L}afMmE=2RNH>`9cgbJkGSMps{ImQb^U$Y_;`_OG**0{Iv!W;U-$zCrjOhf z>?6#C$eU`fL~SoQTFE}ulyHaRArBbXh#D+ajADXQHS%6 zZuRdcf0OY_#ZvI$+{S;8Vs8cH6Q^EyS^Sy1#Sdn8-8cg^sW2kd_+(H2L}qJ*FX_vT zs6DiC*hc^0?}D#`^&UO;Y3-kd9}>P+*de#0(zj?%w{DAy#L-YNq77@N$ z`YZiMQj8BVSm(oBlOG8GBKoVoQ+Vu-;9t4s`*>9G(GFJ*A+2it51-EX_&iJSsp7wt z`IJUJ*@4yJRrUU=|2bG0R`a)w^ZoMt8vm=rJJCOB5&T>GX&<(r^g+)TNIkZJubBE5 z97)^9Tk&a_-k~qA!Af%X)eQ0;frZ8SVo}&wUJ-rtd43i?R`;;fORDxu{Jtsq8znf` zEkEYL7wviFGo(}Ork`ui-%A{TpXh%LG+$V}AbXI>m!943AMoGX<>T^xeV#;2{yclL z+CMM_^8JAM8W}J6jfAg>`ayNPw0|EeBX2Da74HTv4^J~YvjopHe9ri%|2RCU@iO{@ z&t$w8)$^!0C_Gyp&ZB=>&aYAY$NgU)4jTB&_40f4%Ns;j4Ib z6TFg8^-$mK*tahAO5`u|lX>aCaHy*Jq7T%32#g^${+m~Xw6cM3_sl|F{;)f%^)K`f z|4_{bW&Vq3NG%3`^OJ%1hgXxT8fsUop?mLQ-*tZD{>O-yg+_kkSMYW47K5a}?1w%UBYleJ*lAZO~EVNTM<6UvuoS*QSd~SZ@6-e zdZFNz`uGsvC7<^j^ywP?*(NXS&#

(uUOEICXsZF1fQ{O3B9x(!Ln+4jml*V%1*l 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

xI@2FScj_Zb;w{)sK{z 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 !d9C+j)j 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
v}U70g{$E_$$CV*91tV2ZIDda}Ps=s!BY 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:{:?}", 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 @@

-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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�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%0D`P|=8@u+UQ%=z7R+43L4Zl8#;T;K1r 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≤GWXA<}4NfYWI^m11sQ58*e$_lfk}0Xc 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

_(y_@sc** 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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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

YQnce&OUhf~QVW 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

%F8AUQpvn(l~~zzOy>1@b4Y}v#!Cyo zY|`n)@}x|6%fs`9(@Q|5scYt=A36eRb#Y1vHV#Y2d;@T-05}L9pxlFHY!c30w=7%# zp@>K^tNf_vI1-6O>CbRV^N-DgMZG>)R1sUr=g0fvRn_BD4LruJb_j%-&SCg9Y6iQc zGw8^~YprTkoO*eQyF^c%;K*6X$3TZz_$88KCwcNozm2VUYaaOq+;uye7+wp_q?pm>3zr z0M{U}T8B+z03@WI2hKlO&w?Y5RxczWnw--Tw*SU@Q}eW><4P(+c|55%KWLrPJT>vS zGW?G6c;fi{LKIV~Ov+KJ;*m7^fe7slgXGjba?%bRY>`Y-6wmY? zO&aMFH<`I;9?#QdQ*&gEjkh^ckSGBP$ZMCUX#|=;enDQ51?n%IEtz8+T1Gawd1YR1 z4%5G0D;7&6dYVpAQ^LdyQ)Z%aWTu-I@QpHkUxBSG#dn)dDv?SJdXrp`m}bh7B@D~T z;>QA?Jc=G>44~VH-5bzntVRKy9L;A@cP59*m%XgIy-;t6?@KBu1kYfDQzGM2JLhKS z_vs8()T(K&)V{cQO9VHgKwqBYJR4&mxFLQ98zWx#^vKp(=L3p!2f{^_HdMO2R;esB zg2&)A{9EKWCkK{NWiu(dYat}~5fb9>0iUbc*`B;;hMI^IVI2=B8TN~piV|635cJav zGLFi$es9s36cwN2P4xPX`d);uw8XDo;PR!JS!Nx*;rC9jRzqUSRP`hz#Xpg+Nran z?x<7^-xNPaIp!#|_c(<4ez%w-5Sir@m~+Nzz1@5hd%N7C*5TnWwoPi6`S=7#ksBj=O19Z(dn6McV!24c;_YvJ>gz1(b z(a4B4QC<};MKhG)r&Q=Eyn`cNjBlR5nB1oh&prq8wjDmB9Qe$QqD4YIBN{^#-D&|kB6Z~^A%$)(ELhcF7g&T?q0W283 z<@b;RBgl(!Ni;*2pw26md|?8m!J8-#fP0H3Wl&}>$GAO#!&%Jb<3sFXw8G$^&_e)! zv1deYQt}hY7NpllwgP+k2<>C@9z;H@Bw~djG5;$zK#wCk-k~HL`=C9eB%h-^d$ed# zfgxvl-q5i^s-|N+y}f_l;wzjuS&v7dTCgM`ai30~9}o#rd_=Fysde<` z-ZBm^IyIrB?yaAnpIBV~<}Ywx`E6Lh=;8iw8}$I0+C*lLurYfE{CyTP|LWgCXOh2P z`5x*z?|}QwZGv0a_Y+T*#P}Idqq3IVZ%(ZpO`cOW@P3@d+`)NYVk6m77^ran!299v zYq@Y|JbCA}zr$?r@samaPu}=^_&fXl|A)Evj*qg~{>Ptro@aN{d$J*Yvq?6Ekh0kn zNJv5rN$5TF-ive;q}inih=q$Nh#-8eZKKZ@R%=2tE z0YBf*_xJk!@gr=qd-lwkGiT16Idf*_JUU#bFRj4+l@Ey@vL&efg}G9Q#c!$fAe+ni zdJJbggXr1u(!2rqUcz=RYI^~XgllZPfwrs?ZTX0JcIdoypfhEnEt?45Rd34;;+e~8 zXLEeOZ%|vPbGsl0u1^#3mU$oJn{~g-G@rjcVi~K@k6>md4;G8~jLfqd6hQR+v zTC7h0)n@c1zy&|Adh;X21O7ed=hZ~wle<0WI|tw^)WzWcRR_UQt6py_9e;l_{Eo

JVuh<&iTWp{J;w*9G-ib5g= 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

( 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 z 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 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.

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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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[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 Yk2qnm_5Kh48}NT<>;J2%6$cFXA4Aln1^@s6 diff --git a/res/fonts/DejaVuSansMono.ttf b/res/fonts/DejaVuSansMono.ttf deleted file mode 100644 index f5786022f18216b4c59c6fb0c634b52c8b6e7990..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 340712 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