From d83871e1612ebc77681e0350260aaf8ffcdc655c Mon Sep 17 00:00:00 2001 From: deadvey Date: Thu, 30 Oct 2025 22:57:31 +0000 Subject: [PATCH] Added a os_upper_case function --- Makefile | 4 +- data/{hello-world.cr => hello.cws} | 0 source/bootload/boot.asm | 173 +++++++++++++++++++---------- source/kernel/features/cli.asm | 48 +++++--- source/kernel/features/strings.asm | 25 ++++- source/kernel/features/utils.asm | 18 +++ source/kernel/kernel.asm | 8 +- 7 files changed, 193 insertions(+), 83 deletions(-) rename data/{hello-world.cr => hello.cws} (100%) create mode 100644 source/kernel/features/utils.asm diff --git a/Makefile b/Makefile index 03eabc1..6757948 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,8 @@ cdrom: $(BUILD_DIR)/crawos.iso $(BUILD_DIR)/crawos.iso: floppy_image mkdir -p disk_images mkisofs -quiet -V 'CRAWOS' -input-charset iso8859-1 -o disk_images/crawos.iso -b crawos.img disk_images/ + chmod 755 disk_images/* + chgrp users disk_images/* # Floppy image # Fat12 @@ -36,4 +38,4 @@ $(BUILD_DIR)/kernel.bin: # Clean clean: - rm -f disk-images/* + rm -f disk_images/* diff --git a/data/hello-world.cr b/data/hello.cws similarity index 100% rename from data/hello-world.cr rename to data/hello.cws diff --git a/source/bootload/boot.asm b/source/bootload/boot.asm index 9922752..15bc38a 100644 --- a/source/bootload/boot.asm +++ b/source/bootload/boot.asm @@ -5,27 +5,27 @@ jmp short main nop ; Define Fat12 header -bdb_oem: db 'MSWIN4.1' -bdb_bytes_per_sector: dw 512 -bdb_sectors_per_cluster: db 1 -bdb_reserved_sectors: dw 1 -bdb_fat_count: db 2 -bdb_dir_entries_count: dw 0E0h -bdb_total_sectors: dw 2880 -bdb_media_descriptor_type: db 0F0h -bdb_sectors_per_fat: dw 9 -bdb_sectors_per_track: dw 18 -bdb_heads: dw 2 -bdb_hidden_sectors: dd 0 -bdb_large_sector_count: dd 0 +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 - db 0 -ebr_signature: db 29h -ebr_volume_id: db 12h, 34h, 56h, 78h -ebr_volume_label: db 'CrawShaw OS' -ebr_system_id: db 'FAT12 ' +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 main: ; Setup registers @@ -37,11 +37,11 @@ main: mov sp, 7C00h ; Read from disk - ;mov [ebr_drive_number], dl - ;mov ax, 1 - ;mov cl, 1 - ;mov bx, 7E00h - ;call disk_read + ; mov [ebr_drive_number], dl + ; mov ax, 1 + ; mov cl, 1 + ; mov bx, 7E00h + ; call disk_read ; Output boot text mov si, boot_text @@ -54,46 +54,54 @@ main: ; root dir: gives location of data ; data: stores the actual data - ; Get LBA of root dir - mov ax, [bdb_sectors_per_fat] - mov bl, [bdb_fat_count] + ; Get LBA of root dir (sectors per fat * fat count) + number of reserved sectors + mov ax, [bdb_sectors_per_fat] ; ax = 09h + mov bl, [bdb_fat_count] ; bl = 02h xor bh,bh ; clear bh - mul bx ; 9 * 2 = 18 - add ax, [bdb_reserved_sectors] ; The LBA of root dir + mul bx ; ax*bx = sectors per fat * fat count = 09h * 02h = 18 + add ax, [bdb_reserved_sectors] ; then add on the reserved sector (1) = The LBA of root dir = 19d = 13h push ax ; Push to stack + ; the top of the ax stack now stores the LBA of the root directory - mov ax, [bdb_dir_entries_count] - shl ax,5 ; ax *= 32 (shifting 5 times) - xor dx,dx ; Clear dx - div word [bdb_bytes_per_sector] ;32*num of entries)/bytes per sector + ; determine the size of the root directory + mov ax, [bdb_dir_entries_count] ; move the number of root directory entries into ax (E0h) + shl ax,5 ; ax *= 32 (shifting 5 times) + xor dx,dx ; Clear dx (remainder) + div word [bdb_bytes_per_sector] ;(32*num of entries)/bytes per sector = total number of sectors we need to read test dx,dx ; See if there's a remainder jz root_dir_after - inc ax ; Add one if there's a remainder + inc ax ; Add one if there's a remainder (this is like rounding up) +; read the root directory tree into memory root_dir_after: + ; read the data from the root directory from disk mov cl, al pop ax ; LBA of root dir mov dl, [ebr_drive_number] mov bx, buffer - call disk_read + call disk_read ; convert the LBA of the root directory to a CHS xor bx,bx ; clear bx - mov di, buffer ; Loaded root dir into memory + mov di, buffer ; Loaded root dir into memory, now we need to find the kernel + ; di points to the start of this memory +; Search for 'KERNEL BIN' in a loop until all root files entries have been checked search_for_kernel: - mov si, file_kernel_bin ; Move the name of the kernel into si - mov cx, 11 + mov si, file_kernel_bin ; Move the name of the kernel into si (string pointer) + mov cx, 11 ; length of 'KERNEL BIN' push di ; Preserve di repe cmpsb ; Repeat a comparison of bytes between kernel name and current bytes until it finds a match pop di ; Retrieve di je found_kernel - add di, 32 ; Next directory entry + add di, 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_for_kernel ; Repeat search jmp kernel_not_found ; If the last dir has been searched, then there is no kernel + +; The kernel has not been found so output an error and halt kernel_not_found: mov si, kernel_load_error call print_string @@ -101,11 +109,12 @@ kernel_not_found: hlt jmp halt +; The kernel has been found found_kernel: mov si, kernel_found_text call print_string ; Find kernel cluster - mov ax, [di+26] + mov ax, [di+26] ; di is the address of the kernel, 26 is the offset mov [kernel_cluster], ax mov ax, [bdb_reserved_sectors] @@ -160,6 +169,8 @@ next_cluster_after: jmp load_kernel_loop read_finish: ; Load kernel + mov si, kernel_loading + call print_string mov dl, [ebr_drive_number] mov ax, kernel_load_segment mov ds, ax @@ -174,33 +185,65 @@ halt: ; LBA = index of data segment on disk ; CHS = cylinder, header, sector +; T = LBA/sectors per track +; S = (LBA%sectors per track) + 1 +; H = T % heads +; C = T / headers ; input, LBA index: ax -; sector number: cx [0-5] -; cylinder: cx [6-15] +; sector number: cl +; cylinder: ch ; head: dh +; Example where LBA = 50h (CHS = 2,0,9) +; ax = 0050h, push this to the stack +; dx = 0000h +; dx = 50h % 12h = 0008h +; ax = 50h / 12h = 0004h +; dx = 0009h +; cx = 0009h +; dx = 0000h +; dx = 04h % 02h = 0000h +; ax = 04h / 02h = 0002h +; dh = 00h (dx = 0000h) +; ch = 02h (cx = 0209h) +; ah = 00h (ax = 0002h) +; cl = 09h OR 00h = 09h (cx = 0209h) +; ax = 0050h +; dl = 50h (dx = 0050h) +; ax = 0050h +; thus: +; cylinder (ch) = 02h +; head (cl) = 00h +; sector (dh) = 09h lba_to_chs: push ax push dx xor dx,dx ; clear dx - div word [bdb_sectors_per_track] ;(LBA % sectors per track) + 1 = sector + div word [bdb_sectors_per_track] ; (LBA % sectors per track) + 1 = sector inc dx ; sector, dx stores the remainder so we increment that. mov cx,dx xor dx,dx ; clear dx - div word [bdb_heads] + div word [bdb_number_of_heads] + mov dh,dl ; head, dx stores remainder so we move that up 8 bits to dh - mov dh,dl ; head mov ch,al - shl ah, 6 - or CL, AH ; cylinder + shl ah, 6 ; * 32 + or cl, ah ; cylinder pop ax mov dl,al pop ax - RET + ret +; 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 @@ -209,22 +252,32 @@ disk_read: push di - call lba_to_chs + ; cl = sector + ; ch = cylinder + ; dh = head + ; dl = drive + call lba_to_chs ; Get the chs address - mov ah, 02h + 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: - stc + ; 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 + jnc done_read ; jump if cf = 0 call disk_reset ; Reset drivers of disk - dec di - test di, di + dec di ; di -= 1 + test di, di ; if di = 0 jnz retry fail_disk_read: @@ -233,6 +286,7 @@ fail_disk_read: hlt jmp halt +; int 13h / ah = 00h reset disk system disk_reset: pusha mov ah, 0 ; Reset drive @@ -280,14 +334,15 @@ print_string: pop si ret -boot_text: db '[OK] Boot sequence begun...', 0 -kernel_found_text: db '[OK] Kernel located...', 0 -disk_read_fail: db '[ERR] Failed to read disk!', 0 +boot_text: db 'OK] Boot sequence 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 file_kernel_bin: db 'KERNEL BIN' ; Must have a double space between KERNEL and BIN -kernel_load_error: db '[ERR] Kernel not found!', 0 +kernel_load_error: db 'ERR] Kernel not found', 0 kernel_cluster: dw 0 -kernel_load_segment: equ 2000h +kernel_load_segment: equ 2000h ; an area in memory we know should be available kernel_load_offset: equ 0 diff --git a/source/kernel/features/cli.asm b/source/kernel/features/cli.asm index 0dcce7e..5ef4e5c 100755 --- a/source/kernel/features/cli.asm +++ b/source/kernel/features/cli.asm @@ -22,30 +22,41 @@ os_read_cli: call os_print_newline .check_matches: ; Check if the user input matches any internal commands - mov si, user_input - mov di, help_string + ; Help + mov di, user_input + mov si, help_string call os_compare_strings cmp cl, 1 je help - mov si, user_input - mov di, clear_string + ; Clear screen + mov di, user_input + mov si, clear_string call os_compare_strings cmp cl, 1 je clear + + ; Reboot + mov di, user_input + mov si, reboot_string + call os_compare_strings + cmp cl, 1 + je os_reboot + + ; Reboot + mov di, user_input + mov si, cat_string + call os_compare_strings + cmp cl, 1 + je cat - mov si, user_input - mov di, pong_string + ; Pong + mov di, user_input + mov si, pong_string call os_compare_strings cmp cl, 1 je pong - mov si, user_input - mov di, snake_string - call os_compare_strings - cmp cl, 1 - je snake - jmp .unkown .unkown: @@ -68,14 +79,14 @@ help: call os_print_string_nl call os_read_cli.finish +cat: + call util_cat + call os_read_cli.finish + pong: call game_pong call os_read_cli.finish -snake: - call game_snake - call os_read_cli.finish - section .data welcome_text db 'Welcome to CrawOS, the Cool, Real and AWsome Operating System', 0 user_input times 20 db 0 @@ -83,8 +94,9 @@ section .data prompt db 'CrawOS sh> ', 0 help_string db 'HELP', 0 clear_string db 'CLEAR', 0 + reboot_string db 'REBOOT', 0 + cat_string db 'CAT', 0 pong_string db 'PONG', 0 - snake_string db 'SNAKE', 0 - help_text db 'This is for Cowards: "HELP" for this help text, "CLEAR" to clear the screen, esc to reboot', 0 + help_text db 'This is for Cowards: "HELP" for this help text, "CLEAR" to clear the screen, esc or "REBOOT" to reboot', 0 command_result_text db 'You typed: ', 0 unknown_command db 'Error: Unkown Command.. ', 0 diff --git a/source/kernel/features/strings.asm b/source/kernel/features/strings.asm index 01abb11..17af0fd 100755 --- a/source/kernel/features/strings.asm +++ b/source/kernel/features/strings.asm @@ -12,7 +12,7 @@ os_compare_strings: .compare: lodsb scasb ; Compare di to si - jne .unequal ; If they are no equal, jump to .unequal + jne .unequal ; If they are not equal, jump to .unequal cmp al, 0 ; Check if string is finished je .equal ; If it has, return true jmp .compare ; Finally, repeat @@ -24,3 +24,26 @@ os_compare_strings: .equal: mov cl, 1 ret + + +; Convert a string to all upper case +os_upper_case: + pusha + mov di, si +.loop: + lodsb + inc di + cmp al, 0 + je .finish + cmp al, 7Ah + jns .loop + cmp al, 61h + js .loop + sub al, 20h + dec di + stosb + jmp .loop +.finish: + popa + ret + diff --git a/source/kernel/features/utils.asm b/source/kernel/features/utils.asm new file mode 100644 index 0000000..5a0dffe --- /dev/null +++ b/source/kernel/features/utils.asm @@ -0,0 +1,18 @@ +; Outputs the contents of a file +util_cat: + pusha + + call os_print_newline + + mov si, cat_prompt + call os_print_string + + mov ax, 11 ; length of input + mov di, user_input + + popa + ret + + +section .data: + cat_prompt db 'Enter file name: ', 0 diff --git a/source/kernel/kernel.asm b/source/kernel/kernel.asm index a3dfd28..be22276 100644 --- a/source/kernel/kernel.asm +++ b/source/kernel/kernel.asm @@ -2,6 +2,8 @@ ORG 0h BITS 16 start: + mov si, boot_message + call os_upper_case mov si, boot_message call os_print_string_nl @@ -14,7 +16,7 @@ start: halt: jmp halt -boot_message: db 0Dh, 'Welcome to CrawOS!', 0Dh, 0 +boot_message: db 'kernel successfully loaded!', 0 ; ------------------------------------------------------------------ ; FEATURES -- Code to pull into the kernel @@ -24,9 +26,7 @@ boot_message: db 0Dh, 'Welcome to CrawOS!', 0Dh, 0 %INCLUDE "source/kernel/features/power.asm" %INCLUDE "source/kernel/features/strings.asm" %INCLUDE "source/kernel/features/graphics.asm" - %INCLUDE "source/kernel/features/sound.asm" - %INCLUDE "source/kernel/features/basic.asm" - %INCLUDE "source/kernel/features/math.asm" + %INCLUDE "source/kernel/features/utils.asm" ; GAMES -- Games that I wrote for it %INCLUDE "source/kernel/games/pong.asm" %INCLUDE "source/kernel/games/snake.asm"