Removed now unneeded-tracing, added hal address. We can see hal from here.
[reactos.git] / reactos / ntoskrnl / ke / freeldr.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ke/freeldr.c
5 * PURPOSE: FreeLDR Bootstrap Support
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #include <ntoskrnl.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16 /* GLOBALS *******************************************************************/
17
18 /* FreeLDR Module Data */
19 LOADER_MODULE KeLoaderModules[64];
20 ULONG KeLoaderModuleCount;
21 static CHAR KeLoaderModuleStrings[64][256];
22
23 /* FreeLDR Memory Data */
24 ADDRESS_RANGE KeMemoryMap[64];
25 ULONG KeMemoryMapRangeCount;
26 ULONG_PTR MmFreeLdrFirstKrnlPhysAddr, MmFreeLdrLastKrnlPhysAddr;
27 ULONG_PTR MmFreeLdrLastKernelAddress;
28 ULONG MmFreeLdrMemHigher;
29 ULONG MmFreeLdrPageDirectoryEnd;
30
31 /* FreeLDR Loader Data */
32 ROS_LOADER_PARAMETER_BLOCK KeRosLoaderBlock;
33 static CHAR KeLoaderCommandLine[256];
34 BOOLEAN AcpiTableDetected;
35
36 /* FreeLDR PE Hack Data */
37 extern LDR_DATA_TABLE_ENTRY HalModuleObject;
38
39 /* NT Loader Data */
40 LOADER_PARAMETER_BLOCK BldrLoaderBlock;
41 LOADER_PARAMETER_EXTENSION BldrExtensionBlock;
42 CHAR BldrCommandLine[256];
43 CHAR BldrArcBootPath[64];
44 CHAR BldrArcHalPath[64];
45 CHAR BldrNtHalPath[64];
46 CHAR BldrNtBootPath[64];
47 LDR_DATA_TABLE_ENTRY BldrModules[64];
48 MEMORY_ALLOCATION_DESCRIPTOR BldrMemoryDescriptors[64];
49 WCHAR BldrModuleStrings[64][260];
50 NLS_DATA_BLOCK BldrNlsDataBlock;
51 SETUP_LOADER_BLOCK BldrSetupBlock;
52 struct _boot_infos_t *BootInfo;
53
54 #ifdef _M_PPC
55 #include "font.h"
56 boot_infos_t PpcEarlybootInfo;
57 #endif
58
59 #define KSEG0_BASE 0x80000000
60
61 /* FUNCTIONS *****************************************************************/
62
63 VOID
64 NTAPI
65 KiRosFrldrLpbToNtLpb(IN PROS_LOADER_PARAMETER_BLOCK RosLoaderBlock,
66 IN PLOADER_PARAMETER_BLOCK *NtLoaderBlock)
67 {
68 PLOADER_PARAMETER_BLOCK LoaderBlock;
69 PLDR_DATA_TABLE_ENTRY LdrEntry;
70 PMEMORY_ALLOCATION_DESCRIPTOR MdEntry;
71 PLOADER_MODULE RosEntry;
72 ULONG i, j, ModSize;
73 PVOID ModStart;
74 PCHAR DriverName;
75 PCHAR BootPath, HalPath;
76 CHAR CommandLine[256];
77
78 /* First get some kernel-loader globals */
79 AcpiTableDetected = (RosLoaderBlock->Flags & MB_FLAGS_ACPI_TABLE) ? TRUE : FALSE;
80 MmFreeLdrMemHigher = RosLoaderBlock->MemHigher;
81 MmFreeLdrPageDirectoryEnd = RosLoaderBlock->PageDirectoryEnd;
82 KeLoaderModuleCount = RosLoaderBlock->ModsCount;
83
84 /* Set the NT Loader block and initialize it */
85 *NtLoaderBlock = LoaderBlock = &BldrLoaderBlock;
86 RtlZeroMemory(LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
87
88 /* Set the NLS Data block */
89 LoaderBlock->NlsData = &BldrNlsDataBlock;
90
91 /* Assume this is from FreeLDR's SetupLdr */
92 LoaderBlock->SetupLdrBlock = &BldrSetupBlock;
93
94 /* Setup the list heads */
95 InitializeListHead(&LoaderBlock->LoadOrderListHead);
96 InitializeListHead(&LoaderBlock->MemoryDescriptorListHead);
97 InitializeListHead(&LoaderBlock->BootDriverListHead);
98
99 /* Loop boot driver list */
100 for (i = 0; i < KeLoaderModuleCount; i++)
101 {
102 /* Get the ROS loader entry */
103 RosEntry = &KeLoaderModules[i];
104 DriverName = (PCHAR)RosEntry->String;
105 ModStart = (PVOID)RosEntry->ModStart;
106 ModSize = RosEntry->ModEnd - (ULONG_PTR)ModStart;
107
108 /* Check if this is any of the NLS files */
109 if (!_stricmp(DriverName, "ansi.nls"))
110 {
111 /* ANSI Code page */
112 LoaderBlock->NlsData->AnsiCodePageData = ModStart;
113
114 /* Create an MD for it */
115 MdEntry = &BldrMemoryDescriptors[i];
116 MdEntry->MemoryType = LoaderNlsData;
117 MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
118 MdEntry->PageCount = ModSize >> PAGE_SHIFT;
119 InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
120 &MdEntry->ListEntry);
121 continue;
122 }
123 else if (!_stricmp(DriverName, "oem.nls"))
124 {
125 /* OEM Code page */
126 LoaderBlock->NlsData->OemCodePageData = ModStart;
127
128 /* Create an MD for it */
129 MdEntry = &BldrMemoryDescriptors[i];
130 MdEntry->MemoryType = LoaderNlsData;
131 MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
132 MdEntry->PageCount = ModSize >> PAGE_SHIFT;
133 InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
134 &MdEntry->ListEntry);
135 continue;
136 }
137 else if (!_stricmp(DriverName, "casemap.nls"))
138 {
139 /* Unicode Code page */
140 LoaderBlock->NlsData->UnicodeCodePageData = ModStart;
141
142 /* Create an MD for it */
143 MdEntry = &BldrMemoryDescriptors[i];
144 MdEntry->MemoryType = LoaderNlsData;
145 MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
146 MdEntry->PageCount = ModSize >> PAGE_SHIFT;
147 InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
148 &MdEntry->ListEntry);
149 continue;
150 }
151
152 /* Check if this is the SYSTEM hive */
153 if (!(_stricmp(DriverName, "system")) ||
154 !(_stricmp(DriverName, "system.hiv")))
155 {
156 /* Save registry data */
157 LoaderBlock->RegistryBase = ModStart;
158 LoaderBlock->RegistryLength = ModSize;
159
160 /* Disable setup mode */
161 LoaderBlock->SetupLdrBlock = NULL;
162
163 /* Create an MD for it */
164 MdEntry = &BldrMemoryDescriptors[i];
165 MdEntry->MemoryType = LoaderRegistryData;
166 MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
167 MdEntry->PageCount = ModSize >> PAGE_SHIFT;
168 InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
169 &MdEntry->ListEntry);
170 continue;
171 }
172
173 /* Check if this is the HARDWARE hive */
174 if (!(_stricmp(DriverName, "hardware")) ||
175 !(_stricmp(DriverName, "hardware.hiv")))
176 {
177 /* Create an MD for it */
178 MdEntry = &BldrMemoryDescriptors[i];
179 MdEntry->MemoryType = LoaderRegistryData;
180 MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
181 MdEntry->PageCount = ModSize >> PAGE_SHIFT;
182 InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
183 &MdEntry->ListEntry);
184 continue;
185 }
186
187 /* Setup the loader entry */
188 LdrEntry = &BldrModules[i];
189 RtlZeroMemory(LdrEntry, sizeof(LDR_DATA_TABLE_ENTRY));
190
191 /* Convert driver name from ANSI to Unicode */
192 for (j = 0; j < strlen(DriverName); j++)
193 {
194 BldrModuleStrings[i][j] = DriverName[j];
195 }
196
197 /* Setup driver name */
198 RtlInitUnicodeString(&LdrEntry->BaseDllName, BldrModuleStrings[i]);
199 RtlInitUnicodeString(&LdrEntry->FullDllName, BldrModuleStrings[i]);
200
201 /* Copy data from Freeldr Module Entry */
202 LdrEntry->DllBase = ModStart;
203 LdrEntry->SizeOfImage = ModSize;
204
205 /* Initialize other data */
206 LdrEntry->LoadCount = 1;
207 LdrEntry->Flags = LDRP_IMAGE_DLL |
208 LDRP_ENTRY_PROCESSED;
209 if (RosEntry->Reserved) LdrEntry->Flags |= LDRP_ENTRY_INSERTED;
210
211 /* Insert it into the loader block */
212 InsertTailList(&LoaderBlock->LoadOrderListHead,
213 &LdrEntry->InLoadOrderLinks);
214
215 /* Check if this is the kernel */
216 if (!(_stricmp(DriverName, "ntoskrnl.exe")))
217 {
218 /* Create an MD for it */
219 MdEntry = &BldrMemoryDescriptors[i];
220 MdEntry->MemoryType = LoaderSystemCode;
221 MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
222 MdEntry->PageCount = ModSize >> PAGE_SHIFT;
223 InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
224 &MdEntry->ListEntry);
225 }
226 else if (!(_stricmp(DriverName, "hal.dll")))
227 {
228 /* The HAL actually gets loaded somewhere else */
229 ModStart = HalModuleObject.DllBase;
230
231 /* Create an MD for the HAL */
232 MdEntry = &BldrMemoryDescriptors[i];
233 MdEntry->MemoryType = LoaderHalCode;
234 MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
235 MdEntry->PageCount = ModSize >> PAGE_SHIFT;
236 InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
237 &MdEntry->ListEntry);
238 }
239 else
240 {
241 /* Create an MD for any driver */
242 MdEntry = &BldrMemoryDescriptors[i];
243 MdEntry->MemoryType = LoaderBootDriver;
244 MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
245 MdEntry->PageCount = ModSize >> PAGE_SHIFT;
246 InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
247 &MdEntry->ListEntry);
248 }
249 }
250
251 /* Setup command line */
252 LoaderBlock->LoadOptions = BldrCommandLine;
253 strcpy(BldrCommandLine, KeLoaderCommandLine);
254
255 /* Setup the extension block */
256 LoaderBlock->Extension = &BldrExtensionBlock;
257 LoaderBlock->Extension->Size = sizeof(LOADER_PARAMETER_EXTENSION);
258 LoaderBlock->Extension->MajorVersion = 5;
259 LoaderBlock->Extension->MinorVersion = 2;
260
261 /* Now setup the setup block if we have one */
262 if (LoaderBlock->SetupLdrBlock)
263 {
264 /* All we'll setup right now is the flag for text-mode setup */
265 LoaderBlock->SetupLdrBlock->Flags = 1;
266 }
267
268 /* Make a copy of the command line */
269 strcpy(CommandLine, LoaderBlock->LoadOptions);
270
271 /* Find the first \, separating the ARC path from NT path */
272 BootPath = strchr(CommandLine, '\\');
273 *BootPath = ANSI_NULL;
274 strncpy(BldrArcBootPath, CommandLine, 63);
275 LoaderBlock->ArcBootDeviceName = BldrArcBootPath;
276
277 /* The rest of the string is the NT path */
278 HalPath = strchr(BootPath + 1, ' ');
279 *HalPath = ANSI_NULL;
280 BldrNtBootPath[0] = '\\';
281 strncat(BldrNtBootPath, BootPath + 1, 63);
282 strcat(BldrNtBootPath,"\\");
283 LoaderBlock->NtBootPathName = BldrNtBootPath;
284
285 /* Set the HAL paths */
286 strncpy(BldrArcHalPath, BldrArcBootPath, 63);
287 LoaderBlock->ArcHalDeviceName = BldrArcHalPath;
288 strcpy(BldrNtHalPath, "\\");
289 LoaderBlock->NtHalPathName = BldrNtHalPath;
290
291 /* Use this new command line */
292 strncpy(LoaderBlock->LoadOptions, HalPath + 2, 255);
293
294 /* Parse it and change every slash to a space */
295 BootPath = LoaderBlock->LoadOptions;
296 do {if (*BootPath == '/') *BootPath = ' ';} while (*BootPath++);
297 }
298
299 VOID
300 FASTCALL
301 KiRosPrepareForSystemStartup(IN ULONG Dummy,
302 IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock)
303 {
304 ULONG i;
305 ULONG size;
306 ULONG StartKernelBase;
307 ULONG HalBase;
308 ULONG DriverBase;
309 ULONG DriverSize;
310 PLOADER_PARAMETER_BLOCK NtLoaderBlock;
311 CHAR* s;
312 #ifdef _M_IX86
313 PKTSS Tss;
314 PKGDTENTRY TssEntry;
315 #endif
316 #ifdef _M_PPC
317 {
318 __asm__("ori 0,0,0");
319 char *nk = "ntoskrnl is here";
320 boot_infos_t *XBootInfo = (boot_infos_t *)LoaderBlock->ArchExtra;
321 memcpy(&PpcEarlybootInfo, XBootInfo, sizeof(PpcEarlybootInfo));
322 PpcEarlybootInfo.dispFont = BootDigits;
323 BootInfo = (struct _boot_infos_t *)&PpcEarlybootInfo;
324 DrawNumber(BootInfo, 0x1234abcd, 10, 100);
325 DrawNumber(BootInfo, (ULONG)nk, 10 , 150);
326 DrawString(BootInfo, nk, 100, 150);
327 __asm__("ori 0,0,0");
328 }
329 #endif
330
331 #ifdef _M_IX86
332 /* Load the GDT and IDT */
333 Ke386SetGlobalDescriptorTable(KiGdtDescriptor);
334 Ke386SetInterruptDescriptorTable(KiIdtDescriptor);
335
336 /* Initialize the boot TSS */
337 Tss = &KiBootTss;
338 TssEntry = &KiBootGdt[KGDT_TSS / sizeof(KGDTENTRY)];
339 TssEntry->HighWord.Bits.Type = I386_TSS;
340 TssEntry->HighWord.Bits.Pres = 1;
341 TssEntry->HighWord.Bits.Dpl = 0;
342 TssEntry->BaseLow = (USHORT)((ULONG_PTR)Tss & 0xFFFF);
343 TssEntry->HighWord.Bytes.BaseMid = (UCHAR)((ULONG_PTR)Tss >> 16);
344 TssEntry->HighWord.Bytes.BaseHi = (UCHAR)((ULONG_PTR)Tss >> 24);
345 #endif
346
347 DrawNumber(BootInfo, 0xb0071f03, 190, 90);
348 DrawNumber(BootInfo, (ULONG)BootInfo, 190, 100);
349
350 /* Copy the Loader Block Data locally since Low-Memory will be wiped */
351 memcpy(&KeRosLoaderBlock, LoaderBlock, sizeof(ROS_LOADER_PARAMETER_BLOCK));
352 memcpy(&KeLoaderModules[0],
353 (PVOID)KeRosLoaderBlock.ModsAddr,
354 sizeof(LOADER_MODULE) * KeRosLoaderBlock.ModsCount);
355 KeRosLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules;
356
357 /* Check for BIOS memory map */
358 KeMemoryMapRangeCount = 0;
359 if (KeRosLoaderBlock.Flags & MB_FLAGS_MMAP_INFO)
360 {
361 /* We have a memory map from the nice BIOS */
362 size = *((PULONG)(KeRosLoaderBlock.MmapAddr - sizeof(ULONG)));
363 i = 0;
364
365 /* Map it until we run out of size */
366 while (i < KeRosLoaderBlock.MmapLength)
367 {
368 /* Copy into the Kernel Memory Map */
369 memcpy (&KeMemoryMap[KeMemoryMapRangeCount],
370 (PVOID)(KeRosLoaderBlock.MmapAddr + i),
371 sizeof(ADDRESS_RANGE));
372
373 /* Increase Memory Map Count */
374 KeMemoryMapRangeCount++;
375
376 /* Increase Size */
377 i += size;
378 }
379
380 /* Save data */
381 KeRosLoaderBlock.MmapLength = KeMemoryMapRangeCount *
382 sizeof(ADDRESS_RANGE);
383 KeRosLoaderBlock.MmapAddr = (ULONG)KeMemoryMap;
384 }
385 else
386 {
387 /* Nothing from BIOS */
388 KeRosLoaderBlock.MmapLength = 0;
389 KeRosLoaderBlock.MmapAddr = (ULONG)KeMemoryMap;
390 }
391
392 /* Save the Base Address */
393 MmSystemRangeStart = (PVOID)KeRosLoaderBlock.KernelBase;
394
395 /* Set the Command Line */
396 strcpy(KeLoaderCommandLine, (PCHAR)LoaderBlock->CommandLine);
397 KeRosLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine;
398
399 /* Get the address of ntoskrnl in openfirmware memory */
400 StartKernelBase = KeLoaderModules[0].ModStart;
401
402 /* Create a block for each module */
403 for (i = 0; i < KeRosLoaderBlock.ModsCount; i++)
404 {
405 /* Check if we have to copy the path or not */
406 if ((s = strrchr((PCHAR)KeLoaderModules[i].String, '/')) != 0)
407 {
408 strcpy(KeLoaderModuleStrings[i], s + 1);
409 }
410 else
411 {
412 strcpy(KeLoaderModuleStrings[i], (PCHAR)KeLoaderModules[i].String);
413 }
414
415 #ifdef _M_PPC
416 if(i == 0) {
417 DrawNumber(BootInfo, KeLoaderModules[i].ModStart, 10, 200);
418 DrawNumber(BootInfo, KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart, 100, 200);
419 DrawNumber(BootInfo, KeLoaderModules[i].ModEnd, 190, 200);
420 DrawNumber(BootInfo, KeLoaderModules[i+1].ModStart, 10, 210);
421 DrawNumber(BootInfo, KeLoaderModules[i+1].ModEnd - KeLoaderModules[i+1].ModStart, 100, 210);
422 DrawNumber(BootInfo, KeLoaderModules[i+1].ModEnd, 190, 210);
423 }
424 KeLoaderModules[i].ModStart += KSEG0_BASE - StartKernelBase;
425 KeLoaderModules[i].ModEnd += KSEG0_BASE - StartKernelBase;
426 #else
427 /* Substract the base Address in Physical Memory */
428 KeLoaderModules[i].ModStart -= 0x200000;
429
430 /* Add the Kernel Base Address in Virtual Memory */
431 KeLoaderModules[i].ModStart += KSEG0_BASE;
432
433 /* Substract the base Address in Physical Memory */
434 KeLoaderModules[i].ModEnd -= 0x200000;
435
436 /* Add the Kernel Base Address in Virtual Memory */
437 KeLoaderModules[i].ModEnd += KSEG0_BASE;
438 #endif
439
440 /* Select the proper String */
441 KeLoaderModules[i].String = (ULONG)KeLoaderModuleStrings[i];
442 }
443
444 /* Choose last module address as the final kernel address */
445 MmFreeLdrLastKernelAddress =
446 PAGE_ROUND_UP(KeLoaderModules[KeRosLoaderBlock.ModsCount - 1].ModEnd);
447
448 #ifndef _M_PPC
449 /* Select the HAL Base */
450 HalBase = KeLoaderModules[1].ModStart;
451
452 /* Choose Driver Base */
453 DriverBase = MmFreeLdrLastKernelAddress;
454 LdrHalBase = (ULONG_PTR)DriverBase;
455 #else
456 HalBase = KeLoaderModules[1].ModStart;
457 DriverBase = MmFreeLdrLastKernelAddress;
458 LdrHalBase = KeLoaderModules[1].ModStart;
459 #endif
460
461 /* Initialize Module Management */
462 LdrInitModuleManagement((PVOID)KeLoaderModules[0].ModStart);
463
464 /* Load HAL.DLL with the PE Loader */
465 LdrSafePEProcessModule((PVOID)HalBase,
466 (PVOID)DriverBase,
467 (PVOID)KeLoaderModules[0].ModStart,
468 &DriverSize);
469
470 //
471 //
472 // HACK HACK HACK WHEN WILL YOU PEOPLE FIX FREELDR?!?!?!
473 // FREELDR SENDS US AN ***INVALID*** HAL PE HEADER!!!
474 // WE READ IT IN LdrInitModuleManagement ABOVE!!!
475 // WE SET .SizeOfImage TO A *GARBAGE* VALUE!!!
476 //
477 // This dirty hack fixes it, and should make symbol lookup work too.
478 //
479 HalModuleObject.SizeOfImage = RtlImageNtHeader((PVOID)HalModuleObject.
480 DllBase)->
481 OptionalHeader.SizeOfImage;
482
483 /* Increase the last kernel address with the size of HAL */
484 MmFreeLdrLastKernelAddress += PAGE_ROUND_UP(DriverSize);
485
486 #ifdef _M_IX86
487 /* Now select the final beginning and ending Kernel Addresses */
488 MmFreeLdrFirstKrnlPhysAddr = KeLoaderModules[0].ModStart -
489 KSEG0_BASE + 0x200000;
490 MmFreeLdrLastKrnlPhysAddr = MmFreeLdrLastKernelAddress -
491 KSEG0_BASE + 0x200000;
492 #endif
493
494 /* Setup the IDT */
495 KeInitExceptions(); // ONCE HACK BELOW IS GONE, MOVE TO KISYSTEMSTARTUP!
496 KeInitInterrupts(); // ROS HACK DEPRECATED SOON BY NEW HAL
497
498 /* Load the Kernel with the PE Loader */
499 LdrSafePEProcessModule((PVOID)KeLoaderModules[0].ModStart,
500 (PVOID)KeLoaderModules[0].ModStart,
501 (PVOID)DriverBase,
502 &DriverSize);
503
504 /* Sets up the VDM Data */
505 #ifdef _M_IX86
506 NtEarlyInitVdm();
507 #endif
508
509 /* Convert the loader block */
510 KiRosFrldrLpbToNtLpb(&KeRosLoaderBlock, &NtLoaderBlock);
511
512 /* Do general System Startup */
513 KiSystemStartup(NtLoaderBlock);
514 }
515
516 /* EOF */