.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: */