726d2d23311b9698d3bf27c4e69c551aa5a860d0
[tpg/acess2.git] / mboot.c
1 /*
2  * Acess2 Kernel x86 Port
3  * - By John Hodge (thePowersGang)
4  *
5  * mboot.c
6  * - Multiboot Support
7  */
8 #define DEBUG   1
9 #include <acess.h>
10 #include <mboot.h>
11
12 // === CODE ===
13 int Multiboot_LoadMemoryMap(tMBoot_Info *MBInfo, tVAddr MapOffset, tPMemMapEnt *Map, const int MapSize, tPAddr KStart, tPAddr KEnd)
14 {
15          int    nPMemMapEnts = 0;
16         
17         ENTER("pMBInfo pMapOffset pMap iMapSize PKStart PKEnd",
18                 MBInfo, MapOffset, Map, MapSize, KStart, KEnd);
19
20         // Check that the memory map is present
21         if( MBInfo->Flags & (1 << 6) )
22         {
23                 tMBoot_MMapEnt  *ent = (void*)((tVAddr)MBInfo->MMapAddr + MapOffset);
24                 tMBoot_MMapEnt  *last = (void*)((tVAddr)ent + MBInfo->MMapLength);
25                 // Build up memory map
26                 nPMemMapEnts = 0;
27                 while( ent < last && nPMemMapEnts < MapSize )
28                 {
29                         tPMemMapEnt     *nent = &Map[nPMemMapEnts];
30                         if( !MM_GetPhysAddr(ent) )
31                                 Log_KernelPanic("MBoot", "MBoot Map entry %i addres bad (%p)",
32                                         nPMemMapEnts, ent);
33                         LOG("%llx+%llx", ent->Base, ent->Length);
34         
35                         nent->Start = ent->Base;
36                         nent->Length = ent->Length;
37                         switch(ent->Type)
38                         {
39                         case 1:
40                                 nent->Type = PMEMTYPE_FREE;
41                                 break;
42                         default:
43                                 nent->Type = PMEMTYPE_RESERVED;
44                                 break;
45                         }
46                         nent->NUMADomain = 0;
47                         
48                         nPMemMapEnts ++;
49                         ent = (void*)( (tVAddr)ent + ent->Size + 4 );
50                 }
51                 if( ent < last )
52                 {
53                         Log_Warning("MBoot", "Memory map has >%i entries, internal version is truncated",
54                                 MapSize);
55                 }
56         }
57         else if( MBInfo->Flags & (1 << 0) )
58         {
59                 Log_Warning("MBoot", "No memory map passed, using mem_lower and mem_upper");
60                 ASSERT(MapSize >= 2);
61                 nPMemMapEnts = 2;
62                 Map[0].Start = 0;
63                 Map[0].Length = MBInfo->LowMem * 1024;
64                 Map[0].Type = PMEMTYPE_FREE;
65                 Map[0].NUMADomain = 0;
66
67                 Map[1].Start = 0x100000;
68                 Map[1].Length = MBInfo->HighMem * 1024;
69                 Map[1].Type = PMEMTYPE_FREE;
70                 Map[1].NUMADomain = 0;
71         }
72         else
73         {
74                 Log_KernelPanic("MBoot", "Multiboot didn't pass memory information");
75         }
76
77         // Ensure it's valid
78         LOG("Validating");
79         nPMemMapEnts = PMemMap_ValidateMap(Map, nPMemMapEnts, MapSize);
80         // TODO: Error handling
81
82         // Replace kernel with PMEMTYPE_USED
83         LOG("Marking kernel");
84         nPMemMapEnts = PMemMap_MarkRangeUsed(
85                 Map, nPMemMapEnts, MapSize,
86                 KStart, KEnd - KStart
87                 );
88
89         LOG("Dumping");
90         PMemMap_DumpBlocks(Map, nPMemMapEnts);
91
92         // Check if boot modules were passed
93         if( MBInfo->Flags & (1 << 3) )
94         {
95                 // Replace modules with PMEMTYPE_USED
96                 nPMemMapEnts = PMemMap_MarkRangeUsed(Map, nPMemMapEnts, MapSize,
97                         MBInfo->Modules, MBInfo->ModuleCount*sizeof(tMBoot_Module)
98                         );
99                 LOG("MBInfo->Modules = %x", MBInfo->Modules);
100                 tMBoot_Module *mods = (void*)( (tVAddr)MBInfo->Modules + MapOffset);
101                 for( int i = 0; i < MBInfo->ModuleCount; i ++ )
102                 {
103                         LOG("&mods[%i] = %p", i, &mods[i]);
104                         LOG("mods[i] = {0x%x -> 0x%x}", mods[i].Start, mods[i].End);
105                         nPMemMapEnts = PMemMap_MarkRangeUsed(
106                                 Map, nPMemMapEnts, MapSize,
107                                 mods[i].Start, mods[i].End - mods[i].Start
108                                 );
109                 }
110         }
111                 
112         // Debug - Output map
113         PMemMap_DumpBlocks(Map, nPMemMapEnts);
114
115         LEAVE('i', nPMemMapEnts);
116         return nPMemMapEnts;
117 }
118
119 tBootModule *Multiboot_LoadModules(tMBoot_Info *MBInfo, tVAddr MapOffset, int *ModuleCount)
120 {
121         if( !(MBInfo->Flags & (1 << 3)) ) {
122                 *ModuleCount = 0;
123                 Log_Log("Arch", "No multiboot module information passed");
124                 return NULL;
125         }
126
127         tMBoot_Module   *mods = (void*)( MBInfo->Modules + MapOffset );
128         *ModuleCount = MBInfo->ModuleCount;
129         tBootModule *ret = malloc( MBInfo->ModuleCount * sizeof(*ret) );
130         for( int i = 0; i < MBInfo->ModuleCount; i ++ )
131         {
132                  int    ofs;
133         
134                 Log_Log("Arch", "Multiboot Module at 0x%08x, 0x%08x bytes (String at 0x%08x)",
135                         mods[i].Start, mods[i].End-mods[i].Start, mods[i].String);
136         
137                 ret[i].PBase = mods[i].Start;
138                 ret[i].Size = mods[i].End - mods[i].Start;
139         
140                 // Always HW map the module data        
141                 ofs = mods[i].Start&0xFFF;
142                 ret[i].Base = (void*)( (tVAddr)MM_MapHWPages(mods[i].Start, (ret[i].Size+ofs+0xFFF) / 0x1000)
143                         + ofs );
144                 
145                 // Assumes the string is < 4096 bytes long)
146                 ret[i].ArgString = (char*)MM_MapHWPages(mods[i].String, 2) + (mods[i].String&0xFFF);
147         }
148
149         return ret;
150 }
151
152 void Multiboot_FreeModules(const int ModuleCount, tBootModule *Modules)
153 {
154         for( int i = 0; i < ModuleCount; i ++ )
155         {
156                 Uint    ofs = Modules[i].PBase % PAGE_SIZE;
157                 Uint    nPages = (Modules[i].Size+ofs+PAGE_SIZE-1) / PAGE_SIZE;
158                 MM_UnmapHWPages(Modules[i].Base, nPages);
159                 MM_UnmapHWPages(Modules[i].ArgString, 2);
160                 
161                 // TODO: handle previous freeing of this page
162                 for( int pg = 0; pg < nPages; pg ++ )
163                         MM_DerefPhys( Modules[i].PBase + pg*PAGE_SIZE );
164         }
165         free(Modules);
166 }
167

UCC git Repository :: git.ucc.asn.au