public static PartitionBlock Create(RigidDiskBlock rigidDiskBlock, byte[] dosType, string driveName, long size = 0, bool bootable = false)
        {
            var lastPartitionBlock = rigidDiskBlock.PartitionBlocks.LastOrDefault();
            var lowCyl             = lastPartitionBlock == null ? rigidDiskBlock.LoCylinder : lastPartitionBlock.HighCyl + 1;

            uint cylinders;

            if (size > 0)
            {
                size = size.ToSectorSize();
                var blocksPerCylinder = rigidDiskBlock.Heads * rigidDiskBlock.Sectors;
                cylinders = (uint)Math.Floor((double)size / (blocksPerCylinder * rigidDiskBlock.BlockSize));
            }
            else
            {
                cylinders = lastPartitionBlock == null
                    ? rigidDiskBlock.Cylinders
                    : rigidDiskBlock.Cylinders - lowCyl;
            }

            var highCyl = lowCyl + cylinders - 1 > rigidDiskBlock.HiCylinder
                ? rigidDiskBlock.HiCylinder
                : lowCyl + cylinders - 1;

            var partitionBlock = new PartitionBlock
            {
                PartitionSize = cylinders * rigidDiskBlock.Heads * rigidDiskBlock.Sectors * rigidDiskBlock.BlockSize,
                DosType       = dosType,
                DriveName     = driveName,
                Flags         = bootable ? (uint)PartitionFlagsEnum.Bootable : 0,
                LowCyl        = lowCyl,
                HighCyl       = highCyl
            };

            return(partitionBlock);
        }
        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 void ResetPartitionBlockPointers(PartitionBlock partitionBlock)
 {
     partitionBlock.NextPartitionBlock = 0;
 }