-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
98 changed files
with
8,083 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
bochs = bochs | ||
qemu = qemu-system-x86_64 | ||
qemu-img = qemu-img | ||
make = make | ||
gpp = g++ --std=c++11 | ||
|
||
bootsector/bootsector.bin : FORCE | ||
$(make) -C bootsector bootsector.bin | ||
|
||
bootloader/bootloader.bin : FORCE | ||
$(make) -C bootloader bootloader.bin | ||
|
||
image.bin : bootsector/bootsector.bin bootloader/bootloader.bin | ||
copy bootsector\bootsector.bin /b + bootloader\bootloader.bin /b $@ /b | ||
|
||
# On linux, 'truncate' can be used instead | ||
extend_file.exe : extend_file.cpp | ||
$(gpp) $< -o $@ | ||
|
||
harddisk.img : image.bin extend_file.exe | ||
copy $< $@ | ||
extend_file.exe $@ 10321920 | ||
|
||
sim : harddisk.img cerius.bxrc | ||
$(bochs) -f cerius.bxrc -q | ||
|
||
simqemu: harddisk.img | ||
$(qemu) -drive file=harddisk.img,format=raw -m 512M | ||
|
||
simqemuahci: harddisk.img | ||
$(qemu) -device ahci,id=ahci0 -drive if=none,file=harddisk.img,format=raw,id=drive -device ide-drive,bus=ahci0.0,drive=drive,id=sata0-0-0 -m 512M | ||
|
||
harddisk.vmdk: harddisk.img | ||
$(qemu-img) convert -O vmdk $< $@ | ||
|
||
clear : FORCE | ||
$(make) -C bootsector clear | ||
$(make) -C bootloader clear | ||
del image.bin | ||
del harddisk.img | ||
del harddisk.vmdk | ||
del extend_file.exe | ||
|
||
FORCE: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# TODO: Can we get 'make' to search these directories recursively for C++ files? | ||
MEMORY_SRC_DIRS = $(wildcard memory/*) | ||
SRC_DIRS = drivers drivers/Ata common interrupt tests $(MEMORY_SRC_DIRS) | ||
C_SOURCES = $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.cpp)) | ||
C_OBJS = ${C_SOURCES:.cpp=.o} | ||
ASM_DIRS = asm interrupt | ||
ASM_SOURCES = $(foreach dir,$(ASM_DIRS),$(wildcard $(dir)/*.asm)) | ||
ASM_OBJS = ${ASM_SOURCES:.asm=.o} | ||
|
||
nasm = nasm | ||
# -fno-rtti : Disables runtime type identification, i.e., dynamic_cast | ||
# -fno-exceptions: Disables exceptions and all the related crazyness. | ||
gpp = g++ -fno-rtti -fno-exceptions -nostdlib -ffreestanding -fno-use-cxa-atexit --std=c++11 -I. -Icommon | ||
ld = ld | ||
|
||
bit16/bootloader_16bit_stage.bin : bit16/bootloader_16bit_stage.asm bit16/*.asm | ||
$(nasm) $< -f bin -o $@ -Wall | ||
|
||
bootloader_64bit_stage.o : bootloader_64bit_stage.cpp | ||
$(gpp) -c $< -o $@ | ||
|
||
bootloader_64bit_stage_caller.elf : bootloader_64bit_stage_caller.asm | ||
$(nasm) $< -f elf64 -o $@ -Wall | ||
|
||
bootloader_64bit_stage_with_caller.pe : mylinkscript.txt bootloader_64bit_stage.o bootloader_64bit_stage_caller.elf $(C_OBJS) $(ASM_OBJS) | ||
$(ld) -T $< -o $@ $(filter-out $<,$^) | ||
|
||
bootloader_64bit_stage_with_caller.bin : bootloader_64bit_stage_with_caller.pe | ||
objcopy -O binary $< $@ | ||
|
||
bootloader.bin : bit16/bootloader_16bit_stage.bin bootloader_64bit_stage_with_caller.bin | ||
copy bit16\bootloader_16bit_stage.bin /b + bootloader_64bit_stage_with_caller.bin /b $@ /b | ||
|
||
$(C_OBJS) : %.o : %.cpp | ||
$(gpp) -c $< -o $@ | ||
|
||
$(ASM_OBJS) : %.o : %.asm | ||
$(nasm) $< -f elf64 -o $@ -Wall | ||
|
||
clear : | ||
$(foreach dir,$(SRC_DIRS), $(shell del "$(dir)\*.o")) | ||
del bit16\*.bin | ||
del asm\*.o | ||
del *.bin | ||
del *.elf | ||
del *.pe | ||
del *.o | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
[BITS 64] | ||
global MoveStack | ||
|
||
MoveStack: | ||
sub rbp, rsp | ||
add rbp, rdi | ||
mov rcx, rsi | ||
mov rsi, rsp | ||
mov rdi, rdi | ||
mov rsp, rdi | ||
rep movsb | ||
ret |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#ifndef MOVESTACK_H | ||
#define MOVESTACK_H | ||
|
||
// Moves the stack to specified location. Changes rbp such that rbp-rsp will not change. | ||
// Copies the first *stackMoveSize* many bytes from the old stack into the new stack. | ||
// Since this function isn't smart enough to change stack-relative pointers that currently exist on the stack (rbp's in particular), it needs to be called directly from bootloader_64bit_stage | ||
extern "C" __attribute((sysv_abi)) void MoveStack(void* newStackTop, uint64_t stackMoveSize); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
[bits 16] | ||
|
||
; uint64_t adjust_page_table(uint32_t initReserveLower, uint32_t initReserveHigher); | ||
|
||
; Identity maps the first megabyte and the given initial reserve with kernel-exclusive read-write access. | ||
; Note that initReserveLower/Higher are physical addresses which contain 2mb of usable memory. | ||
; Sets eax to the lower half of the linear address of the 2mb-long initial reserve | ||
; Sets ebx to the higher half | ||
|
||
adjust_page_table: | ||
push bp | ||
mov bp, sp | ||
; Initialize the first entry of PML4 | ||
mov ebx, paging64.pml4 | ||
mov dword [ebx], paging64.pdpt | ||
or dword [ebx], 3 | ||
mov dword [ebx+4096], paging64.pdpt | ||
; Initialize the first entry of PDPT | ||
mov ebx, paging64.pdpt | ||
mov dword [ebx], paging64.pd | ||
or dword [ebx], 3 | ||
mov dword [ebx+4096], paging64.pd | ||
; Initialize the first entry of PD | ||
mov ebx, paging64.pd | ||
mov dword [ebx], paging64.pt | ||
or dword [ebx], 3 | ||
mov dword [ebx+4096], paging64.pt | ||
; Initialize the relevant part of PT | ||
; eax : current physical address to map, ebx: current physical address of current PT entry, ecx: number of PT entries initialized so far | ||
mov eax, 0 | ||
mov ecx, 0 | ||
mov ebx, paging64.pt | ||
.pt_loop_begin: | ||
cmp ecx, 256 ; 1 mb = 256 * 4kb | ||
jae .pt_loop_end | ||
mov edx, eax | ||
or edx, 11b | ||
mov [ebx], edx | ||
;mov [ebx+4096], edx ; We don't need to set the linear fields for PT entries, because they don't have any child. | ||
add eax, 4096 ; 4kb | ||
add ebx, 8 | ||
inc ecx | ||
jmp .pt_loop_begin | ||
.pt_loop_end: | ||
mov eax, [bp+4] ; Page in the initial reserve | ||
mov ebx, [bp+8] | ||
or eax, 10000011b ; Present, writable, pagesize | ||
mov [paging64.pd+8], eax | ||
mov [paging64.pd+12], ebx ; No need to initialize the lin field of the entry because it maps a page, because it has pagesize bit set. | ||
mov eax, 2*1024*1024 ; TODO: Randomize the linear address of the initial reserve. | ||
xor ebx, ebx | ||
leave | ||
ret 8 | ||
|
||
paging64: | ||
times 4096-(($-$$+0x7E00) % 4096) db 0 ; 4kb alignment | ||
.pml4: | ||
times 512 dq 0 ; This is the format expected by 64bit Pager | ||
times 512 dq 0 | ||
.pdpt: | ||
times 512 dq 0 | ||
times 512 dq 0 | ||
.pd: | ||
times 512 dq 0 | ||
times 512 dq 0 | ||
.pt: | ||
times 512 dq 0 | ||
times 512 dq 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
[bits 16] | ||
[org 0x7E00] ; Bootsector jmp's to 0x7E00 after it loads the bootloader into the memory | ||
|
||
mov sp, 0x7C00 ; Addresses 0x7C00 through 0x7E00 is reserved for the SMAP. Stack starts at 0x7C00 and grows downwards. | ||
mov bp,sp | ||
|
||
sub sp, 10 ; word [bp-2] : Number of SMAP entries as returned by detect_mem function. | ||
; dword [bp-6] : Initial reserve linear address, as mapped by adjust_page_table (higher bits) | ||
; dword [bp-10] : Initial reserve linear address, as mapped by adjust_page_table (lower bits) | ||
|
||
mov bx, TESTING_A20_MSG | ||
call print_string | ||
call test_a20 | ||
test ax, ax | ||
jnz a20_enabled | ||
mov bx, ENABLING_A20_MSG | ||
call print_string | ||
call enable_a20 | ||
mov bx, TESTING_A20_MSG | ||
call print_string | ||
call test_a20 | ||
test ax, ax | ||
jz a20_cannot_enable | ||
a20_enabled: | ||
mov bx, A20_ENABLED_MSG | ||
call print_string | ||
mov bx, DETECTING_CAPABILITIES_MSG | ||
call print_string | ||
call detect_capabilities | ||
test eax, eax | ||
jz missing_capabilities | ||
mov bx, DETECTING_MEMORY_MSG | ||
call print_string | ||
|
||
push 32 ; We have 512 bytes reserved for the SMAP. Since each entry is 16 bytes long, that gives us a maximum of 32 entries. | ||
push 0x7C00; | ||
call detect_mem | ||
cmp ax, 0 | ||
je smap_failed | ||
mov word [bp-2], ax | ||
push ax | ||
push 0x7C00 | ||
call find_place_for_initial_reserve | ||
mov ecx, eax | ||
or ecx, ebx | ||
test ecx, ecx | ||
jz no_initial_reserve_found | ||
push ebx ; We need not remember the physical address of the initial reserve | ||
push eax | ||
call adjust_page_table | ||
mov dword [bp-6], ebx | ||
mov dword [bp-10], eax | ||
jmp switch_64 | ||
[bits 64] | ||
long_mode_begin: | ||
mov rdi, paging64.pml4 | ||
mov rsi, 0x7C00 | ||
movzx rdx, word [rbp-2] | ||
mov rcx, qword [rbp-10] | ||
mov r8, 2*1024*1024 | ||
add sp, 10 | ||
call STAGE64_BEGIN ; bootloader_64bit_stage(paging64.pml4, smap, smap_length, initialreservestart, initialreservelength) | ||
cli ; If the kernel returns, shut the cpu down. | ||
hlt | ||
|
||
|
||
[BITS 16] | ||
|
||
a20_cannot_enable: | ||
mov bx, A20_CANNOT_ENABLE_MSG | ||
call print_string | ||
jmp hang | ||
|
||
missing_capabilities: | ||
mov bx, MISSING_CAPABILITIES_MSG | ||
call print_string | ||
jmp hang | ||
|
||
smap_failed: | ||
mov bx, SMAP_FAILED_MSG | ||
call print_string | ||
jmp hang | ||
|
||
no_initial_reserve_found: | ||
mov bx, NO_INITIAL_RESERVE_MSG | ||
call print_string | ||
jmp hang | ||
|
||
hang: | ||
cli | ||
hlt | ||
jmp hang | ||
|
||
|
||
; Constants | ||
TESTING_A20_MSG: db 'Testing if A20 line is enabled...', 0 | ||
ENABLING_A20_MSG: db 'Enabling A20 line...', 0 | ||
A20_ENABLED_MSG: db 'A20 line is enabled.', 0 | ||
A20_CANNOT_ENABLE_MSG: db 'Cannot enable A20 line. Hanging...', 0 | ||
DETECTING_CAPABILITIES_MSG: db 'Checking CPU capabilities...', 0 | ||
DETECTING_MEMORY_MSG: db 'Detecting memory...', 0 | ||
SMAP_FAILED_MSG: db 'Smap failed. Hanging...', 0 | ||
MISSING_CAPABILITIES_MSG: db 'No support for CPUID, long mode or SSE2. Hanging...', 0 | ||
NO_INITIAL_RESERVE_MSG: db 'No suitable range for the initial memory reserve was found. Hanging...', 0 | ||
|
||
; Constants | ||
STAGE64_BEGIN equ 0x11E00 ; Linking 16-bit and 64-bit code together seems to confuse the linker. To avoid linking the 16-bit stage with the rest of the bootloader, we jump to a specific address in memory once we switch from 16-bit mode to 64-bit mode. We also tell the linker to put a "jmp" instruction to that address, which jumps to the actual entry point of the 64-bit stage. | ||
|
||
|
||
%include "bit16/print_string.asm" ; NASM is weird and searches for these includes in its cd, instead of the directory of the code. | ||
%include "bit16/test_a20.asm" | ||
%include "bit16/enable_a20.asm" | ||
%include "bit16/print_hex.asm" | ||
%include "bit16/detect_capabilities.asm" | ||
%include "bit16/detect_mem.asm" | ||
%include "bit16/initial_reserve.asm" | ||
%include "bit16/switch_64.asm" | ||
%include "bit16/adjust_page_table.asm" | ||
|
||
times (STAGE64_BEGIN-0x7E00)-($-$$) db 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
[BITS 16] | ||
|
||
detect_capabilities: | ||
call detect_cpuid | ||
test eax, eax | ||
jz .fail | ||
|
||
call detect_long_mode | ||
test eax, eax | ||
jz .fail | ||
|
||
call detect_sse2 | ||
test eax, eax | ||
jz .fail | ||
|
||
mov eax, 1 | ||
ret | ||
|
||
.fail: | ||
xor eax, eax | ||
ret | ||
|
||
%include "bit16/detect_cpuid.asm" | ||
%include "bit16/detect_long_mode.asm" | ||
%include "bit16/detect_sse2.asm" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
[bits 16] | ||
|
||
; From : http://wiki.osdev.org/Setting_Up_Long_Mode | ||
|
||
detect_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. | ||
xor eax, ecx | ||
|
||
ret |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
[bits 16] | ||
|
||
; From : http://wiki.osdev.org/Setting_Up_Long_Mode | ||
|
||
detect_long_mode: | ||
mov eax, 0x80000000 ; Set the A-register to 0x80000000. | ||
cpuid ; CPU identification. | ||
cmp eax, 0x80000001 ; Compare the A-register with 0x80000001. | ||
jb .fail ; It is less, there is no long mode. | ||
mov eax, 0x80000001 ; Set the A-register to 0x80000001. | ||
cpuid ; CPU identification. | ||
test edx, 1 << 29 ; Test if the LM-bit, which is bit 29, is set in the D-register. | ||
jz .fail ; They aren't, there is no long mode. | ||
mov eax, 1 | ||
ret | ||
|
||
.fail: | ||
xor eax, eax | ||
ret |
Oops, something went wrong.