public static async Task <byte[]> BuildBlock(BadBlock badBlock) { if (badBlock.Data.Length % 4 != 0) { throw new ArgumentException("Bad block data must be dividable by 4", nameof(BadBlock.Data)); } var structureSize = 6 * 4; var maxDataSize = 512 - structureSize; if (badBlock.Data.Length > maxDataSize) { throw new ArgumentException($"Bad block data is larger than max data size {maxDataSize}", nameof(LoadSegBlock.Data)); } var blockStream = new MemoryStream(badBlock.BlockBytes == null || badBlock.BlockBytes.Length == 0 ? new byte[structureSize + badBlock.Data.Length] : badBlock.BlockBytes); var size = (structureSize + badBlock.Data.Length) / 4; await blockStream.WriteAsciiString(BlockIdentifiers.BadBlock); await blockStream.WriteLittleEndianUInt32((uint)size); // size // skip checksum, calculated when block is built blockStream.Seek(4, SeekOrigin.Current); await blockStream.WriteLittleEndianUInt32(badBlock.HostId); // SCSI Target ID of host, not really used await blockStream.WriteLittleEndianUInt32(badBlock.NextBadBlock); // next BadBlock block // skip reserved blockStream.Seek(4, SeekOrigin.Current); // bad block data await blockStream.WriteBytes(badBlock.Data); // calculate and update checksum var blockBytes = blockStream.ToArray(); badBlock.Checksum = await BlockHelper.UpdateChecksum(blockBytes, 8); badBlock.BlockBytes = blockBytes; return(blockBytes); }
public static async Task <byte[]> BuildBlock(PartitionBlock partitionBlock) { var blockStream = new MemoryStream(partitionBlock.BlockBytes == null || partitionBlock.BlockBytes.Length == 0 ? new byte[BlockSize.PartitionBlock * 4] : partitionBlock.BlockBytes); await blockStream.WriteAsciiString(BlockIdentifiers.PartitionBlock); await blockStream.WriteLittleEndianUInt32(BlockSize.PartitionBlock); // size // skip checksum, calculated when block is built blockStream.Seek(4, SeekOrigin.Current); await blockStream.WriteLittleEndianUInt32(partitionBlock .HostId); // SCSI Target ID of host, not really used await blockStream.WriteLittleEndianUInt32(partitionBlock .NextPartitionBlock); // Block number of the next PartitionBlock await blockStream.WriteLittleEndianUInt32(partitionBlock.Flags); // Part Flags (NOMOUNT and BOOTABLE) // skip reserved blockStream.Seek(4 * 2, SeekOrigin.Current); await blockStream.WriteLittleEndianUInt32(partitionBlock.DevFlags); // Preferred flags for OpenDevice var driveName = partitionBlock.DriveName.Length > 31 ? partitionBlock.DriveName.Substring(0, 31) : partitionBlock.DriveName; await blockStream.WriteBytes(new[] { Convert.ToByte(driveName.Length) }); await blockStream.WriteString(driveName, 31); // skip reserved blockStream.Seek(4 * 15, SeekOrigin.Current); await blockStream.WriteLittleEndianUInt32(partitionBlock.SizeOfVector); // Size of Environment vector await blockStream.WriteLittleEndianUInt32(partitionBlock .SizeBlock); // Size of the blocks in 32 bit words, usually 128 await blockStream.WriteLittleEndianUInt32(partitionBlock.SecOrg); // Not used; must be 0 await blockStream.WriteLittleEndianUInt32(partitionBlock.Surfaces); // Number of heads (surfaces) await blockStream.WriteLittleEndianUInt32(partitionBlock .Sectors); // Disk sectors per block, used with SizeBlock, usually 1 await blockStream.WriteLittleEndianUInt32(partitionBlock .BlocksPerTrack); // Blocks per track. drive specific await blockStream.WriteLittleEndianUInt32(partitionBlock .Reserved); // DOS reserved blocks at start of partition. await blockStream.WriteLittleEndianUInt32(partitionBlock .PreAlloc); // DOS reserved blocks at end of partition await blockStream.WriteLittleEndianUInt32(partitionBlock.Interleave); // Not used, usually 0 await blockStream.WriteLittleEndianUInt32(partitionBlock.LowCyl); // First cylinder of the partition await blockStream.WriteLittleEndianUInt32(partitionBlock.HighCyl); // Last cylinder of the partition await blockStream.WriteLittleEndianUInt32(partitionBlock.NumBuffer); // Initial # DOS of buffers. await blockStream.WriteLittleEndianUInt32(partitionBlock.BufMemType); // Type of mem to allocate for buffers await blockStream.WriteLittleEndianUInt32(partitionBlock .MaxTransfer); // Max number of bytes to transfer at a time await blockStream.WriteLittleEndianUInt32(partitionBlock.Mask); // Address Mask to block out certain memory await blockStream.WriteLittleEndianUInt32(partitionBlock.BootPriority); // Boot priority for autoboot await blockStream.WriteBytes(partitionBlock.DosType); // # Dostype of the file system await blockStream.WriteLittleEndianUInt32(partitionBlock.Baud); // Baud rate for serial handler await blockStream.WriteLittleEndianUInt32(partitionBlock.Control); // Control word for handler/filesystem await blockStream.WriteLittleEndianUInt32(partitionBlock .BootBlocks); // Number of blocks containing boot code // skip reserved blockStream.Seek(4 * 12, SeekOrigin.Current); // calculate and update checksum var blockBytes = blockStream.ToArray(); partitionBlock.Checksum = await BlockHelper.UpdateChecksum(blockBytes, 8); partitionBlock.BlockBytes = blockBytes; return(blockBytes); }
public static async Task <byte[]> BuildBlock(RigidDiskBlock rigidDiskBlock) { var blockStream = new MemoryStream(rigidDiskBlock.BlockBytes == null || rigidDiskBlock.BlockBytes.Length == 0 ? new byte[BlockSize.RigidDiskBlock * 4] : rigidDiskBlock.BlockBytes); await blockStream.WriteAsciiString(BlockIdentifiers.RigidDiskBlock); await blockStream.WriteLittleEndianUInt32(BlockSize.RigidDiskBlock); // size // skip checksum, calculated when block is built blockStream.Seek(4, SeekOrigin.Current); await blockStream.WriteLittleEndianUInt32(rigidDiskBlock.HostId); // SCSI Target ID of host, not really used await blockStream.WriteLittleEndianUInt32(rigidDiskBlock.BlockSize); // Size of disk blocks await blockStream.WriteLittleEndianUInt32(rigidDiskBlock.Flags); // RDB Flags await blockStream.WriteLittleEndianUInt32(rigidDiskBlock.BadBlockList); // Bad block list await blockStream.WriteLittleEndianUInt32(rigidDiskBlock.PartitionList); // Partition list await blockStream.WriteLittleEndianUInt32(rigidDiskBlock.FileSysHdrList); // File system header list await blockStream.WriteLittleEndianUInt32(rigidDiskBlock.DriveInitCode); // Drive specific init code await blockStream.WriteLittleEndianUInt32(rigidDiskBlock.BootBlockList); // Amiga OS 4 Boot Blocks // read reserved, unused word, need to be set to $ffffffff var reservedBytes = new byte[] { 255, 255, 255, 255 }; for (var i = 0; i < 5; i++) { await blockStream.WriteBytes(reservedBytes); } // physical drive characteristics await blockStream.WriteLittleEndianUInt32(rigidDiskBlock.Cylinders); // Number of the cylinders of the drive await blockStream.WriteLittleEndianUInt32(rigidDiskBlock.Sectors); // Number of sectors of the drive await blockStream.WriteLittleEndianUInt32(rigidDiskBlock.Heads); // Number of heads of the drive await blockStream.WriteLittleEndianUInt32(rigidDiskBlock.Interleave); // Interleave await blockStream.WriteLittleEndianUInt32(rigidDiskBlock.ParkingZone); // Head parking cylinder // read reserved, unused word, need to be set to $ffffffff reservedBytes = new byte[4]; for (var i = 0; i < 3; i++) { await blockStream.WriteBytes(reservedBytes); } await blockStream.WriteLittleEndianUInt32(rigidDiskBlock .WritePreComp); // Starting cylinder of write pre-compensation await blockStream.WriteLittleEndianUInt32(rigidDiskBlock .ReducedWrite); // Starting cylinder of reduced write current await blockStream.WriteLittleEndianUInt32(rigidDiskBlock.StepRate); // Step rate of the drive // read reserved, unused word, need to be set to $ffffffff for (var i = 0; i < 5; i++) { await blockStream.WriteBytes(reservedBytes); } // logical drive characteristics await blockStream.WriteLittleEndianUInt32(rigidDiskBlock .RdbBlockLo); // low block of range reserved for hardblocks await blockStream.WriteLittleEndianUInt32(rigidDiskBlock .RdbBlockHi); // high block of range for these hardblocks await blockStream.WriteLittleEndianUInt32(rigidDiskBlock .LoCylinder); // low cylinder of partitionable disk area await blockStream.WriteLittleEndianUInt32(rigidDiskBlock .HiCylinder); // high cylinder of partitionable data area await blockStream.WriteLittleEndianUInt32(rigidDiskBlock .CylBlocks); // number of blocks available per cylinder await blockStream.WriteLittleEndianUInt32(rigidDiskBlock.AutoParkSeconds); // zero for no auto park await blockStream.WriteLittleEndianUInt32(rigidDiskBlock .HighRsdkBlock); // highest block used by RDSK (not including replacement bad blocks) await blockStream.WriteBytes(reservedBytes); // read reserved, unused word // drive identification await blockStream.WriteString(rigidDiskBlock.DiskVendor, 8, 32); await blockStream.WriteString(rigidDiskBlock.DiskProduct, 16, 32); await blockStream.WriteString(rigidDiskBlock.DiskRevision, 4, 32); // write controller vendor if (!string.IsNullOrWhiteSpace(rigidDiskBlock.ControllerVendor)) { await blockStream.WriteString(rigidDiskBlock.ControllerVendor, 8, 32); } else { await blockStream.WriteBytes(new byte[8]); } // write controller product if (!string.IsNullOrWhiteSpace(rigidDiskBlock.ControllerProduct)) { await blockStream.WriteString(rigidDiskBlock.ControllerProduct, 16, 32); } else { await blockStream.WriteBytes(new byte[16]); } // write controller revision if (!string.IsNullOrWhiteSpace(rigidDiskBlock.ControllerRevision)) { await blockStream.WriteString(rigidDiskBlock.ControllerRevision, 4, 32); } else { await blockStream.WriteBytes(new byte[4]); } await blockStream.WriteBytes(reservedBytes); // read reserved, unused word // calculate and update checksum var blockBytes = blockStream.ToArray(); rigidDiskBlock.Checksum = await BlockHelper.UpdateChecksum(blockBytes, 8); rigidDiskBlock.BlockBytes = blockBytes; return(blockBytes); }
public static async Task <byte[]> BuildBlock(FileSystemHeaderBlock fileSystemHeaderBlock) { var blockStream = new MemoryStream( fileSystemHeaderBlock.BlockBytes == null || fileSystemHeaderBlock.BlockBytes.Length == 0 ? new byte[BlockSize.FileSystemHeaderBlock * 4] : fileSystemHeaderBlock.BlockBytes); await blockStream.WriteAsciiString(BlockIdentifiers.FileSystemHeaderBlock); await blockStream.WriteLittleEndianUInt32(BlockSize.FileSystemHeaderBlock); // size // skip checksum, calculated when block is built blockStream.Seek(4, SeekOrigin.Current); await blockStream.WriteLittleEndianUInt32(fileSystemHeaderBlock .HostId); // SCSI Target ID of host, not really used await blockStream.WriteLittleEndianUInt32(fileSystemHeaderBlock .NextFileSysHeaderBlock); // Block number of the next FileSysHeaderBlock await blockStream.WriteLittleEndianUInt32(fileSystemHeaderBlock.Flags); // Flags // skip reserved blockStream.Seek(4 * 2, SeekOrigin.Current); await blockStream .WriteBytes(fileSystemHeaderBlock .DosType); // # Dostype of the file system, file system description: match this with partition environment's DE_DOSTYPE entry await blockStream.WriteLittleEndianUInt32(fileSystemHeaderBlock .Version); // filesystem version 0x0027001b == 39.27 await blockStream.WriteLittleEndianUInt32(fileSystemHeaderBlock.PatchFlags); await blockStream.WriteLittleEndianUInt32(fileSystemHeaderBlock.Type); await blockStream.WriteLittleEndianUInt32(fileSystemHeaderBlock.Task); await blockStream.WriteLittleEndianUInt32(fileSystemHeaderBlock.Lock); await blockStream.WriteLittleEndianUInt32(fileSystemHeaderBlock.Handler); await blockStream.WriteLittleEndianUInt32(fileSystemHeaderBlock.StackSize); await blockStream.WriteLittleEndianInt32(fileSystemHeaderBlock.Priority); await blockStream.WriteLittleEndianInt32(fileSystemHeaderBlock.Startup); await blockStream.WriteLittleEndianInt32(fileSystemHeaderBlock .SegListBlocks); // first of linked list of LoadSegBlocks await blockStream.WriteLittleEndianInt32(fileSystemHeaderBlock.GlobalVec); // skip reserved blockStream.Seek((23 + 21) * 4, SeekOrigin.Current); // calculate and update checksum var blockBytes = blockStream.ToArray(); fileSystemHeaderBlock.Checksum = await BlockHelper.UpdateChecksum(blockBytes, 8); fileSystemHeaderBlock.BlockBytes = blockBytes; return(blockBytes); }