initial commit

This commit is contained in:
Mahdi Dibaiee
2016-06-25 16:03:02 +04:30
commit aeeef30e09
34 changed files with 486 additions and 0 deletions
Generated
+12
View File
@@ -0,0 +1,12 @@
[root]
name = "mahdi_os"
version = "0.1.0"
dependencies = [
"rlibc 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rlibc"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
+15
View File
@@ -0,0 +1,15 @@
[package]
name = "mahdi_os"
version = "0.1.0"
authors = ["Mahdi Dibaiee <mdibaiee@aol.com>"]
[lib]
crate-type = ["staticlib"]
[dependencies]
rlibc = "0.1.4"
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"
+39
View File
@@ -0,0 +1,39 @@
arch ?= x86_64
kernel := build/kernel-$(arch).bin
iso := build/os-$(arch).iso
target ?= $(arch)-unknown-linux-gnu
rust_os := target/$(target)/debug/libmahdi_os.a
linker_script = src/arch/$(arch)/linker.ld
grub_cfg = src/arch/$(arch)/grub.cfg
assembly_source_files = $(wildcard src/arch/$(arch)/*.asm)
assembly_object_files = $(patsubst src/arch/$(arch)/%.asm, build/arch/$(arch)/%.o, $(assembly_source_files))
.PHONY: all clean run iso
all: $(kernel)
clean:
@rm -r build
run: $(iso)
@qemu-system-x86_64 -curses -cdrom $(iso)
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 -d /usr/lib/grub/i386-pc 2> /dev/null
@rm -r build/isofiles
$(kernel): cargo $(rust_os) $(assembly_object_files) $(linker_script)
@ld -n --gc-sections -T $(linker_script) -o $(kernel) $(assembly_object_files) $(rust_os)
cargo:
@cargo build --target $(target)
build/arch/$(arch)/%.o: src/arch/$(arch)/%.asm
@mkdir -p $(shell dirname $@)
@nasm -felf64 $< -o $@
BIN
View File
Binary file not shown.
+128
View File
@@ -0,0 +1,128 @@
; Copyright 2015 Philipp Oppermann
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
; http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
global start
section .text
bits 32
start:
mov esp, stack_top
call check_multiboot
call check_cpuid
call check_long_mode
call setup_page_tables
call enable_paging
; print `OK` to screen
mov dword [0xb8000], 0x2f4b2f4f
hlt
setup_page_tables:
; 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 a huge page that starts at address 0
mov dword [p3_table], 0b10000011 ; present + writable + huge
ret
enable_paging:
; load P4 to cr3 register (cpu uses this to access 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
or eax, 1 << 16
mov cr0, eax
ret
; Prints `ERR: ` and the given error code to screen and hangs.
; parameter: error code (in ascii) in al
error:
mov dword [0xb8000], 0x4f524f45
mov dword [0xb8004], 0x4f3a4f52
mov dword [0xb8008], 0x4f204f20
mov byte [0xb800a], al
hlt
; Throw error 0 if eax doesn't contain the Multiboot 2 magic value (0x36d76289).
check_multiboot:
cmp eax, 0x36d76289
jne .no_multiboot
ret
.no_multiboot:
mov al, "0"
jmp error
; Throw error 1 if the CPU doesn't support the CPUID command.
check_cpuid:
pushfd ; Store the FLAGS-register.
pop eax ; Restore the A-register.
mov ecx, eax ; Set the C-register to the A-register.
xor eax, 1 << 21 ; Flip the ID-bit, which is bit 21.
push eax ; Store the A-register.
popfd ; Restore the FLAGS-register.
pushfd ; Store the FLAGS-register.
pop eax ; Restore the A-register.
push ecx ; Store the C-register.
popfd ; Restore the FLAGS-register.
xor eax, ecx ; Do a XOR-operation on the A-register and the C-register.
jz .no_cpuid ; The zero flag is set, no CPUID.
ret ; CPUID is available for use.
.no_cpuid:
mov al, "1"
jmp error
; Throw error 2 if the CPU doesn't support Long Mode.
check_long_mode:
mov eax, 0x80000000 ; Set the A-register to 0x80000000.
cpuid ; CPU identification.
cmp eax, 0x80000001 ; Compare the A-register with 0x80000001.
jb .no_long_mode ; It is less, there is no long mode.
mov eax, 0x80000000 ; Set the A-register to 0x80000000.
cpuid ; CPU identification.
cmp eax, 0x80000001 ; Compare the A-register with 0x80000001.
jb .no_long_mode ; It is less, there is no long mode.
ret
.no_long_mode:
mov al, "2"
jmp error
section .bss
align 4096
p4_table:
resb 4096
p3_table:
resb 4096
stack_bottom:
resb 64
stack_top:
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Executable
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
+189
View File
@@ -0,0 +1,189 @@
global start
extern long_mode_start
section .text
bits 32
start:
; move stack pointer register
mov esp, stack_top
call check_multiboot
call check_cpuid
call check_long_mode
call set_up_page_tables
call enable_paging
call set_up_SSE
lgdt [gdt64.pointer]
; update selectors
; data
mov ax, gdt64.data
mov ss, ax ; stack selector
mov ds, ax ; data selector
mov es, ax ; extra selector
; code
jmp gdt64.code:long_mode_start
; print "ERR: " and the given error code to screen and hang
error:
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
; 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 is not supported.
cmp eax, ecx
je .no_cpuid
ret
.no_cpuid:
mov al, "1"
jmp error
check_long_mode:
; test if extended processor info is available
mov eax, 0x80000000 ; implicit argument for cpuid
cpuid ; get highest supported argument
cmp eax, 0x80000001 ; it needs to be at least this value
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 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
; map each P2 entry to a huge 2MiB page
mov ecx, 0
.map_p2_table:
; map ecx-th P2 entry to a huge page that starts at address 2MiB*ecx
mov eax, 0x200000 ; 2MiB
mul ecx ; start address of ecx-th page
or eax, 0b10000011 ; present + writable + huge
mov [p2_table + ecx * 8], eax ; map ecx-th entry
inc ecx ; increase
cmp ecx, 512 ; if counter == 512, the whole P2 table is mapped
jne .map_p2_table
ret
enable_paging:
; load P4 to cr3 register (cpu uses this to access 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
; Check for SSE and enable it, if it's not supported throw error "a"
set_up_SSE:
; check for SSE
mov eax, 0x1
cpuid
test edx, 1<<25
jz .no_SSE
; enable SSE
mov eax, cr0
and ax, 0xFFFB ; clear coprocessor emulation CR0.EM
or ax, 0x2 ; set coprocessor monitoring CR0.MP
mov cr0, eax
mov eax, cr4
or ax, 3 << 9 ; set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time
mov cr4, eax
ret
.no_SSE:
mov al, "a"
jmp error
section .rodata
gdt64:
dq 0 ; zero entry
.code: equ $ - gdt64
dq (1 << 44) | (1 << 47) | (1 << 41) | (1 << 43) | (1 << 54) ; code segment
.data equ $ - gdt64
dq (1 << 44) | (1 << 47) | (1 << 41) ; data segment
.pointer:
dw $ - gdt64 - 1
dq gdt64
section .bss
align 4096
p4_table:
resb 4096
p3_table:
resb 4096
p2_table:
resb 4096
stack_bottom:
resb 64
stack_top:
+7
View File
@@ -0,0 +1,7 @@
set timeout=0
set default=0
menuentry "Mahdi OS :|" {
multiboot2 /boot/kernel.bin
boot
}
+16
View File
@@ -0,0 +1,16 @@
ENTRY(start)
SECTIONS {
. = 1M;
.boot :
{
/* ensure that the multiboot header is tat the beginning */
KEEP(*(.multiboot_header))
}
.text :
{
*(.text)
}
}
+16
View File
@@ -0,0 +1,16 @@
global long_mode_start
section .text
bits 64
long_mode_start:
extern rust_main
call rust_main
; rust main returned, print `OS returned!`
mov rax, 0x4f724f204f534f4f
mov [0xb8000], rax
mov rax, 0x4f724f754f744f65
mov [0xb8008], rax
mov rax, 0x4f214f644f654f6e
mov [0xb8010], rax
hlt
+14
View File
@@ -0,0 +1,14 @@
section .multiboot_header
header_start:
dd 0xe85250d6 ; magic number (multiboot 2)
dd 0 ; architecture 0 (protected mode i386)
dd header_end - header_start ; header length
dd 0x100000000 - (0xe85250d6 + 0 + (header_end - header_start)) ; checksum
; optional tags
; end tags
dw 0 ; type
dw 0 ; flags
dd 8 ; size
header_end:
+30
View File
@@ -0,0 +1,30 @@
#![feature(lang_items)]
#![no_std]
extern crate rlibc;
#[no_mangle]
pub extern fn rust_main() {
// ATTENTION: we have a very small stack and no guard page
let hello = b"Hello World!";
let color_byte = 0x1f; // white foreground, blue background
let mut hello_colored = [color_byte; 24];
for (i, char_byte) in hello.into_iter().enumerate() {
hello_colored[i*2] = *char_byte;
}
let buffer_ptr = (0xb8000 + 1988) as *mut _;
unsafe { *buffer_ptr = hello_colored };
loop {}
}
#[allow(non_snake_case)]
#[no_mangle]
pub extern "C" fn _Unwind_Resume() -> ! {
loop {}
}
#[lang = "eh_personality"] extern fn eh_personality() {}
#[lang = "panic_fmt"] extern fn panic_fmt() -> ! { loop {} }
View File
@@ -0,0 +1 @@
{"rustc":6621389328642914105,"target":6192930460042594332,"profile":10749699831569892475,"local":{"variant":"MtimeBased","fields":[[1466853811,226666665],[47,114,111,111,116,47,107,101,114,110,101,108,47,116,97,114,103,101,116,47,120,56,54,95,54,52,45,117,110,107,110,111,119,110,45,108,105,110,117,120,45,103,110,117,47,100,101,98,117,103,47,46,102,105,110,103,101,114,112,114,105,110,116,47,109,97,104,100,105,95,111,115,45,56,52,101,51,51,55,102,51,99,54,57,102,100,55,97,98,47,100,101,112,45,108,105,98,45,109,97,104,100,105,95,111,115]]},"features":"None","deps":[["rlibc v0.1.5",9884570034738440005]],"rustflags":[]}
@@ -0,0 +1 @@
45270e6e130c2d89
@@ -0,0 +1 @@
{"rustc":6621389328642914105,"target":9571294117447932849,"profile":10749699831569892475,"local":{"variant":"Precalculated","fields":["0.1.5"]},"features":"None","deps":[],"rustflags":[]}
Binary file not shown.
+16
View File
@@ -0,0 +1,16 @@
{
"llvm-target": "x86_64-unknown-none-gnu",
"target-endian": "little",
"target-pointer-width": "64",
"os": "none",
"arch": "x86_64",
"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",
"pre-link-args": ["-m64"],
"cpu": "x86-64",
"features": "-mmx,-sse,-sse2,-sse3,-ssse3",
"disable-redzone": true,
"eliminate-frame-pointer": false,
"linker-is-gnu": true,
"no-compiler-rt": true,
"archive-format": "gnu"
}