- KdDebuggerNotPresent should be FALSE by default.
[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 #define NDEBUG
13 #include <debug.h>
14
15 /* GLOBALS *******************************************************************/
16
17 /* FreeLDR Memory Data */
18 ULONG_PTR MmFreeLdrFirstKrnlPhysAddr, MmFreeLdrLastKrnlPhysAddr;
19 ULONG_PTR MmFreeLdrLastKernelAddress;
20 ULONG MmFreeLdrMemHigher;
21 ULONG MmFreeLdrPageDirectoryEnd;
22
23 /* FreeLDR Loader Data */
24 PROS_LOADER_PARAMETER_BLOCK KeRosLoaderBlock;
25 BOOLEAN AcpiTableDetected;
26
27 /* NT Loader Data. Eats up about 50KB! */
28 LOADER_PARAMETER_BLOCK BldrLoaderBlock; // 0x0000
29 LOADER_PARAMETER_EXTENSION BldrExtensionBlock; // 0x0060
30 CHAR BldrCommandLine[256]; // 0x00DC
31 CHAR BldrArcBootPath[64]; // 0x01DC
32 CHAR BldrArcHalPath[64]; // 0x021C
33 CHAR BldrNtHalPath[64]; // 0x025C
34 CHAR BldrNtBootPath[64]; // 0x029C
35 LDR_DATA_TABLE_ENTRY BldrModules[64]; // 0x02DC
36 MEMORY_ALLOCATION_DESCRIPTOR BldrMemoryDescriptors[64]; // 0x14DC
37 WCHAR BldrModuleStrings[64][260]; // 0x19DC
38 NLS_DATA_BLOCK BldrNlsDataBlock; // 0x9BDC
39 SETUP_LOADER_BLOCK BldrSetupBlock; // 0x9BE8
40 ARC_DISK_INFORMATION BldrArcDiskInfo; // 0x9F34
41 CHAR BldrArcNames[32][256]; // 0x9F3C
42 ARC_DISK_SIGNATURE BldrDiskInfo[32]; // 0xBF3C
43 // 0xC23C
44
45 /* FUNCTIONS *****************************************************************/
46
47 VOID
48 NTAPI
49 KiRosFrldrLpbToNtLpb(IN PROS_LOADER_PARAMETER_BLOCK RosLoaderBlock,
50 IN PLOADER_PARAMETER_BLOCK *NtLoaderBlock)
51 {
52 PLOADER_PARAMETER_BLOCK LoaderBlock;
53 PLDR_DATA_TABLE_ENTRY LdrEntry;
54 PMEMORY_ALLOCATION_DESCRIPTOR MdEntry;
55 PLOADER_MODULE RosEntry;
56 ULONG i, j, ModSize;
57 PVOID ModStart;
58 PCHAR DriverName;
59 PCHAR BootPath, HalPath;
60 CHAR CommandLine[256];
61 PARC_DISK_SIGNATURE RosDiskInfo, ArcDiskInfo;
62 PIMAGE_NT_HEADERS NtHeader;
63
64 /* First get some kernel-loader globals */
65 AcpiTableDetected = (RosLoaderBlock->Flags & MB_FLAGS_ACPI_TABLE) ? TRUE : FALSE;
66 MmFreeLdrMemHigher = RosLoaderBlock->MemHigher;
67 MmFreeLdrPageDirectoryEnd = RosLoaderBlock->PageDirectoryEnd;
68
69 /* Set the NT Loader block and initialize it */
70 *NtLoaderBlock = LoaderBlock = &BldrLoaderBlock;
71 RtlZeroMemory(LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
72
73 /* Set the NLS Data block */
74 LoaderBlock->NlsData = &BldrNlsDataBlock;
75
76 /* Set the ARC Data block */
77 LoaderBlock->ArcDiskInformation = &BldrArcDiskInfo;
78
79 /* Assume this is from FreeLDR's SetupLdr */
80 LoaderBlock->SetupLdrBlock = &BldrSetupBlock;
81
82 /* Setup the list heads */
83 InitializeListHead(&LoaderBlock->LoadOrderListHead);
84 InitializeListHead(&LoaderBlock->MemoryDescriptorListHead);
85 InitializeListHead(&LoaderBlock->BootDriverListHead);
86 InitializeListHead(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead);
87
88 /* Loop boot driver list */
89 for (i = 0; i < RosLoaderBlock->ModsCount; i++)
90 {
91 /* Get the ROS loader entry */
92 RosEntry = &RosLoaderBlock->ModsAddr[i];
93 DriverName = (PCHAR)RosEntry->String;
94 ModStart = (PVOID)RosEntry->ModStart;
95 ModSize = RosEntry->ModEnd - (ULONG_PTR)ModStart;
96
97 /* Check if this is any of the NLS files */
98 if (!_stricmp(DriverName, "ansi.nls"))
99 {
100 /* ANSI Code page */
101 LoaderBlock->NlsData->AnsiCodePageData = ModStart;
102
103 /* Create an MD for it */
104 MdEntry = &BldrMemoryDescriptors[i];
105 MdEntry->MemoryType = LoaderNlsData;
106 MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
107 MdEntry->PageCount = ModSize >> PAGE_SHIFT;
108 InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
109 &MdEntry->ListEntry);
110 continue;
111 }
112 else if (!_stricmp(DriverName, "oem.nls"))
113 {
114 /* OEM Code page */
115 LoaderBlock->NlsData->OemCodePageData = ModStart;
116
117 /* Create an MD for it */
118 MdEntry = &BldrMemoryDescriptors[i];
119 MdEntry->MemoryType = LoaderNlsData;
120 MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
121 MdEntry->PageCount = ModSize >> PAGE_SHIFT;
122 InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
123 &MdEntry->ListEntry);
124 continue;
125 }
126 else if (!_stricmp(DriverName, "casemap.nls"))
127 {
128 /* Unicode Code page */
129 LoaderBlock->NlsData->UnicodeCodePageData = ModStart;
130
131 /* Create an MD for it */
132 MdEntry = &BldrMemoryDescriptors[i];
133 MdEntry->MemoryType = LoaderNlsData;
134 MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
135 MdEntry->PageCount = ModSize >> PAGE_SHIFT;
136 InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
137 &MdEntry->ListEntry);
138 continue;
139 }
140
141 /* Check if this is the SYSTEM hive */
142 if (!(_stricmp(DriverName, "system")) ||
143 !(_stricmp(DriverName, "system.hiv")))
144 {
145 /* Save registry data */
146 LoaderBlock->RegistryBase = ModStart;
147 LoaderBlock->RegistryLength = ModSize;
148
149 /* Disable setup mode */
150 LoaderBlock->SetupLdrBlock = NULL;
151
152 /* Create an MD for it */
153 MdEntry = &BldrMemoryDescriptors[i];
154 MdEntry->MemoryType = LoaderRegistryData;
155 MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
156 MdEntry->PageCount = ModSize >> PAGE_SHIFT;
157 InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
158 &MdEntry->ListEntry);
159 continue;
160 }
161
162 /* Check if this is the HARDWARE hive */
163 if (!(_stricmp(DriverName, "hardware")) ||
164 !(_stricmp(DriverName, "hardware.hiv")))
165 {
166 /* Create an MD for it */
167 MdEntry = &BldrMemoryDescriptors[i];
168 MdEntry->MemoryType = LoaderRegistryData;
169 MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
170 MdEntry->PageCount = ModSize >> PAGE_SHIFT;
171 InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
172 &MdEntry->ListEntry);
173 continue;
174 }
175
176 /* Check if this is the kernel */
177 if (!(_stricmp(DriverName, "ntoskrnl.exe")))
178 {
179 /* Create an MD for it */
180 MdEntry = &BldrMemoryDescriptors[i];
181 MdEntry->MemoryType = LoaderSystemCode;
182 MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
183 MdEntry->PageCount = ModSize >> PAGE_SHIFT;
184 InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
185 &MdEntry->ListEntry);
186 }
187 else if (!(_stricmp(DriverName, "hal.dll")))
188 {
189 /* Create an MD for the HAL */
190 MdEntry = &BldrMemoryDescriptors[i];
191 MdEntry->MemoryType = LoaderHalCode;
192 MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
193 MdEntry->PageCount = ModSize >> PAGE_SHIFT;
194 InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
195 &MdEntry->ListEntry);
196 }
197 else
198 {
199 /* Create an MD for any driver */
200 MdEntry = &BldrMemoryDescriptors[i];
201 MdEntry->MemoryType = LoaderBootDriver;
202 MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
203 MdEntry->PageCount = ModSize >> PAGE_SHIFT;
204 InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
205 &MdEntry->ListEntry);
206 }
207
208 /* Setup the loader entry */
209 LdrEntry = &BldrModules[i];
210 RtlZeroMemory(LdrEntry, sizeof(LDR_DATA_TABLE_ENTRY));
211
212 /* Convert driver name from ANSI to Unicode */
213 for (j = 0; j < strlen(DriverName); j++)
214 {
215 BldrModuleStrings[i][j] = DriverName[j];
216 }
217
218 /* Setup driver name */
219 RtlInitUnicodeString(&LdrEntry->BaseDllName, BldrModuleStrings[i]);
220 RtlInitUnicodeString(&LdrEntry->FullDllName, BldrModuleStrings[i]);
221
222 /* Copy data from Freeldr Module Entry */
223 LdrEntry->DllBase = ModStart;
224 LdrEntry->SizeOfImage = ModSize;
225
226 /* Copy additional data */
227 NtHeader = RtlImageNtHeader(ModStart);
228 LdrEntry->EntryPoint = RVA(ModStart,
229 NtHeader->
230 OptionalHeader.AddressOfEntryPoint);
231
232 /* Initialize other data */
233 LdrEntry->LoadCount = 1;
234 LdrEntry->Flags = LDRP_IMAGE_DLL |
235 LDRP_ENTRY_PROCESSED;
236 if (RosEntry->Reserved) LdrEntry->Flags |= LDRP_ENTRY_INSERTED;
237
238 /* Insert it into the loader block */
239 InsertTailList(&LoaderBlock->LoadOrderListHead,
240 &LdrEntry->InLoadOrderLinks);
241 }
242
243 /* Setup command line */
244 LoaderBlock->LoadOptions = BldrCommandLine;
245 strcpy(BldrCommandLine, RosLoaderBlock->CommandLine);
246
247 /* Setup the extension block */
248 LoaderBlock->Extension = &BldrExtensionBlock;
249 LoaderBlock->Extension->Size = sizeof(LOADER_PARAMETER_EXTENSION);
250 LoaderBlock->Extension->MajorVersion = 5;
251 LoaderBlock->Extension->MinorVersion = 2;
252
253 /* Now setup the setup block if we have one */
254 if (LoaderBlock->SetupLdrBlock)
255 {
256 /* All we'll setup right now is the flag for text-mode setup */
257 LoaderBlock->SetupLdrBlock->Flags = 1;
258 }
259
260 /* Make a copy of the command line */
261 strcpy(CommandLine, LoaderBlock->LoadOptions);
262
263 /* Find the first \, separating the ARC path from NT path */
264 BootPath = strchr(CommandLine, '\\');
265 *BootPath = ANSI_NULL;
266 strncpy(BldrArcBootPath, CommandLine, 63);
267 LoaderBlock->ArcBootDeviceName = BldrArcBootPath;
268
269 /* The rest of the string is the NT path */
270 HalPath = strchr(BootPath + 1, ' ');
271 *HalPath = ANSI_NULL;
272 BldrNtBootPath[0] = '\\';
273 strncat(BldrNtBootPath, BootPath + 1, 63);
274 strcat(BldrNtBootPath,"\\");
275 LoaderBlock->NtBootPathName = BldrNtBootPath;
276
277 /* Set the HAL paths */
278 strncpy(BldrArcHalPath, BldrArcBootPath, 63);
279 LoaderBlock->ArcHalDeviceName = BldrArcHalPath;
280 strcpy(BldrNtHalPath, "\\");
281 LoaderBlock->NtHalPathName = BldrNtHalPath;
282
283 /* Use this new command line */
284 strncpy(LoaderBlock->LoadOptions, HalPath + 2, 255);
285
286 /* Parse it and change every slash to a space */
287 BootPath = LoaderBlock->LoadOptions;
288 do {if (*BootPath == '/') *BootPath = ' ';} while (*BootPath++);
289
290 /* Now let's loop ARC disk information */
291 for (i = 0; i < RosLoaderBlock->DrivesCount; i++)
292 {
293 /* Get the ROS loader entry */
294 RosDiskInfo = &RosLoaderBlock->DrivesAddr[i];
295
296 /* Get the ARC structure */
297 ArcDiskInfo = &BldrDiskInfo[i];
298
299 /* Copy the data over */
300 ArcDiskInfo->Signature = RosDiskInfo->Signature;
301 ArcDiskInfo->CheckSum = RosDiskInfo->CheckSum;
302
303 /* Copy the ARC Name */
304 strcpy(BldrArcNames[i], RosDiskInfo->ArcName);
305 ArcDiskInfo->ArcName = BldrArcNames[i];
306
307 /* Insert into the list */
308 InsertTailList(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead,
309 &ArcDiskInfo->ListEntry);
310 }
311 }
312
313 VOID
314 FASTCALL
315 KiRosPrepareForSystemStartup(IN ULONG Dummy,
316 IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock)
317 {
318 ULONG i;
319 PLOADER_PARAMETER_BLOCK NtLoaderBlock;
320 PKTSS Tss;
321 PKGDTENTRY TssEntry;
322
323 /* Load the GDT and IDT */
324 Ke386SetGlobalDescriptorTable(KiGdtDescriptor);
325 Ke386SetInterruptDescriptorTable(KiIdtDescriptor);
326
327 /* Initialize the boot TSS */
328 Tss = &KiBootTss;
329 TssEntry = &KiBootGdt[KGDT_TSS / sizeof(KGDTENTRY)];
330 TssEntry->HighWord.Bits.Type = I386_TSS;
331 TssEntry->HighWord.Bits.Pres = 1;
332 TssEntry->HighWord.Bits.Dpl = 0;
333 TssEntry->BaseLow = (USHORT)((ULONG_PTR)Tss & 0xFFFF);
334 TssEntry->HighWord.Bytes.BaseMid = (UCHAR)((ULONG_PTR)Tss >> 16);
335 TssEntry->HighWord.Bytes.BaseHi = (UCHAR)((ULONG_PTR)Tss >> 24);
336
337 /* Save pointer to ROS Block */
338 KeRosLoaderBlock = LoaderBlock;
339
340 /* Save the Base Address */
341 MmSystemRangeStart = (PVOID)KeRosLoaderBlock->KernelBase;
342
343 /* Convert every driver address to virtual memory */
344 for (i = 3; i < KeRosLoaderBlock->ModsCount; i++)
345 {
346 /* Subtract the base Address in Physical Memory */
347 KeRosLoaderBlock->ModsAddr[i].ModStart -= 0x200000;
348
349 /* Add the Kernel Base Address in Virtual Memory */
350 KeRosLoaderBlock->ModsAddr[i].ModStart += KSEG0_BASE;
351
352 /* Subtract the base Address in Physical Memory */
353 KeRosLoaderBlock->ModsAddr[i].ModEnd -= 0x200000;
354
355 /* Add the Kernel Base Address in Virtual Memory */
356 KeRosLoaderBlock->ModsAddr[i].ModEnd += KSEG0_BASE;
357 }
358
359 /* Save memory manager data */
360 MmFreeLdrLastKernelAddress = PAGE_ROUND_UP(KeRosLoaderBlock->
361 ModsAddr[KeRosLoaderBlock->
362 ModsCount - 1].
363 ModEnd);
364 MmFreeLdrFirstKrnlPhysAddr = KeRosLoaderBlock->ModsAddr[0].ModStart -
365 KSEG0_BASE + 0x200000;
366 MmFreeLdrLastKrnlPhysAddr = MmFreeLdrLastKernelAddress -
367 KSEG0_BASE + 0x200000;
368
369 /* Set up the VDM Data */
370 NtEarlyInitVdm();
371
372 /* Convert the loader block */
373 KiRosFrldrLpbToNtLpb(KeRosLoaderBlock, &NtLoaderBlock);
374
375 /* Do general System Startup */
376 KiSystemStartup(NtLoaderBlock);
377 }
378
379 /* EOF */