ReactOS  0.4.15-dev-492-ga1108f6
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  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 
131 static ARC_STATUS
132 LoadPartitionOrDrive(
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  {
149  PCSTR FileName = NULL;
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 
209 static ARC_STATUS
210 LoadPartition(
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 
250 static ARC_STATUS
251 LoadDrive(
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 
294 LoadAndBootDevice(
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  /* Boot the loaded sector code */
344  /* Must not return! */
345  return ESUCCESS;
346 }
347 
348 #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:1420
VOID ConstructArcPath(PCHAR ArcPath, PCHAR SystemFolder, UCHAR Disk, ULONG Partition)
Definition: arcname.c:175
#define UlongToPtr(u)
Definition: config.h:106
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:893
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
ULONG Pc98GetBootSectorLoadAddress(IN UCHAR DriveNumber)
Definition: machpc98.c:44
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68