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 *******************************************************************/
25 DBG_DEFAULT_CHANNEL(WARNING
);
27 /* GLOBALS ********************************************************************/
31 (*EDIT_OS_ENTRY_PROC
)(
32 IN OUT OperatingSystemItem
* OperatingSystem
);
35 EditCustomBootReactOSSetup(
36 IN OUT OperatingSystemItem
* OperatingSystem
)
38 EditCustomBootReactOS(OperatingSystem
, TRUE
);
43 IN OUT OperatingSystemItem
* OperatingSystem
)
45 EditCustomBootReactOS(OperatingSystem
, FALSE
);
51 EDIT_OS_ENTRY_PROC EditOsEntry
;
52 ARC_ENTRY_POINT OsLoader
;
53 } OSLoadingMethods
[] =
55 {"ReactOSSetup", EditCustomBootReactOSSetup
, LoadReactOSSetup
},
57 #if defined(_M_IX86) || defined(_M_AMD64)
58 {"Drive" , EditCustomBootDisk
, LoadAndBootDevice
},
59 {"Partition" , EditCustomBootPartition
, LoadAndBootDevice
},
60 {"BootSector" , EditCustomBootSectorFile
, LoadAndBootDevice
},
61 {"Linux" , EditCustomBootLinux
, LoadAndBootLinux
},
64 {"WindowsNT40" , EditCustomBootNTOS
, LoadAndBootWindows
},
66 {"Windows" , EditCustomBootNTOS
, LoadAndBootWindows
},
67 {"Windows2003" , EditCustomBootNTOS
, LoadAndBootWindows
},
70 /* FUNCTIONS ******************************************************************/
73 * This function converts the list of key=value options in the given operating
74 * system section into an ARC-compatible argument vector, providing in addition
75 * the extra mandatory Software Loading Environment Variables, following the
80 IN PCSTR LoadIdentifier
,
81 IN ULONG_PTR SectionId
,
90 PCHAR SettingName
, SettingValue
;
94 ASSERT(SectionId
!= 0);
96 /* Validate the LoadIdentifier (to make tests simpler later) */
97 if (LoadIdentifier
&& !*LoadIdentifier
)
98 LoadIdentifier
= NULL
;
100 /* Count the number of operating systems in the section */
101 Count
= IniGetNumSectionItems(SectionId
);
104 * The argument vector contains the program name, the SystemPartition,
105 * the LoadIdentifier (optional), and the items in the OS section.
107 Argc
= 2 + (LoadIdentifier
? 1 : 0) + Count
;
109 /* Calculate the total size needed for the string buffer of the argument vector */
111 /* i == 0: Program name */
112 /* i == 1: SystemPartition : from where FreeLdr has been started */
113 Size
+= (strlen("SystemPartition=") + strlen(FrLdrBootPath
) + 1) * sizeof(CHAR
);
114 /* i == 2: LoadIdentifier : ASCII string that may be used to associate an identifier with a set of load parameters */
117 Size
+= (strlen("LoadIdentifier=") + strlen(LoadIdentifier
) + 1) * sizeof(CHAR
);
119 for (i
= 0; i
< Count
; ++i
)
121 Size
+= IniGetSectionSettingNameSize(SectionId
, i
); // Counts also the NULL-terminator, that we transform into the '=' sign separator.
122 Size
+= IniGetSectionSettingValueSize(SectionId
, i
); // Counts also the NULL-terminator.
124 Size
+= sizeof(ANSI_NULL
); // Final NULL-terminator.
126 /* Allocate memory to hold the argument vector: pointers and string buffer */
127 Argv
= FrLdrHeapAlloc(Argc
* sizeof(PCHAR
) + Size
, TAG_STRING
);
131 /* Initialize the argument vector: loop through the section and copy the key=value options */
132 SettingName
= (PCHAR
)((ULONG_PTR
)Argv
+ (Argc
* sizeof(PCHAR
)));
134 /* i == 0: Program name */
136 /* i == 1: SystemPartition */
138 strcpy(SettingName
, "SystemPartition=");
139 strcat(SettingName
, FrLdrBootPath
);
141 *Args
++ = SettingName
;
142 SettingName
+= (strlen(SettingName
) + 1);
144 /* i == 2: LoadIdentifier */
147 strcpy(SettingName
, "LoadIdentifier=");
148 strcat(SettingName
, LoadIdentifier
);
150 *Args
++ = SettingName
;
151 SettingName
+= (strlen(SettingName
) + 1);
153 for (i
= 0; i
< Count
; ++i
)
155 Size
= IniGetSectionSettingNameSize(SectionId
, i
);
156 SettingValue
= SettingName
+ Size
;
157 IniReadSettingByNumber(SectionId
, i
,
159 SettingValue
, IniGetSectionSettingValueSize(SectionId
, i
));
160 SettingName
[Size
- 1] = '=';
162 *Args
++ = SettingName
;
163 SettingName
+= (strlen(SettingName
) + 1);
167 /* Dump the argument vector for debugging */
168 for (i
= 0; i
< Argc
; ++i
)
170 TRACE("Argv[%lu]: '%s'\n", i
, Argv
[i
]);
178 VOID
LoadOperatingSystem(IN OperatingSystemItem
* OperatingSystem
)
180 ULONG_PTR SectionId
= OperatingSystem
->SectionId
;
186 /* The operating system section has been opened by InitOperatingSystemList() */
187 ASSERT(SectionId
!= 0);
189 /* Try to read the boot type */
190 *BootType
= ANSI_NULL
;
191 IniReadSettingByName(SectionId
, "BootType", BootType
, sizeof(BootType
));
193 /* We must have the "BootType" value (it has been possibly added by InitOperatingSystemList()) */
197 /* Install the drive mapper according to this section drive mappings */
198 DriveMapMapDrivesInSection(SectionId
);
201 /* Find the suitable OS loader to start */
204 if (i
>= RTL_NUMBER_OF(OSLoadingMethods
))
206 if (_stricmp(BootType
, OSLoadingMethods
[i
].BootType
) == 0)
210 /* Build the ARC-compatible argument vector */
211 Argv
= BuildArgvForOsLoader(OperatingSystem
->LoadIdentifier
, SectionId
, &Argc
);
213 return; // Unexpected failure.
215 /* Start the OS loader */
216 OSLoadingMethods
[i
].OsLoader(Argc
, Argv
, NULL
);
217 FrLdrHeapFree(Argv
, TAG_STRING
);
220 #ifdef HAS_OPTION_MENU_EDIT_CMDLINE
222 VOID
EditOperatingSystemEntry(IN OperatingSystemItem
* OperatingSystem
)
224 ULONG_PTR SectionId
= OperatingSystem
->SectionId
;
228 /* The operating system section has been opened by InitOperatingSystemList() */
229 ASSERT(SectionId
!= 0);
231 /* Try to read the boot type */
232 *BootType
= ANSI_NULL
;
233 IniReadSettingByName(SectionId
, "BootType", BootType
, sizeof(BootType
));
235 /* We must have the "BootType" value (it has been possibly added by InitOperatingSystemList()) */
238 /* Find the suitable OS entry editor */
241 if (i
>= RTL_NUMBER_OF(OSLoadingMethods
))
243 if (_stricmp(BootType
, OSLoadingMethods
[i
].BootType
) == 0)
248 OSLoadingMethods
[i
].EditOsEntry(OperatingSystem
);
251 #endif // HAS_OPTION_MENU_EDIT_CMDLINE
255 IN ULONG_PTR FrLdrSectionId
)
258 CHAR TimeOutText
[20];
260 TimeOut
= CmdLineGetTimeOut();
266 if ((FrLdrSectionId
!= 0) &&
267 IniReadSettingByName(FrLdrSectionId
, "TimeOut", TimeOutText
, sizeof(TimeOutText
)))
269 TimeOut
= atoi(TimeOutText
);
276 MainBootMenuKeyPressFilter(
278 IN ULONG SelectedMenuItem
,
279 IN PVOID Context OPTIONAL
)
284 DoOptionsMenu(&((OperatingSystemItem
*)Context
)[SelectedMenuItem
]);
287 #ifdef HAS_OPTION_MENU_EDIT_CMDLINE
289 EditOperatingSystemEntry(&((OperatingSystemItem
*)Context
)[SelectedMenuItem
]);
294 /* We didn't handle the key */
303 ULONG OperatingSystemCount
;
304 OperatingSystemItem
* OperatingSystemList
;
305 PCSTR
* OperatingSystemDisplayNames
;
306 ULONG DefaultOperatingSystem
;
307 ULONG SelectedOperatingSystem
;
310 if (!MachInitializeBootDevices())
312 UiMessageBoxCritical("Error when detecting hardware.");
317 /* Load additional SCSI driver (if any) */
318 if (LoadBootDeviceDriver() != ESUCCESS
)
320 UiMessageBoxCritical("Unable to load additional boot device drivers.");
324 if (!IniFileInitialize())
326 UiMessageBoxCritical("Error initializing .ini file.");
330 /* Open the [FreeLoader] section */
331 if (!IniOpenSection("FreeLoader", &SectionId
))
333 UiMessageBoxCritical("Section [FreeLoader] not found in freeldr.ini.");
337 /* Debugger main initialization */
338 DebugInit(SectionId
);
340 /* Retrieve the default timeout */
341 TimeOut
= GetTimeOut(SectionId
);
343 /* UI main initialization */
344 if (!UiInitialize(TRUE
))
346 UiMessageBoxCritical("Unable to initialize UI.");
350 OperatingSystemList
= InitOperatingSystemList(SectionId
,
351 &OperatingSystemCount
,
352 &DefaultOperatingSystem
);
353 if (!OperatingSystemList
)
355 UiMessageBox("Unable to read operating systems section in freeldr.ini.\nPress ENTER to reboot.");
358 if (OperatingSystemCount
== 0)
360 UiMessageBox("There were no operating systems listed in freeldr.ini.\nPress ENTER to reboot.");
364 /* Create list of display names */
365 OperatingSystemDisplayNames
= FrLdrTempAlloc(sizeof(PCSTR
) * OperatingSystemCount
, 'mNSO');
366 if (!OperatingSystemDisplayNames
)
369 for (i
= 0; i
< OperatingSystemCount
; i
++)
371 OperatingSystemDisplayNames
[i
] = OperatingSystemList
[i
].LoadIdentifier
;
374 /* Find all the message box settings and run them */
375 UiShowMessageBoxesInSection(SectionId
);
379 /* Redraw the backdrop */
382 /* Show the operating system list menu */
383 if (!UiDisplayMenu("Please select the operating system to start:",
384 "For troubleshooting and advanced startup options for "
385 "ReactOS, press F8.",
387 OperatingSystemDisplayNames
,
388 OperatingSystemCount
,
389 DefaultOperatingSystem
,
391 &SelectedOperatingSystem
,
393 MainBootMenuKeyPressFilter
,
394 OperatingSystemList
))
396 UiMessageBox("Press ENTER to reboot.");
402 /* Load the chosen operating system */
403 LoadOperatingSystem(&OperatingSystemList
[SelectedOperatingSystem
]);
407 UiUnInitialize("Rebooting...");