69b7d98359c13ebb31466e3fb0220507ef71a2b9
[reactos.git] / boot / freeldr / freeldr / bootmgr.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 #include <debug.h>
24
25 /* GLOBALS ********************************************************************/
26
27 typedef
28 VOID
29 (*OS_LOADING_METHOD)(IN OperatingSystemItem* OperatingSystem,
30 IN USHORT OperatingSystemVersion);
31
32 static const struct
33 {
34 PCHAR BootType;
35 USHORT OperatingSystemVersion;
36 OS_LOADING_METHOD Load;
37 } OSLoadingMethods[] =
38 {
39 {"ReactOSSetup", 0 , LoadReactOSSetup },
40
41 #ifdef _M_IX86
42 {"BootSector" , 0 , LoadAndBootBootSector},
43 {"Drive" , 0 , LoadAndBootDrive },
44 {"Partition" , 0 , LoadAndBootPartition },
45
46 {"Linux" , 0 , LoadAndBootLinux },
47
48 {"Windows" , 0 , LoadAndBootWindows },
49 {"WindowsNT40" , _WIN32_WINNT_NT4 , LoadAndBootWindows },
50 #endif
51 {"Windows2003" , _WIN32_WINNT_WS03, LoadAndBootWindows },
52 };
53
54 /* FUNCTIONS ******************************************************************/
55
56 VOID LoadOperatingSystem(IN OperatingSystemItem* OperatingSystem)
57 {
58 ULONG_PTR SectionId;
59 PCSTR SectionName = OperatingSystem->SystemPartition;
60 CHAR BootType[80];
61 ULONG i;
62
63 /* Try to open the operating system section in the .ini file */
64 if (IniOpenSection(SectionName, &SectionId))
65 {
66 /* Try to read the boot type */
67 IniReadSettingByName(SectionId, "BootType", BootType, sizeof(BootType));
68 }
69 else
70 {
71 BootType[0] = ANSI_NULL;
72 }
73
74 if (BootType[0] == ANSI_NULL && SectionName[0] != ANSI_NULL)
75 {
76 /* Try to infer the boot type value */
77 #ifdef _M_IX86
78 ULONG FileId;
79 if (ArcOpen((PSTR)SectionName, OpenReadOnly, &FileId) == ESUCCESS)
80 {
81 ArcClose(FileId);
82 strcpy(BootType, "BootSector");
83 }
84 else
85 #endif
86 {
87 strcpy(BootType, "Windows");
88 }
89 }
90
91 #if defined(_M_IX86)
92 /* Install the drive mapper according to this section drive mappings */
93 DriveMapMapDrivesInSection(SectionName);
94 #endif
95
96 /* Loop through the OS loading method table and find a suitable OS to boot */
97 for (i = 0; i < sizeof(OSLoadingMethods) / sizeof(OSLoadingMethods[0]); ++i)
98 {
99 if (_stricmp(BootType, OSLoadingMethods[i].BootType) == 0)
100 {
101 OSLoadingMethods[i].Load(OperatingSystem,
102 OSLoadingMethods[i].OperatingSystemVersion);
103 return;
104 }
105 }
106 }
107
108 ULONG GetDefaultOperatingSystem(OperatingSystemItem* OperatingSystemList, ULONG OperatingSystemCount)
109 {
110 CHAR DefaultOSText[80];
111 PCSTR DefaultOSName;
112 ULONG_PTR SectionId;
113 ULONG DefaultOS = 0;
114 ULONG Idx;
115
116 if (!IniOpenSection("FreeLoader", &SectionId))
117 return 0;
118
119 DefaultOSName = CmdLineGetDefaultOS();
120 if (DefaultOSName == NULL)
121 {
122 if (IniReadSettingByName(SectionId, "DefaultOS", DefaultOSText, sizeof(DefaultOSText)))
123 {
124 DefaultOSName = DefaultOSText;
125 }
126 }
127
128 if (DefaultOSName != NULL)
129 {
130 for (Idx = 0; Idx < OperatingSystemCount; Idx++)
131 {
132 if (_stricmp(DefaultOSName, OperatingSystemList[Idx].SystemPartition) == 0)
133 {
134 DefaultOS = Idx;
135 break;
136 }
137 }
138 }
139
140 return DefaultOS;
141 }
142
143 LONG GetTimeOut(VOID)
144 {
145 CHAR TimeOutText[20];
146 LONG TimeOut;
147 ULONG_PTR SectionId;
148
149 TimeOut = CmdLineGetTimeOut();
150 if (TimeOut >= 0)
151 return TimeOut;
152
153 if (!IniOpenSection("FreeLoader", &SectionId))
154 return -1;
155
156 if (IniReadSettingByName(SectionId, "TimeOut", TimeOutText, sizeof(TimeOutText)))
157 TimeOut = atoi(TimeOutText);
158 else
159 TimeOut = -1;
160
161 return TimeOut;
162 }
163
164 BOOLEAN MainBootMenuKeyPressFilter(ULONG KeyPress)
165 {
166 if (KeyPress == KEY_F8)
167 {
168 DoOptionsMenu();
169 return TRUE;
170 }
171
172 /* We didn't handle the key */
173 return FALSE;
174 }
175
176 VOID RunLoader(VOID)
177 {
178 ULONG_PTR SectionId;
179 ULONG OperatingSystemCount;
180 OperatingSystemItem* OperatingSystemList;
181 PCSTR* OperatingSystemDisplayNames;
182 ULONG DefaultOperatingSystem;
183 LONG TimeOut;
184 ULONG SelectedOperatingSystem;
185 ULONG i;
186
187 if (!MachInitializeBootDevices())
188 {
189 UiMessageBoxCritical("Error when detecting hardware.");
190 return;
191 }
192
193 #ifdef _M_IX86
194 /* Load additional SCSI driver (if any) */
195 if (LoadBootDeviceDriver() != ESUCCESS)
196 {
197 UiMessageBoxCritical("Unable to load additional boot device drivers.");
198 }
199 #endif
200
201 if (!IniFileInitialize())
202 {
203 UiMessageBoxCritical("Error initializing .ini file.");
204 return;
205 }
206
207 /* Debugger main initialization */
208 DebugInit(TRUE);
209
210 if (!IniOpenSection("FreeLoader", &SectionId))
211 {
212 UiMessageBoxCritical("Section [FreeLoader] not found in freeldr.ini.");
213 return;
214 }
215
216 TimeOut = GetTimeOut();
217
218 /* UI main initialization */
219 if (!UiInitialize(TRUE))
220 {
221 UiMessageBoxCritical("Unable to initialize UI.");
222 return;
223 }
224
225 OperatingSystemList = InitOperatingSystemList(&OperatingSystemCount);
226 if (!OperatingSystemList)
227 {
228 UiMessageBox("Unable to read operating systems section in freeldr.ini.\nPress ENTER to reboot.");
229 goto Reboot;
230 }
231
232 if (OperatingSystemCount == 0)
233 {
234 UiMessageBox("There were no operating systems listed in freeldr.ini.\nPress ENTER to reboot.");
235 goto Reboot;
236 }
237
238 DefaultOperatingSystem = GetDefaultOperatingSystem(OperatingSystemList, OperatingSystemCount);
239
240 /* Create list of display names */
241 OperatingSystemDisplayNames = FrLdrTempAlloc(sizeof(PCSTR) * OperatingSystemCount, 'mNSO');
242 if (!OperatingSystemDisplayNames)
243 goto Reboot;
244
245 for (i = 0; i < OperatingSystemCount; i++)
246 {
247 OperatingSystemDisplayNames[i] = OperatingSystemList[i].LoadIdentifier;
248 }
249
250 /* Find all the message box settings and run them */
251 UiShowMessageBoxesInSection("FreeLoader");
252
253 for (;;)
254 {
255 /* Redraw the backdrop */
256 UiDrawBackdrop();
257
258 /* Show the operating system list menu */
259 if (!UiDisplayMenu("Please select the operating system to start:",
260 "For troubleshooting and advanced startup options for "
261 "ReactOS, press F8.",
262 TRUE,
263 OperatingSystemDisplayNames,
264 OperatingSystemCount,
265 DefaultOperatingSystem,
266 TimeOut,
267 &SelectedOperatingSystem,
268 FALSE,
269 MainBootMenuKeyPressFilter))
270 {
271 UiMessageBox("Press ENTER to reboot.");
272 goto Reboot;
273 }
274
275 TimeOut = -1;
276
277 /* Load the chosen operating system */
278 LoadOperatingSystem(&OperatingSystemList[SelectedOperatingSystem]);
279 }
280
281 Reboot:
282 UiUnInitialize("Rebooting...");
283 return;
284 }