diff --git a/elf.i b/elf.i new file mode 100644 index 0000000..f9857bb --- /dev/null +++ b/elf.i @@ -0,0 +1,237 @@ + ifnd ELF_I +ELF_I equ 1 + clrso +Elf_Ehdr.ei_mag: so.b 4 +Elf_Ehdr.ei_class: so.b 1 +Elf_Ehdr.ei_data: so.b 1 +Elf_Ehdr.ei_version so.b 1 +Elf_Ehdr.ei_osabi: so.b 1 +Elf_Ehdr.ei_padd: so.b 8 +Elf_Ehdr.e_type: so.w 1 +Elf_Ehdr.e_machine: so.w 1 +Elf_Ehdr.e_version: so.l 1 +Elf_Ehdr.sizeof equ __SO +Elf32_Ehdr.e_entry: so.l 1 +Elf32_Ehdr.e_phoff: so.l 1 +Elf32_Ehdr.e_shoff: so.l 1 +Elf32_Ehdr.e_flags: so.l 1 +Elf32_Ehdr.e_ehsize: so.w 1 +Elf32_Ehdr.e_phentsize: so.w 1 +Elf32_Ehdr.e_phnum: so.w 1 +Elf32_Ehdr.e_shentsize: so.w 1 +Elf32_Ehdr.e_shnum: so.w 1 +Elf32_Ehdr.e_shstrndx: so.w 1 +Elf32_Ehdr.sizeof equ __SO + + +ELFMAG0 equ $7f ; EI_MAG +ELFMAG1 equ 'E' +ELFMAG2 equ 'L' +ELFMAG3 equ 'F' + +ELFCLASSNONE equ 0 ; EI_CLASS +ELFCLASS32 equ 1 +ELFCLASS64 equ 2 +ELFCLASSNUM equ 3 + +ELFDATANONE equ 0 ; EI_DATA +ELFDATA2LSB equ 1 +ELFDATA2MSB equ 2 +ELFDATANUM equ 3 + +ET_NONE equ 0 ; e_type +ET_REL equ 1 +ET_EXEC equ 2 +ET_DYN equ 3 +ET_CORE equ 4 +ET_NUM equ 5 +ET_LOOS equ $fe00 ; OS specific range +ET_LOSUNW equ $feff +ET_SUNWPSEUDO equ $feff +ET_HISUNW equ $feff +ET_HIOS equ $feff +ET_LOPROC equ $ff00 ; processor specific range +ET_HIPROC equ $ffff + +EM_NONE equ 0 ; e_machine +EM_M32 equ 1 ; AT&T WE 32100 +EM_SPARC equ 2 ; Sun SPARC +EM_386 equ 3 ; Intel 80386 +EM_68K equ 4 ; Motorola 68000 +EM_88K equ 5 ; Motorola 88000 +EM_486 equ 6 ; Intel 80486 +EM_860 equ 7 ; Intel i860 +EM_MIPS equ 8 ; MIPS RS3000 Big-Endian +EM_S370 equ 9 ; IBM System/370 Processor +EM_MIPS_RS3_LE equ 10 ; MIPS RS3000 Little-Endian +EM_RS6000 equ 11 ; RS6000 +EM_UNKNOWN12 equ 12 +EM_UNKNOWN13 equ 13 +EM_UNKNOWN14 equ 14 +EM_PA_RISC equ 15 ; PA-RISC +EM_nCUBE equ 16 ; nCUBE +EM_VPP500 equ 17 ; Fujitsu VPP500 +EM_SPARC32PLUS equ 18 ; Sun SPARC 32+ +EM_960 equ 19 ; Intel 80960 +EM_PPC equ 20 ; PowerPC +EM_PPC64 equ 21 ; 64-bit PowerPC +EM_UNKNOWN22 equ 22 +EM_UNKNOWN23 equ 23 +EM_UNKNOWN24 equ 24 +EM_UNKNOWN25 equ 25 +EM_UNKNOWN26 equ 26 +EM_UNKNOWN27 equ 27 +EM_UNKNOWN28 equ 28 +EM_UNKNOWN29 equ 29 +EM_UNKNOWN30 equ 30 +EM_UNKNOWN31 equ 31 +EM_UNKNOWN32 equ 32 +EM_UNKNOWN33 equ 33 +EM_UNKNOWN34 equ 34 +EM_UNKNOWN35 equ 35 +EM_V800 equ 36 ; NEX V800 +EM_FR20 equ 37 ; Fujitsu FR20 +EM_RH32 equ 38 ; TRW RH-32 +EM_RCE equ 39 ; Motorola RCE +EM_ARM equ 40 ; Advanced RISC Marchines ARM +EM_ALPHA equ 41 ; Digital Alpha +EM_SH equ 42 ; Hitachi SH +EM_SPARCV9 equ 43 ; Sun SPARC V9 (64-bit) +EM_TRICORE equ 44 ; Siemens Tricore embedded processor +EM_ARC equ 45 ; Argonaut RISC Core, + ; Argonaut Technologies Inc. +EM_H8_300 equ 46 ; Hitachi H8/300 +EM_H8_300H equ 47 ; Hitachi H8/300H +EM_H8S equ 48 ; Hitachi H8S +EM_H8_500 equ 49 ; Hitachi H8/500 +EM_IA_64 equ 50 ; Intel IA64 +EM_MIPS_X equ 51 ; Stanford MIPS-X +EM_COLDFIRE equ 52 ; Motorola ColdFire +EM_68HC12 equ 53 ; Motorola M68HC12 +EM_MMA equ 54 ; Fujitsu MMA Mulimedia Accelerator +EM_PCP equ 55 ; Siemens PCP +EM_NCPU equ 56 ; Sony nCPU embedded RISC processor +EM_NDR1 equ 57 ; Denso NDR1 microprocessor +EM_STARCORE equ 58 ; Motorola Star*Core processor +EM_ME16 equ 59 ; Toyota ME16 processor +EM_ST100 equ 60 ; STMicroelectronics ST100 processor +EM_TINYJ equ 61 ; Advanced Logic Corp. TinyJ + ; embedded processor family +EM_AMD64 equ 62 ; AMDs x86-64 architecture +EM_X86_64 equ EM_AMD64 ; (compatibility) + +EM_PDSP equ 63 ; Sony DSP Processor +EM_UNKNOWN64 equ 64 +EM_UNKNOWN65 equ 65 +EM_FX66 equ 66 ; Siemens FX66 microcontroller +EM_ST9PLUS equ 67 ; STMicroelectronics ST9+8/16 bit +; microcontroller +EM_ST7 equ 68 ; STMicroelectronics ST7 8-bit +; microcontroller +EM_68HC16 equ 69 ; Motorola MC68HC16 Microcontroller +EM_68HC11 equ 70 ; Motorola MC68HC11 Microcontroller +EM_68HC08 equ 71 ; Motorola MC68HC08 Microcontroller +EM_68HC05 equ 72 ; Motorola MC68HC05 Microcontroller +EM_SVX equ 73 ; Silicon Graphics SVx +EM_ST19 equ 74 ; STMicroelectronics ST19 8-bit +; microcontroller +EM_VAX equ 75 ; Digital VAX +EM_CRIS equ 76 ; Axis Communications 32-bit + ; embedded processor +EM_JAVELIN equ 77 ; Infineon Technologies 32-bit + ; embedded processor +EM_FIREPATH equ 78 ; Element 14 64-bit DSP Processor +EM_ZSP equ 79 ; LSI Logic 16-bit DSP Processor +EM_MMIX equ 80 ; Donald Knuth's educational + ; 64-bit processor +EM_HUANY equ 81 ; Harvard University +; machine-independent + ; object files +EM_PRISM equ 82 ; SiTera Prism +EM_AVR equ 83 ; Atmel AVR 8-bit microcontroller +EM_FR30 equ 84 ; Fujitsu FR30 +EM_D10V equ 85 ; Mitsubishi D10V +EM_D30V equ 86 ; Mitsubishi D30V +EM_V850 equ 87 ; NEC v850 +EM_M32R equ 88 ; Mitsubishi M32R +EM_MN10300 equ 89 ; Matsushita MN10300 +EM_MN10200 equ 90 ; Matsushita MN10200 +EM_PJ equ 91 ; picoJava +EM_OPENRISC equ 92 ; OpenRISC 32-bit embedded processor +EM_ARC_A5 equ 93 ; ARC Cores Tangent-A5 +EM_XTENSA equ 94 ; Tensilica Xtensa architecture +EM_NUM equ 95 + +EV_NONE equ 0 ; e_version, EI_VERSION +EV_CURRENT equ 1 +EV_NUM equ 2 + + +ELFOSABI_NONE equ 0 ; No extensions or unspecified +ELFOSABI_HPUX equ 1 ; Hewlett-Packard HP-UX +ELFOSABI_NETBSD equ 2 ; NetBSD +ELFOSABI_LINUX equ 3 ; Linux +ELFOSABI_UNKNOWN4 equ 4 +ELFOSABI_UNKNOWN5 equ 5 +ELFOSABI_SOLARIS equ 6 ; Sun Solaris +ELFOSABI_AIX equ 7 ; AIX +ELFOSABI_IRIX equ 8 ; IRIX +ELFOSABI_FREEBSD equ 9 ; FreeBSD +ELFOSABI_TRU64 equ 10 ; Compaq TRU64 UNIX +ELFOSABI_MODESTO equ 11 ; Novell Modesto +ELFOSABI_OPENBSD equ 12 ; Open BSD + + clrso +Elf32_Phdr.p_type: so.l 1 +Elf32_Phdr.p_offset: so.l 1 +Elf32_Phdr.p_vaddr: so.l 1 +Elf32_Phdr.p_paddr: so.l 1 +Elf32_Phdr.p_filesz: so.l 1 +Elf32_Phdr.p_memsz: so.l 1 +Elf32_Phdr.p_flags: so.l 1 +Elf32_Phdr.p_align: so.l 1 +Elf32_Phdr.sizeof equ __SO + +PT_NULL equ 0 ; p_type +PT_LOAD equ 1 +PT_DYNAMIC equ 2 +PT_INTERP equ 3 +PT_NOTE equ 4 +PT_SHLIB equ 5 +PT_PHDR equ 6 +PT_TLS equ 7 +PT_NUM equ 8 + +PT_LOOS equ $60000000 ; OS specific range + +; +; Note: The amd64 psABI defines that the UNWIND program header +; should reside in the OS specific range of the program +; headers. +; +PT_SUNW_UNWIND equ $6464e550 ; amd64 UNWIND program header +PT_GNU_EH_FRAME equ PT_SUNW_UNWIND + + +PT_LOSUNW equ $6ffffffa +PT_SUNWBSS equ $6ffffffa ; Sun Specific segment +PT_SUNWSTACK equ $6ffffffb ; describes the stack segment +PT_SUNWDTRACE equ $6ffffffc ; private +PT_SUNWCAP equ $6ffffffd ; hard/soft capabilities segment +PT_HISUNW equ $6fffffff +PT_HIOS equ $6fffffff + +PT_LOPROC equ $70000000 ; processor specific range +PT_HIPROC equ $7fffffff + +PF_R equ $4 ; p_flags +PF_W equ $2 +PF_X equ $1 + +PF_MASKOS equ $0ff00000 ; OS specific values +PF_MASKPROC equ $f0000000 ; processor specific values + +PF_SUNW_FAILURE equ $00100000 ; mapping absent due to failure + +PN_XNUM equ $ffff ; extended program header index + endif diff --git a/main.68k b/main.68k index 183e8c5..a46a30a 100644 --- a/main.68k +++ b/main.68k @@ -1,6 +1,8 @@ include cards.i include initrd.i include syscalls.i + include elf.i + include memory.i section .text,text public _start _start: @@ -11,18 +13,143 @@ _start: jsr syscall_vmem_map_free adda.l #(2*4096), a0 move.l a0, a7 + 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 #init_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 jsr syscall_exit section .data,data msg: dc.b "Hello from init",0 -init_name: dc.b "init.elf",0 +init_name: dc.b "init",0 section .bss,bss tmp_stack: ds.b 32