Binary Formatter (Little Endian)
예제 #1
0
        /// <summary>
        /// Reads the master boot block.
        /// </summary>
        /// <returns></returns>
        public bool Read()
        {
            valid = false;

            MasterBootBlock mbr = new MasterBootBlock(diskDevice);

            if (!mbr.Valid)
                return false;

            if ((mbr.Partitions[0].PartitionType != PartitionType.GPT) ||
                (mbr.Partitions[1].PartitionType != PartitionType.Empty) ||
                (mbr.Partitions[2].PartitionType != PartitionType.Empty) ||
                (mbr.Partitions[3].PartitionType != PartitionType.Empty) ||
                (!mbr.Partitions[0].Bootable) || (mbr.Partitions[0].StartLBA != 1))
                return false;

            BinaryFormat gpt = new BinaryFormat(diskDevice.ReadBlock(1, 1));

            if ((gpt.GetByte(0) != 45) && (gpt.GetByte(1) != 46) && (gpt.GetByte(2) != 49) && (gpt.GetByte(3) != 20) &&
                (gpt.GetByte(4) != 50) && (gpt.GetByte(5) != 41) && (gpt.GetByte(6) != 52) && (gpt.GetByte(7) != 54))
                return false;

            if ((gpt.GetUInt(GPT.Revision) != GPTConstant.SupportedRevision) ||
                (gpt.GetUInt(GPT.HeaderSize) != GPTConstant.HeaderSize) ||
                (gpt.GetUInt(GPT.Reserved) != 0) ||
                (gpt.GetUInt(GPT.PartitionStartingLBA) != 2)
                )
                return false;

            valid = true;

            return valid;
        }
예제 #2
0
        /// <summary>
        /// Compares the specified data.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <param name="offset">The offset.</param>
        /// <param name="type">The type.</param>
        /// <returns></returns>
        public bool Compare(byte[] data, uint offset, FatType type)
        {
            BinaryFormat entry = new BinaryFormat(data);

            byte first = entry.GetByte(offset + Entry.DOSName);

            if (first == FileNameAttribute.LastEntry)
                return true;

            if ((first == FileNameAttribute.Deleted) | (first == FileNameAttribute.Dot))
                return true;

            return false;
        }
예제 #3
0
        /// <summary>
        /// Compares the specified data.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <param name="offset">The offset.</param>
        /// <param name="type">The type.</param>
        /// <returns></returns>
        public bool Compare(byte[] data, uint offset, FatType type)
        {
            var entry = new BinaryFormat(data);

            byte first = entry.GetByte(offset + Entry.DOSName);

            if (first == FileNameAttribute.LastEntry)
                return false;

            if ((first == FileNameAttribute.Deleted) | (first == FileNameAttribute.Dot))
                return false;

            if (first == FileNameAttribute.Escape)
                return false;

            string entryname = FatFileSystem.ExtractFileName(data, offset);

            if (entryname == name)
                return true;

            return false;
        }
예제 #4
0
				return false;

			if ((first == FileNameAttribute.Deleted) | (first == FileNameAttribute.Dot))
				return false;

			if (first == FileNameAttribute.Escape)
				return false;

			uint startcluster = FatFileSystem.GetClusterEntry(data, offset, type);

			if (startcluster == cluster)
				return true;

			return false;
		}
	}
}
예제 #5
0
        /// <summary>
        /// Compares the specified data.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <param name="offset">The offset.</param>
        /// <param name="type">The type.</param>
        /// <returns></returns>
        public bool Compare(byte[] data, uint offset, FatType type)
        {
            BinaryFormat entry = new BinaryFormat(data);

            byte first = entry.GetByte(Entry.DOSName + offset);

            if (first == FileNameAttribute.LastEntry)
                return false;

            if ((first == FileNameAttribute.Deleted) | (first == FileNameAttribute.Dot))
                return false;

            if (first == FileNameAttribute.Escape)
                return false;

            FatFileAttributes attribute = (FatFileAttributes)entry.GetByte(Entry.FileAttributes + offset);

            if ((attribute & FatFileAttributes.VolumeLabel) == FatFileAttributes.VolumeLabel)
                return true;

            return false;
        }
예제 #6
0
        /// <summary>
        /// Finds the entry.
        /// </summary>
        /// <param name="compare">The compare.</param>
        /// <param name="startCluster">The start cluster.</param>
        /// <returns></returns>
        public FatFileLocation FindEntry(FatFileSystem.ICompare compare, uint startCluster)
        {
            uint activeSector = startCluster * sectorsPerCluster;

            if (startCluster == 0)
                activeSector = (fatType == FatType.FAT32) ? GetSectorByCluster(rootCluster32) : firstRootDirectorySector;

            uint increment = 0;

            for (;;)
            {
                BinaryFormat directory = new BinaryFormat(partition.ReadBlock(activeSector, 1));

                for (uint index = 0; index < entriesPerSector; index++)
                {
                    if (compare.Compare(directory.Data, index * 32, fatType))
                    {
                        FatFileAttributes attribute = (FatFileAttributes)directory.GetByte((index * Entry.EntrySize) + Entry.FileAttributes);
                        return new FatFileLocation(GetClusterEntry(directory.Data, index, fatType), activeSector, index, (attribute & FatFileAttributes.SubDirectory) != 0);
                    }

                    if (directory.GetByte(Entry.DOSName + (index * Entry.EntrySize)) == FileNameAttribute.LastEntry)
                        return new FatFileLocation();
                }

                ++increment;

                if ((startCluster == 0) && (fatType != FatType.FAT32))
                {
                    // FAT12/16 Root directory
                    if (increment >= rootDirSectors)
                        return new FatFileLocation();

                    activeSector = startCluster + increment;
                    continue;
                }
                else
                {
                    // subdirectory
                    if (increment < sectorsPerCluster)
                    {
                        // still within cluster
                        activeSector = startCluster + increment;
                        continue;
                    }

                    // exiting cluster

                    // goto next cluster (if any)
                    uint cluster = GetClusterBySector(startCluster);

                    if (cluster == 0)
                        return new FatFileLocation();

                    uint nextCluster = GetClusterEntryValue(cluster);

                    if ((IsClusterLast(nextCluster)) || (IsClusterBad(nextCluster)) || (IsClusterFree(nextCluster)) || (IsClusterReserved(nextCluster)))
                        return new FatFileLocation();

                    activeSector = (uint)(dataAreaStart + (nextCluster - 1 * sectorsPerCluster));

                    continue;
                }
            }
        }
예제 #7
0
        /// <summary>
        /// Creates the file.
        /// </summary>
        /// <param name="filename">The filename.</param>
        /// <param name="fileAttributes">The file attributes.</param>
        /// <param name="directoryCluster">The directory cluster.</param>
        /// <returns></returns>
        public FatFileLocation CreateFile(string filename, FatFileAttributes fileAttributes, uint directoryCluster)
        {
            FatFileLocation location = FindEntry(new Find.WithName(filename), directoryCluster);

            if (location.Valid)
            {
                // Truncate the file
                BinaryFormat entry = new BinaryFormat(partition.ReadBlock(location.DirectorySector, 1));

                // Truncate the file length and reset the start cluster
                entry.SetUInt(Entry.FileSize + (location.DirectorySectorIndex * Entry.EntrySize), 0);
                entry.SetUInt(Entry.FirstCluster + (location.DirectorySectorIndex * Entry.EntrySize), 0);

                partition.WriteBlock(location.DirectorySector, 1, entry.Data);

                FreeClusterChain(location.FirstCluster);

                location.FirstCluster = 0;

                return location;
            }

            // Find an empty location in the directory
            location = FindEntry(new Find.Empty(), directoryCluster);

            if (!location.Valid)
            {
                // Extend Directory

                // TODO

                return location;
            }

            BinaryFormat directory = new BinaryFormat(partition.ReadBlock(location.DirectorySector, 1));

            if (filename.Length > 11)
                filename = filename.Substring(0, 11);

            // Create Entry
            directory.SetString(Entry.DOSName + (location.DirectorySectorIndex * Entry.EntrySize), "            ", 11);
            directory.SetString(Entry.DOSName + (location.DirectorySectorIndex * Entry.EntrySize), filename);
            directory.SetByte(Entry.FileAttributes + (location.DirectorySectorIndex * Entry.EntrySize), (byte)fileAttributes);
            directory.SetByte(Entry.Reserved + (location.DirectorySectorIndex * Entry.EntrySize), 0);
            directory.SetByte(Entry.CreationTimeFine + (location.DirectorySectorIndex * Entry.EntrySize), 0);
            directory.SetUShort(Entry.CreationTime + (location.DirectorySectorIndex * Entry.EntrySize), 0);
            directory.SetUShort(Entry.CreationDate + (location.DirectorySectorIndex * Entry.EntrySize), 0);
            directory.SetUShort(Entry.LastAccessDate + (location.DirectorySectorIndex * Entry.EntrySize), 0);
            directory.SetUShort(Entry.LastModifiedTime + (location.DirectorySectorIndex * Entry.EntrySize), 0);
            directory.SetUShort(Entry.LastModifiedDate + (location.DirectorySectorIndex * Entry.EntrySize), 0);
            directory.SetUShort(Entry.FirstCluster + (location.DirectorySectorIndex * Entry.EntrySize), 0);
            directory.SetUInt(Entry.FileSize + (location.DirectorySectorIndex * Entry.EntrySize), 0);

            partition.WriteBlock(location.DirectorySector, 1, directory.Data);

            return location;
        }
예제 #8
0
        /// <summary>
        /// Deletes the specified file or directory
        /// </summary>
        /// <param name="targetCluster">The target cluster.</param>
        /// <param name="directorySector">The directory sector.</param>
        /// <param name="directorySectorIndex">Index of the directory sector.</param>
        public void Delete(uint targetCluster, uint directorySector, uint directorySectorIndex)
        {
            BinaryFormat entry = new BinaryFormat(partition.ReadBlock(directorySector, 1));

            entry.SetByte(Entry.DOSName + (directorySectorIndex * Entry.EntrySize), (byte)FileNameAttribute.Deleted);

            partition.WriteBlock(directorySector, 1, entry.Data);

            FreeClusterChain(targetCluster);
        }
예제 #9
0
        /// <summary>
        /// Gets the cluster entry.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <param name="index">The index.</param>
        /// <param name="type">The type.</param>
        /// <returns></returns>
        public static uint GetClusterEntry(byte[] data, uint index, FatType type)
        {
            BinaryFormat entry = new BinaryFormat(data);

            uint cluster = entry.GetUShort(Entry.FirstCluster + (index * Entry.EntrySize));

            if (type == FatType.FAT32)
                cluster |= ((uint)entry.GetUShort(Entry.EAIndex + (index * Entry.EntrySize))) << 16;

            return cluster;
        }
예제 #10
0
        /// <summary>
        /// Allocates the first cluster.
        /// </summary>
        /// <param name="directorySector">The directory sector.</param>
        /// <param name="directorySectorIndex">Index of the directory sector.</param>
        /// <returns></returns>
        public uint AllocateFirstCluster(uint directorySector, uint directorySectorIndex)
        {
            uint newCluster = AllocateCluster();

            if (newCluster == 0)
                return 0;

            // Truncate set first cluster
            BinaryFormat entry = new BinaryFormat(partition.ReadBlock(directorySector, 1));
            entry.SetUInt(Entry.FirstCluster + (directorySectorIndex * Entry.EntrySize), newCluster);
            partition.WriteBlock(directorySector, 1, entry.Data);

            return newCluster;
        }
예제 #11
0
        /// <summary>
        /// Sets the cluster entry value.
        /// </summary>
        /// <param name="cluster">The cluster.</param>
        /// <param name="nextcluster">The nextcluster.</param>
        /// <returns></returns>
        protected bool SetClusterEntryValue(uint cluster, uint nextcluster)
        {
            uint fatOffset = 0;

            if (fatType == FatType.FAT12)
                fatOffset = (cluster + (cluster / 2));
            else if (fatType == FatType.FAT16)
                fatOffset = cluster * 2;
            else //if (type == FatType.FAT32)
                fatOffset = cluster * 4;

            uint sector = reservedSectors + (fatOffset / bytesPerSector);
            uint sectorOffset = fatOffset % bytesPerSector;
            uint nbrSectors = 1;

            if ((fatType == FatType.FAT12) && (sectorOffset == bytesPerSector - 1))
                nbrSectors = 2;

            BinaryFormat fat = new BinaryFormat(partition.ReadBlock(sector, nbrSectors));

            if (fatType == FatType.FAT12)
            {
                uint clustervalue = fat.GetUShort(sectorOffset);

                if (cluster % 2 == 1)
                    clustervalue = ((clustervalue & 0x000F) | (nextcluster << 4));
                else
                    clustervalue = ((clustervalue & 0xF000) | (nextcluster & 0x0FFF));

                fat.SetUShort(sectorOffset, (ushort)clustervalue);
            }
            else if (fatType == FatType.FAT16)
                fat.SetUShort(sectorOffset, (ushort)(nextcluster & 0xFFFF));
            else //if (type == FatType.FAT32)
                fat.SetUInt(sectorOffset, nextcluster);

            partition.WriteBlock(sector, nbrSectors, fat.Data);

            return true;
        }
