diff --git a/.Makefile.swo b/.Makefile.swo new file mode 100644 index 0000000..2b1fc5f Binary files /dev/null and b/.Makefile.swo differ diff --git a/.gitignore b/.gitignore index 747b558..6048758 100755 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.swp disk_images/* +tmp-loop/* diff --git a/source/bootload/boot.asm b/source/bootload/boot.asm index 15bc38a..0ecb953 100644 --- a/source/bootload/boot.asm +++ b/source/bootload/boot.asm @@ -25,7 +25,7 @@ ebr_drive_number: db 0 ; ignore ebr_signature: db 29h ; boot signature, indicates that the next three fields are present (0x29) ebr_volume_id: db 12h, 34h, 56h, 78h ; unique id for volume tracking ebr_volume_label: db 'CrawShaw OS' ; must be 11 bytes -ebr_system_id: db 'FAT12 ' ' ; must be 8 bytes +ebr_system_id: db 'FAT12 ' ; must be 8 bytes main: ; Setup registers @@ -117,6 +117,7 @@ found_kernel: mov ax, [di+26] ; di is the address of the kernel, 26 is the offset mov [kernel_cluster], ax + ; Setup registers for disk read mov ax, [bdb_reserved_sectors] mov bx, buffer mov cl, [bdb_sectors_per_fat] @@ -334,7 +335,7 @@ print_string: pop si ret -boot_text: db 'OK] Boot sequence begun', 0 +boot_text: db 'OK] Boot begun', 0 kernel_found_text: db 'OK] Kernel located', 0 kernel_loading: db 'OK] Loading kernel', 0 disk_read_fail: db 'ERR] Disk read fail', 0 diff --git a/source/kernel/features/cli.asm b/source/kernel/features/cli.asm index ee3e582..07ef453 100755 --- a/source/kernel/features/cli.asm +++ b/source/kernel/features/cli.asm @@ -17,6 +17,8 @@ os_start_cli: os_read_cli: pusha + mov si, user_input + call os_upper_case ; Make the input uppercase so it's case insensitive .output_the_user_input: call os_print_newline diff --git a/source/kernel/features/disk.asm b/source/kernel/features/disk.asm index e69de29..60cade1 100644 --- a/source/kernel/features/disk.asm +++ b/source/kernel/features/disk.asm @@ -0,0 +1,175 @@ +; Reset the disk system using int 13h / AH = 00h +disk_reset: + pusha + stc + mov ah, 00h + int 13h + popa + ret + +; ------------------------------------ + +; Load the root directory into memory (into disk_buffer which is 24000h) +disk_load_root: + pusha + mov ax, 19 ; First sector of root entry + call math_lba_to_chs ; Assigns ch, cl and dh the correct values + xor ax,ax + mov dl, [ebr_drive_number] ; Drive number + mov ah, 02h ; BIOS ah code for read disk sectors to memory + mov al, 0Ch ; Root directory has 12 sectors + + mov si, root_buffer ; ES:BX should point to our buffer + mov bx, si + + ; repeat drive read 3 times (incase of random error) + mov di, 3 ; counter + ; This is basically + ; for di in range(3,1,1): + ; We test to see if we can read the disk 3 times +.try_read_disk: ; Try read the floppy three times + ; When the disk is tried to be read, the CF flag will be + ; set if there's an error, so we just clear it to return it to + ; the default state + stc ; sets the cf flag + int 13h + jnc .done_read ; jump if cf = 0 + + call disk_reset ; Reset drivers of disk + + dec di ; di -= 1 + test di, di ; if di = 0 + jnz .try_read_disk + jmp .disk_error +.disk_error: + mov si, disk_read_fail + call os_print_string + popa + ret +.done_read: + popa + ret + +; --------------------------------------------- + +; Reads a certain number of sectors into memory +; int 13h/ah = 02h read disk sectors into memory +; al = number of sectors to read +; ch = cylinder number +; cl = sector number +; dh = head number +; dl = drive number +; es:bx = points to data buffer +disk_read: + push ax + push bx + push cx + push dx + push di + + + ; cl = sector + ; ch = cylinder + ; dh = head + ; dl = drive + call math_lba_to_chs ; Get the chs address + + mov ah, 02h ; BIOS ah code for read disk sectors to memory + + ; repeat drive read 3 times (incase of random error) + mov di, 3 ; counter + +; This is basically +; for di in range(3,1,1): +; We test to see if we can read the disk 3 times +.retry: + ; When the disk is tried to be read, the CF flag will be + ; set if there's an error, so we just clear it to return it to + ; the default state + stc ; sets the cf flag + int 13h + jnc .done_read ; jump if cf = 0 + + call .disk_reset ; Reset drivers of disk + + dec di ; di -= 1 + test di, di ; if di = 0 + jnz .retry + +.fail_disk_read: + pop di + pop dx + pop cx + pop bx + pop ax + ret + +; int 13h / ah = 00h reset disk system +.disk_reset: + pusha + mov ah, 0 ; Reset drive + stc + int 13h + jc .fail_disk_read + popa + ret + +.done_read: + pop di + pop dx + pop cx + pop bx + pop ax + ret + +; ------------------------------------- + +disk_load_file: + pusha + mov di, fat12_file_name + call os_format_fat_filename + + ; Prepare values + mov si, root_buffer + xor bx,bx +.search_root: + mov di, fat12_file_name ; Move the name of the kernel into di + mov cx, 11 ; length of 'KERNEL BIN' + push si ; Preserve si + repe cmpsb ; Repeat a comparison of bytes between file name and current bytes until it finds a match + pop si ; Retrieve si + je .found_file + + add si, 32 ; increment di to the next directory entry + inc bx + cmp bx, [bdb_dir_entries_count] ; Have we reached the number of directories that exist + jl .search_root ; Repeat search + + jmp .file_not_found ; If the last dir has been searched, then there is no kernel +.found_file: + mov ax, [si+26] ; ax is now a pointer to the pointer to the file relative to the data segments :D + add ax, 20h + mov [file_cluster], ax + ; Setup registers for disk read + mov bx, data_buffer + mov dl, [ebr_drive_number] + + call disk_read ; Load file from disk into memory + jmp .done +.file_not_found: + mov si, file_not_found + call os_print_string + jmp .done +.done: + popa + ret + + + +section .data: + disk_read_fail: db 'Error: Could not read disk\n', 0 + file_not_found: db 'File not found\n', 0 + file_found: db 'File found\n', 0 + loading_root: db 'Loading root diretory\n', 0 + file_cluster: dw 0 + fat12_file_name: db ' ' diff --git a/source/kernel/features/math.asm b/source/kernel/features/math.asm index 6f988f6..b98cb25 100644 --- a/source/kernel/features/math.asm +++ b/source/kernel/features/math.asm @@ -5,6 +5,7 @@ ; H = T % heads ; C = T / headers ; input, LBA index: ax +; ouput: ; sector number: cl ; cylinder: ch ; head: dh @@ -29,7 +30,7 @@ ; cylinder (ch) = 02h ; head (cl) = 00h ; sector (dh) = 09h -os_lba_to_chs: +math_lba_to_chs: push ax push dx diff --git a/source/kernel/features/text.asm b/source/kernel/features/text.asm index 0458192..500fb01 100755 --- a/source/kernel/features/text.asm +++ b/source/kernel/features/text.asm @@ -48,6 +48,31 @@ os_print_string: popa ret +; This is similar to the previous, however it prints +; raw output (including null) and prints the number +; of character defined by ax +; IN: +; SI = pointer to start of string to be printed +; AX = Length of string to print +text_raw_output: + pusha + + mov di, ax + + mov ah, 0Eh ; int 10h teletype function, we're telling the BIOS we will print something + +.repeat: + lodsb ; Get char from si into al + int 10h ; Otherwise, print it + dec di + cmp di, 00h + je .done + jne .repeat +.done: + popa + ret + + ; -------------------------------------------- os_print_newline: diff --git a/source/kernel/games/pong.asm b/source/kernel/games/pong.asm index 71745a3..4d3fb90 100644 --- a/source/kernel/games/pong.asm +++ b/source/kernel/games/pong.asm @@ -48,24 +48,24 @@ game_pong: mov dx, [p1_y] sub dx, 5 mov [p1_y], dx - jmp .detect_input + ret .p1_down: mov dx, [p1_y] add dx, 5 mov [p1_y], dx - jmp .detect_input + ret ; Player 2 movements .p2_up: mov dx, [p2_y] sub dx, 5 mov [p2_y], dx - jmp .detect_input + ret .p2_down: mov dx, [p2_y] add dx, 5 mov [p2_y], dx - jmp .detect_input + ret ; Ball bouncing ; This should move the ball along one frame @@ -97,17 +97,17 @@ game_pong: ; Player 1 cmp al, 77h ; Pressed 'w' (player 1 up) - je .p1_up + call .p1_up cmp al, 73h ; Pressed 's' (player 1 down) - je .p1_down + call .p1_down ; Player 2 cmp al, 5bh ; Pressed '[' (player 2 up) - je .p2_up + call .p2_up cmp al, 27h ; Pressed ''' (player 2 down) - je .p2_down + call .p2_down - call .bounce_ball + ;call .bounce_ball call .draw_screen jmp .detect_input diff --git a/source/kernel/kernel.asm b/source/kernel/kernel.asm index a1ef637..ab044c5 100644 --- a/source/kernel/kernel.asm +++ b/source/kernel/kernel.asm @@ -1,12 +1,17 @@ -ORG 0h +ORG 00h BITS 16 +root_buffer equ 24000h +data_buffer equ 26000h start: mov si, boot_message call os_print_string - mov si, help_text - call os_print_string + call disk_load_root ; Loads the root directory into disk_buffer + + ; Physical address = (segment * 16) + offset + mov si, file_name + call disk_load_file call os_start_cli hlt @@ -14,7 +19,31 @@ start: halt: jmp halt -boot_message: db 'OK] Kernel successfully loaded!\n', 0 +boot_message: db 'OK] Kernel successfully loaded!\n\n', 0 +file_name: db 'hello.cws', 0 + +; Define Fat12 header +bdb_oem: db 'MSWIN4.1' ; ignore +bdb_bytes_per_sector: dw 200h ; = 512d +bdb_sectors_per_cluster: db 01h ; sector = cluster +bdb_reserved_sectors: dw 01h +bdb_fat_count: db 02h ; We've got a fat1 and fat2 +bdb_dir_entries_count: dw 0E0h ; Maximum number of root directory entries +bdb_total_sectors: dw 0B40h ; = 2880d +bdb_media_descriptor_type: db 0F0h ; ignore +bdb_sectors_per_fat: dw 09h +bdb_sectors_per_track: dw 12h ; = 18d +bdb_number_of_heads: dw 02h ; top and bottom of the floppy disk +bdb_hidden_sectors: dd 0 ; ignore +bdb_large_sector_count: dd 0 ; total sector count for fat32 (0 for fat12 or fat16) + +; extended boot record +ebr_drive_number: db 0 ; ignore + db 0 ; ignore +ebr_signature: db 29h ; boot signature, indicates that the next three fields are present (0x29) +ebr_volume_id: db 12h, 34h, 56h, 78h ; unique id for volume tracking +ebr_volume_label: db 'CrawShaw OS' ; must be 11 bytes +ebr_system_id: db 'FAT12 ' ; must be 8 bytes ; ------------------------------------------------------------------ ; FEATURES -- Code to pull into the kernel @@ -25,5 +54,8 @@ boot_message: db 'OK] Kernel successfully loaded!\n', 0 %INCLUDE "source/kernel/features/strings.asm" %INCLUDE "source/kernel/features/graphics.asm" %INCLUDE "source/kernel/features/disk.asm" + %INCLUDE "source/kernel/features/math.asm" ; GAMES -- Games that I wrote for it %INCLUDE "source/kernel/games/pong.asm" + + diff --git a/test-linux.sh b/test-linux.sh index bb5be71..af9b2fa 100755 --- a/test-linux.sh +++ b/test-linux.sh @@ -1,6 +1,9 @@ #!/bin/sh - -# This script starts the QEMU PC emulator, booting from the -# MikeOS floppy disk image - -qemu-system-i386 -soundhw pcspk -drive format=raw,file=disk_images/mikeos.flp,index=0,if=floppy +make clean +sudo make +sudo chown $(whoami) disk_images/* +qemu-system-i386\ + -drive file=disk_images/crawos.img,if=floppy,format=raw\ + -m 512m\ + -object memory-backend-file,id=pc.ram,size=512m,mem-path=/dev/shm/qemu-ram,share=on -machine memory-backend=pc.ram\ + $1 $2