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:
Stas Sergeev 2017-09-22 20:25:04 +03:00 committed by Kenneth J Davis
parent 5fb0c4482d
commit 8187fd8153

View File

@ -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 :