4 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
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.
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.
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.
29 #include <multiboot.h>
38 #define IsRecognizedPartition(P) \
39 ((P) == PARTITION_FAT_12 || \
40 (P) == PARTITION_FAT_16 || \
41 (P) == PARTITION_HUGE || \
42 (P) == PARTITION_IFS || \
43 (P) == PARTITION_FAT32 || \
44 (P) == PARTITION_FAT32_XINT13 || \
45 (P) == PARTITION_XINT13)
48 LoadKernel(PCHAR szFileName
, int nPos
)
54 szShortName
= strrchr(szFileName
, '\\');
55 if (szShortName
== NULL
)
56 szShortName
= szFileName
;
58 szShortName
= szShortName
+ 1;
60 FilePointer
= FsOpenFile(szFileName
);
61 if (FilePointer
== NULL
)
63 strcpy(szBuffer
, szShortName
);
64 strcat(szBuffer
, " not found.");
65 UiMessageBox(szBuffer
);
70 * Update the status bar with the current file
72 strcpy(szBuffer
, "Reading ");
73 strcat(szBuffer
, szShortName
);
74 UiDrawStatusText(szBuffer
);
79 MultiBootLoadKernel(FilePointer
);
81 UiDrawProgressBarCenter(nPos
, 100, "Loading ReactOS...");
87 LoadSymbolFile(PCHAR szSystemRoot
,
91 CHAR SymbolFileName
[1024];
99 /* Get the path to the symbol store */
100 strcpy(SymbolFileName
, szSystemRoot
);
101 strcat(SymbolFileName
, "symbols\\");
103 /* Get the symbol filename from the module name */
104 Start
= strrchr(ModuleName
, '\\');
110 Ext
= strrchr(ModuleName
, '.');
112 Length
= Ext
- Start
;
114 Length
= strlen(Start
);
116 strncat(SymbolFileName
, Start
, Length
);
117 strcat(SymbolFileName
, ".sym");
119 FilePointer
= FsOpenFile((PCHAR
)&SymbolFileName
[0]);
120 if (FilePointer
== NULL
)
122 DbgPrint((DPRINT_REACTOS
, "Symbol file %s not loaded.\n", SymbolFileName
));
123 /* This is not critical */
127 DbgPrint((DPRINT_REACTOS
, "Symbol file %s is loaded.\n", SymbolFileName
));
130 * Update the status bar with the current file
132 strcpy(value
, "Reading ");
133 p
= strrchr(SymbolFileName
, '\\');
135 strcat(value
, SymbolFileName
);
137 strcat(value
, p
+ 1);
138 UiDrawStatusText(value
);
141 * Load the symbol file
143 MultiBootLoadModule(FilePointer
, SymbolFileName
, NULL
);
145 UiDrawProgressBarCenter(nPos
, 100, "Loading ReactOS...");
152 LoadDriver(PCHAR szFileName
, int nPos
)
158 FilePointer
= FsOpenFile(szFileName
);
159 if (FilePointer
== NULL
)
161 strcpy(value
, szFileName
);
162 strcat(value
, " not found.");
168 * Update the status bar with the current file
170 strcpy(value
, "Reading ");
171 p
= strrchr(szFileName
, '\\');
173 strcat(value
, szFileName
);
175 strcat(value
, p
+ 1);
176 UiDrawStatusText(value
);
181 MultiBootLoadModule(FilePointer
, szFileName
, NULL
);
183 UiDrawProgressBarCenter(nPos
, 100, "Loading ReactOS...");
190 LoadNlsFile(PCHAR szFileName
, PCHAR szModuleName
)
196 FilePointer
= FsOpenFile(szFileName
);
197 if (FilePointer
== NULL
)
199 strcpy(value
, szFileName
);
200 strcat(value
, " not found.");
206 * Update the status bar with the current file
208 strcpy(value
, "Reading ");
209 p
= strrchr(szFileName
, '\\');
211 strcat(value
, szFileName
);
213 strcat(value
, p
+ 1);
214 UiDrawStatusText(value
);
219 MultiBootLoadModule(FilePointer
, szModuleName
, NULL
);
226 LoadBootDrivers(PCHAR szSystemRoot
, int nPos
)
229 HKEY hGroupKey
, hServiceKey
, hDriverKey
;
230 char ValueBuffer
[512];
231 char ServiceName
[256];
239 UCHAR DriverGroup
[256];
242 UCHAR ImagePath
[256];
243 UCHAR TempImagePath
[256];
245 /* get 'service group order' key */
246 rc
= RegOpenKey(NULL
,
247 "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ServiceGroupOrder",
249 if (rc
!= ERROR_SUCCESS
)
251 DbgPrint((DPRINT_REACTOS
, "Failed to open the 'ServiceGroupOrder key (rc %d)\n", (int)rc
));
255 /* enumerate drivers */
256 rc
= RegOpenKey(NULL
,
257 "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services",
259 if (rc
!= ERROR_SUCCESS
)
261 DbgPrint((DPRINT_REACTOS
, "Failed to open the 'Services' key (rc %d)\n", (int)rc
));
265 BufferSize
= sizeof(ValueBuffer
);
266 rc
= RegQueryValue(hGroupKey
, "List", NULL
, (PUCHAR
)ValueBuffer
, &BufferSize
);
267 DbgPrint((DPRINT_REACTOS
, "RegQueryValue(): rc %d\n", (int)rc
));
268 if (rc
!= ERROR_SUCCESS
)
271 DbgPrint((DPRINT_REACTOS
, "BufferSize: %d \n", (int)BufferSize
));
273 DbgPrint((DPRINT_REACTOS
, "ValueBuffer: '%s' \n", ValueBuffer
));
275 GroupName
= ValueBuffer
;
278 DbgPrint((DPRINT_REACTOS
, "Driver group: '%s'\n", GroupName
));
280 /* enumerate all drivers */
284 ValueSize
= sizeof(ValueBuffer
);
285 rc
= RegEnumKey(hServiceKey
, Index
, ServiceName
, &ValueSize
);
286 DbgPrint((DPRINT_REACTOS
, "RegEnumKey(): rc %d\n", (int)rc
));
287 if (rc
== ERROR_NO_MORE_ITEMS
)
289 if (rc
!= ERROR_SUCCESS
)
291 DbgPrint((DPRINT_REACTOS
, "Service %d: '%s'\n", (int)Index
, ServiceName
));
293 /* open driver Key */
294 rc
= RegOpenKey(hServiceKey
, ServiceName
, &hDriverKey
);
296 ValueSize
= sizeof(U32
);
297 rc
= RegQueryValue(hDriverKey
, "Start", &ValueType
, (PUCHAR
)&StartValue
, &ValueSize
);
298 DbgPrint((DPRINT_REACTOS
, " Start: %x \n", (int)StartValue
));
300 DriverGroupSize
= 256;
301 rc
= RegQueryValue(hDriverKey
, "Group", NULL
, (PUCHAR
)DriverGroup
, &DriverGroupSize
);
302 DbgPrint((DPRINT_REACTOS
, " Group: '%s' \n", DriverGroup
));
304 if ((StartValue
== 0) && (stricmp(DriverGroup
, GroupName
) == 0))
307 rc
= RegQueryValue(hDriverKey
,
310 (PUCHAR
)TempImagePath
,
312 if (rc
!= ERROR_SUCCESS
)
314 DbgPrint((DPRINT_REACTOS
, " ImagePath: not found\n"));
315 strcpy(ImagePath
, szSystemRoot
);
316 strcat(ImagePath
, "system32\\drivers\\");
317 strcat(ImagePath
, ServiceName
);
318 strcat(ImagePath
, ".sys");
320 else if (TempImagePath
[0] != '\\')
322 strcpy(ImagePath
, szSystemRoot
);
323 strcat(ImagePath
, TempImagePath
);
327 strcpy(ImagePath
, TempImagePath
);
328 DbgPrint((DPRINT_REACTOS
, " ImagePath: '%s'\n", ImagePath
));
330 DbgPrint((DPRINT_REACTOS
, " Loading driver: '%s'\n", ImagePath
));
335 LoadDriver(ImagePath
, nPos
);
336 LoadSymbolFile(szSystemRoot
, ImagePath
, nPos
);
340 DbgPrint((DPRINT_REACTOS
, " Skipping driver '%s' with Start %d and Group '%s' (Current group '%s')\n",
341 ImagePath
, StartValue
, DriverGroup
, GroupName
));
346 GroupName
= GroupName
+ strlen(GroupName
) + 1;
352 LoadNlsFiles(PCHAR szSystemRoot
, PCHAR szErrorOut
)
354 S32 rc
= ERROR_SUCCESS
;
357 char szNameBuffer
[80];
358 char szFileName
[256];
361 /* open the codepage key */
362 rc
= RegOpenKey(NULL
,
363 "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage",
365 if (rc
!= ERROR_SUCCESS
) {
366 strcpy(szErrorOut
, "Couldn't open CodePage registry key");
371 /* get ANSI codepage */
373 rc
= RegQueryValue(hKey
, "ACP", NULL
, (PUCHAR
)szIdBuffer
, &BufferSize
);
374 if (rc
!= ERROR_SUCCESS
) {
375 strcpy(szErrorOut
, "Couldn't get ACP NLS setting");
380 rc
= RegQueryValue(hKey
, szIdBuffer
, NULL
, (PUCHAR
)szNameBuffer
, &BufferSize
);
381 if (rc
!= ERROR_SUCCESS
) {
382 strcpy(szErrorOut
, "ACP NLS Setting exists, but isn't readable");
386 /* load ANSI codepage table */
387 strcpy(szFileName
, szSystemRoot
);
388 strcat(szFileName
, "system32\\");
389 strcat(szFileName
, szNameBuffer
);
390 DbgPrint((DPRINT_REACTOS
, "ANSI file: %s\n", szFileName
));
391 if (!LoadNlsFile(szFileName
, "ansi.nls")) {
392 strcpy(szErrorOut
, "Couldn't load ansi.nls");
396 /* get OEM codepage */
398 rc
= RegQueryValue(hKey
, "OEMCP", NULL
, (PUCHAR
)szIdBuffer
, &BufferSize
);
399 if (rc
!= ERROR_SUCCESS
) {
400 strcpy(szErrorOut
, "Couldn't get OEMCP NLS setting");
405 rc
= RegQueryValue(hKey
, szIdBuffer
, NULL
, (PUCHAR
)szNameBuffer
, &BufferSize
);
406 if (rc
!= ERROR_SUCCESS
) {
407 strcpy(szErrorOut
, "OEMCP NLS setting exists, but isn't readable");
411 /* load OEM codepage table */
412 strcpy(szFileName
, szSystemRoot
);
413 strcat(szFileName
, "system32\\");
414 strcat(szFileName
, szNameBuffer
);
415 DbgPrint((DPRINT_REACTOS
, "Oem file: %s\n", szFileName
));
416 if (!LoadNlsFile(szFileName
, "oem.nls")) {
417 strcpy(szErrorOut
, "Couldn't load oem.nls");
421 /* open the language key */
422 rc
= RegOpenKey(NULL
,
423 "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\Language",
425 if (rc
!= ERROR_SUCCESS
) {
426 strcpy(szErrorOut
, "Couldn't open Language registry key");
430 /* get the Unicode case table */
432 rc
= RegQueryValue(hKey
, "Default", NULL
, (PUCHAR
)szIdBuffer
, &BufferSize
);
433 if (rc
!= ERROR_SUCCESS
) {
434 strcpy(szErrorOut
, "Couldn't get Language Default setting");
439 rc
= RegQueryValue(hKey
, szIdBuffer
, NULL
, (PUCHAR
)szNameBuffer
, &BufferSize
);
440 if (rc
!= ERROR_SUCCESS
) {
442 "Language Default setting exists, but isn't readable");
446 /* load Unicode case table */
447 strcpy(szFileName
, szSystemRoot
);
448 strcat(szFileName
, "system32\\");
449 strcat(szFileName
, szNameBuffer
);
450 DbgPrint((DPRINT_REACTOS
, "Casemap file: %s\n", szFileName
));
451 if (!LoadNlsFile(szFileName
, "casemap.nls")) {
452 strcpy(szErrorOut
, "casemap.nls");
461 LoadAndBootReactOS(PUCHAR OperatingSystemName
)
466 char szKernelName
[1024];
467 char szHalName
[1024];
468 char szFileName
[1024];
469 char szBootPath
[256];
471 // int nNumDriverFiles=0;
472 // int nNumFilesLoaded=0;
479 PARTITION_TABLE_ENTRY PartitionTableEntry
;
483 // Open the operating system section
484 // specified in the .ini file
486 if (!IniOpenSection(OperatingSystemName
, &SectionId
))
488 sprintf(MsgBuffer
,"Operating System section '%s' not found in freeldr.ini", OperatingSystemName
);
489 UiMessageBox(MsgBuffer
);
494 * Setup multiboot information structure
496 mb_info
.flags
= MB_INFO_FLAG_MEM_SIZE
| MB_INFO_FLAG_BOOT_DEVICE
| MB_INFO_FLAG_COMMAND_LINE
| MB_INFO_FLAG_MODULES
;
497 mb_info
.mem_lower
= GetConventionalMemorySize();
498 mb_info
.mem_upper
= GetExtendedMemorySize();
499 mb_info
.boot_device
= 0xffffffff;
500 mb_info
.cmdline
= (unsigned long)multiboot_kernel_cmdline
;
501 mb_info
.mods_count
= 0;
502 mb_info
.mods_addr
= (unsigned long)multiboot_modules
;
503 mb_info
.mmap_length
= (unsigned long)GetBiosMemoryMap((PBIOS_MEMORY_MAP
)&multiboot_memory_map
, 32) * sizeof(memory_map_t
);
504 if (mb_info
.mmap_length
)
506 mb_info
.mmap_addr
= (unsigned long)&multiboot_memory_map
;
507 mb_info
.flags
|= MB_INFO_FLAG_MEMORY_MAP
;
508 multiboot_memory_map_descriptor_size
= sizeof(memory_map_t
); // GetBiosMemoryMap uses a fixed value of 24
509 DbgPrint((DPRINT_REACTOS
, "memory map length: %d\n", mb_info
.mmap_length
));
510 DbgPrint((DPRINT_REACTOS
, "dumping memory map:\n"));
511 for (i
=0; i
<(mb_info
.mmap_length
/sizeof(memory_map_t
)); i
++)
513 DbgPrint((DPRINT_REACTOS
, "start: %x\t size: %x\t type %d\n",
514 multiboot_memory_map
[i
].base_addr_low
,
515 multiboot_memory_map
[i
].length_low
,
516 multiboot_memory_map
[i
].type
));
519 DbgPrint((DPRINT_REACTOS
, "low_mem = %d\n", mb_info
.mem_lower
));
520 DbgPrint((DPRINT_REACTOS
, "high_mem = %d\n", mb_info
.mem_upper
));
523 * Initialize the registry
525 RegInitializeRegistry();
528 * Make sure the system path is set in the .ini file
530 if (!IniReadSettingByName(SectionId
, "SystemPath", value
, 1024))
532 UiMessageBox("System path not specified for selected operating system.");
537 * Special case for Live CD.
539 if (!stricmp(value
, "LiveCD"))
541 strcpy(szBootPath
, "\\reactos");
543 /* Set kernel command line */
544 sprintf(multiboot_kernel_cmdline
,
545 "multi(0)disk(0)cdrom(%u)\\reactos /MININT",
546 (unsigned int)BootDrive
);
553 if (!DissectArcPath(value
, szBootPath
, &BootDrive
, &BootPartition
))
555 sprintf(MsgBuffer
,"Invalid system path: '%s'", value
);
556 UiMessageBox(MsgBuffer
);
560 /* recalculate the boot partition for freeldr */
565 if (!DiskGetPartitionEntry(BootDrive
, ++i
, &PartitionTableEntry
))
570 if (IsRecognizedPartition(PartitionTableEntry
.SystemIndicator
))
572 if (++rosPartition
== BootPartition
)
579 if (BootPartition
== 0)
581 sprintf(MsgBuffer
,"Invalid system path: '%s'", value
);
582 UiMessageBox(MsgBuffer
);
586 /* copy ARC path into kernel command line */
587 strcpy(multiboot_kernel_cmdline
, value
);
590 /* Set boot drive and partition */
591 ((char *)(&mb_info
.boot_device
))[0] = (char)BootDrive
;
592 ((char *)(&mb_info
.boot_device
))[1] = (char)BootPartition
;
595 * Read the optional kernel parameters (if any)
597 if (IniReadSettingByName(SectionId
, "Options", value
, 1024))
599 strcat(multiboot_kernel_cmdline
, " ");
600 strcat(multiboot_kernel_cmdline
, value
);
603 /* append a backslash */
604 if ((strlen(szBootPath
)==0) ||
605 szBootPath
[strlen(szBootPath
)] != '\\')
606 strcat(szBootPath
, "\\");
608 DbgPrint((DPRINT_REACTOS
,"SystemRoot: '%s'\n", szBootPath
));
612 UiDrawStatusText("Detecting Hardware...");
620 UiDrawStatusText("Loading...");
621 UiDrawProgressBarCenter(0, 100, "Loading ReactOS...");
624 * Try to open boot drive
626 if (!FsOpenVolume(BootDrive
, BootPartition
))
628 UiMessageBox("Failed to open boot drive.");
633 * Find the kernel image name
634 * and try to load the kernel off the disk
636 if(IniReadSettingByName(SectionId
, "Kernel", value
, 1024))
641 if (value
[0] == '\\')
643 strcpy(szKernelName
, value
);
647 strcpy(szKernelName
, szBootPath
);
648 strcat(szKernelName
, "SYSTEM32\\");
649 strcat(szKernelName
, value
);
654 strcpy(value
, "NTOSKRNL.EXE");
655 strcpy(szKernelName
, szBootPath
);
656 strcat(szKernelName
, "SYSTEM32\\");
657 strcat(szKernelName
, value
);
660 if (!LoadKernel(szKernelName
, 5))
664 * Find the HAL image name
665 * and try to load the kernel off the disk
667 if(IniReadSettingByName(SectionId
, "Hal", value
, 1024))
672 if (value
[0] == '\\')
674 strcpy(szHalName
, value
);
678 strcpy(szHalName
, szBootPath
);
679 strcat(szHalName
, "SYSTEM32\\");
680 strcat(szHalName
, value
);
685 strcpy(value
, "HAL.DLL");
686 strcpy(szHalName
, szBootPath
);
687 strcat(szHalName
, "SYSTEM32\\");
688 strcat(szHalName
, value
);
691 if (!LoadDriver(szHalName
, 10))
695 * Load the System hive from disk
697 strcpy(szFileName
, szBootPath
);
698 strcat(szFileName
, "SYSTEM32\\CONFIG\\SYSTEM");
700 DbgPrint((DPRINT_REACTOS
, "SystemHive: '%s'", szFileName
));
702 FilePointer
= FsOpenFile(szFileName
);
703 if (FilePointer
== NULL
)
705 UiMessageBox("Could not find the System hive!");
710 * Update the status bar with the current file
712 strcpy(name
, "Reading ");
714 while (strlen(name
) < 80)
716 UiDrawStatusText(name
);
719 * Load the System hive
721 Base
= MultiBootLoadModule(FilePointer
, szFileName
, &Size
);
722 if (Base
== NULL
|| Size
== 0)
724 UiMessageBox("Could not load the System hive!\n");
727 DbgPrint((DPRINT_REACTOS
, "SystemHive loaded at 0x%x size %u", (unsigned)Base
, (unsigned)Size
));
730 * Import the loaded system hive
732 RegImportBinaryHive(Base
, Size
);
735 * Initialize the 'CurrentControlSet' link
737 RegInitCurrentControlSet(FALSE
);
739 UiDrawProgressBarCenter(15, 100, "Loading ReactOS...");
742 * Export the hardware hive
744 Base
= MultiBootCreateModule ("HARDWARE");
745 RegExportBinaryHive ("\\Registry\\Machine\\HARDWARE", Base
, &Size
);
746 MultiBootCloseModule (Base
, Size
);
748 UiDrawProgressBarCenter(20, 100, "Loading ReactOS...");
753 if (!LoadNlsFiles(szBootPath
, MsgBuffer
))
755 UiMessageBox(MsgBuffer
);
758 UiDrawProgressBarCenter(25, 100, "Loading ReactOS...");
763 LoadSymbolFile(szBootPath
, szKernelName
, 30);
764 LoadSymbolFile(szBootPath
, szHalName
, 30);
766 UiDrawProgressBarCenter(30, 100, "Loading ReactOS...");
771 LoadBootDrivers(szBootPath
, 30);
776 * Clear the screen and redraw the backdrop and status bar
779 UiDrawStatusText("Press any key to boot");
784 strcpy(name
, "Kernel and Drivers loaded.\nPress any key to boot ");
785 strcat(name
, OperatingSystemName
);
790 UiUnInitialize("Booting ReactOS...");
793 * Now boot the kernel
795 DiskStopFloppyMotor();