scroll mode for very long start menus
[reactos.git] / 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 #include <freeldr.h>
22 #include <debug.h>
23 #include <arch.h>
24 #include <disk.h>
25 #include <reactos.h>
26 #include <rtl.h>
27 #include <fs.h>
28 #include <multiboot.h>
29 #include <mm.h>
30 #include <ui.h>
31 #include <inffile.h>
32
33 #include "registry.h"
34
35
36 //#define USE_UI
37
38
39 static BOOL
40 LoadKernel(PCHAR szSourcePath, PCHAR szFileName)
41 {
42 CHAR szFullName[256];
43 #ifdef USE_UI
44 CHAR szBuffer[80];
45 #endif
46 PFILE FilePointer;
47 PCHAR szShortName;
48
49 if (szSourcePath[0] != '\\')
50 {
51 strcpy(szFullName, "\\");
52 strcat(szFullName, szSourcePath);
53 }
54 else
55 {
56 strcpy(szFullName, szSourcePath);
57 }
58
59 if (szFullName[strlen(szFullName)] != '\\')
60 {
61 strcat(szFullName, "\\");
62 }
63
64 if (szFileName[0] != '\\')
65 {
66 strcat(szFullName, szFileName);
67 }
68 else
69 {
70 strcat(szFullName, szFileName + 1);
71 }
72
73 szShortName = strrchr(szFileName, '\\');
74 if (szShortName == NULL)
75 szShortName = szFileName;
76 else
77 szShortName = szShortName + 1;
78
79 FilePointer = FsOpenFile(szFullName);
80 if (FilePointer == NULL)
81 {
82 printf("Could not find %s\n", szShortName);
83 return(FALSE);
84 }
85
86 /*
87 * Update the status bar with the current file
88 */
89 #ifdef USE_UI
90 sprintf(szBuffer, "Reading %s", szShortName);
91 UiDrawStatusText(szBuffer);
92 #else
93 printf("Reading %s\n", szShortName);
94 #endif
95
96 /*
97 * Load the kernel
98 */
99 MultiBootLoadKernel(FilePointer);
100
101 return(TRUE);
102 }
103
104
105 static BOOL
106 LoadDriver(PCHAR szSourcePath, PCHAR szFileName)
107 {
108 CHAR szFullName[256];
109 #ifdef USE_UI
110 CHAR szBuffer[80];
111 #endif
112 PFILE FilePointer;
113 PCHAR szShortName;
114
115 if (szSourcePath[0] != '\\')
116 {
117 strcpy(szFullName, "\\");
118 strcat(szFullName, szSourcePath);
119 }
120 else
121 {
122 strcpy(szFullName, szSourcePath);
123 }
124
125 if (szFullName[strlen(szFullName)] != '\\')
126 {
127 strcat(szFullName, "\\");
128 }
129
130 if (szFileName[0] != '\\')
131 {
132 strcat(szFullName, szFileName);
133 }
134 else
135 {
136 strcat(szFullName, szFileName + 1);
137 }
138
139 szShortName = strrchr(szFileName, '\\');
140 if (szShortName == NULL)
141 szShortName = szFileName;
142 else
143 szShortName = szShortName + 1;
144
145
146 FilePointer = FsOpenFile(szFullName);
147 if (FilePointer == NULL)
148 {
149 printf("Could not find %s\n", szFileName);
150 return(FALSE);
151 }
152
153 /*
154 * Update the status bar with the current file
155 */
156 #ifdef USE_UI
157 sprintf(szBuffer, "Reading %s", szShortName);
158 UiDrawStatusText(szBuffer);
159 #else
160 printf("Reading %s\n", szShortName);
161 #endif
162
163 /* Load the driver */
164 MultiBootLoadModule(FilePointer, szFileName, NULL);
165
166 return(TRUE);
167 }
168
169
170 static BOOL
171 LoadNlsFile(PCHAR szSourcePath, PCHAR szFileName, PCHAR szModuleName)
172 {
173 CHAR szFullName[256];
174 #ifdef USE_UI
175 CHAR szBuffer[80];
176 #endif
177 PFILE FilePointer;
178 PCHAR szShortName;
179
180 if (szSourcePath[0] != '\\')
181 {
182 strcpy(szFullName, "\\");
183 strcat(szFullName, szSourcePath);
184 }
185 else
186 {
187 strcpy(szFullName, szSourcePath);
188 }
189
190 if (szFullName[strlen(szFullName)] != '\\')
191 {
192 strcat(szFullName, "\\");
193 }
194
195 if (szFileName[0] != '\\')
196 {
197 strcat(szFullName, szFileName);
198 }
199 else
200 {
201 strcat(szFullName, szFileName + 1);
202 }
203
204 szShortName = strrchr(szFileName, '\\');
205 if (szShortName == NULL)
206 szShortName = szFileName;
207 else
208 szShortName = szShortName + 1;
209
210
211 FilePointer = FsOpenFile(szFullName);
212 if (FilePointer == NULL)
213 {
214 printf("Could not find %s\n", szFileName);
215 return(FALSE);
216 }
217
218 /*
219 * Update the status bar with the current file
220 */
221 #ifdef USE_UI
222 sprintf(szBuffer, "Reading %s", szShortName);
223 UiDrawStatusText(szBuffer);
224 #else
225 printf("Reading %s\n", szShortName);
226 #endif
227
228 /* Load the driver */
229 MultiBootLoadModule(FilePointer, szModuleName, NULL);
230
231 return(TRUE);
232 }
233
234
235 VOID RunLoader(VOID)
236 {
237 PVOID Base;
238 U32 Size;
239 char *SourcePath;
240 char *LoadOptions;
241
242 HINF InfHandle;
243 U32 ErrorLine;
244 INFCONTEXT InfContext;
245
246 /* Setup multiboot information structure */
247 mb_info.flags = MB_INFO_FLAG_MEM_SIZE | MB_INFO_FLAG_BOOT_DEVICE | MB_INFO_FLAG_COMMAND_LINE | MB_INFO_FLAG_MODULES;
248 mb_info.mem_lower = GetConventionalMemorySize();
249 mb_info.mem_upper = GetExtendedMemorySize();
250 mb_info.boot_device = 0xffffffff;
251 mb_info.cmdline = (unsigned long)multiboot_kernel_cmdline;
252 mb_info.mods_count = 0;
253 mb_info.mods_addr = (unsigned long)multiboot_modules;
254 mb_info.mmap_length = (unsigned long)GetBiosMemoryMap((PBIOS_MEMORY_MAP)&multiboot_memory_map, 32) * sizeof(memory_map_t);
255 if (mb_info.mmap_length)
256 {
257 mb_info.mmap_addr = (unsigned long)&multiboot_memory_map;
258 mb_info.flags |= MB_INFO_FLAG_MEMORY_MAP;
259 multiboot_memory_map_descriptor_size = sizeof(memory_map_t); // GetBiosMemoryMap uses a fixed value of 24
260 #if 0
261 {
262 int i;
263 printf("memory map length: %d\n", mb_info.mmap_length);
264 printf("dumping memory map:\n");
265 for (i=0; i<(mb_info.mmap_length / sizeof(memory_map_t)); i++)
266 {
267 printf("start: %x\t size: %x\t type %d\n",
268 multiboot_memory_map[i].base_addr_low,
269 multiboot_memory_map[i].length_low,
270 multiboot_memory_map[i].type);
271 }
272 getch();
273 }
274 #endif
275 }
276 #if 0
277 printf("low_mem = %d\n", mb_info.mem_lower);
278 printf("high_mem = %d\n", mb_info.mem_upper);
279 getch();
280 #endif
281
282 #ifdef USE_UI
283 UiInitialize();
284 UiDrawStatusText("");
285 #endif
286
287 /* Initialize registry */
288 RegInitializeRegistry();
289
290 /* Detect hardware */
291 #ifdef USE_UI
292 UiDrawStatusText("Detecting hardware...");
293 #else
294 printf("Detecting hardware...\n\n");
295 #endif
296 DetectHardware();
297 #ifdef USE_UI
298 UiDrawStatusText("");
299 #endif
300
301 /* set boot drive and partition */
302 ((char *)(&mb_info.boot_device))[0] = (char)BootDrive;
303 ((char *)(&mb_info.boot_device))[1] = (char)BootPartition;
304
305
306 /* Open boot drive */
307 if (!FsOpenVolume(BootDrive, BootPartition))
308 {
309 #ifdef USE_UI
310 UiMessageBox("Failed to open boot drive.");
311 #else
312 printf("Failed to open boot drive.");
313 #endif
314 return;
315 }
316
317 /* Open 'txtsetup.sif' */
318 if (!InfOpenFile (&InfHandle,
319 (BootDrive < 0x80) ? "\\txtsetup.sif" : "\\reactos\\txtsetup.sif",
320 &ErrorLine))
321 {
322 printf("Failed to open 'txtsetup.sif'\n");
323 return;
324 }
325
326 /* Get load options */
327 if (!InfFindFirstLine (InfHandle,
328 "SetupData",
329 "OsLoadOptions",
330 &InfContext))
331 {
332 printf("Failed to find 'SetupData/OsLoadOptions'\n");
333 return;
334 }
335
336 if (!InfGetDataField (&InfContext,
337 1,
338 &LoadOptions))
339 {
340 printf("Failed to get load options\n");
341 return;
342 }
343 #if 0
344 printf("LoadOptions: '%s'\n", LoadOptions);
345 #endif
346
347 if (BootDrive < 0x80)
348 {
349 /* Boot from floppy disk */
350 SourcePath = "\\";
351 }
352 else
353 {
354 /* Boot from cdrom */
355 SourcePath = "\\reactos";
356 }
357
358 /* Set kernel command line */
359 sprintf(multiboot_kernel_cmdline,
360 "multi(0)disk(0)%s(%u)%s %s",
361 (BootDrive < 0x80) ? "fdisk" : "cdrom",
362 (unsigned int)BootDrive,
363 SourcePath,
364 LoadOptions);
365
366 /* Load ntoskrnl.exe */
367 if (!LoadKernel(SourcePath, "ntoskrnl.exe"))
368 return;
369
370
371 /* Load hal.dll */
372 if (!LoadDriver(SourcePath, "hal.dll"))
373 return;
374
375
376 /* Export the hardware hive */
377 Base = MultiBootCreateModule ("HARDWARE");
378 RegExportBinaryHive ("\\Registry\\Machine\\HARDWARE", Base, &Size);
379 MultiBootCloseModule (Base, Size);
380
381 #if 0
382 printf("Base: %x\n", Base);
383 printf("Size: %u\n", Size);
384 printf("*** System stopped ***\n");
385 for(;;);
386 #endif
387
388 /* Insert boot disk 2 */
389 if (BootDrive < 0x80)
390 {
391 #ifdef USE_UI
392 UiMessageBox("Please insert \"ReactOS Boot Disk 2\" and press ENTER");
393 #else
394 printf("\n\n Please insert \"ReactOS Boot Disk 2\" and press ENTER\n");
395 getch();
396 #endif
397
398 /* Open boot drive */
399 if (!FsOpenVolume(BootDrive, BootPartition))
400 {
401 #ifdef USE_UI
402 UiMessageBox("Failed to open boot drive.");
403 #else
404 printf("Failed to open boot drive.");
405 #endif
406 return;
407 }
408
409 /* FIXME: check volume label or disk marker file */
410 }
411
412
413 /* Get ANSI codepage file */
414 if (!InfFindFirstLine (InfHandle,
415 "NLS",
416 "AnsiCodepage",
417 &InfContext))
418 {
419 printf("Failed to find 'NLS/AnsiCodepage'\n");
420 return;
421 }
422
423 if (!InfGetDataField (&InfContext,
424 1,
425 &LoadOptions))
426 {
427 printf("Failed to get load options\n");
428 return;
429 }
430
431 /* Load ANSI codepage file */
432 if (!LoadNlsFile(SourcePath, LoadOptions, "ansi.nls"))
433 {
434 #ifdef USE_UI
435 UiMessageBox("Failed to load the ANSI codepage file.");
436 #else
437 printf("Failed to load the ANSI codepage file.");
438 #endif
439 return;
440 }
441
442 /* Get OEM codepage file */
443 if (!InfFindFirstLine (InfHandle,
444 "NLS",
445 "OemCodepage",
446 &InfContext))
447 {
448 printf("Failed to find 'NLS/AnsiCodepage'\n");
449 return;
450 }
451
452 if (!InfGetDataField (&InfContext,
453 1,
454 &LoadOptions))
455 {
456 printf("Failed to get load options\n");
457 return;
458 }
459
460 /* Load OEM codepage file */
461 if (!LoadNlsFile(SourcePath, LoadOptions, "oem.nls"))
462 {
463 #ifdef USE_UI
464 UiMessageBox("Failed to load the OEM codepage file.");
465 #else
466 printf("Failed to load the OEM codepage file.");
467 #endif
468 return;
469 }
470
471 /* Get Unicode Casemap file */
472 if (!InfFindFirstLine (InfHandle,
473 "NLS",
474 "UnicodeCasetable",
475 &InfContext))
476 {
477 printf("Failed to find 'NLS/AnsiCodepage'\n");
478 return;
479 }
480
481 if (!InfGetDataField (&InfContext,
482 1,
483 &LoadOptions))
484 {
485 printf("Failed to get load options\n");
486 return;
487 }
488
489 /* Load Unicode casemap file */
490 if (!LoadNlsFile(SourcePath, LoadOptions, "casemap.nls"))
491 {
492 #ifdef USE_UI
493 UiMessageBox("Failed to load the Unicode casemap file.");
494 #else
495 printf("Failed to load the Unicode casemap file.");
496 #endif
497 return;
498 }
499
500
501 /* Load drivers */
502 if (BootDrive < 0x80)
503 {
504 /*
505 * Load floppy.sys
506 */
507 if (!LoadDriver(SourcePath, "floppy.sys"))
508 return;
509
510 /*
511 * Load vfatfs.sys (could be loaded by the setup prog!)
512 */
513 if (!LoadDriver(SourcePath, "vfatfs.sys"))
514 return;
515 }
516 else
517 {
518 /*
519 * Load scsiport.sys
520 */
521 if (!LoadDriver(SourcePath, "scsiport.sys"))
522 return;
523
524 /*
525 * Load atapi.sys (depends on hardware detection)
526 */
527 if (!LoadDriver(SourcePath, "atapi.sys"))
528 return;
529
530 /*
531 * Load class2.sys
532 */
533 if (!LoadDriver(SourcePath, "class2.sys"))
534 return;
535
536 /*
537 * Load cdrom.sys
538 */
539 if (!LoadDriver(SourcePath, "cdrom.sys"))
540 return;
541
542 /*
543 * Load cdfs.sys
544 */
545 if (!LoadDriver(SourcePath, "cdfs.sys"))
546 return;
547
548 /*
549 * Load disk.sys
550 */
551 if (!LoadDriver(SourcePath, "disk.sys"))
552 return;
553
554 /*
555 * Load vfatfs.sys (could be loaded by the setup prog!)
556 */
557 if (!LoadDriver(SourcePath, "vfatfs.sys"))
558 return;
559 }
560
561
562 /*
563 * Load keyboard driver
564 */
565 if (!LoadDriver(SourcePath, "keyboard.sys"))
566 return;
567
568 /*
569 * Load screen driver
570 */
571 if (!LoadDriver(SourcePath, "blue.sys"))
572 return;
573
574 #ifdef USE_UI
575 UiUnInitialize("Booting ReactOS...");
576 #endif
577
578 /*
579 * Now boot the kernel
580 */
581 DiskStopFloppyMotor();
582 boot_reactos();
583 }
584
585 /* EOF */