Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

initdisk: actually restrict disk size to 2TB instead of modulo 2TB, fix ExtLBAForce usage #118

Merged
merged 4 commits into from
Dec 20, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 54 additions & 43 deletions kernel/initdisk.c
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,8 @@ STATIC int LBA_Get_Drive_Parameters(int drive, struct DriveParamS *driveParam, i
iregs regs;
struct _bios_LBA_disk_parameterS lba_bios_parameters;

ExtLBAForce = InitKernelConfig.ForceLBA;
if (firstPass && (InitKernelConfig.Verbose >= 1))
printf("Checking for LBA support in BIOS for drive %02x\n", drive);

memset(driveParam, 0, sizeof *driveParam);
drive |= 0x80;
Expand All @@ -654,27 +655,20 @@ STATIC int LBA_Get_Drive_Parameters(int drive, struct DriveParamS *driveParam, i

init_call_intr(0x13, &regs);

if (regs.b.x != 0xaa55 || (regs.flags & 0x01))
if ((regs.flags & 0x01) || regs.b.x != 0xaa55 || (regs.c.x & 0x01) == 0)
{
/* error conditions:
carry set or BX != 0xaa55 => no EDD spec compatible BIOS
CX bit 1 clear => fixed disc access subset not supported */
goto StandardBios;
}

/* by ralph :
if DAP cannot be used, don't use
LBA
*/
if (((regs.c.x & 1) == 0) && !ExtLBAForce)
{
goto StandardBios;
}

/* drive supports LBA addressing */
if (firstPass && (InitKernelConfig.Verbose >= 1)) printf("Checking for LBA support in BIOS\n");

/* version 1.0, 2.0 have different verify */
if (regs.a.x < 0x2100)
LBA_WRITE_VERIFY = 0x4301;
if (regs.a.b.h < 0x21)
LBA_WRITE_VERIFY = 0x4301; /* may be problematic if INT13 is hooked by
different controllers / drivers */

/* query disk size and DMA handling, geometry is queried later by INT13,08 */
memset(&lba_bios_parameters, 0, sizeof(lba_bios_parameters));
lba_bios_parameters.size = sizeof(lba_bios_parameters);

Expand All @@ -684,50 +678,56 @@ STATIC int LBA_Get_Drive_Parameters(int drive, struct DriveParamS *driveParam, i
regs.d.b.l = drive;
init_call_intr(0x13, &regs);

/* error or DMA boundary errors not handled transparently */
if (regs.flags & 0x01)
{
/* carry flag set indicates failed LBA disk parameter query */
goto StandardBios;
}

/* verify maximum settings, we can't handle more */

if (lba_bios_parameters.heads > 0xffff ||
lba_bios_parameters.sectors > 0xffff ||
lba_bios_parameters.totalSectHigh != 0)
(lba_bios_parameters.totalSect == 0 &&
lba_bios_parameters.totalSectHigh == 0))
{
if (firstPass)
{
printf("Drive is too large to handle, ");
if (ExtLBAForce)
printf("limited to 2TB");
else
printf("using CHS, limited to 8GB");
printf("\nDrive %02x, heads=%lu, sectors=%lu, total=0x%lx-%08lx\n",
printf("Suspicious LBA disk parameters, reverting to CHS access:\n");
printf(" drive %02x, heads=%lu, sectors=%lu, total=0x%lx-%08lx\n",
drive,
(ULONG) lba_bios_parameters.heads,
(ULONG) lba_bios_parameters.sectors,
(ULONG) lba_bios_parameters.totalSect,
(ULONG) lba_bios_parameters.totalSectHigh);
}

if (!ExtLBAForce) goto StandardBios;
goto StandardBios;
}

driveParam->total_sectors = lba_bios_parameters.totalSect;
/* restrict disk size to 2TB, because we can not handle more */
if (lba_bios_parameters.totalSectHigh == 0)
{
driveParam->total_sectors = lba_bios_parameters.totalSect;
}
else
{
if (firstPass) printf("Drive %02x is too large to handle, restricted to 2TB\n", drive);
driveParam->total_sectors = 0xffffffffu;
}

/* if we arrive here, success */
/* if we arrive here, mark drive as LBA capable */
driveParam->descflags = DF_LBA;
if (lba_bios_parameters.information & 8)
driveParam->descflags |= DF_WRTVERIFY;

if (lba_bios_parameters.information & 1)
{
driveParam->descflags |= DF_DMA_TRANSPARENT; /* DMA boundary errors are handled transparently */
/* DMA boundary errors are handled transparently */
driveParam->descflags |= DF_DMA_TRANSPARENT;
}

StandardBios: /* old way to get parameters */
if (firstPass && (InitKernelConfig.Verbose >= 1)) printf("Retrieving CHS values for drive\n");
StandardBios: /* get disk geometry, and if LBA is not enabled, also size */
if (firstPass && (InitKernelConfig.Verbose >= 1))
printf("Retrieving CHS values for drive\n");

regs.a.b.h = 0x08;
regs.d.b.l = drive;
Expand All @@ -736,9 +736,6 @@ STATIC int LBA_Get_Drive_Parameters(int drive, struct DriveParamS *driveParam, i

if (regs.flags & 0x01)
{
/* to avoid division by zero later, use some sane defaults */
driveParam->chs.Head = 16;
driveParam->chs.Sector = 63;
goto ErrorReturn;
}

Expand All @@ -751,7 +748,8 @@ STATIC int LBA_Get_Drive_Parameters(int drive, struct DriveParamS *driveParam, i
if (driveParam->chs.Sector == 0) {
/* happens e.g. with Bochs 1.x if no harddisk defined */
driveParam->chs.Sector = 63; /* avoid division by zero...! */
if (firstPass && (InitKernelConfig.Verbose >= 0)) printf("BIOS reported 0 sectors/track, assuming 63!\n");
if (firstPass && (InitKernelConfig.Verbose >= 0))
printf("BIOS reported 0 sectors/track, assuming 63!\n");
}

if (!(driveParam->descflags & DF_LBA))
Expand All @@ -769,9 +767,15 @@ STATIC int LBA_Get_Drive_Parameters(int drive, struct DriveParamS *driveParam, i
driveParam->chs.Head, driveParam->chs.Sector));
DebugPrintf((" total size %luMB\n\n", driveParam->total_sectors / 2048));

ErrorReturn:

return driveParam->driveno;


ErrorReturn:
/* to avoid division by zero later, use some sane defaults */
driveParam->total_sectors = 0;
driveParam->chs.Head = 16;
driveParam->chs.Sector = 63;
return 0;
}

/*
Expand Down Expand Up @@ -997,7 +1001,11 @@ int Read1LBASector(struct DriveParamS *driveParam, unsigned drive,

for (num_retries = 0; num_retries < N_RETRY; num_retries++)
{
if (InitKernelConfig.Verbose >= 1) printf("retry# %i\n", num_retries);
if (InitKernelConfig.Verbose >= 1)
{
printf("retry# %i sector %lu\n", num_retries, LBA_address);
}

regs.d.b.l = drive | 0x80;
LBA_to_CHS(&chs, LBA_address, driveParam);
/* Some old "security" software (PROT) traps int13 and assumes non
Expand Down Expand Up @@ -1074,6 +1082,9 @@ int ProcessDisk(int scanType, unsigned drive, int PartitionsToIgnore)

RelSectorOffset = 0; /* boot sector */
ExtendedPartitionOffset = 0; /* not found yet */
ExtLBAForce = 0; /* initially we are not dealing with partitions
within a type 0x0E LBA extended partition,
so we do not enforce LBA access by now */

/* Read the Primary Partition Table. */

Expand Down Expand Up @@ -1130,7 +1141,7 @@ int ProcessDisk(int scanType, unsigned drive, int PartitionsToIgnore)
{
RelSectorOffset = ExtendedPartitionOffset + PTable[iPart].RelSect;

if (ExtendedPartitionOffset == 0)
if (ExtendedPartitionOffset == 0) /* first extended in chain? */
{
ExtendedPartitionOffset = PTable[iPart].RelSect;
/* grand parent LBA -> all children and grandchildren LBA */
Expand Down Expand Up @@ -1407,14 +1418,14 @@ void ReadAllPartitionTables(void)

if (InitKernelConfig.Verbose >= 0)
{
unsigned foundPartitionsCount = 0;
unsigned foundPartitionsCount = 0;
/* Tell user if no valid partitions found on any hard drive */
for (HardDrive = 0; HardDrive < nHardDisk; HardDrive++)
{
foundPartitionsCount += foundPartitions[HardDrive];
}
/* printf("Found %i partitions\n", foundPartitionsCount); */
if (!foundPartitionsCount) printf("No supported partitions found.\n");
/* printf("Found %i partitions\n", foundPartitionsCount); */
if (!foundPartitionsCount) printf("No supported partitions found.\n");
}
}

Expand Down