include cards.i include initrd.i include syscalls.i include elf.i include memory.i section .text,text public main main: clrfo main.elf_header: fo.b Elf32_Ehdr.sizeof link a6, #__FO ; Create a stack frame move.l #msg, a0 jsr syscall_println jsr cards_init jsr initrd_init move.l #test_proc_name, a0 jsr initrd_find_file move.l d0, d5 ; Read the ELF header lea.l (main.elf_header,a6), a0 move.l #0, d1 move.l #Elf32_Ehdr.sizeof, d2 hdr_read: jsr initrd_read_bytes ; Allocate elf_header.e_phnum * 32 bytes to read the program headers into clr.l d0 move.w (main.elf_header+Elf32_Ehdr.e_phnum,a6), d0 move.l d0, d4 lsl.l #5, d0 move.l d0, d2 jsr malloc phdr_read: ; Read the program headers move.l (main.elf_header+Elf32_Ehdr.e_phoff,a6), d1 move.l a0, -(a7) move.l d5, d0 jsr initrd_read_bytes move.l (a7)+, a2 phead_loop: ; If the program header's type is not LOAD, skip it move.l (Elf32_Phdr.p_type,a2), d0 cmpi.l #PT_LOAD, d0 bne.w skip_pheader ; Get the memory size of the pheader into d0 and round it to the next multiple of 4096 ; round_size = p_memsz & 0xFFF > 0 ? p_memsz & ~(0xFFF) + 1 : p_memsz & ~(0xFF) move.l (Elf32_Phdr.p_memsz,a2), d0 andi.l #$FFF, d0 beq.b .1 move.l #$1000, d1 bra.b .2 .1: move.l #0, d1 .2: move.l (Elf32_Phdr.p_memsz,a2), d0 andi.l #(~$FFF), d0 add.l d1, d0 ; Shift the rounded size right by 12 to get the number of pages the pheader takes up lsr.l #8, d0 lsr.l #4, d0 ; Map the segment to free memory move.l #6, d1 jsr syscall_vmem_map_free move.l a0, a3 ; Save the allocated address in a3 ; Offset the allocated address by the page offset in the pheader's virtaddr field move.l (Elf32_Phdr.p_vaddr,a2), d0 andi.l #$FFF, d0 adda.l d0, a3 move.l a3, a0 ; Zero the segment's memory move.l (Elf32_Phdr.p_memsz,a2), d0 subi.l #1, d0 .3: move.b #0, (a0)+ dbra d0, .3 ; Read the segment's data off disk move.l d5, d0 move.l (Elf32_Phdr.p_offset,a2), d1 move.l (Elf32_Phdr.p_filesz,a2), d2 move.l a3, a0 jsr initrd_read_bytes ; Get the memory size of the pheader into d0 and round it to the next multiple of 4096 ; Same as above move.l (Elf32_Phdr.p_memsz,a2), d0 andi.l #$FFF, d0 beq.b .4 move.l #$1000, d1 bra.b .5 .4: move.l #0, d1 .5: move.l (Elf32_Phdr.p_memsz,a2), d0 andi.l #(~$FFF), d0 add.l d1, d0 ; Shift the rounded size right by 12 to get the number of pages the pheader takes up lsr.l #8, d0 lsr.l #4, d0 ; Get the pheader's flags and make them into the page mapping flags, put the ; argumemts into the right registers, and set the flags for the pheader's memory move.l d0, d1 move.l a3, a0 move.l (Elf32_Phdr.p_flags,a2), d0 andi.l #PF_W, d0 move.l (Elf32_Phdr.p_flags,a2), d2 andi.l #PF_X, d2 lsl.l #3, d2 or.l d2, d0 ori.l #$4, d0 move.l #$0, d2 jsr syscall_vmem_set_flags move.l a3, a0 ; Get the memory size of the pheader into d0 and round it to the next multiple of 4096 ; Same as above move.l (Elf32_Phdr.p_memsz,a2), d0 andi.l #$FFF, d0 beq.b .6 move.l #$1000, d1 bra.b .7 .6: move.l #0, d1 .7: move.l (Elf32_Phdr.p_memsz,a2), d0 andi.l #(~$FFF), d0 add.l d1, d0 ; Shift the rounded size right by 12 to get the number of pages the pheader takes up lsr.l #8, d0 lsr.l #4, d0 ; Get the starting page of the allocated memory segment into a0 move.l a3, d1 andi.l #(~$FFF), d1 move.l d1, a0 move.l (Elf32_Phdr.p_vaddr,a2), a1 dbg: jsr syscall_vmem_copy_to_secondary skip_pheader: ; Advance to the next pheader and loop back if there are more lea.l (Elf32_Phdr.sizeof,a2), a2 dbra d4, phead_loop ; Create the init process move.l (main.elf_header+Elf32_Ehdr.e_entry,a6), a0 jsr syscall_new_process unlk a6 rts section .data,data msg: dc.b "Hello from init",0 test_proc_name: dc.b "test_proc",0 section .bss,bss tmp_stack: ds.b 32 tmp_stack_top: