https://git.reactos.org/?p=reactos.git;a=commitdiff;h=85d44fca5923089cd10e0…
commit 85d44fca5923089cd10e03efe58c4854a2b8b176
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Tue Aug 13 17:34:57 2019 +0200
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Tue Aug 13 23:07:01 2019 +0200
[FREELDR] Minor enhancements for disk/partition boot and UI.
- Factor out disk & partition opening in LoadAndBootPartition() and
LoadAndBootDrive() into a LoadAndBootPartitionOrDrive() helper.
- Use ARC paths and ArcOpen()/ArcRead() instead of calling the
machine-specific BIOS-oriented DiskGetPartitionEntry() and
MachDiskReadLogicalSectors() functions to open the disk/partition
and read their boot sectors.
- Don't forget to close the opened boot sector file in LoadAndBootBootSector().
- Add assertions for DiskReadBufferSize in PcMemFinalizeMemoryMap()
and EnumerateHarddisks().
- x86/amd64 only:
* Add a DisableA20 helper for disabling the A20 line, before rebooting
back, or chain-load a boot sector, into 16-bit world.
Also pulse the output port of the keyboard controller to clear out
its state after having set the state of the A20 line.
* In addition to disabling the A20 line when rebooting or chain-loading
a boot sector, reset the video back to 80x25 text mode.
- Reset the cursor position back to the origin when initializing or
terminating the TUI.
---
boot/freeldr/freeldr/arch/i386/hwdisk.c | 4 +-
boot/freeldr/freeldr/arch/i386/pcmem.c | 2 +
boot/freeldr/freeldr/arch/realmode/helpers.inc | 35 ++++++-
boot/freeldr/freeldr/disk/disk.c | 2 +-
boot/freeldr/freeldr/include/arch/pc/pcbios.h | 1 -
boot/freeldr/freeldr/miscboot.c | 125 ++++++++++++-------------
boot/freeldr/freeldr/ui/tui.c | 2 +
7 files changed, 102 insertions(+), 69 deletions(-)
diff --git a/boot/freeldr/freeldr/arch/i386/hwdisk.c
b/boot/freeldr/freeldr/arch/i386/hwdisk.c
index 853d37f0981..fde0d8acf89 100644
--- a/boot/freeldr/freeldr/arch/i386/hwdisk.c
+++ b/boot/freeldr/freeldr/arch/i386/hwdisk.c
@@ -152,7 +152,7 @@ DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
MaxSectors = DiskReadBufferSize / Context->SectorSize;
SectorOffset = Context->SectorNumber + Context->SectorOffset;
- // If MaxSectors is 0, this will lead to infinite loop
+ // If MaxSectors is 0, this will lead to infinite loop.
// In release builds assertions are disabled, however we also have sanity checks in
DiskOpen()
ASSERT(MaxSectors > 0);
@@ -319,6 +319,8 @@ EnumerateHarddisks(OUT PBOOLEAN BootDriveReported)
DiskCount = 0;
DriveNumber = 0x80;
+ ASSERT(DiskReadBufferSize > 0);
+
/*
* There are some really broken BIOSes out there. There are even BIOSes
* that happily report success when you ask them to read from non-existent
diff --git a/boot/freeldr/freeldr/arch/i386/pcmem.c
b/boot/freeldr/freeldr/arch/i386/pcmem.c
index 4dd709b247c..b3b5761d957 100644
--- a/boot/freeldr/freeldr/arch/i386/pcmem.c
+++ b/boot/freeldr/freeldr/arch/i386/pcmem.c
@@ -571,6 +571,8 @@ PcMemFinalizeMemoryMap(
TRACE("DiskReadBuffer=0x%p, DiskReadBufferSize=0x%lx\n",
DiskReadBuffer, DiskReadBufferSize);
+ ASSERT(DiskReadBufferSize > 0);
+
/* Now reserve the range for the disk read buffer */
ReserveMemory(MemoryMap,
(ULONG_PTR)DiskReadBuffer,
diff --git a/boot/freeldr/freeldr/arch/realmode/helpers.inc
b/boot/freeldr/freeldr/arch/realmode/helpers.inc
index 8f5db395892..981354826ae 100644
--- a/boot/freeldr/freeldr/arch/realmode/helpers.inc
+++ b/boot/freeldr/freeldr/arch/realmode/helpers.inc
@@ -18,6 +18,24 @@ EnableA20:
mov al, HEX(0DF) // A20 on
out HEX(060), al
call Empty8042
+ mov al, HEX(0FF) // pulse output port
+ out HEX(064), al
+ call Empty8042
+ popa
+ ret
+
+DisableA20:
+ pusha
+ call Empty8042
+ mov al, HEX(0D1) // command write
+ out HEX(064), al
+ call Empty8042
+ mov al, HEX(0DD) // A20 off
+ out HEX(060), al
+ call Empty8042
+ mov al, HEX(0FF) // pulse output port
+ out HEX(064), al
+ call Empty8042
popa
ret
@@ -95,6 +113,13 @@ writehex_common:
Reboot:
cli
+ /* Disable A20 address line */
+ call DisableA20
+
+ /* Set the video back to 80x25 text mode */
+ mov ax, HEX(0003)
+ int HEX(10)
+
/* Set the word at location 40h:72h to 0 (cold reboot) */
mov word ptr ds:[HEX(0472)], HEX(0)
@@ -103,8 +128,16 @@ Reboot:
ChainLoadBiosBootSectorCode:
- /* Load segment registers */
cli
+
+ /* Disable A20 address line */
+ call DisableA20
+
+ /* Set the video back to 80x25 text mode */
+ mov ax, HEX(0003)
+ int HEX(10)
+
+ /* Load segment registers */
xor ax, ax
mov ds, ax
mov es, ax
diff --git a/boot/freeldr/freeldr/disk/disk.c b/boot/freeldr/freeldr/disk/disk.c
index 11cc0a7a63d..e9579a0beab 100644
--- a/boot/freeldr/freeldr/disk/disk.c
+++ b/boot/freeldr/freeldr/disk/disk.c
@@ -81,7 +81,7 @@ PCSTR DiskGetErrorCodeString(ULONG ErrorCode)
case 0xE0: return "fixed disk status error/Error reg = 0";
case 0xFF: return "sense operation failed";
- default: return "unknown error code";
+ default: return "unknown error code";
}
}
diff --git a/boot/freeldr/freeldr/include/arch/pc/pcbios.h
b/boot/freeldr/freeldr/include/arch/pc/pcbios.h
index 5ad273f0442..6faeb06986d 100644
--- a/boot/freeldr/freeldr/include/arch/pc/pcbios.h
+++ b/boot/freeldr/freeldr/include/arch/pc/pcbios.h
@@ -160,7 +160,6 @@ int __cdecl Int386(int ivec, REGS* in, REGS* out);
// If CF is set then the call failed (usually)
#define INT386_SUCCESS(regs) ((regs.x.eflags & EFLAGS_CF) == 0)
-void EnableA20(void);
VOID __cdecl ChainLoadBiosBootSectorCode(VOID); // Implemented in boot.S
VOID __cdecl Reboot(VOID); // Implemented in boot.S
VOID DetectHardware(VOID); // Implemented in hardware.c
diff --git a/boot/freeldr/freeldr/miscboot.c b/boot/freeldr/freeldr/miscboot.c
index 0d12e4bc2c6..535f9d6efab 100644
--- a/boot/freeldr/freeldr/miscboot.c
+++ b/boot/freeldr/freeldr/miscboot.c
@@ -54,13 +54,14 @@ LoadAndBootBootSector(
}
/* Read boot sector */
- if (ArcRead(FileId, (void*)0x7c00, 512, &BytesRead) != ESUCCESS ||
- (BytesRead != 512))
+ if ((ArcRead(FileId, (PVOID)0x7c00, 512, &BytesRead) != ESUCCESS) || (BytesRead
!= 512))
{
UiMessageBox("Unable to read boot sector.");
return EIO;
}
+ ArcClose(FileId);
+
/* Check for validity */
if (*((USHORT*)(0x7c00 + 0x1fe)) != 0xaa55)
{
@@ -81,56 +82,45 @@ LoadAndBootBootSector(
* result in a read error.
*/
// DiskStopFloppyMotor();
- // DisableA20();
+ /* NOTE: Don't touch FrldrBootDrive */
ChainLoadBiosBootSectorCode();
+ Reboot(); /* 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)
{
- PCSTR ArgValue;
- PARTITION_TABLE_ENTRY PartitionTableEntry;
- UCHAR DriveNumber;
- ULONG PartitionNumber;
-
- /* Find all the message box settings and run them */
- UiShowMessageBoxesInArgv(Argc, Argv);
-
- /* Read the boot drive */
- ArgValue = GetArgumentValue(Argc, Argv, "BootDrive");
- if (!ArgValue)
- {
- UiMessageBox("Boot drive not specified for selected OS!");
- return EINVAL;
- }
- DriveNumber = DriveMapGetBiosDriveNumber(ArgValue);
-
- /* Read the boot partition */
- ArgValue = GetArgumentValue(Argc, Argv, "BootPartition");
- if (!ArgValue)
- {
- UiMessageBox("Boot partition not specified for selected OS!");
- return EINVAL;
- }
- PartitionNumber = atoi(ArgValue);
+ ULONG FileId;
+ ULONG BytesRead;
+ CHAR ArcPath[MAX_PATH];
- /* Get the partition table entry */
- if (!DiskGetPartitionEntry(DriveNumber, PartitionNumber, &PartitionTableEntry))
+ /* Construct the corresponding ARC path */
+ ConstructArcPath(ArcPath, "", DriveNumber, PartitionNumber);
+ *strrchr(ArcPath, '\\') = ANSI_NULL; // Trim the trailing path separator.
+ if (ArcOpen(ArcPath, OpenReadOnly, &FileId) != ESUCCESS)
{
+ UiMessageBox("Unable to open %s", ArcPath);
return ENOENT;
}
- /* Now try to read the partition boot sector. If this fails then abort. */
- if (!MachDiskReadLogicalSectors(DriveNumber,
PartitionTableEntry.SectorCountBeforePartition, 1, (PVOID)0x7C00))
+ /*
+ * Now try to read the partition boot sector or the MBR (when PartitionNumber == 0).
+ * If this fails then abort.
+ */
+ if ((ArcRead(FileId, (PVOID)0x7c00, 512, &BytesRead) != ESUCCESS) || (BytesRead
!= 512))
{
- UiMessageBox("Unable to read partition's boot sector.");
+ if (PartitionNumber != 0)
+ UiMessageBox("Unable to read partition's boot sector.");
+ else
+ UiMessageBox("Unable to read MBR boot sector.");
return EIO;
}
+ ArcClose(FileId);
+
/* Check for validity */
if (*((USHORT*)(0x7c00 + 0x1fe)) != 0xaa55)
{
@@ -151,20 +141,22 @@ LoadAndBootPartition(
* result in a read error.
*/
// DiskStopFloppyMotor();
- // DisableA20();
FrldrBootDrive = DriveNumber;
+ FrldrBootPartition = PartitionNumber;
ChainLoadBiosBootSectorCode();
+ Reboot(); /* Must not return! */
return ESUCCESS;
}
ARC_STATUS
-LoadAndBootDrive(
+LoadAndBootPartition(
IN ULONG Argc,
IN PCHAR Argv[],
IN PCHAR Envp[])
{
PCSTR ArgValue;
UCHAR DriveNumber;
+ ULONG PartitionNumber;
/* Find all the message box settings and run them */
UiShowMessageBoxesInArgv(Argc, Argv);
@@ -178,37 +170,40 @@ LoadAndBootDrive(
}
DriveNumber = DriveMapGetBiosDriveNumber(ArgValue);
- /* Now try to read the boot sector (or mbr). If this fails then abort. */
- if (!MachDiskReadLogicalSectors(DriveNumber, 0, 1, (PVOID)0x7C00))
+ /* Read the boot partition */
+ ArgValue = GetArgumentValue(Argc, Argv, "BootPartition");
+ if (!ArgValue)
{
- UiMessageBox("Unable to read boot sector");
- return EIO;
+ UiMessageBox("Boot partition not specified for selected OS!");
+ return EINVAL;
}
+ PartitionNumber = atoi(ArgValue);
- /* Check for validity */
- if (*((USHORT*)(0x7c00 + 0x1fe)) != 0xaa55)
+ return LoadAndBootPartitionOrDrive(DriveNumber, PartitionNumber);
+}
+
+ARC_STATUS
+LoadAndBootDrive(
+ IN ULONG Argc,
+ IN PCHAR Argv[],
+ IN PCHAR Envp[])
+{
+ PCSTR ArgValue;
+ UCHAR DriveNumber;
+
+ /* Find all the message box settings and run them */
+ UiShowMessageBoxesInArgv(Argc, Argv);
+
+ /* Read the boot drive */
+ ArgValue = GetArgumentValue(Argc, Argv, "BootDrive");
+ if (!ArgValue)
{
- UiMessageBox("Invalid boot sector magic (0xaa55)");
- return ENOEXEC;
+ 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);
}
#endif // _M_IX86
diff --git a/boot/freeldr/freeldr/ui/tui.c b/boot/freeldr/freeldr/ui/tui.c
index 8fd16aabc72..44f80163a5b 100644
--- a/boot/freeldr/freeldr/ui/tui.c
+++ b/boot/freeldr/freeldr/ui/tui.c
@@ -52,6 +52,7 @@ int TuiPrintf(const char *Format, ...)
BOOLEAN TuiInitialize(VOID)
{
MachVideoHideShowTextCursor(FALSE);
+ MachVideoSetTextCursorPosition(0, 0);
MachVideoClearScreen(ATTR(COLOR_GRAY, COLOR_BLACK));
TextVideoBuffer = VideoAllocateOffScreenBuffer();
@@ -75,6 +76,7 @@ VOID TuiUnInitialize(VOID)
}
MachVideoClearScreen(ATTR(COLOR_GRAY, COLOR_BLACK));
+ MachVideoSetTextCursorPosition(0, 0);
MachVideoHideShowTextCursor(TRUE);
}