예제 #12
0
        /// <summary>
        /// Extracts the name of the file.
        /// </summary>
        /// <param name="directory">The directory.</param>
        /// <param name="index">The index.</param>
        /// <returns></returns>
        public static string ExtractFileName(byte[] directory, uint index)
        {
            // rewrite to use string
            BinaryFormat entry = new BinaryFormat(directory);

            char[] name = new char[12];

            for (uint i = 0; i < 8; i++)
                name[i] = (char)entry.GetByte(index + i + Entry.DOSName);

            int len = 8;

            for (int i = 7; i > 0; i--)
                if (name[i] == ' ')
                    len--;
                else
                    break;

            // special case where real character is same as the delete
            if ((len >= 1) && (name[0] == (char)FileNameAttribute.Escape))
                name[0] = (char)FileNameAttribute.Deleted;

            name[len] = '.';

            len++;

            for (uint i = 0; i < 3; i++)
                name[len + i] = (char)entry.GetByte(index + i + Entry.DOSExtension);

            len = len + 3;

            int spaces = 0;
            for (int i = len - 1; i >= 0; i--)
                if (name[i] == ' ')
                    spaces++;
                else
                    break;

            if (spaces == 3)
                spaces = 4;

            len = len - spaces;

            // FIXME
            string str = string.Empty;

            for (uint i = 0; i < len; i++)
                str = str + (char)name[i];

            return str;
        }
예제 #13
0
        /// <summary>
        /// Writes the master boot block.
        /// </summary>
        /// <returns></returns>
        public bool Write()
        {
            if (!diskDevice.CanWrite) { return false; }

            BinaryFormat masterboot = new BinaryFormat(new byte[512]);

            masterboot.SetUInt(MBR.DiskSignature, diskSignature);
            masterboot.SetUShort(MBR.MBRSignature, MBRConstant.MBRSignature);

            if (code != null)
                for (uint index = 0; ((index < MBRConstant.CodeAreaSize) && (index < code.Length)); index++)
                    masterboot.SetByte(index, code[index]);

            for (uint index = 0; index < MaxMBRPartitions; index++)
                if (Partitions[index].TotalBlocks != 0) {
                    uint offset = MBR.FirstPartition + (index * 16);
                    masterboot.SetByte(offset + PartitionRecord.Status, (byte)(Partitions[index].Bootable ? 0x80 : 0x00));
                    masterboot.SetByte(offset + PartitionRecord.PartitionType, Partitions[index].PartitionType);
                    masterboot.SetUInt(offset + PartitionRecord.LBA, Partitions[index].StartLBA);
                    masterboot.SetUInt(offset + PartitionRecord.Sectors, Partitions[index].TotalBlocks);

                    DiskGeometry diskGeometry = new DiskGeometry();
                    diskGeometry.GuessGeometry(diskDevice.TotalBlocks);

                    CHS chsStart = new CHS();
                    CHS chsEnd = new CHS();

                    chsStart.SetCHS(diskGeometry, Partitions[index].StartLBA);
                    chsEnd.SetCHS(diskGeometry, Partitions[index].StartLBA + Partitions[index].TotalBlocks - 1);

                    masterboot.SetByte(offset + PartitionRecord.FirstCRS, chsStart.Head);
                    masterboot.SetByte(offset + PartitionRecord.FirstCRS + 1, (byte)((chsStart.Sector & 0x3F) | ((chsStart.Cylinder >> 8) & 0x03)));
                    masterboot.SetByte(offset + PartitionRecord.FirstCRS + 2, (byte)(chsStart.Cylinder & 0xFF));
                    masterboot.SetByte(offset + PartitionRecord.LastCRS, chsEnd.Head);
                    masterboot.SetByte(offset + PartitionRecord.LastCRS + 1, (byte)((chsEnd.Sector & 0x3F) | ((chsEnd.Cylinder >> 8) & 0x03)));
                    masterboot.SetByte(offset + PartitionRecord.LastCRS + 2, (byte)(chsEnd.Cylinder & 0xFF));
                }

            diskDevice.WriteBlock(0, 1, masterboot.Data);

            return true;
        }
예제 #14
0
        /// <summary>
        /// Reads the boot sector.
        /// </summary>
        /// <returns></returns>
        protected bool ReadBootSector()
        {
            valid = false;

            if (blockSize != 512)   // only going to work with 512 sector sizes (for now)
                return false;

            BinaryFormat bootSector = new BinaryFormat(partition.ReadBlock(0, 1));

            if (bootSector.GetUShort(BootSector.BootSectorSignature) != 0xAA55)
                return false;

            byte extendedBootSignature = bootSector.GetByte(BootSector.ExtendedBootSignature);
            byte extendedBootSignature32 = bootSector.GetByte(BootSector.FAT32_ExtendedBootSignature);

            if ((extendedBootSignature != 0x29) && (extendedBootSignature != 0x28) && (extendedBootSignature32 != 0x29))
                return false;

            volumeLabel = bootSector.GetString(BootSector.VolumeLabel, 8).ToString().TrimEnd();
            bytesPerSector = bootSector.GetUShort(BootSector.BytesPerSector);
            sectorsPerCluster = bootSector.GetByte(BootSector.SectorsPerCluster);
            reservedSectors = bootSector.GetByte(BootSector.ReservedSectors);
            nbrFats = bootSector.GetByte(BootSector.FatAllocationTables);
            rootEntries = bootSector.GetUShort(BootSector.MaxRootDirEntries);
            rootCluster32 = bootSector.GetUInt(BootSector.FAT32_ClusterNumberOfRoot);

            uint sectorsPerFat16 = bootSector.GetUShort(BootSector.SectorsPerFAT);
            uint sectorsPerFat32 = bootSector.GetUInt(BootSector.FAT32_SectorPerFAT);
            uint totalSectors16 = bootSector.GetUShort(BootSector.TotalSectors16);
            uint totalSectors32 = bootSector.GetUInt(BootSector.TotalSectors32);
            uint sectorsPerFat = (sectorsPerFat16 != 0) ? sectorsPerFat16 : sectorsPerFat32;
            uint fatSectors = 0;

            try
            {
                fatSectors = nbrFats * sectorsPerFat;
                clusterSizeInBytes = sectorsPerCluster * blockSize;
                rootDirSectors = (((rootEntries * 32) + (bytesPerSector - 1)) / bytesPerSector);
                firstDataSector = reservedSectors + (nbrFats * sectorsPerFat) + rootDirSectors;
                totalSectors = (totalSectors16 != 0) ? totalSectors16 : totalSectors32;
                dataSectors = totalSectors - (reservedSectors + (nbrFats * sectorsPerFat) + rootDirSectors);
                totalClusters = dataSectors / sectorsPerCluster;
                entriesPerSector = (bytesPerSector / 32);
                firstRootDirectorySector = reservedSectors + fatSectors;
                dataAreaStart = firstRootDirectorySector + rootDirSectors;
            }
            catch
            {
                return false;
            }

            // Some basic checks
            if ((nbrFats == 0) || (nbrFats > 2) || (totalSectors == 0) || (sectorsPerFat == 0))
                return false;

            if (totalClusters < 4085)
                fatType = FatType.FAT12;
            else if (totalClusters < 65525)
                fatType = FatType.FAT16;
            else
                fatType = FatType.FAT32;

            if (fatType == FatType.FAT12)
            {
                reservedClusterMark = 0xFF0;
                endOfClusterMark = 0x0FF8;
                badClusterMark = 0x0FF7;
                fatMask = 0xFFFFFFFF;
                fatEntries = sectorsPerFat * 3 * blockSize / 2;
            }
            else if (fatType == FatType.FAT16)
            {
                reservedClusterMark = 0xFFF0;
                endOfClusterMark = 0xFFF8;
                badClusterMark = 0xFFF7;
                fatMask = 0xFFFFFFFF;
                fatEntries = sectorsPerFat * blockSize / 2;
            }
            else
            { //  if (type == FatType.FAT32) {
                reservedClusterMark = 0xFFF0;
                endOfClusterMark = 0x0FFFFFF8;
                badClusterMark = 0x0FFFFFF7;
                fatMask = 0x0FFFFFFF;
                fatEntries = sectorsPerFat * blockSize / 4;
            }

            // More basic checks
            if ((fatType == FatType.FAT32) && (rootCluster32 == 0))
                return false;

            valid = true;

            serialNbr = bootSector.GetBytes(fatType != FatType.FAT32 ? BootSector.IDSerialNumber : BootSector.FAT32_IDSerialNumber, 4);

            return true;
        }
