Arm!
This commit is contained in:
parent
c2a95c96d5
commit
6715d5c534
|
@ -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" }
|
||||
|
||||
|
|
49
Makefile
49
Makefile
|
@ -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)
|
||||
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
8
arch/arm/Cargo.toml
Normal 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
9
arch/arm/src/context.rs
Normal 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
70
arch/arm/src/externs.rs
Normal 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
30
arch/arm/src/interrupt.rs
Normal 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
39
arch/arm/src/lib.rs
Normal 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
60
arch/arm/src/linker.ld
Normal 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
38
arch/arm/src/panic.rs
Normal 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
27
arch/arm/src/start.rs
Normal 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 {}
|
||||
}
|
25
arm-unknown-none.json
Normal file
25
arm-unknown-none.json
Normal 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
17
bootloader/arm/start.s
Normal 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
|
15
kernel/console.rs
Normal file
15
kernel/console.rs
Normal file
|
@ -0,0 +1,15 @@
|
|||
use ransid::Console;
|
||||
use spin::{Once, Mutex, MutexGuard};
|
||||
|
||||
/// Console
|
||||
static CONSOLE: Once<Mutex<Console>> = Once::new();
|
||||
|
||||
/// Initialize console, called if needed
|
||||
fn init_console() -> Mutex<Console> {
|
||||
Mutex::new(Console::new(0, 0))
|
||||
}
|
||||
|
||||
/// Get the global console
|
||||
pub fn console() -> MutexGuard<'static, Console> {
|
||||
CONSOLE.call_once(init_console).lock()
|
||||
}
|
|
@ -80,6 +80,11 @@ use arch::interrupt;
|
|||
#[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]
|
||||
|
@ -92,12 +97,17 @@ extern crate collections;
|
|||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
extern crate goblin;
|
||||
extern crate ransid;
|
||||
extern crate spin;
|
||||
|
||||
/// Console
|
||||
pub mod console;
|
||||
|
||||
/// Context management
|
||||
pub mod context;
|
||||
|
||||
/// ELF file parsing
|
||||
#[cfg(all(not(test), target_arch = "x86_64"))]
|
||||
pub mod elf;
|
||||
|
||||
/// Schemes, filesystem handlers
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use core::str;
|
||||
|
||||
use syscall::Result;
|
||||
use super::Scheme;
|
||||
|
||||
|
|
Loading…
Reference in a new issue