Basic Paging for Long Mode setup
Posted: Sat Dec 03, 2016 3:51 pm
I am writing a set of functions to implement a preliminary paging table to shift into long mode. Right now I think I have it set up to map the first 14MB of memory, and a way to reliably get the memory map. I am hoping that someone can point out errors or give suggestions on how to improve my code. I will also be posting updates to the file as I work out how to map the rest of memory.
Link to most recent Version: MemStart.c
Code: Select all
#include <multiboot2.h>
#include <stdarg.h>
// Using Multiboot 2
#define SPACE_GIGABYTE 0x40000000 // 1 Gigabyte
#define SPACE_MEGABYTE 0x00200000 // 2 Megabytes
#define SPACE_KILOBYTE 0x00001000 // 4 Kilobytes
#define TABLE 0x8 // size in bytes of a paging table entry
uint64_t *PML4[512] = 0x8000;
uint64_t *PDP[512] = 0x9000;
uint64_t *PD[512][512] = 0xA000;
uint64_t *PT = 0x4A000;
uint64_t* memStart(uint64_t addr)
{
struct multiboot_tag* tag;
struct multiboot_memory_map_t *mmap;
uint64_t mmap_len;
uint64_t entry_size;
tag = (struct multiboot_tag *)addr + 8;
while(tag->type != MULTIBOOT_TAG_TYPE_END)
{
if(tag->type == MULTIBOOT_TAG_TYPE_MMAP)
{
mmap = ((multiboot_tag_mmap *)tag)->entries; // set mmap to location of Memory map
mmap_len = tag + tag->size; // get length of the memory map
entry_size = ((multiboot_tag_mmap *)tag)->entry_size; // get size of the memory map entries.
}
}
uint32_t entries;
entries = GetEntries(*mmap, mmap_len, entry_size);
multiboot_memory_map_t memMap[entries];
multiboot_memory_map_t *memMapP = &memMap;
fillMemMap(*mmap, mmap_len, entry_size, *memMapP);
sortMemMap(*memMapP, entries);
fillPageTables(*memMapP, entries);
return *PML4;
}
void fillMemMap(multiboot_memory_map_t *mmap, uint64_t mmap_len,
uint64_t entry_size, multiboot_memory_map_t *memMapP)
{
for(entries=0;mmap < (mmap + mmap_len);
mmap = (multiboot_memory_map_t *)
((uint64_t) mmap
+ (entry_size))
{
entries++;
memMapP->addr = mmap->addr;
memMapP->len = mmap->len;
memMapP->type = mmap->type;
memMapP++;
}
}
uint32_t GetEntries(multiboot_memory_map_t *mmap, uint64_t mmap_len, uint64_t entry_size)
{
uint32_t entries;
for(entries=0;mmap < (mmap + mmap_len);
mmap = (multiboot_memory_map_t *)
((uint64_t) mmap
+ (entry_size))
{
entries++;
}
return entries;
}
void sortMemMap(multiboot_memory_map_t *memMapP, uint32_t entries)
{
multiboot_memory_map_t swap, *Start;
Start = memMapP;
for(int i=0;i<entries;i++)
{
for(int j;j<entries-i;j++)
{
if(memMapP->addr > ((memMapP+1)->addr)
{
swap = *memMapP;
*memMapP = *(memMapP+1);
*(memMapP+1) = swap;
}
memMapP++;
}
memMapP = Start;
}
}
void fillPageTables(multiboot_memory_map_t *memMapP, uint32_t entries)
{
// point first entry of PML4 to Page Directory Pointers and initiallize the first 14 MB
*PML4[0] = PDP + 0x7; // 0x7 User, Write, Present
uint64_t addr = 0x00000;
uint64_t size = 0;
// map first 14 MB as 2MB Pages
*PDP[0] = PD + 0x07;
for(int i=0; i<7; i++)
{
*PD[0][i] = addr + 0x83;
addr += 0x200000;
}
// first 14 MB mapped as 0x0000000000000000 - 0x0000000000E00000
// TODO: after setting up paging, remap page table locations to higher memory.
}