Fix memory map to kernel mode.
[reactos.git] / reactos / boot / freeldr / freeldr / reactos / setupldr.c
1 /*
2 * FreeLoader
3 *
4 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #define _NTSYSTEM_
22 #include <freeldr.h>
23 #include <debug.h>
24
25 extern ULONG PageDirectoryStart;
26 extern ULONG PageDirectoryEnd;
27
28 ROS_LOADER_PARAMETER_BLOCK LoaderBlock;
29 char reactos_kernel_cmdline[255]; // Command line passed to kernel
30 LOADER_MODULE reactos_modules[64]; // Array to hold boot module info loaded for the kernel
31 char reactos_module_strings[64][256]; // Array to hold module names
32 reactos_mem_data_t reactos_mem_data;
33 char szBootPath[256];
34 char szHalName[256];
35 CHAR SystemRoot[255];
36 extern ULONG_PTR KernelBase, KernelEntryPoint;
37
38 extern BOOLEAN FrLdrLoadDriver(PCHAR szFileName, INT nPos);
39
40 #define USE_UI
41
42 BOOLEAN
43 NTAPI
44 static FrLdrLoadKernel(IN PCHAR szFileName,
45 IN INT nPos)
46 {
47 PFILE FilePointer;
48 PCHAR szShortName;
49 CHAR szBuffer[256];
50 PVOID LoadBase;
51 PIMAGE_NT_HEADERS NtHeader;
52
53 /* Extract Kernel filename without path */
54 szShortName = strrchr(szFileName, '\\');
55 if (!szShortName)
56 {
57 /* No path, leave it alone */
58 szShortName = szFileName;
59 }
60 else
61 {
62 /* Skip the path */
63 szShortName = szShortName + 1;
64 }
65
66 /* Open the Kernel */
67 FilePointer = FsOpenFile(szFileName);
68 if (!FilePointer)
69 {
70 /* Return failure on the short name */
71 strcpy(szBuffer, szShortName);
72 strcat(szBuffer, " not found.");
73 UiMessageBox(szBuffer);
74 return FALSE;
75 }
76
77 /* Update the status bar with the current file */
78 strcpy(szBuffer, "Reading ");
79 strcat(szBuffer, szShortName);
80 UiDrawStatusText(szBuffer);
81
82 /* Do the actual loading */
83 LoadBase = FrLdrMapImage(FilePointer, szShortName, 1);
84
85 /* Get the NT header, kernel base and kernel entry */
86 NtHeader = RtlImageNtHeader(LoadBase);
87 KernelBase = NtHeader->OptionalHeader.ImageBase;
88 KernelEntryPoint = KernelBase + NtHeader->OptionalHeader.AddressOfEntryPoint;
89 LoaderBlock.KernelBase = KernelBase;
90
91 /* Update Processbar and return success */
92 return TRUE;
93 }
94
95 static BOOLEAN
96 LoadDriver(PCSTR szSourcePath, PCSTR szFileName)
97 {
98 return FrLdrLoadDriver((PCHAR)szFileName, 0);
99 }
100
101
102 static BOOLEAN
103 LoadNlsFile(PCSTR szSourcePath, PCSTR szFileName, PCSTR szModuleName)
104 {
105 CHAR szFullName[256];
106 #ifdef USE_UI
107 CHAR szBuffer[80];
108 #endif
109 PFILE FilePointer;
110 PCSTR szShortName;
111
112 if (szSourcePath[0] != '\\')
113 {
114 strcpy(szFullName, "\\");
115 strcat(szFullName, szSourcePath);
116 }
117 else
118 {
119 strcpy(szFullName, szSourcePath);
120 }
121
122 if (szFullName[strlen(szFullName)] != '\\')
123 {
124 strcat(szFullName, "\\");
125 }
126
127 if (szFileName[0] != '\\')
128 {
129 strcat(szFullName, szFileName);
130 }
131 else
132 {
133 strcat(szFullName, szFileName + 1);
134 }
135
136 szShortName = strrchr(szFileName, '\\');
137 if (szShortName == NULL)
138 szShortName = szFileName;
139 else
140 szShortName = szShortName + 1;
141
142
143 FilePointer = FsOpenFile(szFullName);
144 if (FilePointer == NULL)
145 {
146 printf("Could not find %s\n", szFileName);
147 return(FALSE);
148 }
149
150 /*
151 * Update the status bar with the current file
152 */
153 #ifdef USE_UI
154 sprintf(szBuffer, "Setup is loading files (%s)", szShortName);
155 UiDrawStatusText(szBuffer);
156 #else
157 printf("Reading %s\n", szShortName);
158 #endif
159
160 /* Load the driver */
161 FrLdrLoadModule(FilePointer, szModuleName, NULL);
162
163 return(TRUE);
164 }
165
166 VOID RunLoader(VOID)
167 {
168 ULONG_PTR Base;
169 ULONG Size, i;
170 const char *SourcePath;
171 const char *LoadOptions = "", *DbgLoadOptions = "";
172 const char *sourcePaths[] = {
173 "", /* Only for floppy boot */
174 #if defined(_M_IX86)
175 "\\I386",
176 #elif defined(_M_MPPC)
177 "\\PPC",
178 #elif defined(_M_MRX000)
179 "\\MIPS",
180 #endif
181 "\\reactos",
182 NULL };
183 char szKernelName[256];
184
185 HINF InfHandle;
186 ULONG ErrorLine;
187 INFCONTEXT InfContext;
188
189 /* Setup multiboot information structure */
190 LoaderBlock.CommandLine = reactos_kernel_cmdline;
191 LoaderBlock.PageDirectoryStart = (ULONG)&PageDirectoryStart;
192 LoaderBlock.PageDirectoryEnd = (ULONG)&PageDirectoryEnd;
193 LoaderBlock.ModsCount = 0;
194 LoaderBlock.ModsAddr = reactos_modules;
195 LoaderBlock.MmapLength = (unsigned long)MachGetMemoryMap((PBIOS_MEMORY_MAP)reactos_memory_map, 32) * sizeof(memory_map_t);
196 if (LoaderBlock.MmapLength)
197 {
198 ULONG i;
199
200 LoaderBlock.MmapAddr = (unsigned long)&reactos_memory_map;
201 reactos_memory_map_descriptor_size = sizeof(memory_map_t); // GetBiosMemoryMap uses a fixed value of 24
202 for (i=0; i<(LoaderBlock.MmapLength/sizeof(memory_map_t)); i++)
203 {
204 if (BiosMemoryUsable == reactos_memory_map[i].type &&
205 0 == reactos_memory_map[i].base_addr_low)
206 {
207 LoaderBlock.MemLower = (reactos_memory_map[i].base_addr_low + reactos_memory_map[i].length_low) / 1024;
208 if (640 < LoaderBlock.MemLower)
209 {
210 LoaderBlock.MemLower = 640;
211 }
212 }
213 if (BiosMemoryUsable == reactos_memory_map[i].type &&
214 reactos_memory_map[i].base_addr_low <= 1024 * 1024 &&
215 1024 * 1024 <= reactos_memory_map[i].base_addr_low + reactos_memory_map[i].length_low)
216 {
217 LoaderBlock.MemHigher = (reactos_memory_map[i].base_addr_low + reactos_memory_map[i].length_low) / 1024 - 1024;
218 }
219 }
220 }
221
222 #ifdef USE_UI
223 SetupUiInitialize();
224 UiDrawStatusText("");
225 #endif
226
227 extern BOOLEAN FrLdrBootType;
228 FrLdrBootType = TRUE;
229
230 /* Initialize registry */
231 RegInitializeRegistry();
232
233 /* Detect hardware */
234 #ifdef USE_UI
235 UiDrawStatusText("Detecting hardware...");
236 #else
237 printf("Detecting hardware...\n\n");
238 #endif
239 MachHwDetect();
240 #ifdef USE_UI
241 UiDrawStatusText("");
242 #endif
243
244 /* set boot device */
245 MachDiskGetBootDevice(&LoaderBlock.BootDevice);
246
247 /* Open boot drive */
248 if (!FsOpenBootVolume())
249 {
250 #ifdef USE_UI
251 UiMessageBox("Failed to open boot drive.");
252 #else
253 printf("Failed to open boot drive.");
254 #endif
255 return;
256 }
257
258 /* Open 'txtsetup.sif' */
259 for (i = MachDiskBootingFromFloppy() ? 0 : 1; ; i++)
260 {
261 SourcePath = sourcePaths[i];
262 if (!SourcePath)
263 {
264 printf("Failed to open 'txtsetup.sif'\n");
265 return;
266 }
267 strcpy(szKernelName, SourcePath);
268 strcat(szKernelName, "\\txtsetup.sif");
269 if (InfOpenFile (&InfHandle, szKernelName, &ErrorLine))
270 break;
271 }
272 if (!*SourcePath)
273 SourcePath = "\\";
274
275 #ifdef DBG
276 /* Get load options */
277 if (InfFindFirstLine (InfHandle,
278 "SetupData",
279 "DbgOsLoadOptions",
280 &InfContext))
281 {
282 if (!InfGetDataField (&InfContext, 1, &DbgLoadOptions))
283 DbgLoadOptions = "";
284 }
285 #endif
286 if (!strlen(DbgLoadOptions) && !InfFindFirstLine (InfHandle,
287 "SetupData",
288 "OsLoadOptions",
289 &InfContext))
290 {
291 printf("Failed to find 'SetupData/OsLoadOptions'\n");
292 return;
293 }
294
295 if (!InfGetDataField (&InfContext,
296 1,
297 &LoadOptions))
298 {
299 printf("Failed to get load options\n");
300 return;
301 }
302 #if 0
303 printf("LoadOptions: '%s'\n", LoadOptions);
304 #endif
305
306 /* Set kernel command line */
307 MachDiskGetBootPath(reactos_kernel_cmdline, sizeof(reactos_kernel_cmdline));
308 strcat(strcat(strcat(strcat(reactos_kernel_cmdline, SourcePath), " "),
309 LoadOptions), DbgLoadOptions);
310
311 strcpy(SystemRoot, SourcePath);
312 strcat(SystemRoot, "\\");
313
314 /* Setup the boot path and kernel path */
315 strcpy(szBootPath, SourcePath);
316 strcpy(szKernelName, szBootPath);
317 strcat(szKernelName, "\\ntoskrnl.exe");
318
319 /* Setup the HAL path */
320 strcpy(szHalName, szBootPath);
321 strcat(szHalName, "\\hal.dll");
322
323 /* Load the kernel */
324 if (!FrLdrLoadKernel(szKernelName, 5)) return;
325
326 /* Export the hardware hive */
327 Base = FrLdrCreateModule ("HARDWARE");
328 RegExportBinaryHive (L"\\Registry\\Machine\\HARDWARE", (PVOID)Base, &Size);
329 FrLdrCloseModule (Base, Size);
330
331 #if 0
332 printf("Base: %x\n", Base);
333 printf("Size: %u\n", Size);
334 printf("*** System stopped ***\n");
335 for(;;);
336 #endif
337
338 /* Insert boot disk 2 */
339 if (MachDiskBootingFromFloppy())
340 {
341 #ifdef USE_UI
342 UiMessageBox("Please insert \"ReactOS Boot Disk 2\" and press ENTER");
343 #else
344 printf("\n\n Please insert \"ReactOS Boot Disk 2\" and press ENTER\n");
345 MachConsGetCh();
346 #endif
347
348 /* Open boot drive */
349 if (!FsOpenBootVolume())
350 {
351 #ifdef USE_UI
352 UiMessageBox("Failed to open boot drive.");
353 #else
354 printf("Failed to open boot drive.");
355 #endif
356 return;
357 }
358
359 /* FIXME: check volume label or disk marker file */
360 }
361
362
363 /* Get ANSI codepage file */
364 if (!InfFindFirstLine (InfHandle,
365 "NLS",
366 "AnsiCodepage",
367 &InfContext))
368 {
369 printf("Failed to find 'NLS/AnsiCodepage'\n");
370 return;
371 }
372
373 if (!InfGetDataField (&InfContext,
374 1,
375 &LoadOptions))
376 {
377 printf("Failed to get load options\n");
378 return;
379 }
380
381 /* Load ANSI codepage file */
382 if (!LoadNlsFile(SourcePath, LoadOptions, "ansi.nls"))
383 {
384 #ifdef USE_UI
385 UiMessageBox("Failed to load the ANSI codepage file.");
386 #else
387 printf("Failed to load the ANSI codepage file.");
388 #endif
389 return;
390 }
391
392 /* Get OEM codepage file */
393 if (!InfFindFirstLine (InfHandle,
394 "NLS",
395 "OemCodepage",
396 &InfContext))
397 {
398 printf("Failed to find 'NLS/AnsiCodepage'\n");
399 return;
400 }
401
402 if (!InfGetDataField (&InfContext,
403 1,
404 &LoadOptions))
405 {
406 printf("Failed to get load options\n");
407 return;
408 }
409
410 /* Load OEM codepage file */
411 if (!LoadNlsFile(SourcePath, LoadOptions, "oem.nls"))
412 {
413 #ifdef USE_UI
414 UiMessageBox("Failed to load the OEM codepage file.");
415 #else
416 printf("Failed to load the OEM codepage file.");
417 #endif
418 return;
419 }
420
421 /* Get Unicode Casemap file */
422 if (!InfFindFirstLine (InfHandle,
423 "NLS",
424 "UnicodeCasetable",
425 &InfContext))
426 {
427 printf("Failed to find 'NLS/AnsiCodepage'\n");
428 return;
429 }
430
431 if (!InfGetDataField (&InfContext,
432 1,
433 &LoadOptions))
434 {
435 printf("Failed to get load options\n");
436 return;
437 }
438
439 /* Load Unicode casemap file */
440 if (!LoadNlsFile(SourcePath, LoadOptions, "casemap.nls"))
441 {
442 #ifdef USE_UI
443 UiMessageBox("Failed to load the Unicode casemap file.");
444 #else
445 printf("Failed to load the Unicode casemap file.");
446 #endif
447 return;
448 }
449
450 /* Load atapi.sys (depends on hardware detection) */
451 if (!LoadDriver(SourcePath, "atapi.sys"))
452 return;
453
454 /* Load buslogic.sys (depends on hardware detection) */
455 if (!LoadDriver(SourcePath, "buslogic.sys"))
456 return;
457
458 /* Load vfatfs.sys (could be loaded by the setup prog!) */
459 if (!LoadDriver(SourcePath, "vfatfs.sys"))
460 return;
461
462 /* Load additional files specified in txtsetup.inf */
463 if (InfFindFirstLine(InfHandle,
464 "SourceDiskFiles",
465 NULL,
466 &InfContext))
467 {
468 do
469 {
470 LPCSTR Media, DriverName;
471 if (InfGetDataField(&InfContext, 7, &Media) &&
472 InfGetDataField(&InfContext, 0, &DriverName))
473 {
474 if (strcmp(Media, "x") == 0)
475 {
476 if (!LoadDriver(SourcePath, DriverName))
477 return;
478 }
479 }
480 } while (InfFindNextLine(&InfContext, &InfContext));
481 }
482
483 #ifdef USE_UI
484 UiUnInitialize("Booting ReactOS...");
485 #endif
486
487 /* Now boot the kernel */
488 DiskStopFloppyMotor();
489 MachVideoPrepareForReactOS(TRUE);
490 FrLdrStartup(0x2badb002);
491 }
492
493 /* EOF */