ReactOS 0.4.15-dev-6056-gb29b268
miscboot.c
Go to the documentation of this file.
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#if defined(_M_IX86) || defined(_M_AMD64)
21
22/* INCLUDES *******************************************************************/
23
24#include <freeldr.h>
25
26/* FUNCTIONS ******************************************************************/
27
28static ARC_STATUS
29LoadBootSector(
30 IN ULONG Argc,
31 IN PCHAR Argv[],
32 OUT PUCHAR DriveNumber,
34{
36 PCSTR ArgValue;
37 PCSTR BootPath;
39 ULONG FileId;
41 CHAR ArcPath[MAX_PATH];
42 ULONG LoadAddress;
43
44 *DriveNumber = 0;
45 *PartitionNumber = 0;
46
47 /*
48 * Check whether we have a "BootPath" value (takes precedence
49 * over both "BootDrive" and "BootPartition").
50 */
51 BootPath = GetArgumentValue(Argc, Argv, "BootPath");
52 if (!BootPath || !*BootPath)
53 {
54 /* We don't have one, check whether we use "BootDrive" and "BootPartition" */
55
56 /* Retrieve the boot drive (optional, fall back to using default path otherwise) */
57 ArgValue = GetArgumentValue(Argc, Argv, "BootDrive");
58 if (ArgValue && *ArgValue)
59 {
60 *DriveNumber = DriveMapGetBiosDriveNumber(ArgValue);
61
62 /* Retrieve the boot partition (not optional and cannot be zero) */
63 *PartitionNumber = 0;
64 ArgValue = GetArgumentValue(Argc, Argv, "BootPartition");
65 if (ArgValue && *ArgValue)
66 *PartitionNumber = atoi(ArgValue);
67 if (*PartitionNumber == 0)
68 {
69 UiMessageBox("Boot partition cannot be 0!");
70 return EINVAL;
71 }
72
73 /* Construct the corresponding ARC path */
74 ConstructArcPath(ArcPath, "", *DriveNumber, *PartitionNumber);
75 *strrchr(ArcPath, '\\') = ANSI_NULL; // Trim the trailing path separator.
76
77 BootPath = ArcPath;
78 }
79 else
80 {
81 /* Fall back to using the system partition as default path */
82 BootPath = GetArgumentValue(Argc, Argv, "SystemPartition");
83 }
84 }
85
86 /* Retrieve the file name */
87 FileName = GetArgumentValue(Argc, Argv, "BootSectorFile");
88 if (!FileName || !*FileName)
89 {
90 UiMessageBox("Boot sector file not specified for selected OS!");
91 return EINVAL;
92 }
93
94 /* Open the boot sector file */
95 Status = FsOpenFile(FileName, BootPath, OpenReadOnly, &FileId);
96 if (Status != ESUCCESS)
97 {
98 UiMessageBox("Unable to open %s", FileName);
99 return Status;
100 }
101
102#if defined(SARCH_PC98)
103 LoadAddress = Pc98GetBootSectorLoadAddress(*DriveNumber);
104#else
105 LoadAddress = 0x7C00;
106#endif
107
108 /* Now try to load the boot sector. If this fails then abort. */
109 Status = ArcRead(FileId, UlongToPtr(LoadAddress), 512, &BytesRead);
110 ArcClose(FileId);
111 if ((Status != ESUCCESS) || (BytesRead != 512))
112 {
113 UiMessageBox("Unable to load boot sector.");
114 return EIO;
115 }
116
117 /* Check for validity */
118 if (*(USHORT*)UlongToPtr(LoadAddress + 0x1FE) != 0xAA55)
119 {
120 UiMessageBox("Invalid boot sector magic (0xaa55)");
121 return ENOEXEC;
122 }
123
124 /* Reset the drive and partition numbers so as to use their default values */
125 *DriveNumber = 0;
126 *PartitionNumber = 0;
127
128 return ESUCCESS;
129}
130
131static ARC_STATUS
132LoadPartitionOrDrive(
133 IN OUT PUCHAR DriveNumber,
135 IN PCSTR BootPath OPTIONAL)
136{
138 ULONG FileId;
140 CHAR ArcPath[MAX_PATH];
141 ULONG LoadAddress;
142
143 /*
144 * The ARC "BootPath" value takes precedence over
145 * both the DriveNumber and PartitionNumber options.
146 */
147 if (BootPath && *BootPath)
148 {
150
151 /*
152 * Retrieve the BIOS drive and partition numbers; verify also that the
153 * path is "valid" in the sense that it must not contain any file name.
154 */
155 if (!DissectArcPath(BootPath, &FileName, DriveNumber, PartitionNumber) ||
156 (FileName && *FileName))
157 {
158 return EINVAL;
159 }
160 }
161 else
162 {
163 /* We don't have one, so construct the corresponding ARC path */
164 ConstructArcPath(ArcPath, "", *DriveNumber, *PartitionNumber);
165 *strrchr(ArcPath, '\\') = ANSI_NULL; // Trim the trailing path separator.
166
167 BootPath = ArcPath;
168 }
169
170 /* Open the volume */
171 Status = ArcOpen((PSTR)BootPath, OpenReadOnly, &FileId);
172 if (Status != ESUCCESS)
173 {
174 UiMessageBox("Unable to open %s", BootPath);
175 return Status;
176 }
177
178#if defined(SARCH_PC98)
179 LoadAddress = Pc98GetBootSectorLoadAddress(*DriveNumber);
180#else
181 LoadAddress = 0x7C00;
182#endif
183
184 /*
185 * Now try to load the partition boot sector or the MBR (when PartitionNumber == 0).
186 * If this fails then abort.
187 */
188 Status = ArcRead(FileId, UlongToPtr(LoadAddress), 512, &BytesRead);
189 ArcClose(FileId);
190 if ((Status != ESUCCESS) || (BytesRead != 512))
191 {
192 if (*PartitionNumber != 0)
193 UiMessageBox("Unable to load partition's boot sector.");
194 else
195 UiMessageBox("Unable to load MBR boot sector.");
196 return EIO;
197 }
198
199 /* Check for validity */
200 if (*(USHORT*)UlongToPtr(LoadAddress + 0x1FE) != 0xAA55)
201 {
202 UiMessageBox("Invalid boot sector magic (0xaa55)");
203 return ENOEXEC;
204 }
205
206 return ESUCCESS;
207}
208
209static ARC_STATUS
210LoadPartition(
211 IN ULONG Argc,
212 IN PCHAR Argv[],
213 OUT PUCHAR DriveNumber,
215{
216 PCSTR ArgValue;
217 PCSTR BootPath;
218
219 *DriveNumber = 0;
220 *PartitionNumber = 0;
221
222 /*
223 * Check whether we have a "BootPath" value (takes precedence
224 * over both "BootDrive" and "BootPartition").
225 */
226 BootPath = GetArgumentValue(Argc, Argv, "BootPath");
227 if (!BootPath || !*BootPath)
228 {
229 /* We don't have one */
230
231 /* Retrieve the boot drive */
232 ArgValue = GetArgumentValue(Argc, Argv, "BootDrive");
233 if (!ArgValue || !*ArgValue)
234 {
235 UiMessageBox("Boot drive not specified for selected OS!");
236 return EINVAL;
237 }
238 *DriveNumber = DriveMapGetBiosDriveNumber(ArgValue);
239
240 /* Retrieve the boot partition (optional, fall back to zero otherwise) */
241 *PartitionNumber = 0;
242 ArgValue = GetArgumentValue(Argc, Argv, "BootPartition");
243 if (ArgValue && *ArgValue)
244 *PartitionNumber = atoi(ArgValue);
245 }
246
247 return LoadPartitionOrDrive(DriveNumber, PartitionNumber, BootPath);
248}
249
250static ARC_STATUS
251LoadDrive(
252 IN ULONG Argc,
253 IN PCHAR Argv[],
254 OUT PUCHAR DriveNumber,
256{
257 PCSTR ArgValue;
258 PCSTR BootPath;
259
260 *DriveNumber = 0;
261 *PartitionNumber = 0;
262
263 /* Check whether we have a "BootPath" value (takes precedence over "BootDrive") */
264 BootPath = GetArgumentValue(Argc, Argv, "BootPath");
265 if (BootPath && *BootPath)
266 {
267 /*
268 * We have one, check that it does not contain any
269 * "partition()" specification, and fail if so.
270 */
271 if (strstr(BootPath, ")partition("))
272 {
273 UiMessageBox("Invalid 'BootPath' value!");
274 return EINVAL;
275 }
276 }
277 else
278 {
279 /* We don't, retrieve the boot drive value instead */
280 ArgValue = GetArgumentValue(Argc, Argv, "BootDrive");
281 if (!ArgValue || !*ArgValue)
282 {
283 UiMessageBox("Boot drive not specified for selected OS!");
284 return EINVAL;
285 }
286 *DriveNumber = DriveMapGetBiosDriveNumber(ArgValue);
287 }
288
289 return LoadPartitionOrDrive(DriveNumber, PartitionNumber, BootPath);
290}
291
292
294LoadAndBootDevice(
295 IN ULONG Argc,
296 IN PCHAR Argv[],
297 IN PCHAR Envp[])
298{
300 PCSTR ArgValue;
301 UCHAR Type;
302 UCHAR DriveNumber = 0;
304
305 /* Retrieve the (mandatory) boot type */
306 ArgValue = GetArgumentValue(Argc, Argv, "BootType");
307 if (!ArgValue || !*ArgValue)
308 return EINVAL;
309 if (_stricmp(ArgValue, "Drive") == 0)
310 Type = 1;
311 else if (_stricmp(ArgValue, "Partition") == 0)
312 Type = 2;
313 else if (_stricmp(ArgValue, "BootSector") == 0)
314 Type = 3;
315 else
316 return EINVAL;
317
318 /* Find all the message box settings and run them */
319 UiShowMessageBoxesInArgv(Argc, Argv);
320
321 /* Load the corresponding device */
322 switch (Type)
323 {
324 case 1:
325 Status = LoadDrive(Argc, Argv, &DriveNumber, &PartitionNumber);
326 break;
327 case 2:
328 Status = LoadPartition(Argc, Argv, &DriveNumber, &PartitionNumber);
329 break;
330 case 3:
331 Status = LoadBootSector(Argc, Argv, &DriveNumber, &PartitionNumber);
332 break;
333 default:
334 return EINVAL;
335 }
336 if (Status != ESUCCESS)
337 return Status;
338
339 UiUnInitialize("Booting...");
340 IniCleanup();
341
342#ifndef UEFIBOOT
343 /* Boot the loaded sector code */
345#endif
346 /* Must not return! */
347 return ESUCCESS;
348}
349
350#endif /* _M_IX86 || _M_AMD64 */
Type
Definition: Type.h:7
#define EINVAL
Definition: acclib.h:90
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
#define EIO
Definition: acclib.h:81
PCHAR GetArgumentValue(IN ULONG Argc, IN PCHAR Argv[], IN PCHAR ArgumentName)
Definition: arcsupp.c:41
BOOLEAN DissectArcPath(IN PCSTR ArcPath, OUT PCSTR *Path OPTIONAL, OUT PUCHAR DriveNumber, OUT PULONG PartitionNumber)
Definition: arcname.c:25
VOID ConstructArcPath(PCHAR ArcPath, PCHAR SystemFolder, UCHAR Disk, ULONG Partition)
Definition: arcname.c:175
#define DriveMapGetBiosDriveNumber(DeviceName)
Definition: hardware.h:35
ARC_STATUS ArcClose(ULONG FileId)
Definition: fs.c:220
ARC_STATUS ArcOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
Definition: fs.c:56
ARC_STATUS FsOpenFile(IN PCSTR FileName, IN PCSTR DefaultPath OPTIONAL, IN OPENMODE OpenMode, OUT PULONG FileId)
Definition: fs.c:268
ARC_STATUS ArcRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: fs.c:238
#define _stricmp
Definition: cat.c:22
#define NULL
Definition: types.h:112
#define MAX_PATH
Definition: compat.h:34
#define ENOEXEC
Definition: errno.h:14
#define UlongToPtr(u)
Definition: config.h:106
struct _FileName FileName
Definition: fatprocs.h:896
Status
Definition: gdiplustypes.h:25
_Check_return_ int __cdecl atoi(_In_z_ const char *_Str)
VOID IniCleanup(VOID)
Definition: inifile.c:235
ULONG Pc98GetBootSectorLoadAddress(IN UCHAR DriveNumber)
Definition: machpc98.c:44
VOID __cdecl ChainLoadBiosBootSectorCode(IN UCHAR BootDrive OPTIONAL, IN ULONG BootPartition OPTIONAL)
Definition: machpc.c:1482
#define ANSI_NULL
unsigned short USHORT
Definition: pedump.c:61
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
@ ESUCCESS
Definition: arc.h:32
ULONG ARC_STATUS
Definition: arc.h:4
@ OpenReadOnly
Definition: arc.h:65
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
uint32_t * PULONG
Definition: typedefs.h:59
char * PSTR
Definition: typedefs.h:51
const char * PCSTR
Definition: typedefs.h:52
#define IN
Definition: typedefs.h:39
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
char * PCHAR
Definition: typedefs.h:51
VOID UiShowMessageBoxesInArgv(IN ULONG Argc, IN PCHAR Argv[])
Definition: ui.c:563
VOID UiUnInitialize(PCSTR BootText)
Definition: ui.c:224
VOID UiMessageBox(PCSTR Format,...)
Definition: ui.c:357
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR _In_opt_ PLONGLONG _In_opt_ PWDF_REQUEST_SEND_OPTIONS _Out_opt_ PULONG_PTR BytesRead
Definition: wdfiotarget.h:870
_In_ ULONG _In_ ULONG PartitionNumber
Definition: iofuncs.h:2061
unsigned char UCHAR
Definition: xmlstorage.h:181
char CHAR
Definition: xmlstorage.h:175