.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 call get_free_mailbox ; Initialize a mailbox ld (mailbox_num), hl ld iy, vfs_name ; Load and run the VFS call run_file vfs_loaded: call yield ; Yield to let the VFS initialize vfs_returned: ld iy, test_fs_name ; Load and run the test fs call run_file test_fs_loaded: test_fs_init_wait_loop: call yield ; Yield to let the test fs initialize yield_done: ld de, 3 call proc_map_get ld a, l cp 0 jp z, test_fs_init_wait_loop test_fs_initialized: 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 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, mount_loop ld a, (0xA001) ld c, a mount_done: 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" test_fs_name: .asciz "test_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: */