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