/** * load_elf_file tries to load the ELF file specified in file_addr * * it first checks if the file is a PPC ELF executable and then loads * the segments depending if it is a 64bit or 32 bit ELF file * * @param file_addr pointer to the start of the elf file * @param entry pointer where the ELF loader will store * the entry point * @return 1 for a 32 bit file * 2 for a 64 bit file * anything else means an error during load */ int load_elf_file(unsigned long *file_addr, unsigned long *entry) { int type = elf_check_file(file_addr); switch (type) { case 1: *entry = load_segments(file_addr); break; case 2: *entry = load_segments64(file_addr); break; } return type; }
struct thread *init(struct multiboot *mboot, uint32_t mboot_magic) { struct process *idle, *init; struct module *module; struct memory_map *mem_map; size_t mem_map_count, i, addr; uintptr_t boot_image_size; void *boot_image; struct elf32_ehdr *init_image; struct elf32_ehdr *dl_image; /* initialize debugging output */ debug_init(); debug_printf("Rhombus Operating System Kernel v0.8a\n"); /* check multiboot header */ if (mboot_magic != 0x2BADB002) { debug_panic("bootloader is not multiboot compliant"); } /* touch pages for the kernel heap */ for (i = KSPACE; i < KERNEL_HEAP_END; i += SEGSZ) { page_touch(i); } /* identity map kernel boot frames */ for (i = KSPACE + KERNEL_BOOT; i < KSPACE + KERNEL_BOOT_END; i += PAGESZ) { page_set(i, page_fmt(i - KSPACE, PF_PRES | PF_RW)); } /* parse the multiboot memory map to find the size of memory */ mem_map = (void*) (mboot->mmap_addr + KSPACE); mem_map_count = mboot->mmap_length / sizeof(struct memory_map); for (i = 0; i < mem_map_count; i++) { if (mem_map[i].type == 1 && mem_map[i].base_addr_low <= 0x100000) { for (addr = 0; addr < mem_map[i].length_low; addr += PAGESZ) { frame_add(mem_map[i].base_addr_low + addr); } } } /* bootstrap process 0 (idle) */ idle = process_alloc(); idle->space = cpu_get_cr3(); idle->user = 0; /* fork process 1 (init) and switch */ init = process_clone(idle, NULL); process_switch(init); /* get multiboot module information */ if (mboot->mods_count < 3) { if (mboot->mods_count < 2) { if (mboot->mods_count < 1) { debug_panic("no boot or init or dl modules found"); } else { debug_panic("no boot or dl modules found"); } } else { debug_panic("no dl module found"); } } module = (void*) (mboot->mods_addr + KSPACE); init_image = (void*) (module[0].mod_start + KSPACE); boot_image = (void*) (module[1].mod_start + KSPACE); dl_image = (void*) (module[2].mod_start + KSPACE); boot_image_size = module[1].mod_end - module[1].mod_start; /* move boot image to BOOT_IMAGE in userspace */ mem_alloc(BOOT_IMAGE, boot_image_size, PF_PRES | PF_USER | PF_RW); memcpy((void*) BOOT_IMAGE, boot_image, boot_image_size); /* bootstrap thread 0 in init */ thread_bind(init->thread[0], init); init->thread[0]->useresp = init->thread[0]->stack + SEGSZ; init->thread[0]->esp = (uintptr_t) &init->thread[0]->num; init->thread[0]->ss = 0x23; init->thread[0]->ds = 0x23; init->thread[0]->cs = 0x1B; init->thread[0]->eflags = cpu_get_eflags() | 0x3200; /* IF, IOPL = 3 */ /* bootstrap idle thread */ idle->thread[0] = &__idle_thread; __idle_thread.proc = idle; /* load dl */ if (elf_check_file(dl_image)) { debug_panic("dl.so is not a valid ELF executable"); } elf_load_file(dl_image); /* execute init */ if (elf_check_file(init_image)) { debug_panic("init is not a valid ELF executable"); } elf_load_file(init_image); init->thread[0]->eip = init_image->e_entry; /* register system calls */ int_set_handler(SYSCALL_SEND, syscall_send); int_set_handler(SYSCALL_DONE, syscall_done); int_set_handler(SYSCALL_WHEN, syscall_when); int_set_handler(SYSCALL_RIRQ, syscall_rirq); int_set_handler(SYSCALL_ALSO, syscall_also); int_set_handler(SYSCALL_STAT, syscall_stat); int_set_handler(SYSCALL_PAGE, syscall_page); int_set_handler(SYSCALL_PHYS, syscall_phys); int_set_handler(SYSCALL_FORK, syscall_fork); int_set_handler(SYSCALL_EXIT, syscall_exit); int_set_handler(SYSCALL_STOP, syscall_stop); int_set_handler(SYSCALL_WAKE, syscall_wake); int_set_handler(SYSCALL_GPID, syscall_gpid); int_set_handler(SYSCALL_TIME, syscall_time); int_set_handler(SYSCALL_USER, syscall_user); int_set_handler(SYSCALL_AUTH, syscall_auth); int_set_handler(SYSCALL_PROC, syscall_proc); int_set_handler(SYSCALL_KILL, syscall_kill); int_set_handler(SYSCALL_VM86, syscall_vm86); int_set_handler(SYSCALL_NAME, syscall_name); int_set_handler(SYSCALL_REAP, syscall_reap); /* register fault handlers */ int_set_handler(FAULT_DE, fault_float); int_set_handler(FAULT_DB, fault_generic); int_set_handler(FAULT_NI, fault_generic); int_set_handler(FAULT_BP, fault_generic); int_set_handler(FAULT_OF, fault_generic); int_set_handler(FAULT_BR, fault_generic); int_set_handler(FAULT_UD, fault_generic); int_set_handler(FAULT_NM, fault_nomath); int_set_handler(FAULT_DF, fault_double); int_set_handler(FAULT_CO, fault_float); int_set_handler(FAULT_TS, fault_generic); int_set_handler(FAULT_NP, fault_generic); int_set_handler(FAULT_SS, fault_generic); int_set_handler(FAULT_GP, fault_gpf); int_set_handler(FAULT_PF, fault_page); int_set_handler(FAULT_MF, fault_float); int_set_handler(FAULT_AC, fault_generic); int_set_handler(FAULT_MC, fault_generic); int_set_handler(FAULT_XM, fault_nomath); /* start timer (for preemption) */ timer_set_freq(64); /* initialize FPU/MMX/SSE */ cpu_init_fpu(); /* drop to usermode, scheduling the next thread */ debug_printf("dropping to usermode\n"); return thread_switch(NULL, schedule_next()); }