This commit is contained in:
Jeremy Soller 2016-08-25 17:03:01 -06:00
commit 6715d5c534
29 changed files with 386 additions and 22 deletions

View file

@ -9,6 +9,7 @@ crate-type = ["staticlib"]
[dependencies]
bitflags = "*"
ransid = "*"
spin = "*"
[dependencies.goblin]
@ -19,6 +20,9 @@ features = ["no_mach", "no_mach32", "no_pe", "no_pe32", "no_endian_fd", "pure"]
[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" }

View file

@ -1,24 +1,27 @@
ARCH?=x86_64
ARCH?=arm
LD=ld
QEMU=qemu-system-$(ARCH)
QEMUFLAGS=-enable-kvm -cpu host
QEMUFLAGS=-serial mon:stdio -d guest_errors
UNAME := $(shell uname)
ifeq ($(UNAME),Darwin)
LD=$(ARCH)-elf-ld
QEMUFLAGS=
ifeq ($(ARCH),arm)
LD=$(ARCH)-none-eabi-ld
QEMUFLAGS+=-cpu arm1176 -machine integratorcp
QEMUFLAGS+=-nographic
else
LD=ld
QEMUFLAGS+=-enable-kvm -cpu host -machine q35 -smp 4
#,int,pcall
#-nographic
#-device intel-iommu
UNAME := $(shell uname)
ifeq ($(UNAME),Darwin)
LD=$(ARCH)-elf-ld
QEMUFLAGS=
endif
endif
QEMUFLAGS+=-smp 4 -machine q35
QEMUFLAGS+=-serial mon:stdio
QEMUFLAGS+=-d guest_errors
#,int,pcall
#-nographic
#-device intel-iommu
all: build/harddrive.bin
all: build/kernel.bin
list: build/kernel.list
@ -27,9 +30,6 @@ run: bochs
bochs: build/harddrive.bin
bochs -f bochs.$(ARCH)
qemu: build/harddrive.bin
$(QEMU) $(QEMUFLAGS) -drive file=$<,format=raw,index=0,media=disk
FORCE:
build/libcore.rlib: rust/src/libcore/lib.rs
@ -53,13 +53,24 @@ build/libkernel.a: build/libcore.rlib build/liballoc.rlib build/libcollections.r
RUSTC="./rustc.sh" cargo rustc --target $(ARCH)-unknown-none.json -- -C soft-float -o $@
build/kernel.bin: build/libkernel.a
$(LD) --gc-sections -z max-page-size=0x1000 -T bootloader/x86/kernel.ld -o $@ $<
$(LD) --gc-sections -z max-page-size=0x1000 -T arch/$(ARCH)/src/linker.ld -o $@ $<
ifeq ($(ARCH),arm)
build/kernel.list: build/kernel.bin
$(ARCH)-none-eabi-objdump -C -D $< > $@
qemu: build/kernel.bin
$(QEMU) $(QEMUFLAGS) -kernel $<
else
build/kernel.list: build/kernel.bin
objdump -C -M intel -D $< > $@
build/harddrive.bin: build/kernel.bin
nasm -f bin -o $@ -D ARCH_$(ARCH) -ibootloader/x86/ -ibuild/ bootloader/x86/harddrive.asm
nasm -f bin -o $@ -D ARCH_$(ARCH) -ibootloader/$(ARCH)/ -ibuild/ bootloader/$(ARCH)/harddrive.asm
qemu: build/harddrive.bin
$(QEMU) $(QEMUFLAGS) -drive file=$<,format=raw,index=0,media=disk
endif
clean:
rm -rf build/* target/*

8
arch/arm/Cargo.toml Normal file
View file

@ -0,0 +1,8 @@
[package]
name = "arch_arm"
version = "0.1.0"
[dependencies]
bitflags = "*"
hole_list_allocator = { path = "../../alloc/hole_list_allocator"}
spin = "*"

9
arch/arm/src/context.rs Normal file
View file

@ -0,0 +1,9 @@
#[derive(Debug)]
pub struct Context;
impl Context {
pub fn new() -> Self {
Context
}
}

70
arch/arm/src/externs.rs Normal file
View file

@ -0,0 +1,70 @@
/// 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
}

30
arch/arm/src/interrupt.rs Normal file
View file

@ -0,0 +1,30 @@
//! 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() {
}

39
arch/arm/src/lib.rs Normal file
View file

@ -0,0 +1,39 @@
//! 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;

60
arch/arm/src/linker.ld Normal file
View file

@ -0,0 +1,60 @@
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*)
}
}

38
arch/arm/src/panic.rs Normal file
View file

@ -0,0 +1,38 @@
//! 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 {}
}

27
arch/arm/src/start.rs Normal file
View file

@ -0,0 +1,27 @@
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 {}
}

62
arch/x86_64/src/linker.ld Normal file
View file

@ -0,0 +1,62 @@
ENTRY(kstart)
OUTPUT_FORMAT(elf64-x86-64)
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*)
}
}

25
arm-unknown-none.json Normal file
View file

@ -0,0 +1,25 @@
{
"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": ["-m32", "-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
}

17
bootloader/arm/start.s Normal file
View file

@ -0,0 +1,17 @@
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

View file

@ -0,0 +1,131 @@
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
mov [disk], dl
mov si, name
call print
call print_line
mov bh, 0
mov bl, [disk]
call print_num
call print_line
mov ax, (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, 64
jbe .good_size
pusha
mov cx, 64
call load
popa
add ax, 64
add dx, 64 * 512 / 16
sub cx, 64
jmp load
.good_size:
mov [DAPACK.addr], ax
mov [DAPACK.buf], bx
mov [DAPACK.count], cx
mov [DAPACK.seg], dx
mov si, loading
call print
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
call print_line
mov dl, [disk]
mov si, DAPACK
mov ah, 0x42
int 0x13
jc error
ret
error:
mov si, errored
call print
call print_line
.halt:
cli
hlt
jmp .halt
%include "print16.asm"
name: db "Redox Loader",0
loading: db "Load ",0
errored: db "Could not read disk",0
finished: db "Finished Loading",0
line: db 13,10,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: dd 0 ; put the lba to read in this spot
dd 0 ; more storage bytes only for big lba's ( > 4 bytes )
times 510-($-$$) db 0
db 0x55
db 0xaa

View file

@ -0,0 +1,46 @@
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

View file

@ -0,0 +1,8 @@
struc GDTEntry
.limitl resw 1
.basel resw 1
.basem resb 1
.attribute resb 1
.flags__limith resb 1
.baseh resb 1
endstruc

View file

@ -0,0 +1,19 @@
%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 "kernel.bin"
align 512, db 0
.end:
.length equ kernel_file.end - kernel_file
.length_sectors equ .length / 512

View file

@ -0,0 +1,78 @@
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, 5370 ;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

View file

@ -0,0 +1,32 @@
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

View file

@ -0,0 +1,66 @@
SECTION .text
USE16
; provide function for printing in x86 real mode
; a newline
newline: db 0xD, 0xA, 0
; print a string and a newline
; IN
; si: points at zero-terminated String
; CLOBBER
; ax
print_line:
mov si, newline
call print
ret
; print a string
; IN
; si: points at zero-terminated String
; CLOBBER
; ax
print:
lodsb
test al, al
jz .done
call print_char
jmp print
.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

Some files were not shown because too many files have changed in this diff Show more