This commit is contained in:
secXsQuared 2018-11-09 00:24:22 -05:00
parent dab0070369
commit bc32a1f2fa
14 changed files with 381 additions and 95 deletions

1
.gitignore vendored
View File

@ -1 +0,0 @@
.idea

View File

@ -1,34 +0,0 @@
void kprintstr(char* str);
void khang();
/* HACK. kmain has to come first because of flat binary */
void kmain(void)
{
char* k_msg = "Hello world from 32-bit C kernel!";
kprintstr(k_msg);
khang();
}
void kprintstr(char* str)
{
/* last line of 80x25 */
char* ch = (char*)0xb8000 + 2 * 80 * 22;
while(*str)
{
*ch = *str;
ch++;
*ch = 0xf; /* white character */
ch++;
str++;
}
return;
}
void khang()
{
while(1)
{
}
}

11
src/addr.inc Normal file
View File

@ -0,0 +1,11 @@
STAGE2_BASE equ 0x8000
STAGE2_OFFSET equ 0x0
STAGE2_FLAT equ (STAGE2_BASE * 0x10) + STAGE2_OFFSET
STAGE3_BASE equ 0x1000
STAGE3_OFFSET equ 0
STAGE3_FLAT equ (STAGE3_BASE * 0x10) + STAGE3_OFFSET
KERNEL_BASE equ 0x4000
KERNEL_OFFSET equ 0
KERNEL_FLAT equ (KERNEL_BASE * 0x10) + KERNEL_OFFSET

54
src/kernel.c Normal file
View File

@ -0,0 +1,54 @@
void kprintstr(char* str);
void khang();
void kdelay(int mills);
/* HACK. kmain has to come first because of flat binary */
void kmain(void)
{
char* k_msg = "Hello world from 32-bit C kernel!"; /*33 characters*/
kprintstr(k_msg);
}
void kdelay(int millis)
{
for(int i = 0; i < millis; i++)
{
for(int j = 0; j < millis; j++)
{
}
}
}
void kprintstr(char* str)
{
/* 80x25 */
char* ch = (char*)0xb8000 + 2 * 80 * 21;
char color = 0xF;
char swap[] = {'|','\\', '/', '\\', '/', '|', '|'};
while(*str)
{
*ch = *str;
ch++;
*ch = color; /* white character */
ch++;
str++;
}
ch = (char*)0xb8000 + 2 * 80 * 22;
while(1)
{
int i = 0;
while(1)
{
/*display 10 characters doing*/
for(int j = 0; j < 80 * 3; j++)
{
*(ch + j * 2) = swap[(i * 1337 + j * 33 ) % 3];
*(ch + j * 2+ 1) = color;
color = (color + 1) % 0xF;
}
kdelay(5000);
i++;
}
}
}

View File

@ -6,7 +6,7 @@ ASM_FLAGS=-f bin -o
CFLAGS=-ffreestanding -m32 -target i386-pc-none-elf -c -Wall -Wextra -Werror -mno-red-zone -std=c17 -o
STAGE1_TARGET=stage1.bin
ASM_TARGET=stage2.bin stage1.bin
ASM_TARGET=stage2.bin stage1.bin stage3.bin
TARGET_DIR=out
all : createdir $(ASM_TARGET) kernel.bin image

122
src/print32.lib Normal file
View File

@ -0,0 +1,122 @@
; global position for vram
vb_pos: dd 0
;;;;;;;;;;;;;;;;;;;;;
;print a 32-bit integer
; input: push u32
;;;;;;;;;;;;;;;;;;;;;;
print_u32:
push ebp
mov ebp, esp
push eax
push ebx
push ecx
; loop 4 times
mov ebx, 8
mov ecx, 32 - 4
.lp:
; eax = thing to print
mov eax, dword [ebp + 2 * 4]
shr eax, cl
and eax, 0xF
call al_to_char
call print_char
sub ecx, 4
dec ebx
test ebx, ebx
jne .lp
pop ecx
pop ebx
pop eax
pop ebp
ret
;;;;;;;;;;;;;;;;;;;;;
;print a char in
;;;;;;;;;;;;;;;;;;;;;;
print_char:
; input: al = char
push edi
push eax
push esi
push ecx
; esi points to current frame buffer
mov esi, 0xb8000
; edi points to offset
mov edi, dword [vb_pos]
; handle return character
cmp al, 0xA
jne .char
; round up to 80 * 2
mov eax, edi
add ax, 2 * 80 - 1
mov cl, 2 * 80
div cl
mul cl
mov edi, eax
jmp .end
.char:
mov byte [esi + edi], al
mov word [esi + edi + 1], 0xf
add edi, 2
.end:
mov dword [vb_pos], edi
pop ecx
pop esi
pop eax
pop edi
ret
;;;;;;;;;;;;;;;;;;;;;
;print a null-terminated string
;;;;;;;;;;;;;;;;;;;;;;
print_str:
;offset
push ebp
mov ebp, esp
push esi
push eax
push edi
mov esi, dword [ebp + 2 * 4]
mov edi, 0xb8000
.loop_each_char:
mov al, byte [esi]
test al, al
je .end
call print_char
inc esi
jmp .loop_each_char
.end:
pop edi
pop eax
pop esi
pop ebp
ret
;;;;;;;;;;;;;;;;;;;;;
; helper function converting 4 bit val in al to its character
;;;;;;;;;;;;;;;;;;;;;;
al_to_char:
; no parameters
cmp al,09h
jna .l2
add al,37h
jmp .end
.l2:
add al,30h
.end:
ret

