Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 3
0
        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);
        }