IN PCHAR Argv[],
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 */
- if (ArcRead(FileId, (void*)0x7c00, 512, &BytesRead) != ESUCCESS ||
- (BytesRead != 512))
+ /* 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();
- // DisableA20();
- ChainLoadBiosBootSectorCode();
+ ChainLoadBiosBootSectorCode(0 /*DriveNumber*/, 0 /*PartitionNumber*/);
+ /* Must not return! */
return ESUCCESS;
}
-ARC_STATUS
-LoadAndBootPartition(
- IN ULONG Argc,
- IN PCHAR Argv[],
- IN PCHAR Envp[])
+static ARC_STATUS
+LoadAndBootPartitionOrDrive(
+ IN UCHAR DriveNumber,
+ IN ULONG PartitionNumber OPTIONAL,
+ IN PCSTR BootPath OPTIONAL)
{
- PCSTR ArgValue;
- PARTITION_TABLE_ENTRY PartitionTableEntry;
- UCHAR DriveNumber;
- ULONG PartitionNumber;
-
- /* Find all the message box settings and run them */
- UiShowMessageBoxesInArgv(Argc, Argv);
+ ARC_STATUS Status;
+ ULONG FileId;
+ ULONG BytesRead;
+ CHAR ArcPath[MAX_PATH];
- /* Read the boot drive */
- ArgValue = GetArgumentValue(Argc, Argv, "BootDrive");
- if (!ArgValue)
+ /*
+ * If the user specifies an ARC "BootPath" value, it takes precedence
+ * over both the DriveNumber and PartitionNumber options.
+ */
+ if (BootPath && *BootPath)
{
- UiMessageBox("Boot drive not specified for selected OS!");
- return EINVAL;
- }
- DriveNumber = DriveMapGetBiosDriveNumber(ArgValue);
+ PCSTR FileName = NULL;
- /* Read the boot partition */
- ArgValue = GetArgumentValue(Argc, Argv, "BootPartition");
- if (!ArgValue)
+ /*
+ * 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
{
- UiMessageBox("Boot partition not specified for selected OS!");
- return EINVAL;
+ /* 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;
}
- PartitionNumber = atoi(ArgValue);
- /* Get the partition table entry */
- if (!DiskGetPartitionEntry(DriveNumber, PartitionNumber, &PartitionTableEntry))
+ /* Open the volume */
+ Status = ArcOpen((PSTR)BootPath, OpenReadOnly, &FileId);
+ if (Status != ESUCCESS)
{
- return ENOENT;
+ UiMessageBox("Unable to open %s", BootPath);
+ return Status;
}
- /* Now try to read the partition boot sector. If this fails then abort. */
- if (!MachDiskReadLogicalSectors(DriveNumber, PartitionTableEntry.SectorCountBeforePartition, 1, (PVOID)0x7C00))
+ /*
+ * 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);
+ ArcClose(FileId);
+ if ((Status != ESUCCESS) || (BytesRead != 512))
{
- UiMessageBox("Unable to read partition's boot sector.");
+ if (PartitionNumber != 0)
+ UiMessageBox("Unable to load partition's boot sector.");
+ else
+ 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();
- // DisableA20();
- FrldrBootDrive = DriveNumber;
- ChainLoadBiosBootSectorCode();
+ ChainLoadBiosBootSectorCode(DriveNumber, PartitionNumber);
+ /* Must not return! */
return ESUCCESS;
}
ARC_STATUS
-LoadAndBootDrive(
+LoadAndBootPartition(
IN ULONG Argc,
IN PCHAR Argv[],
IN PCHAR Envp[])
{
PCSTR ArgValue;
- UCHAR DriveNumber;
+ 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;
+ /* We don't have one */
+
+ /* 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);
}
- DriveNumber = DriveMapGetBiosDriveNumber(ArgValue);
- /* Now try to read the boot sector (or mbr). If this fails then abort. */
- if (!MachDiskReadLogicalSectors(DriveNumber, 0, 1, (PVOID)0x7C00))
+ return LoadAndBootPartitionOrDrive(DriveNumber, PartitionNumber, BootPath);
+}
+
+ARC_STATUS
+LoadAndBootDrive(
+ IN ULONG Argc,
+ IN PCHAR Argv[],
+ IN PCHAR Envp[])
+{
+ PCSTR ArgValue;
+ PCSTR BootPath;
+ UCHAR DriveNumber = 0;
+
+ /* Find all the message box settings and run them */
+ UiShowMessageBoxesInArgv(Argc, Argv);
+
+ /* Check whether we have a "BootPath" value (takes precedence over "BootDrive") */
+ BootPath = GetArgumentValue(Argc, Argv, "BootPath");
+ if (BootPath && *BootPath)
{
- UiMessageBox("Unable to read boot sector");
- return EIO;
+ /*
+ * 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;
+ }
}
-
- /* Check for validity */
- if (*((USHORT*)(0x7c00 + 0x1fe)) != 0xaa55)
+ else
{
- UiMessageBox("Invalid boot sector magic (0xaa55)");
- return ENOEXEC;
+ /* 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);
}
- 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();
- // DisableA20();
- FrldrBootDrive = DriveNumber;
- ChainLoadBiosBootSectorCode();
- return ESUCCESS;
+ return LoadAndBootPartitionOrDrive(DriveNumber, 0, BootPath);
}
#endif // _M_IX86