os-z80/initrd_fs.z80
2023-09-03 10:03:51 -05:00

309 lines
4.7 KiB
Z80 Assembly

.global _start
_start:
call get_free_mailbox ; Get a mailbox
ld (sec_read_mailbox_num), hl
call get_free_mailbox ; Get a mailbox
ld (mailbox_num), hl
ld de, 1
call get_free_frame ; Set up a frame to send messages at 0xA000
ld a, c
ld (msg_frame_phys), a
ld a, l
ld (msg_frame_phys+1), a
ld a, h
ld (msg_frame_phys+2), a
ld b, c
ld e, l
ld d, h
ld c, 0xA
call set_frame
call get_free_frame ; Set up a frame for the file mapping at 0x8000
ld b, c
ld e, l
ld d, h
ld c, 0x8
call set_frame
ld c, 0
ld de, 1
ld hl, 0x8000
initrd_read_loop:
push bc
push de
push hl
; FM SECL SECH
ld hl, 0xA000
call read_sector
pop de
push de
; FM SECL SECH
ld b, 0 ; Load the filename length in BC
ld a, (0xA000)
cp 0
jp z, initrd_read_done
ld c, a
ld hl, 0xA001 ; Read the name + null terminator into the mapping list
ldir
ld a, (hl)
ld (de), a
inc hl
pop de ; Restore the value of DE before reading the name in
; SECL SECH
dbg_label:
ld a, e ; Add 0x20 to DE
add a, 0x20
ld e, a
ld a, d
adc a, 0x0
ld d, a
ld a, (hl) ; Write the file legth to the mapping list
ld (de), a
inc hl
inc de
ld a, (hl)
ld (de), a
inc hl
inc de
ld l, e
ld h, d
pop iy
; SECH
pop bc
; (EMPTY)
push de
; FM
push bc
; SECH FM
ld e, iyl
ld d, iyh
ld (hl), e ; Write the starting block of the file to the mapping list
inc hl
ld (hl), d
inc hl
ld (hl), c
inc hl
; Advance to the next header
ld b, 0 ; Load the filename length in BC
ld a, (0xA000)
ld c, a
ld hl, 0xA004
add hl, bc ; Add the filename length to get the pointer to the
; # of blocks in the file in HL
ld c, (hl) ; Read the # of blocks into BC
inc hl
ld b, (hl)
ld l, c ; Move it into HL
ld h, b
inc hl ; Add 1 to account for the header sector
pop bc
; FM
add hl, de ; 24-bit add of HL to C:DE
ld e, l
ld d, h
ld a, c
adc a, 0
ld c, a
pop hl
; (empty)
inc hl
inc hl
inc hl
jp initrd_read_loop
initrd_read_done:
ld de, 1
ld hl, (mailbox_num)
pms_call:
call proc_map_set ; Register ourselves as ID 1
msg_loop:
call yield
yield_back:
ld hl, (mailbox_num)
call mb_read
mb_read_done:
ld a, b
cp 1
jp z, msg_loop
msg_read:
push bc
push de
push hl
ld b, c
ld c, 0xB
call set_frame
set_frame_done:
ld hl, (0xB000) ; Load destination mailbox into HL and save it on the stack
push hl
ld hl, 0xB002
; Handling code goes here
ld a, (hl)
inc hl
cp 0x0
jp z, open
cp 0x1
jp z, read
operation_done:
pop hl
pop ix
pop de
pop bc
call mb_send
jp msg_loop
; de = start of file map list
; c = 0
; while (1) {
; if (*de == 0) {
; (0xB000) = 1;
; return
; }
; if (strcmp(de, 0xB003) == 0) {
; (0xB000) = 0;
; (0xB001) = c;
; return;
; }
; }
open:
ld de, 0x8000
ld c, 0
open_find_loop:
ld a, (de)
cp 0
jp nz, open_not_end
ld a, 1
ld (0xB000), a
jp operation_done
open_not_end:
ld ix, 0xB003
push de
pop iy
call strcmp
cp 0
jp nz, open_not_match
ld a, 0
ld (0xB000), a
ld a, c
ld (0xB001), a
jp operation_done
open_not_match:
inc c
push de
pop hl
ld de, 0x25
add hl, de
push hl
pop de
jp open_find_loop
read:
ld a, (0xB003)
ld l, a
ld h, 0
push hl
pop ix
add hl, hl
add hl, hl
push hl
pop de
add ix, de
add hl, hl
add hl, hl
add hl, hl
push hl
pop de
add ix, de
ld de, 0x8020
add ix, de
ld d, (ix+2)
ld e, 0x0
ld hl, (0xB004)
add hl, de
ld bc, 0x100
add hl, bc
ld c, l
ld b, h
ld de, (0xB006)
call read_bytes
ld de, 0xB000
ld hl, 0xA000
ld bc, (0xB006)
ldir
jp operation_done
strcmp:
strcmp_loop:
ld a, (ix+0)
ld b, (iy+0)
cp b
jp nz, strcmp_different
cp 0
ret z
inc ix
inc iy
jp strcmp_loop
strcmp_different:
ld a, 1
ret
sec_read_mailbox_num: .ds.b 2
mailbox_num: .ds.b 2
msg_frame_phys: .ds.b 3
; Given a sector number in C:DE, reads the sector off disk into 0xA000
read_sector:
; Set up a read message to the driver starting at the sector in register E and reading
; 0x100 bytes
ld a, 0x0
ld (0xA000), a
ld a, e
ld (0xA001), a
ld a, 0x00
ld (0xA002), a
ld a, 0x1
ld (0xA003), a
ld hl, (sec_read_mailbox_num)
ld (0xA004), hl
ld de, 0 ; Get the mailbox number for the initrd driver
call proc_map_get
read_sec_pmg_done:
ld a, (msg_frame_phys)
ld c, a
ld de, (msg_frame_phys + 1)
ld ix, 0
call mb_send
read_sec_msg_sent:
loop:
call yield
ld hl, (sec_read_mailbox_num)
read_sector_done:
ret
; Given a byte offset in BC, and a byte length in DE no more than 0x1000, reads the data off disk into 0xA000
read_bytes:
; Set up a read message to the driver starting at the sector in register E and reading
; 0x100 bytes
ld (0xA000), bc
ld (0xA002), de
ld hl, (sec_read_mailbox_num)
ld (0xA004), hl
ld de, 0 ; Get the mailbox number for the initrd driver
call proc_map_get
read_bytes_pmg_done:
ld a, (msg_frame_phys)
ld c, a
ld de, (msg_frame_phys + 1)
ld ix, 0
call mb_send
read_bytes_msg_sent:
read_bytes_loop:
call yield
ld hl, (sec_read_mailbox_num)
call mb_read ; Read a message
ld a, b ; Loop if there is no message
cp 0
jp nz, read_bytes_loop
read_bytes_done:
ret