Some small fixes related to receive list buffers and error cases
This commit is contained in:
parent
6b9f4d38e4
commit
4c4f6c6702
1 changed files with 96 additions and 65 deletions
|
@ -48,6 +48,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
|
|
||||||
private struct MessageHeader
|
private struct MessageHeader
|
||||||
{
|
{
|
||||||
|
public uint Word0 { get; }
|
||||||
|
public uint Word1 { get; }
|
||||||
|
public uint Word2 { get; }
|
||||||
|
|
||||||
public uint PointerBuffersCount { get; }
|
public uint PointerBuffersCount { get; }
|
||||||
public uint SendBuffersCount { get; }
|
public uint SendBuffersCount { get; }
|
||||||
public uint ReceiveBuffersCount { get; }
|
public uint ReceiveBuffersCount { get; }
|
||||||
|
@ -70,6 +74,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
|
|
||||||
public MessageHeader(uint word0, uint word1, uint word2)
|
public MessageHeader(uint word0, uint word1, uint word2)
|
||||||
{
|
{
|
||||||
|
Word0 = word0;
|
||||||
|
Word1 = word1;
|
||||||
|
Word2 = word2;
|
||||||
|
|
||||||
HasHandles = word1 >> 31 != 0;
|
HasHandles = word1 >> 31 != 0;
|
||||||
|
|
||||||
uint handleDescSizeInWords = 0;
|
uint handleDescSizeInWords = 0;
|
||||||
|
@ -241,16 +249,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
request.CustomCmdBuffAddr,
|
request.CustomCmdBuffAddr,
|
||||||
request.CustomCmdBuffSize);
|
request.CustomCmdBuffSize);
|
||||||
|
|
||||||
Message serverMsg = new Message(
|
Message serverMsg = new Message(serverThread, customCmdBuffAddr, customCmdBuffSize);
|
||||||
serverThread,
|
|
||||||
customCmdBuffAddr,
|
|
||||||
customCmdBuffSize);
|
|
||||||
|
|
||||||
uint word0 = System.Device.Memory.ReadUInt32((long)clientMsg.DramAddress + 0);
|
MessageHeader header = GetClientMessageHeader(clientMsg);
|
||||||
uint word1 = System.Device.Memory.ReadUInt32((long)clientMsg.DramAddress + 4);
|
|
||||||
uint word2 = System.Device.Memory.ReadUInt32((long)clientMsg.DramAddress + 8);
|
|
||||||
|
|
||||||
MessageHeader header = new MessageHeader(word0, word1, word2);
|
|
||||||
|
|
||||||
KernelResult serverResult = KernelResult.NotFound;
|
KernelResult serverResult = KernelResult.NotFound;
|
||||||
KernelResult clientResult = KernelResult.Success;
|
KernelResult clientResult = KernelResult.Success;
|
||||||
|
@ -278,19 +279,22 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
WakeClient(request, clientResult);
|
WakeClient(request, clientResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header.ReceiveListType < 2 && header.ReceiveListOffset > clientMsg.Size)
|
if (header.ReceiveListType < 2 &&
|
||||||
|
header.ReceiveListOffset > clientMsg.Size)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
return KernelResult.InvalidCombination;
|
return KernelResult.InvalidCombination;
|
||||||
}
|
}
|
||||||
else if (header.ReceiveListType == 2 && header.ReceiveListOffset + 8 > clientMsg.Size)
|
else if (header.ReceiveListType == 2 &&
|
||||||
|
header.ReceiveListOffset + 8 > clientMsg.Size)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
return KernelResult.InvalidCombination;
|
return KernelResult.InvalidCombination;
|
||||||
}
|
}
|
||||||
else if (header.ReceiveListType * 8 - 0x10 + header.ReceiveListOffset > clientMsg.Size)
|
else if (header.ReceiveListType > 2 &&
|
||||||
|
header.ReceiveListType * 8 - 0x10 + header.ReceiveListOffset > clientMsg.Size)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
|
@ -311,28 +315,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
return KernelResult.CmdBufferTooSmall;
|
return KernelResult.CmdBufferTooSmall;
|
||||||
}
|
}
|
||||||
|
|
||||||
int recvListSize = 0;
|
ulong[] receiveList = GetReceiveList(clientMsg, header.ReceiveListType, header.ReceiveListOffset);
|
||||||
|
|
||||||
if (header.ReceiveListType >= 3)
|
serverProcess.CpuMemory.WriteUInt32((long)serverMsg.Address + 0, header.Word0);
|
||||||
{
|
serverProcess.CpuMemory.WriteUInt32((long)serverMsg.Address + 4, header.Word1);
|
||||||
recvListSize = (int)header.ReceiveListType - 2;
|
|
||||||
}
|
|
||||||
else if (header.ReceiveListType == 2)
|
|
||||||
{
|
|
||||||
recvListSize = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ulong[] receiveList = new ulong[recvListSize];
|
|
||||||
|
|
||||||
long recvListAddress = (long)serverMsg.Address + header.ReceiveListOffset;
|
|
||||||
|
|
||||||
for (int index = 0; index < recvListSize; index++)
|
|
||||||
{
|
|
||||||
receiveList[index] = serverProcess.CpuMemory.ReadUInt64(recvListAddress + index * 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
serverProcess.CpuMemory.WriteUInt32((long)serverMsg.Address + 0, word0);
|
|
||||||
serverProcess.CpuMemory.WriteUInt32((long)serverMsg.Address + 4, word1);
|
|
||||||
|
|
||||||
uint offset;
|
uint offset;
|
||||||
|
|
||||||
|
@ -346,7 +332,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
return KernelResult.InvalidCombination;
|
return KernelResult.InvalidCombination;
|
||||||
}
|
}
|
||||||
|
|
||||||
serverProcess.CpuMemory.WriteUInt32((long)serverMsg.Address + 8, word2);
|
serverProcess.CpuMemory.WriteUInt32((long)serverMsg.Address + 8, header.Word2);
|
||||||
|
|
||||||
offset = 3;
|
offset = 3;
|
||||||
|
|
||||||
|
@ -417,7 +403,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
|
|
||||||
if (descriptor.BufferSize != 0)
|
if (descriptor.BufferSize != 0)
|
||||||
{
|
{
|
||||||
clientResult = GetReceiveListAddress(serverMsg, header, descriptor, receiveList, out ulong recvListBufferAddress);
|
clientResult = GetReceiveListAddress(
|
||||||
|
descriptor,
|
||||||
|
serverMsg,
|
||||||
|
header.ReceiveListType,
|
||||||
|
header.MessageSizeInWords,
|
||||||
|
receiveList,
|
||||||
|
out ulong recvListBufferAddress);
|
||||||
|
|
||||||
if (clientResult != KernelResult.Success)
|
if (clientResult != KernelResult.Success)
|
||||||
{
|
{
|
||||||
|
@ -627,10 +619,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
request.CustomCmdBuffAddr,
|
request.CustomCmdBuffAddr,
|
||||||
request.CustomCmdBuffSize);
|
request.CustomCmdBuffSize);
|
||||||
|
|
||||||
Message serverMsg = new Message(
|
Message serverMsg = new Message(serverThread, customCmdBuffAddr, customCmdBuffSize);
|
||||||
serverThread,
|
|
||||||
customCmdBuffAddr,
|
|
||||||
customCmdBuffSize);
|
|
||||||
|
|
||||||
uint word0 = serverProcess.CpuMemory.ReadUInt32((long)serverMsg.Address + 0);
|
uint word0 = serverProcess.CpuMemory.ReadUInt32((long)serverMsg.Address + 0);
|
||||||
uint word1 = serverProcess.CpuMemory.ReadUInt32((long)serverMsg.Address + 4);
|
uint word1 = serverProcess.CpuMemory.ReadUInt32((long)serverMsg.Address + 4);
|
||||||
|
@ -638,6 +627,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
|
|
||||||
MessageHeader header = new MessageHeader(word0, word1, word2);
|
MessageHeader header = new MessageHeader(word0, word1, word2);
|
||||||
|
|
||||||
|
MessageHeader clientHeader = GetClientMessageHeader(clientMsg);
|
||||||
|
|
||||||
KernelResult clientResult = KernelResult.Success;
|
KernelResult clientResult = KernelResult.Success;
|
||||||
KernelResult serverResult = KernelResult.Success;
|
KernelResult serverResult = KernelResult.Success;
|
||||||
|
|
||||||
|
@ -648,26 +639,29 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
CancelRequest(request, clientResult);
|
CancelRequest(request, clientResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header.ReceiveListType < 2 && header.ReceiveListOffset > clientMsg.Size)
|
if (clientHeader.ReceiveListType < 2 &&
|
||||||
|
clientHeader.ReceiveListOffset > clientMsg.Size)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
return KernelResult.InvalidCombination;
|
return KernelResult.InvalidCombination;
|
||||||
}
|
}
|
||||||
else if (header.ReceiveListType == 2 && header.ReceiveListOffset + 8 > clientMsg.Size)
|
else if (clientHeader.ReceiveListType == 2 &&
|
||||||
|
clientHeader.ReceiveListOffset + 8 > clientMsg.Size)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
return KernelResult.InvalidCombination;
|
return KernelResult.InvalidCombination;
|
||||||
}
|
}
|
||||||
else if (header.ReceiveListType * 8 - 0x10 + header.ReceiveListOffset > clientMsg.Size)
|
else if (clientHeader.ReceiveListType > 2 &&
|
||||||
|
clientHeader.ReceiveListType * 8 - 0x10 + clientHeader.ReceiveListOffset > clientMsg.Size)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
return KernelResult.InvalidCombination;
|
return KernelResult.InvalidCombination;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header.ReceiveListOffsetInWords < header.MessageSizeInWords)
|
if (clientHeader.ReceiveListOffsetInWords < clientHeader.MessageSizeInWords)
|
||||||
{
|
{
|
||||||
CleanUpForError();
|
CleanUpForError();
|
||||||
|
|
||||||
|
@ -681,24 +675,20 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
return KernelResult.CmdBufferTooSmall;
|
return KernelResult.CmdBufferTooSmall;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (header.SendBuffersCount != 0 ||
|
||||||
|
header.ReceiveBuffersCount != 0 ||
|
||||||
|
header.ExchangeBuffersCount != 0)
|
||||||
|
{
|
||||||
|
CleanUpForError();
|
||||||
|
|
||||||
|
return KernelResult.InvalidCombination;
|
||||||
|
}
|
||||||
|
|
||||||
//Read receive list.
|
//Read receive list.
|
||||||
ulong[] receiveList = null;
|
ulong[] receiveList = GetReceiveList(
|
||||||
|
clientMsg,
|
||||||
if (header.ReceiveListType >= 2)
|
clientHeader.ReceiveListType,
|
||||||
{
|
clientHeader.ReceiveListOffset);
|
||||||
uint count = header.ReceiveListType == 2 ? 1 : header.ReceiveListType - 2;
|
|
||||||
|
|
||||||
receiveList = new ulong[count];
|
|
||||||
|
|
||||||
ulong receiveListAddress = clientMsg.DramAddress + header.ReceiveListOffset;
|
|
||||||
|
|
||||||
for (uint index = 0; index < count; index++)
|
|
||||||
{
|
|
||||||
ulong dword = System.Device.Memory.ReadUInt64((long)receiveListAddress + index * 8);
|
|
||||||
|
|
||||||
receiveList[index] = dword;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Copy receive and exchange buffers.
|
//Copy receive and exchange buffers.
|
||||||
clientResult = request.BufferDescriptorTable.CopyBuffersToClient(clientProcess.MemoryManager);
|
clientResult = request.BufferDescriptorTable.CopyBuffersToClient(clientProcess.MemoryManager);
|
||||||
|
@ -783,7 +773,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
|
|
||||||
if (descriptor.BufferSize != 0)
|
if (descriptor.BufferSize != 0)
|
||||||
{
|
{
|
||||||
clientResult = GetReceiveListAddress(serverMsg, header, descriptor, receiveList, out ulong recvListBufferAddress);
|
clientResult = GetReceiveListAddress(
|
||||||
|
descriptor,
|
||||||
|
clientMsg,
|
||||||
|
clientHeader.ReceiveListType,
|
||||||
|
header.MessageSizeInWords,
|
||||||
|
receiveList,
|
||||||
|
out ulong recvListBufferAddress);
|
||||||
|
|
||||||
if (clientResult != KernelResult.Success)
|
if (clientResult != KernelResult.Success)
|
||||||
{
|
{
|
||||||
|
@ -878,6 +874,15 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
return serverResult;
|
return serverResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private MessageHeader GetClientMessageHeader(Message clientMsg)
|
||||||
|
{
|
||||||
|
uint word0 = System.Device.Memory.ReadUInt32((long)clientMsg.DramAddress + 0);
|
||||||
|
uint word1 = System.Device.Memory.ReadUInt32((long)clientMsg.DramAddress + 4);
|
||||||
|
uint word2 = System.Device.Memory.ReadUInt32((long)clientMsg.DramAddress + 8);
|
||||||
|
|
||||||
|
return new MessageHeader(word0, word1, word2);
|
||||||
|
}
|
||||||
|
|
||||||
private KernelResult GetCopyObjectHandle(
|
private KernelResult GetCopyObjectHandle(
|
||||||
KThread srcThread,
|
KThread srcThread,
|
||||||
KProcess dstProcess,
|
KProcess dstProcess,
|
||||||
|
@ -937,27 +942,53 @@ namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ulong[] GetReceiveList(Message message, uint recvListType, uint recvListOffset)
|
||||||
|
{
|
||||||
|
int recvListSize = 0;
|
||||||
|
|
||||||
|
if (recvListType >= 3)
|
||||||
|
{
|
||||||
|
recvListSize = (int)recvListType - 2;
|
||||||
|
}
|
||||||
|
else if (recvListType == 2)
|
||||||
|
{
|
||||||
|
recvListSize = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ulong[] receiveList = new ulong[recvListSize];
|
||||||
|
|
||||||
|
long recvListAddress = (long)message.DramAddress + recvListOffset;
|
||||||
|
|
||||||
|
for (int index = 0; index < recvListSize; index++)
|
||||||
|
{
|
||||||
|
receiveList[index] = System.Device.Memory.ReadUInt64(recvListAddress + index * 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
return receiveList;
|
||||||
|
}
|
||||||
|
|
||||||
private KernelResult GetReceiveListAddress(
|
private KernelResult GetReceiveListAddress(
|
||||||
Message message,
|
|
||||||
MessageHeader header,
|
|
||||||
PointerBufferDesc descriptor,
|
PointerBufferDesc descriptor,
|
||||||
|
Message message,
|
||||||
|
uint recvListType,
|
||||||
|
uint messageSizeInWords,
|
||||||
ulong[] receiveList,
|
ulong[] receiveList,
|
||||||
out ulong address)
|
out ulong address)
|
||||||
{
|
{
|
||||||
ulong recvListBufferAddress = address = 0;
|
ulong recvListBufferAddress = address = 0;
|
||||||
|
|
||||||
if (header.ReceiveListType == 0)
|
if (recvListType == 0)
|
||||||
{
|
{
|
||||||
return KernelResult.OutOfResource;
|
return KernelResult.OutOfResource;
|
||||||
}
|
}
|
||||||
else if (header.ReceiveListType == 1 || header.ReceiveListType == 2)
|
else if (recvListType == 1 || recvListType == 2)
|
||||||
{
|
{
|
||||||
ulong recvListBaseAddr;
|
ulong recvListBaseAddr;
|
||||||
ulong recvListEndAddr;
|
ulong recvListEndAddr;
|
||||||
|
|
||||||
if (header.ReceiveListType == 1)
|
if (recvListType == 1)
|
||||||
{
|
{
|
||||||
recvListBaseAddr = message.Address + header.MessageSizeInWords * 4;
|
recvListBaseAddr = message.Address + messageSizeInWords * 4;
|
||||||
recvListEndAddr = message.Address + message.Size;
|
recvListEndAddr = message.Address + message.Size;
|
||||||
}
|
}
|
||||||
else /* if (recvListType == 2) */
|
else /* if (recvListType == 2) */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue