Compare commits

..

2 Commits

Author SHA1 Message Date
Juhani Krekelä 3f4c6c0559 Make output code work also on the original IBM PC 2021-06-30 23:22:09 +03:00
Juhani Krekelä 7e41612687 Add OS selector to bootloader 2021-06-30 22:56:42 +03:00
9 changed files with 161 additions and 343 deletions

1
.gitignore vendored
View File

@ -1,4 +1,3 @@
*.bin
*.img
*.d
*.krn

View File

@ -1,30 +1,24 @@
FLOPPY = 360
FLOPPY = 1440
.SUFFIXES:
.SUFFIXES: .bin .asm
all: nor86.img
nor86.img: boot.bin nor86.krn CC0 README.md
nor86.img: bootsect.bin kernel.bin CC0 README.md
rm -f $@
mkdosfs -C $@ $(FLOPPY)
rw -i boot.bin -o $@
rw -i bootsect.bin -o $@
mcopy -i $@ CC0 ::
mcopy -i $@ README.md ::
mcopy -i $@ *.asm ::
mcopy -i $@ *.inc ::
mcopy -i $@ nor86.krn ::
nor86.krn: kernel.asm
nasm -fbin -d F$(FLOPPY) -o $@ $<
nasm -MD $@.d -d F$(FLOPPY) -fbin -o $@ $<
mcopy -i $@ kernel.bin ::
.asm.bin:
nasm -fbin -d F$(FLOPPY) -o $@ $<
nasm -MD $@.d -d F$(FLOPPY) -fbin -o $@ $<
clean:
rm -f *.bin *.img *.bin.d *.krn *.krn.d
rm -f *.bin *.img *.bin.d
run: nor86.img
qemu-system-i386 -fda $<

View File

@ -8,6 +8,6 @@ Floppy sizes
------------
You can build either a 1440K or a 360K floppy image from Nor86 sources, the
default being 360K. To build a 1440K floppy instead, run:
default being 1440K. To build a 360K floppy instead, run:
make FLOPPY=1440
make FLOPPY=360

View File

