Compare commits
No commits in common. "978fd364906c82a3c0687c79f5651da8503bc526" and "d97ec36f8c86036b0378e9e900a2c93286b08cd5" have entirely different histories.
978fd36490
...
d97ec36f8c
6 changed files with 52 additions and 122 deletions
6
Makefile
6
Makefile
|
|
@ -1,7 +1,7 @@
|
||||||
###CONFIGURATION
|
###CONFIGURATION
|
||||||
ARCH := i686
|
ARCH := i686
|
||||||
CROSS := $(ARCH)-elf-
|
CROSS := $(ARCH)-elf-
|
||||||
AS := nasm
|
AS := $(CROSS)as
|
||||||
CC := $(CROSS)gcc
|
CC := $(CROSS)gcc
|
||||||
LD := $(CROSS)ld
|
LD := $(CROSS)ld
|
||||||
QEMU := qemu-system-i386
|
QEMU := qemu-system-i386
|
||||||
|
|
@ -9,8 +9,6 @@ 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
|
||||||
|
|
@ -41,7 +39,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) $(ASFLAGS) $< -o $@
|
$(AS) $< -o $@
|
||||||
|
|
||||||
#Related targets
|
#Related targets
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,5 +34,6 @@ SECTIONS
|
||||||
{
|
{
|
||||||
*(COMMON)
|
*(COMMON)
|
||||||
*(.bss)
|
*(.bss)
|
||||||
|
*(.tss_sect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
56
src/gdt.s
56
src/gdt.s
|
|
@ -1,56 +0,0 @@
|
||||||
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,13 +6,8 @@
|
||||||
#include "kmultiboot.h"
|
#include "kmultiboot.h"
|
||||||
|
|
||||||
//finally, main.
|
//finally, main.
|
||||||
void kern_main(uint32_t multiboot_magic, mb_info_t* multiboot_info)
|
void kern_main(uint32_t multiboot_magic, multiboot_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
|
||||||
|
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
;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,55 +1,60 @@
|
||||||
; Bootloader places us in 32 bit mode :)
|
//C main function for our kernel
|
||||||
bits 32
|
//See: kernel.c
|
||||||
;Some symbols we'll need from other files...
|
.extern kern_main
|
||||||
extern kern_main
|
//This will be our entrypoint function name - gotta initialize it now as global so the linker knows later.
|
||||||
extern gdtr
|
.global start
|
||||||
;This will be our entrypoint function name - gotta initialize it now as global so the linker knows later.
|
|
||||||
global start
|
|
||||||
|
|
||||||
|
|
||||||
; Set up for C code. Practically the only requirement for C-generated assembly to work properly is alignment and the presence of a stack.
|
//multiboot for GRUB to boot it. Ideally stage01_bootloader will be able to support the multiboot standard.
|
||||||
section .bss align=16
|
//regardless of who's doing it, we have to set the required stuff
|
||||||
|
.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:
|
||||||
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.
|
.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.
|
||||||
;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:
|
||||||
;We're gonna throw the TSS here too.
|
//Allocation of some space for our TSS.
|
||||||
|
|
||||||
|
|
||||||
|
.section .tss_sect:
|
||||||
|
.align 8
|
||||||
tss:
|
tss:
|
||||||
resb 104
|
.skip 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:
|
||||||
;We made a GDT! Let's use it!
|
//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.
|
||||||
lgdt [gdtr]
|
mov $stack_top, %esp //set the stack pointer
|
||||||
;Now we start by setting the code segment (CS) with a far jump...
|
pushl %ebx
|
||||||
jmp 0x08:segment_be_gone
|
pushl %eax
|
||||||
|
//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