예제 #15
0
        /// <summary>
        /// Formats the partition with specified fat settings.
        /// </summary>
        /// <param name="fatSettings">The fat settings.</param>
        /// <returns></returns>
        public bool Format(FatSettings fatSettings)
        {
            if (!partition.CanWrite)
                return false;

            this.fatType = fatSettings.FATType;
            bytesPerSector = 512;
            nbrFats = 2;

            totalSectors = partition.BlockCount;
            sectorsPerCluster = GetSectorsPerClusterByTotalSectors(fatType, totalSectors);

            if (sectorsPerCluster == 0)
                return false;

            if (fatType == FatType.FAT32)
            {
                reservedSectors = 32;
                rootEntries = 0;
            }
            else
            {
                reservedSectors = 1;
                rootEntries = 512;
            }

            rootDirSectors = (((rootEntries * 32) + (bytesPerSector - 1)) / bytesPerSector);

            uint val1 = totalSectors - (reservedSectors + rootDirSectors);
            uint val2 = (uint)((sectorsPerCluster * 256) + nbrFats);

            if (fatType == FatType.FAT32)
                val2 = val2 / 2;

            uint sectorsPerFat = (val1 + (val2 - 1)) / val2;

            firstRootDirectorySector = reservedSectors + sectorsPerFat;

            BinaryFormat bootSector = new BinaryFormat(512);

            bootSector.SetUInt(BootSector.JumpInstruction, 0);
            bootSector.SetString(BootSector.EOMName, "MOSA    ");
            bootSector.SetUShort(BootSector.BytesPerSector, (ushort)bytesPerSector);
            bootSector.SetByte(BootSector.SectorsPerCluster, (byte)sectorsPerCluster);
            bootSector.SetUShort(BootSector.ReservedSectors, (ushort)reservedSectors);
            bootSector.SetByte(BootSector.FatAllocationTables, nbrFats);
            bootSector.SetUShort(BootSector.MaxRootDirEntries, (ushort)rootEntries);
            bootSector.SetUShort(BootSector.BootSectorSignature, 0xAA55);

            if (totalSectors > 0xFFFF)
            {
                bootSector.SetUShort(BootSector.TotalSectors16, 0);
                bootSector.SetUInt(BootSector.TotalSectors32, totalSectors);
            }
            else
            {
                bootSector.SetUShort(BootSector.TotalSectors16, (ushort)totalSectors);
                bootSector.SetUInt(BootSector.TotalSectors32, 0);
            }

            if (fatSettings.FloppyMedia)
            {
                // Default is 1.44
                bootSector.SetByte(BootSector.MediaDescriptor, 0xF0); // 0xF0 = 3.5" Double Sided, 80 tracks per side, 18 sectors per track (1.44MB).
            }
            else
                bootSector.SetByte(BootSector.MediaDescriptor, 0xF8); // 0xF8 = Hard disk

            bootSector.SetUShort(BootSector.SectorsPerTrack, fatSettings.SectorsPerTrack);
            bootSector.SetUShort(BootSector.NumberOfHeads, fatSettings.NumberOfHeads);
            bootSector.SetUInt(BootSector.HiddenSectors, fatSettings.HiddenSectors);

            if (fatType != FatType.FAT32)
            {
                bootSector.SetUShort(BootSector.SectorsPerFAT, (ushort)sectorsPerFat);
                if (fatSettings.FloppyMedia)
                    bootSector.SetByte(BootSector.PhysicalDriveNbr, 0x00);
                else
                    bootSector.SetByte(BootSector.PhysicalDriveNbr, 0x80);

                bootSector.SetByte(BootSector.ReservedCurrentHead, 0);
                bootSector.SetByte(BootSector.ExtendedBootSignature, 0x29);
                bootSector.SetBytes(BootSector.IDSerialNumber, fatSettings.SerialID, 0, (uint)Math.Min(4, fatSettings.SerialID.Length));

                if (string.IsNullOrEmpty(fatSettings.VolumeLabel))
                    bootSector.SetString(BootSector.VolumeLabel, "NO NAME    ");
                else
                {
                    bootSector.SetString(BootSector.VolumeLabel, "           ");  // 11 blank spaces
                    bootSector.SetString(BootSector.VolumeLabel, fatSettings.VolumeLabel, (uint)Math.Min(11, fatSettings.VolumeLabel.Length));
                }

                if (fatSettings.OSBootCode != null)
                {
                    if (fatSettings.OSBootCode.Length == 512)
                    {
                        bootSector.SetBytes(BootSector.JumpInstruction, fatSettings.OSBootCode, BootSector.JumpInstruction, 3);
                        bootSector.SetBytes(BootSector.OSBootCode, fatSettings.OSBootCode, BootSector.OSBootCode, 448);
                    }
                    else
                    {
                        bootSector.SetByte(BootSector.JumpInstruction, 0xEB); // 0xEB = JMP Instruction
                        bootSector.SetByte(BootSector.JumpInstruction + 1, 0x3C);
                        bootSector.SetByte(BootSector.JumpInstruction + 2, 0x90);
                        bootSector.SetBytes(BootSector.OSBootCode, fatSettings.OSBootCode, 0, (uint)Math.Min(448, fatSettings.OSBootCode.Length));
                    }
                }

                if (fatType == FatType.FAT12)
                    bootSector.SetString(BootSector.FATType, "FAT12   ");
                else
                    bootSector.SetString(BootSector.FATType, "FAT16   ");
            }

            if (fatType == FatType.FAT32)
            {
                bootSector.SetUShort(BootSector.SectorsPerFAT, 0);
                bootSector.SetUInt(BootSector.FAT32_SectorPerFAT, sectorsPerFat);
                bootSector.SetByte(BootSector.FAT32_Flags, 0);
                bootSector.SetUShort(BootSector.FAT32_Version, 0);
                bootSector.SetUInt(BootSector.FAT32_ClusterNumberOfRoot, 2);
                bootSector.SetUShort(BootSector.FAT32_SectorFSInformation, 1);
                bootSector.SetUShort(BootSector.FAT32_SecondBootSector, 6);
                bootSector.SetByte(BootSector.FAT32_PhysicalDriveNbr, 0x80);
                bootSector.SetByte(BootSector.FAT32_Reserved2, 0);
                bootSector.SetByte(BootSector.FAT32_ExtendedBootSignature, 0x29);
                bootSector.SetBytes(BootSector.FAT32_IDSerialNumber, fatSettings.SerialID, 0, (uint)Math.Min(4, fatSettings.SerialID.Length));
                bootSector.SetString(BootSector.FAT32_VolumeLabel, "           ");  // 11 blank spaces
                bootSector.SetString(BootSector.FAT32_VolumeLabel, fatSettings.VolumeLabel, (uint)(fatSettings.VolumeLabel.Length <= 11 ? fatSettings.VolumeLabel.Length : 11));
                bootSector.SetString(BootSector.FAT32_FATType, "FAT32   ");

                if (fatSettings.OSBootCode.Length == 512)
                {
                    bootSector.SetBytes(BootSector.JumpInstruction, fatSettings.OSBootCode, BootSector.JumpInstruction, 3);
                    bootSector.SetBytes(BootSector.FAT32_OSBootCode, fatSettings.OSBootCode, BootSector.FAT32_OSBootCode, 420);
                }
                else
                {
                    bootSector.SetByte(BootSector.JumpInstruction, 0xEB);  // 0xEB = JMP Instruction
                    bootSector.SetByte(BootSector.JumpInstruction + 1, 0x58);
                    bootSector.SetByte(BootSector.JumpInstruction + 2, 0x90);
                    bootSector.SetBytes(BootSector.FAT32_OSBootCode, fatSettings.OSBootCode, 0, (uint)Math.Min(420, fatSettings.OSBootCode.Length));
                }
            }

            // Write Boot Sector
            partition.WriteBlock(0, 1, bootSector.Data);

            if (fatType == FatType.FAT32)
            {
                // Write backup Boot Sector
                if (fatType == FatType.FAT32)
                    partition.WriteBlock(6, 1, bootSector.Data);

                // Create FSInfo Structure
                BinaryFormat infoSector = new BinaryFormat(512);

                infoSector.SetUInt(FSInfo.FSI_LeadSignature, 0x41615252);

                //FSInfo.FSI_Reserved1
                infoSector.SetUInt(FSInfo.FSI_StructureSigature, 0x61417272);
                infoSector.SetUInt(FSInfo.FSI_FreeCount, 0xFFFFFFFF);
                infoSector.SetUInt(FSInfo.FSI_NextFree, 0xFFFFFFFF);

                //FSInfo.FSI_Reserved2
                bootSector.SetUInt(FSInfo.FSI_TrailSignature, 0xAA550000);

                // Write FSInfo Structure
                partition.WriteBlock(1, 1, infoSector.Data);
                partition.WriteBlock(7, 1, infoSector.Data);

                // Create 2nd sector
                BinaryFormat secondSector = new BinaryFormat(512);

                secondSector.SetUShort(FSInfo.FSI_TrailSignature2, 0xAA55);

                partition.WriteBlock(2, 1, secondSector.Data);
                partition.WriteBlock(8, 1, secondSector.Data);
            }

            // Create FAT table(s)

            // Clear primary & secondary FATs
            BinaryFormat emptyFat = new BinaryFormat(512);

            for (uint i = 1; i < sectorsPerFat; i++)
                partition.WriteBlock(reservedSectors + i, 1, emptyFat.Data);

            if (nbrFats == 2)
                for (uint i = 1; i < sectorsPerFat; i++)
                    partition.WriteBlock(reservedSectors + sectorsPerFat + i, 1, emptyFat.Data);

            // First FAT block is special
            BinaryFormat firstFat = new BinaryFormat(512);

            if (fatType == FatType.FAT12)
            {
                firstFat.SetByte(1, 0xFF);
                firstFat.SetByte(2, 0xFF); // 0xF8
            }
            else if (fatType == FatType.FAT16)
            {
                firstFat.SetUShort(0, 0xFFFF);
                firstFat.SetUShort(2, 0xFFFF); // 0xFFF8
            }
            else // if (type == FatType.FAT32)
            {
                firstFat.SetUInt(0, 0x0FFFFFFF);
                firstFat.SetUInt(4, 0x0FFFFFFF); // 0x0FFFFFF8
                firstFat.SetUInt(8, 0x0FFFFFFF); // Also reserve the 2nd cluster for root directory
            }

            if (fatSettings.FloppyMedia)
                firstFat.SetByte(0, 0xF0);
            else
                firstFat.SetByte(0, 0xF8);

            partition.WriteBlock(reservedSectors, 1, firstFat.Data);

            if (nbrFats == 2)
                partition.WriteBlock(reservedSectors + sectorsPerFat, 1, firstFat.Data);

            // Create Empty Root Directory
            if (fatType == FatType.FAT32)
            {
            }
            else
            {
                for (uint i = 0; i < rootDirSectors; i++)
                    partition.WriteBlock(firstRootDirectorySector + i, 1, emptyFat.Data);
            }

            return ReadBootSector();
        }
