From 20a27d9fdf2597ab929fced980e2d5dec6dab4e0 Mon Sep 17 00:00:00 2001 From: "E. C. Masloch" Date: Tue, 18 Feb 2025 21:08:40 +0100 Subject: [PATCH 1/2] fix 2F.4A MS-DOS v5 style HMA access services * Reject allocation call with too large requested size, rather than allocating the remaining HMA. * Align returned offset to paragraph boundary. * Allow to allocate up to the very last byte of the HMA, rather than 1 byte less. * Pass last allocated byte to AllocateHMASpace instead of the byte past it, which would carry for a full allocation. --- kernel/blockio.c | 2 +- kernel/inthndlr.c | 36 +++++++++++++++++++++++++----------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/kernel/blockio.c b/kernel/blockio.c index ae2e8198..b74416b3 100644 --- a/kernel/blockio.c +++ b/kernel/blockio.c @@ -500,7 +500,7 @@ void AllocateHMASpace (size_t lowbuffer, size_t highbuffer) do { /* check if buffer intersects with requested area */ - if (FP_OFF(bp) < highbuffer && FP_OFF(bp+1) > lowbuffer) + if (FP_OFF(bp) <= highbuffer && FP_OFF(bp+1) > lowbuffer) { flush1(bp); /* unlink bp from buffer chain */ diff --git a/kernel/inthndlr.c b/kernel/inthndlr.c index b4be07c0..05e4a605 100644 --- a/kernel/inthndlr.c +++ b/kernel/inthndlr.c @@ -1928,26 +1928,40 @@ VOID ASMCFUNC int2F_12_handler(struct int2f12regs FAR *pr) { COUNT rc; long lrc; - UDWORD tsize; + UWORD requestedsize; #define r (*pr) if (r.AH == 0x4a) { - size_t size = 0, offs = 0xffff; + size_t size = 0, offs = 0xffff, realoffs; /* defaults for no alloc */ r.ES = offs; if (FP_SEG(firstAvailableBuf) == offs) /* HMA present? */ { - offs = FP_OFF(firstAvailableBuf); - size = ~offs; /* BX for query HMA */ - if (r.AL == 0x02) /* allocate HMA space */ - { - tsize = (r.BX + 0xf) & 0xfffffff0UL; /* align to paragraph */ - if (tsize < size) - size = (UWORD)tsize; - AllocateHMASpace(offs, offs+size); - firstAvailableBuf += size; + realoffs = FP_OFF(firstAvailableBuf); + if (realoffs <= 0xFFF0) { /* if any free (not yet exthausted) */ + offs = realoffs; + offs += 15; + offs &= ~ 15; /* annoying: buffers may be unaligned */ + size = - offs; /* bx + di = 10000h */ + if (r.AL == 0x02) /* allocate HMA space */ + { + requestedsize = (r.BX + 15) & ~ 15; /* align to paragraph */ + if (requestedsize < r.BX || + requestedsize > size) { /* overflow or OOM */ + size = 0; + offs = 0xffff; /* requested more than we have */ + } else { + size = (UWORD)requestedsize; /* return rounded size */ + AllocateHMASpace(realoffs, offs + size - 1); /* ! realoffs */ + if ( ((UDWORD)offs + (UDWORD)size) == 0x10000UL ) { + firstAvailableBuf = MK_FP(0xFFFF, 0xFFFF); /* exhausted */ + } else { + firstAvailableBuf += size; /* advance free pointer */ + } + } + } } } r.DI = offs; From 2a28789322fe222e4a46135bf64086e0fa991172 Mon Sep 17 00:00:00 2001 From: "E. C. Masloch" Date: Tue, 18 Feb 2025 21:19:10 +0100 Subject: [PATCH 2/2] in 2F.4A02 advance firstAvailableBuf past the alignment as well (neater) --- kernel/inthndlr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/inthndlr.c b/kernel/inthndlr.c index 05e4a605..40cb3861 100644 --- a/kernel/inthndlr.c +++ b/kernel/inthndlr.c @@ -1953,12 +1953,13 @@ VOID ASMCFUNC int2F_12_handler(struct int2f12regs FAR *pr) size = 0; offs = 0xffff; /* requested more than we have */ } else { + UWORD alignment = offs - realoffs; size = (UWORD)requestedsize; /* return rounded size */ AllocateHMASpace(realoffs, offs + size - 1); /* ! realoffs */ if ( ((UDWORD)offs + (UDWORD)size) == 0x10000UL ) { firstAvailableBuf = MK_FP(0xFFFF, 0xFFFF); /* exhausted */ } else { - firstAvailableBuf += size; /* advance free pointer */ + firstAvailableBuf += size + alignment; /* advance free pointer */ } } }