Commit ae98eb9f by malcolm

Merge branch 'elf_load' into 'master'

Elf load

Still doesn't compile due to assembler errors. But not that far off.

See merge request !20
parents 8e6d9b19 8ab5d6ea
...@@ -11,16 +11,31 @@ void load_elf(elf_header* elf_start) ...@@ -11,16 +11,31 @@ void load_elf(elf_header* elf_start)
// The elf will get its own memory space. // The elf will get its own memory space.
page_directory_entry* pgdir = page_new_directory(); page_directory_entry* pgdir = page_new_directory();
void* highest_vpage = (void*)0;
serial_writestring("Loading elf\n");
// loop through and copy memory segments // loop through and copy memory segments
for (int i = 0; i < elf_start->ph_entry_count; i++) for (int i = 0; i < elf_start->ph_entry_count; i++)
{ {
serial_writestring("Loading memory segment\n");
// get this section header // get this section header
elf_program_header* ph; elf_program_header* ph;
ph = (elf_program_header*) elf_start + (elf_start->ph_table_offset + (i * elf_start->ph_entry_size)); ph = (elf_program_header*) ((uint32_t)elf_start + (uint32_t)(elf_start->ph_table_offset + (i * elf_start->ph_entry_size)));
serial_hexword((uint32_t)elf_start);
serial_writechar('\n');
serial_hexword((uint32_t)ph);
serial_writechar('\n');
serial_hexword((uint32_t)elf_start + (uint32_t)(elf_start->ph_table_offset + (i * elf_start->ph_entry_size)));
serial_writechar('\n');
// map and copy // map and copy
for (void* pg = (void*)((uint32_t)ph->p_vaddr & 0xfffff000); (uint32_t)(pg - ph->p_vaddr) < ph->memory_segment_size; pg+=0x1000) for (void* pg = (void*)((uint32_t)ph->p_vaddr & 0xfffff000); ((int)pg - (int)ph->p_vaddr) < (int)ph->memory_segment_size; pg+=0x1000)
{ {
serial_writestring("Copying in memory segment\n");
void* real_page = page_map(pgdir, pg); void* real_page = page_map(pgdir, pg);
void* start = (pg > ph->p_vaddr) ? pg : ph->p_vaddr; void* start = (pg > ph->p_vaddr) ? pg : ph->p_vaddr;
...@@ -30,7 +45,43 @@ void load_elf(elf_header* elf_start) ...@@ -30,7 +45,43 @@ void load_elf(elf_header* elf_start)
size_t offset = (pg > ph->p_vaddr) ? 0 : ph->p_vaddr - pg; size_t offset = (pg > ph->p_vaddr) ? 0 : ph->p_vaddr - pg;
// do some memcpy stuff // do some memcpy stuff
page_table_inspect(kernel_page_directory, real_page);
memcpy(real_page + offset, start, size); memcpy(real_page + offset, start, size);
// save the highest start
if (pg > highest_vpage)
{
highest_vpage = pg;
}
break;
} }
} }
// Allocate two more pages for stack
page_map(pgdir, highest_vpage + 0x1000);
page_map(pgdir, highest_vpage + 0x2000);
// initial esp = highest_vpage + 0x1000
process* pcb = kmalloc(sizeof(process) + sizeof(context) + sizeof(trapframe));
pcb->ctxt = (context*)((size_t)pcb + sizeof(process));
pcb->tf = (trapframe*)((size_t)pcb + sizeof(process) + sizeof(context));
pcb->mem = pgdir;
pcb->pid = -1;
pcb->parent = 0;
pcb->kstack = 0;
//pcb->name = "debugstuff";
pcb->state = RUNNABLE;
pcb->ctxt->edi = 0;
pcb->ctxt->esi = 0;
pcb->ctxt->ebx = 0;
pcb->ctxt->ebp = (uint32_t)highest_vpage + 0x1000;
pcb->ctxt->eip = (uint32_t)elf_start->program_entry_position;
pcb->tf->ebp = (uint32_t)highest_vpage + 0x1000;
pcb->tf->eip = (uint32_t)elf_start->program_entry_position;
addproc(pcb);
asm("mov $3, %eax; int 0x80");
} }
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
#include "mem.h" #include "mem.h"
#include "string.h" #include "string.h"
#include "serial.h"
#include "PCB.h"
extern uint8_t elf_hello[] asm("_binary_hello_elf_start"); extern uint8_t elf_hello[] asm("_binary_hello_elf_start");
......
...@@ -82,6 +82,8 @@ void kernel_main(multiboot_info* mbt, uint32_t magic) ...@@ -82,6 +82,8 @@ void kernel_main(multiboot_info* mbt, uint32_t magic)
serial_hexstring(elf_hello, 4); serial_hexstring(elf_hello, 4);
serial_writestring("\n"); serial_writestring("\n");
load_elf((elf_header*)&elf_hello);
test_idt(); test_idt();
while(true) while(true)
{ {
......
...@@ -5,14 +5,6 @@ ...@@ -5,14 +5,6 @@
#include "mem.h" #include "mem.h"
#include "serial.h" #include "serial.h"
// page_directory is currently defined once and should not be touched
// later. It must be page aligned for the MMU to read properly
page_directory_entry page_directory[1024] __attribute__((aligned(4096)));
// page_table_one is the first page table, and at the beginning the
// only page table in the page directory
page_table_entry page_table_one[1024] __attribute__((aligned(4096)));
// populate_page_table makes a page table at `table` mapping `num` // populate_page_table makes a page table at `table` mapping `num`
// pages to bytes after `start + offset*4KB` // pages to bytes after `start + offset*4KB`
// both table and start must be properly aligned // both table and start must be properly aligned
...@@ -77,6 +69,22 @@ void page_free(void* page_start) ...@@ -77,6 +69,22 @@ void page_free(void* page_start)
*index = ~(~*index | (1<<(8-(page_number%8)))); *index = ~(~*index | (1<<(8-(page_number%8))));
} }
// Just pages the entire addressable space. Takes about 4MB of space.
// Should be ~fine~ this won't break things I totally know what I'm doing
void page_everything(page_directory_entry* pg_dir)
{
for (int i = 0; i < 1024; i++)
{
page_table_entry* pg_tab = (page_table_entry*) page_allocate();
pg_dir[i] = (page_directory_entry)((uint32_t)pg_tab | PAGE_WRITABLE | PAGE_PRESENT);
for (int j = 0; j < 1024; j++)
{
void* page = (void*)((i << 22) | (j << 12));
pg_tab[j] = (page_directory_entry)((uint32_t)page | PAGE_WRITABLE | PAGE_PRESENT);
}
}
}
// This goes through all available memory, and maps 1 to 1 virtual memory to it. // This goes through all available memory, and maps 1 to 1 virtual memory to it.
page_directory_entry* mem_init_kern_tables(multiboot_memory_map* mmap, multiboot_memory_map* mmap_end) page_directory_entry* mem_init_kern_tables(multiboot_memory_map* mmap, multiboot_memory_map* mmap_end)
{ {
...@@ -86,60 +94,64 @@ page_directory_entry* mem_init_kern_tables(multiboot_memory_map* mmap, multiboot ...@@ -86,60 +94,64 @@ page_directory_entry* mem_init_kern_tables(multiboot_memory_map* mmap, multiboot
page_allocate(); page_allocate();
} }
// Make a page directory structure easily // Initilize a directory mapped to everything
page_directory_entry* kern_page_dir = initiate_directory(); page_directory_entry* kern_page_dir = kernel_page_directory;
page_everything(kern_page_dir);
// _kern_end is defined in the linker script // _kern_end is defined in the linker script
/* page_table_entry* next_table = (page_table_entry*) &_kernel_end; */ /* page_table_entry* next_table = (page_table_entry*) &_kernel_end; */
int current_dir_entry = 0; //int current_dir_entry = 0;
uint32_t totalmem = 0;
// For each entry in the memory map // For each entry in the memory map
while (mmap < mmap_end) while (mmap < mmap_end)
{ {
void* next_table = page_allocate(); //void* next_table = page_allocate();
// Special case for the first memory segment - it gets its own directory entry // Special case for the first memory segment - it gets its own directory entry
if (mmap->base_addr == 0) if (mmap->base_addr == 0)
{ {
// Lower memory should be first in the page directory and // Lower memory should be first in the page directory and
// mapped one to one // mapped one to one
populate_page_table(next_table, 0, 1024, 0); /* populate_page_table(next_table, 0, 1024, 0); */
page_directory[0] = (uint32_t) next_table; /* kern_page_dir[0] = (uint32_t) next_table; */
page_directory[0] |= PAGE_WRITABLE | PAGE_PRESENT; /* kern_page_dir[0] |= PAGE_WRITABLE | PAGE_PRESENT; */
current_dir_entry = 1; /* current_dir_entry = 1; */
/* next_table += 0x1000; */ /* next_table += 0x1000; */
} }
else if (mmap->type == 1) else if (mmap->type == 1)
{ {
uint32_t i; totalmem += mmap->length;
for (i = 0; i+0x1000000 < mmap->length; i += 0x1000000) /* uint32_t i; */
{ /* for (i = 0; i+0x1000000 < mmap->length; i += 0x1000000) */
populate_page_table(next_table, (void*)(intptr_t) mmap->base_addr + i, 1024 ,0); /* { */
page_directory[current_dir_entry] = (uint32_t) next_table; /* populate_page_table(next_table, (void*)(intptr_t) mmap->base_addr + i, 1024 ,0); */
page_directory[current_dir_entry] |= PAGE_WRITABLE | PAGE_PRESENT; /* kern_page_dir[current_dir_entry] = (uint32_t) next_table; */
/* kern_page_dir[current_dir_entry] |= PAGE_WRITABLE | PAGE_PRESENT; */
current_dir_entry += 1;
/* next_table += 0x1000; */ /* current_dir_entry += 1; */
} /* /\* next_table += 0x1000; *\/ */
/* } */
// There will be an edge case where there is less than a // There will be an edge case where there is less than a
// full page table to be mapped. This handlis this case. // full page table to be mapped. This handlis this case.
if (i != mmap->length) /* if (i != mmap->length) */
{ /* { */
populate_page_table(next_table, (void*)(intptr_t) mmap->base_addr + i, (mmap->length - i) / 0x1000 ,0); /* populate_page_table(next_table, (void*)(intptr_t) mmap->base_addr + i, (mmap->length - i) / 0x1000 ,0); */
page_directory[current_dir_entry] = (uint32_t) next_table; /* kern_page_dir[current_dir_entry] = (uint32_t) next_table; */
page_directory[current_dir_entry] |= PAGE_WRITABLE | PAGE_PRESENT; /* kern_page_dir[current_dir_entry] |= PAGE_WRITABLE | PAGE_PRESENT; */
current_dir_entry += 1; /* current_dir_entry += 1; */
/* next_table += 0x1000; */ /* /\* next_table += 0x1000; *\/ */
} /* } */
} }
mmap = (multiboot_memory_map*)((uint32_t)mmap + mmap->size + sizeof(uint32_t)); mmap = (multiboot_memory_map*)((uint32_t)mmap + mmap->size + sizeof(uint32_t));
} }
// let the memory allocator work freely with all remaining memory // let the memory allocator work freely with all remaining memory
memory_mark = page_allocate(); /* memory_mark = page_allocate(); */
return kern_page_dir; return kern_page_dir;
} }
...@@ -149,16 +161,17 @@ page_directory_entry* mem_init_kern_tables(multiboot_memory_map* mmap, multiboot ...@@ -149,16 +161,17 @@ page_directory_entry* mem_init_kern_tables(multiboot_memory_map* mmap, multiboot
void* page_map(page_directory_entry pgdir[], void* page_start) void* page_map(page_directory_entry pgdir[], void* page_start)
{ {
void* page = 0; void* page = 0;
if ((pgdir[(uint32_t)page_start>>22] & 0xfffff) == 0) if ((pgdir[(uint32_t)page_start>>22] & 0xfffff000) == 0)
{ {
pgdir[(uint32_t)page_start>>22] |= (page_directory_entry)page_new_table(); pgdir[(uint32_t)page_start>>22] |= (page_directory_entry)page_new_table();
} }
page_table_entry* page_table = (page_table_entry*) ((uint32_t) pgdir[(uint32_t)page_start>>22] & 0xfffff000); page_table_entry* page_table = (page_table_entry*) ((uint32_t) pgdir[(uint32_t)page_start>>22] & 0xfffff000);
if ((page_table[((uint32_t)page_start >> 12) % 1024] & 0xfffff) == 0) if ((page_table[((uint32_t)page_start >> 12) % 1024] & 0xfffff000) == 0)
{ {
page = page_allocate(); page = page_allocate();
page_table[((uint32_t)page_start>>12)%1024] |= (page_table_entry)page; page_table[((uint32_t)page_start>>12)%1024] |= (page_table_entry)page;
} }
return page; return page;
} }
...@@ -209,15 +222,15 @@ page_directory_entry* initiate_directory() ...@@ -209,15 +222,15 @@ page_directory_entry* initiate_directory()
// Write Enabled: It can be both read from and written to // Write Enabled: It can be both read from and written to
// (this is the 2 bit) // (this is the 2 bit)
// Not Present: The page table is not present // Not Present: The page table is not present
page_directory[i] = 0; kernel_page_directory[i] = 0;
page_directory[i] |= PAGE_WRITABLE; kernel_page_directory[i] |= PAGE_WRITABLE;
} }
// Set last directory entry to point back // Set last directory entry to point back
page_directory[1023] = (uint32_t) page_directory; kernel_page_directory[1023] = (uint32_t) kernel_page_directory;
page_directory[1023] |= PAGE_WRITABLE | PAGE_PRESENT; kernel_page_directory[1023] |= PAGE_WRITABLE | PAGE_PRESENT;
return page_directory; return kernel_page_directory;
} }
void* malloc(uint32_t bytes) void* malloc(uint32_t bytes)
...@@ -232,3 +245,21 @@ void* kmalloc(uint32_t size __attribute__((unused))) ...@@ -232,3 +245,21 @@ void* kmalloc(uint32_t size __attribute__((unused)))
{ {
return page_allocate(); return page_allocate();
} }
// Debugging
void* page_table_inspect(page_directory_entry* pg_dir, void* addr)
{
serial_writestring("Inspecting page tables for address 0x");
serial_hexword((uint32_t)addr);
serial_writestring("\nDirectory Entry: 0x");
page_directory_entry page_dir_entry = pg_dir[((uint32_t)addr) >> 22];
serial_hexword(page_dir_entry);
serial_writestring("\nPage Table Entry: 0x");
page_table_entry* page_table = (page_table_entry*)((uint32_t) page_dir_entry & 0xfffff000);
page_table_entry pg_tab_entry = page_table[((uint32_t)addr >> 12) % 1024];
serial_hexword(pg_tab_entry);
serial_writechar('\n');
return (void*)((uint32_t)pg_tab_entry & 0xfffff000);
}
...@@ -27,6 +27,10 @@ typedef uint32_t page_table_entry; ...@@ -27,6 +27,10 @@ typedef uint32_t page_table_entry;
extern void loadPageDirectory(page_directory_entry*); extern void loadPageDirectory(page_directory_entry*);
extern void enablePaging(); extern void enablePaging();
// page_directory is currently defined once and should not be touched
// later. It must be page aligned for the MMU to read properly
page_directory_entry kernel_page_directory[1024] __attribute__((aligned(4096)));
// Defined in linker.ld // Defined in linker.ld
extern char _kernel_end[]; extern char _kernel_end[];
...@@ -36,6 +40,7 @@ void page_free(void* page_start); ...@@ -36,6 +40,7 @@ void page_free(void* page_start);
void* page_map(page_directory_entry pgdir[], void* page_start); void* page_map(page_directory_entry pgdir[], void* page_start);
// Initilization // Initilization
void page_everything(page_directory_entry* pg_dir);
page_directory_entry* mem_init_kern_tables(multiboot_memory_map* mmap, multiboot_memory_map* mmap_end); page_directory_entry* mem_init_kern_tables(multiboot_memory_map* mmap, multiboot_memory_map* mmap_end);
// Directory and table handling // Directory and table handling
...@@ -51,6 +56,9 @@ void* memory_mark; ...@@ -51,6 +56,9 @@ void* memory_mark;
void* kmalloc(uint32_t); void* kmalloc(uint32_t);
void* malloc(uint32_t bytes); void* malloc(uint32_t bytes);
// Debugging
void* page_table_inspect(page_directory_entry* pg_dir, void* addr);
// Required for elf loading - virtual memory and stuff // Required for elf loading - virtual memory and stuff
// TODO: // TODO:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment