Cosmos/source/Cosmos.Kernel.FileSystems/MBR.cs

271 lines
7.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Cosmos.Hardware;
namespace Cosmos.FileSystem
{
public class MBR : PartitionManager
{
protected Disk blockdevice;
public static void Initialise()
{
for (int i = 0; i < Cosmos.Hardware.Device.Devices.Count; i++)
{
Device d = Cosmos.Hardware.Device.Devices[i];
if (d is Disk)
{
MBR mbr = new MBR(d as Disk);
if (mbr.IsValid())
Cosmos.Hardware.Device.Devices.Add(mbr);
}
}
}
public MBR(Disk bd)
{
this.blockdevice = bd;
Partition = new IBMPartitionInformation[4];
Partition[0] = new IBMPartitionInformation(this, 0);
Partition[1] = new IBMPartitionInformation(this, 1);
Partition[2] = new IBMPartitionInformation(this, 2);
Partition[3] = new IBMPartitionInformation(this, 3);
Refresh();
}
private byte[] Sector;
public byte[] Code
{
get
{
byte[] b = new byte[440];
Array.Copy(Sector, b, 440);
return b;
}
set
{
byte[] b;
if (value.Length != 440)
{
b = new byte[440];
Array.Copy(value, b, 0);
}
else
{
b = value;
}
Array.Copy(value, Sector, 0);
}
}
public uint DiskSignature
{
get
{
return BitConverter.ToUInt32(Sector, 440);
}
set
{
byte[] b = BitConverter.GetBytes(value);
Sector[440] = b[0];
Sector[441] = b[1];
Sector[442] = b[2];
Sector[443] = b[3];
}
}
public ushort Null
{
get
{
return BitConverter.ToUInt16(Sector, 444);
}
set
{
byte[] b = BitConverter.GetBytes(value);
Sector[444] = b[0];
Sector[445] = b[1];
}
}
public IBMPartitionInformation[] Partition;
public ushort MBRSignature
{
get
{
return BitConverter.ToUInt16(Sector,510);
}
}
public void Refresh()
{
// disable and remove any partitions we already added
blockdevice.ReadBlock(0, Sector);
//add partitons back to device list
}
public void Save()
{
Sector[510] = 0x55;
Sector[511] = 0xaa;
blockdevice.WriteBlock(0, Sector);
}
public bool IsValid()
{
return MBRSignature == 0x55aa;
}
public class IBMPartitionInformation
{
private MBR mbr;
private int offset;
public IBMPartitionInformation(MBR mbr, int index)
{
this.mbr=mbr;
this.offset=446+16*index;
}
public byte Status
{
get
{
return mbr.Sector[offset];
}
set
{
mbr.Sector[offset] = value;
}
}
public bool Bootable
{
get
{
return (Status & 0x80) == 0x80;
}
set
{
Status = (byte)((Status & 0x7f) | (value ? 0x80 : 0));
}
}
public byte PartitionType
{
get
{
return mbr.Sector[offset + 4];
}
set
{
mbr.Sector[offset + 4] = value;
}
}
public uint StartLBA
{
get
{
return BitConverter.ToUInt32(mbr.Sector,offset+8);
}
set
{
byte[] b = BitConverter.GetBytes(value);
mbr.Sector[offset + 8] = b[0];
mbr.Sector[offset + 9] = b[1];
mbr.Sector[offset + 10] = b[2];
mbr.Sector[offset + 11] = b[3];
}
}
public uint LengthLBA
{
get
{
return BitConverter.ToUInt32(mbr.Sector, offset + 12);
}
set
{
byte[] b = BitConverter.GetBytes(value);
mbr.Sector[offset + 12] = b[0];
mbr.Sector[offset + 13] = b[1];
mbr.Sector[offset + 14] = b[2];
mbr.Sector[offset + 15] = b[3];
}
}
public bool ValidPartition()
{
return (PartitionType > 0 && (Status == 0x00 || Status == 0x80));
}
public Partition GetPartitionDevice()
{
if (ValidPartition())
return new MBRPartition(this, mbr);
return null;
}
}
public class MBRPartition : Partition
{
private MBR Mbr;
private ulong Start, Length;
private BlockDevice blockDev;
public MBRPartition(IBMPartitionInformation info, MBR mbr)
{
Mbr = mbr;
Start = info.StartLBA;
Length = info.LengthLBA;
Identifier = info.PartitionType;
blockDev = mbr.blockdevice;
}
public override uint BlockSize
{
get { return blockDev.BlockSize; }
}
public override ulong BlockCount
{
get { return Length; }
}
public override void ReadBlock(ulong aBlock, byte[] aBuffer)
{
blockDev.ReadBlock(aBlock + Start, aBuffer);
}
public override void WriteBlock(ulong aBlock, byte[] aContents)
{
blockDev.WriteBlock(aBlock + Start, aContents);
}
public override string Name
{
get { return "MBR Partition [Type="+Identifier + "] in MBR " + blockDev.Name; }
}
}
public override string Name
{
get { throw new NotImplementedException(); }
}
}
public abstract class Disk : BlockDevice
{
}
public abstract class PartitionManager : Device
{
}
public abstract class Partition : BlockDevice
{
public object Identifier;
}
}