예제 #16
0
        /// <summary>
        /// Sets the name of the volume.
        /// </summary>
        /// <param name="volumeName">Name of the volume.</param>
        public void SetVolumeName(string volumeName)
        {
            if (volumeLabel.Length > 8)
                volumeLabel = volumeLabel.Substring(0, 8);

            FatFileLocation location = FindEntry(new Find.Volume(), 0);

            if (!location.Valid)
            {
                location = FindEntry(new Find.Empty(), 0);

                if (!location.Valid)
                    return; // TODO: something went wrong
            }

            BinaryFormat directory = new BinaryFormat(partition.ReadBlock(location.DirectorySector, 1));

            if (volumeName.Length > 8)
                volumeName = volumeName.Substring(0, 8);

            // Create Entry
            directory.SetString(Entry.DOSName + (location.DirectorySectorIndex * Entry.EntrySize), "            ", 11);
            directory.SetString(Entry.DOSName + (location.DirectorySectorIndex * Entry.EntrySize), volumeName);
            directory.SetByte(Entry.FileAttributes + (location.DirectorySectorIndex * Entry.EntrySize), (byte)FatFileAttributes.VolumeLabel);
            directory.SetByte(Entry.Reserved + (location.DirectorySectorIndex * Entry.EntrySize), 0);
            directory.SetByte(Entry.CreationTimeFine + (location.DirectorySectorIndex * Entry.EntrySize), 0);
            directory.SetUShort(Entry.CreationTime + (location.DirectorySectorIndex * Entry.EntrySize), 0);
            directory.SetUShort(Entry.CreationDate + (location.DirectorySectorIndex * Entry.EntrySize), 0);
            directory.SetUShort(Entry.LastAccessDate + (location.DirectorySectorIndex * Entry.EntrySize), 0);
            directory.SetUShort(Entry.LastModifiedTime + (location.DirectorySectorIndex * Entry.EntrySize), 0);
            directory.SetUShort(Entry.LastModifiedDate + (location.DirectorySectorIndex * Entry.EntrySize), 0);
            directory.SetUShort(Entry.FirstCluster + (location.DirectorySectorIndex * Entry.EntrySize), 0);
            directory.SetUInt(Entry.FileSize + (location.DirectorySectorIndex * Entry.EntrySize), 0);

            partition.WriteBlock(location.DirectorySector, 1, directory.Data);
        }
