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