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

XFESystem

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

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Buffers.Binary;
using Cosmos.Kernel.Boot.Limine;
using XFESystem.Desktop;

namespace XFESystem.Kernel;

internal readonly record struct NativeMonitorInfo(DisplayTimingResult Timing, string Origin, int FirmwareOutputs);

/// <summary>Copies bounded original firmware data. Boot Services are never called after exit.</summary>
internal static class NativeDisplayInfo
{
    private static ReadOnlySpan<byte> HandoffGuid => [0x44,0x46,0x45,0x58,0x49,0x53,0x50,0x31,0x9c,0x46,0x58,0x46,0x45,0x53,0x59,0x53];
    public static unsafe NativeMonitorInfo Read(int width, int height)
    {
        const int ReportBytes = 60192, DisplayBytes = 7520;
        byte* table = (byte*)(Limine.EfiSystemTable.Response == null ? null : Limine.EfiSystemTable.Response->Address);
        if (table != null)
        {
            var header = new ReadOnlySpan<byte>(table, 120);
            ulong count = BinaryPrimitives.ReadUInt64LittleEndian(header[104..]);
            ulong entriesAddress = BinaryPrimitives.ReadUInt64LittleEndian(header[112..]);
            if (count <= 4096 && entriesAddress != 0)
            {
                var entries = new ReadOnlySpan<byte>((void*)entriesAddress, checked((int)count * 24));
                for (int i = 0; i < (int)count; i++)
                {
                    var entry = entries.Slice(i * 24, 24);
                    if (!entry[..16].SequenceEqual(HandoffGuid)) continue;
                    ulong address = BinaryPrimitives.ReadUInt64LittleEndian(entry[16..]);
                    if (address == 0) continue;
                    var reportHeader = new ReadOnlySpan<byte>((void*)address, 32);
                    if (!reportHeader[..8].SequenceEqual("XFEDISP1"u8) ||
                        BinaryPrimitives.ReadUInt32LittleEndian(reportHeader[8..]) != 1 ||
                        BinaryPrimitives.ReadUInt32LittleEndian(reportHeader[12..]) != ReportBytes ||
                        (BinaryPrimitives.ReadUInt32LittleEndian(reportHeader[28..]) & 256) == 0) continue;
                    uint outputs = BinaryPrimitives.ReadUInt32LittleEndian(reportHeader[16..]);
                    if (outputs is 0 or > 8) continue;
                    var report = new ReadOnlySpan<byte>((void*)address, ReportBytes);
                    for (int display = 0; display < (int)outputs; display++)
                    {
                        var record = report.Slice(32 + display * DisplayBytes, DisplayBytes);
                        if (BinaryPrimitives.ReadUInt32LittleEndian(record[40..]) != width ||
                            BinaryPrimitives.ReadUInt32LittleEndian(record[44..]) != height ||
                            (BinaryPrimitives.ReadUInt32LittleEndian(record[48..]) & 256) == 0) continue;
                        uint bytes = BinaryPrimitives.ReadUInt32LittleEndian(record[56..]);
                        if (bytes is < 128 or > 4096) continue;
                        var timing = DisplayTiming.Read(record.Slice(3168, (int)bytes), width, height);
                        if (timing.IsValid) return new(timing, "Original UEFI display handoff", (int)outputs);
                    }
                }
            }
        }
        var response = Limine.Framebuffer.Response;
        if (response != null && response->Framebuffers != null && response->FramebufferCount is > 0 and <= 8)
            for (int i = 0; i < (int)response->FramebufferCount; i++)
            {
                var framebuffer = response->Framebuffers[i];
                if (framebuffer == null || framebuffer->Width != (ulong)width || framebuffer->Height != (ulong)height ||
                    framebuffer->Edid == null || framebuffer->EdidSize is < 128 or > 4096) continue;
                return new(DisplayTiming.Read(new ReadOnlySpan<byte>(framebuffer->Edid, (int)framebuffer->EdidSize), width, height),
                    "Limine EDID (possibly base block only)", (int)response->FramebufferCount);
            }
        return new(DisplayTiming.Read([], width, height), "Firmware EDID unavailable", 1);
    }
}