예제 #17
0
        /// <summary>
        /// Identifies the drive.
        /// </summary>
        protected void IdentifyDrive()
        {
            byte drive = (byte)(((deviceHead & 0x10) != 0x10) ? 0 : 1);
            byte d = (byte)('0' + drive + 1);
            BinaryFormat data = new BinaryFormat(bufferData);

            data.Fill(0, 0, 512);

            // fixed drive and over 5Mb/sec
            data.SetUShort(0x00, 0x140);
            // Serial Number
            data.Fill(0x0A * 2, d, 20);
            data.SetByte(0x0A * 2, d);
            // Firmware version
            data.Fill(0x17 * 2, d, 8);
            data.SetChar(0x17 * 2 + 0, '1');
            data.SetChar(0x17 * 2 + 1, '.');
            data.SetChar(0x17 * 2 + 2, '0');
            // Model Number
            data.Fill(0x1B * 2, d, 40);
            data.SetChar(0x17 * 2 + 0, 'D');
            data.SetChar(0x17 * 2 + 1, 'R');
            data.SetChar(0x17 * 2 + 2, 'I');
            data.SetChar(0x17 * 2 + 3, 'V');
            data.SetChar(0x17 * 2 + 4, 'E');
            data.SetByte(0x1B * 2 + 5, d);
            // lba28
            data.SetUInt(0x3C * 2, (uint)(driveFiles[drive].Length / 512));

            commandStatus = (byte)((commandStatus | 0x08) & ~0x80); // Set DRQ (bit 3), clear BUSY (bit 7)

            status = DeviceStatus.IdentifyDrive;
        }
예제 #18
0
        public static void PatchSyslinux_3_72(PartitionDevice partitionDevice, FatFileSystem fat)
        {
            // Locate ldlinux.sys file for patching
            string filename = "ldlinux.sys";
            string name = (Path.GetFileNameWithoutExtension(filename) + Path.GetExtension(filename).PadRight(4).Substring(0, 4)).ToUpper();

            var location = fat.FindEntry(new Mosa.FileSystem.FAT.Find.WithName(name), 0);

            if (location.IsValid)
            {
                // Read boot sector
                var bootSector = new BinaryFormat(partitionDevice.ReadBlock(0, 1));

                // Set the first sector location of the file
                bootSector.SetUInt(0x1F8, fat.GetSectorByCluster(location.FirstCluster));

                // Change jump address
                bootSector.SetUInt(0x01, 0x58);

                // Write back patched boot sector
                partitionDevice.WriteBlock(0, 1, bootSector.Data);

                // Get the file size & number of sectors used
                uint fileSize = fat.GetFileSize(location.DirectorySector, location.DirectorySectorIndex);
                uint sectorCount = (fileSize + 511) >> 9;

                uint[] sectors = new uint[65];
                uint nsec = 0;

                // Create list of the first 65 sectors of the file
                for (uint cluster = location.FirstCluster; ((cluster != 0) & (nsec <= 64)); cluster = fat.GetNextCluster(cluster))
                {
                    uint sec = fat.GetSectorByCluster(cluster);
                    for (uint s = 0; s < fat.SectorsPerCluster; s++)
                        sectors[nsec++] = sec + s;
                }

                // Read the first cluster of the file
                var firstCluster = new BinaryFormat(fat.ReadCluster(location.FirstCluster));

                uint patchArea = 0;

                // Search for 0x3EB202FE (magic)
                for (patchArea = 0; (firstCluster.GetUInt(patchArea) != 0x3EB202FE) && (patchArea < fat.ClusterSizeInBytes); patchArea += 4) ;

                patchArea = patchArea + 8;

                if (patchArea < fat.ClusterSizeInBytes)
                {
                    // Set up the totals
                    firstCluster.SetUShort(patchArea, (ushort)(fileSize >> 2));
                    firstCluster.SetUShort(patchArea + 2, (ushort)(sectorCount - 1));

                    // Clear sector entries
                    firstCluster.Fill(patchArea + 8, 0, 64 * 4);

                    // Set sector entries
                    for (nsec = 0; nsec < 64; nsec++)
                        firstCluster.SetUInt(patchArea + 8 + (nsec * 4), sectors[nsec + 1]);

                    // Clear out checksum
                    firstCluster.SetUInt(patchArea + 4, 0);

                    // Write back the updated cluster
                    fat.WriteCluster(location.FirstCluster, firstCluster.Data);

                    // Re-Calculate checksum by opening the file
                    var file = new FatFileStream(fat, location);

                    uint csum = 0x3EB202FE;
                    for (uint index = 0; index < (file.Length >> 2); index++)
                    {
                        uint value = (uint)file.ReadByte() | ((uint)file.ReadByte() << 8) | ((uint)file.ReadByte() << 16) | ((uint)file.ReadByte() << 24);
                        csum -= value;
                    }

                    // Set the checksum
                    firstCluster.SetUInt(patchArea + 4, csum);

                    // Write patched cluster back to disk
                    fat.WriteCluster(location.FirstCluster, firstCluster.Data);
                }
            }
        }
