diff --git a/kernel-rs/Cargo.toml b/kernel-rs/Cargo.toml index 7f432ba4..6a7f203c 100644 --- a/kernel-rs/Cargo.toml +++ b/kernel-rs/Cargo.toml @@ -1,14 +1,12 @@ [package] -name = "kfs" +name = "bluesnow" version = "0.1.0" -authors = ["Jack Halford "] +authors = ["Jack Halford ", "William Escande "] [lib] crate-type = ["staticlib"] +[profile.release] +panic = "abort" + [dependencies] -rlibc = "1.0" -volatile = "0.1.0" -spin = "0.4.5" -multiboot2 = "0.1.0" -bitflags = "0.9.1" diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile index da90be37..a31c2d95 100644 --- a/kernel-rs/Makefile +++ b/kernel-rs/Makefile @@ -1,49 +1,50 @@ -arch ?= x86_64 +project := bluesnow +arch ?= x86 +NASM := nasm -f elf +LD := ld -m elf_i386 -n +QEMU := qemu-system-x86_64 -enable-kvm -monitor telnet:127.0.0.1:1234,server,nowait + kernel := build/kernel-$(arch).bin iso := build/os-$(arch).iso +DIRISO := build/isofiles -target ?= $(arch)-kfs -rust_os := target/$(target)/debug/libkfs.a +target ?= $(arch)-$(project) +rust_os := target/$(target)/release/lib$(project).a +SHELL := /bin/bash -linker_script := src/arch/$(arch)/linker.ld -grub.cfg := src/arch/$(arch)/grub.cfg -asm_source_files := $(wildcard src/arch/$(arch)/*.asm) -asm_object_files := $(patsubst src/arch/$(arch)/%.asm, \ - build/arch/$(arch)/%.o, $(asm_source_files)) - -.PHONY: all clean run iso kernel -SHELL := /bin/bash +linker_script := src/arch/$(arch)/linker.ld +grub.cfg := src/arch/$(arch)/grub.cfg +asm_source := $(wildcard src/arch/$(arch)/*.asm) +asm_object := $(patsubst src/arch/$(arch)/%.asm, build/arch/$(arch)/%.o, $(asm_source)) all: $(kernel) +build/arch/$(arch)/%.o: src/arch/$(arch)/%.asm Makefile + @mkdir -p $(shell dirname $@) + @$(NASM) $< -o $@ + +$(kernel): $(rust_os) $(asm_object) $(linker_script) Makefile + @$(LD) -o $(kernel) -T $(linker_script) $(asm_object) $(rust_os) + +$(iso): $(kernel) $(grub.cfg) Makefile + @mkdir -p $(DIRISO)/boot/grub + @cp $(grub.cfg) $(DIRISO)/boot/grub + @cp $(kernel) $(DIRISO)/boot/kernel.bin + @grub-mkrescue -o $(iso) $(DIRISO) 2>/dev/null + +run: $(iso) Makefile + @tmux info >&- || { echo -e "\033[38;5;16m ~~ NOT IN A VALID TMUX SESSION ~~\033[0m" ; exit 1; } + @tmux split-window "tmux resize-pane -y 20; sleep 0.5; telnet 127.0.0.1 1234" + @$(QEMU) -curses -cdrom $(iso) + clean: @cargo clean @rm -r build -run: - @qemu-system-x86_64 -curses -cdrom $(iso) - -devrun: - @tmux info >&- || { echo -e "\033[38;5;16m ~~ NOT IN A VALID TMUX SESSION ~~\033[0m" ; exit 1; } - @tmux split-window "tmux resize-pane -y 20; sleep 0.5; telnet 127.0.0.1 1234" - @qemu-system-x86_64 -enable-kvm -monitor telnet:127.0.0.1:1234,server,nowait -curses -cdrom build/os-x86_64.iso +$(rust_os): $(target).json Makefile + @xargo build --release --target $(target) +kernel: $(rust_os) iso: $(iso) -$(iso): $(kernel) $(grub.cfg) - @mkdir -p build/isofiles/boot/grub - cp $(kernel) build/isofiles/boot/kernel.bin - cp $(grub.cfg) build/isofiles/boot/grub - grub-mkrescue -o $(iso) build/isofiles 2>/dev/null - rm -r build/isofiles - -$(kernel): kernel $(asm_object_files) $(linker_script) - @ld -n --gc-sections -T $(linker_script) -o $(kernel) $(asm_object_files) $(rust_os) - -kernel: - @RUST_TARGET_PATH="$(shell pwd)" xargo build --target $(target) - -# compile asm files -build/arch/$(arch)/%.o: src/arch/$(arch)/%.asm - @mkdir -p $(shell dirname $@) - @nasm -felf64 $< -o $@ +.PHONY: run clean kernel iso diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm new file mode 100644 index 00000000..8624af56 --- /dev/null +++ b/kernel-rs/src/arch/x86/boot.asm @@ -0,0 +1,23 @@ +global start +extern kmain + +section .text +bits 32 +start: + ; print `OK` to screen + ; mov dword [0xb8000], 0x2f4b2f4f + mov word [0xb8000], 0x0248 ; H + mov word [0xb8002], 0x0265 ; e + mov word [0xb8004], 0x026c ; l + mov word [0xb8006], 0x026c ; l + mov word [0xb8008], 0x026f ; o + mov word [0xb800a], 0x022c ; , + mov word [0xb800c], 0x0220 ; + mov word [0xb800e], 0x0277 ; w + mov word [0xb8010], 0x026f ; o + mov word [0xb8012], 0x0272 ; r + mov word [0xb8014], 0x026c ; l + mov word [0xb8016], 0x0264 ; d + mov word [0xb8018], 0x0221 ; ! + call kmain + hlt diff --git a/kernel-rs/src/arch/x86/grub.cfg b/kernel-rs/src/arch/x86/grub.cfg new file mode 100644 index 00000000..982ff586 --- /dev/null +++ b/kernel-rs/src/arch/x86/grub.cfg @@ -0,0 +1,7 @@ +set timeout=5 +set default=0 + +menuentry "Blue Snow" { + multiboot2 /boot/kernel.bin + boot +} diff --git a/kernel-rs/src/arch/x86/linker.ld b/kernel-rs/src/arch/x86/linker.ld new file mode 100644 index 00000000..b86d432e --- /dev/null +++ b/kernel-rs/src/arch/x86/linker.ld @@ -0,0 +1,15 @@ +ENTRY(start) +OUTPUT_FORMAT(elf32-i386) + +SECTIONS { + . = 1M; + + .boot : { + /* ensure that the multiboot header is at the beginning */ + *(.multiboot_header) + } + + .text : { + *(.text) + } +} diff --git a/kernel-rs/src/arch/x86_64/multiboot_header.asm b/kernel-rs/src/arch/x86/multiboot_header.asm similarity index 66% rename from kernel-rs/src/arch/x86_64/multiboot_header.asm rename to kernel-rs/src/arch/x86/multiboot_header.asm index 737a2b95..9f87d3bb 100644 --- a/kernel-rs/src/arch/x86_64/multiboot_header.asm +++ b/kernel-rs/src/arch/x86/multiboot_header.asm @@ -1,15 +1,15 @@ section .multiboot_header header_start: dd 0xe85250d6 ; magic number (multiboot 2) - dd 0 ; architecture - (protected mode i386) + dd 0 ; architecture 0 (protected mode i386) dd header_end - header_start ; header length - ; checksum - dd 0x100000000 - (0xe85250d6 + 0 + (header_end - header_start)) + + dd 0x100000000 - (0xe85250d6 + 0 + (header_end - header_start)); checksum ; insert optional multiboot tags here - ; required end tag here - dw 0 ; type - dw 0 ; flags - dd 0 ; size + ; required end tag + dw 0 ; type + dw 0 ; flags + dd 8 ; size header_end: diff --git a/kernel-rs/src/arch/x86_64/boot.asm b/kernel-rs/src/arch/x86_64/boot.asm deleted file mode 100644 index d17c833e..00000000 --- a/kernel-rs/src/arch/x86_64/boot.asm +++ /dev/null @@ -1,165 +0,0 @@ -global start -extern long_mode_start - -section .text -bits 32 -start: - mov esp, stack_top - - ; Move multiboot info pointer to edi - ; which is the first argument for the rust main - mov edi, ebx - - call check_multiboot - call check_cpuid - call check_long_mode - - call set_up_page_tables - call enable_paging - - ; load the 64-bit GDT - lgdt [gdt64.pointer] - - jmp gdt64.code:long_mode_start - - ; print 'OK' to screen - mov dword [0xb8000], 0x2f4b2f4f - hlt -error: - ; print 'ERR: ' and the given error code to screen and hangs - mov dword [0xb8000], 0x4f524f45 - mov dword [0xb8004], 0x4f3a4f52 - mov dword [0xb8008], 0x4f204f20 - mov byte [0xb800a], al - hlt - -check_multiboot: - cmp eax, 0x36d76289 - jne .no_multiboot - ret -.no_multiboot: - mov al, "0" - jmp error - -check_cpuid: - ; Check if CPUID is supported by attempting to flip the ID bit (bit 21) - ; in the FLAGS register. If we can flip it, CPUID is available. - - ; Copy FLAGS in to EAX via stack - pushfd - pop eax - ; Copy to ECX as well for comparing later on - mov ecx, eax - ; Flip the ID bit - xor eax, 1 << 21 - ; Copy EAX to FLAGS via the stack - push eax - popfd - ; Copy FLAGS back to EAX (with the flipped bit if CPUID is supported) - pushfd - pop eax - ; Restore FLAGS from the old version stored in ECX (i.e. flipping the - ; ID bit back if it was ever flipped). - push ecx - popfd - - ; Compare EAX and ECX. If they are equal then that means the bit - ; wasn't flipped, and CPUID isn't supported. - cmp eax, ecx - je .no_cpuid - ret -.no_cpuid: - mov al, "1" - jmp error - -check_long_mode: - ; test if extended processor info in available - mov eax, 0x80000000 ; implicit argument for cpuid - cpuid ; get highest supported argument - cmp eax, 0x80000001 ; it needs to be at least 0x80000001 - jb .no_long_mode ; if it's less, the CPU is too old for long mode - - ; use extended info to test if long mode is available - mov eax, 0x80000001 ; argument for extended processor info - cpuid ; returns various feature bits in ecx and edx - test edx, 1 << 29 ; test if the LM-bit is set in the D-register - jz .no_long_mode ; If it's not set, there is no long mode - ret -.no_long_mode: - mov al, "2" - jmp error - -set_up_page_tables: - ; map P4 511th byte recursively to P4 - mov eax, p4_table - or eax, 0b11 ; present + writable - mov [p4_table + 511 * 8], eax - - ; map first P4 entry to P3 table - mov eax, p3_table - or eax, 0b11 ; present + writable - mov [p4_table], eax - - ; map first P3 entry to P2 table - mov eax, p2_table - or eax, 0b11 ; present + writable - mov [p3_table], eax - - mov ecx, 0 ;counter variable -.map_p2_table: - ; map ecx-th P2 entry to a huge page that start at address 2MiB*ecx - mov eax, 0x200000 ; 2MiB - mul ecx ; start address of ecx-th page - or eax, 0b10000011 ; present + writeable + huge - mov [p2_table + ecx * 8], eax ; map ecx-th entry - - inc ecx ; increase counter - cmp ecx, 512 ; if counter == 512, the whole P2 table is mapped - jne .map_p2_table ; else map the next entry - - ret - -enable_paging: - ; load P4 to cr3 register (cpu uses this to acces the P4 table) - mov eax, p4_table - mov cr3, eax - - ; enable PAE-flag in cr4 (Physical Address Extension) - mov eax, cr4 - or eax, 1 << 5 - mov cr4, eax - - ; set the long mode bit in the EFER MSR (model specific register) - mov ecx, 0xC0000080 - rdmsr - or eax, 1 << 8 - wrmsr - - ; enable paging in the cr0 register - mov eax, cr0 - or eax, 1 << 31 - mov cr0, eax - - ret - - -section .bss -align 4096 -p4_table: - resb 4096 -p3_table: - resb 4096 -p2_table: - resb 4096 -stack_bottom: - resb 4096 * 4 -stack_top: - -section .rodata -gdt64: - dq 0 ; zero entry -.code: equ $ - gdt64 - dq (1<<43) | (1<<44) | (1<<47) | (1<<53) ; code segment -.pointer: - dw $ - gdt64 - 1 - dq gdt64 diff --git a/kernel-rs/src/arch/x86_64/grub.cfg b/kernel-rs/src/arch/x86_64/grub.cfg deleted file mode 100644 index a1f38c91..00000000 --- a/kernel-rs/src/arch/x86_64/grub.cfg +++ /dev/null @@ -1,7 +0,0 @@ -set timeout=0 -set default=0 - -menuentry "my os" { - multiboot2 /boot/kernel.bin - boot -} diff --git a/kernel-rs/src/arch/x86_64/linker.ld b/kernel-rs/src/arch/x86_64/linker.ld deleted file mode 100644 index 06648ad5..00000000 --- a/kernel-rs/src/arch/x86_64/linker.ld +++ /dev/null @@ -1,24 +0,0 @@ -ENTRY(start) - -SECTIONS { - . = 1M; - - .boot : - { - /* ensure that the multiboot header is at the beginning */ - KEEP(*(.multiboot_header)) - } - - .text : - { - *(.text .text.*) - } - - .rodata : { - *(.rodata .rodata.*) - } - - .data.rel.ro : { - *(.data.rel.ro.local*) *(.data.rel.ro .data.rel.ro.*) - } -} diff --git a/kernel-rs/src/arch/x86_64/long_mode_init.asm b/kernel-rs/src/arch/x86_64/long_mode_init.asm deleted file mode 100644 index e89e7955..00000000 --- a/kernel-rs/src/arch/x86_64/long_mode_init.asm +++ /dev/null @@ -1,20 +0,0 @@ -global long_mode_start - -section .text -bits 64 -long_mode_start: - ; load 0 into all data segment registers - mov ax, 0 - mov ss, ax - mov ds, ax - mov es, ax - mov fs, ax - mov gs, ax - - extern rust_main - call rust_main - - ;;print 'OKAY' to screen - ;mov rax, 0x2f592f412f4b2f4f - ;mov qword [0xb8000], rax - hlt diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs old mode 100755 new mode 100644 index cc210957..8cc59775 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -1,47 +1,36 @@ +// #![no_std] +// #[cfg(test)] +// mod tests { +// #[test] +// fn it_works() { +// assert_eq!(2 + 2, 4); +// } +// } + #![feature(lang_items)] -#![feature(const_fn)] -#![feature(ptr_internals)] -#![feature(asm)] #![no_std] -extern crate rlibc; -extern crate volatile; -extern crate spin; -extern crate multiboot2; -#[macro_use] extern crate bitflags; +#[lang = "eh_personality"] +extern fn eh_personality() { -#[macro_use] mod vga_buffer; - - -// mod memory; - -#[no_mangle] -pub extern fn rust_main(multiboot_information_address: usize) { - vga_buffer::clear_screen(); - - use core::ptr::{read_volatile, write_volatile}; - let kbd1 = &0x60 as *const i32; - let kbd2 = &0x64 as *const i32; - - loop{ - unsafe { - if (read_volatile(kbd1) != 96) { - println!("0x60: {} !!!!!!", read_volatile(kbd1)); - break; - } - println!("0x60: {} 0x64: {}", - read_volatile(kbd1), read_volatile(kbd2) ); - } - }; } -#[lang = "eh_personality"] #[no_mangle] pub extern fn eh_personality() {} - #[lang = "panic_fmt"] -#[no_mangle] -pub extern fn panic_fmt(fmt: core::fmt::Arguments, file: &'static str, - line: u32) -> ! { - println!("\n\nPANIC in {} at line {}:", file, line); - println!(" {}", fmt); - loop{} +extern fn rust_begin_panic() -> ! { + loop {} + +} + + +#[no_mangle] +pub extern fn kmain() -> ! { + unsafe { + let vga = 0xb8000 as *mut u32; + + *vga = 0x2f592f412f; + + }; + + loop { } + } diff --git a/kernel-rs/src/memory/area_frame_allocator.rs b/kernel-rs/src/memory/area_frame_allocator.rs deleted file mode 100644 index 3693f45d..00000000 --- a/kernel-rs/src/memory/area_frame_allocator.rs +++ /dev/null @@ -1,94 +0,0 @@ -use memory::{Frame, FrameAllocator}; -use multiboot2::{MemoryAreaIter, MemoryArea}; - -pub struct AreaFrameAllocator { - next_free_frame: Frame, - current_area: Option<&'static MemoryArea>, - areas: MemoryAreaIter, - kernel_start: Frame, - kernel_end: Frame, - multiboot_start: Frame, - multiboot_end: Frame, -} - -impl AreaFrameAllocator { - pub fn new( - kernel_start: usize, - kernel_end: usize, - multiboot_start: usize, - multiboot_end: usize, - memory_areas: MemoryAreaIter - ) -> AreaFrameAllocator { - let mut allocator = AreaFrameAllocator { - next_free_frame: Frame::containing_address(0), - current_area: None, - areas: memory_areas, - kernel_start: Frame::containing_address(kernel_start), - kernel_end: Frame::containing_address(kernel_end), - multiboot_start: Frame::containing_address(multiboot_start), - multiboot_end: Frame::containing_address(multiboot_end), - }; - allocator.choose_next_area(); - allocator - } - - fn choose_next_area(&mut self) { - self.current_area = self.areas.clone().filter(|area| { - // filter in areas with remaining free frames - // i.e. next_free_frame is before the last frame - let address = area.base_addr + area.length - 1; - Frame::containing_address(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(area.base_addr as usize); - if self.next_free_frame < start_frame { - self.next_free_frame = start_frame; - } - } - } -} - -impl FrameAllocator for AreaFrameAllocator { - fn allocate_frame(&mut self) -> Option { - 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 frame = Frame{ number: self.next_free_frame.number }; - - // the last frame of the current area - let current_area_last_frame = { - let address = area.base_addr + area.length - 1; - Frame::containing_address(address as usize) - }; - - if frame > current_area_last_frame { - // all frames of current area are used, switch to next area - self.choose_next_area(); - } else if frame >= self.kernel_start && frame <= self.kernel_end { - // 'frame' is used by the kernel - self.next_free_frame = Frame { - number: self.kernel_end.number + 1 - }; - } else if frame >= self.multiboot_start && frame <= self.multiboot_end { - // 'frame' is used by the multiboot information structure - self.next_free_frame = Frame { - number: self.multiboot_end.number + 1 - }; - } else { - // 'frame' is unused, increment next_free_frame and return it; - self.next_free_frame.number += 1; - return Some(frame) - }; - // frame was not valid, try it again with the updated next_free_frame - self.allocate_frame() - } else { - None // no free frames left - } - } - - fn deallocate_frame(&mut self, frame: Frame) { - unimplemented!() - } - -} diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs deleted file mode 100644 index 8cd88e6e..00000000 --- a/kernel-rs/src/memory/mod.rs +++ /dev/null @@ -1,27 +0,0 @@ -pub use self::area_frame_allocator::AreaFrameAllocator; -use self::paging::PhysicalAddress; - -mod area_frame_allocator; -mod paging; - -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] -pub struct Frame { - number: usize, -} - -pub const PAGE_SIZE: usize = 4096; - -impl Frame { - fn containing_address(address: usize) -> Frame { - Frame{ number: address / PAGE_SIZE } - } - - fn start_address(&self) -> PhysicalAddress { - self.number * PAGE_SIZE - } -} - -pub trait FrameAllocator { - fn allocate_frame(&mut self) -> Option; - fn deallocate_frame(&mut self, frame: Frame); -} diff --git a/kernel-rs/src/memory/paging/entry.rs b/kernel-rs/src/memory/paging/entry.rs deleted file mode 100644 index 18415098..00000000 --- a/kernel-rs/src/memory/paging/entry.rs +++ /dev/null @@ -1,47 +0,0 @@ -use memory::Frame; - -pub struct Entry(u64) - -bitflags! { - pub struct 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; - } -} - -impl Entry { - pub fn is_unused(&self) -> bool { - self.0 == 0; - } - - pub fn set_unused(&mut self) { - self.0 = 0; - } - - pub fn flags(&self) -> EntryFlags { - EntryFlags::from_bits_truncate(self.0) - } - - pub fn pointed_frame(&self) -> Option { - if self.flags().contains(PRESENT) { - Some(Frame::containing_address( - self.0 as usize & 0x000fffff_fffff000 - )) - } else { - None - } - } - - pub fn set(&mut self, frame: Frame, flags: EntryFlags) { - assert!(frame.start_address() & !0x000fffff_fffff000 == 0); - self.0 = (frame.start_address() as u64) | flags.bits(); - } -} diff --git a/kernel-rs/src/memory/paging/mod.rs b/kernel-rs/src/memory/paging/mod.rs deleted file mode 100644 index 17896565..00000000 --- a/kernel-rs/src/memory/paging/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -use memory::PAGE_SIZE; - -const ENTRY_COUNT: usize = 512; - -pub type PhysicalAddress = usize; -pub type VirtualAddress = usize; - -pub struct Page { - number: usize, -} diff --git a/kernel-rs/src/memory/paging/table.rs b/kernel-rs/src/memory/paging/table.rs deleted file mode 100644 index e8b1244d..00000000 --- a/kernel-rs/src/memory/paging/table.rs +++ /dev/null @@ -1,51 +0,0 @@ -use memory::paging::entry::* -use memory::paging::ENTRY_COUNT; -use core::ops::{Index, IndexMut}; - -pub const P4: *mut Table = 0xffffffff_fffff000 as *mut _; - -pub struct Table { - entries: [Entry; ENTRY_COUNT], -} - -impl Index for Table { - type Output = Entry; - - fn index(&sef, index: usize) -> &Entry { - &self.entries[index] - } -} - -impl IndexMut for Table { - fn index_mut(&mut self, index: usize) -> &mut Entry { - &mut self.entries[index] - } -} - -impl Table { - pub fn zero(&mut self) { - for entry in self.entries.iter_mut() { - entry.set_unused(); - } - } - - 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(&self, index: usize) -> Option<&mut Table> { - self.next_table_address(index) - .map(|address| unsafe { &*(address as *mut _) }) - } - - 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 - } - } -} diff --git a/kernel-rs/src/vga_buffer.rs b/kernel-rs/src/vga_buffer.rs deleted file mode 100644 index 76473320..00000000 --- a/kernel-rs/src/vga_buffer.rs +++ /dev/null @@ -1,148 +0,0 @@ -use core::ptr::Unique; -use volatile::Volatile; -use core::fmt; -use spin::Mutex; - -pub static WRITER: Mutex = Mutex::new(Writer { - column_position: 0, - color_code: ColorCode::new(Color::Green, Color::Black), - buffer: unsafe { Unique::new_unchecked(0xb8000 as *mut _) }, -}); - -macro_rules! println { - ($fmt:expr) => (print!(concat!($fmt, "\n"))); - ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); -} - -macro_rules! print { - ($($arg:tt)*) => ({ - $crate::vga_buffer::print(format_args!($($arg)*)); - }); -} - -pub fn print(args: fmt::Arguments) { - use core::fmt::Write; - WRITER.lock().write_fmt(args).unwrap(); -} - -impl fmt::Write for Writer { - fn write_str(&mut self, s: &str) -> fmt::Result { - for byte in s.bytes() { - self.putchar(byte) - } - Ok(()) - } -} - -#[allow(dead_code)] -#[derive(Debug, Clone, Copy)] -#[repr(u8)] -pub enum Color { - Black = 0, - Blue = 1, - Green = 2, - Cyan = 3, - Red = 4, - Magenta = 5, - Brown = 6, - LightGray = 7, - DarkGray = 8, - LightBlue = 9, - LightGreen = 10, - LightCyan = 11, - LightRed = 12, - Pink = 13, - Yellow = 14, - White = 15, -} - -#[derive(Debug, Clone, Copy)] -struct ColorCode(u8); - -impl ColorCode { - const fn new(foreground: Color, background: Color) -> ColorCode { - ColorCode((background as u8) << 4 | (foreground as u8)) - } -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -struct ScreenChar { - ascii_character: u8, - color_code: ColorCode, -} - -const BUFFER_HEIGHT: usize = 25; -const BUFFER_WIDTH: usize = 80; - -struct Buffer { - chars: [[Volatile; BUFFER_WIDTH]; BUFFER_HEIGHT] -} - -pub struct Writer { - column_position: usize, - color_code: ColorCode, - buffer: Unique, -} - -#[allow(dead_code)] -impl Writer { - pub fn putchar(&mut self, byte: u8) { - match byte { - b'\n' => self.put_endl(), - byte => { - if self.column_position >= BUFFER_WIDTH { - self.put_endl(); - } - - let row = BUFFER_HEIGHT - 1; - let col = self.column_position; - - let color_code = self.color_code; - self.buffer().chars[row][col].write(ScreenChar { - ascii_character: byte, - color_code: color_code, - }); - self.column_position += 1; - } - } - } - - pub fn putstr(&mut self, s: &str) { - for byte in s.bytes() { - self.putchar(byte) - } - } - - fn buffer(&mut self) -> &mut Buffer { - unsafe{ self.buffer.as_mut()} - } - - fn put_endl(&mut self) { - for row in 1..BUFFER_HEIGHT { - for col in 0..BUFFER_WIDTH { - let buffer = self.buffer(); - let character = buffer.chars[row][col].read(); - buffer.chars[row - 1][col].write(character); - } - } - self.clear_row(BUFFER_HEIGHT - 1); - self.column_position = 0; - } - - fn clear_row(&mut self, row: usize) { - let blank = ScreenChar { - ascii_character: b' ', - color_code: self.color_code, - }; - for col in 0..BUFFER_WIDTH { - self.buffer().chars[row][col].write(blank); - } - } -} - -pub fn clear_screen() { - for _ in 0..BUFFER_HEIGHT { - println!(""); - } -} diff --git a/kernel-rs/x86-bluesnow.json b/kernel-rs/x86-bluesnow.json new file mode 100644 index 00000000..73bedb92 --- /dev/null +++ b/kernel-rs/x86-bluesnow.json @@ -0,0 +1,15 @@ +{ + "arch": "x86", + "cpu": "pentium4", + "data-layout": "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128", + "llvm-target": "i686-unknown-none", + "linker-flavor": "gcc", + "no-compiler-rt": true, + "os": "bluesnow", + "target-endian": "little", + "target-pointer-width": "32", + "target-c-int-width": "32", + "features": "-mmx,-fxsr,-sse,-sse2,+soft-float", + "eliminate-frame-pointer": false + +} diff --git a/kernel-rs/x86_64-kfs.json b/kernel-rs/x86_64-kfs.json deleted file mode 100644 index d2fa22e1..00000000 --- a/kernel-rs/x86_64-kfs.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "llvm-target": "x86_64-unknown-none", - "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128", - "linker-flavor": "gcc", - "target-endian": "little", - "target-pointer-width": "64", - "target-c-int-width": "32", - "arch": "x86_64", - "os": "none", - "disable-redzone": true, - "features": "-mmx,-sse,+soft-float", - "panic-strategy": "abort" -}