Fix a couple of problems with FreeLDR portability.
[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 extern char reactos_arc_hardware_data[HW_MAX_ARC_HEAP_SIZE];
34 char szBootPath[256];
35 char szHalName[256];
36 CHAR SystemRoot[255];
37 extern ULONG_PTR KernelBase;
38 extern ROS_KERNEL_ENTRY_POINT KernelEntryPoint;
39
40 extern BOOLEAN FrLdrLoadDriver(PCHAR szFileName, INT nPos);
41
42 #define USE_UI
43
44 BOOLEAN
45 NTAPI
46 static FrLdrLoadKernel(IN PCHAR szFileName,
47 IN INT nPos)
48 {
49 PFILE FilePointer;
50 PCHAR szShortName;
51 CHAR szBuffer[256];
52 PVOID LoadBase;
53 PIMAGE_NT_HEADERS NtHeader;
54
55 /* Extract Kernel filename without path */
56 szShortName = strrchr(szFileName, '\\');
57 if (!szShortName)
58 {
59 /* No path, leave it alone */
60 szShortName = szFileName;
61 }
62 else
63 {
64 /* Skip the path */
65 szShortName = szShortName + 1;
66 }
67
68 /* Open the Kernel */
69 FilePointer = FsOpenFile(szFileName);
70 if (!FilePointer)
71 {
72 /* Return failure on the short name */
73 strcpy(szBuffer, szShortName);
74 strcat(szBuffer, " not found.");
75 UiMessageBox(szBuffer);
76 return FALSE;
77 }
78
79 /* Update the status bar with the current file */
80 strcpy(szBuffer, "Reading ");
81 strcat(szBuffer, szShortName);
82 UiDrawStatusText(szBuffer);
83
84 /* Do the actual loading */
85 LoadBase = FrLdrMapImage(FilePointer, szShortName, 1);
86
87 /* Get the NT header, kernel base and kernel entry */
88 NtHeader = RtlImageNtHeader(LoadBase);
89 KernelBase = NtHeader->OptionalHeader.ImageBase;
90 KernelEntryPoint = (ROS_KERNEL_ENTRY_POINT)(KernelBase + NtHeader->OptionalHeader.AddressOfEntryPoint);
91 LoaderBlock.KernelBase = KernelBase;
92
93 /* Update Processbar and return success */
94 return TRUE;
95 }
96
97 static BOOLEAN
98 LoadDriver(PCSTR szSourcePath, PCSTR szFileName)
99 {
100 return FrLdrLoadDriver((PCHAR)szFileName, 0);
101 }
102
103
104 static BOOLEAN
105 LoadNlsFile(PCSTR szSourcePath, PCSTR szFileName, PCSTR szModuleName)
106 {
107 CHAR szFullName[256];
108 CHAR szBuffer[80];
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 sprintf(szBuffer, "Setup is loading files (%s)", szShortName);
154 UiDrawStatusText(szBuffer);
155
156 /* Load the driver */
157 FrLdrLoadModule(FilePointer, szModuleName, NULL);
158
159 return(TRUE);
160 }
161
162 VOID RunLoader(VOID)
163 {
164 ULONG i;
165 const char *SourcePath;
166 const char *LoadOptions = "", *DbgLoadOptions = "";
167 const char *sourcePaths[] = {
168 "", /* Only for floppy boot */
169 #if defined(_M_IX86)
170 "\\I386",
171 #elif defined(_M_MPPC)
172 "\\PPC",
173 #elif defined(_M_MRX000)
174 "\\MIPS",
175 #endif
176 "\\reactos",
177 NULL };
178 char szKernelName[256];
179
180 HINF InfHandle;
181 ULONG ErrorLine;
182 INFCONTEXT InfContext;
183
184 /* Setup multiboot information structure */
185 LoaderBlock.CommandLine = reactos_kernel_cmdline;
186 LoaderBlock.PageDirectoryStart = (ULONG)&PageDirectoryStart;
187 LoaderBlock.PageDirectoryEnd = (ULONG)&PageDirectoryEnd;
188 LoaderBlock.ModsCount = 0;
189 LoaderBlock.ModsAddr = reactos_modules;
190 LoaderBlock.MmapLength = (unsigned long)MachGetMemoryMap((PBIOS_MEMORY_MAP)reactos_memory_map, 32) * sizeof(memory_map_t);
191 if (LoaderBlock.MmapLength)
192 {
193 #ifdef _M_IX86
194 ULONG i;
195 #endif
196 LoaderBlock.Flags |= MB_FLAGS_MEM_INFO | MB_FLAGS_MMAP_INFO;
197 LoaderBlock.MmapAddr = (unsigned long)&reactos_memory_map;
198 reactos_memory_map_descriptor_size = sizeof(memory_map_t); // GetBiosMemoryMap uses a fixed value of 24
199 #ifdef _M_IX86
200 for (i=0; i<(LoaderBlock.MmapLength/sizeof(memory_map_t)); i++)
201 {
202 if (BiosMemoryUsable == reactos_memory_map[i].type &&
203 0 == reactos_memory_map[i].base_addr_low)
204 {
205 LoaderBlock.MemLower = (reactos_memory_map[i].base_addr_low + reactos_memory_map[i].length_low) / 1024;
206 if (640 < LoaderBlock.MemLower)
207 {
208 LoaderBlock.MemLower = 640;
209 }
210 }
211 if (BiosMemoryUsable == reactos_memory_map[i].type &&
212 reactos_memory_map[i].base_addr_low <= 1024 * 1024 &&
213 1024 * 1024 <= reactos_memory_map[i].base_addr_low + reactos_memory_map[i].length_low)
214 {
215 LoaderBlock.MemHigher = (reactos_memory_map[i].base_addr_low + reactos_memory_map[i].length_low) / 1024 - 1024;
216 }
217 }
218 #endif
219 }
220
221 #ifdef USE_UI
222 SetupUiInitialize();
223 #endif
224 UiDrawStatusText("");
225
226 extern BOOLEAN FrLdrBootType;
227 FrLdrBootType = TRUE;
228
229 /* Initialize registry */
230 RegInitializeRegistry();
231
232 /* Detect hardware */
233 UiDrawStatusText("Detecting hardware...");
234 LoaderBlock.ArchExtra = (ULONG)MachHwDetect();
235 UiDrawStatusText("");
236
237 /* set boot device */
238 MachDiskGetBootDevice(&LoaderBlock.BootDevice);
239
240 /* Open boot drive */
241 if (!FsOpenBootVolume())
242 {
243 UiMessageBox("Failed to open boot drive.");
244 return;
245 }
246
247 /* Open 'txtsetup.sif' */
248 for (i = MachDiskBootingFromFloppy() ? 0 : 1; ; i++)
249 {
250 SourcePath = sourcePaths[i];
251 if (!SourcePath)
252 {
253 printf("Failed to open 'txtsetup.sif'\n");
254 return;
255 }
256 strcpy(szKernelName, SourcePath);
257 strcat(szKernelName, "\\txtsetup.sif");
258 if (InfOpenFile (&InfHandle, szKernelName, &ErrorLine))
259 break;
260 }
261 if (!*SourcePath)
262 SourcePath = "\\";
263
264 #ifdef DBG
265 /* Get load options */
266 if (InfFindFirstLine (InfHandle,
267 "SetupData",
268 "DbgOsLoadOptions",
269 &InfContext))
270 {
271 if (!InfGetDataField (&InfContext, 1, &DbgLoadOptions))
272 DbgLoadOptions = "";
273 }
274 #endif
275 if (!strlen(DbgLoadOptions) && !InfFindFirstLine (InfHandle,
276 "SetupData",
277 "OsLoadOptions",
278 &InfContext))
279 {
280 printf("Failed to find 'SetupData/OsLoadOptions'\n");
281 return;
282 }
283
284 if (!InfGetDataField (&InfContext,
285 1,
286 &LoadOptions))
287 {
288 printf("Failed to get load options\n");
289 return;
290 }
291
292 /* Set kernel command line */
293 MachDiskGetBootPath(reactos_kernel_cmdline, sizeof(reactos_kernel_cmdline));
294 strcat(strcat(strcat(strcat(reactos_kernel_cmdline, SourcePath), " "),
295 LoadOptions), DbgLoadOptions);
296
297 strcpy(SystemRoot, SourcePath);
298 strcat(SystemRoot, "\\");
299
300 /* Setup the boot path and kernel path */
301 strcpy(szBootPath, SourcePath);
302 strcpy(szKernelName, szBootPath);
303 strcat(szKernelName, "\\ntoskrnl.exe");
304
305 /* Setup the HAL path */
306 strcpy(szHalName, szBootPath);
307 strcat(szHalName, "\\hal.dll");
308
309 /* Load the kernel */
310 if (!FrLdrLoadKernel(szKernelName, 5)) return;
311
312 /* Insert boot disk 2 */
313 if (MachDiskBootingFromFloppy())
314 {
315 UiMessageBox("Please insert \"ReactOS Boot Disk 2\" and press ENTER");
316
317 /* Open boot drive */
318 if (!FsOpenBootVolume())
319 {
320 UiMessageBox("Failed to open boot drive.");
321 return;
322 }
323
324 /* FIXME: check volume label or disk marker file */
325 }
326
327
328 /* Get ANSI codepage file */
329 if (!InfFindFirstLine (InfHandle,
330 "NLS",
331 "AnsiCodepage",
332 &InfContext))
333 {
334 printf("Failed to find 'NLS/AnsiCodepage'\n");
335 return;
336 }
337
338 if (!InfGetDataField (&InfContext,
339 1,
340 &LoadOptions))
341 {
342 printf("Failed to get load options\n");
343 return;
344 }
345
346 /* Load ANSI codepage file */
347 if (!LoadNlsFile(SourcePath, LoadOptions, "ansi.nls"))
348 {
349 UiMessageBox("Failed to load the ANSI codepage file.");
350 return;
351 }
352
353 /* Get OEM codepage file */
354 if (!InfFindFirstLine (InfHandle,
355 "NLS",
356 "OemCodepage",
357 &InfContext))
358 {
359 printf("Failed to find 'NLS/AnsiCodepage'\n");
360 return;
361 }
362
363 if (!InfGetDataField (&InfContext,
364 1,
365 &LoadOptions))
366 {
367 printf("Failed to get load options\n");
368 return;
369 }
370
371 /* Load OEM codepage file */
372 if (!LoadNlsFile(SourcePath, LoadOptions, "oem.nls"))
373 {
374 UiMessageBox("Failed to load the OEM codepage file.");
375 return;
376 }
377
378 /* Get Unicode Casemap file */
379 if (!InfFindFirstLine (InfHandle,
380 "NLS",
381 "UnicodeCasetable",
382 &InfContext))
383 {
384 printf("Failed to find 'NLS/AnsiCodepage'\n");
385 return;
386 }
387
388 if (!InfGetDataField (&InfContext,
389 1,
390 &LoadOptions))
391 {
392 printf("Failed to get load options\n");
393 return;
394 }
395
396 /* Load Unicode casemap file */
397 if (!LoadNlsFile(SourcePath, LoadOptions, "casemap.nls"))
398 {
399 UiMessageBox("Failed to load the Unicode casemap file.");
400 return;
401 }
402
403 /* Load vfatfs.sys (could be loaded by the setup prog!) */
404 if (!LoadDriver(SourcePath, "vfatfs.sys"))
405 return;
406
407 /* Load additional files specified in txtsetup.inf */
408 if (InfFindFirstLine(InfHandle,
409 "SourceDisksFiles",
410 NULL,
411 &InfContext))
412 {
413 do
414 {
415 LPCSTR Media, DriverName;
416 if (InfGetDataField(&InfContext, 7, &Media) &&
417 InfGetDataField(&InfContext, 0, &DriverName))
418 {
419 if (strcmp(Media, "x") == 0)
420 {
421 if (!LoadDriver(SourcePath, DriverName))
422 return;
423 }
424 }
425 } while (InfFindNextLine(&InfContext, &InfContext));
426 }
427
428 UiUnInitialize("Booting ReactOS...");
429
430 //
431 // Perform architecture-specific pre-boot configuration
432 //
433 MachPrepareForReactOS(FALSE);
434
435 //
436 // Setup paging and jump to kernel
437 //
438 FrLdrStartup(0x2badb002);
439 }
440
441 /* EOF */