mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-19 20:39:01 +00:00
153 lines
4.6 KiB
C#
153 lines
4.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using Cosmos.Sys.FileSystem;
|
|
|
|
namespace Cosmos.Sys.FileSystem.FAT32
|
|
{
|
|
public abstract class FileAllocationTable
|
|
{
|
|
public abstract uint GetFreeCluster();
|
|
public abstract uint GetNextCluster(uint CurrentCluster);
|
|
public abstract uint AddFreeCluster(uint LastSector);
|
|
|
|
|
|
public uint ClusterSize;
|
|
|
|
public abstract void Format();
|
|
}
|
|
public class FileAllocationTableFAT32 : FileAllocationTable
|
|
{
|
|
private FAT32 fat32;
|
|
private uint FirstSector;
|
|
private uint SecondSector;
|
|
private uint TotalClusters;
|
|
private Partition p;
|
|
public FileAllocationTableFAT32(FAT32 fat32, Partition p, uint firstsector, uint secondsector)
|
|
{
|
|
this.fat32 = fat32;
|
|
this.FirstSector = firstsector;
|
|
this.SecondSector = secondsector;
|
|
this.TotalClusters = (fat32.BootSector.TotalSectors32-fat32.BootSector.ReservedSectorCount)/ fat32.BootSector.SectorsPerCluster;
|
|
this.p = p;
|
|
this.ClusterSize = (uint)(fat32.BootSector.SectorsPerCluster * fat32.BootSector.BytesPerSec);
|
|
|
|
switch (fat32.BootSector.BytesPerSec/4)
|
|
{
|
|
case 128:
|
|
Shift = 7;
|
|
Mask = 0x7f;
|
|
break;
|
|
default:
|
|
throw new Exception("weird sector size");
|
|
}
|
|
}
|
|
|
|
|
|
private int Shift;
|
|
private uint Mask;
|
|
|
|
public override void Format()
|
|
{
|
|
byte[] b = new byte[fat32.BootSector.BytesPerSec];
|
|
for (int i = 0; i < fat32.BootSector.FATsz16; i++)
|
|
p.WriteBlock((uint)(FirstSector + i), b);
|
|
|
|
b[0] = fat32.BootSector.Media;
|
|
b[1] = 0xff;
|
|
b[2] = 0xff;
|
|
b[3] = 0xff;
|
|
|
|
Array.Copy(BitConverter.GetBytes((uint)0x0ffffff8), 0, b, 4, 4);
|
|
|
|
p.WriteBlock(FirstSector, b); // first 2 sectors are reserved
|
|
}
|
|
|
|
public uint ClusterFree = 0x0;
|
|
public uint ClusterReserved = 0x0;
|
|
public uint ClusterEOL = 0xffffff8;
|
|
public uint ClusterBAD = 0xffffff6;
|
|
|
|
|
|
public override uint AddFreeCluster(uint LastCluster)
|
|
{
|
|
uint newcluster = GetFreeCluster();
|
|
WriteClusterAllocation(newcluster, ClusterEOL);
|
|
WriteClusterAllocation(LastCluster, newcluster);
|
|
return newcluster;
|
|
}
|
|
|
|
public override uint GetFreeCluster()
|
|
{
|
|
uint start = fat32.FileSystemInfo32.Nxt_Free;
|
|
if (start == 0x0 || start == 0xffffffff)
|
|
start = 0x2;
|
|
|
|
for (uint i = 0; i < TotalClusters; i++)
|
|
{
|
|
uint actualcluster = (start + i - 2) % (TotalClusters) + 2;
|
|
if (ReadClusterAllocation(actualcluster) == 0x0)
|
|
{
|
|
fat32.FileSystemInfo32.Nxt_Free = actualcluster + 1;
|
|
return actualcluster;
|
|
}
|
|
}
|
|
|
|
throw new Exception("Disk full");
|
|
|
|
}
|
|
|
|
private unsafe uint ReadClusterAllocation(uint actualcluster)
|
|
{
|
|
uint index = actualcluster & Mask;
|
|
uint sector = FirstSector + actualcluster >> Shift;
|
|
|
|
byte[] data= GetSector(sector);
|
|
|
|
return BitConverter.ToUInt32(data,(int)(index<<2));
|
|
}
|
|
private unsafe void WriteClusterAllocation(uint actualcluster, uint value)
|
|
{
|
|
uint index = actualcluster & Mask;
|
|
uint sector = FirstSector + actualcluster >> Shift;
|
|
|
|
byte[] data = GetSector(sector);
|
|
byte[] b = BitConverter.GetBytes(value);
|
|
index <<= 2;
|
|
data[index++] = b[0];
|
|
data[index++] = b[1];
|
|
data[index++] = b[2];
|
|
data[index++] = b[3];
|
|
|
|
SetSector(sector, data);
|
|
}
|
|
|
|
byte[] CachedSector;
|
|
uint SectorNumber=0xffffffff;
|
|
|
|
|
|
public override uint GetNextCluster(uint CurrentCluster)
|
|
{
|
|
return ReadClusterAllocation(CurrentCluster);
|
|
}
|
|
|
|
private void SetSector(uint sector, byte[] data)
|
|
{
|
|
if (sector == SectorNumber)
|
|
CachedSector = data;
|
|
p.WriteBlock(sector, data);
|
|
}
|
|
private unsafe byte[] GetSector(uint Sector)
|
|
{
|
|
if (Sector != SectorNumber)
|
|
{
|
|
SectorNumber = Sector;
|
|
p.ReadBlock(Sector, CachedSector);
|
|
}
|
|
return CachedSector;
|
|
}
|
|
|
|
|
|
}
|
|
}
|