#include #include #include #include #include #include #include #include #include #include #include #include #include "makemast.h" PARTITION_IMAGE PartitionImage; ULONG TotalSectorsToTransfer; ULONG TotalSectorsDone; BOOL TransferNonClusterData( IN HDISK DiskHandle, IN unsigned FileHandle, IN ULONG TargetStart ); BOOL ExpandClusters( IN HDISK DiskHandle, IN unsigned FileHandle, IN ULONG TargetStart ); BOOL InitializeClusterMap( IN unsigned FileHandle ); BOOL GetClusterRun( IN unsigned FileHandle, OUT ULONG *StartCluster, OUT ULONG *ClusterCount ); BOOL ApplyImage( IN HDISK DiskHandle, IN ULONG TargetStart, IN ULONG MaxSize, IN BYTE SectorsPerTrack, IN USHORT Heads ) { unsigned FileHandle; unsigned Read; printf("\n"); printf(textTransferringFile,CmdLineArgs.ImageFile,0); printf("\r"); // // Open the source file, read the image header, and validate it. // if(_dos_open(CmdLineArgs.ImageFile,SH_DENYWR,&FileHandle)) { fprintf(stderr,"\n%s\n",textCantAccessImageFile); return(FALSE); } if(_dos_read(FileHandle,&PartitionImage,sizeof(PARTITION_IMAGE),&Read) || (Read != sizeof(PARTITION_IMAGE)) || (PartitionImage.Signature != PARTITION_IMAGE_SIGNATURE) || (PartitionImage.Size != sizeof(PARTITION_IMAGE))) { _dos_close(FileHandle); fprintf(stderr,"\n%s\n",textInvalidImageFile); return(FALSE); } // // Make sure we've got the space. // if(PartitionImage.TotalSectorCount > MaxSize) { _dos_close(FileHandle); fprintf(stderr,"\n"); fprintf(stderr,textImageFileTooBig,PartitionImage.TotalSectorCount,MaxSize); fprintf(stderr,"\n"); return(FALSE); } TotalSectorsToTransfer = PartitionImage.NonClusterSectors + (PartitionImage.SectorsPerCluster*PartitionImage.UsedClusterCount); TotalSectorsDone = 0; // // Transfer non-cluster data from the image. // if(!TransferNonClusterData(DiskHandle,FileHandle,TargetStart)) { _dos_close(FileHandle); return(FALSE); } // // Expand out cluster data from the image. // if(!ExpandClusters(DiskHandle,FileHandle,TargetStart)) { _dos_close(FileHandle); return(FALSE); } // // Fix up BPB. // if(!ReadDisk(DiskHandle,TargetStart,1,IoBuffer)) { _dos_close(FileHandle); fprintf(stderr,"\n"); fprintf(stderr,textDiskReadError,TargetStart); fprintf(stderr,"\n"); return(FALSE); } *(FPUSHORT)&((FPBYTE)IoBuffer)[24] = SectorsPerTrack; *(FPUSHORT)&((FPBYTE)IoBuffer)[26] = Heads; *(FPULONG)&((FPBYTE)IoBuffer)[28] = TargetStart; if(!WriteDisk(DiskHandle,TargetStart,1,IoBuffer)) { _dos_close(FileHandle); fprintf(stderr,"\n"); fprintf(stderr,textDiskWriteError,TargetStart); fprintf(stderr,"\n"); return(FALSE); } _dos_close(FileHandle); return(TRUE); } BOOL TransferNonClusterData( IN HDISK DiskHandle, IN unsigned FileHandle, IN ULONG TargetStart ) { ULONG NonClusterSectorsDone; ULONG Count; unsigned Read; // // Seek past partition image header // if(DosSeek(FileHandle,512,DOSSEEK_START) != 512) { fprintf(stderr,"\n%s\n",textCantAccessImageFile); return(FALSE); } // // Now transfer the non-cluster data // NonClusterSectorsDone = 0; while(NonClusterSectorsDone < PartitionImage.NonClusterSectors) { Count = PartitionImage.NonClusterSectors - NonClusterSectorsDone; if(Count > 63) { Count = 63; } if(_dos_read(FileHandle,IoBuffer,(unsigned)Count*512,&Read) || (Read != ((unsigned)Count*512))) { fprintf(stderr,"\n%s\n",textCantAccessImageFile); return(FALSE); } if(!WriteDisk(DiskHandle,TargetStart,(BYTE)Count,IoBuffer)) { fprintf(stderr,"\n"); fprintf(stderr,textDiskWriteError,TargetStart); fprintf(stderr,"\n"); return(FALSE); } TargetStart += Count; NonClusterSectorsDone += Count; TotalSectorsDone += Count; printf(textTransferringFile,CmdLineArgs.ImageFile,100*TotalSectorsDone/TotalSectorsToTransfer); printf("\r"); } return(TRUE); } BOOL ExpandClusters( IN HDISK DiskHandle, IN unsigned FileHandle, IN ULONG TargetStart ) { ULONG Start,Count; ULONG TargetSector; BYTE u; unsigned Read; if(!InitializeClusterMap(FileHandle)) { return(FALSE); } // // Seek to start of cluster data in input file. // Start = (1 + PartitionImage.NonClusterSectors) * 512; if(DosSeek(FileHandle,Start,DOSSEEK_START) != Start) { fprintf(stderr,"\n%s\n",textCantAccessImageFile); return(FALSE); } // // Get a run of clusters. If there are no more clusters left, we're done. // nextrun: if(!GetClusterRun(FileHandle,&Start,&Count)) { return(FALSE); } if(!Count) { return(TRUE); } Count *= PartitionImage.SectorsPerCluster; // // Calculate the offset of the data in the source file and // the starting sector number of the target. // TargetSector = TargetStart + PartitionImage.NonClusterSectors + (Start*PartitionImage.SectorsPerCluster); while(Count) { u = (BYTE)((Count > 63L) ? 63L : Count); if(_dos_read(FileHandle,IoBuffer,u*512U,&Read) || (Read != (u*512U))) { fprintf(stderr,"\n%s\n",textCantAccessImageFile); return(FALSE); } if(!WriteDisk(DiskHandle,TargetSector,u,IoBuffer)) { fprintf(stderr,"\n"); fprintf(stderr,textDiskWriteError,TargetSector); fprintf(stderr,"\n"); return(FALSE); } TargetSector += u; Count -= u; TotalSectorsDone += u; printf(textTransferringFile,CmdLineArgs.ImageFile,100*TotalSectorsDone/TotalSectorsToTransfer); printf("\r"); } // // Process additional clusters. // goto nextrun; } //////////////////////////////////////////////////// ULONG _ClusterSectorFileOffset; ULONG _NextClusterToExamine; ULONG _ClusterBufferBase; BYTE _ClusterBuffer[512]; extern BYTE BitValue[8]; BOOL InitializeClusterMap( IN unsigned FileHandle ) { unsigned read; // // Figure out where in the file the cluster bitmap starts. // _ClusterSectorFileOffset = PartitionImage.NonClusterSectors + (PartitionImage.UsedClusterCount * PartitionImage.SectorsPerCluster) + 1; _ClusterSectorFileOffset *= 512; // // Read the first sector of the cluster bitmap. Read into IoBuffer to avoid // DMA boundary issues. // if((DosSeek(FileHandle,_ClusterSectorFileOffset,DOSSEEK_START) != _ClusterSectorFileOffset) || _dos_read(FileHandle,IoBuffer,512,&read) || (read != 512)) { fprintf(stderr,"\n%s\n",textCantAccessImageFile); return(FALSE); } memmove(_ClusterBuffer,IoBuffer,512); _NextClusterToExamine = 0; _ClusterBufferBase = 0; return(TRUE); } BOOL GetClusterRun( IN unsigned FileHandle, OUT ULONG *StartCluster, OUT ULONG *ClusterCount ) { ULONG Offset; UINT cluster; BOOL b; *ClusterCount = 0; // // Locate the next 1 bit in the map. // while(_NextClusterToExamine <= PartitionImage.LastUsedCluster) { // // Reload the cluster buffer if necessary. Preserve file pointer! // if(_NextClusterToExamine && !(_NextClusterToExamine % (8*512))) { _ClusterSectorFileOffset += 512; if(((Offset = DosSeek(FileHandle,0,DOSSEEK_CURRENT)) == (ULONG)(-1)) || (DosSeek(FileHandle,_ClusterSectorFileOffset,DOSSEEK_START) != _ClusterSectorFileOffset) || _dos_read(FileHandle,IoBuffer,512,&cluster) || (cluster != 512) || (DosSeek(FileHandle,Offset,DOSSEEK_START) != Offset)) { fprintf(stderr,"\n%s\n",textCantAccessImageFile); return(FALSE); } memmove(_ClusterBuffer,IoBuffer,512); _ClusterBufferBase += 8*512; } cluster = (UINT)(_NextClusterToExamine - _ClusterBufferBase); // // See if this bit is one, which starts a run of used clusters. // To simplify things, we won't return a run that spans sectors // in the cluster bitmap. // b = FALSE; while((_ClusterBuffer[cluster/8] & BitValue[cluster%8]) && (cluster < (8*512)) && (_NextClusterToExamine <= PartitionImage.LastUsedCluster)) { if(!b) { *StartCluster = _NextClusterToExamine; b = TRUE; } *ClusterCount += 1; cluster++; _NextClusterToExamine++; } if(b) { return(TRUE); } _NextClusterToExamine++; } return(TRUE); }