data structs

This commit is contained in:
José Pedro 2018-12-04 19:42:52 +00:00
parent 3d3f032d79
commit 03c9caf688
No known key found for this signature in database
GPG key ID: B8247B9301707B83
11 changed files with 478 additions and 255 deletions

View file

@ -0,0 +1,82 @@
using System.Text;
namespace Cosmos.System.FileSystem.FAT
{
internal sealed class BiosParameterBlock : DataStructure
{
public static readonly ByteField JmpBoot0 = new ByteField(0);
public static readonly ByteField JmpBoot1 = new ByteField(1);
public static readonly ByteField JmpBoot2 = new ByteField(2);
public static readonly StringField OemName = new StringField(3, 8, Encoding.ASCII);
public static readonly UInt16Field BytesPerSector = new UInt16Field(11);
public static readonly ByteField SectorsPerCluster = new ByteField(13);
public static readonly UInt16Field ReservedSectorCount = new UInt16Field(14);
public static readonly ByteField FatCount = new ByteField(16);
public static readonly UInt16Field RootEntryCount = new UInt16Field(17);
public static readonly UInt16Field TotalSectorCount16 = new UInt16Field(19);
public static readonly EnumField<FatMediaKind, byte> MediaKind = new EnumField<FatMediaKind, byte>(new ByteField(21));
public static readonly UInt16Field FatSectorCount16 = new UInt16Field(22);
public static readonly UInt16Field SectorsPerTrack = new UInt16Field(24);
public static readonly UInt16Field HeadCount = new UInt16Field(26);
public static readonly UInt32Field HiddenSectorCount = new UInt32Field(28);
public static readonly UInt32Field TotalSectorCount32 = new UInt32Field(32);
public static readonly UInt16Field Signature = new UInt16Field(510);
public static class Fat12
{
public static readonly ByteField DriveNumber = new ByteField(36);
public static readonly ByteField Reserved1 = new ByteField(37);
public static readonly ByteField BootSignature = new ByteField(38);
public static readonly UInt32Field VolumeId = new UInt32Field(39);
public static readonly StringField VolumeLabel = new StringField(43, 11, Encoding.ASCII);
public static readonly StringField FileSystemType = new StringField(54, 8, Encoding.ASCII);
}
public static class Fat32
{
public static readonly UInt32Field FatSectorCount32 = new UInt32Field(36);
public static readonly EnumField<Fat32ExtendedFlags, ushort> ExtendedFlags =
new EnumField<Fat32ExtendedFlags, ushort>(new UInt16Field(40));
public static readonly UInt16Field FileSystemVersion = new UInt16Field(42);
public static readonly UInt32Field RootCluster = new UInt32Field(44);
public static readonly UInt16Field FileSystemInfo = new UInt16Field(48);
public static readonly UInt16Field BackupBootSector = new UInt16Field(50);
public static readonly ByteField DriveNumber = new ByteField(64);
public static readonly ByteField Reserved1 = new ByteField(65);
public static readonly ByteField BootSignature = new ByteField(66);
public static readonly UInt32Field VolumeId = new UInt32Field(67);
public static readonly StringField VolumeLabel = new StringField(71, 11, Encoding.ASCII);
public static readonly StringField FileSystemType = new StringField(82, 8, Encoding.ASCII);
}
public BiosParameterBlock(byte[] data)
: base(data)
{
}
}
}

View file

