From f4c5d59d8e40c308bc4411e113dd46b354a9e2fe Mon Sep 17 00:00:00 2001 From: Greg Bowne Date: Sun, 24 Mar 2024 21:09:02 -0700 Subject: [PATCH] adding bootloader files from the issue in gittea --- .vscode/browse.vc.db | Bin 33939456 -> 33939456 bytes .vscode/browse.vc.db-shm | Bin 32768 -> 32768 bytes .vscode/browse.vc.db-wal | Bin 82192 -> 0 bytes src/boot/boot.asm | 253 ++++++++++++++++++++++----------------- src/boot/boot2.asm | 210 +++++++++++++------------------- 5 files changed, 224 insertions(+), 239 deletions(-) diff --git a/.vscode/browse.vc.db b/.vscode/browse.vc.db index 0dd233d22fe6b1b65416e2b1c0c6b25d3716b07b..0da4a0d04bee1133668435113af3e84f76119f17 100644 GIT binary patch delta 2778 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 N>U+S<)c1ge2>@b80pS1u diff --git a/.vscode/browse.vc.db-shm b/.vscode/browse.vc.db-shm index 393371e9adfd62d87381ce987d3247ef5cc5a839..795ab0e70a110a7b1ee150a6ed2f1cf0414f0801 100644 GIT binary patch delta 267 zcmZo@U}|V!s+V}A%K!p$3=9m63=9e&w!Q!Z!;asapY^g13W%GWsB0;?(admuYxUMJ z+2y3F2bl-M|B(PxY+^m9EfWI+12Y2ygB=3{10N#;13x1JgE%7tgA^kJgFGW{aj?FP z8+o0W*%){>Zd7MxW@O;sxbZg=GZTZr#*OEhnAsV4H*WmQ$IQXNw{fF9FEa}R7g(N^ TfqUb|`FzaG44fM`RWMW`pU}NB5;M#bR(GURf=Q73s diff --git a/.vscode/browse.vc.db-wal b/.vscode/browse.vc.db-wal index a58895a7e3aaae2b5ce0f223c908db513acd7b10..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 GIT binary patch literal 0 HcmV?d00001 literal 82192 zcmXr7XKP~6eI&uapuhkEYi2|$Ze4G)^;^R1{mE06B^ekPSdhhw{vLTRxhL@(F9QPu ztGpD0{1W*Jc@KFh`AZ;Gqj)p~MnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ON zU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz5lA2ARtLtr!nMnhmU z1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0q zLtr!nMnhmU1W-aih1r*pz%07~QEEVnpeq4zt}{?ZQiOAPffAA;oNEdckrd%vOaMAW z0Oh=ZR^i=hl0EM=;O7NEPYaM=f)Xa9oY4>%4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R z7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5E$YiFo@0z zP^I5_0Y@HO*>fu{{{QHC0Yg0bjyiud1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ON zU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONfY=ZK?YkeY=LM)T zFfgE;7hq=cJb1~k8{+Wu0zBlU&xJK2DhQMeDjE2By2#kinXb6mkz-S1J zhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kin zPzV7UpBJFU;wvl+y;T6`T>zdgKA9;wI&?fQz@lMO{AM>H$InCVjE2By z2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1J zhQMeDjE2By2#kgR6+&Q$o)@47ayNA0fsvVuv8#!bsf(qNsjG#fiLsNprG=4!lL^Lo z0ozsAxeKn#+y_4|0D4-0yayFRa@2^?5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7 zfzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2cG$BCZc>(Gy zzOsVQX?Ry$)9}8jC5b7CC5gEyT7&ewfcei@cNln2J~Mh=z@SNpqYfDjfzc2c4S~@R z7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7 zfzc2c4S~@Rpe+FHyEh;Jh*ASm1YJ2`fotV}GLj;k%L~+z6ydysfV}epvc=@u=D#sE zfS(s|Nq&iZg}jHn6m0`})b!C17!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7 zfzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GZ|-2 z3HHgzDbCRwCg%khE;{n>z`Yo?(enc6o7zTg8x4Wc5Eu=C(GVC7fzc2c4S~@R7!85Z z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVE05CCn? XCvaSV0a0o|iU_SU&_Gf|kMjZmIs9&r diff --git a/src/boot/boot.asm b/src/boot/boot.asm index 9ed4f16..926dd31 100644 --- a/src/boot/boot.asm +++ b/src/boot/boot.asm @@ -1,131 +1,166 @@ -[BITS 16] -[ORG 0x7c00] +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Stage 1 bootloader for ClassicOS ; +; -------------------------------- ; +; Determines if it was loaded from ; +; a floppy disk or an hard disk ; +; drive, and then loads stage 2 ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;;;;;;;;;;;;;;;;;;;;;;; +; Assembler directives ; +;;;;;;;;;;;;;;;;;;;;;;;; + +; tells the assembler that the program will be loaded at 0x7C00 +; this is done by the BIOS +org 0x7C00 + +; we are targeting (x86) 16-bit real mode +bits 16 + +;;;;;;;;;;;;;;;;; +; Jump to start ; +;;;;;;;;;;;;;;;;; +jmp start + +;;;;;;;; +; Data ; +;;;;;;;; +; fdd geometry & options +fddsamt db 8 ; how many sectors to load +fddretr db 5 ; max retries for fdd operations +fddcretr db 0 ; current retries left + +; misc strings +welcome1 db "Welcome to the ClassicOS Stage 1 bootloader.", 13, 10, 0 +disktype db "Drive type: ", 0 +diskfdd db "FDD", 13, 10, 0 +diskhdd db "HDD", 13, 10, 0 +loaded db "Data loaded!", 13, 10, 0 + +; errors +fdderes db "FDD reset failed.", 13, 10, 0 +fddeload db "FDD read failed.", 13, 10, 0 + +; storage +disknum db 0 + +;;;;;;;;;;; +; Program ; +;;;;;;;;;;; start: - ; Processor initialization (only stack segment register needed) - mov ss, 0x1000 ; Set stack segment register - mov sp, 0x7C00 ; Set stack pointer (SP) - mov ds, ss ; Set data segment register (DS) + xor ax, ax ; set up segment registers to segment 0 since + mov ds, ax ; our addresses are already relative to 0x7C00 + mov es, ax -; Identify boot device using BIOS calls -identify_drive: - mov ah, 0x0E ; Get Interrupt Vector for INT 13h (Disk Services) - int 0x80 - cmp cl, 0x41 ; Check for floppy drive interrupt vector (example) - je is_floppy - cmp cl, 0x80 ; Check for hard disk interrupt vector (example) - je is_harddrive - ; Handle invalid drive type (error handling) - ; ... + mov [disknum], dl ; save disk number to memory -is_floppy: - ; Perform floppy disk access (assuming AH=0x02 for read sectors) - mov ah, 0x02 ; Read sectors - mov al, 1 ; Number of sectors to read (1) + mov ah, 0x01 ; set cursor shape + mov cx, 0x0100 ; hide cursor by setting ch = 1 and cl = 0x00 + int 0x10 ; video interrupt - ; Set CH, CL, DH, DL for floppy based on your system configuration - ; (Replace these values with appropriate settings for your floppy drive) - mov ch, 0 ; Cylinder (example, adjust based on your floppy) - mov cl, 1 ; Sector number (example, adjust based on boot sector location) - mov dh, 0 ; Head number (example, typically 0 for single-sided floppies) - mov dl, 0x00 ; Drive number (0x00 for floppy drive A) + mov ah, 0x08 ; read page number into bh + int 0x10 - ; Set ES:BX to the memory address where you want to store the read data - mov es, 0x1000 ; Example segment (adjust as needed) - mov bx, 0x0 ; Memory offset within the segment (example) + mov si, welcome1 ; print welcome + call printstr - int 0x13 - jc error_floppy + mov si, disktype ; print first part of disk type + call printstr - ; Implement error handling (omitted here for brevity) - ; Process the read data from the floppy sector (load second stage bootloader, etc.) + mov dl, [disknum] ; restore disk number - should not be + ; strictly necessary but you never know + and dl, 0x80 ; sets zf if disk is floppy + jz fddload -is_harddrive: +hddload: + mov si, diskhdd ; print disk type + call printstr - ; Sample code (not guaranteed to work universally) - mov ah, 0x02 ; Set function for read sectors - mov al, 0x01 ; Read one sector - ; Set CH, CL, DH for desired sector location (e.g., first sector) - mov dl, 0x80 ; Drive number (assuming drive A is boot device) - mov es, segment_address ; Set ES for buffer to store read data - mov bx, buffer_offset ; Set BX for offset within the buffer + jmp halt ; not implemented! - int 13h ; Raise BIOS interrupt for disk read +fddload: + mov si, diskfdd ; print disk type + call printstr - ; Check Carry flag for error handling - jc harddrive_not_found ; Jump if Carry flag is set (potential error) +fddload_onto_reset: + mov ah, [fddretr] ; load max retries in memory + mov [fddcretr], ah +fddload_reset: + mov si, fdderes ; load error message pointer + dec byte [fddcretr] ; decrement the retries counter + jz fddload_err ; if it is 0, we stop trying - ; Hard drive likely present (further processing can occur) + mov ah, 0x00 ; otherwise, reset function (int 0x13) + int 0x13 + jc fddload_reset ; if jc (error), we try again - ; ... (rest of your bootloader code) +fddload_onto_load: + mov ah, [fddretr] ; reset retries counter + mov [fddcretr], ah + mov ax, 0x1000 ; need to stay within real mode limits + mov es, ax +fddload_load: ; loads 512*fddsamt bytes from sector 2 on. + mov si, fddeload + dec byte [fddcretr] + jz fddload_err - harddrive_not_found: - ; Handle error condition (missing drive or other issue) + mov dh, 0 ; head 0 + mov ch, 0 ; cyl/track 0 + mov cl, 2 ; start sector + mov bx, 0 ; memory location + mov al, [fddsamt] ; how many sectors to read + mov ah, 0x02 ; read function (int 0x13) + int 0x13 + jc fddload_load ; if jc (error), we try again + cmp al, [fddsamt] ; also if al is not 1, we have a problem + jnz fddload_load - ; ... (error handling logic) +fddload_done: + mov si, loaded ; we have successfully loaded the data + call printstr + jmp halt ; this will be jmp 0x1000:0x0000 -memory_error: - ; ... (error handling or continue with limited memory) +fddload_err: + call printstr ; print + jmp halt ; and die -; Second stage loading (simplified example) -; Here's an improved version of the load_second_stage section with the placeholder jump replaced by actual loading logic: -; Code snippet +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; printstr routine, prints the string pointed by si using int 0x10 ; +; sets the direction flag to 0 ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +printstr: + cld ; clear df flag - lodsb increments si +printstr_loop: + lodsb ; load next character into al, increment si + or al, al ; sets zf if al is 0x00 + jz printstr_end + mov ah, 0x0E ; teletype output (int 0x10) + int 0x10 ; print character + jmp printstr_loop +printstr_end: + ret ; return to caller address -load_second_stage: - ; Calculate address of second stage bootloader (assuming offset from boot sector) - mov dx, 0x0000 ; Clear DX register for better calculation - add dx, sector_count ; Add number of sectors to skip (adjust as needed) - shl dx, 5 ; Multiply by sector size (512 bytes) - add dx, 0x7C00 ; Add boot sector address offset - ; Read second stage bootloader from calculated address - mov ah, 0x02 ; Function for reading sectors - mov al, 1 ; Number of sectors to read (1 for second stage) - mov es, dx ; Set ES segment register to calculated address - mov bx, 0x0000 ; Set BX offset within the segment (example) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; halt routine - infinite loop ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +halt: + cli + jmp halt - int 13h ; Raise BIOS interrupt for disk read +;;;;;;;;;;; +; Padding ; +;;;;;;;;;;; +; $ is the address of the current line, $$ is the base address for +; this program. +; the expression is expanded to 510 - ($ - 0x7C00), or +; 510 + 0x7C00 - $, which is, in other words, the number of bytes +; before the address 510 + 0x7C00 (= 0x7DFD), where the 0xAA55 +; signature shall be put. +times 510 - ($ - $$) db 0x00 - ; Check Carry flag for error handling - jc memory_error ; Jump if Carry flag is set (potential error) - - ; Second stage likely loaded successfully, jump to it - jmp second_stage_address ; Direct jump to the defined address - -error_floppy: - ; Display a basic error message (optional) - mov ah, 0x0E ; BIOS video call for displaying text (educational purposes) - mov bh, 0x00 ; Set background color (black) - mov bl, 0x07 ; Set text color (white) - mov dx, error_floppy_message ; Address of error message string - int 0x10 ; BIOS video interrupt - - ; Halt the boot process (replace with a retry or more advanced error handling) - hlt ; Halt instruction - -error_floppy_message db 'Floppy disk read error!', 0x0 - -memory_error: - ; Check for available memory (replace with actual method) - ; ... (e.g., call BIOS service for memory size or use a constant value) - cmp available_memory, memory_threshold ; Compare with minimum required memory - jb limited_memory_boot ; Jump if below threshold - - ; ... (standard error handling for other scenarios) - -limited_memory_boot: - ; Perform minimal setup for limited memory boot - ; ... (disable non-essential features, adjust kernel parameters) - - ; Load and jump to second stage bootloader (potentially with adjustments) - ; ... (modify loading logic if necessary) - -; Define variables used for calculation (adjust as needed) -sector_count db 1 ; Number of sectors to skip before second stage (change if needed) -second_stage_address equ 0x8000 ; Replace with actual address of your second stage bootloader -available_memory equ 0x100000 ; Replace with actual memory size detection (1MB in this example) -memory_threshold equ 0x0A0000 ; Example minimum memory required (adjust based on needs) - -; Padding and magic number (standard practice) -times 510-($-$$) db 0 -dw 0xaa55 +;;;;;;;;;;;;;;;;;; +; BIOS signature ; +;;;;;;;;;;;;;;;;;; +dw 0xAA55 diff --git a/src/boot/boot2.asm b/src/boot/boot2.asm index fffde1f..cf5c437 100644 --- a/src/boot/boot2.asm +++ b/src/boot/boot2.asm @@ -1,141 +1,91 @@ -[BITS 16] -[ORG 0x0000] +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Stage 2 bootloader for ClassicOS ; +; -------------------------------- ; +; Loads the kernel, sets up tables, ; +; and transitions to protected mode ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;;;;;;;;;;;;;;;;;;;;;;; +; Assembler directives ; +;;;;;;;;;;;;;;;;;;;;;;;; + +; tells the assembler that the program will be loaded at 0x8000 +; this is done by the first stage bootloader +org 0x8000 + +; we are targeting (x86) 16-bit real mode +bits 16 + +;;;;;;;;;;;;;;;;; +; Jump to start ; +;;;;;;;;;;;;;;;;; +jmp start + +;;;;;;;; +; Data ; +;;;;;;;; +; kernel file name +kername db "KERNEL.BIN", 0 + +;;;;;;;;;;; +; Program ; +;;;;;;;;;;; start: - ; Initialize stack - MOV AX, 0x0000 ; Set up a segment for the stack - MOV SS, AX - MOV SP, 0xFFFF ; Stack grows downwards from the top of the segment + xor ax, ax ; set up segment registers to segment 0 since + mov ds, ax ; our addresses are already relative to 0x8000 + mov es, ax - ; Copy boot sector data to a safe location - call mCopyBootSector - ; Load the kernel - CALL load_kernel + mov si, kername ; print kernel file name + call printstr -switch_to_protected_mode: - CLI ; Disable interrupts - lgdt [gdt_descriptor] ; Load the global descriptor table - MOV EAX, CR0 - OR EAX, 0x1 ; Set the PE (Protection Enable) bit - MOV CR0, EAX - ; Far jump to flush CPU queue after changing to protected mode - JMP CODE_SEG:init_pm ; CODE_SEG is the segment selector for code segment in GDT -init_pm: - ; Update segment registers here - ; Set code segment register (CS) to point to code segment descriptor (selector 1) - mov ax, 0x0001 - mov ds, ax ; Set data segment register (DS) to point to data segment descriptor (selector 2) - mov es, ax ; Set other segment registers (ES, SS, etc.) as needed - RET + ; Load the kernel into memory + ; ... -enable_a20: - cli ; Disable interrupts to prevent interference - call a20wait ; Wait for the keyboard controller to be ready - mov al, 0xAD ; Command to disable keyboard - out 0x64, al ; Send command to keyboard controller command port - call a20wait ; Wait for the keyboard controller to be ready - mov al, 0xD0 ; Command to read output port - out 0x64, al ; Send command to keyboard controller command port - call a20wait ; Wait for the keyboard controller to be ready - in al, 0x60 ; Read current state of output port - or al, 0x02 ; Set A20 bit - out 0x64, al ; Send command to keyboard controller command port - call a20wait ; Wait for the keyboard controller to be ready - mov al, 0xD1 ; Command to write output port - out 0x64, al ; Send command to keyboard controller command port - call a20wait ; Wait for the keyboard controller to be ready - mov al, 0xAE ; Command to re-enable keyboard - out 0x64, al ; Send command to keyboard controller command port - sti ; Re-enable interrupts - ret + ; Set up GDT, IDT, IVT + ; ... -; Wait for keyboard controller to be ready -a20wait: - in al, 0x64 ; Read keyboard controller status port - test al, 0x02 ; Check if input buffer is full - jnz a20wait ; Wait until it's not full - ret + ; Switch to protected mode + ; ... -; Enter kernel space and jump to the kernel entry point -JMP 0x1000:0x0000 + ; Set up stack and start executing kernel's code + ; ... -; Code to set up flat memory model for protected mode -; This involves setting up the segment registers with selectors -; that point to descriptors in the GDT that define a flat memory model +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; printstr routine, prints the string pointed by si using int 0x10 ; +; sets the direction flag to 0 ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +printstr: + cld ; clear df flag - lodsb increments si +printstr_loop: + lodsb ; load next character into al, increment si + or al, al ; sets zf if al is 0x00 + jz printstr_end + mov ah, 0x0E ; teletype output (int 0x10) + int 0x10 ; print character + jmp printstr_loop +printstr_end: + ret ; return to caller address -limit = 0x00CFFFFFh ; Define limit as a separate variable within gdt_struct +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; halt routine - infinite loop ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +halt: + cli + jmp halt -; Placeholder instruction to satisfy NASM -dummy_instruction DB 0x90 ; NOP instruction as a placeholder +;;;;;;;;;;; +; Padding ; +;;;;;;;;;;; +; $ is the address of the current line, $$ is the base address for +; this program. +; the expression is expanded to 510 - ($ - 0x8000), or +; 510 + 0x8000 - $, which is, in other words, the number of bytes +; before the address 510 + 0x8000 (= 0x80FD), where the 0xAA55 +; signature shall be put. +times 510 - ($ - $$) db 0x00 -gdt_struct: - - base_addr equ 0x0000000 - - ; Null descriptor (ignored) - dd base_addr, 0 ; Both values are zero for a null descriptor - - ; Code segment descriptor (flat memory model) - dd base_addr, limit - db 0x9A - db 0xCF - - ; Data segment descriptor (flat memory model) - dd base_addr, limit - db 0x92 - db 0xCF - -; Macro to copy boot sector data to a safe location -mCopyBootSector: - pusha ; Save all general-purpose registers - mov si, 0x7C00 ; Source address: where BIOS loads the boot sector - mov di, 0x6000 ; Destination address: safe memory area - mov cx, 512 ; Number of bytes to copy (size of boot sector) - cld ; Clear direction flag to increment SI and DI -copy_loop: - lodsb ; Load byte at address DS:SI into AL, increment SI - stosb ; Store byte from AL to address ES:DI, increment DI - loop copy_loop ; Decrement CX; if CX != 0, repeat loop - popa ; Restore all general-purpose registers - ret - -; Subroutine to load the kernel -load_kernel: - ; Disable interrupts - cli - - ; Setup disk parameters - ; ... (set CH, CL, DH, DL for LBA, set DX for drive number) - - ; Calculate load address for kernel - ; ... (set ES:BX to the target memory address) - - ; Read sectors from disk into memory - mov ah, 0x02 ; Read sectors function - mov al, 1 ; Number of sectors to read - int 0x13 ; BIOS disk services - - ; Check for read error - jc .disk_error ; Carry flag set means an error occurred - - ; Enable A20 line if necessary - ; ... (implementation depends on your system) - - ; Jump to the kernel's entry point - jmp 0x1000:0x0000 ; Assuming the kernel is loaded at 0x1000:0x0000 - -.disk_error: - ; Handle disk read error - ; ... (display error message or halt) - - hlt ; Halt the system - -; Function or Subroutine to switch to protected mode -switch_to_protected_mode: - CLI ; Disable interrupts - LGDT [gdt_descriptor] ; Load the global descriptor table - MOV EAX, CR0 - OR EAX, 0x1 ; Set the PE (Protection Enable) bit - MOV CR0, EAX - ; Far jump to flush CPU queue after changing to protected mode - JMP CODE_SEG:init_pm ; CODE_SEG is the segment selector for code segment in GDT \ No newline at end of file +;;;;;;;;;;;;;;;;;; +; BIOS signature ; +;;;;;;;;;;;;;;;;;; +dw 0xAA55