2019-09-24 22:54:27 +02:00
# include "ipc.h"
# include "types/KProcess.h"
namespace skyline : : kernel : : ipc {
IpcRequest : : IpcRequest ( bool isDomain , const DeviceState & state ) : isDomain ( isDomain ) , state ( state ) , tls ( ) {
u8 * currPtr = tls . data ( ) ;
state . thisProcess - > ReadMemory ( currPtr , state . thisThread - > tls , constant : : TlsIpcSize ) ;
header = reinterpret_cast < CommandHeader * > ( currPtr ) ;
currPtr + = sizeof ( CommandHeader ) ;
if ( header - > handle_desc ) {
handleDesc = reinterpret_cast < HandleDescriptor * > ( currPtr ) ;
2019-10-13 10:04:47 +02:00
currPtr + = sizeof ( HandleDescriptor ) + ( handleDesc - > send_pid ? sizeof ( u64 ) : 0 ) ;
2019-09-24 22:54:27 +02:00
for ( uint index = 0 ; handleDesc - > copy_count > index ; index + + ) {
copyHandles . push_back ( * reinterpret_cast < handle_t * > ( currPtr ) ) ;
currPtr + = sizeof ( handle_t ) ;
}
for ( uint index = 0 ; handleDesc - > move_count > index ; index + + ) {
moveHandles . push_back ( * reinterpret_cast < handle_t * > ( currPtr ) ) ;
currPtr + = sizeof ( handle_t ) ;
}
}
for ( uint index = 0 ; header - > x_no > index ; index + + ) {
vecBufX . push_back ( reinterpret_cast < BufferDescriptorX * > ( currPtr ) ) ;
currPtr + = sizeof ( BufferDescriptorX ) ;
}
for ( uint index = 0 ; header - > a_no > index ; index + + ) {
vecBufA . push_back ( reinterpret_cast < BufferDescriptorABW * > ( currPtr ) ) ;
currPtr + = sizeof ( BufferDescriptorABW ) ;
}
for ( uint index = 0 ; header - > b_no > index ; index + + ) {
vecBufB . push_back ( reinterpret_cast < BufferDescriptorABW * > ( currPtr ) ) ;
currPtr + = sizeof ( BufferDescriptorABW ) ;
}
for ( uint index = 0 ; header - > w_no > index ; index + + ) {
vecBufW . push_back ( reinterpret_cast < BufferDescriptorABW * > ( currPtr ) ) ;
currPtr + = sizeof ( BufferDescriptorABW ) ;
}
currPtr = reinterpret_cast < u8 * > ( ( ( ( reinterpret_cast < u64 > ( currPtr ) - reinterpret_cast < u64 > ( tls . data ( ) ) ) - 1U ) & ~ ( constant : : PaddingSum - 1U ) ) + constant : : PaddingSum + reinterpret_cast < u64 > ( tls . data ( ) ) ) ; // Align to 16 bytes relative to start of TLS
if ( isDomain ) {
domain = reinterpret_cast < DomainHeaderRequest * > ( currPtr ) ;
currPtr + = sizeof ( DomainHeaderRequest ) ;
payload = reinterpret_cast < PayloadHeader * > ( currPtr ) ;
currPtr + = sizeof ( PayloadHeader ) ;
cmdArg = currPtr ;
cmdArgSz = domain - > payload_sz - sizeof ( PayloadHeader ) ;
currPtr + = domain - > payload_sz ;
for ( uint index = 0 ; domain - > input_count > index ; index + + ) {
domainObjects . push_back ( * reinterpret_cast < handle_t * > ( currPtr ) ) ;
currPtr + = sizeof ( handle_t ) ;
}
} else {
payload = reinterpret_cast < PayloadHeader * > ( currPtr ) ;
currPtr + = sizeof ( PayloadHeader ) ;
cmdArg = currPtr ;
cmdArgSz = ( header - > raw_sz * sizeof ( u32 ) ) - ( constant : : PaddingSum + sizeof ( PayloadHeader ) ) ;
currPtr + = cmdArgSz ;
}
if ( payload - > magic ! = constant : : SfciMagic )
2019-09-27 18:09:48 +02:00
state . logger - > Write ( Logger : : Debug , " Unexpected Magic in PayloadHeader: 0x{:X} " , u32 ( payload - > magic ) ) ;
2019-09-24 22:54:27 +02:00
if ( header - > c_flag = = static_cast < u8 > ( BufferCFlag : : SingleDescriptor ) ) {
vecBufC . push_back ( reinterpret_cast < BufferDescriptorC * > ( currPtr ) ) ;
} else if ( header - > c_flag > static_cast < u8 > ( BufferCFlag : : SingleDescriptor ) ) {
for ( uint index = 0 ; ( header - > c_flag - 2 ) > index ; index + + ) { // (c_flag - 2) C descriptors are present
vecBufC . push_back ( reinterpret_cast < BufferDescriptorC * > ( currPtr ) ) ;
state . logger - > Write ( Logger : : Debug , " Buf C #{} AD: 0x{:X} SZ: 0x{:X} " , index , u64 ( vecBufC [ index ] - > address ) , u16 ( vecBufC [ index ] - > size ) ) ;
currPtr + = sizeof ( BufferDescriptorC ) ;
}
}
state . logger - > Write ( Logger : : Debug , " Header: X No: {}, A No: {}, B No: {}, W No: {}, C No: {}, Raw Size: {} " , u8 ( header - > x_no ) , u8 ( header - > a_no ) , u8 ( header - > b_no ) , u8 ( header - > w_no ) , u8 ( vecBufC . size ( ) ) , u64 ( cmdArgSz ) ) ;
if ( header - > handle_desc )
state . logger - > Write ( Logger : : Debug , " Handle Descriptor: Send PID: {}, Copy Count: {}, Move Count: {} " , bool ( handleDesc - > send_pid ) , u32 ( handleDesc - > copy_count ) , u32 ( handleDesc - > move_count ) ) ;
if ( isDomain )
state . logger - > Write ( Logger : : Debug , " Domain Header: Command: {}, Input Object Count: {}, Object ID: 0x{:X} " , domain - > command , domain - > input_count , domain - > object_id ) ;
state . logger - > Write ( Logger : : Debug , " Data Payload: Command ID: 0x{:X} " , u32 ( payload - > value ) ) ;
}
IpcResponse : : IpcResponse ( bool isDomain , const DeviceState & state ) : isDomain ( isDomain ) , state ( state ) { }
void IpcResponse : : WriteTls ( ) {
std : : array < u8 , constant : : TlsIpcSize > tls { } ;
u8 * currPtr = tls . data ( ) ;
auto header = reinterpret_cast < CommandHeader * > ( currPtr ) ;
2019-09-26 17:37:24 +02:00
header - > raw_sz = static_cast < u32 > ( ( sizeof ( PayloadHeader ) + argVec . size ( ) + ( domainObjects . size ( ) * sizeof ( handle_t ) ) + constant : : PaddingSum + ( isDomain ? sizeof ( DomainHeaderRequest ) : 0 ) ) / sizeof ( u32 ) ) ; // Size is in 32-bit units because Nintendo
2019-09-24 22:54:27 +02:00
header - > handle_desc = ( ! copyHandles . empty ( ) | | ! moveHandles . empty ( ) ) ;
currPtr + = sizeof ( CommandHeader ) ;
if ( header - > handle_desc ) {
auto handleDesc = reinterpret_cast < HandleDescriptor * > ( currPtr ) ;
handleDesc - > copy_count = static_cast < u8 > ( copyHandles . size ( ) ) ;
handleDesc - > move_count = static_cast < u8 > ( moveHandles . size ( ) ) ;
currPtr + = sizeof ( HandleDescriptor ) ;
for ( unsigned int copyHandle : copyHandles ) {
* reinterpret_cast < handle_t * > ( currPtr ) = copyHandle ;
currPtr + = sizeof ( handle_t ) ;
}
for ( unsigned int moveHandle : moveHandles ) {
* reinterpret_cast < handle_t * > ( currPtr ) = moveHandle ;
currPtr + = sizeof ( handle_t ) ;
}
}
u64 padding = ( ( ( ( reinterpret_cast < u64 > ( currPtr ) - reinterpret_cast < u64 > ( tls . data ( ) ) ) - 1U ) & ~ ( constant : : PaddingSum - 1U ) ) + constant : : PaddingSum + ( reinterpret_cast < u64 > ( tls . data ( ) ) - reinterpret_cast < u64 > ( currPtr ) ) ) ; // Calculate the amount of padding at the front
currPtr + = padding ;
if ( isDomain ) {
auto domain = reinterpret_cast < DomainHeaderResponse * > ( currPtr ) ;
domain - > output_count = static_cast < u32 > ( domainObjects . size ( ) ) ;
currPtr + = sizeof ( DomainHeaderResponse ) ;
}
auto payload = reinterpret_cast < PayloadHeader * > ( currPtr ) ;
payload - > magic = constant : : SfcoMagic ;
payload - > version = 1 ;
payload - > value = errorCode ;
currPtr + = sizeof ( PayloadHeader ) ;
if ( ! argVec . empty ( ) )
memcpy ( currPtr , argVec . data ( ) , argVec . size ( ) ) ;
currPtr + = argVec . size ( ) ;
if ( isDomain ) {
for ( auto & domainObject : domainObjects ) {
* reinterpret_cast < handle_t * > ( currPtr ) = domainObject ;
currPtr + = sizeof ( handle_t ) ;
}
}
2019-10-13 10:04:47 +02:00
state . logger - > Write ( Logger : : Debug , " Output: Raw Size: {}, Command ID: 0x{:X}, Copy Handles: {}, Move Handles: {} " , u32 ( header - > raw_sz ) , u32 ( payload - > value ) , copyHandles . size ( ) , moveHandles . size ( ) ) ;
2019-09-24 22:54:27 +02:00
state . thisProcess - > WriteMemory ( tls . data ( ) , state . thisThread - > tls , constant : : TlsIpcSize ) ;
}
}