@ -0,0 +1,147 @@
using System;
using System.Text;
namespace Cosmos.System.FileSystem.FAT
{
internal abstract class DataStructure
{
protected DataStructure(byte[] data)
{
Data = data ?? throw new ArgumentNullException(nameof(data));
}
protected byte[] Data { get; }
public T GetValue<T>(Field<T> field) => field.GetValue(Data);
public void SetValue<T>(Field<T> field, T value) => field.SetValue(Data, value);
}
internal abstract class Field<T>
{
public Field(int position, int length)
{
Position = position;
Length = length;
}
/// <summary>
/// Position, in bytes, of the field.
/// </summary>
public int Position { get; }
/// <summary>
/// Length, in bytes, of the field.
/// </summary>
public int Length { get; }
/// <summary>
/// Gets the value for this field from the data structure.
/// </summary>
/// <param name="data">A byte array which contains a data structure for which this field was defined.</param>
/// <returns>The field value.</returns>
public abstract T GetValue(byte[] data);
/// <summary>
/// Sets the value for this field on the data structure.
/// </summary>
/// <param name="data">A byte array which contains a data structure for which this field was defined.</param>
/// <param name="value">The value to set this field to.</param>
public abstract void SetValue(byte[] data, T value);
}
internal class ByteField : Field<byte>
{
public ByteField(int position)
: base(position, 1)
{
}
public override byte GetValue(byte[] data) => data[Position];
public override void SetValue(byte[] data, byte value) => data[Position] = value;
}
internal class UInt16Field : Field<ushort>
{
public UInt16Field(int position)
: base(position, 2)
{
}
public override ushort GetValue(byte[] data) => BitConverter.ToUInt16(data, Position);
public override void SetValue(byte[] data, ushort value)
{
data[Position] = (byte)value;
data[Position + 1] = (byte)(value >> 8);
}
}
internal class Int32Field : Field<int>
{
public Int32Field(int position)
: base(position, 4)
{
}
public override int GetValue(byte[] data) => BitConverter.ToInt32(data, Position);
public override void SetValue(byte[] data, int value)
{
data[Position] = (byte)value;
data[Position + 1] = (byte)(value >> 8);
data[Position + 2] = (byte)(value >> 16);
data[Position + 3] = (byte)(value >> 24);
}
}
internal class UInt32Field : Field<uint>
{
public UInt32Field(int position)
: base(position, 4)
{
}
public override uint GetValue(byte[] data) => BitConverter.ToUInt32(data, Position);
public override void SetValue(byte[] data, uint value)
{
data[Position] = (byte)value;
data[Position + 1] = (byte)(value >> 8);
data[Position + 2] = (byte)(value >> 16);
data[Position + 3] = (byte)(value >> 24);
}
}
internal class StringField : Field<string>
{
public StringField(int position, int length, Encoding encoding)
: base(position, length)
{
Encoding = encoding;
}
public Encoding Encoding { get; }
public override string GetValue(byte[] data) => Encoding.GetString(data, Position, Length);
public override void SetValue(byte[] data, string value) => Encoding.GetBytes(value, 0, Length, data, Position);
}
internal class EnumField<TEnum, TEnumUnderlyingType> : Field<TEnum>
{
private static readonly EnumField<Fat32ExtendedFlags, int> test = new EnumField<Fat32ExtendedFlags, int>(new Int32Field(12));
private readonly Field<TEnumUnderlyingType> _innerField;
public EnumField(Field<TEnumUnderlyingType> innerField)
: base(innerField.Position, innerField.Length)
{
_innerField = innerField;
}
public override TEnum GetValue(byte[] data) => (TEnum)(object)_innerField.GetValue(data);
public override void SetValue(byte[] data, TEnum value) => _innerField.SetValue(data, (TEnumUnderlyingType)(object)value);
}
}

View file

@ -0,0 +1,11 @@
using System;
namespace Cosmos.System.FileSystem.FAT
{
[Flags]
internal enum Fat32ExtendedFlags
{
ActiveFatMask = 0x000F,
Mirrored = 0x0080
}
}

View file

