mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-27 05:52:11 +00:00
data structs
This commit is contained in:
parent
3d3f032d79
commit
03c9caf688
11 changed files with 478 additions and 255 deletions
82
source/Cosmos.System2/FileSystem/FAT/BiosParameterBlock.cs
Normal file
82
source/Cosmos.System2/FileSystem/FAT/BiosParameterBlock.cs
Normal 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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
147
source/Cosmos.System2/FileSystem/FAT/DataStructures.cs
Normal file
147
source/Cosmos.System2/FileSystem/FAT/DataStructures.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
source/Cosmos.System2/FileSystem/FAT/Fat32ExtendedFlags.cs
Normal file
11
source/Cosmos.System2/FileSystem/FAT/Fat32ExtendedFlags.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Cosmos.System.FileSystem.FAT
|
||||||
|
{
|
||||||
|
[Flags]
|
||||||
|
internal enum Fat32ExtendedFlags
|
||||||
|
{
|
||||||
|
ActiveFatMask = 0x000F,
|
||||||
|
Mirrored = 0x0080
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,8 @@ using Cosmos.Common.Extensions;
|
||||||
using Cosmos.HAL.BlockDevice;
|
using Cosmos.HAL.BlockDevice;
|
||||||
using Cosmos.System.FileSystem.FAT.Listing;
|
using Cosmos.System.FileSystem.FAT.Listing;
|
||||||
using Cosmos.System.FileSystem.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
|
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>
|
/// <param name="aFatSector">The first sector of the FAT table.</param>
|
||||||
public Fat(FatFileSystem aFileSystem, ulong aFatSector)
|
public Fat(FatFileSystem aFileSystem, ulong aFatSector)
|
||||||
{
|
{
|
||||||
if (aFileSystem == null)
|
mFileSystem = aFileSystem ?? throw new ArgumentNullException(nameof(aFileSystem));
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(aFileSystem));
|
|
||||||
}
|
|
||||||
|
|
||||||
mFileSystem = aFileSystem;
|
|
||||||
mFatSector = aFatSector;
|
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>
|
/// <exception cref="NotSupportedException">Can not get the FAT entry size for an unknown FAT type.</exception>
|
||||||
private uint GetFatEntrySizeInBytes()
|
private uint GetFatEntrySizeInBytes()
|
||||||
{
|
{
|
||||||
switch (mFileSystem.mFatType)
|
switch (mFileSystem.FatKind)
|
||||||
{
|
{
|
||||||
case FatTypeEnum.Fat32:
|
case FatKind.Fat32:
|
||||||
return 4;
|
return 4;
|
||||||
|
|
||||||
case FatTypeEnum.Fat16:
|
case FatKind.Fat16:
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
case FatTypeEnum.Fat12:
|
case FatKind.Fat12:
|
||||||
// TODO:
|
// TODO:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -72,9 +69,8 @@ namespace Cosmos.System.FileSystem.FAT
|
||||||
Global.mFileSystemDebugger.SendInternal("aDataSize =");
|
Global.mFileSystemDebugger.SendInternal("aDataSize =");
|
||||||
Global.mFileSystemDebugger.SendInternal(aDataSize);
|
Global.mFileSystemDebugger.SendInternal(aDataSize);
|
||||||
|
|
||||||
var xReturn = new uint[0];
|
var xReturn = Array.Empty<uint>();
|
||||||
uint xCurrentEntry = aFirstEntry;
|
uint xCurrentEntry = aFirstEntry;
|
||||||
uint xValue;
|
|
||||||
|
|
||||||
long xEntriesRequired = aDataSize / mFileSystem.BytesPerCluster;
|
long xEntriesRequired = aDataSize / mFileSystem.BytesPerCluster;
|
||||||
if (aDataSize % mFileSystem.BytesPerCluster != 0)
|
if (aDataSize % mFileSystem.BytesPerCluster != 0)
|
||||||
|
|
@ -82,7 +78,7 @@ namespace Cosmos.System.FileSystem.FAT
|
||||||
xEntriesRequired++;
|
xEntriesRequired++;
|
||||||
}
|
}
|
||||||
|
|
||||||
GetFatEntry(xCurrentEntry, out xValue);
|
GetFatEntry(xCurrentEntry, out var xValue);
|
||||||
Array.Resize(ref xReturn, xReturn.Length + 1);
|
Array.Resize(ref xReturn, xReturn.Length + 1);
|
||||||
xReturn[xReturn.Length - 1] = xCurrentEntry;
|
xReturn[xReturn.Length - 1] = xCurrentEntry;
|
||||||
|
|
||||||
|
|
@ -145,8 +141,7 @@ namespace Cosmos.System.FileSystem.FAT
|
||||||
uint xTotalEntries = mFileSystem.FatSectorCount * mFileSystem.BytesPerSector / GetFatEntrySizeInBytes();
|
uint xTotalEntries = mFileSystem.FatSectorCount * mFileSystem.BytesPerSector / GetFatEntrySizeInBytes();
|
||||||
for (uint i = mFileSystem.RootCluster; i < xTotalEntries; i++)
|
for (uint i = mFileSystem.RootCluster; i < xTotalEntries; i++)
|
||||||
{
|
{
|
||||||
uint xEntryValue;
|
GetFatEntry(i, out var xEntryValue);
|
||||||
GetFatEntry(i, out xEntryValue);
|
|
||||||
if (!FatEntryIsEof(xEntryValue))
|
if (!FatEntryIsEof(xEntryValue))
|
||||||
{
|
{
|
||||||
Global.mFileSystemDebugger.SendInternal("i =");
|
Global.mFileSystemDebugger.SendInternal("i =");
|
||||||
|
|
@ -172,17 +167,15 @@ namespace Cosmos.System.FileSystem.FAT
|
||||||
uint xEntrySize = GetFatEntrySizeInBytes();
|
uint xEntrySize = GetFatEntrySizeInBytes();
|
||||||
ulong xEntryOffset = aEntryNumber * xEntrySize;
|
ulong xEntryOffset = aEntryNumber * xEntrySize;
|
||||||
|
|
||||||
|
switch (mFileSystem.FatKind)
|
||||||
|
|
||||||
switch (mFileSystem.mFatType)
|
|
||||||
{
|
{
|
||||||
case FatTypeEnum.Fat12:
|
case FatKind.Fat12:
|
||||||
aData.SetUInt16(xEntryOffset, (ushort)aValue);
|
aData.SetUInt16(xEntryOffset, (ushort)aValue);
|
||||||
break;
|
break;
|
||||||
case FatTypeEnum.Fat16:
|
case FatKind.Fat16:
|
||||||
aData.SetUInt16(xEntryOffset, (ushort)aValue);
|
aData.SetUInt16(xEntryOffset, (ushort)aValue);
|
||||||
break;
|
break;
|
||||||
case FatTypeEnum.Fat32:
|
case FatKind.Fat32:
|
||||||
aData.SetUInt32(xEntryOffset, (uint)aValue);
|
aData.SetUInt32(xEntryOffset, (uint)aValue);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -195,9 +188,9 @@ namespace Cosmos.System.FileSystem.FAT
|
||||||
uint xEntrySize = GetFatEntrySizeInBytes();
|
uint xEntrySize = GetFatEntrySizeInBytes();
|
||||||
ulong xEntryOffset = aEntryNumber * xEntrySize;
|
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
|
// 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
|
// 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.
|
// 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
|
aValue = xResult >> 4; // Odd
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FatTypeEnum.Fat16:
|
case FatKind.Fat16:
|
||||||
aValue = BitConverter.ToUInt16(aData, (int)xEntryOffset);
|
aValue = BitConverter.ToUInt16(aData, (int)xEntryOffset);
|
||||||
break;
|
break;
|
||||||
case FatTypeEnum.Fat32:
|
case FatKind.Fat32:
|
||||||
aValue = BitConverter.ToUInt32(aData, (int)xEntryOffset) & 0x0FFFFFFF;
|
aValue = BitConverter.ToUInt32(aData, (int)xEntryOffset) & 0x0FFFFFFF;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -232,8 +225,7 @@ namespace Cosmos.System.FileSystem.FAT
|
||||||
Global.mFileSystemDebugger.SendInternal($"RootCluster is {mFileSystem.RootCluster}");
|
Global.mFileSystemDebugger.SendInternal($"RootCluster is {mFileSystem.RootCluster}");
|
||||||
Global.mFileSystemDebugger.SendInternal("Clearing all Fat Table");
|
Global.mFileSystemDebugger.SendInternal("Clearing all Fat Table");
|
||||||
|
|
||||||
byte[] xFatTableFistSector;
|
ReadFatSector(0, out var xFatTableFistSector);
|
||||||
ReadFatSector(0, out xFatTableFistSector);
|
|
||||||
|
|
||||||
/* Change 3rd entry (RootDirectory) to be EOC */
|
/* Change 3rd entry (RootDirectory) to be EOC */
|
||||||
SetFatEntry(xFatTableFistSector, 2, FatEntryEofValue());
|
SetFatEntry(xFatTableFistSector, 2, FatEntryEofValue());
|
||||||
|
|
@ -312,9 +304,9 @@ namespace Cosmos.System.FileSystem.FAT
|
||||||
|
|
||||||
ReadFatSector(xSector, out xData);
|
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
|
// 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
|
// 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.
|
// we want the high 12-bits of the 16-bits we fetch.
|
||||||
|
|
@ -329,11 +321,11 @@ namespace Cosmos.System.FileSystem.FAT
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FatTypeEnum.Fat16:
|
case FatKind.Fat16:
|
||||||
aValue = BitConverter.ToUInt16(xData, (int)xEntryOffset);
|
aValue = BitConverter.ToUInt16(xData, (int)xEntryOffset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FatTypeEnum.Fat32:
|
case FatKind.Fat32:
|
||||||
aValue = BitConverter.ToUInt32(xData, (int)xEntryOffset) & 0x0FFFFFFF;
|
aValue = BitConverter.ToUInt32(xData, (int)xEntryOffset) & 0x0FFFFFFF;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -364,20 +356,17 @@ namespace Cosmos.System.FileSystem.FAT
|
||||||
byte[] xData;
|
byte[] xData;
|
||||||
ReadFatSector(xSector, out xData);
|
ReadFatSector(xSector, out xData);
|
||||||
|
|
||||||
switch (mFileSystem.mFatType)
|
switch (mFileSystem.FatKind)
|
||||||
{
|
{
|
||||||
case FatTypeEnum.Fat12:
|
case FatKind.Fat12:
|
||||||
xData.SetUInt16(xEntryOffset, (ushort)aValue);
|
xData.SetUInt16(xEntryOffset, (ushort)aValue);
|
||||||
break;
|
break;
|
||||||
|
case FatKind.Fat16:
|
||||||
case FatTypeEnum.Fat16:
|
|
||||||
xData.SetUInt16(xEntryOffset, (ushort)aValue);
|
xData.SetUInt16(xEntryOffset, (ushort)aValue);
|
||||||
break;
|
break;
|
||||||
|
case FatKind.Fat32:
|
||||||
case FatTypeEnum.Fat32:
|
|
||||||
xData.SetUInt32(xEntryOffset, (uint)aValue);
|
xData.SetUInt32(xEntryOffset, (uint)aValue);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new NotSupportedException("Unknown FAT type.");
|
throw new NotSupportedException("Unknown FAT type.");
|
||||||
}
|
}
|
||||||
|
|
@ -393,188 +382,170 @@ namespace Cosmos.System.FileSystem.FAT
|
||||||
/// <exception cref="Exception">Unknown file system type.</exception>
|
/// <exception cref="Exception">Unknown file system type.</exception>
|
||||||
private bool FatEntryIsEof(ulong aValue)
|
private bool FatEntryIsEof(ulong aValue)
|
||||||
{
|
{
|
||||||
switch (mFileSystem.mFatType)
|
switch (mFileSystem.FatKind)
|
||||||
{
|
{
|
||||||
case FatTypeEnum.Fat12:
|
case FatKind.Fat12:
|
||||||
return aValue >= 0xFF8;
|
return aValue >= 0xFF8;
|
||||||
|
case FatKind.Fat16:
|
||||||
case FatTypeEnum.Fat16:
|
|
||||||
return aValue >= 0xFFF8;
|
return aValue >= 0xFFF8;
|
||||||
|
case FatKind.Fat32:
|
||||||
case FatTypeEnum.Fat32:
|
|
||||||
return aValue >= 0xFFFFFF8;
|
return aValue >= 0xFFFFFF8;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new Exception("Unknown file system type.");
|
throw new Exception("Unknown file system type.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The the EOF value for a specific FAT type.
|
/// The EOF value for a specific FAT type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The EOF value.</returns>
|
/// <returns>The EOF value.</returns>
|
||||||
/// <exception cref="Exception">Unknown file system type.</exception>
|
/// <exception cref="Exception">Unknown file system type.</exception>
|
||||||
private ulong FatEntryEofValue()
|
private ulong FatEntryEofValue()
|
||||||
{
|
{
|
||||||
switch (mFileSystem.mFatType)
|
switch (mFileSystem.FatKind)
|
||||||
{
|
{
|
||||||
case FatTypeEnum.Fat12:
|
case FatKind.Fat12:
|
||||||
return 0x0FFF;
|
return 0x0FFF;
|
||||||
|
case FatKind.Fat16:
|
||||||
case FatTypeEnum.Fat16:
|
|
||||||
return 0xFFFF;
|
return 0xFFFF;
|
||||||
|
case FatKind.Fat32:
|
||||||
case FatTypeEnum.Fat32:
|
|
||||||
return 0x0FFFFFFF;
|
return 0x0FFFFFFF;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new Exception("Unknown file system type.");
|
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;
|
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>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="FatFileSystem"/> class.
|
/// Initializes a new instance of the <see cref="FatFileSystem"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="aDevice">The partition.</param>
|
/// <param name="aDevice">The partition.</param>
|
||||||
/// <param name="aRootPath">The root path.</param>
|
/// <param name="aRootPath">The root path.</param>
|
||||||
/// <exception cref="Exception">FAT signature not found.</exception>
|
/// <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)
|
: base(aDevice, aRootPath, aSize)
|
||||||
{
|
{
|
||||||
if (aDevice == null)
|
BiosParameterBlock = bpb;
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(aDevice));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (String.IsNullOrEmpty(aRootPath))
|
BytesPerSector = BiosParameterBlock.GetValue(Fields.BytesPerSector);
|
||||||
{
|
SectorsPerCluster = BiosParameterBlock.GetValue(Fields.SectorsPerCluster);
|
||||||
throw new ArgumentException("Argument is null or empty", nameof(aRootPath));
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
FatCount = BiosParameterBlock.GetValue(Fields.FatCount);
|
||||||
if (xSig != 0xAA55)
|
|
||||||
{
|
|
||||||
throw new Exception("FAT signature not found.");
|
|
||||||
}
|
|
||||||
|
|
||||||
BytesPerSector = BitConverter.ToUInt16(xBPB, 11);
|
var rootEntryCount = BiosParameterBlock.GetValue(Fields.RootEntryCount);
|
||||||
SectorsPerCluster = xBPB[13];
|
|
||||||
BytesPerCluster = BytesPerSector * SectorsPerCluster;
|
|
||||||
ReservedSectorCount = BitConverter.ToUInt16(xBPB, 14);
|
|
||||||
NumberOfFATs = xBPB[16];
|
|
||||||
RootEntryCount = BitConverter.ToUInt16(xBPB, 17);
|
|
||||||
|
|
||||||
TotalSectorCount = BitConverter.ToUInt16(xBPB, 19);
|
// 1.
|
||||||
if (TotalSectorCount == 0)
|
RootDirectorySectorCount = (uint)(((rootEntryCount * 32) + (BytesPerSector - 1)) / BytesPerSector);
|
||||||
{
|
|
||||||
TotalSectorCount = BitConverter.ToUInt32(xBPB, 32);
|
// 2.
|
||||||
}
|
FatSectorCount = BiosParameterBlock.GetValue(Fields.FatSectorCount16);
|
||||||
|
|
||||||
// FATSz
|
|
||||||
FatSectorCount = BitConverter.ToUInt16(xBPB, 22);
|
|
||||||
if (FatSectorCount == 0)
|
if (FatSectorCount == 0)
|
||||||
{
|
{
|
||||||
FatSectorCount = BitConverter.ToUInt32(xBPB, 36);
|
FatSectorCount = BiosParameterBlock.GetValue(Fat32.FatSectorCount32);
|
||||||
}
|
}
|
||||||
|
|
||||||
DataSectorCount = TotalSectorCount -
|
TotalSectorCount = BiosParameterBlock.GetValue(Fields.TotalSectorCount16);
|
||||||
(ReservedSectorCount + NumberOfFATs * FatSectorCount + ReservedSectorCount);
|
|
||||||
|
|
||||||
// Computation rounds down.
|
if (TotalSectorCount == 0)
|
||||||
|
{
|
||||||
|
TotalSectorCount = BiosParameterBlock.GetValue(Fields.TotalSectorCount32);
|
||||||
|
}
|
||||||
|
|
||||||
|
FirstDataSector = ReservedSectorCount + (FatCount * FatSectorCount) + RootDirectorySectorCount;
|
||||||
|
DataSectorCount = TotalSectorCount - FirstDataSector;
|
||||||
|
|
||||||
|
// 3.
|
||||||
ClusterCount = DataSectorCount / SectorsPerCluster;
|
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)
|
if (ClusterCount < 4085)
|
||||||
{
|
{
|
||||||
mFatType = FatTypeEnum.Fat12;
|
FatKind = FatKind.Fat12;
|
||||||
}
|
}
|
||||||
else if (ClusterCount < 65525)
|
else if (ClusterCount < 65525)
|
||||||
{
|
{
|
||||||
mFatType = FatTypeEnum.Fat16;
|
FatKind = FatKind.Fat16;
|
||||||
}
|
}
|
||||||
else
|
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
|
else
|
||||||
{
|
{
|
||||||
RootSector = ReservedSectorCount + NumberOfFATs * FatSectorCount;
|
RootSector = ReservedSectorCount + FatCount * FatSectorCount;
|
||||||
RootSectorCount = (RootEntryCount * 32 + (BytesPerSector - 1)) / BytesPerSector;
|
|
||||||
}
|
}
|
||||||
DataSector = ReservedSectorCount + NumberOfFATs * FatSectorCount + RootSectorCount;
|
|
||||||
|
|
||||||
mFats = new Fat[NumberOfFATs];
|
mFats = new Fat[FatCount];
|
||||||
for (ulong i = 0; i < NumberOfFATs; i++)
|
for (ulong i = 0; i < FatCount; i++)
|
||||||
{
|
{
|
||||||
mFats[i] = new Fat(this, (ReservedSectorCount + i * FatSectorCount));
|
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)
|
internal Fat GetFat(int aTableNumber)
|
||||||
{
|
{
|
||||||
if (mFats.Length > aTableNumber)
|
if (mFats.Length > aTableNumber)
|
||||||
|
|
@ -582,7 +553,7 @@ namespace Cosmos.System.FileSystem.FAT
|
||||||
return mFats[aTableNumber];
|
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()
|
internal byte[] NewBlockArray()
|
||||||
|
|
@ -599,16 +570,16 @@ namespace Cosmos.System.FileSystem.FAT
|
||||||
aSize = BytesPerCluster;
|
aSize = BytesPerCluster;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mFatType == FatTypeEnum.Fat32)
|
if (FatKind == FatKind.Fat32)
|
||||||
{
|
{
|
||||||
aData = NewBlockArray();
|
aData = NewBlockArray();
|
||||||
long xSector = DataSector + (aCluster - RootCluster) * SectorsPerCluster;
|
long xSector = FirstDataSector + (aCluster - RootCluster) * SectorsPerCluster;
|
||||||
Device.ReadBlock((ulong)xSector, SectorsPerCluster, aData);
|
Device.ReadBlock((ulong)xSector, SectorsPerCluster, aData);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
aData = Device.NewBlockArray(1);
|
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;
|
aSize = BytesPerCluster;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] xData;
|
Read(aCluster, out var xData);
|
||||||
|
|
||||||
Read(aCluster, out xData);
|
|
||||||
Array.Copy(aData, 0, xData, aOffset, aData.Length);
|
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);
|
Device.WriteBlock((ulong)xSector, SectorsPerCluster, xData);
|
||||||
}
|
}
|
||||||
else
|
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 Cluster = " + BytesPerCluster);
|
||||||
global::System.Console.WriteLine("Bytes per Sector = " + BytesPerSector);
|
global::System.Console.WriteLine("Bytes per Sector = " + BytesPerSector);
|
||||||
global::System.Console.WriteLine("Cluster Count = " + ClusterCount);
|
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("Data Sector Count = " + DataSectorCount);
|
||||||
global::System.Console.WriteLine("FAT Sector Count = " + FatSectorCount);
|
global::System.Console.WriteLine("FAT Sector Count = " + FatSectorCount);
|
||||||
global::System.Console.WriteLine("FAT Type = " + (uint)mFatType);
|
global::System.Console.WriteLine("FAT Kind = " + (uint)FatKind);
|
||||||
global::System.Console.WriteLine("Number of FATS = " + NumberOfFATs);
|
global::System.Console.WriteLine("Number of FATs = " + FatCount);
|
||||||
global::System.Console.WriteLine("Reserved Sector Count = " + ReservedSectorCount);
|
global::System.Console.WriteLine("Reserved Sector Count = " + ReservedSectorCount);
|
||||||
global::System.Console.WriteLine("Root Cluster = " + RootCluster);
|
global::System.Console.WriteLine("Root Cluster = " + RootCluster);
|
||||||
global::System.Console.WriteLine("Root Entry Count = " + RootEntryCount);
|
global::System.Console.WriteLine("Root Entry Count = " + BiosParameterBlock.GetValue(Fields.RootEntryCount));
|
||||||
global::System.Console.WriteLine("Root Sector = " + RootSector);
|
global::System.Console.WriteLine("Root Sector Count = " + RootDirectorySectorCount);
|
||||||
global::System.Console.WriteLine("Root Sector Count = " + RootSectorCount);
|
|
||||||
global::System.Console.WriteLine("Sectors per Cluster = " + SectorsPerCluster);
|
global::System.Console.WriteLine("Sectors per Cluster = " + SectorsPerCluster);
|
||||||
global::System.Console.WriteLine("Total Sector Count = " + TotalSectorCount);
|
global::System.Console.WriteLine("Total Sector Count = " + TotalSectorCount);
|
||||||
|
|
||||||
|
|
@ -667,26 +637,24 @@ namespace Cosmos.System.FileSystem.FAT
|
||||||
Global.mFileSystemDebugger.SendInternal(BytesPerSector);
|
Global.mFileSystemDebugger.SendInternal(BytesPerSector);
|
||||||
Global.mFileSystemDebugger.SendInternal("Cluster Count =");
|
Global.mFileSystemDebugger.SendInternal("Cluster Count =");
|
||||||
Global.mFileSystemDebugger.SendInternal(ClusterCount);
|
Global.mFileSystemDebugger.SendInternal(ClusterCount);
|
||||||
Global.mFileSystemDebugger.SendInternal("Data Sector =");
|
Global.mFileSystemDebugger.SendInternal("First Data Sector =");
|
||||||
Global.mFileSystemDebugger.SendInternal(DataSector);
|
Global.mFileSystemDebugger.SendInternal(FirstDataSector);
|
||||||
Global.mFileSystemDebugger.SendInternal("Data Sector Count =");
|
Global.mFileSystemDebugger.SendInternal("Data Sector Count =");
|
||||||
Global.mFileSystemDebugger.SendInternal(DataSectorCount);
|
Global.mFileSystemDebugger.SendInternal(DataSectorCount);
|
||||||
Global.mFileSystemDebugger.SendInternal("FAT Sector Count =");
|
Global.mFileSystemDebugger.SendInternal("FAT Sector Count =");
|
||||||
Global.mFileSystemDebugger.SendInternal(FatSectorCount);
|
Global.mFileSystemDebugger.SendInternal(FatSectorCount);
|
||||||
Global.mFileSystemDebugger.SendInternal("FAT Type =");
|
Global.mFileSystemDebugger.SendInternal("FAT Type =");
|
||||||
Global.mFileSystemDebugger.SendInternal((uint)mFatType);
|
Global.mFileSystemDebugger.SendInternal((uint)FatKind);
|
||||||
Global.mFileSystemDebugger.SendInternal("Number of FATS =");
|
Global.mFileSystemDebugger.SendInternal("Number of FATs =");
|
||||||
Global.mFileSystemDebugger.SendInternal(NumberOfFATs);
|
Global.mFileSystemDebugger.SendInternal(FatCount);
|
||||||
Global.mFileSystemDebugger.SendInternal("Reserved Sector Count =");
|
Global.mFileSystemDebugger.SendInternal("Reserved Sector Count =");
|
||||||
Global.mFileSystemDebugger.SendInternal(ReservedSectorCount);
|
Global.mFileSystemDebugger.SendInternal(ReservedSectorCount);
|
||||||
Global.mFileSystemDebugger.SendInternal("Root Cluster =");
|
Global.mFileSystemDebugger.SendInternal("Root Cluster =");
|
||||||
Global.mFileSystemDebugger.SendInternal(RootCluster);
|
Global.mFileSystemDebugger.SendInternal(RootCluster);
|
||||||
Global.mFileSystemDebugger.SendInternal("Root Entry Count =");
|
Global.mFileSystemDebugger.SendInternal("Root Entry Count =");
|
||||||
Global.mFileSystemDebugger.SendInternal(RootEntryCount);
|
Global.mFileSystemDebugger.SendInternal(BiosParameterBlock.GetValue(Fields.RootEntryCount));
|
||||||
Global.mFileSystemDebugger.SendInternal("Root Sector =");
|
|
||||||
Global.mFileSystemDebugger.SendInternal(RootSector);
|
|
||||||
Global.mFileSystemDebugger.SendInternal("Root Sector Count =");
|
Global.mFileSystemDebugger.SendInternal("Root Sector Count =");
|
||||||
Global.mFileSystemDebugger.SendInternal(RootSectorCount);
|
Global.mFileSystemDebugger.SendInternal(RootDirectorySectorCount);
|
||||||
Global.mFileSystemDebugger.SendInternal("Sectors per Cluster =");
|
Global.mFileSystemDebugger.SendInternal("Sectors per Cluster =");
|
||||||
Global.mFileSystemDebugger.SendInternal(SectorsPerCluster);
|
Global.mFileSystemDebugger.SendInternal(SectorsPerCluster);
|
||||||
Global.mFileSystemDebugger.SendInternal("Total Sector Count =");
|
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)
|
public override void Format(string aDriveFormat, bool aQuick)
|
||||||
{
|
{
|
||||||
var xRootDirectory = (FatDirectoryEntry)GetRootDirectory();
|
var xRootDirectory = (FatDirectoryEntry)GetRootDirectory();
|
||||||
|
|
|
||||||
54
source/Cosmos.System2/FileSystem/FAT/FatFileSystemFactory.cs
Normal file
54
source/Cosmos.System2/FileSystem/FAT/FatFileSystemFactory.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
10
source/Cosmos.System2/FileSystem/FAT/FatKind.cs
Normal file
10
source/Cosmos.System2/FileSystem/FAT/FatKind.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
namespace Cosmos.System.FileSystem.FAT
|
||||||
|
{
|
||||||
|
internal enum FatKind
|
||||||
|
{
|
||||||
|
Unkown,
|
||||||
|
Fat12,
|
||||||
|
Fat16,
|
||||||
|
Fat32
|
||||||
|
}
|
||||||
|
}
|
||||||
15
source/Cosmos.System2/FileSystem/FAT/FatMediaKind.cs
Normal file
15
source/Cosmos.System2/FileSystem/FAT/FatMediaKind.cs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -31,12 +31,7 @@ namespace Cosmos.System.FileSystem.FAT
|
||||||
|
|
||||||
public FatStream(FatDirectoryEntry aEntry)
|
public FatStream(FatDirectoryEntry aEntry)
|
||||||
{
|
{
|
||||||
if (aEntry == null)
|
mDirectoryEntry = aEntry ?? throw new ArgumentNullException(nameof(aEntry));
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(aEntry));
|
|
||||||
}
|
|
||||||
|
|
||||||
mDirectoryEntry = aEntry;
|
|
||||||
mFS = aEntry.GetFileSystem();
|
mFS = aEntry.GetFileSystem();
|
||||||
mFatTable = aEntry.GetFatTable();
|
mFatTable = aEntry.GetFatTable();
|
||||||
mSize = aEntry.mSize;
|
mSize = aEntry.mSize;
|
||||||
|
|
@ -47,29 +42,11 @@ namespace Cosmos.System.FileSystem.FAT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool CanSeek
|
public override bool CanSeek => true;
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanRead
|
public override bool CanRead => true;
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanWrite
|
public override bool CanWrite => true;
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed override long Length
|
public sealed override long Length
|
||||||
{
|
{
|
||||||
|
|
@ -78,7 +55,7 @@ namespace Cosmos.System.FileSystem.FAT
|
||||||
Global.mFileSystemDebugger.SendInternal("-- FatStream.get_Length --");
|
Global.mFileSystemDebugger.SendInternal("-- FatStream.get_Length --");
|
||||||
Global.mFileSystemDebugger.SendInternal("Length =");
|
Global.mFileSystemDebugger.SendInternal("Length =");
|
||||||
Global.mFileSystemDebugger.SendInternal(mSize);
|
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("-- FatStream.get_Position --");
|
||||||
Global.mFileSystemDebugger.SendInternal("Position =");
|
Global.mFileSystemDebugger.SendInternal("Position =");
|
||||||
Global.mFileSystemDebugger.SendInternal(mPosition);
|
Global.mFileSystemDebugger.SendInternal(mPosition);
|
||||||
return (long)mPosition;
|
return mPosition;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using Cosmos.HAL.BlockDevice;
|
using Cosmos.HAL.BlockDevice;
|
||||||
using Cosmos.System.FileSystem.FAT;
|
|
||||||
using Cosmos.System.FileSystem.Listing;
|
using Cosmos.System.FileSystem.Listing;
|
||||||
|
|
||||||
namespace Cosmos.System.FileSystem
|
namespace Cosmos.System.FileSystem
|
||||||
|
|
@ -11,8 +10,8 @@ namespace Cosmos.System.FileSystem
|
||||||
{
|
{
|
||||||
protected FileSystem(Partition aDevice, string aRootPath, long aSize)
|
protected FileSystem(Partition aDevice, string aRootPath, long aSize)
|
||||||
{
|
{
|
||||||
Device = aDevice;
|
Device = aDevice ?? throw new ArgumentNullException(nameof(aDevice));
|
||||||
RootPath = aRootPath;
|
RootPath = aRootPath ?? throw new ArgumentNullException(nameof(aRootPath));
|
||||||
Size = aSize;
|
Size = aSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
using Cosmos.HAL.BlockDevice;
|
using System;
|
||||||
|
|
||||||
|
using Cosmos.HAL.BlockDevice;
|
||||||
|
|
||||||
namespace Cosmos.System.FileSystem
|
namespace Cosmos.System.FileSystem
|
||||||
{
|
{
|
||||||
|
|
@ -15,6 +17,7 @@ namespace Cosmos.System.FileSystem
|
||||||
/// <param name="aDevice">The partition.</param>
|
/// <param name="aDevice">The partition.</param>
|
||||||
/// <returns>Returns true if the file system can handle the partition, false otherwise.</returns>
|
/// <returns>Returns true if the file system can handle the partition, false otherwise.</returns>
|
||||||
public abstract bool IsType(Partition aDevice);
|
public abstract bool IsType(Partition aDevice);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new <see cref="FileSystem"/> object for the given partition, root path, and size.
|
/// Creates a new <see cref="FileSystem"/> object for the given partition, root path, and size.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -23,5 +26,7 @@ namespace Cosmos.System.FileSystem
|
||||||
/// <param name="aSize">The size, in MB.</param>
|
/// <param name="aSize">The size, in MB.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public abstract FileSystem Create(Partition aDevice, string aRootPath, long aSize);
|
public abstract FileSystem Create(Partition aDevice, string aRootPath, long aSize);
|
||||||
|
|
||||||
|
public virtual void Format(Partition partition) => throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue