XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESystem

【Rust】XFE系统,基于Rust和汇编

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Runtime.InteropServices;
using XFESystem.Core;

namespace XFESystem.NativeRuntime.Application;

internal sealed unsafe class NativeWorkspaceDevice : IWorkspaceBlockDevice
{
    [DllImport("xfe_pal", EntryPoint="xfe_usb_storage_info")] internal static extern ulong Info(uint field);
    [DllImport("xfe_pal", EntryPoint="xfe_usb_storage_read")] private static extern int ReadNative(ulong lba,uint count,byte* data);
    [DllImport("xfe_pal", EntryPoint="xfe_usb_storage_write")] private static extern int WriteNative(ulong lba,uint count,byte* data);
    [DllImport("xfe_pal", EntryPoint="xfe_usb_storage_flush")] private static extern int FlushNative();
    [DllImport("xfe_pal", EntryPoint="xfe_usb_storage_allow_workspace")] private static extern int AllowNative(ulong lba,uint count);
    public ulong SectorCount => Info(3);
    public void Read(ulong lba,Span<byte> destination)
    {
        if(destination.Length%512!=0)throw new IOException("USB read must use whole sectors.");
        while(!destination.IsEmpty) { int count=Math.Min(destination.Length,65536); fixed(byte* data=destination)if(ReadNative(lba,(uint)count/512,data)!=1)throw new IOException("USB sector read failed."); lba+=(uint)count/512;destination=destination[count..]; }
    }
    public void Write(ulong lba,ReadOnlySpan<byte> source)
    {
        if(source.Length%512!=0)throw new IOException("USB write must use whole sectors.");
        while(!source.IsEmpty) { int count=Math.Min(source.Length,65536); fixed(byte* data=source)if(WriteNative(lba,(uint)count/512,data)!=1)throw new IOException("USB workspace write failed; data was not reported saved."); lba+=(uint)count/512;source=source[count..]; }
    }
    public void Flush() { if(FlushNative()!=1)throw new IOException("USB cache synchronization failed."); }
    public void AllowWorkspace(ulong lba,uint sectors) { if(AllowNative(lba,sectors)!=1)throw new IOException("USB workspace write extent was refused."); }
}

internal static class NativeWorkspace
{
    public static IWorkspaceBinaryStorage Open()
    {
        long end=NativePlatform.Milliseconds()+20000;
        while(NativeWorkspaceDevice.Info(1)==1&&NativePlatform.Milliseconds()<end)Thread.Sleep(10);
        if(NativeWorkspaceDevice.Info(2)!=1)
        {
            NativePlatform.Write("XFE_WORKSPACE|Mode|RAM|Persistent|0|Reason|NoUniqueBootUsbStorage\n");
            return new MemoryWorkspace(false);
        }
        var device=new NativeWorkspaceDevice();var fat=new ReadOnlyFat32Volume(device,NativeWorkspaceDevice.Info(5),NativeWorkspaceDevice.Info(6));
        var extent=fat.ContiguousWorkspace();var journal=new UsbWorkspaceJournal(device,extent.Lba);
        var workspace=new PersistentUsbWorkspace(journal,fat);
        NativePlatform.Write("XFE_WORKSPACE|Mode|USB|Persistent|1|Generation|"+workspace.Generation+"|Start|"+extent.Lba+"|Sectors|"+extent.Sectors+"\n");
        return workspace;
    }
}