diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 485dee6..0000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.idea diff --git a/kernel.c b/kernel.c deleted file mode 100644 index 6ac43f6..0000000 --- a/kernel.c +++ /dev/null @@ -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) - { - - } -} diff --git a/src/addr.inc b/src/addr.inc new file mode 100644 index 0000000..d4db610 --- /dev/null +++ b/src/addr.inc @@ -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 diff --git a/bochsrc b/src/bochsrc similarity index 100% rename from bochsrc rename to src/bochsrc diff --git a/fat12_drv.lib b/src/fat12_drv.lib similarity index 100% rename from fat12_drv.lib rename to src/fat12_drv.lib diff --git a/fat12_hdr.inc b/src/fat12_hdr.inc similarity index 100% rename from fat12_hdr.inc rename to src/fat12_hdr.inc diff --git a/src/kernel.c b/src/kernel.c new file mode 100644 index 0000000..a847d6b --- /dev/null +++ b/src/kernel.c @@ -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++; + } + } +} \ No newline at end of file diff --git a/makefile b/src/makefile similarity index 95% rename from makefile rename to src/makefile index 037d73f..f44d9af 100644 --- a/makefile +++ b/src/makefile @@ -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 diff --git a/print16.lib b/src/print16.lib similarity index 100% rename from print16.lib rename to src/print16.lib diff --git a/src/print32.lib b/src/print32.lib new file mode 100644 index 0000000..337bea0 --- /dev/null +++ b/src/print32.lib @@ -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 \ No newline at end of file diff --git a/stage1.asm b/src/stage1.asm similarity index 94% rename from stage1.asm rename to src/stage1.asm index 911d1bc..832632d 100644 --- a/stage1.asm +++ b/src/stage1.asm @@ -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 \ No newline at end of file diff --git a/stage2.asm b/src/stage2.asm similarity index 75% rename from stage2.asm rename to src/stage2.asm index 10cb6a1..83ab013 100644 --- a/stage2.asm +++ b/src/stage2.asm @@ -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 diff --git a/src/stage3.asm b/src/stage3.asm new file mode 100644 index 0000000..a09a00a --- /dev/null +++ b/src/stage3.asm @@ -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 \ No newline at end of file diff --git a/stage2.inc b/stage2.inc deleted file mode 100644 index e03a42e..0000000 --- a/stage2.inc +++ /dev/null @@ -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 \ No newline at end of file