mirror of
https://github.com/reactos/reactos.git
synced 2024-12-13 14:13:36 +08: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
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,8 +82,69 @@ LoadAndBootBootSector(
|
||||
* result in a read error.
|
||||
*/
|
||||
// DiskStopFloppyMotor();
|
||||
// DisableA20();
|
||||
/* NOTE: Don't touch FrldrBootDrive */
|
||||
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;
|
||||
}
|
||||
|
||||
@ -93,7 +155,6 @@ LoadAndBootPartition(
|
||||
IN PCHAR Envp[])
|
||||
{
|
||||
PCSTR ArgValue;
|
||||
PARTITION_TABLE_ENTRY PartitionTableEntry;
|
||||
UCHAR DriveNumber;
|
||||
ULONG PartitionNumber;
|
||||
|
||||
@ -118,43 +179,7 @@ LoadAndBootPartition(
|
||||
}
|
||||
PartitionNumber = atoi(ArgValue);
|
||||
|
||||
/* Get the partition table entry */
|
||||
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;
|
||||
return LoadAndBootPartitionOrDrive(DriveNumber, PartitionNumber);
|
||||
}
|
||||
|
||||
ARC_STATUS
|
||||
@ -178,37 +203,7 @@ 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))
|
||||
{
|
||||
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;
|
||||
return LoadAndBootPartitionOrDrive(DriveNumber, 0);
|
||||
}
|
||||
|
||||
#endif // _M_IX86
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user