IN PCHAR Envp[])
{
ARC_STATUS Status;
+ PCSTR ArgValue;
+ PCSTR BootPath;
PCSTR FileName;
+ UCHAR DriveNumber = 0;
+ ULONG PartitionNumber = 0;
ULONG FileId;
ULONG BytesRead;
+ CHAR ArcPath[MAX_PATH];
/* Find all the message box settings and run them */
UiShowMessageBoxesInArgv(Argc, Argv);
- /* Read the file name */
+ /*
+ * Check whether we have a "BootPath" value (takes precedence
+ * over both "BootDrive" and "BootPartition").
+ */
+ BootPath = GetArgumentValue(Argc, Argv, "BootPath");
+ if (!BootPath || !*BootPath)
+ {
+ /* We don't have one, check whether we use "BootDrive" and "BootPartition" */
+
+ /* Retrieve the boot drive (optional, fall back to using default path otherwise) */
+ ArgValue = GetArgumentValue(Argc, Argv, "BootDrive");
+ if (ArgValue && *ArgValue)
+ {
+ DriveNumber = DriveMapGetBiosDriveNumber(ArgValue);
+
+ /* Retrieve the boot partition (not optional and cannot be zero) */
+ PartitionNumber = 0;
+ ArgValue = GetArgumentValue(Argc, Argv, "BootPartition");
+ if (ArgValue && *ArgValue)
+ PartitionNumber = atoi(ArgValue);
+ if (PartitionNumber == 0)
+ {
+ UiMessageBox("Boot partition cannot be 0!");
+ return EINVAL;
+ }
+
+ /* Construct the corresponding ARC path */
+ ConstructArcPath(ArcPath, "", DriveNumber, PartitionNumber);
+ *strrchr(ArcPath, '\\') = ANSI_NULL; // Trim the trailing path separator.
+
+ BootPath = ArcPath;
+ }
+ else
+ {
+ /* Fall back to using the system partition as default path */
+ BootPath = GetArgumentValue(Argc, Argv, "SystemPartition");
+ }
+ }
+
+ /* Retrieve the file name */
FileName = GetArgumentValue(Argc, Argv, "BootSectorFile");
- if (!FileName)
+ if (!FileName || !*FileName)
{
UiMessageBox("Boot sector file not specified for selected OS!");
return EINVAL;
}
- FileId = FsOpenFile(FileName);
- if (!FileId)
+ /* Open the boot sector file */
+ Status = FsOpenFile(FileName, BootPath, OpenReadOnly, &FileId);
+ if (Status != ESUCCESS)
{
- UiMessageBox("%s not found.", FileName);
- return ENOENT;
+ UiMessageBox("Unable to open %s", FileName);
+ return Status;
}
- /* Read boot sector */
+ /* Now try to load the boot sector. If this fails then abort. */
Status = ArcRead(FileId, (PVOID)0x7c00, 512, &BytesRead);
ArcClose(FileId);
if ((Status != ESUCCESS) || (BytesRead != 512))
{
- UiMessageBox("Unable to read boot sector.");
+ UiMessageBox("Unable to load boot sector.");
return EIO;
}
UiUnInitialize("Booting...");
IniCleanup();
- /*
- * Don't stop the floppy drive motor when we
- * are just booting a bootsector, or drive, or partition.
- * If we were to stop the floppy motor then
- * the BIOS wouldn't be informed and if the
- * next read is to a floppy then the BIOS will
- * still think the motor is on and this will
- * result in a read error.
- */
- // DiskStopFloppyMotor();
- /* NOTE: Don't touch FrldrBootDrive */
- ChainLoadBiosBootSectorCode();
- Reboot(); /* Must not return! */
+ ChainLoadBiosBootSectorCode(0 /*DriveNumber*/, 0 /*PartitionNumber*/);
+ /* Must not return! */
return ESUCCESS;
}
static ARC_STATUS
LoadAndBootPartitionOrDrive(
IN UCHAR DriveNumber,
- IN ULONG PartitionNumber OPTIONAL)
+ IN ULONG PartitionNumber OPTIONAL,
+ IN PCSTR BootPath OPTIONAL)
{
ARC_STATUS Status;
ULONG FileId;
ULONG BytesRead;
CHAR ArcPath[MAX_PATH];
- /* Construct the corresponding ARC path */
- ConstructArcPath(ArcPath, "", DriveNumber, PartitionNumber);
- *strrchr(ArcPath, '\\') = ANSI_NULL; // Trim the trailing path separator.
+ /*
+ * If the user specifies an ARC "BootPath" value, it takes precedence
+ * over both the DriveNumber and PartitionNumber options.
+ */
+ if (BootPath && *BootPath)
+ {
+ PCSTR FileName = NULL;
+
+ /*
+ * Retrieve the BIOS drive and partition numbers; verify also that the
+ * path is "valid" in the sense that it must not contain any file name.
+ */
+ if (!DissectArcPath(BootPath, &FileName, &DriveNumber, &PartitionNumber) ||
+ (FileName && *FileName))
+ {
+ return EINVAL;
+ }
+ }
+ else
+ {
+ /* We don't have one, so construct the corresponding ARC path */
+ ConstructArcPath(ArcPath, "", DriveNumber, PartitionNumber);
+ *strrchr(ArcPath, '\\') = ANSI_NULL; // Trim the trailing path separator.
+
+ BootPath = ArcPath;
+ }
/* Open the volume */
- Status = ArcOpen(ArcPath, OpenReadOnly, &FileId);
+ Status = ArcOpen((PSTR)BootPath, OpenReadOnly, &FileId);
if (Status != ESUCCESS)
{
- UiMessageBox("Unable to open %s", ArcPath);
- return ENOENT;
+ UiMessageBox("Unable to open %s", BootPath);
+ return Status;
}
/*
- * Now try to read the partition boot sector or the MBR (when PartitionNumber == 0).
+ * Now try to load the partition boot sector or the MBR (when PartitionNumber == 0).
* If this fails then abort.
*/
Status = ArcRead(FileId, (PVOID)0x7c00, 512, &BytesRead);
if ((Status != ESUCCESS) || (BytesRead != 512))
{
if (PartitionNumber != 0)
- UiMessageBox("Unable to read partition's boot sector.");
+ UiMessageBox("Unable to load partition's boot sector.");
else
- UiMessageBox("Unable to read MBR boot sector.");
+ UiMessageBox("Unable to load MBR boot sector.");
return EIO;
}
UiUnInitialize("Booting...");
IniCleanup();
- /*
- * Don't stop the floppy drive motor when we
- * are just booting a bootsector, or drive, or partition.
- * If we were to stop the floppy motor then
- * the BIOS wouldn't be informed and if the
- * next read is to a floppy then the BIOS will
- * still think the motor is on and this will
- * result in a read error.
- */
- // DiskStopFloppyMotor();
- FrldrBootDrive = DriveNumber;
- FrldrBootPartition = PartitionNumber;
- ChainLoadBiosBootSectorCode();
- Reboot(); /* Must not return! */
+ ChainLoadBiosBootSectorCode(DriveNumber, PartitionNumber);
+ /* Must not return! */
return ESUCCESS;
}
IN PCHAR Envp[])
{
PCSTR ArgValue;
- UCHAR DriveNumber;
- ULONG PartitionNumber;
+ PCSTR BootPath;
+ UCHAR DriveNumber = 0;
+ ULONG PartitionNumber = 0;
/* Find all the message box settings and run them */
UiShowMessageBoxesInArgv(Argc, Argv);
- /* Read the boot drive */
- ArgValue = GetArgumentValue(Argc, Argv, "BootDrive");
- if (!ArgValue)
+ /*
+ * Check whether we have a "BootPath" value (takes precedence
+ * over both "BootDrive" and "BootPartition").
+ */
+ BootPath = GetArgumentValue(Argc, Argv, "BootPath");
+ if (!BootPath || !*BootPath)
{
- UiMessageBox("Boot drive not specified for selected OS!");
- return EINVAL;
- }
- DriveNumber = DriveMapGetBiosDriveNumber(ArgValue);
+ /* We don't have one */
- /* Read the boot partition */
- ArgValue = GetArgumentValue(Argc, Argv, "BootPartition");
- if (!ArgValue)
- {
- UiMessageBox("Boot partition not specified for selected OS!");
- return EINVAL;
+ /* Retrieve the boot drive */
+ ArgValue = GetArgumentValue(Argc, Argv, "BootDrive");
+ if (!ArgValue || !*ArgValue)
+ {
+ UiMessageBox("Boot drive not specified for selected OS!");
+ return EINVAL;
+ }
+ DriveNumber = DriveMapGetBiosDriveNumber(ArgValue);
+
+ /* Retrieve the boot partition (optional, fall back to zero otherwise) */
+ PartitionNumber = 0;
+ ArgValue = GetArgumentValue(Argc, Argv, "BootPartition");
+ if (ArgValue && *ArgValue)
+ PartitionNumber = atoi(ArgValue);
}
- PartitionNumber = atoi(ArgValue);
- return LoadAndBootPartitionOrDrive(DriveNumber, PartitionNumber);
+ return LoadAndBootPartitionOrDrive(DriveNumber, PartitionNumber, BootPath);
}
ARC_STATUS
IN PCHAR Envp[])
{
PCSTR ArgValue;
- UCHAR DriveNumber;
+ PCSTR BootPath;
+ UCHAR DriveNumber = 0;
/* Find all the message box settings and run them */
UiShowMessageBoxesInArgv(Argc, Argv);
- /* Read the boot drive */
- ArgValue = GetArgumentValue(Argc, Argv, "BootDrive");
- if (!ArgValue)
+ /* Check whether we have a "BootPath" value (takes precedence over "BootDrive") */
+ BootPath = GetArgumentValue(Argc, Argv, "BootPath");
+ if (BootPath && *BootPath)
{
- UiMessageBox("Boot drive not specified for selected OS!");
- return EINVAL;
+ /*
+ * We have one, check that it does not contain any
+ * "partition()" specification, and fail if so.
+ */
+ if (strstr(BootPath, ")partition("))
+ {
+ UiMessageBox("Invalid 'BootPath' value!");
+ return EINVAL;
+ }
+ }
+ else
+ {
+ /* We don't, retrieve the boot drive value instead */
+ ArgValue = GetArgumentValue(Argc, Argv, "BootDrive");
+ if (!ArgValue || !*ArgValue)
+ {
+ UiMessageBox("Boot drive not specified for selected OS!");
+ return EINVAL;
+ }
+ DriveNumber = DriveMapGetBiosDriveNumber(ArgValue);
}
- DriveNumber = DriveMapGetBiosDriveNumber(ArgValue);
- return LoadAndBootPartitionOrDrive(DriveNumber, 0);
+ return LoadAndBootPartitionOrDrive(DriveNumber, 0, BootPath);
}
#endif // _M_IX86