.global _start _start: call find_disk /* ld hl, test_string */ /* call print */ /* call get_free_mailbox ; Initialize a mailbox */ /* ld (mailbox_num), hl */ 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, 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: call yield ; Yield to let the initrd driver initialize /* call get_free_frame ; Set up a message frame at 0xA000 */ /* ld b, c */ /* push hl */ /* pop de */ /* ld c, 0xA */ /* call set_frame */ ; Set up a read message to the driver starting at 0x80 and reading ; 0x200 bytes /* ld a, 0x80 */ /* ld (0xA000), a */ /* ld a, 0x00 */ /* ld (0xA001), a */ /* ld a, 0x00 */ /* ld (0xA002), a */ /* ld a, 0x2 */ /* ld (0xA003), a */ /* ld hl, (mailbox_num) */ /* ld (0xA004), hl */ /* push de */ /* push bc */ /* ld de, 0 ; Get the mailbox number for the initrd driver */ /* call proc_map_get */ /* pop bc */ /* pop de */ /* ld c, b ; Send the message */ /* ld ix, 0x0000 */ /* call mb_send */ /* loop: */ /* call yield */ /* ld hl, (mailbox_num) */ /* call mb_read ; Read a message */ /* ld a, b ; Loop if there is no message */ /* cp 0 */ /* jp nz, loop */ loop: call yield jp loop mailbox_num: .ds.b 2 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: */