diff --git a/README.md b/README.md new file mode 100644 index 0000000..296ca88 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# foxdos diff --git a/b b/b new file mode 100755 index 0000000..0e4a036 --- /dev/null +++ b/b @@ -0,0 +1,11 @@ +NAME=foxdos + +rm $NAME + +mkdir -p obj + +# TODO this only works in root directory. might be good to just use a proper build system +nasm -I. -Isrc src/boot.s -o obj/boot +nasm -I. -Isrc src/kernel.s -o obj/kernel + +cat obj/boot obj/kernel > $NAME diff --git a/config.s b/config.s new file mode 100644 index 0000000..5d830b2 --- /dev/null +++ b/config.s @@ -0,0 +1,5 @@ +NUMSEG equ 0 ; TODO build system should calculate this value + +; might be good to move one of these into the high memory area +K_ADDR equ 0x500 ; kernel load address +STACK_SEG equ 0x1050 diff --git a/src/boot.s b/src/boot.s new file mode 100644 index 0000000..ef1b0ee --- /dev/null +++ b/src/boot.s @@ -0,0 +1,45 @@ +; mothdos boot sector. should load kernel into segment 0x50 at 0x00. max size +; would be 64k but i doubt a dos needs more than that. stack is placed at +; 0x10500. i would suggest changing this to load the kernel into extended +; a20-gate memory so as not to overwrite the boot sector with larger kernels +; but i will leave that for you to do. code is public domain as always. i +; have not tested any of this so your mileage using it may vary + +%include "config.s" + +[org 0x7C00] +[bits 16] + +mov ax, K_ADDR << 4 +push ax ; setup for ds +mov es, ax +mov gs, ax +mov fs, ax + +xor bx, bx +mov ds, bx +mov word [0x21*4], 2 ; see kernel_entry +mov word [0x21*4+2], ax +pop ds + +mov ax, 0x200 | NUMSEG +mov cl, 2 +xor dh, dh +int 13h + +; 64kb stack +mov ax, STACK_SEG +mov ss, ax +xor sp, sp +mov ax, sp +not sp + +; kernel time(?) +push ds +push ax +retf + +; TODO we have lots of space for init code here + +times 510 - ($-$$) db 0 +dw 0xAA55 diff --git a/src/int21.s b/src/int21.s new file mode 100644 index 0000000..52ebb81 --- /dev/null +++ b/src/int21.s @@ -0,0 +1,128 @@ +int21: + push ds + push cs + pop ds + ; your handler goes here + ; you could maybe make a jump table that takes ah as input? + pop ds + iret + +retcode: dw 0 +verify: db 0 + +get_retcode:; ah=4dh + mov ax, [retcode] + retf + +get_version:; ah=30h + mov ax, 8 ; if it is not zero indexed this indicates windows ME + xor bx, bx ; update: what does that comment mean + mov cx, bx + retf + +getverify:; ah=54h + mov al, [verify] + retf + +setverify:; ah=2eh + mov [verify], al + retf + +getint:; ah=35h + push ds + push di + push ax + xor ah, ah + shl ax, 2 + mov di, ax + xor ax, ax + mov ds, ax + pop ax + mov word bx, [di] + mov word es, [di+2] + pop di + pop ds + retf + +setint:; ah=25h + pusha + xor ah, ah + shl ax, 2 + mov di, ax + xor ax, ax + push ds + mov ds, ax + mov word [di], dx + mov word [di+2], ds + pop ds + popa + retf + +rdcmos:; input in al. TODO handle bcd here to abstractt it from the kernel + cli + cmp al, 9 ; not rtc register, do not wait. if this function bugs out + jg .rd ; on a century boundary thats not on me. stop using dos + xchg al, ah +.wait: mov al, 0xA ; msb specifies if rtc update is in progress + out 0x70, al ; TODO https://wiki.osdev.org/CMOS#RTC_Update_In_Progress + in al, 0x71 + shl al, 1 + jc .wait + xchg al, ah +.rd: out 0x70, al + in al, 0x71 + sti + ret + +wrcmos:; register in bh, value in bl + cli + push ax + mov al, bh + or al, 0x80 ; nmi always on + out 0x70, al + mov al, bl + out 0x71, al + pop ax + sti + ret + +gettime:; ah=2ch + push ax + xor dl, dl + + mov al, dl ; seconds + call rdcmos + mov dh, al + + mov al, 2h ; minutes + call rdcmos + mov cl, al + + mov al, 4h ; hours + call rdcmos + mov ch, al + + shl al, 1 ; adjust for 12 hour time + jnc .end + add ch, 12 + +.end: pop ax + retf + +settime:; ah=2dh + push bx + mov bl, ch + mov bh, 0x4 + call wrcmos + mov bl, cl + shr bh, 1 + call wrcmos + mov bl, dh + cmp dl, 50 ; rtc cannot hold hundredths of a second so we round + jng .f + inc bl +.f: xor bh, bh + call wrcmos + xor al, al ; it probably succeeded, its fine. TODO am i missing return codes anywhere else + pop bx + iret diff --git a/src/kernel.s b/src/kernel.s new file mode 100644 index 0000000..405553f --- /dev/null +++ b/src/kernel.s @@ -0,0 +1,6 @@ +%include "config.s" +[org K_ADDR] +kernel_entry: ; MUST be a short jump due to loader config + jmp $ ; TODO stub because os doesnt actually exist yet + +%include "int21.s"