diff --git a/sim_disk.c b/sim_disk.c index fedfa427..8397c15b 100644 --- a/sim_disk.c +++ b/sim_disk.c @@ -2902,11 +2902,11 @@ if (!hVHD) { } LocatorPosition = NtoHll (hVHD->Dynamic.TableOffset)+BytesPerSector*((NtoHl (hVHD->Dynamic.MaxTableEntries)*sizeof(*hVHD->BAT)+BytesPerSector-1)/BytesPerSector); hVHD->Dynamic.Checksum = 0; -RelativeParentVHDPath = calloc (1, BytesPerSector+1); -FullParentVHDPath = calloc (1, BytesPerSector+1); -RelativeParentVHDPathBuffer = calloc (1, BytesPerSector); -FullParentVHDPathBuffer = calloc (1, BytesPerSector); -FullVHDPath = calloc (1, BytesPerSector+1); +RelativeParentVHDPath = calloc (1, BytesPerSector+2); +FullParentVHDPath = calloc (1, BytesPerSector+2); +RelativeParentVHDPathBuffer = calloc (1, BytesPerSector+2); +FullParentVHDPathBuffer = calloc (1, BytesPerSector+2); +FullVHDPath = calloc (1, BytesPerSector+2); ExpandToFullPath (szParentVHDPath, FullParentVHDPath, BytesPerSector); for (i=0; i < strlen (FullParentVHDPath); i++) hVHD->Dynamic.ParentUnicodeName[i*2+1] = FullParentVHDPath[i]; @@ -3240,8 +3240,13 @@ while (sects) { } SectorsInWrite = 1; if (hVHD->BAT[BlockNumber] == VHD_BAT_FREE_ENTRY) { - void *BitMap = NULL; + uint8 *BitMap = NULL; + uint32 BitMapBufferSize = VHD_DATA_BLOCK_ALIGNMENT; + uint8 *BitMapBuffer = NULL; void *BlockData = NULL; + uint8 *BATUpdateBufferAddress; + uint32 BATUpdateBufferSize; + uint64 BATUpdateStorageAddress; if (!hVHD->Parent && BufferIsZeros(buf, SectorSize)) goto IO_Done; @@ -3249,28 +3254,51 @@ while (sects) { BlockOffset = sim_fsize_ex (hVHD->File); if (((int64)BlockOffset) == -1) return SCPE_IOERR; - BitMap = malloc(BitMapSectors*SectorSize); + if (BitMapSectors*SectorSize > BitMapBufferSize) + BitMapBufferSize = BitMapSectors*SectorSize; + BitMapBuffer = calloc(1, BitMapBufferSize + SectorSize*SectorsPerBlock); + if (BitMapBufferSize > BitMapSectors*SectorSize) + BitMap = BitMapBuffer + BitMapBufferSize-BitMapBytes; + else + BitMap = BitMapBuffer; memset(BitMap, 0xFF, BitMapBytes); BlockOffset -= sizeof(hVHD->Footer); - /* align the data portion of the block to the desired alignment */ - /* compute the address of the data portion of the block */ - BlockOffset += BitMapSectors*SectorSize; - /* round up this address to the desired alignment */ - BlockOffset += VHD_DATA_BLOCK_ALIGNMENT-1; - BlockOffset &= ~(VHD_DATA_BLOCK_ALIGNMENT-1); - /* the actual block address is the beginning of the block bitmap */ + if (0 == (BlockOffset & ~(VHD_DATA_BLOCK_ALIGNMENT-1))) + { // Already aligned, so use padded BitMapBuffer + if (WriteFilePosition(hVHD->File, + BitMapBuffer, + BitMapBufferSize + SectorSize*SectorsPerBlock, + NULL, + BlockOffset)) { + free (BitMapBuffer); + return SCPE_IOERR; + } + BlockOffset += BitMapBufferSize; + } + else + { + // align the data portion of the block to the desired alignment + // compute the address of the data portion of the block + BlockOffset += BitMapSectors*SectorSize; + // round up this address to the desired alignment + BlockOffset += VHD_DATA_BLOCK_ALIGNMENT-1; + BlockOffset &= ~(VHD_DATA_BLOCK_ALIGNMENT-1); + BlockOffset -= BitMapSectors*SectorSize; + if (WriteFilePosition(hVHD->File, + BitMap, + SectorSize * (BitMapSectors + SectorsPerBlock), + NULL, + BlockOffset)) { + free (BitMapBuffer); + return SCPE_IOERR; + } + BlockOffset += BitMapSectors*SectorSize; + } + free(BitMapBuffer); + BitMapBuffer = BitMap = NULL; + /* the BAT block address is the beginning of the block bitmap */ BlockOffset -= BitMapSectors*SectorSize; hVHD->BAT[BlockNumber] = NtoHl((uint32)(BlockOffset/SectorSize)); - if (WriteFilePosition(hVHD->File, - BitMap, - BitMapSectors*SectorSize, - NULL, - BlockOffset)) { - free (BitMap); - return SCPE_IOERR; - } - free(BitMap); - BitMap = NULL; BlockOffset += SectorSize * (SectorsPerBlock + BitMapSectors); if (WriteFilePosition(hVHD->File, &hVHD->Footer, @@ -3278,11 +3306,17 @@ while (sects) { NULL, BlockOffset)) goto Fatal_IO_Error; + BATUpdateBufferAddress = ((uint8 *)hVHD->BAT) + + (((((size_t)&hVHD->BAT[BlockNumber]) - ((size_t)hVHD->BAT) + VHD_DATA_BLOCK_ALIGNMENT - 1)/VHD_DATA_BLOCK_ALIGNMENT)*VHD_DATA_BLOCK_ALIGNMENT); + BATUpdateBufferSize = SectorSize*((sizeof(*hVHD->BAT)*NtoHl(hVHD->Dynamic.MaxTableEntries)+511)/512); + if (BATUpdateBufferSize > VHD_DATA_BLOCK_ALIGNMENT) + BATUpdateBufferSize = VHD_DATA_BLOCK_ALIGNMENT; + BATUpdateStorageAddress = NtoHll(hVHD->Dynamic.TableOffset) + BATUpdateBufferAddress - ((uint8 *)hVHD->BAT); if (WriteFilePosition(hVHD->File, - hVHD->BAT, - SectorSize*((sizeof(*hVHD->BAT)*NtoHl(hVHD->Dynamic.MaxTableEntries)+511)/512), + BATUpdateBufferAddress, + BATUpdateBufferSize, NULL, - NtoHll(hVHD->Dynamic.TableOffset))) + BATUpdateStorageAddress)) goto Fatal_IO_Error; if (hVHD->Parent) { /* Need to populate data block contents from parent VHD */