Skip to content
Permalink
Browse files

Add files via upload

  • Loading branch information...
mstniy committed Jan 26, 2018
1 parent 165d1c1 commit 6e4a7f3b28c2e61ecfc9cda87a8f3c642477a39c
Showing with 8,083 additions and 0 deletions.
  1. +44 −0 Makefile
  2. +48 −0 bootloader/Makefile
  3. +12 −0 bootloader/asm/movestack.asm
  4. +9 −0 bootloader/asm/movestack.h
  5. +68 −0 bootloader/bit16/adjust_page_table.asm
  6. +120 −0 bootloader/bit16/bootloader_16bit_stage.asm
  7. +25 −0 bootloader/bit16/detect_capabilities.asm
  8. +35 −0 bootloader/bit16/detect_cpuid.asm
  9. +20 −0 bootloader/bit16/detect_long_mode.asm
  10. +109 −0 bootloader/bit16/detect_mem.asm
  11. +15 −0 bootloader/bit16/detect_sse2.asm
  12. +46 −0 bootloader/bit16/enable_a20.asm
  13. +60 −0 bootloader/bit16/initial_reserve.asm
  14. +85 −0 bootloader/bit16/print_hex.asm
  15. +34 −0 bootloader/bit16/print_string.asm
  16. +101 −0 bootloader/bit16/switch_64.asm
  17. +55 −0 bootloader/bit16/test_a20.asm
  18. +72 −0 bootloader/bootloader_64bit_stage.cpp
  19. +5 −0 bootloader/bootloader_64bit_stage_caller.asm
  20. +26 −0 bootloader/common/RangePair.cpp
  21. +20 −0 bootloader/common/RangePair.h
  22. +15 −0 bootloader/common/kassert.cpp
  23. +10 −0 bootloader/common/kassert.h
  24. +44 −0 bootloader/common/kout.cpp
  25. +22 −0 bootloader/common/kout.h
  26. +37 −0 bootloader/common/port_io.cpp
  27. +20 −0 bootloader/common/port_io.h
  28. +7 −0 bootloader/common/stuff.cpp
  29. +15 −0 bootloader/common/type.h
  30. +22 −0 bootloader/common/utils.cpp
  31. +31 −0 bootloader/common/utils.h
  32. +1 −0 bootloader/disasm.bat
  33. +362 −0 bootloader/drivers/Ata/Ahci.cpp
  34. +60 −0 bootloader/drivers/Ata/Ahci.h
  35. +112 −0 bootloader/drivers/Ata/AhciDefs.h
  36. +35 −0 bootloader/drivers/Ata/AtaDefs.h
  37. +168 −0 bootloader/drivers/Ata/Ide.cpp
  38. +29 −0 bootloader/drivers/Ata/Ide.h
  39. +34 −0 bootloader/drivers/Ata/IdeDefs.h
  40. +109 −0 bootloader/drivers/Ata/SataDefs.h
  41. +13 −0 bootloader/drivers/Disk.h
  42. +73 −0 bootloader/drivers/Gpt.cpp
  43. +39 −0 bootloader/drivers/Gpt.h
  44. +237 −0 bootloader/drivers/display8025_col.cpp
  45. +20 −0 bootloader/drivers/display8025_col.h
  46. +38 −0 bootloader/drivers/mbr.cpp
  47. +28 −0 bootloader/drivers/mbr.h
  48. +143 −0 bootloader/drivers/pci.cpp
  49. +29 −0 bootloader/drivers/pci.h
  50. +48 −0 bootloader/drivers/ps2kbd.cpp
  51. +17 −0 bootloader/drivers/ps2kbd.h
  52. +489 −0 bootloader/interrupt/interrupt.cpp
  53. +55 −0 bootloader/interrupt/interrupt.h
  54. +1,624 −0 bootloader/interrupt/pre_handlers.asm
  55. +61 −0 bootloader/memory/AddressSpaceManager/AddressSpaceManager.cpp
  56. +34 −0 bootloader/memory/AddressSpaceManager/AddressSpaceManager.h
  57. +156 −0 bootloader/memory/AslrTree/AslrEntry.cpp
  58. +35 −0 bootloader/memory/AslrTree/AslrEntry.h
  59. +28 −0 bootloader/memory/AslrTree/AslrTree.cpp
  60. +22 −0 bootloader/memory/AslrTree/AslrTree.h
  61. +38 −0 bootloader/memory/AvlTree/AvlEntry.h
  62. +220 −0 bootloader/memory/AvlTree/AvlEntry.hpp
  63. +32 −0 bootloader/memory/AvlTree/AvlTree.h
  64. +67 −0 bootloader/memory/AvlTree/AvlTree.hpp
  65. +291 −0 bootloader/memory/Heap/Heap.cpp
  66. +74 −0 bootloader/memory/Heap/Heap.h
  67. +76 −0 bootloader/memory/Initializer/MemoryManagerInitializer.cpp
  68. +40 −0 bootloader/memory/Initializer/MemoryManagerInitializer.h
  69. +32 −0 bootloader/memory/LinearSpaceManager/LinearSpaceManager.cpp
  70. +22 −0 bootloader/memory/LinearSpaceManager/LinearSpaceManager.h
  71. +39 −0 bootloader/memory/MemoryManager/MemoryManager.cpp
  72. +24 −0 bootloader/memory/MemoryManager/MemoryManager.h
  73. +192 −0 bootloader/memory/Pager/Pager.cpp
  74. +54 −0 bootloader/memory/Pager/Pager.h
  75. +37 −0 bootloader/memory/PhysicalSpaceManager/PhysicalSpaceManager.cpp
  76. +22 −0 bootloader/memory/PhysicalSpaceManager/PhysicalSpaceManager.h
  77. +37 −0 bootloader/memory/PrimitiveHeap/BitmapHelper.cpp
  78. +11 −0 bootloader/memory/PrimitiveHeap/BitmapHelper.h
  79. +246 −0 bootloader/memory/PrimitiveHeap/PrimitiveHeap.cpp
  80. +66 −0 bootloader/memory/PrimitiveHeap/PrimitiveHeap.h
  81. +26 −0 bootloader/memory/Reserve/MemoryReserveManager.cpp
  82. +33 −0 bootloader/memory/Reserve/MemoryReserveManager.h
  83. +13 −0 bootloader/mylinkscript.txt
  84. +35 −0 bootloader/shared_ptr/shared_ptr.h
  85. +131 −0 bootloader/shared_ptr/shared_ptr.hpp
  86. +33 −0 bootloader/shared_ptr/unique_ptr.h
  87. +91 −0 bootloader/shared_ptr/unique_ptr.hpp
  88. +229 −0 bootloader/tests/HeapTests.cpp
  89. +38 −0 bootloader/tests/MemoryTests.cpp
  90. +84 −0 bootloader/tests/StorageTest.cpp
  91. +9 −0 bootloader/tests/Tests.h
  92. +15 −0 bootsector/Makefile
  93. +58 −0 bootsector/bootsector.asm
  94. +164 −0 bootsector/disk_load.asm
  95. +50 −0 bootsector/print_hex.asm
  96. +15 −0 bootsector/print_string.asm
  97. +11 −0 bootsector/utils.asm
  98. +97 −0 extend_file.cpp
@@ -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:
@@ -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

@@ -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
@@ -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
@@ -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
@@ -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
@@ -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"
@@ -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
@@ -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

0 comments on commit 6e4a7f3

Please sign in to comment.
You can’t perform that action at this time.