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..40cb3861 100644 --- a/kernel/inthndlr.c +++ b/kernel/inthndlr.c @@ -1928,26 +1928,41 @@ 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 { + 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 + alignment; /* advance free pointer */ + } + } + } } } r.DI = offs;