mirror of
https://github.com/reactos/reactos.git
synced 2024-12-31 19:42:51 +00:00
[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.
This commit is contained in:
parent
4578ee3e20
commit
85d44fca59
7 changed files with 109 additions and 76 deletions
|
@ -152,7 +152,7 @@ DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
|
||||||
MaxSectors = DiskReadBufferSize / Context->SectorSize;
|
MaxSectors = DiskReadBufferSize / Context->SectorSize;
|
||||||
SectorOffset = Context->SectorNumber + Context->SectorOffset;
|
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()
|
// In release builds assertions are disabled, however we also have sanity checks in DiskOpen()
|
||||||
ASSERT(MaxSectors > 0);
|
ASSERT(MaxSectors > 0);
|
||||||
|
|
||||||
|
@ -319,6 +319,8 @@ EnumerateHarddisks(OUT PBOOLEAN BootDriveReported)
|
||||||
DiskCount = 0;
|
DiskCount = 0;
|
||||||
DriveNumber = 0x80;
|
DriveNumber = 0x80;
|
||||||
|
|
||||||
|
ASSERT(DiskReadBufferSize > 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There are some really broken BIOSes out there. There are even BIOSes
|
* 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
|
* that happily report success when you ask them to read from non-existent
|
||||||
|
|
|
@ -571,6 +571,8 @@ PcMemFinalizeMemoryMap(
|
||||||
TRACE("DiskReadBuffer=0x%p, DiskReadBufferSize=0x%lx\n",
|
TRACE("DiskReadBuffer=0x%p, DiskReadBufferSize=0x%lx\n",
|
||||||
DiskReadBuffer, DiskReadBufferSize);
|
DiskReadBuffer, DiskReadBufferSize);
|
||||||
|
|
||||||
|
ASSERT(DiskReadBufferSize > 0);
|
||||||
|
|
||||||
/* Now reserve the range for the disk read buffer */
|
/* Now reserve the range for the disk read buffer */
|
||||||
ReserveMemory(MemoryMap,
|
ReserveMemory(MemoryMap,
|
||||||
(ULONG_PTR)DiskReadBuffer,
|
(ULONG_PTR)DiskReadBuffer,
|
||||||
|
|
|
@ -18,6 +18,24 @@ EnableA20:
|
||||||
mov al, HEX(0DF) // A20 on
|
mov al, HEX(0DF) // A20 on
|
||||||
out HEX(060), al
|
out HEX(060), al
|
||||||
call Empty8042
|
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
|
popa
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
@ -95,6 +113,13 @@ writehex_common:
|
||||||
Reboot:
|
Reboot:
|
||||||
cli
|
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) */
|
/* Set the word at location 40h:72h to 0 (cold reboot) */
|
||||||
mov word ptr ds:[HEX(0472)], HEX(0)
|
mov word ptr ds:[HEX(0472)], HEX(0)
|
||||||
|
|
||||||
|
@ -103,8 +128,16 @@ Reboot:
|
||||||
|
|
||||||
|
|
||||||
ChainLoadBiosBootSectorCode:
|
ChainLoadBiosBootSectorCode:
|
||||||
/* Load segment registers */
|
|
||||||
cli
|
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
|
xor ax, ax
|
||||||
mov ds, ax
|
mov ds, ax
|
||||||
mov es, ax
|
mov es, ax
|
||||||
|
|
|
@ -160,7 +160,6 @@ int __cdecl Int386(int ivec, REGS* in, REGS* out);
|
||||||
// If CF is set then the call failed (usually)
|
// If CF is set then the call failed (usually)
|
||||||
#define INT386_SUCCESS(regs) ((regs.x.eflags & EFLAGS_CF) == 0)
|
#define INT386_SUCCESS(regs) ((regs.x.eflags & EFLAGS_CF) == 0)
|
||||||
|
|
||||||
void EnableA20(void);
|
|
||||||
VOID __cdecl ChainLoadBiosBootSectorCode(VOID); // Implemented in boot.S
|
VOID __cdecl ChainLoadBiosBootSectorCode(VOID); // Implemented in boot.S
|
||||||
VOID __cdecl Reboot(VOID); // Implemented in boot.S
|
VOID __cdecl Reboot(VOID); // Implemented in boot.S
|
||||||
VOID DetectHardware(VOID); // Implemented in hardware.c
|
VOID DetectHardware(VOID); // Implemented in hardware.c
|
||||||
|
|
|
@ -54,13 +54,14 @@ LoadAndBootBootSector(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read boot sector */
|
/* Read boot sector */
|
||||||
if (ArcRead(FileId, (void*)0x7c00, 512, &BytesRead) != ESUCCESS ||
|
if ((ArcRead(FileId, (PVOID)0x7c00, 512, &BytesRead) != ESUCCESS) || (BytesRead != 512))
|
||||||
(BytesRead != 512))
|
|
||||||
{
|
{
|
||||||
UiMessageBox("Unable to read boot sector.");
|
UiMessageBox("Unable to read boot sector.");
|
||||||
return EIO;
|
return EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ArcClose(FileId);
|
||||||
|
|
||||||
/* Check for validity */
|
/* Check for validity */
|
||||||
if (*((USHORT*)(0x7c00 + 0x1fe)) != 0xaa55)
|
if (*((USHORT*)(0x7c00 + 0x1fe)) != 0xaa55)
|
||||||
{
|
{
|
||||||
|
@ -81,8 +82,69 @@ LoadAndBootBootSector(
|
||||||
* result in a read error.
|
* result in a read error.
|
||||||
*/
|
*/
|
||||||
// DiskStopFloppyMotor();
|
// DiskStopFloppyMotor();
|
||||||
// DisableA20();
|
/* NOTE: Don't touch FrldrBootDrive */
|
||||||
ChainLoadBiosBootSectorCode();
|
ChainLoadBiosBootSectorCode();
|
||||||
|
Reboot(); /* Must not return! */
|
||||||
|
return ESUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ARC_STATUS
|
||||||
|
LoadAndBootPartitionOrDrive(
|
||||||
|
IN UCHAR DriveNumber,
|
||||||
|
IN ULONG PartitionNumber OPTIONAL)
|
||||||
|
{
|
||||||
|
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 (ArcOpen(ArcPath, OpenReadOnly, &FileId) != ESUCCESS)
|
||||||
|
{
|
||||||
|
UiMessageBox("Unable to open %s", ArcPath);
|
||||||
|
return ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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))
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
UiMessageBox("Invalid boot sector magic (0xaa55)");
|
||||||
|
return ENOEXEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
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! */
|
||||||
return ESUCCESS;
|
return ESUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +155,6 @@ LoadAndBootPartition(
|
||||||
IN PCHAR Envp[])
|
IN PCHAR Envp[])
|
||||||
{
|
{
|
||||||
PCSTR ArgValue;
|
PCSTR ArgValue;
|
||||||
PARTITION_TABLE_ENTRY PartitionTableEntry;
|
|
||||||
UCHAR DriveNumber;
|
UCHAR DriveNumber;
|
||||||
ULONG PartitionNumber;
|
ULONG PartitionNumber;
|
||||||
|
|
||||||
|
@ -118,43 +179,7 @@ LoadAndBootPartition(
|
||||||
}
|
}
|
||||||
PartitionNumber = atoi(ArgValue);
|
PartitionNumber = atoi(ArgValue);
|
||||||
|
|
||||||
/* Get the partition table entry */
|
return LoadAndBootPartitionOrDrive(DriveNumber, PartitionNumber);
|
||||||
if (!DiskGetPartitionEntry(DriveNumber, PartitionNumber, &PartitionTableEntry))
|
|
||||||
{
|
|
||||||
return ENOENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now try to read the partition boot sector. If this fails then abort. */
|
|
||||||
if (!MachDiskReadLogicalSectors(DriveNumber, PartitionTableEntry.SectorCountBeforePartition, 1, (PVOID)0x7C00))
|
|
||||||
{
|
|
||||||
UiMessageBox("Unable to read partition's boot sector.");
|
|
||||||
return EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for validity */
|
|
||||||
if (*((USHORT*)(0x7c00 + 0x1fe)) != 0xaa55)
|
|
||||||
{
|
|
||||||
UiMessageBox("Invalid boot sector magic (0xaa55)");
|
|
||||||
return ENOEXEC;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ARC_STATUS
|
ARC_STATUS
|
||||||
|
@ -178,37 +203,7 @@ LoadAndBootDrive(
|
||||||
}
|
}
|
||||||
DriveNumber = DriveMapGetBiosDriveNumber(ArgValue);
|
DriveNumber = DriveMapGetBiosDriveNumber(ArgValue);
|
||||||
|
|
||||||
/* Now try to read the boot sector (or mbr). If this fails then abort. */
|
return LoadAndBootPartitionOrDrive(DriveNumber, 0);
|
||||||
if (!MachDiskReadLogicalSectors(DriveNumber, 0, 1, (PVOID)0x7C00))
|
|
||||||
{
|
|
||||||
UiMessageBox("Unable to read boot sector");
|
|
||||||
return EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for validity */
|
|
||||||
if (*((USHORT*)(0x7c00 + 0x1fe)) != 0xaa55)
|
|
||||||
{
|
|
||||||
UiMessageBox("Invalid boot sector magic (0xaa55)");
|
|
||||||
return ENOEXEC;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // _M_IX86
|
#endif // _M_IX86
|
||||||
|
|
|
@ -52,6 +52,7 @@ int TuiPrintf(const char *Format, ...)
|
||||||
BOOLEAN TuiInitialize(VOID)
|
BOOLEAN TuiInitialize(VOID)
|
||||||
{
|
{
|
||||||
MachVideoHideShowTextCursor(FALSE);
|
MachVideoHideShowTextCursor(FALSE);
|
||||||
|
MachVideoSetTextCursorPosition(0, 0);
|
||||||
MachVideoClearScreen(ATTR(COLOR_GRAY, COLOR_BLACK));
|
MachVideoClearScreen(ATTR(COLOR_GRAY, COLOR_BLACK));
|
||||||
|
|
||||||
TextVideoBuffer = VideoAllocateOffScreenBuffer();
|
TextVideoBuffer = VideoAllocateOffScreenBuffer();
|
||||||
|
@ -75,6 +76,7 @@ VOID TuiUnInitialize(VOID)
|
||||||
}
|
}
|
||||||
|
|
||||||
MachVideoClearScreen(ATTR(COLOR_GRAY, COLOR_BLACK));
|
MachVideoClearScreen(ATTR(COLOR_GRAY, COLOR_BLACK));
|
||||||
|
MachVideoSetTextCursorPosition(0, 0);
|
||||||
MachVideoHideShowTextCursor(TRUE);
|
MachVideoHideShowTextCursor(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue