ReactOS  0.4.14-dev-614-gbfd8a84
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 
29 typedef
30 VOID
32  IN OUT OperatingSystemItem* OperatingSystem);
33 
34 static VOID
36  IN OUT OperatingSystemItem* OperatingSystem)
37 {
38  EditCustomBootReactOS(OperatingSystem, TRUE);
39 }
40 
41 static VOID
43  IN OUT OperatingSystemItem* OperatingSystem)
44 {
45  EditCustomBootReactOS(OperatingSystem, FALSE);
46 }
47 
48 static const struct
49 {
53 } OSLoadingMethods[] =
54 {
56 
57 #if defined(_M_IX86) || defined(_M_AMD64)
58  {"Drive" , EditCustomBootDisk , LoadAndBootDevice},
59  {"Partition" , EditCustomBootPartition , LoadAndBootDevice},
60  {"BootSector" , EditCustomBootSectorFile, LoadAndBootDevice},
61  {"Linux" , EditCustomBootLinux, LoadAndBootLinux },
62 #endif
63 #ifdef _M_IX86
64  {"WindowsNT40" , EditCustomBootNTOS , LoadAndBootWindows},
65 #endif
66  {"Windows" , EditCustomBootNTOS , LoadAndBootWindows},
67  {"Windows2003" , EditCustomBootNTOS , LoadAndBootWindows},
68 };
69 
70 /* FUNCTIONS ******************************************************************/
71 
72 /*
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
76  * ARC specification.
77  */
78 PCHAR*
80  IN PCSTR LoadIdentifier,
81  IN ULONG_PTR SectionId,
82  OUT PULONG pArgc)
83 {
84  SIZE_T Size;
85  ULONG Count;
86  ULONG i;
87  ULONG Argc;
88  PCHAR* Argv;
89  PCHAR* Args;
90  PCHAR SettingName, SettingValue;
91 
92  *pArgc = 0;
93 
94  ASSERT(SectionId != 0);
95 
96  /* Validate the LoadIdentifier (to make tests simpler later) */
97  if (LoadIdentifier && !*LoadIdentifier)
98  LoadIdentifier = NULL;
99 
100  /* Count the number of operating systems in the section */
101  Count = IniGetNumSectionItems(SectionId);
102 
103  /*
104  * The argument vector contains the program name, the SystemPartition,
105  * the LoadIdentifier (optional), and the items in the OS section.
106  */
107  Argc = 2 + (LoadIdentifier ? 1 : 0) + Count;
108 
109  /* Calculate the total size needed for the string buffer of the argument vector */
110  Size = 0;
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 */
115  if (LoadIdentifier)
116  {
117  Size += (strlen("LoadIdentifier=") + strlen(LoadIdentifier) + 1) * sizeof(CHAR);
118  }
119  for (i = 0; i < Count; ++i)
120  {
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.
123  }
124  Size += sizeof(ANSI_NULL); // Final NULL-terminator.
125 
126  /* Allocate memory to hold the argument vector: pointers and string buffer */
127  Argv = FrLdrHeapAlloc(Argc * sizeof(PCHAR) + Size, TAG_STRING);
128  if (!Argv)
129  return NULL;
130 
131  /* Initialize the argument vector: loop through the section and copy the key=value options */
132  SettingName = (PCHAR)((ULONG_PTR)Argv + (Argc * sizeof(PCHAR)));
133  Args = Argv;
134  /* i == 0: Program name */
135  *Args++ = NULL;
136  /* i == 1: SystemPartition */
137  {
138  strcpy(SettingName, "SystemPartition=");
139  strcat(SettingName, FrLdrBootPath);
140 
141  *Args++ = SettingName;
142  SettingName += (strlen(SettingName) + 1);
143  }
144  /* i == 2: LoadIdentifier */
145  if (LoadIdentifier)
146  {
147  strcpy(SettingName, "LoadIdentifier=");
148  strcat(SettingName, LoadIdentifier);
149 
150  *Args++ = SettingName;
151  SettingName += (strlen(SettingName) + 1);
152  }
153  for (i = 0; i < Count; ++i)
154  {
155  Size = IniGetSectionSettingNameSize(SectionId, i);
156  SettingValue = SettingName + Size;
157  IniReadSettingByNumber(SectionId, i,
158  SettingName, Size,
159  SettingValue, IniGetSectionSettingValueSize(SectionId, i));
160  SettingName[Size - 1] = '=';
161 
162  *Args++ = SettingName;
163  SettingName += (strlen(SettingName) + 1);
164  }
165 
166 #if DBG
167  /* Dump the argument vector for debugging */
168  for (i = 0; i < Argc; ++i)
169  {
170  TRACE("Argv[%lu]: '%s'\n", i, Argv[i]);
171  }
172 #endif
173 
174  *pArgc = Argc;
175  return Argv;
176 }
177 
179 {
180  ULONG_PTR SectionId = OperatingSystem->SectionId;
181  ULONG i;
182  ULONG Argc;
183  PCHAR* Argv;
184  CHAR BootType[80];
185 
186  /* The operating system section has been opened by InitOperatingSystemList() */
187  ASSERT(SectionId != 0);
188 
189  /* Try to read the boot type */
190  *BootType = ANSI_NULL;
191  IniReadSettingByName(SectionId, "BootType", BootType, sizeof(BootType));
192 
193  /* We must have the "BootType" value (it has been possibly added by InitOperatingSystemList()) */
194  ASSERT(*BootType);
195 
196 #ifdef _M_IX86
197  /* Install the drive mapper according to this section drive mappings */
198  DriveMapMapDrivesInSection(SectionId);
199 #endif
200 
201  /* Find the suitable OS loader to start */
202  for (i = 0; ; ++i)
203  {
205  return;
207  break;
208  }
209 
210  /* Build the ARC-compatible argument vector */
211  Argv = BuildArgvForOsLoader(OperatingSystem->LoadIdentifier, SectionId, &Argc);
212  if (!Argv)
213  return; // Unexpected failure.
214 
215  /* Start the OS loader */
216  OSLoadingMethods[i].OsLoader(Argc, Argv, NULL);
217  FrLdrHeapFree(Argv, TAG_STRING);
218 }
219 
220 #ifdef HAS_OPTION_MENU_EDIT_CMDLINE
221 
223 {
224  ULONG_PTR SectionId = OperatingSystem->SectionId;
225  ULONG i;
226  CHAR BootType[80];
227 
228  /* The operating system section has been opened by InitOperatingSystemList() */
229  ASSERT(SectionId != 0);
230 
231  /* Try to read the boot type */
232  *BootType = ANSI_NULL;
233  IniReadSettingByName(SectionId, "BootType", BootType, sizeof(BootType));
234 
235  /* We must have the "BootType" value (it has been possibly added by InitOperatingSystemList()) */
236  ASSERT(*BootType);
237 
238  /* Find the suitable OS entry editor */
239  for (i = 0; ; ++i)
240  {
242  return;
244  break;
245  }
246 
247  /* Run it */
248  OSLoadingMethods[i].EditOsEntry(OperatingSystem);
249 }
250 
251 #endif // HAS_OPTION_MENU_EDIT_CMDLINE
252 
253 static LONG
255  IN ULONG_PTR FrLdrSectionId)
256 {
257  LONG TimeOut = -1;
258  CHAR TimeOutText[20];
259 
260  TimeOut = CmdLineGetTimeOut();
261  if (TimeOut >= 0)
262  return TimeOut;
263 
264  TimeOut = -1;
265 
266  if ((FrLdrSectionId != 0) &&
267  IniReadSettingByName(FrLdrSectionId, "TimeOut", TimeOutText, sizeof(TimeOutText)))
268  {
269  TimeOut = atoi(TimeOutText);
270  }
271 
272  return TimeOut;
273 }
274 
275 BOOLEAN
277  IN ULONG KeyPress,
278  IN ULONG SelectedMenuItem,
280 {
281  switch (KeyPress)
282  {
283  case KEY_F8:
284  DoOptionsMenu(&((OperatingSystemItem*)Context)[SelectedMenuItem]);
285  return TRUE;
286 
287 #ifdef HAS_OPTION_MENU_EDIT_CMDLINE
288  case KEY_F10:
289  EditOperatingSystemEntry(&((OperatingSystemItem*)Context)[SelectedMenuItem]);
290  return TRUE;
291 #endif
292 
293  default:
294  /* We didn't handle the key */
295  return FALSE;
296  }
297 }
298 
300 {
301  ULONG_PTR SectionId;
302  LONG TimeOut;
303  ULONG OperatingSystemCount;
304  OperatingSystemItem* OperatingSystemList;
305  PCSTR* OperatingSystemDisplayNames;
306  ULONG DefaultOperatingSystem;
307  ULONG SelectedOperatingSystem;
308  ULONG i;
309 
311  {
312  UiMessageBoxCritical("Error when detecting hardware.");
313  return;
314  }
315 
316 #ifdef _M_IX86
317  /* Load additional SCSI driver (if any) */
319  {
320  UiMessageBoxCritical("Unable to load additional boot device drivers.");
321  }
322 #endif
323 
324  if (!IniFileInitialize())
325  {
326  UiMessageBoxCritical("Error initializing .ini file.");
327  return;
328  }
329 
330  /* Open the [FreeLoader] section */
331  if (!IniOpenSection("FreeLoader", &SectionId))
332  {
333  UiMessageBoxCritical("Section [FreeLoader] not found in freeldr.ini.");
334  return;
335  }
336 
337  /* Debugger main initialization */
338  DebugInit(SectionId);
339 
340  /* Retrieve the default timeout */
341  TimeOut = GetTimeOut(SectionId);
342 
343  /* UI main initialization */
344  if (!UiInitialize(TRUE))
345  {
346  UiMessageBoxCritical("Unable to initialize UI.");
347  return;
348  }
349 
350  OperatingSystemList = InitOperatingSystemList(SectionId,
351  &OperatingSystemCount,
352  &DefaultOperatingSystem);
353  if (!OperatingSystemList)
354  {
355  UiMessageBox("Unable to read operating systems section in freeldr.ini.\nPress ENTER to reboot.");
356  goto Reboot;
357  }
358  if (OperatingSystemCount == 0)
359  {
360  UiMessageBox("There were no operating systems listed in freeldr.ini.\nPress ENTER to reboot.");
361  goto Reboot;
362  }
363 
364  /* Create list of display names */
365  OperatingSystemDisplayNames = FrLdrTempAlloc(sizeof(PCSTR) * OperatingSystemCount, 'mNSO');
366  if (!OperatingSystemDisplayNames)
367  goto Reboot;
368 
369  for (i = 0; i < OperatingSystemCount; i++)
370  {
371  OperatingSystemDisplayNames[i] = OperatingSystemList[i].LoadIdentifier;
372  }
373 
374  /* Find all the message box settings and run them */
375  UiShowMessageBoxesInSection(SectionId);
376 
377  for (;;)
378  {
379  /* Redraw the backdrop */
380  UiDrawBackdrop();
381 
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.",
386  TRUE,
387  OperatingSystemDisplayNames,
388  OperatingSystemCount,
389  DefaultOperatingSystem,
390  TimeOut,
391  &SelectedOperatingSystem,
392  FALSE,
394  OperatingSystemList))
395  {
396  UiMessageBox("Press ENTER to reboot.");
397  goto Reboot;
398  }
399 
400  TimeOut = -1;
401 
402  /* Load the chosen operating system */
403  LoadOperatingSystem(&OperatingSystemList[SelectedOperatingSystem]);
404  }
405 
406 Reboot:
407  UiUnInitialize("Rebooting...");
408  IniCleanup();
409  return;
410 }
VOID EditOperatingSystemEntry(IN OperatingSystemItem *OperatingSystem)
signed char * PCHAR
Definition: retypes.h:7
static LONG GetTimeOut(IN ULONG_PTR FrLdrSectionId)
Definition: bootmgr.c:254
#define IN
Definition: typedefs.h:38
VOID RunLoader(VOID)
Definition: bootmgr.c:299
#define TRUE
Definition: types.h:120
FORCEINLINE VOID FrLdrHeapFree(PVOID MemoryPointer, ULONG Tag)
Definition: mm.h:170
LONG CmdLineGetTimeOut(VOID)
Definition: cmdline.c:135
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
ARC_STATUS LoadAndBootWindows(IN ULONG Argc, IN PCHAR Argv[], IN PCHAR Envp[])
Definition: winldr.c:722
Definition: arc.h:32
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
BOOLEAN UiInitialize(BOOLEAN ShowGui)
Definition: ui.c:84
#define DebugInit(FrLdrSectionId)
Definition: debug.h:116
char CHAR
Definition: xmlstorage.h:175
ULONG LoadBootDeviceDriver(VOID)
Definition: scsiport.c:1619
DBG_DEFAULT_CHANNEL(WARNING)
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
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:463
#define KEY_F8
Definition: keycodes.h:43
#define _stricmp
Definition: cat.c:22
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define MachInitializeBootDevices()
Definition: machine.h:133
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
#define ANSI_NULL
#define WARNING
Definition: BusLogic958.h:56
#define TAG_STRING
Definition: oslist.h:22
long LONG
Definition: pedump.c:60
VOID UiMessageBox(PCSTR Format,...)
Definition: ui.c:320
FORCEINLINE PVOID FrLdrTempAlloc(_In_ SIZE_T Size, _In_ ULONG Tag)
Definition: mm.h:177
Definition: bl.h:892
unsigned char BOOLEAN
#define KEY_F10
Definition: keycodes.h:45
smooth NULL
Definition: ftsmooth.c:416
char ** Args
Definition: acdebug.h:347
ARC_STATUS(__cdecl * ARC_ENTRY_POINT)(IN ULONG Argc, IN PCHAR Argv[], IN PCHAR Envp[])
Definition: arcsupp.h:12
#define PCHAR
Definition: match.c:90
BOOLEAN IniReadSettingByName(ULONG_PTR SectionId, PCSTR SettingName, PCHAR Buffer, ULONG BufferSize)
Definition: inifile.c:147
#define TRACE(s)
Definition: solgame.cpp:4
FORCEINLINE PVOID FrLdrHeapAlloc(SIZE_T MemorySize, ULONG Tag)
Definition: mm.h:163
BOOLEAN IniOpenSection(PCSTR SectionName, ULONG_PTR *SectionId)
Definition: inifile.c:25
PCSTR BootType
Definition: bootmgr.c:50
static VOID EditCustomBootNTOS(IN OUT OperatingSystemItem *OperatingSystem)
Definition: bootmgr.c:42
VOID EditCustomBootReactOS(IN OUT OperatingSystemItem *OperatingSystem, IN BOOLEAN IsSetup)
Definition: custom.c:618
static VOID EditCustomBootReactOSSetup(IN OUT OperatingSystemItem *OperatingSystem)
Definition: bootmgr.c:35
VOID UiShowMessageBoxesInSection(IN ULONG_PTR SectionId)
Definition: ui.c:357
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
EDIT_OS_ENTRY_PROC EditOsEntry
Definition: bootmgr.c:51
ULONG IniGetSectionSettingValueSize(ULONG_PTR SectionId, ULONG SettingIndex)
Definition: inifile.c:101
VOID IniCleanup(VOID)
Definition: inifile.c:235
static const struct @151 OSLoadingMethods[]
#define VOID
Definition: acefi.h:82
VOID UiUnInitialize(PCSTR BootText)
Definition: ui.c:205
VOID(* EDIT_OS_ENTRY_PROC)(IN OUT OperatingSystemItem *OperatingSystem)
Definition: bootmgr.c:31
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
VOID UiDrawBackdrop(VOID)
Definition: ui.c:214
ULONG_PTR SIZE_T
Definition: typedefs.h:78
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
ARC_STATUS LoadReactOSSetup(IN ULONG Argc, IN PCHAR Argv[], IN PCHAR Envp[])
Definition: setupldr.c:178
unsigned int * PULONG
Definition: retypes.h:1
ARC_ENTRY_POINT OsLoader
Definition: bootmgr.c:52
_Check_return_ int __cdecl atoi(_In_z_ const char *_Str)
BOOLEAN IniFileInitialize(VOID)
Definition: ini_init.c:25
#define OUT
Definition: typedefs.h:39
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
unsigned int ULONG
Definition: retypes.h:1
ULONG IniGetSectionSettingNameSize(ULONG_PTR SectionId, ULONG SettingIndex)
Definition: inifile.c:88
ULONG IniGetNumSectionItems(ULONG_PTR SectionId)
Definition: inifile.c:54
VOID LoadOperatingSystem(IN OperatingSystemItem *OperatingSystem)
Definition: bootmgr.c:178
PCHAR * BuildArgvForOsLoader(IN PCSTR LoadIdentifier, IN ULONG_PTR SectionId, OUT PULONG pArgc)
Definition: bootmgr.c:79
const char * PCSTR
Definition: typedefs.h:51
CHAR FrLdrBootPath[MAX_PATH]
Definition: mach.c:34
OperatingSystemItem * InitOperatingSystemList(IN ULONG_PTR FrLdrSectionId, OUT PULONG OperatingSystemCount, OUT PULONG DefaultOperatingSystem)
Definition: oslist.c:46
BOOLEAN IniReadSettingByNumber(ULONG_PTR SectionId, ULONG SettingNumber, PCHAR SettingName, ULONG NameSize, PCHAR SettingValue, ULONG ValueSize)
Definition: inifile.c:114
VOID DoOptionsMenu(IN OperatingSystemItem *OperatingSystem)
Definition: options.c:92
BOOLEAN MainBootMenuKeyPressFilter(IN ULONG KeyPress, IN ULONG SelectedMenuItem, IN PVOID Context OPTIONAL)
Definition: bootmgr.c:276
VOID UiMessageBoxCritical(PCSTR MessageText)
Definition: ui.c:331
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68