@ -67,6 +67,29 @@ _start:
; Save bootdrive
mov [drivenumber], dl
select_os:
mov si, prompt
.print:
lodsb
test al, al
jz .end
; On the original IBM PC BIOS the int 0x10 will clobber this
mov ah, 0xe
int 0x10
jmp .print
.end:
xor ax, ax
int 0x16
cmp al, 'e'
jne calc_constants
mov si, ettinos_kernel_name
mov di, kernel_name
mov cx, 11
rep movsb
calc_constants:
; Disk organization:
; Reserved sectors (MBR)
@ -97,15 +120,25 @@ calc_constants:
fat:
; FAT1 (the main one) follows right after bootsector(s)
mov ax, [reservedsectors]
call chs
; TODO: handle possible crossing of track boundary
mov ax, [sectorsperfat]
mov ah, 2
mov dl, [drivenumber]
mov bx, 0x8000
mov cx, [sectorsperfat]
call loadsectors
int 0x13
root_dir:
mov ax, [rootdir]
call chs
; TODO: handle possible crossing of track boundary
mov ax, [rootdirsectors]
mov ah, 2
mov dl, [drivenumber]
mov bx, 0x500
mov cx, [rootdirsectors]
call loadsectors
int 0x13
search_root:
mov bx, [rootdirentries]
@ -120,53 +153,26 @@ search_root:
cmp byte [si], 0
je .end
; Deleted file?
cmp byte [si], 0xe5
je .skipentry
test byte [si + 11], 0x08 + 0x10
jnz .skipentry
jz .isfile
; Make sure the file has non-zero size
; File size must be <32K anyways so don't bother with >64K
cmp word [si + 28], 0
jne .isfile
.skipentry:
add si, 32
jmp .entry
.isfile:
.nor86:
cmp word [si + 8], 'KR'
jne .ettinos
cmp byte [si + 10], 'N'
jne .ettinos
mov cx, 11
mov bx, kernel_name
mov ax, [si + 26] ; First cluster
mov [kernel_cluster], ax
.compare:
lodsb
cmp al, [bx]
jne .nomatch
inc bx
loop .compare
jmp .skipentry
jmp found
.ettinos:
mov cx, 11
mov bx, ettinos_kernel_name
.compare:
lodsb
cmp al, [bx]
jne .nextentry
inc bx
loop .compare
; SI points to 11 bytes after the start of the
; entry, so adjust offset
mov ax, [si - 11 + 26] ; First cluster
mov [ettinos_kernel_cluster], ax
inc cx ; Offset so that falling through will work
.nextentry:
.nomatch:
; Each entry is 32 bytes long
; During each iteration of the compare loop, si is
; incremented and cx is decremented
@ -180,47 +186,20 @@ search_root:
.end:
which_found:
mov bx, [kernel_cluster]
mov cx, [ettinos_kernel_cluster]
test bx, bx
jz .no_nor86
test cx, cx
jz found
mov si, choose_msg
.loop:
lodsb
test al, al
jz .end
mov ah, 0xe
int 0x10
jmp .loop
.end:
xor ax, ax
int 0x16
cmp ah, 0x12 ; E-key
je found_cx
jmp found
.no_nor86:
test cx, cx
jnz found_cx
notfound:
mov si, notfound_msg
jmp fatal_error
; TODO: Better error messages
mov ax, 0x0e00 + '?'
int 0x10
found_cx:
mov bx, cx
hang:
hlt
jmp hang
found:
mov ax, bx
; SI points to 11 bytes after the start of the entry, so adjust all
; offsets
; TODO: Handle zero-length files
mov ax, [si - 11 + 26] ; First cluster
push ax
; Load OS at the start of the memory
@ -231,8 +210,7 @@ found:
.tosector:
; Adjust the cluster number to account for first two
; "clusters" in the FAT being used for metadata
dec ax
dec ax
sub ax, 2
; Scale by number of sectors per cluster
xor bx, bx
@ -243,12 +221,27 @@ found:
add ax, [rootdir]
add ax, [rootdirsectors]
.load:
; Load sectors
pop bx
xor cx, cx
mov cl, [sectorspercluster]
call loadsectors
; Load sectors
pop bx
xor cx, cx
mov cl, [sectorspercluster]
mov dl, [drivenumber]
.loop:
push ax
push cx
call chs
mov ah, 2
mov al, 1
int 0x13
pop cx
pop ax
add bx, 512
inc ax
loop .loop
.next:
pop ax
@ -271,7 +264,11 @@ found:
; ^ where we start reading on odd cluster numbers
; ^^^^^ loading word: 0xXYZA
test ax, 1
jz .even
jnz .odd
.even:
and dx, 0x0fff
jmp .check_cluster
.odd:
shr dx, 1
@ -279,9 +276,6 @@ found:
shr dx, 1
shr dx, 1
.even:
and dx, 0x0fff
.check_cluster:
mov ax, dx
@ -297,102 +291,51 @@ execute_kernel:
mov dl, [drivenumber]
jmp 0:0x500
; Note: bx will point to after the read data
; Note: ax, cx, dx, and di will be clobbered
loadsectors:
chs:
push ax
push bx
.loop:
mov di, 3 + 1 ; Retry thrice, + 1 is since we dec first
; Save drive number
mov bl, dl
.retry:
xor dx, dx
; cylinder (track) - head - sector
; cylinder = LBA / sectorspertrack / heads
; head = LBA / sectorspertrack % heads
; sector = LBA % sectorspertrack + 1
div word [sectorspertrack]
; ax = LBA / sectorspertrack
; dx = LBA % sectorspertrack
push ax
push cx
; sector
mov cl, dl
inc cl
.chs:
xor dx, dx
; cylinder (track) - head - sector
; cylinder = LBA / sectorspertrack / heads
; head = LBA / sectorspertrack % heads
; sector = LBA % sectorspertrack + 1
div word [sectorspertrack]
; ax = LBA / sectorspertrack
; dx = LBA % sectorspertrack
xor dx, dx
div word [heads]
; ax = LBA / sectorspertrack / heads
; dx = LBA / sectorspertrack % heads
; sector
mov cl, dl
inc cl
; head
mov dh, dl
xor dx, dx
div word [heads]
; ax = LBA / sectorspertrack / heads
; dx = LBA / sectorspertrack % heads
; cylinder (track)
mov ch, al
;shr ax, 1
;shr ax, 1
;and al, 0xC0
;or cl, al
; head
mov dh, dl
; cylinder (track)
mov ch, al
;shr ax, 1
;shr ax, 1
;and al, 0xC0
;or cl, al
mov ax, 0x0201
mov dl, [drivenumber]
int 0x13
jc .error
mov ax, 0x0e00 + '.'
int 0x10
pop cx
pop ax
inc ax
add bx, 512
loop .loop
; Restore drive number
mov dl, bl
pop bx
pop ax
ret
.error:
; Do we still have retries remaining?
mov si, diskerror_msg
dec di
jz fatal_error ; No, fail
; Yes, reset disk
xor ah, ah
int 0x13
; Execute the loop again
pop cx
pop ax
jmp .retry
fatal_error:
mov cx, 9
.loop:
lodsb
mov ah, 0xe
int 0x10
loop .loop
hang:
hlt
jmp hang
kernel_cluster dw 0
ettinos_kernel_cluster dw 0
ettinos_kernel_name db "SYSTEM BIN"
notfound_msg db "No kernel"
diskerror_msg db "Disk error"
choose_msg db 13, 10, "EttinOS/Nor86?", 0
prompt: db "Select OS. 'e' for EttinOS, any other key Nor86.", 0
kernel_name: db "KERNEL BIN"
ettinos_kernel_name: db "SYSTEM BIN"
times 510-($-$$) db 0
db 0x55, 0xaa

