os-z80/init.z80
2023-09-17 11:02:33 -05:00

470 lines
7.7 KiB
Z80 Assembly

.global _start
_start:
call find_disk
/* ld hl, test_string */
/* call print */
call get_free_frame ; Set up a frame to load programs into at 0x8000
ld b, c
ld e, l
ld d, h
ld c, 8
bp_call_sf:
call set_frame
ld iy, vfs_name ; Load and run the initrd driver
call run_file
vfs_loaded:
call yield ; Yield to let the initrd driver initialize
vfs_returned:
ld iy, initrd_driver_name ; Load and run the initrd driver
call run_file
initrd_driver_loaded:
call yield ; Yield to let the initrd driver initialize
initrd_driver_returned:
ld iy, initrd_fs_name ; Load and run the initrd fs driver
call run_file
initrd_fs_loaded:
fs_init_wait_loop:
call yield ; Yield to let the initrd driver initialize
yield_done:
call get_free_mailbox ; Initialize a mailbox
ld (mailbox_num), hl
ld de, 1
call proc_map_get
ld a, l
cp 0
jp z, fs_init_wait_loop
fs_ready:
call get_free_frame ; Set up a message frame at 0xA000
ld a, c
ld (msg_phys_addr), a
ld (msg_phys_addr+1), hl
ld b, c
push hl
pop de
ld c, 0xA
call set_frame
frame_done:
; Set up a register FS message to the VFS for "a" at mailbox 1
ld hl, (mailbox_num)
ld (0xA000), hl
ld a, 0x0 ; Register FS operation
ld (0xA002), a
ld a, 0x61 ; 'a'
ld (0xA003), a
ld a, 0x0 ; '\0'
ld (0xA004), a
ld a, 0x1
ld (0xA011), a
ld a, 0x0
ld (0xA012), a
push de
push bc
ld de, 2 ; Get the mailbox number for the VFS
call proc_map_get
pmg_done:
pop bc
pop de
ld c, b ; Send the message
ld ix, 0x0000
call mb_send
loop:
call yield
loop_yield_done:
ld hl, (mailbox_num)
call mb_read ; Read a message
mb_read_done:
ld a, b ; Loop if there is no message
cp 0
jp nz, loop
ld a, (0xA001)
ld c, a
register_done:
; Set up a mount message to the VFS for "" on "/" with fs "a" at mailbox 1
ld hl, (mailbox_num)
ld (0xA000), hl
ld a, 0x1 ; Mount operation
ld (0xA002), a
ld a, 0x2F ; '/'
ld (0xA003), a
ld a, 0x0 ; '\0'
ld (0xA004), a
ld a, 0x0 ; '\0'
ld (0xA0FF), a
ld a, 0x61 ; 'a'
ld (0xA1FF), a
ld a, 0x0 ; '\0'
ld (0xA200), a
push de
push bc
ld de, 2 ; Get the mailbox number for the VFS
call proc_map_get
mount_pmg_done:
pop bc
pop de
ld c, b ; Send the message
ld ix, 0x0000
call mb_send
mount_loop:
call yield
mount_loop_yield_done:
ld hl, (mailbox_num)
call mb_read ; Read a message
mount_mb_read_done:
ld a, b ; Loop if there is no message
cp 0
jp nz, loop
ld a, (0xA001)
ld c, a
mount_done:
; Set up an open message to the initrd FS for "init.elf"
; ld hl, (mailbox_num)
; ld (0xA000), hl
; ld a, 0x0 ; Open operation
; ld (0xA002), a
; ld a, 0x69 ; i
; ld (0xA003), a
; ld a, 0x6e ; n
; ld (0xA004), a
; ld a, 0x69 ; i
; ld (0xA005), a
; ld a, 0x74 ; t
; ld (0xA006), a
; ld a, 0x2e ; .
; ld (0xA007), a
; ld a, 0x65 ; e
; ld (0xA008), a
; ld a, 0x6c ; l
; ld (0xA009), a
; ld a, 0x66 ; f
; ld (0xA00a), a
; ld a, 0x0 ; NUL
; ld (0xA00b), a
; push de
; push bc
; ld de, 1 ; Get the mailbox number for the initrd driver
; call proc_map_get
; pmg_done:
; pop bc
; pop de
; ld c, b ; Send the message
; ld ix, 0x0000
; call mb_send
; loop:
; call yield
; loop_yield_done:
; ld hl, (mailbox_num)
; call mb_read ; Read a message
; mb_read_done:
; ld a, b ; Loop if there is no message
; cp 0
; jp nz, loop
; ld a, (0xA001)
; ld c, a
; open_done:
; ; Set up a read message to the initrd FS for init.elf starting at 0x10 and reading 0x50 bytes
; ld hl, (mailbox_num)
; ld (0xA000), hl
; ld a, 0x1 ; Read operation
; ld (0xA002), a
; ld a, c ; FD
; ld (0xA003), a
; ld hl, 0x10
; ld (0xA004), hl ; File offset
; ld hl, 0x50
; ld (0xA006), hl ; Read length
; ld de, 1 ; Get the mailbox number for the initrd driver
; call proc_map_get
; read_pmg_done:
; ld a, (msg_phys_addr)
; ld c, a
; ld de, (msg_phys_addr+1)
; ld ix, 0x0000
; call mb_send
; read_loop:
; call yield
; read_loop_yield_done:
; ld hl, (mailbox_num)
; call mb_read ; Read a message
; read_mb_read_done:
; ld a, b ; Loop if there is no message
; cp 0
; jp nz, read_loop
halt
mailbox_num: .ds.b 2
msg_phys_addr: .ds.b 3
vfs_name: .asciz "vfs.elf"
initrd_driver_name: .asciz "initrd_driver.elf"
initrd_fs_name: .asciz "initrd_fs.elf"
; Loads and starts the ELF file with the name pointed to by IY
run_file:
call read_file
ld hl, 0x8000
push hl
pop iy
ld l, (iy+0x1C) ; Load IX with the start of the program headers in memory
ld h, (iy+0x1D) ; Load IX with the start of the program headers in memory
push hl
pop ix
push iy
pop bc
add ix, bc
ld a, (iy+0x2C) ; load B with the number of program headers
ld b, a
phead_loop:
ld a, (ix+0)
cp 1
jp NZ, next_seg
push bc
ld c, (ix+20)
ld b, (ix+21)
; b = if c > 0 || b & 0xF > 0 {
; (b & 0xF0) + 0x10
; } else {
; b & 0xF0
; } >> 4
ld a, c
cp 0
jp z, cmp2
jp blk1
cmp2:
ld a, b
and 0xF
cp 0
jp z, blk2
blk1:
ld a, b
and 0xF0
add a, 0x10
ld b, a
jp end1
blk2:
ld a, b
and 0xF0
ld b, a
end1:
srl b
srl b
srl b
srl b
ld c, (ix+9)
srl c
srl c
srl c
srl c
push iy
push ix
push de
ld a, c
sla a
add a, c
ld c, a
ld b, 0
map_seg_frame:
ld ix, proc_pagemap
add ix, bc
push ix
ld a, 1
call 0xdffd
pop ix
seg_frame_found:
ld (ix+0), c
ld (ix+1), l
ld (ix+2), h
ld b, c
ld e, l
ld d, h
ld c, 7
call set_frame
/* ld b, c */
/* ld d, h */
/* ld e, l */
/* pop hl */
/* ld c, l */
/* push hl */
/* call set_frame */
/* pop bc */
/* inc c */
/* djnz page_alloc_loop */
pop de
pop ix
pop iy
seg_load:
;Zero out the segments place in memory
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 a, d
and 0xF
or 0x70
ld d, a
ld h, d
ld l, e
ld (hl), 0 ; Zero out the first 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)
push iy
pop de
add hl, de
ld e, (ix+8) ; Load the destination & source address register with the destination location of the segment in memory
ld d, (ix+9)
ld a, d
and 0xF
or 0x70
ld d, a
ldir; Do the transfer
pop bc
next_seg:
ld de, 32
add ix, de
dec b
ld a, b
jp nz, phead_loop
ld l, (iy+0x18) ; Load HL with the program entry point
ld h, (iy+0x19) ; Load HL with the program entry point
ld iy, proc_pagemap
call new_process
ret
proc_pagemap:
.ds.b 36
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
; Reads a file off the disk to 0x8000 in memory
; Pointer to file name in iy
read_file:
ld c, 0
ld de, 1
ri_find_loop:
ld hl, 0x8000
push bc
call read_sector
ri_find_read_done:
ld ix, 0x8001
push iy
call strcmp
pop iy
pop bc
jp z, ri_init_found
push bc
ld b, 0
ld a, (0x8000)
ld c, a
ld hl, 0x8004
add hl, bc
ld c, (hl)
inc hl
ld b, (hl)
ld l, c
ld h, b
inc hl
add hl, de
ld e, l
ld d, h
pop bc
ld a, c
adc a, 0
ld c, a
jp ri_find_loop
ri_init_found:
push bc
ld b, 0
ld a, (0x8000)
ld c, a
ld hl, 0x8004
add hl, bc
pop bc
ld b, (hl)
ld hl, 1
add hl, de
ld e, l
ld d, h
ld a, c
adc a, 0
ld c, a
ld hl, 0x8000
ri_read_loop:
push bc
call read_sector
pop bc
push hl
ld hl, 1
add hl, de
ld e, l
ld d, h
ld a, c
adc a, 0
ld c, a
pop hl
djnz ri_read_loop
ret
; Given a sector number in C:DE and a buffer address in HL, reads the sector off disk.
read_sector:
push bc
ld c,0xFF ; Force the top half of the IO address to be the id of the card,
ld a, (disk_num) ; so the block transfer instructions can be used
out (c), a
pop bc
ld a, c
ld c, 0
out (c), e
inc c
out (c), d
inc c
out (c), a
ld b, 0x0 ; Setup a transfer of 256 bytes (1 sector) at a time
ld c, 0x3 ; from the storage device's data port
inir
ld c,0xFF ; Unforce the top half of the IO address
in a,(c)
ret
.global find_disk
; Clobbers A and HL
find_disk:
ld b,0x4
ld a, 10
call 0xdffd
ld a, l
ld (disk_num), a
ret
disk_num: .ds.b 1
/* initrd: */
/* .incbin "initrd" */
/* initrd_end: */