os-z80/boot/boot.z80
2023-02-03 09:24:28 -06:00

111 lines
2.8 KiB
Z80 Assembly

_start:
ld sp,0 ; Initialize the stack
ld a,0x4 ; Find a generic storage card
call find_first_card
ld c,0xFF ; Force the top half of the IO address to be the id of the card,
ld a, b ; so the block transfer instructions can be used
out (c), a
; Load the header sectior for the kernel binary to find it's length in sectors
ld a, 1 ; Set the sector number registers to 1
ld c, 0
out (c), a
inc c
xor a
out (c), a
inc c
out (c), a
ld b, a ; Setup a transfer of 256 bytes (1 sector) at a time
ld c, 0x3 ; from the storage device's data port
ld h, 0xA0 ; Starting at 0xA000
ld l, a
inir
ld h, 0xA0
ld l, 0x0
ld a, (hl)
add a, 3
ld c, a
ld b, 0
add hl, bc
ld d, (hl)
; load the ELF kernel binary off the disk
ld a, 2 ; Set the sector number registers to 2
ld c, 0
out (c), a
inc c
xor a
out (c), a
inc c
out (c), a
ld b, a ; Setup a transfer of 256 bytes (1 sector) at a time
ld c, 0x3 ; from the storage device's data port
ld h, 0xA0 ; Starting at 0xA000
ld l, a
ld a, d ; Transfer 0x23 times
loop:
inir ; Transfer a sector
dec a
jp NZ, loop
ld c,0xFF ; Unforce the top half of the IO address
in a,(c)
ld ix, (0xA01C) ; Load IX with the start of the program headers in memory
ld bc, 0xA000
add ix, bc
ld a, (0xA02C) ; load B with the number of program headers
ld b, a
phead_loop:
ld a, (ix+0)
cp 1
jp NZ, next_seg
;Zero out the segemnts place in memory
push bc
ld c, (ix+20) ; Load the byte counter with the number of bytes to zero out
ld b, (ix+21)
ld e, (ix+8) ; Load the destination & source address register with the destination location of the segment in memory
ld d, (ix+9)
ld h, d
ld l, e
ld (hl), 0 ; Zero out the firts byte in the segment ( Acts as a 'seed' for the zeroing )
ldir
ld c, (ix+16) ; Load the byte counter with the number of bytes to transfer
ld b, (ix+17)
ld l, (ix+4) ; Load the source address register with the memory address if the segment data
ld h, (ix+5)
ld de, 0xA000
add hl, de
ld e, (ix+8) ; Load the destination address register with the destination location of the segment in memory
ld d, (ix+9)
ldir; Do the transfer
pop bc
next_seg:
ld de, 32
add ix, de
djnz phead_loop
ld hl, (0xA018) ; Load HL with the program entry point
jp (hl)
find_first_card:
; Finds the first instance of a card type specified in A
; A is zero if no such card was found, and nonzero if a card was found
; If a card was found, the ID of the card is returned in B
; The values in C, D, and E are destroyed
ld d, a
ld e, 0x0
ld bc, 0x01FF ; BC is the IO address to read. B holds the card ID and C which address to read in the card.
ffc_loop:
in a, (c) ; Get card type
cp d ; Check whether the type of the current card is the type we want
jp Z, done ; If so, return
cp e ; Check whether the card type is 0 (nonexistent card)
jp Z, done ; If so, return
inc b ; Go to the next card
jp ffc_loop
done:
ret
.if . != 256
.org 255
.byte 0
.endif