mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-19 20:39:01 +00:00
271 lines
7.3 KiB
C#
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
|
|
Sector = blockdevice.ReadBlock(0);
|
|
//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 byte[] ReadBlock(ulong aBlock)
|
|
{
|
|
return blockDev.ReadBlock(aBlock + Start);
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|