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 = fatStart + (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 & 0xF) | (nextcluster << 4)); } else { clustervalue = ((clustervalue & 0xf000) | (nextcluster)); } fat.SetUShort(sectorOffset, (ushort)clustervalue); } else if (fatType == FATType.FAT16) { fat.SetUShort(sectorOffset, (ushort)nextcluster); } else //if (type == FatType.FAT32) { fat.SetUInt(sectorOffset, nextcluster); } partition.WriteBlock(sector, nbrSectors, fat.Data); return(true); }
/// <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; }
/// <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 (!WaitForReqisterReady()) { return(false); } BinaryFormat 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); }
public override void MakeDirectory(string DirName) { //TODO: Same Entry Exist exception. FatFileLocation location = FindEntry(new FileSystem.Find.Empty(), FatCurrentDirectoryEntry); uint FirstCluster = AllocateFirstCluster(); var xdata = new byte[512 * SectorsPerCluster]; this.IDevice.Read(location.DirectorySector, SectorsPerCluster, xdata); BinaryFormat directory = new BinaryFormat(xdata); directory.SetString(Entry.DOSName + location.DirectorySectorIndex * 32, " ", 11); directory.SetString(Entry.DOSName + location.DirectorySectorIndex * 32, DirName); directory.SetByte(Entry.FileAttributes + location.DirectorySectorIndex * 32, (byte)0x10); directory.SetByte(Entry.Reserved + location.DirectorySectorIndex * 32, 0); directory.SetByte(Entry.CreationTimeFine + location.DirectorySectorIndex * 32, 0); directory.SetUShort(Entry.CreationTime + location.DirectorySectorIndex * 32, 0); directory.SetUShort(Entry.CreationDate + location.DirectorySectorIndex * 32, 0); directory.SetUShort(Entry.LastAccessDate + location.DirectorySectorIndex * 32, 0); directory.SetUShort(Entry.LastModifiedTime + location.DirectorySectorIndex * 32, 0); directory.SetUShort(Entry.LastModifiedDate + location.DirectorySectorIndex * 32, 0); directory.SetUShort(Entry.FirstCluster + location.DirectorySectorIndex * 32, (ushort)FirstCluster); directory.SetUInt(Entry.FileSize + location.DirectorySectorIndex * 32, 0); this.IDevice.Write(location.DirectorySector, SectorsPerCluster, xdata); FatFileLocation loc = FindEntry(new FileSystem.Find.Empty(), FirstCluster); xdata = new byte[512 * SectorsPerCluster]; this.IDevice.Read(loc.DirectorySector, SectorsPerCluster, xdata); directory = new BinaryFormat(xdata); for (int i = 0; i < 2; i++) { directory.SetString(Entry.DOSName + loc.DirectorySectorIndex * 32, " ", 11); if (i == 0) { directory.SetString(Entry.DOSName + loc.DirectorySectorIndex * 32, "."); directory.SetUShort(Entry.FirstCluster + loc.DirectorySectorIndex * 32, (ushort)FirstCluster); } else { directory.SetString(Entry.DOSName + loc.DirectorySectorIndex * 32, ".."); directory.SetUShort(Entry.FirstCluster + loc.DirectorySectorIndex * 32, (ushort)FatCurrentDirectoryEntry); } directory.SetByte(Entry.FileAttributes + loc.DirectorySectorIndex * 32, (byte)0x10); directory.SetByte(Entry.Reserved + loc.DirectorySectorIndex * 32, 0); directory.SetByte(Entry.CreationTimeFine + loc.DirectorySectorIndex * 32, 0); directory.SetUShort(Entry.CreationTime + loc.DirectorySectorIndex * 32, 0); directory.SetUShort(Entry.CreationDate + loc.DirectorySectorIndex * 32, 0); directory.SetUShort(Entry.LastAccessDate + loc.DirectorySectorIndex * 32, 0); directory.SetUShort(Entry.LastModifiedTime + loc.DirectorySectorIndex * 32, 0); directory.SetUShort(Entry.LastModifiedDate + loc.DirectorySectorIndex * 32, 0); directory.SetUInt(Entry.FileSize + loc.DirectorySectorIndex * 32, 0); loc.DirectorySectorIndex += 1; } this.IDevice.Write(loc.DirectorySector, SectorsPerCluster, xdata); }
/// <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); }
protected bool PerformLBA28(SectorOperation operation, uint driveNbr, uint lba, byte[] data, uint offset) { FeaturePort.Write8(0); SectorCountPort.Write8(1); LBALowPort.Write8((byte)(lba & 0xFF)); LBAMidPort.Write8((byte)((lba >> 8) & 0xFF)); LBAHighPort.Write8((byte)((lba >> 16) & 0xFF)); DeviceHeadPort.Write8((byte)(0xE0 | (driveNbr << 4) | ((lba >> 24) & 0x0F))); if (operation == SectorOperation.Write) { CommandPort.Write8(IDECommand.WriteSectorsWithRetry); } else { CommandPort.Write8(IDECommand.ReadSectorsWithRetry); } if (!WaitForReqisterReady()) { return(false); } BinaryFormat 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); }
/// <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 (!WaitForReqisterReady()) { return(false); } BinaryFormat 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); }
// doesn't work since uint should be uint64 //protected bool ReadLBA48 (SectorOperation operation, uint drive, uint lba, MemoryBlock memory) //{ // 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 (!WaitForReqisterReady ()) // return false; // //TODO: Don't use PIO // if (operation == SectorOperation.Read) { // for (uint index = 0; index < 256; index++) // memory.SetUShort (index * 2, DataPort.Read16 ()); // } // else { // for (uint index = 0; index < 256; index++) // DataPort.WriteUShort (memory.GetUShort (index * 2)); // } // return true; //} public bool Open(uint driveNbr) { if (driveNbr == 0) { DeviceHeadPort.Write8(0xA0); } else if (driveNbr == 1) { DeviceHeadPort.Write8(0xB0); } else { return(false); } CommandPort.Write8(IDECommand.IdentifyDrive); if (!WaitForReqisterReady()) { return(false); } BinaryFormat info = new BinaryFormat(new byte[512]); for (uint index = 0; index < 256; index++) { info.SetUShort(index * 2, DataPort.Read16()); } driveInfo[driveNbr].MaxLBA = info.GetUInt(IdentifyDrive.MaxLBA28); // legacy info driveInfo[driveNbr].Heads = info.GetUShort(IdentifyDrive.LogicalHeads); driveInfo[driveNbr].Cylinders = info.GetUShort(IdentifyDrive.LogicalCylinders); driveInfo[driveNbr].SectorsPerTrack = info.GetUShort(IdentifyDrive.LogicalSectors); return(true); }
public bool Format(FATSettings fatSettings) { if (!partition.CanWrite) { return(false); } this.fatType = fatSettings.FatType; bytesPerSector = 512; totalSectors = partition.BlockCount; sectorsPerCluster = GetSectorsPerClusterByTotalSectors(fatType, totalSectors); nbrFats = 2; if (fatType == FATType.FAT32) { reservedSectors = 32; rootEntries = 0; } else { reservedSectors = 1; rootEntries = 512; } rootDirSectors = (((rootEntries * 32) + (bytesPerSector - 1)) / bytesPerSector); fatStart = reservedSectors; uint val1 = totalSectors - (reservedSectors + rootDirSectors); uint val2 = (uint)((256 * sectorsPerCluster) + nbrFats); if (fatType == FATType.FAT32) { val2 = val2 / 2; } uint sectorsperfat = (val1 + (val2 - 1)) / val2; BinaryFormat bootSector = new BinaryFormat(512); bootSector.SetUInt(BootSector.JumpInstruction, 0); bootSector.SetString(BootSector.EOMName, "MSWIN4.1"); 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); if (totalSectors > 0xFFFF) { bootSector.SetUShort(BootSector.TotalSectors, 0); bootSector.SetUInt(BootSector.FAT32_TotalSectors, totalClusters); } else { bootSector.SetUShort(BootSector.TotalSectors, (ushort)totalSectors); bootSector.SetUInt(BootSector.FAT32_TotalSectors, 0); } bootSector.SetByte(BootSector.MediaDescriptor, 0xF8); if (fatType == FATType.FAT32) { bootSector.SetUShort(BootSector.SectorsPerFAT, 0); } else { bootSector.SetUShort(BootSector.SectorsPerFAT, (ushort)sectorsperfat); } bootSector.SetUShort(BootSector.SectorsPerTrack, 0); ////FIXME bootSector.SetUInt(BootSector.HiddenSectors, 0); if (fatType != FATType.FAT32) { bootSector.SetByte(BootSector.PhysicalDriveNbr, 0x80); bootSector.SetByte(BootSector.ReservedCurrentHead, 0); bootSector.SetByte(BootSector.ExtendedBootSignature, 0x29); bootSector.SetBytes(BootSector.IDSerialNumber, fatSettings.SerialID, 0, (uint)(fatSettings.SerialID.Length <= 4 ? fatSettings.SerialID.Length : 4)); bootSector.SetString(BootSector.VolumeLabel, " "); // 12 blank spaces bootSector.SetString(BootSector.VolumeLabel, fatSettings.VolumeLabel, (uint)(fatSettings.VolumeLabel.Length <= 12 ? fatSettings.VolumeLabel.Length : 12)); bootSector.SetUShort(BootSector.BootSectorSignature, 0x55AA); //BootSector.OSBootCode // TODO } if (fatType == FATType.FAT12) { bootSector.SetString(BootSector.FATType, "FAT12 "); } else if (fatType == FATType.FAT16) { bootSector.SetString(BootSector.FATType, "FAT16 "); } else // if (type == FatType.FAT32) { bootSector.SetString(BootSector.FATType, "FAT32 "); } if (fatType == FATType.FAT32) { 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); //FAT32_Reserved1 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)(fatSettings.SerialID.Length <= 4 ? fatSettings.SerialID.Length : 4)); bootSector.SetString(BootSector.FAT32_VolumeLabel, " "); // 12 blank spaces bootSector.SetString(BootSector.FAT32_VolumeLabel, fatSettings.VolumeLabel, (uint)(fatSettings.VolumeLabel.Length <= 12 ? fatSettings.VolumeLabel.Length : 12)); bootSector.SetString(BootSector.FAT32_FATType, "FAT32 "); //BootSector.OSBootCode // TODO } // Write Boot Sector partition.WriteBlock(0, 1, bootSector.Data); // Write backup Boot Sector if (fatType == FATType.FAT32) { partition.WriteBlock(0, 1, bootSector.Data); // FIXME: wrong block # } // create FSInfo Structure if (fatType == FATType.FAT32) { 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); partition.WriteBlock(1, 1, infoSector.Data); partition.WriteBlock(7, 1, infoSector.Data); // create 2nd sector BinaryFormat secondSector = new BinaryFormat(512); secondSector.SetUInt((ushort)FSInfo.FSI_TrailSignature2, 0xAA55); partition.WriteBlock(2, 1, secondSector.Data); partition.WriteBlock(8, 1, secondSector.Data); } // create fats /// TODO: incomplete BinaryFormat emptyFat = new BinaryFormat(512); // clear primary & secondary fats entries for (uint i = fatStart; i < fatStart + 1; i++) //FIXME { partition.WriteBlock(i, 1, emptyFat.Data); } // first block is special BinaryFormat firstFat = new BinaryFormat(512); // TODO: incomplete partition.WriteBlock(reservedSectors, 1, emptyFat.Data); return(ReadBootSector()); }
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(name); 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); } } }