- Add dumping boot drivers list, remove unneded comment
[reactos.git] / reactos / boot / freeldr / freeldr / windows / winldr.c
1 /*
2 * FreeLoader
3 *
4 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
5 * Copyright (C) 2006 Aleksey Bragin <aleksey@reactos.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include <freeldr.h>
23
24 #include <ndk/ldrtypes.h>
25
26 //#define NDEBUG
27 #include <debug.h>
28
29 // debug stuff
30 VOID DumpMemoryAllocMap(VOID);
31 VOID WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock);
32 VOID WinLdrpDumpBootDriver(PLOADER_PARAMETER_BLOCK LoaderBlock);
33
34 void InitializeHWConfig(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock)
35 {
36 PCONFIGURATION_COMPONENT_DATA ConfigurationRoot;
37 PCONFIGURATION_COMPONENT Component;
38 PCONFIGURATION_COMPONENT_DATA /*CurrentEntry,*/ PreviousEntry, AdapterEntry;
39 BOOLEAN IsNextEntryChild;
40
41 DbgPrint((DPRINT_WINDOWS, "InitializeHWConfig()\n"));
42
43 LoaderBlock->ConfigurationRoot = MmAllocateMemory(sizeof(CONFIGURATION_COMPONENT_DATA));
44 RtlZeroMemory(LoaderBlock->ConfigurationRoot, sizeof(CONFIGURATION_COMPONENT_DATA));
45
46 /* Fill root == SystemClass */
47 ConfigurationRoot = LoaderBlock->ConfigurationRoot;
48 Component = &LoaderBlock->ConfigurationRoot->ComponentEntry;
49
50 Component->Class = SystemClass;
51 Component->Type = MaximumType;
52 Component->Version = 0; // FIXME: ?
53 Component->Key = 0;
54 Component->AffinityMask = 0;
55
56 IsNextEntryChild = TRUE;
57 PreviousEntry = ConfigurationRoot;
58
59 /* Enumerate all PCI buses */
60 AdapterEntry = ConfigurationRoot;
61
62 /* TODO: Disk Geometry */
63 /* TODO: Keyboard */
64
65 /* TODO: Serial port */
66
67 //Config->ConfigurationData = alloc(sizeof(CONFIGURATION_COMPONENT_DATA), EfiLoaderData);
68
69 /* Convert everything to VA */
70 ConvertConfigToVA(LoaderBlock->ConfigurationRoot);
71 LoaderBlock->ConfigurationRoot = PaToVa(LoaderBlock->ConfigurationRoot);
72 }
73
74
75 // Init "phase 0"
76 VOID
77 AllocateAndInitLPB(PLOADER_PARAMETER_BLOCK *OutLoaderBlock)
78 {
79 PLOADER_PARAMETER_BLOCK LoaderBlock;
80
81 /* Allocate and zero-init the LPB */
82 LoaderBlock = MmAllocateMemory(sizeof(LOADER_PARAMETER_BLOCK));
83 RtlZeroMemory(LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
84
85 /* Init three critical lists, used right away */
86 InitializeListHead(&LoaderBlock->LoadOrderListHead);
87 InitializeListHead(&LoaderBlock->MemoryDescriptorListHead);
88 InitializeListHead(&LoaderBlock->BootDriverListHead);
89
90
91 *OutLoaderBlock = LoaderBlock;
92 }
93
94 // Init "phase 1"
95 VOID
96 WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock)
97 {
98 //CHAR Options[] = "/CRASHDEBUG /DEBUGPORT=COM1 /BAUDRATE=115200";
99 CHAR Options[] = "/NODEBUG";
100 CHAR SystemRoot[] = "\\WINNT";
101 CHAR HalPath[] = "\\";
102 CHAR ArcBoot[] = "multi(0)disk(0)rdisk(1)partition(1)";
103 CHAR ArcHal[] = "multi(0)disk(0)rdisk(1)partition(1)";
104
105 PLOADER_PARAMETER_EXTENSION Extension;
106
107 LoaderBlock->u.I386.CommonDataArea = NULL; // Force No ABIOS support
108
109 /* Fill Arc BootDevice */
110 LoaderBlock->ArcBootDeviceName = MmAllocateMemory(strlen(ArcBoot)+1);
111 strcpy(LoaderBlock->ArcBootDeviceName, ArcBoot);
112 LoaderBlock->ArcBootDeviceName = PaToVa(LoaderBlock->ArcBootDeviceName);
113
114 /* Fill Arc HalDevice */
115 LoaderBlock->ArcHalDeviceName = MmAllocateMemory(strlen(ArcHal)+1);
116 strcpy(LoaderBlock->ArcHalDeviceName, ArcHal);
117 LoaderBlock->ArcHalDeviceName = PaToVa(LoaderBlock->ArcHalDeviceName);
118
119 /* Fill SystemRoot */
120 LoaderBlock->NtBootPathName = MmAllocateMemory(strlen(SystemRoot)+1);
121 strcpy(LoaderBlock->NtBootPathName, SystemRoot);
122 LoaderBlock->NtBootPathName = PaToVa(LoaderBlock->NtBootPathName);
123
124 /* Fill NtHalPathName */
125 LoaderBlock->NtHalPathName = MmAllocateMemory(strlen(HalPath)+1);
126 strcpy(LoaderBlock->NtHalPathName, HalPath);
127 LoaderBlock->NtHalPathName = PaToVa(LoaderBlock->NtHalPathName);
128
129 /* Fill load options */
130 LoaderBlock->LoadOptions = MmAllocateMemory(strlen(Options)+1);
131 strcpy(LoaderBlock->LoadOptions, Options);
132 LoaderBlock->LoadOptions = PaToVa(LoaderBlock->LoadOptions);
133
134 /* Arc devices */
135 LoaderBlock->ArcDiskInformation = (PARC_DISK_INFORMATION)MmAllocateMemory(sizeof(ARC_DISK_INFORMATION));
136 InitializeListHead(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead);
137 List_PaToVa(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead);
138 LoaderBlock->ArcDiskInformation = PaToVa(LoaderBlock->ArcDiskInformation);
139
140 /* Alloc space for NLS (it will be converted to VA in WinLdrLoadNLS) */
141 LoaderBlock->NlsData = MmAllocateMemory(sizeof(NLS_DATA_BLOCK));
142 if (LoaderBlock->NlsData == NULL)
143 {
144 UiMessageBox("Failed to allocate memory for NLS table data!");
145 return;
146 }
147 RtlZeroMemory(LoaderBlock->NlsData, sizeof(NLS_DATA_BLOCK));
148
149 /* Create configuration entries */
150 InitializeHWConfig(LoaderBlock);
151
152 /* Convert all DTE into virtual addresses */
153 //TODO: !!!
154
155 /* Convert all list's to Virtual address */
156 List_PaToVa(&LoaderBlock->LoadOrderListHead);
157
158 /* this one will be converted right before switching to
159 virtual paging mode */
160 //List_PaToVa(&LoaderBlock->MemoryDescriptorListHead);
161
162 List_PaToVa(&LoaderBlock->BootDriverListHead);
163
164 /* Initialize Extension now */
165 Extension = MmAllocateMemory(sizeof(LOADER_PARAMETER_EXTENSION));
166 if (Extension == NULL)
167 {
168 UiMessageBox("Failed to allocate LPB Extension!");
169 return;
170 }
171 RtlZeroMemory(Extension, sizeof(LOADER_PARAMETER_EXTENSION));
172
173 Extension->Size = sizeof(LOADER_PARAMETER_EXTENSION);
174 Extension->MajorVersion = 4;
175 Extension->MinorVersion = 0;
176
177
178 LoaderBlock->Extension = PaToVa(Extension);
179 }
180
181 // Last step before going virtual
182 void WinLdrSetupForNt(PLOADER_PARAMETER_BLOCK LoaderBlock,
183 PVOID *GdtIdt,
184 ULONG *PcrBasePage,
185 ULONG *TssBasePage)
186 {
187 ULONG TssSize;
188 ULONG TssPages;
189 ULONG_PTR Pcr = 0;
190 ULONG_PTR Tss = 0;
191 ULONG BlockSize, NumPages;
192
193 LoaderBlock->u.I386.CommonDataArea = NULL;//CommonDataArea;
194 //LoaderBlock->u.I386.MachineType = MachineType; //FIXME: MachineType?
195
196 /* Allocate 2 pages for PCR */
197 Pcr = (ULONG_PTR)MmAllocateMemory(2 * MM_PAGE_SIZE);
198 *PcrBasePage = Pcr >> MM_PAGE_SHIFT;
199
200 if (Pcr == 0)
201 {
202 UiMessageBox("Can't allocate PCR\n");
203 return;
204 }
205
206 /* Allocate TSS */
207 TssSize = (sizeof(KTSS) + MM_PAGE_SIZE) & ~(MM_PAGE_SIZE - 1);
208 TssPages = TssSize / MM_PAGE_SIZE;
209
210 Tss = (ULONG_PTR)MmAllocateMemory(TssSize);
211
212 *TssBasePage = Tss >> MM_PAGE_SHIFT;
213
214 /* Allocate space for new GDT + IDT */
215 BlockSize = NUM_GDT*sizeof(KGDTENTRY) + NUM_IDT*sizeof(KIDTENTRY);//FIXME: Use GDT/IDT limits here?
216 NumPages = (BlockSize + MM_PAGE_SIZE - 1) >> MM_PAGE_SHIFT;
217 *GdtIdt = (PKGDTENTRY)MmAllocateMemory(NumPages * MM_PAGE_SIZE);
218
219 if (*GdtIdt == NULL)
220 {
221 UiMessageBox("Can't allocate pages for GDT+IDT!\n");
222 return;
223 }
224
225 /* Zero newly prepared GDT+IDT */
226 RtlZeroMemory(*GdtIdt, NumPages << MM_PAGE_SHIFT);
227 }
228
229 VOID
230 LoadAndBootWindows(PCSTR OperatingSystemName, WORD OperatingSystemVersion)
231 {
232 CHAR MsgBuffer[256];
233 CHAR SystemPath[1024], SearchPath[1024];
234 CHAR FileName[1024];
235 CHAR BootPath[256];
236 PVOID NtosBase = NULL, HalBase = NULL, KdComBase = NULL;
237 BOOLEAN Status;
238 ULONG SectionId;
239 ULONG BootDevice;
240 PLOADER_PARAMETER_BLOCK LoaderBlock, LoaderBlockVA;
241 KERNEL_ENTRY_POINT KiSystemStartup;
242 PLDR_DATA_TABLE_ENTRY KernelDTE, HalDTE, KdComDTE = NULL;
243 // Mm-related things
244 PVOID GdtIdt;
245 ULONG PcrBasePage=0;
246 ULONG TssBasePage=0;
247
248
249
250 //sprintf(MsgBuffer,"Booting Microsoft(R) Windows(R) OS version '%04x' is not implemented yet", OperatingSystemVersion);
251 //UiMessageBox(MsgBuffer);
252
253 // Open the operating system section
254 // specified in the .ini file
255 if (!IniOpenSection(OperatingSystemName, &SectionId))
256 {
257 sprintf(MsgBuffer,"Operating System section '%s' not found in freeldr.ini", OperatingSystemName);
258 UiMessageBox(MsgBuffer);
259 return;
260 }
261
262 /* Make sure the system path is set in the .ini file */
263 if (!IniReadSettingByName(SectionId, "SystemPath", SystemPath, sizeof(SystemPath)))
264 {
265 UiMessageBox("System path not specified for selected operating system.");
266 return;
267 }
268
269 if (!MachDiskNormalizeSystemPath(SystemPath,
270 sizeof(SystemPath)))
271 {
272 UiMessageBox("Invalid system path");
273 return;
274 }
275
276 UiDrawStatusText("Loading...");
277
278 /* Try to open system drive */
279 BootDevice = 0xffffffff;
280 if (!FsOpenSystemVolume(SystemPath, BootPath, &BootDevice))
281 {
282 UiMessageBox("Failed to open boot drive.");
283 return;
284 }
285
286 /* append a backslash */
287 if ((strlen(BootPath)==0) ||
288 BootPath[strlen(BootPath)] != '\\')
289 strcat(BootPath, "\\");
290
291 DbgPrint((DPRINT_WINDOWS,"SystemRoot: '%s'\n", BootPath));
292
293 // Allocate and minimalistic-initialize LPB
294 AllocateAndInitLPB(&LoaderBlock);
295
296 // Load kernel
297 strcpy(FileName, BootPath);
298 strcat(FileName, "SYSTEM32\\NTOSKRNL.EXE");
299 Status = WinLdrLoadImage(FileName, &NtosBase);
300 DbgPrint((DPRINT_WINDOWS, "Ntos loaded with status %d at %p\n", Status, NtosBase));
301
302 // Load HAL
303 strcpy(FileName, BootPath);
304 strcat(FileName, "SYSTEM32\\HAL.DLL");
305 Status = WinLdrLoadImage(FileName, &HalBase);
306 DbgPrint((DPRINT_WINDOWS, "HAL loaded with status %d at %p\n", Status, HalBase));
307
308 // Load kernel-debugger support dll
309 if (OperatingSystemVersion > _WIN32_WINNT_NT4)
310 {
311 strcpy(FileName, BootPath);
312 strcat(FileName, "SYSTEM32\\KDCOM.DLL");
313 Status = WinLdrLoadImage(FileName, &KdComBase);
314 DbgPrint((DPRINT_WINDOWS, "KdCom loaded with status %d at %p\n", Status, KdComBase));
315 }
316
317 // Allocate data table entries for above-loaded modules
318 WinLdrAllocateDataTableEntry(LoaderBlock, "ntoskrnl.exe",
319 "WINNT\\SYSTEM32\\NTOSKRNL.EXE", NtosBase, &KernelDTE);
320 WinLdrAllocateDataTableEntry(LoaderBlock, "hal.dll",
321 "WINNT\\SYSTEM32\\HAL.DLL", HalBase, &HalDTE);
322 if (OperatingSystemVersion > _WIN32_WINNT_NT4)
323 {
324 WinLdrAllocateDataTableEntry(LoaderBlock, "kdcom.dll",
325 "WINNT\\SYSTEM32\\KDCOM.DLL", KdComBase, &KdComDTE);
326 }
327
328 /* Load all referenced DLLs for kernel, HAL and kdcom.dll */
329 strcpy(SearchPath, BootPath);
330 strcat(SearchPath, "SYSTEM32\\");
331 WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, KernelDTE);
332 WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, HalDTE);
333 if (KdComDTE)
334 WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, KdComDTE);
335
336 /* Initialize Phase 1 - before NLS */
337 WinLdrInitializePhase1(LoaderBlock);
338
339 /* Load Hive, and then NLS data, OEM font, and prepare boot drivers list */
340 Status = WinLdrLoadAndScanSystemHive(LoaderBlock, BootPath);
341 DbgPrint((DPRINT_WINDOWS, "SYSTEM hive loaded and scanned with status %d\n", Status));
342
343 /* Load boot drivers */
344 //WinLdrLoadBootDrivers();
345
346 /* Alloc PCR, TSS, do magic things with the GDT/IDT */
347 WinLdrSetupForNt(LoaderBlock, &GdtIdt, &PcrBasePage, &TssBasePage);
348
349 /* Save entry-point pointer (VA) */
350 KiSystemStartup = (KERNEL_ENTRY_POINT)KernelDTE->EntryPoint;
351
352 LoaderBlockVA = PaToVa(LoaderBlock);
353
354 /* Debugging... */
355 //DumpMemoryAllocMap();
356
357 /* Turn on paging mode of CPU*/
358 WinLdrTurnOnPaging(LoaderBlock, PcrBasePage, TssBasePage, GdtIdt);
359
360 DbgPrint((DPRINT_WINDOWS, "Hello from paged mode, KiSystemStartup %p, LoaderBlockVA %p!\n",
361 KiSystemStartup, LoaderBlockVA));
362
363 WinLdrpDumpMemoryDescriptors(LoaderBlockVA);
364 WinLdrpDumpBootDriver(LoaderBlockVA);
365
366 //FIXME: If I substitute this debugging checkpoint, GCC will "optimize away" the code below
367 //while (1) {};
368 /*asm(".intel_syntax noprefix\n");
369 asm("test1:\n");
370 asm("jmp test1\n");
371 asm(".att_syntax\n");*/
372
373
374 (*KiSystemStartup)(LoaderBlockVA);
375
376 return;
377 }
378
379 VOID
380 WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock)
381 {
382 PLIST_ENTRY NextMd;
383 PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
384
385 NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
386
387 while (NextMd != &LoaderBlock->MemoryDescriptorListHead)
388 {
389 MemoryDescriptor = CONTAINING_RECORD(NextMd, MEMORY_ALLOCATION_DESCRIPTOR, ListEntry);
390
391
392 DbgPrint((DPRINT_WINDOWS, "BP %08X PC %04X MT %d\n", MemoryDescriptor->BasePage,
393 MemoryDescriptor->PageCount, MemoryDescriptor->MemoryType));
394
395 NextMd = MemoryDescriptor->ListEntry.Flink;
396 }
397 }
398
399 VOID
400 WinLdrpDumpBootDriver(PLOADER_PARAMETER_BLOCK LoaderBlock)
401 {
402 PLIST_ENTRY NextBd;
403 PBOOT_DRIVER_LIST_ENTRY BootDriver;
404
405 NextBd = LoaderBlock->BootDriverListHead.Flink;
406
407 while (NextBd != &LoaderBlock->BootDriverListHead)
408 {
409 BootDriver = CONTAINING_RECORD(NextBd, BOOT_DRIVER_LIST_ENTRY, ListEntry);
410
411 DbgPrint((DPRINT_WINDOWS, "BootDriver %wZ DTE %08X RegPath: %wZ\n", &BootDriver->FilePath,
412 BootDriver->DataTableEntry, &BootDriver->RegistryPath));
413
414 NextBd = BootDriver->ListEntry.Flink;
415 }
416 }