paging - grub error [SOLVED]

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
jocke
Posts: 6
Joined: Wed May 02, 2007 5:48 am

paging - grub error [SOLVED]

Post by jocke »

Hi,

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;
	}
}
anyone knows what the problem is?
Last edited by jocke on Sun Jun 15, 2008 12:32 pm, edited 1 time in total.
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

You're probably not linking your boot.s file first, so when you add the paging code the multiboot header gets pushed over the 4KB boundary and GRUB never finds it.

Make sure boot.s is first on your linker line.
jocke
Posts: 6
Joined: Wed May 02, 2007 5:48 am

Post by jocke »

thanks, that works :P
Post Reply