View File

@ -1,4 +1,5 @@
org 0x7c00
%include "addr.inc"
;;;;;;;;;;;;;;;;;;;;;;;
; Constant definition
;;;;;;;;;;;;;;;;;;;;;;;
@ -40,7 +41,6 @@ jmp $
fn_stage2: db 'STAGE2 BIN',0
%include "fat12_drv.lib"
%include "stage2.inc"
times 510-($ - $$) db 0
dw 0xaa55

View File

@ -1,4 +1,4 @@
%include "stage2.inc"
%include "addr.inc"
org STAGE2_OFFSET
jmp start16
@ -16,22 +16,36 @@ mov ax, 0xA
call print_char
%endmacro
%macro print_addr 2
push %1
call print_u16
add sp, 2
mov ax, 0x3A ; colon
call print_char
push %2
call print_u16
add sp, 2
%endmacro
[section .data]
[bits 16]
fn_kernel: db 'KERNEL BIN',0
fn_stage3: db 'STAGE3 BIN',0
msg_ok: db 'OK', 0
msg_err: db 'ERR', 0
msg_stage2_hello: db 'Stage2 loader at ', 0
msg_det_mem_pre: db 'Detecting memory... ', 0
msg_det_mem_title: db "Memory Information:", 0
msg_det_mem_tbl_hdr: db 'Base Length Type',0 ; each field is of length 20
msg_ok: db 'OK ', 0
msg_err: db 'ERR ', 0
msg_stage2_hello: db 'Stage2 loader loaded at ', 0
msg_det_mem: db 'Detecting memory... ', 0
msg_det_mem_title: db "Memory Information: ", 0
msg_det_mem_tbl_hdr: db 'Base Length Type ',0 ; each field is of length 20
msg_det_mem_tbl_pad: db ' ',0 ; 4 x spaces
msg_ld_krnl_pre: db 'Loading kernel.bin... ', 0
msg_ld_krnl_post: db 'kernel.bin loaded to ', 0
msg_pm_pre: db 'Initializing protected mode and jumping to kernel... ', 0
msg_ld_stage3: db 'Loading stage3.bin... ', 0
msg_ld_krnl: db 'Loading kernel.bin... ', 0
msg_init_pm: db 'Initializing protected mode and jumping to stage3 loader... ', 0
%include "fat12_hdr.inc"
@ -52,37 +66,37 @@ mov al, 0x03
int 0x10
print_msg msg_stage2_hello
push word STAGE2_BASE
call print_u16
add sp, 2
mov ax, 0x3A ; colon
call print_char
push word STAGE2_OFFSET
call print_u16
add sp, 2
print_addr STAGE2_BASE, STAGE2_OFFSET
print_rtn
print_msg msg_det_mem_pre
print_msg msg_det_mem
call detect_mem
cmp ax, 1
je .err
print_msg msg_ok
print_rtn
print_msg msg_det_mem_title
print_rtn
call print_mem_layout
print_rtn
print_msg msg_ld_krnl_pre
print_msg msg_ld_stage3
push word fn_stage3
push word STAGE3_OFFSET
push word STAGE3_BASE
call fat12_read_file
add esp, 6
cmp ax, 1
je .err
print_msg msg_ok
print_addr STAGE3_BASE, STAGE3_OFFSET
print_rtn
print_msg msg_ld_krnl
push word fn_kernel
push word KERNEL_OFFSET
push word KERNEL_BASE
@ -92,25 +106,10 @@ cmp ax, 1
je .err
print_msg msg_ok
print_addr KERNEL_BASE, KERNEL_OFFSET
print_rtn
print_msg msg_ld_krnl_post
push word KERNEL_BASE
call print_u16
add sp, 2
mov ax, 0x3A ; colon
call print_char
push word KERNEL_OFFSET
call print_u16
add sp, 2
print_rtn
print_msg msg_pm_pre
print_msg msg_init_pm
;load gdt
lgdt [gdtr32]
@ -125,6 +124,10 @@ mov eax,cr0
or eax,1
mov cr0,eax
; pass the frame buffer
xor ebx, ebx
mov bx, word [vb_pos]
jmp dword gdt32.sel_code:(STAGE2_FLAT + start32)
start16.err:
@ -235,23 +238,20 @@ ret
[section .text]
[bits 32]
start32:
; ebx holds -> vram_buffer
mov ax,gdt32.sel_data
mov ss,ax
mov ds,ax
mov es,ax
mov gs,ax
; adjust
mov esp, STAGE2_FLAT + stack32
;Jump to The Kernel
mov eax, KERNEL_FLAT
;Jump to stage 3
mov eax, STAGE3_FLAT
jmp eax
[section .data]
[bits 32]
times 1024 db 0
stack32:
gdt32:
dd 0
dd 0

