Compare commits
3 commits
d97ec36f8c
...
978fd36490
| Author | SHA1 | Date | |
|---|---|---|---|
| 978fd36490 | |||
| 8fadee6baf | |||
| b127a659bb |
6 changed files with 122 additions and 52 deletions
6
Makefile
6
Makefile
|
|
@ -1,7 +1,7 @@
|
||||||
###CONFIGURATION
|
###CONFIGURATION
|
||||||
ARCH := i686
|
ARCH := i686
|
||||||
CROSS := $(ARCH)-elf-
|
CROSS := $(ARCH)-elf-
|
||||||
AS := $(CROSS)as
|
AS := nasm
|
||||||
CC := $(CROSS)gcc
|
CC := $(CROSS)gcc
|
||||||
LD := $(CROSS)ld
|
LD := $(CROSS)ld
|
||||||
QEMU := qemu-system-i386
|
QEMU := qemu-system-i386
|
||||||
|
|
@ -9,6 +9,8 @@ INCLUDES:= include/
|
||||||
|
|
||||||
CFLAGS := -I $(INCLUDES) -O2 -Wall -Wextra -ffreestanding -nostdlib -lgcc -g
|
CFLAGS := -I $(INCLUDES) -O2 -Wall -Wextra -ffreestanding -nostdlib -lgcc -g
|
||||||
LDFLAGS := -T linker.ld -nostdlib
|
LDFLAGS := -T linker.ld -nostdlib
|
||||||
|
ASFLAGS := -f elf32
|
||||||
|
|
||||||
|
|
||||||
SRC_DIR := src
|
SRC_DIR := src
|
||||||
OBJ_DIR := obj
|
OBJ_DIR := obj
|
||||||
|
|
@ -39,7 +41,7 @@ $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
|
||||||
|
|
||||||
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.s
|
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.s
|
||||||
@mkdir -p $(dir $@)
|
@mkdir -p $(dir $@)
|
||||||
$(AS) $< -o $@
|
$(AS) $(ASFLAGS) $< -o $@
|
||||||
|
|
||||||
#Related targets
|
#Related targets
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,5 @@ SECTIONS
|
||||||
{
|
{
|
||||||
*(COMMON)
|
*(COMMON)
|
||||||
*(.bss)
|
*(.bss)
|
||||||
*(.tss_sect)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
56
src/gdt.s
Normal file
56
src/gdt.s
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
global gdtr
|
||||||
|
|
||||||
|
section .gdt_sect
|
||||||
|
gdt:
|
||||||
|
;Null descriptor
|
||||||
|
dd 0x00000000
|
||||||
|
dd 0x00000000
|
||||||
|
;Kernel code segment.
|
||||||
|
;Limit: in 4kib pages. 0xFFFFF * 4K = full address space.
|
||||||
|
dw 0xFFFF
|
||||||
|
;Base: Start at 0. We want the whole thing.
|
||||||
|
dw 0
|
||||||
|
;ALSO BASE: bits 16-23. All zeroes, still.
|
||||||
|
db 0
|
||||||
|
;Access byte. Defines flags for access permissions to the segment. This segment is:
|
||||||
|
;RX, and code/data segment
|
||||||
|
db 0b10011010
|
||||||
|
;Next two segments are nibbles so I put them together (cant db only a nibble at once).
|
||||||
|
;Upper limit bits (right hand nibble) is all ones to fill out the full 4gib in pages
|
||||||
|
;Flags (left hand nibble) are set to say that the limit is meant to be read as pages, and we're working in 32bit.
|
||||||
|
db 0b11001111
|
||||||
|
;Final upper base bits. Still zero lol.
|
||||||
|
db 0
|
||||||
|
;Done! Now we move onto our next table entries, they are back to back.
|
||||||
|
;Kernel Data Segment
|
||||||
|
dw 0xFFFF
|
||||||
|
dw 0
|
||||||
|
db 0
|
||||||
|
db 0b10010010
|
||||||
|
db 0b11001111
|
||||||
|
db 0
|
||||||
|
;User Code Segment
|
||||||
|
dw 0xFFFF
|
||||||
|
dw 0
|
||||||
|
db 0
|
||||||
|
db 0b11111010
|
||||||
|
db 0b11001111
|
||||||
|
db 0
|
||||||
|
;User Data Segment
|
||||||
|
dw 0xFFFF
|
||||||
|
dw 0
|
||||||
|
db 0
|
||||||
|
db 0b11110010
|
||||||
|
db 0b11001111
|
||||||
|
db 0
|
||||||
|
;Task State Segment
|
||||||
|
;For a lot of this it's going to be zeroes so we can do it dynamically later (such as finding &tss).
|
||||||
|
;Really, we just want to set the access bytes correctly.
|
||||||
|
dd 0
|
||||||
|
db 0
|
||||||
|
db 0b10001001
|
||||||
|
dw 0
|
||||||
|
gdtr:
|
||||||
|
dw gdtr - gdt - 1
|
||||||
|
dd gdt
|
||||||
|
|
||||||
|
|
@ -6,8 +6,13 @@
|
||||||
#include "kmultiboot.h"
|
#include "kmultiboot.h"
|
||||||
|
|
||||||
//finally, main.
|
//finally, main.
|
||||||
void kern_main(uint32_t multiboot_magic, multiboot_info_t* multiboot_info)
|
void kern_main(uint32_t multiboot_magic, mb_info_t* multiboot_info)
|
||||||
{
|
{
|
||||||
|
//Hello C! Let's get to work in cleaning up our environment a bit and creating some safety.
|
||||||
|
//First interrupts.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//wipe the screen
|
//wipe the screen
|
||||||
vga_clear();
|
vga_clear();
|
||||||
//We're going to use this buffer as our 8char hex representation for reading mem
|
//We're going to use this buffer as our 8char hex representation for reading mem
|
||||||
|
|
|
||||||
13
src/multiboot.s
Normal file
13
src/multiboot.s
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
;multiboot for GRUB to boot it. Ideally stage01_bootloader will be able to support the multiboot standard.
|
||||||
|
;regardless of who's doing it, we have to set the required stuff
|
||||||
|
MB_MAGIC equ 0x1BADB002 ; bytes that bootloader will use to find this place
|
||||||
|
MB_FLAGS equ (1 << 0) | (1 << 1) ; flags request the following from the bootloader: maintain page boundaries + provide a memory map
|
||||||
|
MB_CHECKSUM equ (0 - (MB_MAGIC + MB_FLAGS)) ; Fails if checksum doesn't pass. Kind of arbitrary, but required.
|
||||||
|
|
||||||
|
|
||||||
|
;Now we actually place the multiboot stuff into the resulting executable...
|
||||||
|
section .multiboot align=4
|
||||||
|
dd MB_MAGIC
|
||||||
|
dd MB_FLAGS
|
||||||
|
dd MB_CHECKSUM
|
||||||
|
|
||||||
91
src/start.s
91
src/start.s
|
|
@ -1,60 +1,55 @@
|
||||||
//C main function for our kernel
|
; Bootloader places us in 32 bit mode :)
|
||||||
//See: kernel.c
|
bits 32
|
||||||
.extern kern_main
|
;Some symbols we'll need from other files...
|
||||||
//This will be our entrypoint function name - gotta initialize it now as global so the linker knows later.
|
extern kern_main
|
||||||
.global start
|
extern gdtr
|
||||||
|
;This will be our entrypoint function name - gotta initialize it now as global so the linker knows later.
|
||||||
|
global start
|
||||||
|
|
||||||
|
|
||||||
//multiboot for GRUB to boot it. Ideally stage01_bootloader will be able to support the multiboot standard.
|
; Set up for C code. Practically the only requirement for C-generated assembly to work properly is alignment and the presence of a stack.
|
||||||
//regardless of who's doing it, we have to set the required stuff
|
section .bss align=16
|
||||||
.set MB_MAGIC, 0x1BADB002 // bytes that bootloader will use to find this place
|
|
||||||
.set MB_FLAGS, (1 << 0) | (1 << 1) // flags request the following from the bootloader: maintain page boundaries + provide a memory map
|
|
||||||
.set MB_CHECKSUM, (0 - (MB_MAGIC + MB_FLAGS)) // Fails if checksum doesn't pass. Kind of arbitrary, but required.
|
|
||||||
|
|
||||||
|
|
||||||
//Now we actually place the multiboot stuff into the resulting executable...
|
|
||||||
.section .multiboot
|
|
||||||
.align 4 // 4 byte alignment
|
|
||||||
.long MB_MAGIC
|
|
||||||
.long MB_FLAGS
|
|
||||||
.long MB_CHECKSUM
|
|
||||||
|
|
||||||
// Set up for C code. Practically the only requirement for C-generated assembly to work properly is alignment and the presence of a stack.
|
|
||||||
.section .bss
|
|
||||||
.align 16
|
|
||||||
stack_bottom:
|
stack_bottom:
|
||||||
.skip 4096 // 4096 bytes (4kb) large stack. by skipping some amount of data (and eventually filling it with zeroes?), we've essentially just reserved space for our stack.
|
resb 4096 ; 4096 bytes (4kb) large stack. by skipping some amount of data (and eventually filling it with zeroes?), we've essentially just reserved space for our stack.
|
||||||
//Remember, stack grows DOWNWARD! So the last thing in the section -> the highest memory address -> the very first thing on the stack!
|
;Remember, stack grows DOWNWARD! So the last thing in the section -> the highest memory address -> the very first thing on the stack!
|
||||||
//Therefore, we put a label here to represent the top of our stack for later.
|
;Therefore, we put a label here to represent the top of our stack for later.
|
||||||
stack_top:
|
stack_top:
|
||||||
//Allocation of some space for our TSS.
|
;We're gonna throw the TSS here too.
|
||||||
|
|
||||||
|
|
||||||
.section .tss_sect:
|
|
||||||
.align 8
|
|
||||||
tss:
|
tss:
|
||||||
.skip 104
|
resb 104
|
||||||
|
|
||||||
.section .gdt_sect:
|
|
||||||
.align 8
|
|
||||||
gdt:
|
|
||||||
.skip 48
|
|
||||||
|
|
||||||
|
;Actual code. Entry point goes here!
|
||||||
//Actual code. Entry point goes here!
|
section .text
|
||||||
.section .text
|
;Here it is!
|
||||||
//Here it is!
|
|
||||||
start:
|
start:
|
||||||
//Lets set up the stack. Stack grows downward on x86. We did the work earlier of defining where the top of the stack is, so just tell esp.
|
;We made a GDT! Let's use it!
|
||||||
mov $stack_top, %esp //set the stack pointer
|
lgdt [gdtr]
|
||||||
pushl %ebx
|
;Now we start by setting the code segment (CS) with a far jump...
|
||||||
pushl %eax
|
jmp 0x08:segment_be_gone
|
||||||
//To C-land!
|
|
||||||
|
|
||||||
|
segment_be_gone:
|
||||||
|
;Now we go ahead and dump our kernel mode data segment (0x10) into the rest of our segments.
|
||||||
|
;Also preserving eax because it has the bootloader's multiboot magic in it and I want to check it in main.
|
||||||
|
mov cx, 0x10
|
||||||
|
mov ds, cx
|
||||||
|
mov es, cx
|
||||||
|
mov ss, cx
|
||||||
|
mov fs, cx
|
||||||
|
mov gs, cx
|
||||||
|
;Lets set up the stack. Stack grows downward on x86. We did the work earlier of defining where the top of the stack is, so just tell esp.
|
||||||
|
mov esp, stack_top ;set the stack pointer
|
||||||
|
push ebx
|
||||||
|
push eax
|
||||||
|
;To C-land!
|
||||||
call kern_main
|
call kern_main
|
||||||
|
|
||||||
//You should never get here, but in case you do, we will just hang.
|
;You should never get here, but in case you do, we will just hang.
|
||||||
hang:
|
hang:
|
||||||
cli //Interrupts: off
|
cli ;Interrupts: off
|
||||||
hlt //Halt!
|
hlt ;Halt!
|
||||||
jmp hang //just in case...
|
jmp hang ;just in case...
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue