uint32_t elf_load_executable(void* file) { elf_header_t* header = (elf_header_t*)file; if(header->e_ident[0] != ELFMAG0 || header->e_ident[1] != ELFMAG1 || header->e_ident[2] != ELFMAG2 || header->e_ident[3] != ELFMAG3) { last_error = ELF_ERR_WRONG_MAGIC; return 0; } if(header->e_ident[4] != ELFCLASS32) { last_error = ELF_ERR_WRONG_CLASS; return 0; } if(header->e_phoff == 0 || header->e_phnum == 0) { last_error = ELF_ERR_NO_PROGRAM_HEADER; return 0; } for(uint32_t i = 0; i < header->e_phnum; i++) { elf_ph_t* program_header = (elf_ph_t*)(((uint32_t)file) + header->e_phoff + (header->e_phentsize * i)); printf("Found ProgramHeader type 0x%x\n", program_header->type); if(program_header->type == 1) { //Type 'LOAD' printf("Loading Header from 0x%x size 0x%x to 0x%x size 0x%x\n", program_header->offset, program_header->filesize, program_header->vaddr, program_header->memsize); vmm_map_range(program_header->vaddr, program_header->vaddr + program_header->memsize, 0, ((program_header->flags & PF_W) == PF_W)); memcpy((void*)program_header->vaddr, (void*)(((uint32_t)file) + program_header->offset), program_header->memsize); } } vmm_map_range(KERNEL_VIRTUAL_BASE - 2 * 4096, KERNEL_VIRTUAL_BASE, 0, 1); return header->e_entry; }
/* bring up an AP */ static void smp_boot(cpu_t *cpu) { /* figure out where the trampoline is */ extern int trampoline_start, trampoline_end, trampoline_stack; size_t trampoline_len = (uintptr_t) &trampoline_end - (uintptr_t) &trampoline_start; /* map the trampoline into low memory */ if (!vmm_map_range(TRAMPOLINE_BASE, TRAMPOLINE_BASE, trampoline_len, VM_R | VM_W | VM_X)) panic("couldn't map SMP trampoline code"); /* allocate a stack for this AP */ void *idle_stack = memalign(IDLE_STACK_ALIGN, IDLE_STACK_SIZE); if (!idle_stack) panic("couldn't allocate AP stack"); /* set up this cpu's bootstrap stack */ uint64_t *rsp = (uint64_t *) &trampoline_stack; *rsp = (uint64_t) idle_stack + IDLE_STACK_SIZE; /* set the pointer to the cpu struct of the cpu we are booting */ booted_cpu = cpu; /* copy the trampoline into low memory */ memcpy((void *) TRAMPOLINE_BASE, &trampoline_start, trampoline_len); /* reset the ack flag */ ack_sipi = false; barrier(); /* send INIT IPI */ apic_ipi_init(cpu->lapic_id); pit_mdelay(10); /* send STARTUP IPI */ uint8_t vector = TRAMPOLINE_BASE / FRAME_SIZE; apic_ipi_startup(cpu->lapic_id, vector); pit_mdelay(1); /* send STARTUP IPI again */ if (!ack_sipi) { apic_ipi_startup(cpu->lapic_id, vector); pit_mdelay(1); } /* wait for the AP to come up */ while (!ack_sipi) pause_once(); /* unmap the trampoline */ vmm_unmap_range(TRAMPOLINE_BASE, trampoline_len); }
void kernel_main(struct multiboot_info* mb_info) { uint32_t kernel_init_pdir = vmm_init(); kprintf("Setting PIT interval...\n"); outb(0x43, 0x36); outw(0x40, 1000); kprintf("Initializing vfs...\n"); vfs_init_root(); ramfs_fifo_init(); ramfs_block_init(); driver_keyboard_init(); map_address_active((uint32_t) mb_info, (uint32_t) mb_info, 0); map_address_active((uint32_t) mb_info->mi_mods_addr, (uint32_t) mb_info->mi_mods_addr, 0); if (mb_info->mi_flags & MULTIBOOT_INFO_HAS_MODS) { vmm_map_range(mb_info->mi_mods_addr[0].start, mb_info->mi_mods_addr[0].start, mb_info->mi_mods_addr[0].end - mb_info->mi_mods_addr[0].start, 0); kprintf("Assuming mbmod[0] is a tarball (%d bytes) and unpacking it... \n", mb_info->mi_mods_addr[0].end - mb_info->mi_mods_addr[0].start); kprintf("Mapped mod from %x to %x\n", mb_info->mi_mods_addr[0].start, mb_info->mi_mods_addr[0].end); tar_load_ramfs(mb_info->mi_mods_addr[0].start); } else { kprintf("[PANIC] No multiboot module (initrfs) available.\n"); } kprintf("[kernel_res] Creating /dev/vga\n"); vfs_create_kfile("/dev/vga", ramfs_vga_driver_struct(), 0); if(vfs_exists("/ibin/init")) { kprintf("[init] /ibin/init found. Executing...\n"); vfs_exec("/ibin/init", 0); enableScheduling(); } while(1); //*********************************************************************** KERNEL END }
void *mmio_map(uintptr_t phy, size_t len, vm_acc_t flags) { /* align the address and pad with extra length */ uintptr_t aligned_phy = PAGE_ALIGN_REVERSE(phy); size_t off = phy - aligned_phy; len += off; /* reserve some virtual memory in the heap */ uintptr_t aligned_virt = (uintptr_t) heap_reserve(len); if (!aligned_virt) return 0; /* map the physical memory into virtual memory */ if (!vmm_map_range(aligned_virt, aligned_phy, len, flags)) { heap_free((void *) aligned_virt); return 0; } /* return where the memory is mapped */ return (void *) (aligned_virt + off); }
void vmm_init(void) { struct vmm_flags flags = { .present = 1, .privileged = 1, .writeable = 1, .pwt = 0, .dis_cache = 0, .dirty = 0}; kernel_pd = (struct page_directory *)(MMAP_PHYS_PAGING); memset(kernel_pd, 0, sizeof(struct page_directory)); vmm_set_directory(kernel_pd); /* kernel page pdes & ptes */ vmm_map_range(flags, MMAP_PHYS_PAGING, MMAP_PHYS_PAGING, (MMAP_PHYS_PAGING + MMAP_SIZE_PAGING) / PAGE_ALIGNMENT); /* pmm */ flags.writeable = 0; vmm_map_range(flags, MMAP_PHYS_PMM, MMAP_PHYS_PMM, (MMAP_SIZE_PMM + MMAP_PHYS_PMM) / PAGE_ALIGNMENT); /* kernel identity mapping */ vmm_map_range(flags, (uint)(&KERNEL_START), (uint)(&KERNEL_START), ALIGN_UP((uint)(&KERNEL_END)-(uint)(&KERNEL_START)) / PAGE_ALIGNMENT); /* video identity mapping */ flags.privileged = 0; vmm_map_range(flags, MMAP_PHYS_VIDEO, MMAP_PHYS_VIDEO, (MMAP_PHYS_VIDEO + MMAP_SIZE_VIDEO) / PAGE_ALIGNMENT); /* everything needed is mapped, enable paging */ vmm_enable(); /* not working yet struct page_directory *copy_pd = vmm_create_directory(0x400000); vmm_set_directory(copy_pd);*/ } void vmm_map(struct vmm_flags flags, uint phys_addr, uint virt_addr) { static byte map_lock; struct page_directory_entry *t_pde = 0; struct page_table_entry *t_pte = 0; struct page_table *t_pt = 0; uint tmp_va; assert(current_pd != 0); assert(virt_addr > 0); assert(phys_addr > 0); lock_acquire(&map_lock); t_pde = ¤t_pd->entry[VA_TO_DIR(virt_addr)]; t_pt = vmm_get_table(flags, VA_TO_DIR(virt_addr)); t_pte = &t_pt->entry[VA_TO_TBL(virt_addr)]; /* check, if the pte is present */ if(t_pte->page == 0 && t_pte->present == 0) { t_pte->present = flags.present; t_pte->writeable = flags.writeable; t_pte->privileged = flags.privileged; t_pte->pwt = flags.pwt; t_pte->dis_cache = flags.dis_cache; t_pte->page = ((uint)phys_addr) >> 12; } else { /* error: doppelter eintrag */ }