141
src/stage3.asm Normal file
View File

@ -0,0 +1,141 @@
org 0x10000 ; 64k this is terrible but IDC
%include "addr.inc"
%macro print_msg 1
mov eax, %1
push eax
call print_str
add esp, 4
%endmacro
%macro print_rtn 0
mov eax, 0xA
call print_char
%endmacro
%macro print_addr 2
push %1
call print_u32
add esp, 4
mov eax, 0x3A ; colon
call print_char
push %2
call print_u32
add esp, 4
%endmacro
[SECTION .text]
[BITS 32]
jmp start
%include "print32.lib"
start:
mov dword [vb_pos], ebx ; ebx holds framebuffer pointer
print_msg msg_ok
print_rtn
print_msg msg_switch_gdt_pre
; switch stack and GDT
lgdt [gdtr32]
jmp dword gdt32.sel_code:.reload
.reload:
mov ax, gdt32.sel_data
mov ds, ax
mov ss, ax
mov es, ax
mov gs, ax
mov fs, ax
mov esp, stack
print_msg msg_ok
print_rtn
print_msg msg_init_idt
; write offset to idt
mov eax, dummy_handler
mov word [idt32], ax
mov cl, 16
shr eax, cl
mov word [idt32 + 6], ax
lidt [idtr32]
print_msg msg_ok
print_rtn
print_msg msg_test_div
xor ax, ax
div ax
next_op:
print_msg msg_ok
print_rtn
print_msg msg_init_krnl
mov eax, KERNEL_FLAT
jmp eax
err:
print_msg msg_err
jmp $
dummy_handler:
print_msg msg_div
call print_u32 ; top of stack is the address
print_msg msg_space
mov dword [esp], next_op ; overwrite return address
iretd
[SECTION .data]
[BITS 32]
msg_div: db '#DIV at ', 0
msg_space: db ' ', 0
msg_ok: db 'OK ', 0
msg_err: db 'ERR ', 0
msg_switch_gdt_pre: db 'Reloading GDT and stack... ', 0
msg_init_idt: db 'Initializing IDT... ', 0
msg_test_div: db 'Testing #DIV exception... ', 0
msg_init_krnl: db 'Jumping to kernel... ', 0
align 4096
times 4096 db 0
stack:
align 16
idt32:
dw 0 ; offset low 16 bits
dw gdt32.sel_code ; selector
db 0
db 0b10001111 ; Present | DPL 0 | Trap gate
dw 0
.size equ $ - idt32
idtr32:
dw idt32.size - 1
dd idt32
align 16
gdt32:
dd 0
dd 0
.sel_code: equ $ - gdt32
dw 0xFFFF ; LIMIT = 0xFFFF
dw 0 ; BASE LOW = 0
db 0 ; BASE MID = 0
db 10011010b; PRESENT | RW | EXE
db 11001111b; Granularity = 4k | 32 bits
db 0 ; BASE_HIGH = 0
.sel_data: equ $ - gdt32
dw 0xFFFF ; LIMIT = 0xFFFF
dw 0 ; BASE LOW = 0
db 0 ; BASE MID = 0
db 10010010b; PRESENT | RW | EXE
db 11001111b; Granularity = 4k | 32 bits
db 0 ; BASE_HIGH = 0
.size: equ $ - gdt32
align 16
gdtr32:
dw gdt32.size - 1
dd gdt32

View File

@ -1,7 +0,0 @@
STAGE2_BASE equ 0x8000
STAGE2_OFFSET equ 0x0
STAGE2_FLAT equ (STAGE2_BASE * 0x10) + STAGE2_OFFSET
KERNEL_BASE equ 0x4000
KERNEL_OFFSET equ 0x0
KERNEL_FLAT equ (KERNEL_BASE * 0x10) + KERNEL_OFFSET