Unified · Split
| @@ -1,10 +1,25 @@ | |||
| 1 | CONF=pc64 | ||
| 2 | |||
| 1 | ARCH = amd64 | 3 | ARCH = amd64 |
| 4 | RUSTC = rustc | ||
| 5 | CC = gcc | ||
| 2 | LD = ld | 6 | LD = ld |
| 3 | NASM = nasm | 7 | AS = nasm |
| 4 | QEMU = qemu-system-i386 -curses | 8 | QEMU = qemu-system-i386 -curses |
| 5 | 9 | ||
| 6 | OBJECTS = rust9front.o | 10 | LDFLAGS = --gc-sections -T $(CONF).ld |
| 7 | ASMOBJECTS = $(wildcard *.asm) | 11 | RUSTFLAGS = -C soft-float -O --target=$(CONF).json |
| 12 | |||
| 13 | OBJ= \ | ||
| 14 | $(CONF).o \ | ||
| 15 | l.o\ | ||
| 16 | |||
| 17 | RUSTFILES= \ | ||
| 18 | macros.rs \ | ||
| 19 | unwind.rs \ | ||
| 20 | main.rs \ | ||
| 21 | |||
| 22 | LIBCORE = libcore.rlib | ||
| 8 | 23 | ||
| 9 | all: $(BUILDDIR) rust9front.bin | 24 | all: $(BUILDDIR) rust9front.bin |
| 10 | 25 | ||
| @@ -12,10 +27,26 @@ $(BUILDDIR): · 1 unmodified line | |||
| 12 | mkdir -p $(BUILDDIR) | 27 | mkdir -p $(BUILDDIR) |
| 13 | 28 | ||
| 14 | rust9front.o: l.asm | 29 | rust9front.o: l.asm |
| 15 | $(NASM) -f elf32 -Wall -o $@ $< | 30 | $(AS) -f elf32 -Wall -o $@ $< |
| 16 | 31 | ||
| 17 | rust9front.bin: rust9front.o | 32 | rust9front.bin: $(OBJ) |
| 18 | $(LD) -m elf_i386 -o $@ $^ | 33 | $(LD) $(LDFLAGS) -o $@ $(OBJ) |
| 19 | 34 | ||
| 20 | debug: rust9front.bin | 35 | debug: rust9front.bin |
| 21 | $(QEMU) -s -S -kernel $< | 36 | $(QEMU) -s -S -kernel $< |
| 37 | |||
| 38 | $(CONF).o: $(CONF).rs $(LIBCORE) | ||
| 39 | $(RUSTC) $(RUSTFLAGS) -o $@ --emit=obj,dep-info $< --extern core=$(LIBCORE) | ||
| 40 | |||
| 41 | %.o: %.c | ||
| 42 | $(CC) -c -o $@ $< $(CFLAGS) | ||
| 43 | |||
| 44 | %.o: %.asm | ||
| 45 | $(AS) -Wall -o $@ $< $(ASFLAGS) | ||
| 46 | |||
| 47 | libcore.rlib: libcore/lib.rs | ||
| 48 | $(RUSTC) $(RUSTFLAGS) -o $@ --crate-type=lib --emit=link,dep-info $< | ||
| 49 | |||
| 50 | clean: | ||
| 51 | rm -f *.d *.rlib *.o *.bin | ||
| 52 | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | use prelude::*; | ||
| 2 | |||
| 3 | /// Write a string to the output channel | ||
| 4 | /// | ||
| 5 | /// This method is unsafe because it does port accesses without synchronisation | ||
| 6 | pub unsafe fn puts(s: &str) | ||
| 7 | { | ||
| 8 | for b in s.bytes() | ||
| 9 | { | ||
| 10 | putb(b); | ||
| 11 | } | ||
| 12 | } | ||
| 13 | |||
| 14 | /// Write a single byte to the output channel | ||
| 15 | /// | ||
| 16 | /// This method is unsafe because it does port accesses without synchronisation | ||
| 17 | pub unsafe fn putb(b: u8) | ||
| 18 | { | ||
| 19 | // Wait for the serial port's fifo to not be empty | ||
| 20 | while (::io::inb(0x3F8+5) & 0x20) == 0 | ||
| 21 | { | ||
| 22 | // Do nothing | ||
| 23 | } | ||
| 24 | // Send the byte out the serial port | ||
| 25 | ::io::outb(0x3F8, b); | ||
| 26 | |||
| 27 | // Also send to the bochs 0xe9 hack | ||
| 28 | ::io::outb(0xe9, b); | ||
| 29 | } | ||
| @@ -0,0 +1,42 @@ | |||
| 1 | /// Write a byte to the specified port | ||
| 2 | pub unsafe fn outb(port: u16, val: u8) | ||
| 3 | { | ||
| 4 | asm!("outb %al, %dx" : : "{dx}"(port), "{al}"(val)); | ||
| 5 | } | ||
| 6 | |||
| 7 | /// Read a single byte from the specified port | ||
| 8 | pub unsafe fn inb(port: u16) -> u8 | ||
| 9 | { | ||
| 10 | let ret : u8; | ||
| 11 | asm!("inb %dx, %al" : "={ax}"(ret) : "{dx}"(port)); | ||
| 12 | return ret; | ||
| 13 | } | ||
| 14 | |||
| 15 | /// Write a word (16-bits) to the specified port | ||
| 16 | pub unsafe fn outw(port: u16, val: u16) | ||
| 17 | { | ||
| 18 | asm!("outb %ax, %dx" : : "{dx}"(port), "{al}"(val)); | ||
| 19 | } | ||
| 20 | |||
| 21 | /// Read a word (16-bits) from the specified port | ||
| 22 | pub unsafe fn inw(port: u16) -> u16 | ||
| 23 | { | ||
| 24 | let ret : u16; | ||
| 25 | asm!("inb %dx, %ax" : "={ax}"(ret) : "{dx}"(port)); | ||
| 26 | return ret; | ||
| 27 | } | ||
| 28 | |||
| 29 | /// Write a long/double-word (32-bits) to the specified port | ||
| 30 | pub unsafe fn outl(port: u16, val: u32) | ||
| 31 | { | ||
| 32 | asm!("outb %eax, %dx" : : "{dx}"(port), "{al}"(val)); | ||
| 33 | } | ||
| 34 | |||
| 35 | /// Read a long/double-word (32-bits) from the specified port | ||
| 36 | pub unsafe fn inl(port: u16) -> u32 | ||
| 37 | { | ||
| 38 | let ret : u32; | ||
| 39 | asm!("inb %dx, %eax" : "={ax}"(ret) : "{dx}"(port)); | ||
| 40 | return ret; | ||
| 41 | } | ||
| 42 | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | use prelude::*; | ||
| 2 | use core::atomic; | ||
| 3 | use core::fmt; | ||
| 4 | |||
| 5 | /// A formatter object | ||
| 6 | pub struct Writer(bool); | ||
| 7 | |||
| 8 | /// A primitive lock for the logging output | ||
| 9 | /// | ||
| 10 | /// This is not really a lock. Since there is no threading at the moment, all | ||
| 11 | /// it does is prevent writing when a collision would occur. | ||
| 12 | static LOGGING_LOCK: atomic::AtomicBool = atomic::ATOMIC_BOOL_INIT; | ||
| 13 | |||
| 14 | impl Writer | ||
| 15 | { | ||
| 16 | /// Obtain a logger for the specified module | ||
| 17 | pub fn get(module: &str) -> Writer { | ||
| 18 | // This "acquires" the lock (actually just disables output if paralel writes are attempted | ||
| 19 | let mut ret = Writer( ! LOGGING_LOCK.swap(true, atomic::Ordering::Acquire) ); | ||
| 20 | |||
| 21 | // Print the module name before returning (prefixes all messages) | ||
| 22 | { | ||
| 23 | use core::fmt::Write; | ||
| 24 | let _ = write!(&mut ret, "[{}] ", module); | ||
| 25 | } | ||
| 26 | |||
| 27 | ret | ||
| 28 | } | ||
| 29 | } | ||
| 30 | |||
| 31 | impl ::core::ops::Drop for Writer | ||
| 32 | { | ||
| 33 | fn drop(&mut self) | ||
| 34 | { | ||
| 35 | // Write a terminating newline before releasing the lock | ||
| 36 | { | ||
| 37 | use core::fmt::Write; | ||
| 38 | let _ = write!(self, "\n"); | ||
| 39 | } | ||
| 40 | // On drop, "release" the lock | ||
| 41 | if self.0 { | ||
| 42 | LOGGING_LOCK.store(false, atomic::Ordering::Release); | ||
| 43 | } | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | impl fmt::Write for Writer | ||
| 48 | { | ||
| 49 | fn write_str(&mut self, s: &str) -> fmt::Result | ||
| 50 | { | ||
| 51 | // If the lock is owned by this instance, then we can safely write to the output | ||
| 52 | if self.0 | ||
| 53 | { | ||
| 54 | unsafe { | ||
| 55 | ::debug::puts( s ); | ||
| 56 | } | ||
| 57 | } | ||
| 58 | Ok( () ) | ||
| 59 | } | ||
| 60 | } | ||
| 61 | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | macro_rules! log{ | ||
| 2 | ( $($arg:tt)* ) => ({ | ||
| 3 | // Import the Writer trait (required by write!) | ||
| 4 | use core::fmt::Write; | ||
| 5 | let _ = write!(&mut ::logging::Writer::get(module_path!()), $($arg)*); | ||
| 6 | }) | ||
| 7 | } | ||
| 8 | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | { | ||
| 2 | "data-layout": "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128", | ||
| 3 | "llvm-target": "x86_64-unknown-linux-gnu", | ||
| 4 | "target-endian": "little", | ||
| 5 | "target-pointer-width": "64", | ||
| 6 | "features": "-mmx,-sse,-sse2,-sse3,-ssse3", | ||
| 7 | "os": "tifflin", | ||
| 8 | "arch": "x86_64", | ||
| 9 | "pre-link-args": ["-m64"], | ||
| 10 | "no-compiler-rt": true, | ||
| 11 | "disable-redzone": true, | ||
| 12 | "eliminate-frame-pointer": false, | ||
| 13 | "morestack": false | ||
| 14 | } | ||
| 15 | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | //#![crate_type="lib"] | ||
| 2 | #![feature(no_std)] | ||
| 3 | #![feature(asm)] | ||
| 4 | #![feature(core)] | ||
| 5 | #![feature(lang_items)] | ||
| 6 | #![no_std] | ||
| 7 | |||
| 8 | #[macro_use] | ||
| 9 | extern crate core; | ||
| 10 | |||
| 11 | #[macro_use] | ||
| 12 | mod macros; | ||
| 13 | |||
| 14 | mod io; | ||
| 15 | pub mod debug; | ||
| 16 | |||
| 17 | mod prelude; | ||
| 18 | pub mod unwind; | ||
| 19 | |||
| 20 | mod logging; | ||
| 21 | |||
| 22 | #[no_mangle] | ||
| 23 | pub extern "C" fn main() | ||
| 24 | { | ||
| 25 | } | ||
| 26 | |||
| 27 | // vim: ft=rust | ||
| 28 | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | pub use core::prelude::*; | ||
| 2 | |||
| @@ -0,0 +1,71 @@ | |||
| 1 | use prelude::*; | ||
| 2 | |||
| 3 | #[lang="panic_fmt"] | ||
| 4 | #[no_mangle] | ||
| 5 | pub fn rust_begin_unwind(args: ::core::fmt::Arguments, file: &str, line: usize) -> ! | ||
| 6 | { | ||
| 7 | // 'args' will print to the formatted string passed to panic! | ||
| 8 | log!("file='{}', line={} :: {}", file, line, args); | ||
| 9 | loop {} | ||
| 10 | } | ||
| 11 | |||
| 12 | #[lang="stack_exhausted"] | ||
| 13 | #[no_mangle] | ||
| 14 | pub fn __morestack() -> ! | ||
| 15 | { | ||
| 16 | loop {} | ||
| 17 | } | ||
| 18 | |||
| 19 | |||
| 20 | #[allow(non_camel_case_types)] | ||
| 21 | #[repr(C)] | ||
| 22 | #[derive(Clone,Copy)] | ||
| 23 | pub enum _Unwind_Reason_Code | ||
| 24 | { | ||
| 25 | _URC_NO_REASON = 0, | ||
| 26 | _URC_FOREIGN_EXCEPTION_CAUGHT = 1, | ||
| 27 | _URC_FATAL_PHASE2_ERROR = 2, | ||
| 28 | _URC_FATAL_PHASE1_ERROR = 3, | ||
| 29 | _URC_NORMAL_STOP = 4, | ||
| 30 | _URC_END_OF_STACK = 5, | ||
| 31 | _URC_HANDLER_FOUND = 6, | ||
| 32 | _URC_INSTALL_CONTEXT = 7, | ||
| 33 | _URC_CONTINUE_UNWIND = 8, | ||
| 34 | } | ||
| 35 | |||
| 36 | #[allow(non_camel_case_types)] | ||
| 37 | #[derive(Clone,Copy)] | ||
| 38 | pub struct _Unwind_Context; | ||
| 39 | |||
| 40 | #[allow(non_camel_case_types)] | ||
| 41 | pub type _Unwind_Action = u32; | ||
| 42 | static _UA_SEARCH_PHASE: _Unwind_Action = 1; | ||
| 43 | |||
| 44 | #[allow(non_camel_case_types)] | ||
| 45 | #[repr(C)] | ||
| 46 | #[derive(Clone,Copy)] | ||
| 47 | #[allow(raw_pointer_derive)] | ||
| 48 | pub struct _Unwind_Exception | ||
| 49 | { | ||
| 50 | exception_class: u64, | ||
| 51 | exception_cleanup: fn(_Unwind_Reason_Code,*const _Unwind_Exception), | ||
| 52 | private: [u64; 2], | ||
| 53 | } | ||
| 54 | |||
| 55 | #[lang="eh_personality"] | ||
| 56 | #[no_mangle] | ||
| 57 | pub fn rust_eh_personality( | ||
| 58 | _version: isize, _actions: _Unwind_Action, _exception_class: u64, | ||
| 59 | _exception_object: &_Unwind_Exception, _context: &_Unwind_Context | ||
| 60 | ) -> _Unwind_Reason_Code | ||
| 61 | { | ||
| 62 | loop{} | ||
| 63 | } | ||
| 64 | |||
| 65 | #[no_mangle] | ||
| 66 | #[allow(non_snake_case)] | ||
| 67 | pub fn _Unwind_Resume() | ||
| 68 | { | ||
| 69 | loop{} | ||
| 70 | } | ||
| 71 | |||