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