Handle multi-string group order list properly.
[reactos.git] / freeldr / freeldr / reactos / reactos.c
1 /*
2 * FreeLoader
3 *
4 * Copyright (C) 1998-2002 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 <reactos.h>
25 #include <rtl.h>
26 #include <fs.h>
27 #include <ui.h>
28 #include <multiboot.h>
29 #include <mm.h>
30 #include <inifile.h>
31
32 #include "registry.h"
33 #include "hwdetect.h"
34
35
36 #define NDEBUG
37
38
39 static BOOL
40 LoadKernel(PCHAR szFileName, int nPos)
41 {
42 PFILE FilePointer;
43 PCHAR szShortName;
44 char szBuffer[256];
45
46 szShortName = strrchr(szFileName, '\\');
47 if (szShortName == NULL)
48 szShortName = szFileName;
49 else
50 szShortName = szShortName + 1;
51
52 FilePointer = OpenFile(szFileName);
53 if (FilePointer == NULL)
54 {
55 strcpy(szBuffer, szShortName);
56 strcat(szBuffer, " not found.");
57 UiMessageBox(szBuffer);
58 return(FALSE);
59 }
60
61 /*
62 * Update the status bar with the current file
63 */
64 strcpy(szBuffer, "Reading ");
65 strcat(szBuffer, szShortName);
66 UiDrawStatusText(szBuffer);
67
68 /*
69 * Load the kernel
70 */
71 MultiBootLoadKernel(FilePointer);
72
73 UiDrawProgressBarCenter(nPos, 100);
74
75 return(TRUE);
76 }
77
78
79 static BOOL
80 LoadDriver(PCHAR szFileName, int nPos)
81 {
82 PFILE FilePointer;
83 char value[256];
84 char *p;
85
86 FilePointer = OpenFile(szFileName);
87 if (FilePointer == NULL)
88 {
89 strcpy(value, szFileName);
90 strcat(value, " not found.");
91 UiMessageBox(value);
92 return(FALSE);
93 }
94
95 /*
96 * Update the status bar with the current file
97 */
98 strcpy(value, "Reading ");
99 p = strrchr(szFileName, '\\');
100 if (p == NULL)
101 strcat(value, szFileName);
102 else
103 strcat(value, p + 1);
104 UiDrawStatusText(value);
105
106 /*
107 * Load the driver
108 */
109 MultiBootLoadModule(FilePointer, szFileName, NULL);
110
111 UiDrawProgressBarCenter(nPos, 100);
112
113 return(TRUE);
114 }
115
116
117 #if 0
118 static BOOL
119 LoadNlsFile(PCHAR szFileName, PCHAR szModuleName)
120 {
121 PFILE FilePointer;
122 char value[256];
123 char *p;
124
125 FilePointer = OpenFile(szFileName);
126 if (FilePointer == NULL)
127 {
128 strcpy(value, szFileName);
129 strcat(value, " not found.");
130 UiMessageBox(value);
131 return(FALSE);
132 }
133
134 /*
135 * Update the status bar with the current file
136 */
137 strcpy(value, "Reading ");
138 p = strrchr(szFileName, '\\');
139 if (p == NULL)
140 strcat(value, szFileName);
141 else
142 strcat(value, p + 1);
143 UiDrawStatusText(value);
144
145 /*
146 * Load the driver
147 */
148 MultiBootLoadModule(FilePointer, szModuleName, NULL);
149
150 return(TRUE);
151 }
152 #endif
153
154
155 static VOID
156 LoadBootDrivers(PCHAR szSystemRoot, int nPos)
157 {
158 LONG rc = 0;
159 HKEY hGroupKey, hServiceKey, hDriverKey;
160 char ValueBuffer[256];
161 char ServiceName[256];
162 ULONG BufferSize;
163 ULONG Index;
164 char *GroupName;
165
166 ULONG ValueSize;
167 ULONG ValueType;
168 ULONG StartValue;
169 UCHAR DriverGroup[256];
170 ULONG DriverGroupSize;
171
172 UCHAR ImagePath[256];
173
174 /* get 'service group order' key */
175 rc = RegOpenKey(NULL,
176 "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ServiceGroupOrder",
177 &hGroupKey);
178 // printf("RegOpenKey(): rc %d\n", (int)rc);
179 if (rc != ERROR_SUCCESS)
180 return;
181
182 /* enumerate drivers */
183 rc = RegOpenKey(NULL,
184 "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services",
185 &hServiceKey);
186 // printf("RegOpenKey(): rc %d\n", (int)rc);
187 if (rc != ERROR_SUCCESS)
188 return;
189
190 // printf("hKey: %x\n", (int)hKey);
191
192 BufferSize = 256;
193 rc = RegQueryValue(hGroupKey, "List", NULL, (PUCHAR)ValueBuffer, &BufferSize);
194 // printf("RegQueryValue(): rc %d\n", (int)rc);
195 if (rc != ERROR_SUCCESS)
196 return;
197
198
199 // printf("BufferSize: %d \n", (int)BufferSize);
200
201 // printf("ValueBuffer: '%s' \n", ValueBuffer);
202
203 GroupName = ValueBuffer;
204 while (*GroupName)
205 {
206 // printf("Driver group: '%s'\n", GroupName);
207
208 /* enumerate all drivers */
209 Index = 0;
210 while (TRUE)
211 {
212 ValueSize = 256;
213 rc = RegEnumKey(hServiceKey, Index, ServiceName, &ValueSize);
214 // printf("RegEnumKey(): rc %d\n", (int)rc);
215 if (rc == ERROR_NO_MORE_ITEMS)
216 break;
217 if (rc != ERROR_SUCCESS)
218 return;
219 // printf("Service %d: '%s'\n", (int)Index, ServiceName);
220
221 /* open driver Key */
222 rc = RegOpenKey(hServiceKey, ServiceName, &hDriverKey);
223
224 ValueSize = sizeof(ULONG);
225 rc = RegQueryValue(hDriverKey, "Start", &ValueType, (PUCHAR)&StartValue, &ValueSize);
226 // printf(" Start: %x \n", (int)StartValue);
227
228 DriverGroupSize = 256;
229 rc = RegQueryValue(hDriverKey, "Group", NULL, (PUCHAR)DriverGroup, &DriverGroupSize);
230 // printf(" Group: %s \n", DriverGroup);
231
232 if ((StartValue == 0) && (stricmp(DriverGroup, GroupName) == 0))
233 {
234 ValueSize = 256;
235 rc = RegQueryValue(hDriverKey,
236 "ImagePathName",
237 NULL,
238 (PUCHAR)ImagePath,
239 &ValueSize);
240 if (rc != ERROR_SUCCESS)
241 {
242 // printf(" ImagePath: not found\n");
243 strcpy(ImagePath, szSystemRoot);
244 strcat(ImagePath, "system32\\drivers\\");
245 strcat(ImagePath, ServiceName);
246 strcat(ImagePath, ".sys");
247 }
248 else
249 {
250 // printf(" ImagePath: '%s'\n", ImagePath);
251 }
252 // printf(" Loading driver: '%s'\n", ImagePath);
253
254 if (nPos < 100)
255 nPos += 5;
256
257 LoadDriver(ImagePath, nPos);
258 }
259 Index++;
260 }
261
262 GroupName = GroupName + strlen(GroupName) + 1;
263 }
264 }
265
266
267 #if 0
268 static BOOL
269 LoadNlsFiles(PCHAR szSystemRoot)
270 {
271 LONG rc = ERROR_SUCCESS;
272 HKEY hKey;
273 char szIdBuffer[80];
274 char szNameBuffer[80];
275 char szFileName[256];
276 ULONG BufferSize;
277
278 /* open the codepage key */
279 rc = RegOpenKey(NULL,
280 "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage",
281 &hKey);
282 if (rc != ERROR_SUCCESS)
283 return(FALSE);
284
285
286 /* get ANSI codepage */
287 BufferSize = 80;
288 rc = RegQueryValue(hKey, "ACP", NULL, (PUCHAR)szIdBuffer, &BufferSize);
289 if (rc != ERROR_SUCCESS)
290 return(FALSE);
291
292 BufferSize = 80;
293 rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)szNameBuffer, &BufferSize);
294 if (rc != ERROR_SUCCESS)
295 return(FALSE);
296
297
298 /* load ANSI codepage table */
299 strcpy(szFileName, szSystemRoot);
300 strcat(szFileName, "system32\\");
301 strcat(szFileName, szNameBuffer);
302 if (!LoadNlsFile(szFileName, "ANSI.NLS"))
303 return(FALSE);
304
305
306 /* get OEM codepage */
307 BufferSize = 80;
308 rc = RegQueryValue(hKey, "OEMCP", NULL, (PUCHAR)szIdBuffer, &BufferSize);
309 if (rc != ERROR_SUCCESS)
310 return(FALSE);
311
312 BufferSize = 80;
313 rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)szNameBuffer, &BufferSize);
314 if (rc != ERROR_SUCCESS)
315 return(FALSE);
316
317 /* load OEM codepage table */
318 strcpy(szFileName, szSystemRoot);
319 strcat(szFileName, "system32\\");
320 strcat(szFileName, szNameBuffer);
321 if (!LoadNlsFile(szFileName, "OEM.NLS"))
322 return(FALSE);
323
324
325 /* open the language key */
326 rc = RegOpenKey(NULL,
327 "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\Language",
328 &hKey);
329 if (rc != ERROR_SUCCESS)
330 return(FALSE);
331
332
333 /* get the Unicode case table */
334 BufferSize = 80;
335 rc = RegQueryValue(hKey, "Default", NULL, (PUCHAR)szIdBuffer, &BufferSize);
336 if (rc != ERROR_SUCCESS)
337 return(FALSE);
338
339 BufferSize = 80;
340 rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)szNameBuffer, &BufferSize);
341 if (rc != ERROR_SUCCESS)
342 return(FALSE);
343
344 /* load Unicode case table */
345 strcpy(szFileName, szSystemRoot);
346 strcat(szFileName, "system32\\");
347 strcat(szFileName, szNameBuffer);
348 if (!LoadNlsFile(szFileName, "UNICASE.NLS"))
349 return(FALSE);
350
351 return(TRUE);
352 }
353 #endif
354
355
356 void
357 LoadAndBootReactOS(PUCHAR OperatingSystemName)
358 {
359 PFILE FilePointer;
360 char name[1024];
361 char value[1024];
362 char szFileName[1024];
363 char szBootPath[256];
364 // int i;
365 // int nNumDriverFiles=0;
366 // int nNumFilesLoaded=0;
367 char MsgBuffer[256];
368 ULONG SectionId;
369
370 char* Base;
371 ULONG Size;
372
373 //
374 // Open the operating system section
375 // specified in the .ini file
376 //
377 if (!IniOpenSection(OperatingSystemName, &SectionId))
378 {
379 sprintf(MsgBuffer,"Operating System section '%s' not found in freeldr.ini", OperatingSystemName);
380 UiMessageBox(MsgBuffer);
381 return;
382 }
383
384 /*
385 * Setup multiboot information structure
386 */
387 mb_info.flags = MB_INFO_FLAG_MEM_SIZE | MB_INFO_FLAG_BOOT_DEVICE | MB_INFO_FLAG_COMMAND_LINE | MB_INFO_FLAG_MODULES;
388 mb_info.mem_lower = GetConventionalMemorySize();
389 mb_info.mem_upper = GetExtendedMemorySize();
390 mb_info.boot_device = 0xffffffff;
391 mb_info.cmdline = (unsigned long)multiboot_kernel_cmdline;
392 mb_info.mods_count = 0;
393 mb_info.mods_addr = (unsigned long)multiboot_modules;
394 mb_info.mmap_length = GetBiosMemoryMap(&multiboot_memory_map);
395 if (mb_info.mmap_length)
396 {
397 mb_info.mmap_addr = (unsigned long)&multiboot_memory_map;
398 mb_info.flags |= MB_INFO_FLAG_MEMORY_MAP;
399 //printf("memory map length: %d\n", mb_info.mmap_length);
400 //printf("dumping memory map:\n");
401 //for (i=0; i<(mb_info.mmap_length / 4); i++)
402 //{
403 // printf("0x%x\n", ((unsigned long *)&multiboot_memory_map)[i]);
404 //}
405 //getch();
406 }
407 //printf("low_mem = %d\n", mb_info.mem_lower);
408 //printf("high_mem = %d\n", mb_info.mem_upper);
409 //getch();
410
411 /*
412 * Make sure the system path is set in the .ini file
413 */
414 if (!IniReadSettingByName(SectionId, "SystemPath", value, 1024))
415 {
416 UiMessageBox("System path not specified for selected operating system.");
417 return;
418 }
419
420 /*
421 * Verify system path
422 */
423 if (!DissectArcPath(value, szBootPath, &BootDrive, &BootPartition))
424 {
425 sprintf(MsgBuffer,"Invalid system path: '%s'", value);
426 UiMessageBox(MsgBuffer);
427 return;
428 }
429
430 /* set boot drive and partition */
431 ((char *)(&mb_info.boot_device))[0] = (char)BootDrive;
432 ((char *)(&mb_info.boot_device))[1] = (char)BootPartition;
433
434 /* copy ARC path into kernel command line */
435 strcpy(multiboot_kernel_cmdline, value);
436
437 /*
438 * Read the optional kernel parameters (if any)
439 */
440 if (IniReadSettingByName(SectionId, "Options", value, 1024))
441 {
442 strcat(multiboot_kernel_cmdline, " ");
443 strcat(multiboot_kernel_cmdline, value);
444 }
445
446 /* append a backslash */
447 if ((strlen(szBootPath)==0) ||
448 szBootPath[strlen(szBootPath)] != '\\')
449 strcat(szBootPath, "\\");
450
451 DebugPrint(DPRINT_REACTOS,"SystemRoot: '%s'", szBootPath);
452
453 UiDrawBackdrop();
454
455 UiDrawStatusText("Loading...");
456 UiDrawProgressBarCenter(0, 100);
457
458 /*
459 * Try to open boot drive
460 */
461 if (!OpenDiskDrive(BootDrive, BootPartition))
462 {
463 UiMessageBox("Failed to open boot drive.");
464 return;
465 }
466
467 /*
468 * Find the kernel image name
469 * and try to load the kernel off the disk
470 */
471 if(IniReadSettingByName(SectionId, "Kernel", value, 1024))
472 {
473 /*
474 * Set the name and
475 */
476 if (value[0] == '\\')
477 {
478 strcpy(szFileName, value);
479 }
480 else
481 {
482 strcpy(szFileName, szBootPath);
483 strcat(szFileName, "SYSTEM32\\");
484 strcat(szFileName, value);
485 }
486 }
487 else
488 {
489 strcpy(value, "NTOSKRNL.EXE");
490 strcpy(szFileName, szBootPath);
491 strcat(szFileName, "SYSTEM32\\");
492 strcat(szFileName, value);
493 }
494
495 if (!LoadKernel(szFileName, 5))
496 return;
497
498 /*
499 * Find the HAL image name
500 * and try to load the kernel off the disk
501 */
502 if(IniReadSettingByName(SectionId, "Hal", value, 1024))
503 {
504 /*
505 * Set the name and
506 */
507 if (value[0] == '\\')
508 {
509 strcpy(szFileName, value);
510 }
511 else
512 {
513 strcpy(szFileName, szBootPath);
514 strcat(szFileName, "SYSTEM32\\");
515 strcat(szFileName, value);
516 }
517 }
518 else
519 {
520 strcpy(value, "HAL.DLL");
521 strcpy(szFileName, szBootPath);
522 strcat(szFileName, "SYSTEM32\\");
523 strcat(szFileName, value);
524 }
525
526 if (!LoadDriver(szFileName, 10))
527 return;
528
529 /*
530 * Find the System hive image name
531 * and try to load it off the disk
532 */
533 if(IniReadSettingByName(SectionId, "SystemHive", value, 1024))
534 {
535 /*
536 * Set the name and
537 */
538 if (value[0] == '\\')
539 {
540 strcpy(szFileName, value);
541 }
542 else
543 {
544 strcpy(szFileName, szBootPath);
545 strcat(szFileName, "SYSTEM32\\CONFIG\\");
546 strcat(szFileName, value);
547 }
548 }
549 else
550 {
551 strcpy(value, "SYSTEM.HIV");
552 strcpy(szFileName, szBootPath);
553 strcat(szFileName, "SYSTEM32\\CONFIG\\");
554 strcat(szFileName, value);
555 }
556
557 DebugPrint(DPRINT_REACTOS, "SystemHive: '%s'", szFileName);
558
559 FilePointer = OpenFile(szFileName);
560 if (FilePointer == NULL)
561 {
562 strcat(value, " not found.");
563 UiMessageBox(value);
564 return;
565 }
566
567 /*
568 * Update the status bar with the current file
569 */
570 strcpy(name, "Reading ");
571 strcat(name, value);
572 while (strlen(name) < 80)
573 strcat(name, " ");
574 UiDrawStatusText(name);
575
576 /*
577 * Load the system hive
578 */
579 Base = MultiBootLoadModule(FilePointer, szFileName, &Size);
580 RegInitializeRegistry();
581 RegImportHive(Base, Size);
582
583 UiDrawProgressBarCenter(15, 100);
584
585 DebugPrint(DPRINT_REACTOS, "SystemHive loaded at 0x%x size %u", (unsigned)Base, (unsigned)Size);
586
587 /*
588 * Retrieve hardware information and create the hardware hive
589 */
590 DetectHardware();
591 #if 0
592 Base = MultiBootCreateModule(HARDWARE.HIV);
593 RegExportHive("\\Registry\\Machine\\HARDWARE", Base, &Size);
594 MultiBootCloseModule(Base, Size);
595 #endif
596 UiDrawProgressBarCenter(20, 100);
597
598 /*
599 * Load NLS files
600 */
601 #if 0
602 if (!LoadNlsFiles(szBootPath))
603 {
604 MessageBox("Failed to load NLS files\n");
605 return;
606 }
607 #endif
608
609 UiDrawProgressBarCenter(25, 100);
610
611 /*
612 * Load boot drivers
613 */
614 LoadBootDrivers(szBootPath, 25);
615
616
617 /*
618 * Clear the screen and redraw the backdrop and status bar
619 */
620 UiDrawBackdrop();
621 UiDrawStatusText("Press any key to boot");
622
623 /*
624 * Wait for user
625 */
626 strcpy(name, "Kernel and Drivers loaded.\nPress any key to boot ");
627 strcat(name, OperatingSystemName);
628 strcat(name, ".");
629 //MessageBox(name);
630
631 /*
632 * Now boot the kernel
633 */
634 StopFloppyMotor();
635 boot_reactos();
636 }
637