Hey jnc100,
Well I fixed it so far but there is quiet a problem somewhere. It can't display the addresses after page initialization. For the page aligning there is a possebility to use it or not. In the main I am currently not using it tough. The first problem was a problem with the linker script and a variable. But so far it seems to work except for the part that it the variables b, c, d don't display their address. Only a does which is for the page initialization.
This is the main:
Code: Select all
int main() {
gdt_install();
idt_install();
isrs_install();
irq_install();
init_video();
timer_install();
keyboard_install();
//initialize_paging();
__asm__ __volatile__ ("sti");
settextcolor(0x9, 0xF);
puts("Welcome.\n");
puts("\n");
print_floppy_info();
puts("\n");
settextcolor(0x0, 0xF);
unsigned int a = kmalloc(8);
initialize_paging();
unsigned int b = kmalloc(8);
unsigned int c = kmalloc(8);
puts("a: ");
putd(a);
puts(", b: ");
putd(b);
puts("\nc: ");
putd(c);
kfree(c);
kfree(b);
unsigned int d = kmalloc(12);
puts(", d: ");
putd(d);
for (;;);
return 0;
}
I use putd instead of puth because puth broke yesterday
.
kmalloc:
Code: Select all
unsigned int kmalloc_int(unsigned int size, int align, unsigned int* phys) {
if (kheap != 0) {
void *addr = alloc(size, (unsigned char)align, kheap);
if (phys != 0) {
mpage *page = get_page((unsigned int)addr, 0, kernel_directory);
*phys = page->frame*0x1000 + ((unsigned int)addr&0xFFFFF000);
}
return (unsigned int)addr;
} else {
if (align == 1 && (placement_address & 0xFFFFF000)) {
// Align the placement address;
placement_address &= 0xFFFFF000;
placement_address += 0x1000;
}
if (phys) {
*phys = placement_address;
}
unsigned int tmp = placement_address;
placement_address += size;
return tmp;
}
}
unsigned int kmalloc_ap(unsigned int size, unsigned int *phys) { // page aligned and returns a physical address.
return kmalloc_int(size, 1, phys);
}
unsigned int kmalloc_a(unsigned int size) { // page aligned.
return kmalloc_int(size, 1, 0);
}
unsigned int kmalloc_p(unsigned int size, unsigned int *phys) { // returns a physical address.
return kmalloc_int(size, 0, phys);
}
unsigned int kmalloc(unsigned int size) {
return kmalloc_int(size, 0, 0);
}
The alloc function:
Code: Select all
void *alloc(unsigned int size, unsigned char page_align, mheap *heap) {
// Make sure we take the size of header/footer into account.
unsigned int new_size = size + sizeof(mheader) + sizeof(mfooter);
// Find the smallest hole that will fit.
signed int iterator = find_smallest_hole(new_size, page_align, heap);
if (iterator == -1) { // If we didn't find a suitable hole
// Save some previous data.
unsigned int old_length = heap->end_address - heap->start_address;
unsigned int old_end_address = heap->end_address;
// We need to allocate some more space.
expand(old_length + new_size, heap);
unsigned int new_length = heap->end_address-heap->start_address;
// Find the endmost header. (Not endmost in size, but in location).
iterator = 0;
// Vars to hold the index of, and value of, the endmost header found so far.
unsigned int idx = -1;
unsigned int value = 0x0;
while (iterator < heap->index.size) {
unsigned int tmp = (unsigned int)lookup_ordered_array(iterator, &heap->index);
if (tmp > value) {
value = tmp;
idx = iterator;
}
iterator++;
}
// If we didn't find ANY headers, we need to add one.
if (idx == -1) {
mheader *header = (mheader *)old_end_address;
header->magic = HEAP_MAGIC;
header->size = new_length - old_length;
header->is_hole = 1;
mfooter *footer = (mfooter *) (old_end_address + header->size - sizeof(mfooter));
footer->magic = HEAP_MAGIC;
footer->header = header;
insert_ordered_array((void*)header, &heap->index);
} else {
// The last header needs adjusting.
mheader *header = lookup_ordered_array(idx, &heap->index);
header->size += new_length - old_length;
// Rewrite the footer.
mfooter *footer = (mfooter *) ( (unsigned int)header + header->size - sizeof(mfooter) );
footer->header = header;
footer->magic = HEAP_MAGIC;
}
// We now have enough space. Recurse, and call the function again.
return alloc(size, page_align, heap);
}
mheader *orig_hole_header = (mheader *)lookup_ordered_array(iterator, &heap->index);
unsigned int orig_hole_pos = (unsigned int)orig_hole_header;
unsigned int orig_hole_size = orig_hole_header->size;
// Here we work out if we should split the hole we found into two parts.
// Is the original hole size - requested hole size less than the overhead for adding a new hole?
if (orig_hole_size-new_size < sizeof(mheader)+sizeof(mfooter)) {
// Then just increase the requested size to the size of the hole we found.
size += orig_hole_size-new_size;
new_size = orig_hole_size;
}
// If we need to page-align the data, do it now and make a new hole in front of our block.
if (page_align && orig_hole_pos&0xFFFFF000) { // 0x1000 = page size
unsigned int new_location = orig_hole_pos + 0x1000 - (orig_hole_pos&0xFFF) - sizeof(mheader);
mheader *hole_header = (mheader *)orig_hole_pos;
//0x1000 = page size
hole_header->size = 0x1000 - (orig_hole_pos&0xFFF) - sizeof(mheader);
hole_header->magic = HEAP_MAGIC;
hole_header->is_hole = 1;
mfooter *hole_footer = (mfooter *) ((unsigned int)new_location - sizeof(mfooter));
hole_footer->magic = HEAP_MAGIC;
hole_footer->header = hole_header;
orig_hole_pos = new_location;
orig_hole_size = orig_hole_size - hole_header->size;
} else {
// Else we don't need this hole any more, delete it from the index.
remove_ordered_array(iterator, &heap->index);
}
// Overwrite the original header...
mheader *block_header = (mheader *)orig_hole_pos;
block_header->magic = HEAP_MAGIC;
block_header->is_hole = 0;
block_header->size = new_size;
// ...And the footer
mfooter *block_footer = (mfooter *) (orig_hole_pos + sizeof(mheader) + size);
block_footer->magic = HEAP_MAGIC;
block_footer->header = block_header;
// We may need to write a new hole after the allocated block.
// We do this only if the new hole would have positive size...
if (orig_hole_size - new_size > 0) {
mheader *hole_header = (mheader *) (orig_hole_pos + sizeof(mheader) + size + sizeof(mfooter));
hole_header->magic = HEAP_MAGIC;
hole_header->is_hole = 1;
hole_header->size = orig_hole_size - new_size;
mfooter *hole_footer = (mfooter *) ( (unsigned int)hole_header + orig_hole_size - new_size - sizeof(mfooter) );
if ((unsigned int)hole_footer < heap->end_address) {
hole_footer->magic = HEAP_MAGIC;
hole_footer->header = hole_header;
}
// Put the new hole in the index;
insert_ordered_array((void*)hole_header, &heap->index);
}
// ...And we're done!
return (void *) ( (unsigned int)block_header+sizeof(mheader) );
}
And for in case you still need alloc_frame and get_page:
Code: Select all
mpage *get_page(unsigned int address, int make, mpage_directory *dir) {
// Turn the address into an index.
address /= 0x1000;
// Find the page table containing this address.
unsigned int table_idx = address / 1024;
if (dir->tables[table_idx]) { // If this table is already assigned
return &dir->tables[table_idx]->pages[address%1024];
} else if(make) {
unsigned int tmp;
dir->tables[table_idx] = (mpage_table*)kmalloc_ap(sizeof(mpage_table), &tmp);
dir->tablesPhysical[table_idx] = tmp | 0x7; // PRESENT, RW, US.
return &dir->tables[table_idx]->pages[address%1024];
} else {
return 0;
}
}
void alloc_frame(mpage *page, int is_kernel, int is_writeable) {
if (page->frame != 0) {
return;
} else {
unsigned int idx = first_frame();
if (idx == (unsigned int)-1) {
// PANIC! no free frames!!
}
set_frame(idx*0x1000);
page->present = 1;
page->rw = (is_writeable)?1:0;
page->user = (is_kernel)?0:1;
page->frame = idx;
}
}
Sorry if the code is too long and thanks for helping.
Regards, Stephan J.R. van Schaik.