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