i following JamesM's paging tutorial.
but when i run the code grub says that the kernel isn't executeable and give error code 13
when i leaving out the pagingpart the kernel will be started.
so i tried to comment some code in the paging.c to locate the error, it looks like the error is in the 3 first functions of this code:
Code: Select all
#include <heap.h>
#include <string.h>
#include <paging.h>
extern unsigned int placement_address;
page_directory_t *kernel_directory = 0;
page_directory_t *current_directory = 0;
unsigned int *frames;
unsigned int nframes;
#define INDEX_FROM_BIT(a) (a/(8*4))
#define OFFSET_FROM_BIT(a) (a%(8*4))
static void set_frame(unsigned int frame_addr) {
unsigned int frame = frame_addr/0x1000;
unsigned int idx = INDEX_FROM_BIT(frame);
unsigned int off = OFFSET_FROM_BIT(frame);
frames[idx] |= (0x1 << off);
}
static void clear_frame(unsigned int frame_addr) {
unsigned int frame = frame_addr/0x1000;
unsigned int idx = INDEX_FROM_BIT(frame);
unsigned int off = OFFSET_FROM_BIT(frame);
frames[idx] &= ~(0x1 << off);
}
static unsigned int test_frame(unsigned int frame_addr) {
unsigned int frame = frame_addr/0x1000;
unsigned int idx = INDEX_FROM_BIT(frame);
unsigned int off = OFFSET_FROM_BIT(frame);
return (frames[idx] & (0x1 << off));
}
static unsigned int first_frame() {
unsigned int i, j;
for (i = 0; i < INDEX_FROM_BIT(nframes); i++) {
if (frames[i] != 0xFFFFFFFF) {
for (j = 0; j < 32; j++) {
unsigned int toTest = 0x1 << j;
if (!(frames[i] & toTest)) {
return i * 4 * 8 + j;
}
}
}
}
}
void alloc_frame(page_t *page, int is_kernel, int is_writeable) {
if (page->frame != 0) {
return;
} else {
unsigned int idx = first_frame();
if (idx == (unsigned int) -1) {}
set_frame(idx * 0x1000);
page->present = 1;
page->rw = (is_writeable) ? 1 : 0;
page->user = (is_kernel) ? 0 : 1;
page->frame = idx;
}
}
void free_frame(page_t *page) {
unsigned int frame;
if (!(frame = page->frame)) {
return;
} else {
clear_frame(frame);
page->frame = 0x0;
}
}
void init_paging() {
unsigned int mem_end_page = 0x1000000;
nframes = mem_end_page / 0x1000;
frames = (unsigned int *) malloc(INDEX_FROM_BIT(nframes));
memset(frames, 0, INDEX_FROM_BIT(nframes));
kernel_directory = (page_directory_t *) malloc_a(sizeof(page_directory_t));
memset(kernel_directory, 0, sizeof(page_directory_t));
current_directory = kernel_directory;
int i = 0;
while(i < placement_address) {
alloc_frame(get_page(i, 1, kernel_directory), 0, 0);
i += 0x1000;
}
switch_page_directory(kernel_directory);
}
void switch_page_directory(page_directory_t *dir) {
current_directory = dir;
asm volatile("mov %0, %%cr3" :: "r" (&dir->tablesPhysical));
unsigned int cr0;
asm volatile("mov %%cr0, %0" : "=r" (cr0));
cr0 |= 0x80000000;
asm volatile("mov %0, %%cr0" :: "r" (cr0));
}
page_t *get_page(unsigned int address, int make, page_directory_t *dir) {
address /= 0x1000;
unsigned int table_idx = address / 1024;
if (dir->tables[table_idx]) {
return &dir->tables[table_idx]->pages[address % 1024];
} else if (make) {
unsigned int tmp;
dir->tables[table_idx] = (page_table_t *) malloc_ap(sizeof(page_table_t), &tmp);
memset(dir->tables[table_idx], 0, 0x1000);
dir->tablesPhysical[table_idx] = tmp | 0x7;
return &dir->tables[table_idx]->pages[address % 1024];
} else {
return 0;
}
}