@ -7,6 +7,8 @@ using Cosmos.Common.Extensions;
using Cosmos.HAL.BlockDevice;
using Cosmos.System.FileSystem.FAT.Listing;
using Cosmos.System.FileSystem.Listing;
using Fields = Cosmos.System.FileSystem.FAT.BiosParameterBlock;
using static Cosmos.System.FileSystem.FAT.BiosParameterBlock;
namespace Cosmos.System.FileSystem.FAT
{
@ -25,12 +27,7 @@ namespace Cosmos.System.FileSystem.FAT
/// <param name="aFatSector">The first sector of the FAT table.</param>
public Fat(FatFileSystem aFileSystem, ulong aFatSector)
{
if (aFileSystem == null)
{
throw new ArgumentNullException(nameof(aFileSystem));
}
mFileSystem = aFileSystem;
mFileSystem = aFileSystem ?? throw new ArgumentNullException(nameof(aFileSystem));
mFatSector = aFatSector;
}
@ -41,15 +38,15 @@ namespace Cosmos.System.FileSystem.FAT
/// <exception cref="NotSupportedException">Can not get the FAT entry size for an unknown FAT type.</exception>
private uint GetFatEntrySizeInBytes()
{
switch (mFileSystem.mFatType)
switch (mFileSystem.FatKind)
{
case FatTypeEnum.Fat32:
case FatKind.Fat32:
return 4;
case FatTypeEnum.Fat16:
case FatKind.Fat16:
return 2;
case FatTypeEnum.Fat12:
case FatKind.Fat12:
// TODO:
break;
}
@ -72,9 +69,8 @@ namespace Cosmos.System.FileSystem.FAT
Global.mFileSystemDebugger.SendInternal("aDataSize =");
Global.mFileSystemDebugger.SendInternal(aDataSize);
var xReturn = new uint[0];
var xReturn = Array.Empty<uint>();
uint xCurrentEntry = aFirstEntry;
uint xValue;
long xEntriesRequired = aDataSize / mFileSystem.BytesPerCluster;
if (aDataSize % mFileSystem.BytesPerCluster != 0)
@ -82,7 +78,7 @@ namespace Cosmos.System.FileSystem.FAT
xEntriesRequired++;
}
GetFatEntry(xCurrentEntry, out xValue);
GetFatEntry(xCurrentEntry, out var xValue);
Array.Resize(ref xReturn, xReturn.Length + 1);
xReturn[xReturn.Length - 1] = xCurrentEntry;
@ -145,8 +141,7 @@ namespace Cosmos.System.FileSystem.FAT
uint xTotalEntries = mFileSystem.FatSectorCount * mFileSystem.BytesPerSector / GetFatEntrySizeInBytes();
for (uint i = mFileSystem.RootCluster; i < xTotalEntries; i++)
{
uint xEntryValue;
GetFatEntry(i, out xEntryValue);
GetFatEntry(i, out var xEntryValue);
if (!FatEntryIsEof(xEntryValue))
{
Global.mFileSystemDebugger.SendInternal("i =");
@ -172,17 +167,15 @@ namespace Cosmos.System.FileSystem.FAT
uint xEntrySize = GetFatEntrySizeInBytes();
ulong xEntryOffset = aEntryNumber * xEntrySize;
switch (mFileSystem.mFatType)
switch (mFileSystem.FatKind)
{
case FatTypeEnum.Fat12:
case FatKind.Fat12:
aData.SetUInt16(xEntryOffset, (ushort)aValue);
break;
case FatTypeEnum.Fat16:
case FatKind.Fat16:
aData.SetUInt16(xEntryOffset, (ushort)aValue);
break;
case FatTypeEnum.Fat32:
case FatKind.Fat32:
aData.SetUInt32(xEntryOffset, (uint)aValue);
break;
default:
@ -195,9 +188,9 @@ namespace Cosmos.System.FileSystem.FAT
uint xEntrySize = GetFatEntrySizeInBytes();
ulong xEntryOffset = aEntryNumber * xEntrySize;
switch (mFileSystem.mFatType)
switch (mFileSystem.FatKind)
{
case FatTypeEnum.Fat12:
case FatKind.Fat12:
// We now access the FAT entry as a WORD just as we do for FAT16, but if the cluster number is
// EVEN, we only want the low 12-bits of the 16-bits we fetch. If the cluster number is ODD
// we want the high 12-bits of the 16-bits we fetch.
@ -211,10 +204,10 @@ namespace Cosmos.System.FileSystem.FAT
aValue = xResult >> 4; // Odd
}
break;
case FatTypeEnum.Fat16:
case FatKind.Fat16:
aValue = BitConverter.ToUInt16(aData, (int)xEntryOffset);
break;
case FatTypeEnum.Fat32:
case FatKind.Fat32:
aValue = BitConverter.ToUInt32(aData, (int)xEntryOffset) & 0x0FFFFFFF;
break;
default:
@ -232,8 +225,7 @@ namespace Cosmos.System.FileSystem.FAT
Global.mFileSystemDebugger.SendInternal($"RootCluster is {mFileSystem.RootCluster}");
Global.mFileSystemDebugger.SendInternal("Clearing all Fat Table");
byte[] xFatTableFistSector;
ReadFatSector(0, out xFatTableFistSector);
ReadFatSector(0, out var xFatTableFistSector);
/* Change 3rd entry (RootDirectory) to be EOC */
SetFatEntry(xFatTableFistSector, 2, FatEntryEofValue());
@ -312,9 +304,9 @@ namespace Cosmos.System.FileSystem.FAT
ReadFatSector(xSector, out xData);
switch (mFileSystem.mFatType)
switch (mFileSystem.FatKind)
{
case FatTypeEnum.Fat12:
case FatKind.Fat12:
// We now access the FAT entry as a WORD just as we do for FAT16, but if the cluster number is
// EVEN, we only want the low 12-bits of the 16-bits we fetch. If the cluster number is ODD
// we want the high 12-bits of the 16-bits we fetch.
@ -329,11 +321,11 @@ namespace Cosmos.System.FileSystem.FAT
}
break;
case FatTypeEnum.Fat16:
case FatKind.Fat16:
aValue = BitConverter.ToUInt16(xData, (int)xEntryOffset);
break;
case FatTypeEnum.Fat32:
case FatKind.Fat32:
aValue = BitConverter.ToUInt32(xData, (int)xEntryOffset) & 0x0FFFFFFF;
break;
@ -364,20 +356,17 @@ namespace Cosmos.System.FileSystem.FAT
byte[] xData;
ReadFatSector(xSector, out xData);
switch (mFileSystem.mFatType)
switch (mFileSystem.FatKind)
{
case FatTypeEnum.Fat12:
case FatKind.Fat12:
xData.SetUInt16(xEntryOffset, (ushort)aValue);
break;
case FatTypeEnum.Fat16:
case FatKind.Fat16:
xData.SetUInt16(xEntryOffset, (ushort)aValue);
break;
case FatTypeEnum.Fat32:
case FatKind.Fat32:
xData.SetUInt32(xEntryOffset, (uint)aValue);
break;
default:
throw new NotSupportedException("Unknown FAT type.");
}
@ -393,188 +382,170 @@ namespace Cosmos.System.FileSystem.FAT
/// <exception cref="Exception">Unknown file system type.</exception>
private bool FatEntryIsEof(ulong aValue)
{
switch (mFileSystem.mFatType)
switch (mFileSystem.FatKind)
{
case FatTypeEnum.Fat12:
case FatKind.Fat12:
return aValue >= 0xFF8;
case FatTypeEnum.Fat16:
case FatKind.Fat16:
return aValue >= 0xFFF8;
case FatTypeEnum.Fat32:
case FatKind.Fat32:
return aValue >= 0xFFFFFF8;
default:
throw new Exception("Unknown file system type.");
}
}
/// <summary>
/// The the EOF value for a specific FAT type.
/// The EOF value for a specific FAT type.
/// </summary>
/// <returns>The EOF value.</returns>
/// <exception cref="Exception">Unknown file system type.</exception>
private ulong FatEntryEofValue()
{
switch (mFileSystem.mFatType)
switch (mFileSystem.FatKind)
{
case FatTypeEnum.Fat12:
case FatKind.Fat12:
return 0x0FFF;
case FatTypeEnum.Fat16:
case FatKind.Fat16:
return 0xFFFF;
case FatTypeEnum.Fat32:
case FatKind.Fat32:
return 0x0FFFFFFF;
default:
throw new Exception("Unknown file system type.");
}
}
}
public readonly uint BytesPerCluster;
public readonly uint BytesPerSector;
public readonly uint ClusterCount;
public readonly uint DataSector; // First Data Sector
public readonly uint DataSectorCount;
public readonly uint FatSectorCount;
private readonly FatTypeEnum mFatType;
public readonly uint NumberOfFATs;
public readonly uint ReservedSectorCount;
public readonly uint RootCluster; // FAT32
public readonly uint RootEntryCount;
public readonly uint RootSector; // FAT12/16
public readonly uint RootSectorCount; // FAT12/16, FAT32 remains 0
public readonly uint SectorsPerCluster;
public readonly uint TotalSectorCount;
private readonly Fat[] mFats;
public override string Type
{
get
{
switch (mFatType)
{
case FatTypeEnum.Fat12:
return "FAT12";
case FatTypeEnum.Fat16:
return "FAT16";
case FatTypeEnum.Fat32:
return "FAT32";
default:
throw new Exception("Unknown FAT file system type.");
}
}
}
/// <summary>
/// Initializes a new instance of the <see cref="FatFileSystem"/> class.
/// </summary>
/// <param name="aDevice">The partition.</param>
/// <param name="aRootPath">The root path.</param>
/// <exception cref="Exception">FAT signature not found.</exception>
public FatFileSystem(Partition aDevice, string aRootPath, long aSize)
public FatFileSystem(BiosParameterBlock bpb, Partition aDevice, string aRootPath, long aSize)
: base(aDevice, aRootPath, aSize)
{
if (aDevice == null)
{
throw new ArgumentNullException(nameof(aDevice));
}
BiosParameterBlock = bpb;
if (String.IsNullOrEmpty(aRootPath))
{
throw new ArgumentException("Argument is null or empty", nameof(aRootPath));
}
BytesPerSector = BiosParameterBlock.GetValue(Fields.BytesPerSector);
SectorsPerCluster = BiosParameterBlock.GetValue(Fields.SectorsPerCluster);
var xBPB = Device.NewBlockArray(1);
BytesPerCluster = (uint)(BytesPerSector * SectorsPerCluster);
Device.ReadBlock(0UL, 1U, xBPB);
ReservedSectorCount = BiosParameterBlock.GetValue(Fields.ReservedSectorCount);
ushort xSig = BitConverter.ToUInt16(xBPB, 510);
if (xSig != 0xAA55)
{
throw new Exception("FAT signature not found.");
}
FatCount = BiosParameterBlock.GetValue(Fields.FatCount);
BytesPerSector = BitConverter.ToUInt16(xBPB, 11);
SectorsPerCluster = xBPB[13];
BytesPerCluster = BytesPerSector * SectorsPerCluster;
ReservedSectorCount = BitConverter.ToUInt16(xBPB, 14);
NumberOfFATs = xBPB[16];
RootEntryCount = BitConverter.ToUInt16(xBPB, 17);
var rootEntryCount = BiosParameterBlock.GetValue(Fields.RootEntryCount);
TotalSectorCount = BitConverter.ToUInt16(xBPB, 19);
if (TotalSectorCount == 0)
{
TotalSectorCount = BitConverter.ToUInt32(xBPB, 32);
}
// 1.
RootDirectorySectorCount = (uint)(((rootEntryCount * 32) + (BytesPerSector - 1)) / BytesPerSector);
// 2.
FatSectorCount = BiosParameterBlock.GetValue(Fields.FatSectorCount16);
// FATSz
FatSectorCount = BitConverter.ToUInt16(xBPB, 22);
if (FatSectorCount == 0)
{
FatSectorCount = BitConverter.ToUInt32(xBPB, 36);
FatSectorCount = BiosParameterBlock.GetValue(Fat32.FatSectorCount32);
}
DataSectorCount = TotalSectorCount -
(ReservedSectorCount + NumberOfFATs * FatSectorCount + ReservedSectorCount);
TotalSectorCount = BiosParameterBlock.GetValue(Fields.TotalSectorCount16);
// Computation rounds down.
if (TotalSectorCount == 0)
{
TotalSectorCount = BiosParameterBlock.GetValue(Fields.TotalSectorCount32);
}
FirstDataSector = ReservedSectorCount + (FatCount * FatSectorCount) + RootDirectorySectorCount;
DataSectorCount = TotalSectorCount - FirstDataSector;
// 3.
ClusterCount = DataSectorCount / SectorsPerCluster;
// Determine the FAT type. Do not use another method - this IS the official and
// proper way to determine FAT type.
// Comparisons are purposefully < and not <=
// FAT16 starts at 4085, FAT32 starts at 65525
if (ClusterCount < 4085)
{
mFatType = FatTypeEnum.Fat12;
FatKind = FatKind.Fat12;
}
else if (ClusterCount < 65525)
{
mFatType = FatTypeEnum.Fat16;
FatKind = FatKind.Fat16;
}
else
{
mFatType = FatTypeEnum.Fat32;
FatKind = FatKind.Fat32;
}
if (mFatType == FatTypeEnum.Fat32)
if (FatKind == FatKind.Fat32)
{
RootCluster = BitConverter.ToUInt32(xBPB, 44);
RootCluster = BiosParameterBlock.GetValue(Fat32.RootCluster);
}
else
{
RootSector = ReservedSectorCount + NumberOfFATs * FatSectorCount;
RootSectorCount = (RootEntryCount * 32 + (BytesPerSector - 1)) / BytesPerSector;
RootSector = ReservedSectorCount + FatCount * FatSectorCount;
}
DataSector = ReservedSectorCount + NumberOfFATs * FatSectorCount + RootSectorCount;
mFats = new Fat[NumberOfFATs];
for (ulong i = 0; i < NumberOfFATs; i++)
mFats = new Fat[FatCount];
for (ulong i = 0; i < FatCount; i++)
{
mFats[i] = new Fat(this, (ReservedSectorCount + i * FatSectorCount));
}
}
public FatKind FatKind { get; }
protected BiosParameterBlock BiosParameterBlock { get; }
protected ushort BytesPerSector { get; }
protected byte SectorsPerCluster { get; }
public uint BytesPerCluster { get; }
protected ushort ReservedSectorCount { get; }
protected byte FatCount { get; }
protected uint RootDirectorySectorCount { get; }
protected uint FatSectorCount { get; }
protected uint TotalSectorCount { get; }
protected uint FirstDataSector { get; }
protected uint DataSectorCount { get; }
protected uint ClusterCount { get; }
// FAT12/16
public uint RootSector { get; }
// FAT32
public uint RootCluster { get; }
public override string Type
{
get
{
switch (FatKind)
{
case FatKind.Fat12:
return "FAT12";
case FatKind.Fat16:
return "FAT16";
case FatKind.Fat32:
return "FAT32";
default:
throw new Exception("Unknown FAT file system type.");
}
}
}
internal Fat GetFat(int aTableNumber)
{
if (mFats.Length > aTableNumber)
@ -582,7 +553,7 @@ namespace Cosmos.System.FileSystem.FAT
return mFats[aTableNumber];
}
throw new Exception("The fat table number doesn't exist.");
throw new Exception("The FAT table number doesn't exist.");
}
internal byte[] NewBlockArray()
@ -599,16 +570,16 @@ namespace Cosmos.System.FileSystem.FAT
aSize = BytesPerCluster;
}
if (mFatType == FatTypeEnum.Fat32)
if (FatKind == FatKind.Fat32)
{
aData = NewBlockArray();
long xSector = DataSector + (aCluster - RootCluster) * SectorsPerCluster;
long xSector = FirstDataSector + (aCluster - RootCluster) * SectorsPerCluster;
Device.ReadBlock((ulong)xSector, SectorsPerCluster, aData);
}
else
{
aData = Device.NewBlockArray(1);
Device.ReadBlock((ulong)aCluster, RootSectorCount, aData);
Device.ReadBlock((ulong)aCluster, RootDirectorySectorCount, aData);
}
}
@ -626,19 +597,19 @@ namespace Cosmos.System.FileSystem.FAT
aSize = BytesPerCluster;
}
byte[] xData;
Read(aCluster, out xData);
Read(aCluster, out var xData);
Array.Copy(aData, 0, xData, aOffset, aData.Length);
if (mFatType == FatTypeEnum.Fat32)
if (FatKind == FatKind.Fat32)
{
long xSector = DataSector + (aCluster - RootCluster) * SectorsPerCluster;
long xSector = FirstDataSector + (aCluster - RootCluster) * SectorsPerCluster;
Device.WriteBlock((ulong)xSector, SectorsPerCluster, xData);
}
else
{
Device.WriteBlock((ulong)aCluster, RootSectorCount, xData);
Device.WriteBlock((ulong)aCluster, RootSector, xData);
}
}
@ -648,16 +619,15 @@ namespace Cosmos.System.FileSystem.FAT
global::System.Console.WriteLine("Bytes per Cluster = " + BytesPerCluster);
global::System.Console.WriteLine("Bytes per Sector = " + BytesPerSector);
global::System.Console.WriteLine("Cluster Count = " + ClusterCount);
global::System.Console.WriteLine("Data Sector = " + DataSector);
global::System.Console.WriteLine("First Data Sector = " + FirstDataSector);
global::System.Console.WriteLine("Data Sector Count = " + DataSectorCount);
global::System.Console.WriteLine("FAT Sector Count = " + FatSectorCount);
global::System.Console.WriteLine("FAT Type = " + (uint)mFatType);
global::System.Console.WriteLine("Number of FATS = " + NumberOfFATs);
global::System.Console.WriteLine("FAT Kind = " + (uint)FatKind);
global::System.Console.WriteLine("Number of FATs = " + FatCount);
global::System.Console.WriteLine("Reserved Sector Count = " + ReservedSectorCount);
global::System.Console.WriteLine("Root Cluster = " + RootCluster);
global::System.Console.WriteLine("Root Entry Count = " + RootEntryCount);
global::System.Console.WriteLine("Root Sector = " + RootSector);
global::System.Console.WriteLine("Root Sector Count = " + RootSectorCount);
global::System.Console.WriteLine("Root Entry Count = " + BiosParameterBlock.GetValue(Fields.RootEntryCount));
global::System.Console.WriteLine("Root Sector Count = " + RootDirectorySectorCount);
global::System.Console.WriteLine("Sectors per Cluster = " + SectorsPerCluster);
global::System.Console.WriteLine("Total Sector Count = " + TotalSectorCount);
@ -667,26 +637,24 @@ namespace Cosmos.System.FileSystem.FAT
Global.mFileSystemDebugger.SendInternal(BytesPerSector);
Global.mFileSystemDebugger.SendInternal("Cluster Count =");
Global.mFileSystemDebugger.SendInternal(ClusterCount);
Global.mFileSystemDebugger.SendInternal("Data Sector =");
Global.mFileSystemDebugger.SendInternal(DataSector);
Global.mFileSystemDebugger.SendInternal("First Data Sector =");
Global.mFileSystemDebugger.SendInternal(FirstDataSector);
Global.mFileSystemDebugger.SendInternal("Data Sector Count =");
Global.mFileSystemDebugger.SendInternal(DataSectorCount);
Global.mFileSystemDebugger.SendInternal("FAT Sector Count =");
Global.mFileSystemDebugger.SendInternal(FatSectorCount);
Global.mFileSystemDebugger.SendInternal("FAT Type =");
Global.mFileSystemDebugger.SendInternal((uint)mFatType);
Global.mFileSystemDebugger.SendInternal("Number of FATS =");
Global.mFileSystemDebugger.SendInternal(NumberOfFATs);
Global.mFileSystemDebugger.SendInternal((uint)FatKind);
Global.mFileSystemDebugger.SendInternal("Number of FATs =");
Global.mFileSystemDebugger.SendInternal(FatCount);
Global.mFileSystemDebugger.SendInternal("Reserved Sector Count =");
Global.mFileSystemDebugger.SendInternal(ReservedSectorCount);
Global.mFileSystemDebugger.SendInternal("Root Cluster =");
Global.mFileSystemDebugger.SendInternal(RootCluster);
Global.mFileSystemDebugger.SendInternal("Root Entry Count =");
Global.mFileSystemDebugger.SendInternal(RootEntryCount);
Global.mFileSystemDebugger.SendInternal("Root Sector =");
Global.mFileSystemDebugger.SendInternal(RootSector);
Global.mFileSystemDebugger.SendInternal(BiosParameterBlock.GetValue(Fields.RootEntryCount));
Global.mFileSystemDebugger.SendInternal("Root Sector Count =");
Global.mFileSystemDebugger.SendInternal(RootSectorCount);
Global.mFileSystemDebugger.SendInternal(RootDirectorySectorCount);
Global.mFileSystemDebugger.SendInternal("Sectors per Cluster =");
Global.mFileSystemDebugger.SendInternal(SectorsPerCluster);
Global.mFileSystemDebugger.SendInternal("Total Sector Count =");
@ -869,17 +837,6 @@ namespace Cosmos.System.FileSystem.FAT
}
}
private enum FatTypeEnum
{
Unknown,
Fat12,
Fat16,
Fat32
}
public override void Format(string aDriveFormat, bool aQuick)
{
var xRootDirectory = (FatDirectoryEntry)GetRootDirectory();

View file

@ -0,0 +1,54 @@
using System;
using Cosmos.HAL.BlockDevice;
namespace Cosmos.System.FileSystem.FAT
{
public class FatFileSystemFactory : FileSystemFactory
{
public override string Name => "FAT";
public override bool IsType(Partition aDevice)
{
if (aDevice == null)
{
throw new ArgumentNullException(nameof(aDevice));
}
var bootSector = ReadBootSector(aDevice);
var bpb = new BiosParameterBlock(bootSector);
return IsFatPartition(bpb);
}
/// <summary>
/// Initializes a new instance of the <see cref="FatFileSystem"/> class.
/// </summary>
/// <param name="aDevice">The partition.</param>
/// <param name="aRootPath">The root path.</param>
/// <exception cref="Exception">FAT signature not found.</exception>
public override FileSystem Create(Partition aDevice, string aRootPath, long aSize)
{
var bootSector = ReadBootSector(aDevice);
var bpb = new BiosParameterBlock(bootSector);
if (!IsFatPartition(bpb))
{
throw new InvalidOperationException("Partition file system is not FAT!");
}
return new FatFileSystem(bpb, aDevice, aRootPath, aSize);
}
private byte[] ReadBootSector(Partition partition)
{
var bootSector = partition.NewBlockArray(1);
partition.ReadBlock(0, 1, bootSector);
return bootSector;
}
private bool IsFatPartition(BiosParameterBlock bpb) =>
bpb.GetValue(BiosParameterBlock.Signature) == 0xAA55;
}
}

View file

@ -0,0 +1,10 @@
namespace Cosmos.System.FileSystem.FAT
{
internal enum FatKind
{
Unkown,
Fat12,
Fat16,
Fat32
}
}

View file

@ -0,0 +1,15 @@
namespace Cosmos.System.FileSystem.FAT
{
public enum FatMediaKind
{
Removable = 0xF0,
Fixed = 0xF8,
Floppy1 = 0xF9,
Floppy2 = 0xFA,
Floppy3 = 0xFB,
Floppy4 = 0xFC,
Floppy5 = 0xFD,
Floppy6 = 0xFE,
Floppy7 = 0xFF
}
}

View file

@ -31,12 +31,7 @@ namespace Cosmos.System.FileSystem.FAT
public FatStream(FatDirectoryEntry aEntry)
{
if (aEntry == null)
{
throw new ArgumentNullException(nameof(aEntry));
}
mDirectoryEntry = aEntry;
mDirectoryEntry = aEntry ?? throw new ArgumentNullException(nameof(aEntry));
mFS = aEntry.GetFileSystem();
mFatTable = aEntry.GetFatTable();
mSize = aEntry.mSize;
@ -47,29 +42,11 @@ namespace Cosmos.System.FileSystem.FAT
}
}
public override bool CanSeek
{
get
{
return true;
}
}
public override bool CanSeek => true;
public override bool CanRead
{
get
{
return true;
}
}
public override bool CanRead => true;
public override bool CanWrite
{
get
{
return true;
}
}
public override bool CanWrite => true;
public sealed override long Length
{
@ -78,7 +55,7 @@ namespace Cosmos.System.FileSystem.FAT
Global.mFileSystemDebugger.SendInternal("-- FatStream.get_Length --");
Global.mFileSystemDebugger.SendInternal("Length =");
Global.mFileSystemDebugger.SendInternal(mSize);
return (long)mSize;
return mSize;
}
}
@ -89,7 +66,7 @@ namespace Cosmos.System.FileSystem.FAT
Global.mFileSystemDebugger.SendInternal("-- FatStream.get_Position --");
Global.mFileSystemDebugger.SendInternal("Position =");
Global.mFileSystemDebugger.SendInternal(mPosition);
return (long)mPosition;
return mPosition;
}
set
{

View file

@ -1,34 +0,0 @@
using System;
using Cosmos.HAL.BlockDevice;
using Cosmos.System.FileSystem.FAT;
namespace Cosmos.System.FileSystem
{
public class FatFileSystemFactory : FileSystemFactory
{
public override string Name => "FAT";
public override bool IsType(Partition aDevice)
{
if (aDevice == null)
{
throw new ArgumentNullException(nameof(aDevice));
}
var xBPB = aDevice.NewBlockArray(1);
aDevice.ReadBlock(0UL, 1U, xBPB);
var xSig = BitConverter.ToUInt16(xBPB, 510);
return xSig == 0xAA55;
}
/// <summary>
/// Initializes a new instance of the <see cref="FatFileSystem"/> class.
/// </summary>
/// <param name="aDevice">The partition.</param>
/// <param name="aRootPath">The root path.</param>
/// <exception cref="Exception">FAT signature not found.</exception>
public override FileSystem Create(Partition aDevice, string aRootPath, long aSize) => new FatFileSystem(aDevice, aRootPath, aSize);
}
}

View file

@ -1,8 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using Cosmos.HAL.BlockDevice;
using Cosmos.System.FileSystem.FAT;
using Cosmos.System.FileSystem.Listing;
namespace Cosmos.System.FileSystem
@ -11,8 +10,8 @@ namespace Cosmos.System.FileSystem
{
protected FileSystem(Partition aDevice, string aRootPath, long aSize)
{
Device = aDevice;
RootPath = aRootPath;
Device = aDevice ?? throw new ArgumentNullException(nameof(aDevice));
RootPath = aRootPath ?? throw new ArgumentNullException(nameof(aRootPath));
Size = aSize;
}

View file

@ -1,4 +1,6 @@
using Cosmos.HAL.BlockDevice;
using System;
using Cosmos.HAL.BlockDevice;
namespace Cosmos.System.FileSystem
{
@ -15,6 +17,7 @@ namespace Cosmos.System.FileSystem
/// <param name="aDevice">The partition.</param>
/// <returns>Returns true if the file system can handle the partition, false otherwise.</returns>
public abstract bool IsType(Partition aDevice);
/// <summary>
/// Creates a new <see cref="FileSystem"/> object for the given partition, root path, and size.
/// </summary>
@ -23,5 +26,7 @@ namespace Cosmos.System.FileSystem
/// <param name="aSize">The size, in MB.</param>
/// <returns></returns>
public abstract FileSystem Create(Partition aDevice, string aRootPath, long aSize);
public virtual void Format(Partition partition) => throw new NotImplementedException();
}
}