예제 #19
0
        public static void PatchSyslinux_6_03(PartitionDevice partitionDevice, FatFileSystem fat)
        {
            // Locate ldlinux.sys file for patching
            string filename = "ldlinux.sys";
            string name = (Path.GetFileNameWithoutExtension(filename) + Path.GetExtension(filename).PadRight(4).Substring(0, 4)).ToUpper();

            var location = fat.FindEntry(new Mosa.FileSystem.FAT.Find.WithName(name), 0);

            if (!location.IsValid)
                throw new InvalidProgramException("Unable to find syslinux.sys");

            // Get the file size & number of sectors used
            uint fileSize = fat.GetFileSize(location.DirectorySector, location.DirectorySectorIndex);

            var sectors = new List<uint>();

            // Create list of the sectors of the file
            for (uint cluster = location.FirstCluster; (cluster != 0); cluster = fat.GetNextCluster(cluster))
            {
                uint sec = fat.GetSectorByCluster(cluster);
                for (uint i = 0; i < fat.SectorsPerCluster; i++)
                {
                    sectors.Add(sec + i);
                }
            }

            // Get the ldlinux.sys file stream
            var ldlinux = new FatFileStream(fat, location);

            var ldlinuxReader = new EndianAwareBinaryReader(ldlinux, Endianness.Little);

            // Search for 0x3EB202FE (magic)
            while ((ldlinuxReader.ReadUInt32() != Syslinux.LDLINUX_MAGIC) && (ldlinux.Position < ldlinux.Length)) ;

            if (ldlinux.Position >= ldlinux.Length || ldlinux.Position <= 0)
                throw new InvalidProgramException("Unable to find patch location for syslinux");

            uint patchArea = (uint)ldlinux.Position - 4;

            // Get Extended Patch Area offset
            ldlinux.Position = patchArea + Syslinux.PatchAreaOffset.EPAOffset;
            ushort epa = ldlinuxReader.ReadUInt16();

            ldlinux.Position = epa + Syslinux.ExtendedPatchAreaOffset.Sect1Ptr0;
            uint sect1Ptr0 = (uint)ldlinuxReader.ReadUInt16();

            ldlinux.Position = epa + Syslinux.ExtendedPatchAreaOffset.Sect1Ptr1;
            uint sect1Ptr1 = (uint)ldlinuxReader.ReadUInt16();

            ldlinux.Position = epa + Syslinux.ExtendedPatchAreaOffset.SecPtrOffset;
            uint ex = (uint)ldlinuxReader.ReadUInt16();

            ldlinux.Position = epa + Syslinux.ExtendedPatchAreaOffset.SecPtrCnt;
            uint nptrs = (uint)ldlinuxReader.ReadUInt16();

            ldlinux.Position = epa + Syslinux.ExtendedPatchAreaOffset.AdvPtrOffset;
            uint advptrs = (uint)ldlinuxReader.ReadUInt16();

            if (sectors.Count > nptrs)
                throw new InvalidProgramException("Insufficient space for patching syslinux");

            var ldlinuxWriter = new EndianAwareBinaryWriter(ldlinux, Endianness.Little);

            // Set up the totals
            ldlinux.Position = patchArea + Syslinux.PatchAreaOffset.DataSectors;
            ldlinuxWriter.Write((ushort)sectors.Count);

            ldlinux.Position = patchArea + Syslinux.PatchAreaOffset.DataSectors;
            ldlinuxWriter.Write((ushort)2);

            ldlinux.Position = patchArea + Syslinux.PatchAreaOffset.DataSectors;
            ldlinuxWriter.Write((uint)fileSize >> 2);

            // Generate Extents
            var extents = GenerateExtents(sectors);

            ldlinux.Position = ex;

            // Write out extents
            foreach (var extent in extents)
            {
                ldlinuxWriter.Write((ulong)extent.Start);
                ldlinuxWriter.Write((ushort)extent.Length);
            }

            // Write out ADV
            ldlinux.Position = advptrs;
            ldlinuxWriter.Write((ulong)sectors[sectors.Count - 2]);
            ldlinuxWriter.Write((ulong)sectors[sectors.Count - 1]);

            // Clear out checksum
            ldlinux.Position = patchArea + Syslinux.PatchAreaOffset.Checksum;
            ldlinuxWriter.Write((uint)0);

            // Write back the updated cluster
            ldlinuxWriter.Flush();

            // Re-Calculate checksum
            ldlinux.Position = 0;
            uint csum = Syslinux.LDLINUX_MAGIC;
            for (uint index = 0; index < (ldlinux.Length >> 2); index++)
            {
                csum = csum + ldlinuxReader.ReadUInt32();
            }

            // Set the checksum
            ldlinux.Position = patchArea + Syslinux.PatchAreaOffset.Checksum;
            ldlinuxWriter.Write(csum);

            // Write patched cluster back to disk
            ldlinuxWriter.Flush();

            // Read boot sector
            var fatBootSector = new BinaryFormat(partitionDevice.ReadBlock(0, 1));

            // Set the first sector location of the file
            fatBootSector.SetUInt(sect1Ptr0, fat.GetSectorByCluster(location.FirstCluster));
            fatBootSector.SetUInt(sect1Ptr1, 0);   // since only 32-bit offsets are support, the high portion of 64-bit value is zero

            // Write back patched boot sector
            partitionDevice.WriteBlock(0, 1, fatBootSector.Data);
        }
