commit 489b9de84143406e3918575ceab0b19931614300 Author: SowinskiBraeden Date: Sat Oct 22 23:18:16 2022 -0700 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..07ed706 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build/* \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..bea4d7b --- /dev/null +++ b/Makefile @@ -0,0 +1,57 @@ +ASM=nasm + +SRC_DIR=src +BUILD_DIR=build + +.PHONY: all floppy_image kernel bootloader clean always + +# +# Floppy image +# +floppy_image: $(BUILD_DIR)/main_floppy.img + +$(BUILD_DIR)/main_floppy.img: bootloader kernel + dd if=/dev/zero of=$(BUILD_DIR)/main_floppy.img bs=512 count=2880 + mkfs.fat -F 12 -n "NBOS" $(BUILD_DIR)/main_floppy.img + dd if=$(BUILD_DIR)/bootloader.bin of=$(BUILD_DIR)/main_floppy.img conv=notrunc + mcopy -i $(BUILD_DIR)/main_floppy.img $(BUILD_DIR)/kernel.bin "::kernel.bin" + +# +# Bootlader +# +bootloader: $(BUILD_DIR)/bootloader.bin + +$(BUILD_DIR)/bootloader.bin: always + $(ASM) $(SRC_DIR)/bootloader/boot.asm -f bin -o $(BUILD_DIR)/bootloader.bin + +# +# Kernel +# +kernel: $(BUILD_DIR)/kernel.bin + +$(BUILD_DIR)/kernel.bin: always + $(ASM) $(SRC_DIR)/kernel/main.asm -f bin -o $(BUILD_DIR)/kernel.bin + +# +# Always +# +always: + mkdir -p $(BUILD_DIR) + +# +# Clean +# +clean: + rm -rf $(BUILD_DIR)/* + +# +# Run +# +run: $(BUILD_DIR)/main_floppy.img + qemu-system-i386 -fda build/main_floppy.img + +# +# +# Debug +debug: $(BUILD_DIR)/main_floppy.img + bochs -f bochs_config diff --git a/bochs_config b/bochs_config new file mode 100644 index 0000000..d02f03d --- /dev/null +++ b/bochs_config @@ -0,0 +1,7 @@ +megs: 128 +romimage: file=/usr/share/bochs/BIOS-bochs-latest, address=0xfffe0000 +vgaromimage: file=/usr/share/bochs/VGABIOS-lgpl-latest +floppya: 1_44=build/main_floppy.img, status=inserted +boot: floppy +mouse: enabled=0 +display_library: sdl2, options="gui_debug" \ No newline at end of file diff --git a/bx_enh_dbg.ini b/bx_enh_dbg.ini new file mode 100644 index 0000000..1e4094e --- /dev/null +++ b/bx_enh_dbg.ini @@ -0,0 +1,26 @@ +# bx_enh_dbg_ini +SeeReg[0] = TRUE +SeeReg[1] = TRUE +SeeReg[2] = TRUE +SeeReg[3] = TRUE +SeeReg[4] = FALSE +SeeReg[5] = FALSE +SeeReg[6] = FALSE +SeeReg[7] = FALSE +SingleCPU = FALSE +ShowIOWindows = TRUE +ShowButtons = TRUE +SeeRegColors = TRUE +ignoreNxtT = TRUE +ignSSDisasm = TRUE +UprCase = 0 +DumpInAsciiMode = 3 +isLittleEndian = TRUE +DefaultAsmLines = 512 +DumpWSIndex = 0 +DockOrder = 0x123 +ListWidthPix[0] = 323 +ListWidthPix[1] = 292 +ListWidthPix[2] = 437 +MainWindow = 26, 23, 754, 500 +FontName = Normal diff --git a/src/bootloader/boot.asm b/src/bootloader/boot.asm new file mode 100644 index 0000000..d174ae6 --- /dev/null +++ b/src/bootloader/boot.asm @@ -0,0 +1,222 @@ +org 0x7C00 +bits 16 + +%define ENDL 0x0A + +; +; FAT12 header +; +jmp short start +nop + +bdb_oem: db 'MSWIN4.1' ; 8 bytes +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 ; 2880 * 512 = 1.44MB +bdb_media_desciptor_type: db 0F0h ; F0 = 3.5" floppy disk +bdb_sectors_per_fat: dw 9 ; 9 sectors/fat +bdb_sectors_per_track: dw 18 +bdb_heads: dw 2 +bdb_hidden_sectors: dd 0 +bdb_large_sector_count: dd 0 + +; extended boot reord +ebr_drive_number: db 0 ; 0x00 floppy, 0x80hdd, useless + db 0 ; reserved +ebr_signature: db 29h +ebr_volume_id: db 12h, 34h, 56h, 78h ; serial number, value doesn't matter +ebr_volume_label: db 'FLAMIOS ' ; 11 bytes, padded with spaces +ebr_system_id: db 'FAT12 ' ; 8 bytes + +; +; Code goes here +; + +start: + jmp main + +; +; Prints a string to the screen. +; Params: +; - ds:si points to string +; +puts: + ; save registers we will modify + push si + push ax + +.loop: + lodsb ; loads next character in al + or al, al ; verify if next character is null? + jz .done + + mov ah, 0x0e ; call bios interrupt + int 0x10 + + jmp .loop + +.done: + pop ax + pop si + ret + +main: + + ; setup data segments + mov ax, 0 ; can't write to ds/es directly + mov ds, ax + mov es, ax + + ; setup stack + mov ss, ax + mov sp, 0x7C00 ; stack grows downwards from where we are loaded in memory + + ; read something from floppy disk + ; BIOS should set DL to drive number + mov [ebr_drive_number], dl + + mov ax, 1 ; LBA=1, second sector from disk + mov cl, 1 ; 1 sector to read + mov bx, 0x7E00 ; data should be after the bootloader + call disk_read + + ; print hello wrold message + mov si, msg_hello + call puts + + cli ; disable interrupts, this way CPU can't get out of "halt" state + hlt + +; +; Error handlers +; + +floppy_error: + mov si, msg_read_failed + call puts + jmp wait_key_and_reboot + +wait_key_and_reboot: + mov ah, 0 + int 16h ; wait for keypress + jmp 0FFFFh:0 ; jump to beginning of BIOS, should reboot + +.halt: + cli ; disable interrupts, this way CPU can't get out of "halt" state + hlt + +; +; Disk routines +; + +; +; Converts an LBA address to a CHS address +; Parameters: +; - ax: LBA address +; Returns: +; - cx [bits 0-5]: sector number +; - cx [bits 6-15]: cylinder +; - dh: head +; + +lba_to_chs: + + push ax + push dx + + xor dx, dx ; dx = 0 + div word [bdb_sectors_per_track] ; ax = LBA / SectorsPerTrack + ; dx = LBA % SectorsPerTrack + + inc dx ; dx = (LBA % SectorsPerTrack + 1) = sector + mov cx, dx ; cx = sector + + xor dx, dx ; dx = 0 + div word [bdb_heads] ; ax = (LBA / SectorsPerTrack) / Heads = cylinder + ; dx = (LBA / SectorsPerTrack) % Heads = head + mov dh, dl ; dh = head + mov ch, al ; ch = cyliner (lower 8 bits) + shl ah, 6 + or cl, ah ; put upper 2 bits of cylinder in CL + + pop ax + mov dl, al + pop ax + ret + + +; +; Reads sectors from a disk +; Parameters: +; - ax: LBA addres +; - cl: number of sectors to read (up to 128) +; - dl: drive number +; - es:bx: memory address where to store read data +; + +disk_read: + + push ax ; save registers we will modify + push bx + push cx + push dx + push di + + push cx ; temporarily save CL (number of sectors to read) + call lba_to_chs ; compute CHS + pop ax ; AL = number of sectors to read + + mov ah, 02h + mov di, 3 ; retry count + +.retry: + pusha ; save all registers, we don't know what bios modifies + stc ; set carry flag, some BIOS's don't set it + int 13h ; carry flag cleared = success + jnc .done ; jump if carry not set + + ; read failed + popa + call disk_reset + + dec di + test di, di + jnz .retry + +.fail: + ; all attempts are exhausted + jmp floppy_error + +.done: + popa + + pop di + pop dx + pop cx + pop bx + pop ax ; srestore registers modified + ret + +; +; Disk reset +; Parameters: +; dl: drive number +; +disk_reset: + pusha + mov ah, 0 + stc + int 13h + jc floppy_error + popa + ret + +msg_hello: db 'Hello World!', ENDL, 0 +msg_read_failed: db 'Read from disk failed!', ENDL, 0 + + +times 510-($-$$) db 0 +dw 0AA55h \ No newline at end of file diff --git a/src/kernel/main.asm b/src/kernel/main.asm new file mode 100644 index 0000000..9d4a622 --- /dev/null +++ b/src/kernel/main.asm @@ -0,0 +1,57 @@ +org 0x7C00 +bits 16 + +%define ENDL 0x0A + +start: + jmp main + +; +; Prints a string to the screen. +; Params: +; - ds:si points to string +; +puts: + ; save registers we will modify + push si + push ax + +.loop: + lodsb ; loads next character in al + or al, al ; verify if next character is null? + jz .done + + mov ah, 0x0e ; call bios interrupt + int 0x10 + + jmp .loop + +.done: + pop ax + pop si + ret + +main: + + ; setup data segments + mov ax, 0 ; can't write to ds/es directly + mov ds, ax + mov es, ax + + ; setup stack + mov ss, ax + mov sp, 0x7C00 ; stack grows downwards from where we are loaded in memory + + ; print message + mov si, ms_hello + call puts + + hlt + +.halt: + jmp .halt + +ms_hello: db 'Hello World!', ENDL, 0 + +times 510-($-$$) db 0 +dw 0AA55h \ No newline at end of file