[FREELDR]
[reactos.git] / reactos / 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 // Load additional SCSI driver (if any)
123 if (LoadBootDeviceDriver() != ESUCCESS)
124 {
125 UiMessageBoxCritical("Unable to load additional boot device driver");
126 }
127
128 if (!IniFileInitialize())
129 {
130 UiMessageBoxCritical("Error initializing .ini file");
131 return;
132 }
133
134 if (!IniOpenSection("FreeLoader", &SectionId))
135 {
136 UiMessageBoxCritical("Section [FreeLoader] not found in freeldr.ini.");
137 return;
138 }
139 TimeOut = GetTimeOut();
140
141 if (!UiInitialize(TimeOut))
142 {
143 UiMessageBoxCritical("Unable to initialize UI.");
144 return;
145 }
146
147 OperatingSystemList = InitOperatingSystemList(&OperatingSystemCount);
148 if (!OperatingSystemList)
149 {
150 UiMessageBox("Unable to read operating systems section in freeldr.ini.\nPress ENTER to reboot.");
151 goto reboot;
152 }
153
154 if (OperatingSystemCount == 0)
155 {
156 UiMessageBox("There were no operating systems listed in freeldr.ini.\nPress ENTER to reboot.");
157 goto reboot;
158 }
159
160 DefaultOperatingSystem = GetDefaultOperatingSystem(OperatingSystemList, OperatingSystemCount);
161
162 //
163 // Create list of display names
164 //
165 OperatingSystemDisplayNames = MmHeapAlloc(sizeof(PCSTR) * OperatingSystemCount);
166 if (!OperatingSystemDisplayNames)
167 {
168 goto reboot;
169 }
170 for (i = 0; i < OperatingSystemCount; i++)
171 {
172 OperatingSystemDisplayNames[i] = OperatingSystemList[i].LoadIdentifier;
173 }
174
175 //
176 // Find all the message box settings and run them
177 //
178 UiShowMessageBoxesInSection("FreeLoader");
179
180 for (;;)
181 {
182
183 // Redraw the backdrop
184 UiDrawBackdrop();
185
186 // Show the operating system list menu
187 if (!UiDisplayMenu(OperatingSystemDisplayNames, OperatingSystemCount, DefaultOperatingSystem, TimeOut, &SelectedOperatingSystem, FALSE, MainBootMenuKeyPressFilter))
188 {
189 UiMessageBox("Press ENTER to reboot.");
190 goto reboot;
191 }
192
193 TimeOut = -1;
194
195 // Try to open the operating system section in the .ini file
196 SettingValue[0] = ANSI_NULL;
197 SectionName = OperatingSystemList[SelectedOperatingSystem].SystemPartition;
198 if (IniOpenSection(SectionName, &SectionId))
199 {
200 // Try to read the boot type
201 IniReadSettingByName(SectionId, "BootType", BootType, sizeof(BootType));
202 }
203 else
204 BootType[0] = ANSI_NULL;
205
206 if (BootType[0] == ANSI_NULL && SectionName[0] != ANSI_NULL)
207 {
208 // Try to infere boot type value
209 #ifdef __i386__
210 ULONG FileId;
211 if (ArcOpen((CHAR*)SectionName, OpenReadOnly, &FileId) == ESUCCESS)
212 {
213 ArcClose(FileId);
214 strcpy(BootType, "BootSector");
215 }
216 else
217 #endif
218 {
219 strcpy(BootType, "Windows");
220 }
221 }
222
223 // Get OS setting value
224 IniOpenSection("Operating Systems", &SectionId);
225 IniReadSettingByName(SectionId, SectionName, SettingValue, sizeof(SettingValue));
226
227 #ifndef _M_ARM
228 // Install the drive mapper according to this sections drive mappings
229 #ifdef __i386__
230 DriveMapMapDrivesInSection(SectionName);
231 #endif
232 if (_stricmp(BootType, "ReactOS") == 0)
233 {
234 LoadAndBootReactOS(SectionName);
235 }
236 #ifdef FREELDR_REACTOS_SETUP
237 else if (_stricmp(BootType, "ReactOSSetup") == 0)
238 {
239 // In future we could pass the selected OS details through this
240 // to have different install methods, etc.
241 LoadReactOSSetup();
242 }
243 #if defined(__i386__) || defined(__x86_64__)
244 else if (_stricmp(BootType, "ReactOSSetup2") == 0)
245 {
246 // WinLdr-style boot
247 LoadReactOSSetup2();
248 }
249 #endif
250 #endif
251 #ifdef __i386__
252 else if (_stricmp(BootType, "Windows") == 0)
253 {
254 LoadAndBootWindows(SectionName, SettingValue, 0);
255 }
256 else if (_stricmp(BootType, "WindowsNT40") == 0)
257 {
258 LoadAndBootWindows(SectionName, SettingValue, _WIN32_WINNT_NT4);
259 }
260 else if (_stricmp(BootType, "Windows2003") == 0)
261 {
262 LoadAndBootWindows(SectionName, SettingValue, _WIN32_WINNT_WS03);
263 }
264 else if (_stricmp(BootType, "Linux") == 0)
265 {
266 LoadAndBootLinux(SectionName, OperatingSystemDisplayNames[SelectedOperatingSystem]);
267 }
268 else if (_stricmp(BootType, "BootSector") == 0)
269 {
270 LoadAndBootBootSector(SectionName);
271 }
272 else if (_stricmp(BootType, "Partition") == 0)
273 {
274 LoadAndBootPartition(SectionName);
275 }
276 else if (_stricmp(BootType, "Drive") == 0)
277 {
278 LoadAndBootDrive(SectionName);
279 }
280 #endif
281 #else
282 LoadAndBootWindows(SectionName, SettingValue, _WIN32_WINNT_WS03);
283 #endif
284 }
285
286
287 reboot:
288 UiUnInitialize("Rebooting...");
289 return;
290 }