Carlos Fenollosa 10 éve
szülő
commit
d5d1a88cae

+ 43 - 0
14-checkpoint/Makefile

@@ -0,0 +1,43 @@
+C_SOURCES = $(wildcard kernel/*.c drivers/*.c)
+HEADERS = $(wildcard kernel/*.h drivers/*.h)
+OBJ = ${C_SOURCES:.c=.o}
+
+# Change this if your cross-compiler is somewhere else
+CC = /usr/local/i386elfgcc/bin/i386-elf-gcc
+GDB = /usr/local/i386elfgcc/bin/i386-elf-gdb
+# -g: Use debugging symbols
+CFLAGS = -g
+
+# First rule is run by default
+os-image.bin: boot/bootsect.bin kernel.bin
+	cat $^ > os-image.bin
+
+kernel.bin: kernel.elf
+	i386-elf-ld -o $@ -Ttext 0x1000 $^ --oformat binary
+
+run: os-image.bin
+	qemu-system-i386 -fda os-image.bin
+
+debug: os-image.bin kernel.elf
+	qemu-system-i386 -s -fda os-image.bin &
+	${GDB} -ex "target remote localhost:1234" -ex "symbol-file kernel.elf"
+
+# To build the kernel: make all objects first
+kernel.elf: boot/kernel_entry.o ${OBJ}
+	i386-elf-ld -o $@ -Ttext 0x1000 $^ 
+
+# To make an object, always compile from its .c
+%.o: %.c ${HEADERS}
+	${CC} ${CFLAGS} -ffreestanding -c $< -o $@
+
+# Object files from asm files
+%.o: %.asm
+	nasm $< -f elf -o $@
+
+%.bin: %.asm
+	nasm $< -f bin -o $@
+
+
+clean:
+	rm -rf *.bin *.dis *.o os-image.bin *.elf
+	rm -rf kernel/*.o boot/*.bin drivers/*.o

+ 34 - 1
14-checkpoint/README.md

@@ -1,4 +1,4 @@
-*Concepts you may want to Google beforehand: monolithic kernel, microkernel*
+*Concepts you may want to Google beforehand: monolithic kernel, microkernel, debugger, gdb*
 
 **Goal: Pause and organize our code a little bit**
 
@@ -13,6 +13,39 @@ Take a look at the new folder structure. Most of the files have been symlinked
 from previous lessons, so if we have to change them at some point, it will be
 a better idea to remove the symlink and create a new file.
 
+Furthermore, since from now on we will use mostly C to code, we'll take advantage of qemu's
+ability to open a connection to gdb. First, let's install a cross-compiled `gdb` since
+OSX uses `lldb` which is not compatible with the ELF file format (neither is the `gdb` available
+on Homebrew's repos)
+
+```sh
+cd /tmp/src
+curl -O http://ftp.rediris.es/mirror/GNU/gnu/gdb/gdb-7.8.tar.gz
+tar xf gdb-7.8.tar.gz
+mkdir gdb-build
+cd gdb-build
+export PREFIX="/usr/local/i386elfgcc"
+export TARGET=i386-elf
+../gdb-7.8/configure --target="$TARGET" --prefix="$PREFIX" --program-prefix=i386-elf-
+make
+make install
+```
+
+Check out the Makefile target `make debug`. We can take
+advantage of this cool qemu feature. Type `make debug` and, on the gdb shell:
+
+- Set up a breakpoint in `kernel.c:main()`: `b main`
+- Run the OS: `continue`
+- Run two steps into the code: `next` then `next`. You will see that we are just about to set
+  the 'X' on the screen, but it isn't there yet (chech out the qemu screen)
+- Let's see what's in the video memory: `print *video_memory`. There is the 'L' from "Landed in
+  32-bit Protected Mode"
+- Hmmm, let's make sure that `video_memory` points to the correct address: `print video_memory`
+- `next` to put there our 'X'
+- Let's make sure: `print *video_memory` and look at the qemu screen. It's definitely there.
+
+Now is a good time to read some tutorial on `gdb`!
+
 
 Strategy
 --------

+ 1 - 0
14-checkpoint/boot/32bit_print.asm

@@ -0,0 +1 @@
+../../08-32bit-print/32bit-print.asm

+ 51 - 0
14-checkpoint/boot/bootsect.asm

@@ -0,0 +1,51 @@
+; Identical to lesson 13's boot sector, but the %included files have new paths
+[org 0x7c00]
+KERNEL_OFFSET equ 0x1000 ; The same one we used when linking the kernel
+
+    mov [BOOT_DRIVE], dl ; Remember that the BIOS sets us the boot drive in 'dl' on boot
+    mov bp, 0x9000
+    mov sp, bp
+
+    mov bx, MSG_REAL_MODE 
+    call print
+    call print_nl
+
+    call load_kernel ; read the kernel from disk
+    call switch_to_pm ; disable interrupts, load GDT,  etc. Finally jumps to 'BEGIN_PM'
+    jmp $ ; Never executed
+
+%include "boot/print.asm"
+%include "boot/print_hex.asm"
+%include "boot/disk.asm"
+%include "boot/gdt.asm"
+%include "boot/32bit_print.asm"
+%include "boot/switch_pm.asm"
+
+[bits 16]
+load_kernel:
+    mov bx, MSG_LOAD_KERNEL
+    call print
+    call print_nl
+
+    mov bx, KERNEL_OFFSET ; Read from disk and store in 0x1000
+    mov dh, 2
+    mov dl, [BOOT_DRIVE]
+    call disk_load
+    ret
+
+[bits 32]
+BEGIN_PM:
+    mov ebx, MSG_PROT_MODE
+    call print_string_pm
+    call KERNEL_OFFSET ; Give control to the kernel
+    jmp $ ; Stay here when the kernel returns control to us (if ever)
+
+
+BOOT_DRIVE db 0 ; It is a good idea to store it in memory because 'dl' may get overwritten
+MSG_REAL_MODE db "Started in 16-bit Real Mode", 0
+MSG_PROT_MODE db "Landed in 32-bit Protected Mode", 0
+MSG_LOAD_KERNEL db "Loading kernel into memory", 0
+
+; padding
+times 510 - ($-$$) db 0
+dw 0xaa55

BIN
14-checkpoint/boot/bootsect.bin


+ 1 - 0
14-checkpoint/boot/disk.asm

@@ -0,0 +1 @@
+../../07-bootsector-disk/boot_sect_disk.asm

+ 1 - 0
14-checkpoint/boot/gdt.asm

@@ -0,0 +1 @@
+../../09-32bit-gdt/32bit-gdt.asm

+ 1 - 0
14-checkpoint/boot/kernel_entry.asm

@@ -0,0 +1 @@
+../../13-kernel-barebones/kernel_entry.asm

BIN
14-checkpoint/boot/kernel_entry.o


+ 1 - 0
14-checkpoint/boot/switch_pm.asm

@@ -0,0 +1 @@
+../../10-32bit-enter/32bit-switch.asm

BIN
14-checkpoint/kernel.elf


BIN
14-checkpoint/kernel.sym


+ 8 - 0
14-checkpoint/kernel/kernel.c

@@ -0,0 +1,8 @@
+/* This will force us to create a kernel entry function instead of jumping to kernel.c:0x00 */
+void dummy_test_entrypoint() {
+}
+
+void main() {
+    char* video_memory = (char*) 0xb8000;
+    *video_memory = 'X';
+}

BIN
14-checkpoint/kernel/kernel.o