View File

@ -1,39 +0,0 @@
; IN:
; ds:si = start of asciz string
printz:
push ax
push si
.loop:
lodsb
test al, al
jz .end
call printc
jmp .loop
.end:
pop si
pop ax
ret
; IN:
; al = cp437 character
printc:
push ax
cmp al, 10
jne .output
mov ax, 0x0e0d
int 0x10
mov al, 10
.output:
mov ah, 0xe
int 0x10
pop ax
ret

32
hexprint.inc Normal file
View File

@ -0,0 +1,32 @@
hexprint16:
xchg ah, al
call hexprint8
xchg ah, al
hexprint8:
push ax
push bx
push cx
mov cl, al
xor bx, bx
mov ah, 0xe
shr al, 1
shr al, 1
shr al, 1
shr al, 1
mov bl, al
mov al, [.digits + bx]
int 0x10
mov bl, 0xf
and bl, cl
mov al, [.digits + bx]
int 0x10
pop cx
pop bx
pop ax
ret
.digits: db '0123456789abcdef'

View File

@ -1,50 +1,8 @@
cpu 8086
org 0x500
greet:
mov si, kernel_greeting
call printz
mov al, dl
add al, '0'
call printc
mov al, 10
call printc
memsize:
; Get and display memory size
int 0x12
mov bx, buffer
call itoa
mov si, bx
call printz
mov si, memsize_trailer
call printz
floppies:
; Get and display number of floppy disks
int 0x11
times 6 shr ax, 1
and ax, 3
inc ax
add al, '0'
call printc
mov si, floppies_trailer
call printz
mov ax, 0x0e40
int 0x10
hang:
hlt
jmp hang
%include "console.inc"
%include "printhex.inc"
%include "strint.inc"
kernel_greeting db 10, "Nor86 kernel succesfully loaded", 10, "Loaded from disk ", 0
memsize_trailer db "k RAM", 10, 0
floppies_trailer db " floppy drive(s)", 10, 0
buffer times 256 db 0

View File

@ -1,36 +0,0 @@
; IN:
; ax = hex value
printh16:
xchg ah, al
call printh8
xchg ah, al
; IN:
; al = hex value
printh8:
push ax
mov ah, al
shr al, 1
shr al, 1
shr al, 1
shr al, 1
call .printh4
mov al, 0xf
and al, ah
call .printh4
pop ax
ret
.printh4:
cmp al, 10
jb .numeric
add al, 'a' - 10
jmp printc
.numeric:
add al, '0'
jmp printc

View File

@ -1,33 +0,0 @@
; IN:
; ax = number to convert
; ds:bx = storage buffer
; OUT:
; ds:bx = start of converted number
itoa:
push ax
push cx
push dx
mov cx, 10
add bx, 5
mov byte [bx], 0
.convert_loop:
test ax, ax
jz .end
xor dx, dx
div cx
add dl, '0'
dec bx
mov byte [bx], dl
jmp .convert_loop
.end:
pop dx
pop cx
pop ax
ret