3 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 /* INCLUDES *******************************************************************/
24 /* GLOBALS ********************************************************************/
28 const CHAR BootSectorFilePrompt
[] = "Enter the boot sector file path.\n\nExamples:\n\\BOOTSECT.DOS\n/boot/bootsect.dos";
29 const CHAR LinuxKernelPrompt
[] = "Enter the Linux kernel image path.\n\nExamples:\n/vmlinuz\n/boot/vmlinuz-2.4.18";
30 const CHAR LinuxInitrdPrompt
[] = "Enter the initrd image path.\n\nExamples:\n/initrd.gz\n/boot/root.img.gz\n\nLeave blank for no initial ram disk.";
31 const CHAR LinuxCommandLinePrompt
[] = "Enter the Linux kernel command line.\n\nExamples:\nroot=/dev/hda1\nroot=/dev/fd0 read-only\nroot=/dev/sdb1 init=/sbin/init";
35 const CHAR BootDrivePrompt
[] = "Enter the boot drive.\n\nExamples:\nfd0 - first floppy drive\nhd0 - first hard drive\nhd1 - second hard drive\ncd0 - first CD-ROM drive.\n\nBIOS drive numbers may also be used:\n0 - first floppy drive\n0x80 - first hard drive\n0x81 - second hard drive";
36 const CHAR BootPartitionPrompt
[] = "Enter the boot partition.\n\nEnter 0 for the active (bootable) partition.";
37 const CHAR ARCPathPrompt
[] = "Enter the boot ARC path.\n\nExamples:\nmulti(0)disk(0)rdisk(0)partition(1)\nmulti(0)disk(0)fdisk(0)";
38 const CHAR ReactOSSystemPathPrompt
[] = "Enter the path to your ReactOS system directory.\n\nExamples:\n\\REACTOS\n\\ROS";
39 const CHAR ReactOSOptionsPrompt
[] = "Enter the options you want passed to the kernel.\n\nExamples:\n/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200\n/FASTDETECT /SOS /NOGUIBOOT\n/BASEVIDEO /MAXMEM=64\n/KERNEL=NTKRNLMP.EXE /HAL=HALMPS.DLL";
40 const CHAR CustomBootPrompt
[] = "Press ENTER to boot your custom boot setup.";
42 /* FUNCTIONS ******************************************************************/
44 #ifdef HAS_OPTION_MENU_CUSTOM_BOOT
46 VOID
OptionMenuCustomBoot(VOID
)
48 PCSTR CustomBootMenuList
[] = {
58 ULONG SelectedMenuItem
;
59 OperatingSystemItem OperatingSystem
;
61 if (!UiDisplayMenu("Please choose a boot method:", NULL
,
64 sizeof(CustomBootMenuList
) / sizeof(CustomBootMenuList
[0]),
70 /* The user pressed ESC */
74 /* Initialize a new custom OS entry */
75 OperatingSystem
.SectionId
= 0;
76 switch (SelectedMenuItem
)
80 EditCustomBootDisk(&OperatingSystem
);
83 EditCustomBootPartition(&OperatingSystem
);
85 case 2: // Boot Sector File
86 EditCustomBootSectorFile(&OperatingSystem
);
89 EditCustomBootLinux(&OperatingSystem
);
92 EditCustomBootReactOS(&OperatingSystem
, FALSE
);
94 case 5: // ReactOS Setup
95 EditCustomBootReactOS(&OperatingSystem
, TRUE
);
99 EditCustomBootReactOS(&OperatingSystem
, FALSE
);
101 case 1: // ReactOS Setup
102 EditCustomBootReactOS(&OperatingSystem
, TRUE
);
108 if (OperatingSystem
.SectionId
!= 0)
110 UiMessageBox(CustomBootPrompt
);
111 LoadOperatingSystem(&OperatingSystem
);
115 #endif // HAS_OPTION_MENU_CUSTOM_BOOT
121 IN OUT OperatingSystemItem
* OperatingSystem
)
124 ULONG_PTR SectionId
= OperatingSystem
->SectionId
;
125 CHAR SectionName
[100];
126 /* The following is a trick for saving some stack space */
138 RtlZeroMemory(SectionName
, sizeof(SectionName
));
139 RtlZeroMemory(&BootStrings
, sizeof(BootStrings
));
143 /* Load the settings */
145 /* Check whether we have a "BootPath" value (takes precedence over "BootDrive") */
146 *BootStrings
.ArcPath
= ANSI_NULL
;
147 IniReadSettingByName(SectionId
, "BootPath", BootStrings
.ArcPath
, sizeof(BootStrings
.ArcPath
));
148 if (!*BootStrings
.ArcPath
)
150 /* We don't, retrieve the boot drive value instead */
151 IniReadSettingByName(SectionId
, "BootDrive", BootStrings
.Drive
, sizeof(BootStrings
.Drive
));
155 if (!*BootStrings
.ArcPath
)
157 if (!UiEditBox(BootDrivePrompt
, BootStrings
.Drive
, sizeof(BootStrings
.Drive
)))
160 if (!*BootStrings
.Drive
)
162 if (!UiEditBox(ARCPathPrompt
, BootStrings
.ArcPath
, sizeof(BootStrings
.ArcPath
)))
166 /* Modify the settings values and return if we were in edit mode */
169 /* Modify the BootPath if we have one */
170 if (*BootStrings
.ArcPath
)
172 IniModifySettingValue(SectionId
, "BootPath", BootStrings
.ArcPath
);
174 else if (*BootStrings
.Drive
)
176 /* Otherwise, modify the BootDrive */
177 IniModifySettingValue(SectionId
, "BootDrive", BootStrings
.Drive
);
182 /* Generate a unique section name */
183 TimeInfo
= ArcGetTime();
184 RtlStringCbPrintfA(SectionName
, sizeof(SectionName
),
185 "CustomBootDisk%u%u%u%u%u%u",
186 TimeInfo
->Year
, TimeInfo
->Day
, TimeInfo
->Month
,
187 TimeInfo
->Hour
, TimeInfo
->Minute
, TimeInfo
->Second
);
189 /* Add the section */
190 if (!IniAddSection(SectionName
, &SectionId
))
193 /* Add the BootType */
194 if (!IniAddSettingValueToSection(SectionId
, "BootType", "Drive"))
197 /* Add the BootPath if we have one */
198 if (*BootStrings
.ArcPath
)
200 if (!IniAddSettingValueToSection(SectionId
, "BootPath", BootStrings
.ArcPath
))
203 else if (*BootStrings
.Drive
)
205 /* Otherwise, add the BootDrive */
206 if (!IniAddSettingValueToSection(SectionId
, "BootDrive", BootStrings
.Drive
))
210 OperatingSystem
->SectionId
= SectionId
;
211 OperatingSystem
->LoadIdentifier
= NULL
;
215 EditCustomBootPartition(
216 IN OUT OperatingSystemItem
* OperatingSystem
)
219 ULONG_PTR SectionId
= OperatingSystem
->SectionId
;
220 CHAR SectionName
[100];
221 /* The following is a trick for saving some stack space */
234 RtlZeroMemory(SectionName
, sizeof(SectionName
));
235 RtlZeroMemory(&BootStrings
, sizeof(BootStrings
));
239 /* Load the settings */
242 * Check whether we have a "BootPath" value (takes precedence
243 * over both "BootDrive" and "BootPartition").
245 *BootStrings
.ArcPath
= ANSI_NULL
;
246 IniReadSettingByName(SectionId
, "BootPath", BootStrings
.ArcPath
, sizeof(BootStrings
.ArcPath
));
247 if (!*BootStrings
.ArcPath
)
249 /* We don't, retrieve the boot drive and partition values instead */
250 IniReadSettingByName(SectionId
, "BootDrive", BootStrings
.Drive
, sizeof(BootStrings
.Drive
));
251 IniReadSettingByName(SectionId
, "BootPartition", BootStrings
.Partition
, sizeof(BootStrings
.Partition
));
255 if (!*BootStrings
.ArcPath
)
257 if (!UiEditBox(BootDrivePrompt
, BootStrings
.Drive
, sizeof(BootStrings
.Drive
)))
260 if (*BootStrings
.Drive
)
262 if (!UiEditBox(BootPartitionPrompt
, BootStrings
.Partition
, sizeof(BootStrings
.Partition
)))
266 if (!*BootStrings
.Drive
)
268 if (!UiEditBox(ARCPathPrompt
, BootStrings
.ArcPath
, sizeof(BootStrings
.ArcPath
)))
272 /* Modify the settings values and return if we were in edit mode */
275 /* Modify the BootPath if we have one */
276 if (*BootStrings
.ArcPath
)
278 IniModifySettingValue(SectionId
, "BootPath", BootStrings
.ArcPath
);
280 else if (*BootStrings
.Drive
)
282 /* Otherwise, modify the BootDrive and BootPartition */
283 IniModifySettingValue(SectionId
, "BootDrive", BootStrings
.Drive
);
284 IniModifySettingValue(SectionId
, "BootPartition", BootStrings
.Partition
);
289 /* Generate a unique section name */
290 TimeInfo
= ArcGetTime();
291 RtlStringCbPrintfA(SectionName
, sizeof(SectionName
),
292 "CustomBootPartition%u%u%u%u%u%u",
293 TimeInfo
->Year
, TimeInfo
->Day
, TimeInfo
->Month
,
294 TimeInfo
->Hour
, TimeInfo
->Minute
, TimeInfo
->Second
);
296 /* Add the section */
297 if (!IniAddSection(SectionName
, &SectionId
))
300 /* Add the BootType */
301 if (!IniAddSettingValueToSection(SectionId
, "BootType", "Partition"))
304 /* Add the BootPath if we have one */
305 if (*BootStrings
.ArcPath
)
307 if (!IniAddSettingValueToSection(SectionId
, "BootPath", BootStrings
.ArcPath
))
310 else if (*BootStrings
.Drive
)
312 /* Otherwise, add the BootDrive and BootPartition */
313 if (!IniAddSettingValueToSection(SectionId
, "BootDrive", BootStrings
.Drive
))
316 if (!IniAddSettingValueToSection(SectionId
, "BootPartition", BootStrings
.Partition
))
320 OperatingSystem
->SectionId
= SectionId
;
321 OperatingSystem
->LoadIdentifier
= NULL
;
325 EditCustomBootSectorFile(
326 IN OUT OperatingSystemItem
* OperatingSystem
)
329 ULONG_PTR SectionId
= OperatingSystem
->SectionId
;
330 CHAR SectionName
[100];
331 /* The following is a trick for saving some stack space */
343 CHAR BootSectorFileString
[200];
345 RtlZeroMemory(SectionName
, sizeof(SectionName
));
346 RtlZeroMemory(&BootStrings
, sizeof(BootStrings
));
347 RtlZeroMemory(BootSectorFileString
, sizeof(BootSectorFileString
));
351 /* Load the settings */
354 * Check whether we have a "BootPath" value (takes precedence
355 * over both "BootDrive" and "BootPartition").
357 *BootStrings
.ArcPath
= ANSI_NULL
;
358 IniReadSettingByName(SectionId
, "BootPath", BootStrings
.ArcPath
, sizeof(BootStrings
.ArcPath
));
359 if (!*BootStrings
.ArcPath
)
361 /* We don't, retrieve the boot drive and partition values instead */
362 IniReadSettingByName(SectionId
, "BootDrive", BootStrings
.Drive
, sizeof(BootStrings
.Drive
));
363 IniReadSettingByName(SectionId
, "BootPartition", BootStrings
.Partition
, sizeof(BootStrings
.Partition
));
366 IniReadSettingByName(SectionId
, "BootSectorFile", BootSectorFileString
, sizeof(BootSectorFileString
));
369 if (!*BootStrings
.ArcPath
)
371 if (!UiEditBox(BootDrivePrompt
, BootStrings
.Drive
, sizeof(BootStrings
.Drive
)))
374 if (*BootStrings
.Drive
)
376 if (!UiEditBox(BootPartitionPrompt
, BootStrings
.Partition
, sizeof(BootStrings
.Partition
)))
380 if (!*BootStrings
.Drive
)
382 if (!UiEditBox(ARCPathPrompt
, BootStrings
.ArcPath
, sizeof(BootStrings
.ArcPath
)))
386 if (!UiEditBox(BootSectorFilePrompt
, BootSectorFileString
, sizeof(BootSectorFileString
)))
389 /* Modify the settings values and return if we were in edit mode */
392 /* Modify the BootPath if we have one */
393 if (*BootStrings
.ArcPath
)
395 IniModifySettingValue(SectionId
, "BootPath", BootStrings
.ArcPath
);
397 else if (*BootStrings
.Drive
)
399 /* Otherwise, modify the BootDrive and BootPartition */
400 IniModifySettingValue(SectionId
, "BootDrive", BootStrings
.Drive
);
401 IniModifySettingValue(SectionId
, "BootPartition", BootStrings
.Partition
);
406 * Otherwise, zero out all values: BootSectorFile will be
407 * relative to the default system partition.
409 IniModifySettingValue(SectionId
, "BootPath", "");
410 IniModifySettingValue(SectionId
, "BootDrive", "");
411 IniModifySettingValue(SectionId
, "BootPartition", "");
414 IniModifySettingValue(SectionId
, "BootSectorFile", BootSectorFileString
);
418 /* Generate a unique section name */
419 TimeInfo
= ArcGetTime();
420 RtlStringCbPrintfA(SectionName
, sizeof(SectionName
),
421 "CustomBootSectorFile%u%u%u%u%u%u",
422 TimeInfo
->Year
, TimeInfo
->Day
, TimeInfo
->Month
,
423 TimeInfo
->Hour
, TimeInfo
->Minute
, TimeInfo
->Second
);
425 /* Add the section */
426 if (!IniAddSection(SectionName
, &SectionId
))
429 /* Add the BootType */
430 if (!IniAddSettingValueToSection(SectionId
, "BootType", "BootSector"))
433 /* Add the BootPath if we have one */
434 if (*BootStrings
.ArcPath
)
436 if (!IniAddSettingValueToSection(SectionId
, "BootPath", BootStrings
.ArcPath
))
439 else if (*BootStrings
.Drive
)
441 /* Otherwise, add the BootDrive and BootPartition */
442 if (!IniAddSettingValueToSection(SectionId
, "BootDrive", BootStrings
.Drive
))
445 if (!IniAddSettingValueToSection(SectionId
, "BootPartition", BootStrings
.Partition
))
449 /* Add the BootSectorFile */
450 if (!IniAddSettingValueToSection(SectionId
, "BootSectorFile", BootSectorFileString
))
453 OperatingSystem
->SectionId
= SectionId
;
454 OperatingSystem
->LoadIdentifier
= NULL
;
459 IN OUT OperatingSystemItem
* OperatingSystem
)
462 ULONG_PTR SectionId
= OperatingSystem
->SectionId
;
463 CHAR SectionName
[100];
464 /* The following is a trick for saving some stack space */
476 CHAR LinuxKernelString
[200];
477 CHAR LinuxInitrdString
[200];
478 CHAR LinuxCommandLineString
[200];
480 RtlZeroMemory(SectionName
, sizeof(SectionName
));
481 RtlZeroMemory(&BootStrings
, sizeof(BootStrings
));
482 RtlZeroMemory(LinuxKernelString
, sizeof(LinuxKernelString
));
483 RtlZeroMemory(LinuxInitrdString
, sizeof(LinuxInitrdString
));
484 RtlZeroMemory(LinuxCommandLineString
, sizeof(LinuxCommandLineString
));
488 /* Load the settings */
491 * Check whether we have a "BootPath" value (takes precedence
492 * over both "BootDrive" and "BootPartition").
494 *BootStrings
.ArcPath
= ANSI_NULL
;
495 IniReadSettingByName(SectionId
, "BootPath", BootStrings
.ArcPath
, sizeof(BootStrings
.ArcPath
));
496 if (!*BootStrings
.ArcPath
)
498 /* We don't, retrieve the boot drive and partition values instead */
499 IniReadSettingByName(SectionId
, "BootDrive", BootStrings
.Drive
, sizeof(BootStrings
.Drive
));
500 IniReadSettingByName(SectionId
, "BootPartition", BootStrings
.Partition
, sizeof(BootStrings
.Partition
));
503 IniReadSettingByName(SectionId
, "Kernel", LinuxKernelString
, sizeof(LinuxKernelString
));
504 IniReadSettingByName(SectionId
, "Initrd", LinuxInitrdString
, sizeof(LinuxInitrdString
));
505 IniReadSettingByName(SectionId
, "CommandLine", LinuxCommandLineString
, sizeof(LinuxCommandLineString
));
508 if (!*BootStrings
.ArcPath
)
510 if (!UiEditBox(BootDrivePrompt
, BootStrings
.Drive
, sizeof(BootStrings
.Drive
)))
513 if (*BootStrings
.Drive
)
515 if (!UiEditBox(BootPartitionPrompt
, BootStrings
.Partition
, sizeof(BootStrings
.Partition
)))
519 if (!*BootStrings
.Drive
)
521 if (!UiEditBox(ARCPathPrompt
, BootStrings
.ArcPath
, sizeof(BootStrings
.ArcPath
)))
525 if (!UiEditBox(LinuxKernelPrompt
, LinuxKernelString
, sizeof(LinuxKernelString
)))
528 if (!UiEditBox(LinuxInitrdPrompt
, LinuxInitrdString
, sizeof(LinuxInitrdString
)))
531 if (!UiEditBox(LinuxCommandLinePrompt
, LinuxCommandLineString
, sizeof(LinuxCommandLineString
)))
534 /* Modify the settings values and return if we were in edit mode */
537 /* Modify the BootPath if we have one */
538 if (*BootStrings
.ArcPath
)
540 IniModifySettingValue(SectionId
, "BootPath", BootStrings
.ArcPath
);
542 else if (*BootStrings
.Drive
)
544 /* Otherwise, modify the BootDrive and BootPartition */
545 IniModifySettingValue(SectionId
, "BootDrive", BootStrings
.Drive
);
546 IniModifySettingValue(SectionId
, "BootPartition", BootStrings
.Partition
);
551 * Otherwise, zero out all values: BootSectorFile will be
552 * relative to the default system partition.
554 IniModifySettingValue(SectionId
, "BootPath", "");
555 IniModifySettingValue(SectionId
, "BootDrive", "");
556 IniModifySettingValue(SectionId
, "BootPartition", "");
559 IniModifySettingValue(SectionId
, "Kernel", LinuxKernelString
);
560 IniModifySettingValue(SectionId
, "Initrd", LinuxInitrdString
);
561 IniModifySettingValue(SectionId
, "CommandLine", LinuxCommandLineString
);
565 /* Generate a unique section name */
566 TimeInfo
= ArcGetTime();
567 RtlStringCbPrintfA(SectionName
, sizeof(SectionName
),
568 "CustomLinux%u%u%u%u%u%u",
569 TimeInfo
->Year
, TimeInfo
->Day
, TimeInfo
->Month
,
570 TimeInfo
->Hour
, TimeInfo
->Minute
, TimeInfo
->Second
);
572 /* Add the section */
573 if (!IniAddSection(SectionName
, &SectionId
))
576 /* Add the BootType */
577 if (!IniAddSettingValueToSection(SectionId
, "BootType", "Linux"))
580 /* Add the BootPath if we have one */
581 if (*BootStrings
.ArcPath
)
583 if (!IniAddSettingValueToSection(SectionId
, "BootPath", BootStrings
.ArcPath
))
586 else if (*BootStrings
.Drive
)
588 /* Otherwise, add the BootDrive and BootPartition */
589 if (!IniAddSettingValueToSection(SectionId
, "BootDrive", BootStrings
.Drive
))
592 if (!IniAddSettingValueToSection(SectionId
, "BootPartition", BootStrings
.Partition
))
597 if (!IniAddSettingValueToSection(SectionId
, "Kernel", LinuxKernelString
))
601 if (*LinuxInitrdString
)
603 if (!IniAddSettingValueToSection(SectionId
, "Initrd", LinuxInitrdString
))
607 /* Add the CommandLine */
608 if (!IniAddSettingValueToSection(SectionId
, "CommandLine", LinuxCommandLineString
))
611 OperatingSystem
->SectionId
= SectionId
;
612 OperatingSystem
->LoadIdentifier
= "Custom Linux Setup";
618 EditCustomBootReactOS(
619 IN OUT OperatingSystemItem
* OperatingSystem
,
623 ULONG_PTR SectionId
= OperatingSystem
->SectionId
;
624 CHAR SectionName
[100];
625 CHAR BootDriveString
[20];
626 CHAR BootPartitionString
[20];
627 CHAR ReactOSSystemPath
[200];
628 CHAR ReactOSARCPath
[200];
629 CHAR ReactOSOptions
[200];
631 RtlZeroMemory(SectionName
, sizeof(SectionName
));
632 RtlZeroMemory(BootDriveString
, sizeof(BootDriveString
));
633 RtlZeroMemory(BootPartitionString
, sizeof(BootPartitionString
));
634 RtlZeroMemory(ReactOSSystemPath
, sizeof(ReactOSSystemPath
));
635 RtlZeroMemory(ReactOSARCPath
, sizeof(ReactOSARCPath
));
636 RtlZeroMemory(ReactOSOptions
, sizeof(ReactOSOptions
));
640 /* Load the settings */
641 IniReadSettingByName(SectionId
, "SystemPath", ReactOSARCPath
, sizeof(ReactOSARCPath
));
642 IniReadSettingByName(SectionId
, "Options", ReactOSOptions
, sizeof(ReactOSOptions
));
647 if (!UiEditBox(BootDrivePrompt
, BootDriveString
, sizeof(BootDriveString
)))
650 if (!UiEditBox(BootPartitionPrompt
, BootPartitionString
, sizeof(BootPartitionString
)))
653 if (!UiEditBox(ReactOSSystemPathPrompt
, ReactOSSystemPath
, sizeof(ReactOSSystemPath
)))
658 if (!UiEditBox(ReactOSSystemPathPrompt
, ReactOSARCPath
, sizeof(ReactOSARCPath
)))
662 if (!UiEditBox(ReactOSOptionsPrompt
, ReactOSOptions
, sizeof(ReactOSOptions
)))
665 /* Modify the settings values and return if we were in edit mode */
668 IniModifySettingValue(SectionId
, "SystemPath", ReactOSARCPath
);
669 IniModifySettingValue(SectionId
, "Options", ReactOSOptions
);
673 /* Generate a unique section name */
674 TimeInfo
= ArcGetTime();
675 RtlStringCbPrintfA(SectionName
, sizeof(SectionName
),
676 "CustomReactOS%u%u%u%u%u%u",
677 TimeInfo
->Year
, TimeInfo
->Day
, TimeInfo
->Month
,
678 TimeInfo
->Hour
, TimeInfo
->Minute
, TimeInfo
->Second
);
680 /* Add the section */
681 if (!IniAddSection(SectionName
, &SectionId
))
684 /* Add the BootType */
685 if (!IniAddSettingValueToSection(SectionId
, "BootType", IsSetup
? "ReactOSSetup" : "Windows2003"))
688 /* Construct the ReactOS ARC system path */
689 ConstructArcPath(ReactOSARCPath
, ReactOSSystemPath
, DriveMapGetBiosDriveNumber(BootDriveString
), atoi(BootPartitionString
));
691 /* Add the system path */
692 if (!IniAddSettingValueToSection(SectionId
, "SystemPath", ReactOSARCPath
))
695 /* Add the CommandLine */
696 if (!IniAddSettingValueToSection(SectionId
, "Options", ReactOSOptions
))
699 OperatingSystem
->SectionId
= SectionId
;
700 OperatingSystem
->LoadIdentifier
= NULL
;
703 #ifdef HAS_OPTION_MENU_REBOOT
705 VOID
OptionMenuReboot(VOID
)
707 UiMessageBox("The system will now reboot.");
711 #endif // HAS_OPTION_MENU_REBOOT