Basic Paging for Long Mode setup

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
BringerOfShadows
Posts: 15
Joined: Thu Nov 08, 2012 2:59 am

Basic Paging for Long Mode setup

Post by BringerOfShadows »

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.

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.

}


Link to most recent Version: MemStart.c
Post Reply