예제 #20
0
        /// <summary>
        /// Reads the LBA48.
        /// </summary>
        /// <param name="operation">The operation.</param>
        /// <param name="drive">The drive.</param>
        /// <param name="lba">The lba.</param>
        /// <param name="data">The data.</param>
        /// <param name="offset">The offset.</param>
        /// <returns></returns>
        protected bool ReadLBA48(SectorOperation operation, uint drive, uint lba, byte[] data, uint offset)
        {
            if (drive > MaximunDriveCount)
                return false;

            FeaturePort.Write8(0);
            FeaturePort.Write8(0);

            SectorCountPort.Write8(0);
            SectorCountPort.Write8(1);

            LBALowPort.Write8((byte)((lba >> 24) & 0xFF));
            LBALowPort.Write8((byte)(lba & 0xFF));

            LBAMidPort.Write8((byte)((lba >> 32) & 0xFF));
            LBAMidPort.Write8((byte)((lba >> 8) & 0xFF));

            LBAHighPort.Write8((byte)((lba >> 40) & 0xFF));
            LBAHighPort.Write8((byte)((lba >> 16) & 0xFF));

            DeviceHeadPort.Write8((byte)(0x40 | (drive << 4)));

            if (operation == SectorOperation.Write)
                CommandPort.Write8(0x34);
            else
                CommandPort.Write8(0x24);

            if (!WaitForRegisterReady())
                return false;

            var sector = new BinaryFormat(data);

            //TODO: Don't use PIO
            if (operation == SectorOperation.Read)
            {
                for (uint index = 0; index < 256; index++)
                    sector.SetUShort(offset + (index * 2), DataPort.Read16());
            }
            else
            {
                for (uint index = 0; index < 256; index++)
                    DataPort.Write16(sector.GetUShort(offset + (index * 2)));
            }

            return true;
        }
예제 #21
0
        /// <summary>
        /// Opens the specified drive NBR.
        /// </summary>
        /// <param name="drive">The drive NBR.</param>
        /// <returns></returns>
        public bool Open(uint drive)
        {
            if (drive > MaximunDriveCount)
                return false;

            if (!driveInfo[drive].Present)
                return false;

            if (drive == 0)
                DeviceHeadPort.Write8(0xA0);
            else
                if (drive == 1)
                DeviceHeadPort.Write8(0xB0);
            else
                return false;

            CommandPort.Write8(IDECommands.IdentifyDrive);

            if (!WaitForRegisterReady())
                return false;

            var info = new BinaryFormat(new byte[512]);

            for (uint index = 0; index < 256; index++)
                info.SetUShort(index * 2, DataPort.Read16());

            driveInfo[drive].MaxLBA = info.GetUInt(IdentifyDrive.MaxLBA28);

            return true;
        }
예제 #22
0
 /// <summary>
 /// Gets the size of the file.
 /// </summary>
 /// <param name="directoryBlock">The directory block.</param>
 /// <param name="index">The index.</param>
 /// <returns></returns>
 public uint GetFileSize(uint directoryBlock, uint index)
 {
     BinaryFormat directory = new BinaryFormat(partition.ReadBlock(directoryBlock, 1));
     return directory.GetUInt((index * Entry.EntrySize) + Entry.FileSize);
 }
예제 #23
0
        /// <summary>
        /// Updates the length.
        /// </summary>
        /// <param name="size">The size.</param>
        /// <param name="firstCluster">The first cluster.</param>
        /// <param name="directorySector">The directory sector.</param>
        /// <param name="directorySectorIndex">Index of the directory sector.</param>
        public void UpdateLength(uint size, uint firstCluster, uint directorySector, uint directorySectorIndex)
        {
            // Truncate the file
            BinaryFormat entry = new BinaryFormat(partition.ReadBlock(directorySector, 1));

            // Truncate the file length and set
            entry.SetUInt(Entry.FileSize + (directorySectorIndex * Entry.EntrySize), size);

            if (size == 0)
                entry.SetUInt(Entry.FirstCluster + (directorySectorIndex * Entry.EntrySize), 0);

            partition.WriteBlock(directorySector, 1, entry.Data);

            if (size == 0)
                FreeClusterChain(firstCluster);
        }
예제 #24
0
        /// <summary>
        /// Gets the cluster entry value.
        /// </summary>
        /// <param name="cluster">The cluster.</param>
        /// <returns></returns>
        protected uint GetClusterEntryValue(uint cluster)
        {
            uint fatoffset = 0;

            if (fatType == FatType.FAT12)
                fatoffset = (cluster + (cluster / 2));
            else if (fatType == FatType.FAT16)
                fatoffset = cluster * 2;
            else //if (type == FatType.FAT32)
                fatoffset = cluster * 4;

            uint sector = reservedSectors + (fatoffset / bytesPerSector);
            uint sectorOffset = fatoffset % bytesPerSector;
            uint nbrSectors = 1;

            if ((fatType == FatType.FAT12) && (sectorOffset == bytesPerSector - 1))
                nbrSectors = 2;

            BinaryFormat fat = new BinaryFormat(partition.ReadBlock(sector, nbrSectors));

            uint clusterValue;

            if (fatType == FatType.FAT12)
            {
                clusterValue = fat.GetUShort(sectorOffset);
                if (cluster % 2 == 1)
                    clusterValue = clusterValue >> 4;
                else
                    clusterValue = clusterValue & 0x0FFF;
            }
            else if (fatType == FatType.FAT16)
                clusterValue = fat.GetUShort(sectorOffset);
            else //if (type == FatType.FAT32)
                clusterValue = fat.GetUInt(sectorOffset) & 0x0FFFFFFF;

            return clusterValue;
        }
예제 #25
0
        /// <summary>
        /// Reads the master boot block.
        /// </summary>
        /// <returns></returns>
        public bool Read()
        {
            valid = false;

            if (diskDevice.BlockSize != 512) return false;  // only going to work with 512 sector sizes
            if (diskDevice.TotalBlocks < 3) return false;

            BinaryFormat masterboot = new BinaryFormat(diskDevice.ReadBlock(0, 1));

            if (masterboot.GetUShort(MBR.MBRSignature) != MBRConstant.MBRSignature)
                return false;

            valid = true;

            diskSignature = masterboot.GetUInt(MBR.DiskSignature);

            for (uint index = 0; index < MaxMBRPartitions; index++) {
                uint offset = MBR.FirstPartition + (index * MBRConstant.PartitionSize);

                GenericPartition partition = new GenericPartition(index);

                partition.Bootable = masterboot.GetByte(offset + PartitionRecord.Status) == MBRConstant.Bootable;
                partition.PartitionType = masterboot.GetByte(offset + PartitionRecord.PartitionType);
                partition.StartLBA = masterboot.GetUInt(offset + PartitionRecord.LBA);
                partition.TotalBlocks = masterboot.GetUInt(offset + PartitionRecord.Sectors);

                Partitions[index] = partition;
            }

            //TODO: Extended Partitions

            code = new byte[MBRConstant.CodeAreaSize];
            for (uint index = 0; index < MBRConstant.CodeAreaSize; index++)
                code[index] = masterboot.GetByte(index);

            return valid;
        }