111 lines
2.8 KiB
Z80 Assembly
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
|