mirror of
https://github.com/FDOS/kernel.git
synced 2025-07-20 12:24:33 +02:00
disk: fix sectors count truncation for CHS [fixes #10]
LBA_to_CHS() uses geometry taken from BIOS, but LBA_Transfer() was using the geometry from VBR. This caused "count" variable to underflow over unsigned long, then corrupting the entire DOS memory with the large read. This patch makes LBA_to_CHS() to return the geometry to caller, so that the calculus do always match. Thanks to @ecm-pushbx and @andrewbird for helping to nail this down.
This commit is contained in:
parent
5fb0c4482d
commit
8187fd8153
12
kernel/dsk.c
12
kernel/dsk.c
@ -901,7 +901,8 @@ STATIC WORD dskerr(COUNT code)
|
|||||||
translate LBA sectors into CHS addressing
|
translate LBA sectors into CHS addressing
|
||||||
*/
|
*/
|
||||||
|
|
||||||
STATIC int LBA_to_CHS(ULONG LBA_address, struct CHS *chs, const ddt * pddt)
|
STATIC int LBA_to_CHS(ULONG LBA_address, struct CHS *chs, const ddt * pddt,
|
||||||
|
const bpb ** ppbpb)
|
||||||
{
|
{
|
||||||
/* we need the defbpb values since those are taken from the
|
/* we need the defbpb values since those are taken from the
|
||||||
BIOS, not from some random boot sector, except when
|
BIOS, not from some random boot sector, except when
|
||||||
@ -926,6 +927,7 @@ STATIC int LBA_to_CHS(ULONG LBA_address, struct CHS *chs, const ddt * pddt)
|
|||||||
chs->Cylinder = (UWORD)LBA_address;
|
chs->Cylinder = (UWORD)LBA_address;
|
||||||
chs->Head = hsrem / pbpb->bpb_nsecs;
|
chs->Head = hsrem / pbpb->bpb_nsecs;
|
||||||
chs->Sector = hsrem % pbpb->bpb_nsecs + 1;
|
chs->Sector = hsrem % pbpb->bpb_nsecs + 1;
|
||||||
|
*ppbpb = pbpb;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1069,15 +1071,15 @@ STATIC int LBA_Transfer(ddt * pddt, UWORD mode, VOID FAR * buffer,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* transfer data, using old bios functions */
|
{ /* transfer data, using old bios functions */
|
||||||
|
const bpb *pbpb;
|
||||||
if (LBA_to_CHS(LBA_address, &chs, pddt))
|
if (LBA_to_CHS(LBA_address, &chs, pddt, &pbpb))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* avoid overflow at end of track */
|
/* avoid overflow at end of track */
|
||||||
|
|
||||||
if (chs.Sector + count > (unsigned)pddt->ddt_bpb.bpb_nsecs + 1)
|
if (chs.Sector + count > (unsigned)pbpb->bpb_nsecs + 1)
|
||||||
{
|
{
|
||||||
count = pddt->ddt_bpb.bpb_nsecs + 1 - chs.Sector;
|
count = pbpb->bpb_nsecs + 1 - chs.Sector;
|
||||||
}
|
}
|
||||||
|
|
||||||
error_code = (mode == LBA_READ ? fl_read :
|
error_code = (mode == LBA_READ ? fl_read :
|
||||||
|
Loading…
x
Reference in New Issue
Block a user