[FREELDR] Diverse enhancements.
[reactos.git] / boot / freeldr / freeldr / custom.c
1 /*
2 * FreeLoader
3 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
4 *
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.
9 *
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.
14 *
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.
18 */
19
20 /* INCLUDES *******************************************************************/
21
22 #include <freeldr.h>
23
24 /* GLOBALS ********************************************************************/
25
26 #ifdef _M_IX86
27
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";
32
33 #endif // _M_IX86
34
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 ReactOSSystemPathPrompt[] = "Enter the path to your ReactOS system directory.\n\nExamples:\n\\REACTOS\n\\ROS";
38 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";
39 const CHAR CustomBootPrompt[] = "Press ENTER to boot your custom boot setup.";
40
41 /* FUNCTIONS ******************************************************************/
42
43 #ifdef HAS_OPTION_MENU_CUSTOM_BOOT
44
45 VOID OptionMenuCustomBoot(VOID)
46 {
47 PCSTR CustomBootMenuList[] = {
48 #ifdef _M_IX86
49 "Disk",
50 "Partition",
51 "Boot Sector File",
52 "Linux",
53 #endif
54 "ReactOS",
55 "ReactOS Setup"
56 };
57 ULONG SelectedMenuItem;
58
59 if (!UiDisplayMenu("Please choose a boot method:", NULL,
60 FALSE,
61 CustomBootMenuList,
62 sizeof(CustomBootMenuList) / sizeof(CustomBootMenuList[0]),
63 0, -1,
64 &SelectedMenuItem,
65 TRUE,
66 NULL, NULL))
67 {
68 /* The user pressed ESC */
69 return;
70 }
71
72 switch (SelectedMenuItem)
73 {
74 #ifdef _M_IX86
75 case 0: // Disk
76 EditCustomBootDisk(0);
77 break;
78 case 1: // Partition
79 EditCustomBootPartition(0);
80 break;
81 case 2: // Boot Sector File
82 EditCustomBootSectorFile(0);
83 break;
84 case 3: // Linux
85 EditCustomBootLinux(0);
86 break;
87 case 4: // ReactOS
88 EditCustomBootReactOS(0, FALSE);
89 break;
90 case 5: // ReactOS Setup
91 EditCustomBootReactOS(0, TRUE);
92 break;
93 #else
94 case 0: // ReactOS
95 EditCustomBootReactOS(0, FALSE);
96 break;
97 case 1: // ReactOS Setup
98 EditCustomBootReactOS(0, TRUE);
99 break;
100 #endif
101 }
102 }
103
104 #endif // HAS_OPTION_MENU_CUSTOM_BOOT
105
106 #ifdef _M_IX86
107
108 VOID EditCustomBootDisk(IN ULONG_PTR SectionId OPTIONAL)
109 {
110 TIMEINFO* TimeInfo;
111 OperatingSystemItem OperatingSystem;
112 CHAR SectionName[100];
113 CHAR BootDriveString[20];
114
115 RtlZeroMemory(SectionName, sizeof(SectionName));
116 RtlZeroMemory(BootDriveString, sizeof(BootDriveString));
117
118 if (SectionId != 0)
119 {
120 /* Load the settings */
121 IniReadSettingByName(SectionId, "BootDrive", BootDriveString, sizeof(BootDriveString));
122 }
123
124 if (!UiEditBox(BootDrivePrompt, BootDriveString, sizeof(BootDriveString)))
125 return;
126
127 /* Modify the settings values and return if we were in edit mode */
128 if (SectionId != 0)
129 {
130 IniModifySettingValue(SectionId, "BootDrive", BootDriveString);
131 return;
132 }
133
134 /* Generate a unique section name */
135 TimeInfo = ArcGetTime();
136 RtlStringCbPrintfA(SectionName, sizeof(SectionName),
137 "CustomBootDisk%u%u%u%u%u%u",
138 TimeInfo->Year, TimeInfo->Day, TimeInfo->Month,
139 TimeInfo->Hour, TimeInfo->Minute, TimeInfo->Second);
140
141 /* Add the section */
142 if (!IniAddSection(SectionName, &SectionId))
143 return;
144
145 /* Add the BootType */
146 if (!IniAddSettingValueToSection(SectionId, "BootType", "Drive"))
147 return;
148
149 /* Add the BootDrive */
150 if (!IniAddSettingValueToSection(SectionId, "BootDrive", BootDriveString))
151 return;
152
153 UiMessageBox(CustomBootPrompt);
154
155 OperatingSystem.SectionName = SectionName;
156 OperatingSystem.LoadIdentifier = NULL;
157 LoadOperatingSystem(&OperatingSystem);
158 }
159
160 VOID EditCustomBootPartition(IN ULONG_PTR SectionId OPTIONAL)
161 {
162 TIMEINFO* TimeInfo;
163 OperatingSystemItem OperatingSystem;
164 CHAR SectionName[100];
165 CHAR BootDriveString[20];
166 CHAR BootPartitionString[20];
167
168 RtlZeroMemory(SectionName, sizeof(SectionName));
169 RtlZeroMemory(BootDriveString, sizeof(BootDriveString));
170 RtlZeroMemory(BootPartitionString, sizeof(BootPartitionString));
171
172 if (SectionId != 0)
173 {
174 /* Load the settings */
175 IniReadSettingByName(SectionId, "BootDrive", BootDriveString, sizeof(BootDriveString));
176 IniReadSettingByName(SectionId, "BootPartition", BootPartitionString, sizeof(BootPartitionString));
177 }
178
179 if (!UiEditBox(BootDrivePrompt, BootDriveString, sizeof(BootDriveString)))
180 return;
181
182 if (!UiEditBox(BootPartitionPrompt, BootPartitionString, sizeof(BootPartitionString)))
183 return;
184
185 /* Modify the settings values and return if we were in edit mode */
186 if (SectionId != 0)
187 {
188 IniModifySettingValue(SectionId, "BootDrive", BootDriveString);
189 IniModifySettingValue(SectionId, "BootPartition", BootPartitionString);
190 return;
191 }
192
193 /* Generate a unique section name */
194 TimeInfo = ArcGetTime();
195 RtlStringCbPrintfA(SectionName, sizeof(SectionName),
196 "CustomBootPartition%u%u%u%u%u%u",
197 TimeInfo->Year, TimeInfo->Day, TimeInfo->Month,
198 TimeInfo->Hour, TimeInfo->Minute, TimeInfo->Second);
199
200 /* Add the section */
201 if (!IniAddSection(SectionName, &SectionId))
202 return;
203
204 /* Add the BootType */
205 if (!IniAddSettingValueToSection(SectionId, "BootType", "Partition"))
206 return;
207
208 /* Add the BootDrive */
209 if (!IniAddSettingValueToSection(SectionId, "BootDrive", BootDriveString))
210 return;
211
212 /* Add the BootPartition */
213 if (!IniAddSettingValueToSection(SectionId, "BootPartition", BootPartitionString))
214 return;
215
216 UiMessageBox(CustomBootPrompt);
217
218 OperatingSystem.SectionName = SectionName;
219 OperatingSystem.LoadIdentifier = NULL;
220 LoadOperatingSystem(&OperatingSystem);
221 }
222
223 VOID EditCustomBootSectorFile(IN ULONG_PTR SectionId OPTIONAL)
224 {
225 TIMEINFO* TimeInfo;
226 OperatingSystemItem OperatingSystem;
227 CHAR SectionName[100];
228 CHAR BootDriveString[20];
229 CHAR BootPartitionString[20];
230 CHAR BootSectorFileString[200];
231
232 RtlZeroMemory(SectionName, sizeof(SectionName));
233 RtlZeroMemory(BootDriveString, sizeof(BootDriveString));
234 RtlZeroMemory(BootPartitionString, sizeof(BootPartitionString));
235 RtlZeroMemory(BootSectorFileString, sizeof(BootSectorFileString));
236
237 if (SectionId != 0)
238 {
239 /* Load the settings */
240 IniReadSettingByName(SectionId, "BootDrive", BootDriveString, sizeof(BootDriveString));
241 IniReadSettingByName(SectionId, "BootPartition", BootPartitionString, sizeof(BootPartitionString));
242 IniReadSettingByName(SectionId, "BootSectorFile", BootSectorFileString, sizeof(BootSectorFileString));
243 }
244
245 if (!UiEditBox(BootDrivePrompt, BootDriveString, sizeof(BootDriveString)))
246 return;
247
248 if (!UiEditBox(BootPartitionPrompt, BootPartitionString, sizeof(BootPartitionString)))
249 return;
250
251 if (!UiEditBox(BootSectorFilePrompt, BootSectorFileString, sizeof(BootSectorFileString)))
252 return;
253
254 /* Modify the settings values and return if we were in edit mode */
255 if (SectionId != 0)
256 {
257 IniModifySettingValue(SectionId, "BootDrive", BootDriveString);
258 IniModifySettingValue(SectionId, "BootPartition", BootPartitionString);
259 IniModifySettingValue(SectionId, "BootSectorFile", BootSectorFileString);
260 return;
261 }
262
263 /* Generate a unique section name */
264 TimeInfo = ArcGetTime();
265 RtlStringCbPrintfA(SectionName, sizeof(SectionName),
266 "CustomBootSectorFile%u%u%u%u%u%u",
267 TimeInfo->Year, TimeInfo->Day, TimeInfo->Month,
268 TimeInfo->Hour, TimeInfo->Minute, TimeInfo->Second);
269
270 /* Add the section */
271 if (!IniAddSection(SectionName, &SectionId))
272 return;
273
274 /* Add the BootType */
275 if (!IniAddSettingValueToSection(SectionId, "BootType", "BootSector"))
276 return;
277
278 /* Add the BootDrive */
279 if (!IniAddSettingValueToSection(SectionId, "BootDrive", BootDriveString))
280 return;
281
282 /* Add the BootPartition */
283 if (!IniAddSettingValueToSection(SectionId, "BootPartition", BootPartitionString))
284 return;
285
286 /* Add the BootSectorFile */
287 if (!IniAddSettingValueToSection(SectionId, "BootSectorFile", BootSectorFileString))
288 return;
289
290 UiMessageBox(CustomBootPrompt);
291
292 OperatingSystem.SectionName = SectionName;
293 OperatingSystem.LoadIdentifier = NULL;
294 LoadOperatingSystem(&OperatingSystem);
295 }
296
297 VOID EditCustomBootLinux(IN ULONG_PTR SectionId OPTIONAL)
298 {
299 TIMEINFO* TimeInfo;
300 OperatingSystemItem OperatingSystem;
301 CHAR SectionName[100];
302 CHAR BootDriveString[20];
303 CHAR BootPartitionString[20];
304 CHAR LinuxKernelString[200];
305 CHAR LinuxInitrdString[200];
306 CHAR LinuxCommandLineString[200];
307
308 RtlZeroMemory(SectionName, sizeof(SectionName));
309 RtlZeroMemory(BootDriveString, sizeof(BootDriveString));
310 RtlZeroMemory(BootPartitionString, sizeof(BootPartitionString));
311 RtlZeroMemory(LinuxKernelString, sizeof(LinuxKernelString));
312 RtlZeroMemory(LinuxInitrdString, sizeof(LinuxInitrdString));
313 RtlZeroMemory(LinuxCommandLineString, sizeof(LinuxCommandLineString));
314
315 if (SectionId != 0)
316 {
317 /* Load the settings */
318 IniReadSettingByName(SectionId, "BootDrive", BootDriveString, sizeof(BootDriveString));
319 IniReadSettingByName(SectionId, "BootPartition", BootPartitionString, sizeof(BootPartitionString));
320 IniReadSettingByName(SectionId, "Kernel", LinuxKernelString, sizeof(LinuxKernelString));
321 IniReadSettingByName(SectionId, "Initrd", LinuxInitrdString, sizeof(LinuxInitrdString));
322 IniReadSettingByName(SectionId, "CommandLine", LinuxCommandLineString, sizeof(LinuxCommandLineString));
323 }
324
325 if (!UiEditBox(BootDrivePrompt, BootDriveString, sizeof(BootDriveString)))
326 return;
327
328 if (!UiEditBox(BootPartitionPrompt, BootPartitionString, sizeof(BootPartitionString)))
329 return;
330
331 if (!UiEditBox(LinuxKernelPrompt, LinuxKernelString, sizeof(LinuxKernelString)))
332 return;
333
334 if (!UiEditBox(LinuxInitrdPrompt, LinuxInitrdString, sizeof(LinuxInitrdString)))
335 return;
336
337 if (!UiEditBox(LinuxCommandLinePrompt, LinuxCommandLineString, sizeof(LinuxCommandLineString)))
338 return;
339
340 /* Modify the settings values and return if we were in edit mode */
341 if (SectionId != 0)
342 {
343 IniModifySettingValue(SectionId, "BootDrive", BootDriveString);
344 IniModifySettingValue(SectionId, "BootPartition", BootPartitionString);
345 IniModifySettingValue(SectionId, "Kernel", LinuxKernelString);
346 IniModifySettingValue(SectionId, "Initrd", LinuxInitrdString);
347 IniModifySettingValue(SectionId, "CommandLine", LinuxCommandLineString);
348 return;
349 }
350
351 /* Generate a unique section name */
352 TimeInfo = ArcGetTime();
353 RtlStringCbPrintfA(SectionName, sizeof(SectionName),
354 "CustomLinux%u%u%u%u%u%u",
355 TimeInfo->Year, TimeInfo->Day, TimeInfo->Month,
356 TimeInfo->Hour, TimeInfo->Minute, TimeInfo->Second);
357
358 /* Add the section */
359 if (!IniAddSection(SectionName, &SectionId))
360 return;
361
362 /* Add the BootType */
363 if (!IniAddSettingValueToSection(SectionId, "BootType", "Linux"))
364 return;
365
366 /* Add the BootDrive */
367 if (!IniAddSettingValueToSection(SectionId, "BootDrive", BootDriveString))
368 return;
369
370 /* Add the BootPartition */
371 if (!IniAddSettingValueToSection(SectionId, "BootPartition", BootPartitionString))
372 return;
373
374 /* Add the Kernel */
375 if (!IniAddSettingValueToSection(SectionId, "Kernel", LinuxKernelString))
376 return;
377
378 /* Add the Initrd */
379 if (*LinuxInitrdString)
380 {
381 if (!IniAddSettingValueToSection(SectionId, "Initrd", LinuxInitrdString))
382 return;
383 }
384
385 /* Add the CommandLine */
386 if (!IniAddSettingValueToSection(SectionId, "CommandLine", LinuxCommandLineString))
387 return;
388
389 UiMessageBox(CustomBootPrompt);
390
391 OperatingSystem.SectionName = SectionName;
392 OperatingSystem.LoadIdentifier = "Custom Linux Setup";
393 LoadOperatingSystem(&OperatingSystem);
394 }
395
396 #endif // _M_IX86
397
398 VOID
399 EditCustomBootReactOS(
400 IN ULONG_PTR SectionId OPTIONAL,
401 IN BOOLEAN IsSetup)
402 {
403 TIMEINFO* TimeInfo;
404 OperatingSystemItem OperatingSystem;
405 CHAR SectionName[100];
406 CHAR BootDriveString[20];
407 CHAR BootPartitionString[20];
408 CHAR ReactOSSystemPath[200];
409 CHAR ReactOSARCPath[200];
410 CHAR ReactOSOptions[200];
411
412 RtlZeroMemory(SectionName, sizeof(SectionName));
413 RtlZeroMemory(BootDriveString, sizeof(BootDriveString));
414 RtlZeroMemory(BootPartitionString, sizeof(BootPartitionString));
415 RtlZeroMemory(ReactOSSystemPath, sizeof(ReactOSSystemPath));
416 RtlZeroMemory(ReactOSARCPath, sizeof(ReactOSARCPath));
417 RtlZeroMemory(ReactOSOptions, sizeof(ReactOSOptions));
418
419 if (SectionId != 0)
420 {
421 /* Load the settings */
422 // TODO? Maybe use DissectArcPath(CHAR *ArcPath, CHAR *BootPath, UCHAR* BootDrive, ULONG* BootPartition) to get back to the small elements.
423 IniReadSettingByName(SectionId, "SystemPath", ReactOSARCPath, sizeof(ReactOSARCPath));
424 IniReadSettingByName(SectionId, "Options", ReactOSOptions, sizeof(ReactOSOptions));
425 }
426
427 if (SectionId == 0)
428 {
429 if (!UiEditBox(BootDrivePrompt, BootDriveString, sizeof(BootDriveString)))
430 return;
431
432 if (!UiEditBox(BootPartitionPrompt, BootPartitionString, sizeof(BootPartitionString)))
433 return;
434
435 if (!UiEditBox(ReactOSSystemPathPrompt, ReactOSSystemPath, sizeof(ReactOSSystemPath)))
436 return;
437 }
438 else
439 {
440 if (!UiEditBox(ReactOSSystemPathPrompt, ReactOSARCPath, sizeof(ReactOSARCPath)))
441 return;
442 }
443
444 if (!UiEditBox(ReactOSOptionsPrompt, ReactOSOptions, sizeof(ReactOSOptions)))
445 return;
446
447 /* Modify the settings values and return if we were in edit mode */
448 if (SectionId != 0)
449 {
450 IniModifySettingValue(SectionId, "SystemPath", ReactOSARCPath);
451 IniModifySettingValue(SectionId, "Options", ReactOSOptions);
452 return;
453 }
454
455 /* Generate a unique section name */
456 TimeInfo = ArcGetTime();
457 RtlStringCbPrintfA(SectionName, sizeof(SectionName),
458 "CustomReactOS%u%u%u%u%u%u",
459 TimeInfo->Year, TimeInfo->Day, TimeInfo->Month,
460 TimeInfo->Hour, TimeInfo->Minute, TimeInfo->Second);
461
462 /* Add the section */
463 if (!IniAddSection(SectionName, &SectionId))
464 return;
465
466 /* Add the BootType */
467 if (!IniAddSettingValueToSection(SectionId, "BootType", IsSetup ? "ReactOSSetup" : "Windows2003"))
468 return;
469
470 /* Construct the ReactOS ARC system path */
471 ConstructArcPath(ReactOSARCPath, ReactOSSystemPath, DriveMapGetBiosDriveNumber(BootDriveString), atoi(BootPartitionString));
472
473 /* Add the system path */
474 if (!IniAddSettingValueToSection(SectionId, "SystemPath", ReactOSARCPath))
475 return;
476
477 /* Add the CommandLine */
478 if (!IniAddSettingValueToSection(SectionId, "Options", ReactOSOptions))
479 return;
480
481 UiMessageBox(CustomBootPrompt);
482
483 OperatingSystem.SectionName = SectionName;
484 OperatingSystem.LoadIdentifier = NULL;
485 LoadOperatingSystem(&OperatingSystem);
486 }
487
488 #ifdef HAS_OPTION_MENU_REBOOT
489
490 VOID OptionMenuReboot(VOID)
491 {
492 UiMessageBox("The system will now reboot.");
493
494 #if defined(__i386__) || defined(_M_AMD64)
495 DiskStopFloppyMotor();
496 #endif
497 Reboot();
498 }
499
500 #endif // HAS_OPTION_MENU_REBOOT