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