From 30596991abc9e452fbad8372f1ddcce12b87ce72 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Thu, 11 May 2017 22:10:07 +0200 Subject: better documentation for the boot loading process and how much sectors each part needs, fixed truncation problem started a magic signature at the end of the image and started to check it in stage 2 of the boot loader to avoid truncated images in the future --- doc/LINKS.TODO | 4 ++++ src/Makefile | 37 +++++++++++++++++++++++++---------- src/boot.asm | 51 ++++++++++++++++++++++++++++-------------------- src/magic.asm | 6 ++++++ src/stage1_functions.asm | 5 ++--- src/stage2_functions.asm | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 120 insertions(+), 34 deletions(-) create mode 100644 src/magic.asm diff --git a/doc/LINKS.TODO b/doc/LINKS.TODO index 65e754f..f7a602e 100644 --- a/doc/LINKS.TODO +++ b/doc/LINKS.TODO @@ -4,3 +4,7 @@ http://wiki.osdev.org/Linker_Scripts http://wiki.osdev.org/Printing_To_Screen http://wiki.osdev.org/Exceptions#General_Protection_Fault https://en.wikipedia.org/wiki/X86_calling_conventions +https://github.com/FlingOS/FlingOS +http://repo.or.cz/w/lightOS.git +https://littleosbook.github.io/ +http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html diff --git a/src/Makefile b/src/Makefile index c983fb6..4e0755a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,30 +4,47 @@ LD := ld all: image.bin -image.bin: boot.bin kernel.bin - cat boot.bin kernel.bin > image.bin +image.bin: boot.bin kernel.bin magic.bin + cat boot.bin kernel.bin > image.tmp # truncate to correct number of sectors, we have - # 512 (boot, first stage) + N * 512 (N currenty is 3) + M * 512 (M is currently 3) - truncate -s 4096 image.bin + # 512 (boot, stage 1) + N * 512 (N currenty is 3, stage 2) = 2048 for boot.bin + # + M * 512 (M is currently 7) = 3144 for kernel.bin + # + 1 * 512 = 512 for magic.bin + # (M + N + 1 is the number of sectors to be read in stage 2, as stage 1 + # loads only the first sector, so adapt NOF_LOAD_SECTORS to 10) + truncate -s 5632 image.tmp + cat image.tmp magic.bin > image.bin boot.bin: boot.asm gdt.asm stage1_functions.asm stage2_functions.asm switch_mode.asm nasm boot.asm -f bin -o boot.bin -kernel.bin: kernel.o vga.o string.o +kernel.bin: kernel.o vga.o port.o port_asm.o string.o stdlib.o $(LD) -o kernel.bin -n -Ttext 0x8000 --oformat binary \ - kernel.o vga.o string.o + kernel.o vga.o port.o port_asm.o string.o stdlib.o +magic.bin: magic.asm + nasm magic.asm -f bin -o magic.bin + kernel.o: kernel.c - $(CC) $(CFLAGS) -O0 -c -o kernel.o kernel.c + $(CC) $(CFLAGS) -c -o kernel.o kernel.c + +port.o: port.c + $(CC) $(CFLAGS) -c -o port.o port.c vga.o: vga.c - $(CC) $(CFLAGS) -O0 -c -o vga.o vga.c + $(CC) $(CFLAGS) -c -o vga.o vga.c + +port_asm.o: port.asm + nasm port.asm -f elf32 -o port_asm.o string.o: string.c - $(CC) $(CFLAGS) -O0 -c -o string.o string.c + $(CC) $(CFLAGS) -c -o string.o string.c + +stdlib.o: stdlib.c + $(CC) $(CFLAGS) -c -o stdlib.o stdlib.c clean: - -rm -f boot.bin kernel.bin image.bin *.o + -rm -f boot.bin kernel.bin image.bin magic.bin *.o run-qemu: image.bin qemu-system-i386 -m 32 -drive "file=image.bin,if=ide,format=raw" diff --git a/src/boot.asm b/src/boot.asm index 631a99a..9b130a2 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -5,7 +5,10 @@ ; 16-bit real-mode [bits 16] - + +; export a map of kernel symbols for debugging + [map symbols kernel.map] + ; initialize segment registers mov ax, 0 mov ds, ax @@ -18,6 +21,8 @@ mov [BOOT_DRIVE], dl ; make sure we know the location of the stack by setting it on our own +; this stack is only used in real mode in stage 1, so it's growing from +; 0xffff down mov bp, 0xFFFF mov sp, bp @@ -34,10 +39,13 @@ ; print we are going to load stage 2 of the boot blocks mov si, MESSAGE_LOADING_STAGE_2 call print_string - + +; load stage 2 and the kernel together to 0x7e00 (directly +; after the boot sector) mov dl, [BOOT_DRIVE] call read_from_disk - + +; jump over variables and subroutines of stage 1 and execute stage 2 jmp stage2 %include "stage1_functions.asm" @@ -67,13 +75,16 @@ times 510-($-$$) db 0 dw 0xaa55 stage2: +; print a message that we are indeed in stage 2 now mov si, MESSAGE_STAGE_2_LOADED call print_string -; remember current position on screen +; remember current position on screen, otherwise we loose this +; information after switching to protected mode call current_row mov [CURSOR_Y], dh +; enter protected mode call switch_to_protected_mode ; we should never get here, but just in case @@ -88,43 +99,39 @@ MESSAGE_STAGE_2_LOADED: BEGIN_PROTECTED_MODE: - mov edx, 1 -_loop_test: - mov si, MESSAGE_INITIALIZING - call pm_print_string - call pm_print_newline - dec edx - cmp edx, 0 - jnz _loop_test -_end_of_test: - +; we switched to protected mode mov si, MESSAGE_PROTECTED_MODE call pm_print_string call pm_print_newline - + +; check sanity of kernel by searching for MAGIC string at a given +; position + call check_magic + +; print a message before we call the C level kernel mov si, MESSAGE_CALL_C_ENTRY call pm_print_string call pm_print_newline ; call our kernel call c_entry - + +; "kernel halted" message, when we terminate the C kernel mov si, MESSAGE_HALTED call pm_print_string call pm_print_newline ; end of C, disable interupts again, NMIs can still happen +; make sure we loop endlessly here but without burning too +; much CPU cli _halt_loop: hlt jmp _halt_loop - + MESSAGE_PROTECTED_MODE: db "Switched to 32-bit Protected Mode", 0 -MESSAGE_INITIALIZING: - db "Initializing the Foo machine..", 0 - MESSAGE_CALL_C_ENTRY: db "Calling C entry function", 0 @@ -133,7 +140,9 @@ MESSAGE_HALTED: %include "stage2_functions.asm" -; make sure we have full sectors +; make sure we have full sectors, stage one is 512 bytes, so we +; have to will up 3 sectors times 2048-($-$$) db 0 +; position is 0x8400 now for the C entry c_entry: diff --git a/src/magic.asm b/src/magic.asm new file mode 100644 index 0000000..c8c580e --- /dev/null +++ b/src/magic.asm @@ -0,0 +1,6 @@ +; pad rest of sector with zeroes so we get 512 bytes in the end +times 512-11-($-$$) db 0 + +; the magic string we search for in stage 2 to ensure we don't read +; a truncated kernel image +db "ABAOSMAGIC", 0 diff --git a/src/stage1_functions.asm b/src/stage1_functions.asm index b32d23d..c43da4d 100644 --- a/src/stage1_functions.asm +++ b/src/stage1_functions.asm @@ -1,9 +1,8 @@ ; number of sectors to be read -; this is 512 (the bootloader stage1) + ; 3 * 512 for bootloader stage2 and the kernel code ; (note: the first sector gets loaded by the BIOS, so ; subtract 1 here!) -NOF_LOAD_SECTORS equ 7 +NOF_LOAD_SECTORS equ 11 ; IN bx: begin of memory area to dump ; IN ax: number of words to dump @@ -19,7 +18,7 @@ dump_range: jnz dump_range ret -; IN bx: hex value to print +; IN dx: hex value to print print_hex: push bx push si diff --git a/src/stage2_functions.asm b/src/stage2_functions.asm index 018cf6a..d692ed2 100644 --- a/src/stage2_functions.asm +++ b/src/stage2_functions.asm @@ -55,6 +55,34 @@ pm_print_char: call inc_cursor ret +; IN dx: hex value to print +pm_print_hex: + push bx + push si + mov si, HEX_TEMPLATE + mov bx, dx + shr bx, 12 + mov bx, [HEXABET+bx] + mov [HEX_TEMPLATE+2], bl + mov bx, dx + and bx, 0x0FFF + shr bx, 8 + mov bx, [HEXABET+bx] + mov [HEX_TEMPLATE+3], bl + mov bx, dx + and bx, 0x00FF + shr bx, 4 + mov bx, [HEXABET+bx] + mov [HEX_TEMPLATE+4], bl + mov bx, dx + and bx, 0x000F + mov bx, [HEXABET+bx] + mov [HEX_TEMPLATE+5], bl + call pm_print_string + pop si + pop bx + ret + inc_cursor: push eax mov ax, [CURSOR_X] @@ -106,3 +134,26 @@ update_vga_cursor: pop ecx pop ebx ret + +check_magic: + push eax + push ebx + push ecx + push edx + push esi + mov eax, NOF_LOAD_SECTORS ; number of 512-byte sectors + shl eax, 9 ; 512 bytes per sector + mov ecx, 0x7e00 ; offset of stage 2 + add ecx, eax + sub ecx, 11 ; the length of the magic string + mov dx, cx + call pm_print_hex + mov dx, [ecx] + call pm_print_hex + call pm_print_newline + pop esi + pop edx + pop ecx + pop ebx + pop eax + ret -- cgit v1.2.3-54-g00ecf