void init_kspace(int membottom) { uint32 *raw; /* there's an existing aspace at vaddr 0x803FD000 that was initialized by the 2nd stage loader */ raw = (uint32 *) 0x803FD000; flat = &_flat; flat->pdir = raw; flat->ptab = &raw[1024]; flat->high = &raw[2048]; memtotal = memsize; memsize -= 3; /* three pages already in use */ memory_init(membottom, memsize); toppage = (char *) kgetpages(3); /* kernel startup stack */ gdt = (char *) kgetpages(1); rsrc_init(kgetpages(6),4096*6); kernel = (task_t *) kmalloc(task_t); ktss = (TSS *) kgetpages(1); kernel->flags = tKERNEL; kernel->rsrc.id = 0; kernel->rsrc.owner = NULL; list_init(&kernel->rsrc.rights); list_init(&kernel->rsrc.queue); current = kernel; init_idt(idt = kgetpages(1)); /* init the new idt, save the old */ gdt2 = (void *) i386sgdt(&gdt2len); /* save the old gdt */ i386SetSegment(gdt + SEL_KCODE, /* #01 - 32bit DPL0 CODE */ 0, 0xFFFFF, i386rPRESENT | i386rDPL0 | i386rCODE, i386g4K | i386g32BIT); i386SetSegment(gdt + SEL_KDATA, /* #02 - 32bit DPL0 DATA */ 0, 0xFFFFF, i386rPRESENT | i386rDPL0 | i386rDATA, i386g4K | i386g32BIT); i386SetSegment(gdt + SEL_KDATA2, /* #02 - 32bit DPL0 DATA */ 0, 0xFFFFF, i386rPRESENT | i386rDPL0 | i386rDATA, i386g4K | i386g32BIT); i386SetSegment(gdt + SEL_UCODE, /* #03 - 32bit DPL3 CODE */ 0, 0xFFFFF, i386rPRESENT | i386rDPL3 | i386rCODE, i386g4K | i386g32BIT); i386SetSegment(gdt + SEL_UDATA, /* #04 - 32bit DPL3 DATA */ 0, 0xFFFFF, i386rPRESENT | i386rDPL3 | i386rDATA, i386g4K | i386g32BIT); i386SetSegment(gdt + SEL_KTSS, /* #05 - DPL0 TSS (Kernel) */ (uint32) ktss, 104, i386rPRESENT | i386rDPL0 | i386rTSS, 0); i386lgdt((uint32) gdt, 1024/8); asm("mov %%cr3, %0":"=r" (_cr3)); /* setup the kernel TSS to insure that it's happy */ ktss->cs = SEL_KCODE; ktss->ds = ktss->es = ktss->ss = ktss->fs = ktss->gs = SEL_KDATA; ktss->ldts = ktss->debugtrap = ktss->iomapbase = 0; ktss->cr3 = _cr3; ktss->ss0 = SEL_KDATA; ktss->esp1 = ktss->esp2 = ktss->ss1 = ktss->ss2 = 0; i386ltr(SEL_KTSS); }
/* * VERY simple elf loader. * * Make stupid assumptions like linear allocation of segments, in order */ void elf_load(void *base, size_t size) { elf_file_header_t *f; elf_program_header_t *ph; void *alloc_to = (void *)0; int i; f = base; if (f->magic != ELF_MAGIC) { kprint("Bad ELF magic found"); return; } if (f->type != ELF_TYPE_EXEC && f->type != ELF_TYPE_DYN_EXEC) { kprintf("Unknown ELF executable type (%x)\n", f->type); return; } for (i=0; i<(f->ph_entry_count); i++) { ph = base + f->program_head_offset + (f->ph_entry_size * i); if (ph->segment_type == ELF_PROG_SEG_LOAD) { int pages_needed = ((ph->mem_size) / PAGE_SIZE) + 1; void * pages[pages_needed]; void *abase = ph->virtual_addr; int i; /* Show what we are loading if debugging */ if (ph->flags & ELF_PS_READ) kprint("R"); if (ph->flags & ELF_PS_WRITE) kprint("W"); if (ph->flags & ELF_PS_EXEC) kprint("X"); kprintf("elf:\t0x%x(0x%x), mem 0x%x, dsk 0x%x, aln 0x%x\n", ph->phys_addr, ph->virtual_addr, ph->mem_size, ph->file_size, ph->alignment); /* Don't double allocate pages, no matter how * stupid and broken the ELF header is */ while (abase < alloc_to) { pages_needed--; abase += PAGE_SIZE; } alloc_to = abase + (PAGE_SIZE * pages_needed) - 1; kgetpages(pages_needed, pages); for (i = 0; i < pages_needed; i++) { paging_add_to_dir(kernel_page_dir, abase, pages[i]); abase += PAGE_SIZE; } kmemcpy(ph->virtual_addr, base+(ph->offset), ph->file_size); if (ph->file_size < ph->mem_size) { kmemset((ph->virtual_addr)+(ph->file_size), 0, (ph->mem_size - ph->file_size)); } } } #if 0 /* 2008-07-15: THIS IS BAD! * tempstack should NOT be used by things outside of inth.S or mem.S! * even that is going to be phased out... * * new_kthread is a much more sane way to be doing this even to bootstrap * usermode... */ /* Splinter, but give the tempstack, so we have to yield to make * sure that it is freed again before we are called again in this * thread */ splinter(f->entry, tempstack+PAGE_SIZE); yield(); #endif new_kthread(f->entry); }