summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2017-04-23 20:38:39 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2017-04-23 20:38:39 +0200
commita7fb48922dee006339747d128d83fafbe9dfe79a (patch)
tree1059f98f582a83dfeb25aa72fb6bdc2598a66dc3
downloadabaos-a7fb48922dee006339747d128d83fafbe9dfe79a.tar.gz
abaos-a7fb48922dee006339747d128d83fafbe9dfe79a.tar.bz2
fresh import because of huge documents checked in by accident
-rw-r--r--README66
-rw-r--r--README.Wyoos23
-rw-r--r--src/Makefile29
-rw-r--r--src/boot.asm121
-rw-r--r--src/gdt.asm43
-rw-r--r--src/kernel.c10
-rw-r--r--src/stage1_functions.asm136
-rw-r--r--src/stage2_functions.asm108
-rw-r--r--src/switch_mode.asm38
9 files changed, 574 insertions, 0 deletions
diff --git a/README b/README
new file mode 100644
index 0000000..8f082d8
--- /dev/null
+++ b/README
@@ -0,0 +1,66 @@
+Requirements
+------------
+
+nasm
+gcc, clang or tcc
+
+Debugging
+---------
+
+hexdump -C image.bin | less
+
+ndisasm -b16 -o7c00h -a image.bin | less
+
+objdump -M intel -d kernel.o | less
+
+gcc -m32 -ffreestanding -c -o kernel.o kernel.c
+ld -o kernel.bin -Ttext 0x8000 kernel.o -m elf_i386 --oformat binary
+objdump -M intel -d kernel.bin | less
+
+# oformat: objdump -i lists tons of formats
+# -m: ld -V
+# -T: set text segment ot start at BIOS block 3
+# TEXT means code
+
+bochs -q 'boot:floppy' 'floppya: 1_44=image.bin, status=inserted'
+
+Some interesting breakpoints:
+
+boot loader (boot.asm, stage 1)
+break 0x7c00
+
+boot loeader after switching to protecting mode:
+break 0x7e4e
+
+Booting from 0000:7c00
+(0) Breakpoint 1, 0x0000000000007c00 in ?? ()
+Next at t=14040244
+(0) [0x000000007c00] 0000:7c00 (unk. ctxt): mov ax, 0x0000 ; b80000
+
+links
+-----
+
+https://www.youtube.com/watch?v=YvZhgRO7hL4&list=UUjrLiYrvbpXR37c0HV4PmqA
+
+http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-manual-325462.html
+http://wiki.osdev.org/Global_Descriptor_Table
+https://en.wikipedia.org/wiki/INT_10H
+http://www.osdever.net/FreeVGA/vga/crtcreg.htm
+http://wiki.osdev.org/Text_Mode_Cursor
+https://en.wikipedia.org/wiki/Calling_convention
+http://wiki.osdev.org/Main_Page
+
+other project links
+-------------------
+
+http://www.helenos.org
+https://github.com/cfenollosa/os-tutorial
+http://wyoos.org: in C++
+http://osdev.org
+https://github.com/Codepixl/CodeOS
+http://www.osdever.net/tutorials/
+http://lowelevel.eu
+http://download.tyndur.org/releases/0.2/
+https://code.google.com/archive/p/fpos/source/default/source, FreePascal
+https://mirage.io/
+http://www.jamesmolloy.co.uk/tutorial_html/
diff --git a/README.Wyoos b/README.Wyoos
new file mode 100644
index 0000000..7bf4909
--- /dev/null
+++ b/README.Wyoos
@@ -0,0 +1,23 @@
+IDT interupt descriptor table
+
+GDT global descriptor table
+- set up segments
+- code segments, RX, never W
+- data segments, RW, never X
+- 16-bit compatibility on Intel, so quite a nightmare
+- asm( LGDT ) needed
+=> we do GTD all in assembly, not really readable! Ideal would be to
+ do as much as possible in C/C++ (even with some zero-overhead
+ C++17 crazyness maybe) and then call a pure assembly function with
+ a pointer to the GTD doing the 'LGDT' assembly operation
+
+types:
+- have local typedefs for DWORD32 or uint32_t (as Windows and POSIX did
+ it)
+
+keyboard:
+- 0x20 PIC
+- asm( outb( port, byte)), outb function => better have ports knowing
+ their own bandwith.
+ SlowPort8, slowing down assembly code
+
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..ed04a72
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,29 @@
+CC := gcc
+
+all: image.bin
+
+image.bin: boot.bin kernel.bin
+ cat boot.bin kernel.bin > image.bin
+ truncate -s 1536 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
+ ld -o kernel.bin -Ttext 0x8000 kernel.o -m elf_i386 --oformat binary
+
+kernel.o: kernel.c
+ $(CC) -m32 -ffreestanding -c -o kernel.o kernel.c
+
+clean:
+ -rm -f boot.bin kernel.bin image.bin *.o
+
+run-qemu: image.bin
+ qemu-system-i386 -m 16 -drive "file=image.bin,if=ide,format=raw"
+
+run-bochs:
+ bochs -q 'boot:floppy' 'floppya: 1_44=image.bin, status=inserted'
+
+
+functions.o: functions.c
+ gcc -m32 -ffreestanding -c -o functions.o functions.c
diff --git a/src/boot.asm b/src/boot.asm
new file mode 100644
index 0000000..f053270
--- /dev/null
+++ b/src/boot.asm
@@ -0,0 +1,121 @@
+; legacy BIOS PC-boot code, starts in 16-bit real mode
+
+; BIOS always loads us to this location
+ [org 0x7c00]
+
+; 16-bit real-mode
+ [bits 16]
+
+; initialize segment registers
+ mov ax, 0
+ mov ds, ax
+ mov es, ax
+ mov ss, ax
+
+; dl contains the boot drive, primarily because that's the last function
+; called by the BIOS MBR loader, we remember that for loading additional
+; blocks from the boot medium
+ mov [BOOT_DRIVE], dl
+
+; make sure we know the location of the stack by setting it on our own
+ mov bp, 0xFFFF
+ mov sp, bp
+
+; print out some information about CPU mode and BIOS boot drive
+ mov si, MESSAGE_REAL_MODE
+ call print_string
+
+ mov si, MESSAGE_BOOT_DRIVE
+ call print_string
+ mov ax, dx
+ call print_hex
+ call print_newline
+
+; print we are going to load stage 2 of the boot blocks
+ mov si, MESSAGE_LOADING_STAGE_2
+ call print_string
+
+ mov dl, [BOOT_DRIVE]
+ call read_from_disk
+
+ jmp stage2
+
+%include "stage1_functions.asm"
+
+DISK_ERROR:
+ db "DISK ERROR ", 0
+
+SHORT_READ:
+ db "DISK SHORT READ", 0
+
+MESSAGE_REAL_MODE:
+ db "Started in 16-bit Real Mode", 13, 10, 0
+
+MESSAGE_BOOT_DRIVE:
+ db "Booting from drive ", 0
+
+MESSAGE_LOADING_STAGE_2:
+ db "Loading stage 2 boot loader", 13, 10, 0
+
+BOOT_DRIVE:
+ db 0
+
+; pad rest of sector with zeroes so we get 512 bytes in the end
+times 510-($-$$) db 0
+
+; magic number of a boot sector
+dw 0xaa55
+
+stage2:
+ mov si, MESSAGE_STAGE_2_LOADED
+ call print_string
+
+; remember current position on screen
+ call current_row
+ mov [CURSOR_Y], dh
+
+ call switch_to_protected_mode
+
+; we should never get here, but just in case
+ jmp $
+
+MESSAGE_STAGE_2_LOADED:
+ db "Stage 2 boot sectors loaded", 13, 10, 0
+
+%include "switch_mode.asm"
+
+[bits 32]
+
+BEGIN_PROTECTED_MODE:
+ mov si, MESSAGE_PROTECTED_MODE
+ call pm_print_string
+ call pm_print_newline
+
+ mov si, MESSAGE_CALL_C_ENTRY
+ call pm_print_string
+ call pm_print_newline
+
+; call our kernel
+ call c_entry
+
+ mov si, MESSAGE_HALTED
+ call pm_print_string
+ call pm_print_newline
+
+ jmp $
+
+MESSAGE_PROTECTED_MODE:
+ db "Switched to 32-bit Protected Mode", 0
+
+MESSAGE_CALL_C_ENTRY:
+ db "Calling C entry function", 0
+
+MESSAGE_HALTED:
+ db "Operating system halted", 0
+
+%include "stage2_functions.asm"
+
+; make sure we have full sectors
+times 1024-($-$$) db 0
+
+c_entry:
diff --git a/src/gdt.asm b/src/gdt.asm
new file mode 100644
index 0000000..15fe924
--- /dev/null
+++ b/src/gdt.asm
@@ -0,0 +1,43 @@
+; GDT global descriptor table
+
+gdt_start:
+
+; mandatory null entry
+gdt_null:
+ dd 0x0
+ dd 0x0
+
+; code segment
+; base=0x0, limit=0xfffff
+; flags: present (not paged), ring 0, executable, direction bit
+; conforming, writable, not accessed
+; granularity: 4kb pages, 32-bit mode, no 64-bit segment, AVL would
+; be for our own extensions
+gdt_code:
+ dw 0xffff
+ dw 0x0
+ db 0x0
+ db 10011010b
+ db 11001111b
+ db 0x0
+
+; flat model, same as code segment, but flags are
+; flags: ring 0,
+gdt_data:
+ dw 0xffff
+ dw 0x0
+ db 0x0
+ db 10010010b
+ db 11001111b
+ db 0x0
+
+gdt_end:
+
+gdt_descriptor:
+ dw gdt_end -gdt_start - 1 ; size
+ dd gdt_start ; start address of the GDT
+
+; constants representing the segment bases
+CODE_SEGMENT equ gdt_code - gdt_start
+DATA_SEGMENT equ gdt_data - gdt_start
+
diff --git a/src/kernel.c b/src/kernel.c
new file mode 100644
index 0000000..d94f960
--- /dev/null
+++ b/src/kernel.c
@@ -0,0 +1,10 @@
+void entry( )
+{
+ char *VIDEO_MEMORY = (char *)0xb8000;
+ char *bar = "\\|/-";
+ char backup = *VIDEO_MEMORY;
+ for( int i = 0; i < 20000000; i++ ) {
+ *VIDEO_MEMORY = bar[i%4];
+ }
+ *VIDEO_MEMORY = backup;
+}
diff --git a/src/stage1_functions.asm b/src/stage1_functions.asm
new file mode 100644
index 0000000..2ca3eb2
--- /dev/null
+++ b/src/stage1_functions.asm
@@ -0,0 +1,136 @@
+; IN bx: begin of memory area to dump
+; IN ax: number of words to dump
+dump_range:
+ mov dx, bx
+ call print_hex
+ mov dx, [bx]
+ call print_hex
+ call print_newline
+ add bx, 2
+ dec ax
+ cmp ax, 0
+ jnz dump_range
+ ret
+
+; IN bx: hex value to print
+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 print_string
+ pop si
+ pop bx
+ ret
+
+HEX_TEMPLATE:
+ db '0x???? ', 0
+
+HEXABET:
+ db '0123456789ABCDEF'
+
+print_newline:
+ push ax
+ mov al, 10
+ call print_char
+ mov al, 13
+ call print_char
+ pop ax
+ ret
+
+; IN si
+print_string:
+ push ax
+_loop_print_string:
+ lodsb
+ cmp al, 0
+ je print_string_fini
+ call print_char
+ jmp _loop_print_string
+print_string_fini:
+ pop ax
+ ret
+
+; IN al: character to print
+; MOD ah
+print_char:
+ mov ah, 0x0e
+ int 0x10
+ ret
+
+fat_cursor:
+ push ax
+ push cx
+ mov ah, 0x01
+ mov cx, 0x0007
+ int 0x10
+ pop cx
+ pop ax
+ ret
+
+; OUT: current row
+current_row:
+ push ax
+ push bx
+ push cx
+ mov ah, 0x03
+ mov bh, 0
+ int 0x10
+ pop cx
+ pop bx
+ pop ax
+ ret
+
+; IN dl: drive to read from
+read_from_disk:
+
+ mov ah, 0x02 ; read sectors from drive
+
+ mov al, 2 ; read 1 sector
+ mov ch, 0 ; select first cylinder
+ mov dh, 0 ; first head
+ mov cl, 2 ; second sector after boot sector
+
+ mov bx, 0 ; where to store the data
+ mov es, bx
+ mov bx, 0x7e00 ; 512 bytes after first sector
+
+ int 0x13
+
+ jc read_error
+
+ cmp al, 2 ; 1 sector read?
+ jne short_read ; if not, short read
+
+ ret
+
+read_error:
+ mov si, DISK_ERROR
+ call print_string
+ mov dh, 0
+ mov dl, ah
+ call print_hex
+ jmp $
+
+short_read:
+ mov si, SHORT_READ
+ call print_string
+ jmp $
+
diff --git a/src/stage2_functions.asm b/src/stage2_functions.asm
new file mode 100644
index 0000000..018cf6a
--- /dev/null
+++ b/src/stage2_functions.asm
@@ -0,0 +1,108 @@
+VIDEO_MEMORY equ 0xb8000
+
+VIDEO_COLS equ 80
+VIDEO_ROWS equ 25
+
+CURSOR_X:
+ dw 0
+
+CURSOR_Y:
+ dw 0
+
+pm_print_newline:
+ push eax
+ mov [CURSOR_X], word 0
+ mov ax, [CURSOR_Y]
+ inc ax
+ mov [CURSOR_Y], ax
+ pop eax
+ call update_vga_cursor
+ ret
+
+; IN si
+pm_print_string:
+ push eax
+_loop_pm_print_string:
+ lodsb
+ cmp al, 0
+ je pm_print_string_fini
+ call pm_print_char
+ jmp _loop_pm_print_string
+pm_print_string_fini:
+ pop eax
+ ret
+
+; IN al: character to print
+pm_print_char:
+ push edx
+ push ecx
+ push ebx
+ push eax
+ mov ax, [CURSOR_Y]
+ mov cl, VIDEO_COLS
+ mul cl
+ mov bx, [CURSOR_X]
+ add ax, bx
+ shl ax, 1
+ mov edx, VIDEO_MEMORY
+ add dx, ax
+ pop eax
+ mov ah, 0x07
+ mov [edx], ax
+ pop ebx
+ pop ecx
+ pop edx
+ call inc_cursor
+ ret
+
+inc_cursor:
+ push eax
+ mov ax, [CURSOR_X]
+ inc ax
+ mov [CURSOR_X], ax
+ cmp ax, VIDEO_COLS
+ jl inc_cursor_fini
+ mov [CURSOR_X], word 1
+ mov ax, [CURSOR_Y]
+ inc ax
+ mov [CURSOR_Y], ax
+ cmp ax, VIDEO_ROWS
+ jl inc_cursor_fini
+ ; TODO: scoll one line, for now restart on top
+ mov [CURSOR_Y], word 0
+inc_cursor_fini:
+ call update_vga_cursor
+ pop eax
+ ret
+
+; update the VGA cursor on screen
+update_vga_cursor:
+ push ebx
+ push ecx
+ push edx
+ mov al, [CURSOR_Y]
+ mov cl, VIDEO_COLS
+ mul cl
+ mov bx, ax
+ movzx ax, [CURSOR_X]
+ add bx, ax
+ mov cx, bx
+ ;cursor LOW port to vga INDEX register
+ mov al, 0fh ;Cursor Location Low Register --
+ mov dx, 3d4h ;VGA port 3D4h
+ out dx, al
+ mov ax, cx ;restore 'postion' back to AX
+ mov dx, 3d5h ;VGA port 3D5h
+ out dx, al ;send to VGA hardware
+ ;cursor HIGH port to vga INDEX register
+ mov al, 0eh
+ mov dx, 3d4h ;VGA port 3D4h
+ out dx, al
+ mov ax, cx ;restore 'position' back to AX
+ shr ax, 8 ;get high byte in 'position'
+ mov dx, 3d5h ;VGA port 3D5h
+ out dx, al ;send to VGA hardware
+ pop edx
+ pop ecx
+ pop ebx
+ ret
diff --git a/src/switch_mode.asm b/src/switch_mode.asm
new file mode 100644
index 0000000..32cca0b
--- /dev/null
+++ b/src/switch_mode.asm
@@ -0,0 +1,38 @@
+[bits 16]
+
+%include "gdt.asm"
+
+switch_to_protected_mode:
+ ; switch off interrupts for now
+ cli
+
+ ; load GDT (global descriptor table)
+ lgdt [gdt_descriptor]
+
+ ; do the actual switch
+ mov eax, cr0
+ or eax, 0x1
+ mov cr0, eax
+
+ ; unconditional far jump into code segment
+ jmp CODE_SEGMENT:init_pm
+
+[bits 32]
+
+; initialize registers and stack for protected mode
+init_pm:
+ mov ax, DATA_SEGMENT
+ mov ds, ax
+ mov ss, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+
+ ; a new stack
+ mov ebp, 0x90000
+ mov esp, ebp
+
+ call BEGIN_PROTECTED_MODE
+
+[bits 16]
+