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