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