| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- using Ryujinx.Horizon.Common;
- using Ryujinx.Horizon.Sdk.Sf.Hipc;
- using System;
- using System.Runtime.CompilerServices;
- using System.Runtime.InteropServices;
- namespace Ryujinx.Horizon.Sdk.Sf.Cmif
- {
- static class CmifMessage
- {
- public const uint CmifInHeaderMagic = 0x49434653; // SFCI
- public const uint CmifOutHeaderMagic = 0x4f434653; // SFCO
- public static CmifRequest CreateRequest(Span<byte> output, CmifRequestFormat format)
- {
- int totalSize = 16;
- if (format.ObjectId != 0)
- {
- totalSize += Unsafe.SizeOf<CmifDomainInHeader>() + format.ObjectsCount * sizeof(int);
- }
- totalSize += Unsafe.SizeOf<CmifInHeader>() + format.DataSize;
- totalSize = (totalSize + 1) & ~1;
- int outPointerSizeTableOffset = totalSize;
- int outPointerSizeTableSize = format.OutAutoBuffersCount + format.OutPointersCount;
- totalSize += sizeof(ushort) * outPointerSizeTableSize;
- int rawDataSizeInWords = (totalSize + sizeof(uint) - 1) / sizeof(uint);
- CmifRequest request = new()
- {
- Hipc = HipcMessage.WriteMessage(output, new HipcMetadata()
- {
- Type = format.Context != 0 ? (int)CommandType.RequestWithContext : (int)CommandType.Request,
- SendStaticsCount = format.InAutoBuffersCount + format.InPointersCount,
- SendBuffersCount = format.InAutoBuffersCount + format.InBuffersCount,
- ReceiveBuffersCount = format.OutAutoBuffersCount + format.OutBuffersCount,
- ExchangeBuffersCount = format.InOutBuffersCount,
- DataWordsCount = rawDataSizeInWords,
- ReceiveStaticsCount = outPointerSizeTableSize + format.OutFixedPointersCount,
- SendPid = format.SendPid,
- CopyHandlesCount = format.HandlesCount,
- MoveHandlesCount = 0
- })
- };
- Span<uint> data = request.Hipc.DataWords;
- if (format.ObjectId != 0)
- {
- ref CmifDomainInHeader domainHeader = ref MemoryMarshal.Cast<uint, CmifDomainInHeader>(data)[0];
- int payloadSize = Unsafe.SizeOf<CmifInHeader>() + format.DataSize;
- domainHeader = new CmifDomainInHeader()
- {
- Type = CmifDomainRequestType.SendMessage,
- ObjectsCount = (byte)format.ObjectsCount,
- DataSize = (ushort)payloadSize,
- ObjectId = format.ObjectId,
- Padding = 0,
- Token = format.Context
- };
- data = data[(Unsafe.SizeOf<CmifDomainInHeader>() / sizeof(uint))..];
- request.Objects = data[((payloadSize + sizeof(uint) - 1) / sizeof(uint))..];
- }
- ref CmifInHeader header = ref MemoryMarshal.Cast<uint, CmifInHeader>(data)[0];
- header = new CmifInHeader()
- {
- Magic = CmifInHeaderMagic,
- Version = format.Context != 0 ? 1u : 0u,
- CommandId = format.RequestId,
- Token = format.ObjectId != 0 ? 0u : format.Context
- };
- request.Data = MemoryMarshal.Cast<uint, byte>(data)[Unsafe.SizeOf<CmifInHeader>()..];
- int paddingSizeBefore = (rawDataSizeInWords - request.Hipc.DataWords.Length) * sizeof(uint);
- Span<byte> outPointerTable = MemoryMarshal.Cast<uint, byte>(request.Hipc.DataWords)[(outPointerSizeTableOffset - paddingSizeBefore)..];
- request.OutPointerSizes = MemoryMarshal.Cast<byte, ushort>(outPointerTable);
- request.ServerPointerSize = format.ServerPointerSize;
- return request;
- }
- public static Result ParseResponse(out CmifResponse response, Span<byte> input, bool isDomain, int size)
- {
- HipcMessage responseMessage = new(input);
- Span<byte> data = MemoryMarshal.Cast<uint, byte>(responseMessage.Data.DataWords);
- Span<uint> objects = Span<uint>.Empty;
- if (isDomain)
- {
- data = data[Unsafe.SizeOf<CmifDomainOutHeader>()..];
- objects = MemoryMarshal.Cast<byte, uint>(data[(Unsafe.SizeOf<CmifOutHeader>() + size)..]);
- }
- CmifOutHeader header = MemoryMarshal.Cast<byte, CmifOutHeader>(data)[0];
- if (header.Magic != CmifOutHeaderMagic)
- {
- response = default;
- return SfResult.InvalidOutHeader;
- }
- if (header.Result.IsFailure)
- {
- response = default;
- return header.Result;
- }
- response = new CmifResponse()
- {
- Data = data[Unsafe.SizeOf<CmifOutHeader>()..],
- Objects = objects,
- CopyHandles = responseMessage.Data.CopyHandles,
- MoveHandles = responseMessage.Data.MoveHandles
- };
- return Result.Success;
- }
- }
- }
|