ReactOS 0.4.15-dev-5865-g640e228
bootmgr.c
Go to the documentation of this file.
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#include <debug.h>
26
27/* GLOBALS ********************************************************************/
28
29typedef
32 IN OUT OperatingSystemItem* OperatingSystem);
33
34static VOID
36 IN OUT OperatingSystemItem* OperatingSystem)
37{
38 EditCustomBootReactOS(OperatingSystem, TRUE);
39}
40
41static VOID
43 IN OUT OperatingSystemItem* OperatingSystem)
44{
45 EditCustomBootReactOS(OperatingSystem, FALSE);
46}
47
48static const struct
49{
54{
56
57#if defined(_M_IX86) || defined(_M_AMD64)
58#ifndef UEFIBOOT
59 {"Drive" , EditCustomBootDisk , LoadAndBootDevice},
60 {"Partition" , EditCustomBootPartition , LoadAndBootDevice},
61 {"BootSector" , EditCustomBootSectorFile, LoadAndBootDevice},
62 {"Linux" , EditCustomBootLinux, LoadAndBootLinux },
63#endif
64#endif
65#ifdef _M_IX86
66 {"WindowsNT40" , EditCustomBootNTOS , LoadAndBootWindows},
67#endif
69 {"Windows2003" , EditCustomBootNTOS , LoadAndBootWindows},
70};
71
72/* FUNCTIONS ******************************************************************/
73
74/*
75 * This function converts the list of key=value options in the given operating
76 * system section into an ARC-compatible argument vector, providing in addition
77 * the extra mandatory Software Loading Environment Variables, following the
78 * ARC specification.
79 */
80PCHAR*
82 IN PCSTR LoadIdentifier,
83 IN ULONG_PTR SectionId,
84 OUT PULONG pArgc)
85{
88 ULONG i;
89 ULONG Argc;
90 PCHAR* Argv;
91 PCHAR* Args;
92 PCHAR SettingName, SettingValue;
93
94 *pArgc = 0;
95
96 ASSERT(SectionId != 0);
97
98 /* Validate the LoadIdentifier (to make tests simpler later) */
99 if (LoadIdentifier && !*LoadIdentifier)
100 LoadIdentifier = NULL;
101
102 /* Count the number of operating systems in the section */
103 Count = IniGetNumSectionItems(SectionId);
104
105 /*
106 * The argument vector contains the program name, the SystemPartition,
107 * the LoadIdentifier (optional), and the items in the OS section.
108 */
109 Argc = 2 + (LoadIdentifier ? 1 : 0) + Count;
110
111 /* Calculate the total size needed for the string buffer of the argument vector */
112 Size = 0;
113 /* i == 0: Program name */
114 /* i == 1: SystemPartition : from where FreeLdr has been started */
115 Size += (strlen("SystemPartition=") + strlen(FrLdrBootPath) + 1) * sizeof(CHAR);
116 /* i == 2: LoadIdentifier : ASCII string that may be used to associate an identifier with a set of load parameters */
117 if (LoadIdentifier)
118 {
119 Size += (strlen("LoadIdentifier=") + strlen(LoadIdentifier) + 1) * sizeof(CHAR);
120 }
121 for (i = 0; i < Count; ++i)
122 {
123 Size += IniGetSectionSettingNameSize(SectionId, i); // Counts also the NULL-terminator, that we transform into the '=' sign separator.
124 Size += IniGetSectionSettingValueSize(SectionId, i); // Counts also the NULL-terminator.
125 }
126 Size += sizeof(ANSI_NULL); // Final NULL-terminator.
127
128 /* Allocate memory to hold the argument vector: pointers and string buffer */
129 Argv = FrLdrHeapAlloc(Argc * sizeof(PCHAR) + Size, TAG_STRING);
130 if (!Argv)
131 return NULL;
132
133 /* Initialize the argument vector: loop through the section and copy the key=value options */
134 SettingName = (PCHAR)((ULONG_PTR)Argv + (Argc * sizeof(PCHAR)));
135 Args = Argv;
136 /* i == 0: Program name */
137 *Args++ = NULL;
138 /* i == 1: SystemPartition */
139 {
140 strcpy(SettingName, "SystemPartition=");
141 strcat(SettingName, FrLdrBootPath);
142
143 *Args++ = SettingName;
144 SettingName += (strlen(SettingName) + 1);
145 }
146 /* i == 2: LoadIdentifier */
147 if (LoadIdentifier)
148 {
149 strcpy(SettingName, "LoadIdentifier=");
150 strcat(SettingName, LoadIdentifier);
151
152 *Args++ = SettingName;
153 SettingName += (strlen(SettingName) + 1);
154 }
155 for (i = 0; i < Count; ++i)
156 {
157 Size = IniGetSectionSettingNameSize(SectionId, i);
158 SettingValue = SettingName + Size;
159 IniReadSettingByNumber(SectionId, i,
160 SettingName, Size,
161 SettingValue, IniGetSectionSettingValueSize(SectionId, i));
162 SettingName[Size - 1] = '=';
163
164 *Args++ = SettingName;
165 SettingName += (strlen(SettingName) + 1);
166 }
167
168#if DBG
169 /* Dump the argument vector for debugging */
170 for (i = 0; i < Argc; ++i)
171 {
172 TRACE("Argv[%lu]: '%s'\n", i, Argv[i]);
173 }
174#endif
175
176 *pArgc = Argc;
177 return Argv;
178}
179
181{
182 ULONG_PTR SectionId = OperatingSystem->SectionId;
183 ULONG i;
184 ULONG Argc;
185 PCHAR* Argv;
186 CHAR BootType[80];
187
188 /* The operating system section has been opened by InitOperatingSystemList() */
189 ASSERT(SectionId != 0);
190
191 /* Try to read the boot type */
193 IniReadSettingByName(SectionId, "BootType", BootType, sizeof(BootType));
194
195 /* We must have the "BootType" value (it has been possibly added by InitOperatingSystemList()) */
197
198#ifdef _M_IX86
199#ifndef UEFIBOOT
200 /* Install the drive mapper according to this section drive mappings */
201 DriveMapMapDrivesInSection(SectionId);
202#endif
203#endif
204
205 /* Find the suitable OS loader to start */
206 for (i = 0; ; ++i)
207 {
209 return;
211 break;
212 }
213
214 /* Build the ARC-compatible argument vector */
215 Argv = BuildArgvForOsLoader(OperatingSystem->LoadIdentifier, SectionId, &Argc);
216 if (!Argv)
217 return; // Unexpected failure.
218
219 /* Start the OS loader */
220 OSLoadingMethods[i].OsLoader(Argc, Argv, NULL);
222}
223
224#ifdef HAS_OPTION_MENU_EDIT_CMDLINE
225
226VOID EditOperatingSystemEntry(IN OperatingSystemItem* OperatingSystem)
227{
228 ULONG_PTR SectionId = OperatingSystem->SectionId;
229 ULONG i;
230 CHAR BootType[80];
231
232 /* The operating system section has been opened by InitOperatingSystemList() */
233 ASSERT(SectionId != 0);
234
235 /* Try to read the boot type */
237 IniReadSettingByName(SectionId, "BootType", BootType, sizeof(BootType));
238
239 /* We must have the "BootType" value (it has been possibly added by InitOperatingSystemList()) */
241
242 /* Find the suitable OS entry editor */
243 for (i = 0; ; ++i)
244 {
246 return;
248 break;
249 }
250
251 /* Run it */
252 OSLoadingMethods[i].EditOsEntry(OperatingSystem);
253}
254
255#endif // HAS_OPTION_MENU_EDIT_CMDLINE
256
257static LONG
259 IN ULONG_PTR FrLdrSectionId)
260{
261 LONG TimeOut = -1;
262 CHAR TimeOutText[20];
263
264 TimeOut = CmdLineGetTimeOut();
265 if (TimeOut >= 0)
266 return TimeOut;
267
268 TimeOut = -1;
269
270 if ((FrLdrSectionId != 0) &&
271 IniReadSettingByName(FrLdrSectionId, "TimeOut", TimeOutText, sizeof(TimeOutText)))
272 {
273 TimeOut = atoi(TimeOutText);
274 }
275
276 return TimeOut;
277}
278
281 IN ULONG KeyPress,
282 IN ULONG SelectedMenuItem,
284{
285 switch (KeyPress)
286 {
287 case KEY_F8:
288 DoOptionsMenu(&((OperatingSystemItem*)Context)[SelectedMenuItem]);
289 return TRUE;
290
291#ifdef HAS_OPTION_MENU_EDIT_CMDLINE
292 case KEY_F10:
293 EditOperatingSystemEntry(&((OperatingSystemItem*)Context)[SelectedMenuItem]);
294 return TRUE;
295#endif
296
297 default:
298 /* We didn't handle the key */
299 return FALSE;
300 }
301}
302
304{
305 ULONG_PTR SectionId;
306 LONG TimeOut;
307 ULONG OperatingSystemCount;
308 OperatingSystemItem* OperatingSystemList;
309 PCSTR* OperatingSystemDisplayNames;
310 ULONG DefaultOperatingSystem;
311 ULONG SelectedOperatingSystem;
312 ULONG i;
313
315 {
316 UiMessageBoxCritical("Error when detecting hardware.");
317 return;
318 }
319
320#ifdef _M_IX86
321#ifndef UEFIBOOT
322 /* Load additional SCSI driver (if any) */
324 {
325 UiMessageBoxCritical("Unable to load additional boot device drivers.");
326 }
327#endif
328#endif
329
330 if (!IniFileInitialize())
331 {
332 UiMessageBoxCritical("Error initializing .ini file.");
333 return;
334 }
335
336 /* Open the [FreeLoader] section */
337 if (!IniOpenSection("FreeLoader", &SectionId))
338 {
339 UiMessageBoxCritical("Section [FreeLoader] not found in freeldr.ini.");
340 return;
341 }
342
343 /* Debugger main initialization */
344 DebugInit(SectionId);
345
346 /* Retrieve the default timeout */
347 TimeOut = GetTimeOut(SectionId);
348
349 /* UI main initialization */
350 if (!UiInitialize(TRUE))
351 {
352 UiMessageBoxCritical("Unable to initialize UI.");
353 return;
354 }
355
356 OperatingSystemList = InitOperatingSystemList(SectionId,
357 &OperatingSystemCount,
358 &DefaultOperatingSystem);
359 if (!OperatingSystemList)
360 {
361 UiMessageBox("Unable to read operating systems section in freeldr.ini.\nPress ENTER to reboot.");
362 goto Reboot;
363 }
364 if (OperatingSystemCount == 0)
365 {
366 UiMessageBox("There were no operating systems listed in freeldr.ini.\nPress ENTER to reboot.");
367 goto Reboot;
368 }
369
370 /* Create list of display names */
371 OperatingSystemDisplayNames = FrLdrTempAlloc(sizeof(PCSTR) * OperatingSystemCount, 'mNSO');
372 if (!OperatingSystemDisplayNames)
373 goto Reboot;
374
375 for (i = 0; i < OperatingSystemCount; i++)
376 {
377 OperatingSystemDisplayNames[i] = OperatingSystemList[i].LoadIdentifier;
378 }
379
380 /* Find all the message box settings and run them */
382
383 for (;;)
384 {
385 /* Redraw the backdrop */
387
388 /* Show the operating system list menu */
389 if (!UiDisplayMenu("Please select the operating system to start:",
390 "For troubleshooting and advanced startup options for "
391 "ReactOS, press F8.",
392 TRUE,
393 OperatingSystemDisplayNames,
394 OperatingSystemCount,
395 DefaultOperatingSystem,
396 TimeOut,
397 &SelectedOperatingSystem,
398 FALSE,
400 OperatingSystemList))
401 {
402 UiMessageBox("Press ENTER to reboot.");
403 goto Reboot;
404 }
405
406 TimeOut = -1;
407
408 /* Load the chosen operating system */
409 LoadOperatingSystem(&OperatingSystemList[SelectedOperatingSystem]);
410
411 /* If we get there, the OS loader failed. As it may have
412 * messed up the display, re-initialize the UI. */
413#ifndef _M_ARM
415#endif
417 }
418
419Reboot:
420 UiUnInitialize("Rebooting...");
421 IniCleanup();
422 return;
423}
#define WARNING
Definition: BusLogic958.h:56
unsigned char BOOLEAN
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
char ** Args
Definition: acdebug.h:353
#define VOID
Definition: acefi.h:82
ARC_STATUS(__cdecl * ARC_ENTRY_POINT)(IN ULONG Argc, IN PCHAR Argv[], IN PCHAR Envp[])
Definition: arcsupp.h:12
@ Reboot
Definition: bl.h:891
VOID EditCustomBootReactOS(IN OUT OperatingSystemItem *OperatingSystem, IN BOOLEAN IsSetup)
Definition: custom.c:619
ULONG LoadBootDeviceDriver(VOID)
Definition: scsiport.c:1626
#define DebugInit(FrLdrSectionId)
Definition: debug.h:117
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:103
#define MachInitializeBootDevices()
Definition: machine.h:133
FORCEINLINE VOID FrLdrHeapFree(PVOID MemoryPointer, ULONG Tag)
Definition: mm.h:181
FORCEINLINE PVOID FrLdrTempAlloc(_In_ SIZE_T Size, _In_ ULONG Tag)
Definition: mm.h:188
FORCEINLINE PVOID FrLdrHeapAlloc(SIZE_T MemorySize, ULONG Tag)
Definition: mm.h:174
VOID DoOptionsMenu(IN OperatingSystemItem *OperatingSystem)
Definition: options.c:92
#define _stricmp
Definition: cat.c:22
LONG CmdLineGetTimeOut(VOID)
Definition: cmdline.c:135
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
ARC_ENTRY_POINT OsLoader
Definition: bootmgr.c:52
VOID LoadOperatingSystem(IN OperatingSystemItem *OperatingSystem)
Definition: bootmgr.c:180
VOID(* EDIT_OS_ENTRY_PROC)(IN OUT OperatingSystemItem *OperatingSystem)
Definition: bootmgr.c:31
static VOID EditCustomBootNTOS(IN OUT OperatingSystemItem *OperatingSystem)
Definition: bootmgr.c:42
static VOID EditCustomBootReactOSSetup(IN OUT OperatingSystemItem *OperatingSystem)
Definition: bootmgr.c:35
BOOLEAN MainBootMenuKeyPressFilter(IN ULONG KeyPress, IN ULONG SelectedMenuItem, IN PVOID Context OPTIONAL)
Definition: bootmgr.c:280
static LONG GetTimeOut(IN ULONG_PTR FrLdrSectionId)
Definition: bootmgr.c:258
EDIT_OS_ENTRY_PROC EditOsEntry
Definition: bootmgr.c:51
VOID RunLoader(VOID)
Definition: bootmgr.c:303
static const struct @149 OSLoadingMethods[]
PCSTR BootType
Definition: bootmgr.c:50
PCHAR * BuildArgvForOsLoader(IN PCSTR LoadIdentifier, IN ULONG_PTR SectionId, OUT PULONG pArgc)
Definition: bootmgr.c:81
CCHAR FrLdrBootPath[MAX_PATH]
Definition: freeldr.c:39
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
_Check_return_ int __cdecl atoi(_In_z_ const char *_Str)
ARC_STATUS LoadReactOSSetup(IN ULONG Argc, IN PCHAR Argv[], IN PCHAR Envp[])
Definition: setupldr.c:475
ARC_STATUS LoadAndBootWindows(IN ULONG Argc, IN PCHAR Argv[], IN PCHAR Envp[])
Definition: winldr.c:961
ULONG IniGetSectionSettingValueSize(ULONG_PTR SectionId, ULONG SettingIndex)
Definition: inifile.c:101
ULONG IniGetNumSectionItems(ULONG_PTR SectionId)
Definition: inifile.c:54
BOOLEAN IniFileInitialize(VOID)
Definition: ini_init.c:25
ULONG IniGetSectionSettingNameSize(ULONG_PTR SectionId, ULONG SettingIndex)
Definition: inifile.c:88
BOOLEAN IniReadSettingByNumber(ULONG_PTR SectionId, ULONG SettingNumber, PCHAR SettingName, ULONG NameSize, PCHAR SettingValue, ULONG ValueSize)
Definition: inifile.c:114
BOOLEAN IniReadSettingByName(ULONG_PTR SectionId, PCSTR SettingName, PCHAR Buffer, ULONG BufferSize)
Definition: inifile.c:147
BOOLEAN IniOpenSection(PCSTR SectionName, ULONG_PTR *SectionId)
Definition: inifile.c:25
VOID IniCleanup(VOID)
Definition: inifile.c:235
#define KEY_F8
Definition: keycodes.h:58
#define KEY_F10
Definition: keycodes.h:60
#define PCHAR
Definition: match.c:90
#define ASSERT(a)
Definition: mode.c:44
int Count
Definition: noreturn.cpp:7
#define ANSI_NULL
#define TAG_STRING
Definition: oslist.h:22
OperatingSystemItem * InitOperatingSystemList(IN ULONG_PTR FrLdrSectionId, OUT PULONG OperatingSystemCount, OUT PULONG DefaultOperatingSystem)
Definition: oslist.c:46
long LONG
Definition: pedump.c:60
@ ESUCCESS
Definition: arc.h:32
#define TRACE(s)
Definition: solgame.cpp:4
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
VOID(* UnInitialize)(VOID)
Definition: ui.h:248
uint32_t * PULONG
Definition: typedefs.h:59
ULONG_PTR SIZE_T
Definition: typedefs.h:80
const char * PCSTR
Definition: typedefs.h:52
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
char * PCHAR
Definition: typedefs.h:51
VOID UiMessageBoxCritical(PCSTR MessageText)
Definition: ui.c:374
BOOLEAN UiDisplayMenu(IN PCSTR MenuHeader, IN PCSTR MenuFooter OPTIONAL, IN BOOLEAN ShowBootOptions, IN PCSTR MenuItemList[], IN ULONG MenuItemCount, IN ULONG DefaultMenuItem, IN LONG MenuTimeOut, OUT PULONG SelectedMenuItem, IN BOOLEAN CanEscape, IN UiMenuKeyPressFilterCallback KeyPressFilter OPTIONAL, IN PVOID Context OPTIONAL)
Definition: ui.c:631
VOID UiShowMessageBoxesInSection(IN ULONG_PTR SectionId)
Definition: ui.c:550
UIVTBL UiVtbl
Definition: ui.c:70
VOID UiUnInitialize(PCSTR BootText)
Definition: ui.c:230
VOID UiDrawBackdrop(VOID)
Definition: ui.c:239
VOID UiMessageBox(PCSTR Format,...)
Definition: ui.c:363
BOOLEAN UiInitialize(BOOLEAN ShowUi)
Definition: ui.c:98
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
char CHAR
Definition: xmlstorage.h:175