2019-09-05 14:42:19 +02:00
# include <cstdint>
# include <string>
# include <syslog.h>
# include <utility>
# include "svc.h"
namespace lightSwitch : : kernel : : svc {
void SetHeapSize ( device_state & state ) {
2019-09-14 14:41:00 +02:00
auto heap = state . this_process - > MapPrivateRegion ( 0 , state . nce - > GetRegister ( wreg : : w1 ) , { true , true , false } , Memory : : Type : : Heap , Memory : : Region : : heap ) ;
state . nce - > SetRegister ( wreg : : w0 , constant : : status : : success ) ;
state . nce - > SetRegister ( xreg : : x1 , heap - > address ) ;
state . logger - > Write ( Logger : : DEBUG , " Heap size was set to 0x{:X} " , state . nce - > GetRegister ( wreg : : w1 ) ) ;
}
void QueryMemory ( device_state & state ) {
Memory : : MemoryInfo mem_inf ;
u64 addr = state . nce - > GetRegister ( xreg : : x2 ) ;
if ( state . nce - > memory_map . count ( addr ) ) {
mem_inf = state . nce - > memory_map . at ( addr ) - > GetInfo ( state . this_process - > main_thread ) ;
} else if ( state . this_process - > memory_map . count ( addr ) ) {
mem_inf = state . this_process - > memory_map . at ( addr ) - > GetInfo ( ) ;
} else {
state . nce - > SetRegister ( wreg : : w0 , constant : : status : : inv_address ) ;
return ;
}
state . this_process - > WriteMemory < Memory : : MemoryInfo > ( mem_inf , state . nce - > GetRegister ( xreg : : x0 ) ) ;
state . nce - > SetRegister ( wreg : : w0 , constant : : status : : success ) ;
2019-09-05 14:42:19 +02:00
}
void CreateThread ( device_state & state ) {
// TODO: Check if the values supplied by the process are actually valid & Support Core Mask potentially ?
2019-09-14 14:41:00 +02:00
auto thread = state . this_process - > CreateThread ( state . nce - > GetRegister ( xreg : : x1 ) , state . nce - > GetRegister ( xreg : : x2 ) , state . nce - > GetRegister ( xreg : : x3 ) , static_cast < u8 > ( state . nce - > GetRegister ( wreg : : w4 ) ) ) ;
state . nce - > SetRegister ( wreg : : w0 , constant : : status : : success ) ;
state . nce - > SetRegister ( wreg : : w1 , thread - > handle ) ;
2019-09-05 14:42:19 +02:00
}
void StartThread ( device_state & state ) {
2019-09-14 14:41:00 +02:00
auto & object = state . this_process - > handle_table . at ( static_cast < const unsigned int & > ( state . nce - > GetRegister ( wreg : : w0 ) ) ) ;
if ( object - > type = = type : : KObjectType : : KThread ) {
2019-09-05 14:42:19 +02:00
std : : static_pointer_cast < type : : KThread > ( object ) - > Start ( ) ;
} else
throw exception ( " StartThread was called on a non-KThread object " ) ;
}
void ExitThread ( device_state & state ) {
state . os - > KillThread ( state . this_thread - > pid ) ;
}
void GetThreadPriority ( device_state & state ) {
2019-09-14 14:41:00 +02:00
auto & object = state . this_process - > handle_table . at ( static_cast < const unsigned int & > ( state . nce - > GetRegister ( wreg : : w0 ) ) ) ;
if ( object - > type = = type : : KObjectType : : KThread ) {
state . nce - > SetRegister ( wreg : : w0 , constant : : status : : success ) ;
state . nce - > SetRegister ( wreg : : w1 , std : : static_pointer_cast < type : : KThread > ( object ) - > priority ) ;
2019-09-05 14:42:19 +02:00
} else
throw exception ( " GetThreadPriority was called on a non-KThread object " ) ;
}
void SetThreadPriority ( device_state & state ) {
2019-09-14 14:41:00 +02:00
auto & object = state . this_process - > handle_table . at ( static_cast < const unsigned int & > ( state . nce - > GetRegister ( wreg : : w0 ) ) ) ;
if ( object - > type = = type : : KObjectType : : KThread ) {
2019-09-05 14:42:19 +02:00
std : : static_pointer_cast < type : : KThread > ( object ) - > Start ( ) ;
} else
throw exception ( " SetThreadPriority was called on a non-KThread object " ) ;
}
void CloseHandle ( device_state & state ) {
2019-09-14 14:41:00 +02:00
auto & object = state . this_process - > handle_table . at ( static_cast < const unsigned int & > ( state . nce - > GetRegister ( wreg : : w0 ) ) ) ;
2019-09-05 14:42:19 +02:00
switch ( object - > type ) {
2019-09-14 14:41:00 +02:00
case ( type : : KObjectType : : KThread ) :
2019-09-05 14:42:19 +02:00
state . os - > KillThread ( std : : static_pointer_cast < type : : KThread > ( object ) - > pid ) ;
break ;
2019-09-14 14:41:00 +02:00
case ( type : : KObjectType : : KProcess ) :
2019-09-05 14:42:19 +02:00
state . os - > KillThread ( std : : static_pointer_cast < type : : KProcess > ( object ) - > main_thread ) ;
break ;
2019-09-14 14:41:00 +02:00
default :
state . nce - > SetRegister ( wreg : : w0 , constant : : status : : inv_handle ) ;
return ;
2019-09-05 14:42:19 +02:00
}
2019-09-14 14:41:00 +02:00
state . nce - > SetRegister ( wreg : : w0 , constant : : status : : success ) ;
2019-09-05 14:42:19 +02:00
}
void ConnectToNamedPort ( device_state & state ) {
char port [ constant : : port_size ] { 0 } ;
2019-09-14 14:41:00 +02:00
state . os - > this_process - > ReadMemory ( port , state . nce - > GetRegister ( xreg : : x1 ) , constant : : port_size ) ;
2019-09-05 14:42:19 +02:00
if ( std : : strcmp ( port , " sm: " ) = = 0 )
2019-09-14 14:41:00 +02:00
state . nce - > SetRegister ( wreg : : w1 , constant : : sm_handle ) ;
2019-09-05 14:42:19 +02:00
else
throw exception ( fmt : : format ( " svcConnectToNamedPort tried connecting to invalid port: \" {} \" " , port ) ) ;
2019-09-14 14:41:00 +02:00
state . nce - > SetRegister ( wreg : : w0 , constant : : status : : success ) ;
2019-09-05 14:42:19 +02:00
}
void SendSyncRequest ( device_state & state ) {
2019-09-14 14:41:00 +02:00
state . logger - > Write ( Logger : : DEBUG , " ----------------------------svcSendSyncRequest Start----------------------- " ) ;
state . logger - > Write ( Logger : : DEBUG , " svcSendSyncRequest called for handle 0x{:X}. " , state . nce - > GetRegister ( xreg : : x0 ) ) ;
state . os - > IpcHandler ( static_cast < handle_t > ( state . nce - > GetRegister ( xreg : : x0 ) ) ) ;
state . nce - > SetRegister ( wreg : : w0 , constant : : status : : success ) ;
state . nce - > SetRegister ( wreg : : w19 , constant : : status : : success ) ;
state . logger - > Write ( Logger : : DEBUG , " ----------------------------svcSendSyncRequest End------------------------- " ) ;
2019-09-05 14:42:19 +02:00
}
void OutputDebugString ( device_state & state ) {
2019-09-14 14:41:00 +02:00
std : : string debug ( state . nce - > GetRegister ( xreg : : x1 ) , ' \0 ' ) ;
state . os - > this_process - > ReadMemory ( ( void * ) debug . data ( ) , state . nce - > GetRegister ( xreg : : x0 ) , state . nce - > GetRegister ( xreg : : x1 ) ) ;
2019-09-05 14:42:19 +02:00
state . logger - > Write ( Logger : : INFO , " svcOutputDebugString: {} " , debug . c_str ( ) ) ;
2019-09-14 14:41:00 +02:00
state . nce - > SetRegister ( wreg : : w0 , 0 ) ;
2019-09-05 14:42:19 +02:00
}
void GetInfo ( device_state & state ) {
2019-09-14 14:41:00 +02:00
state . logger - > Write ( Logger : : DEBUG , " svcGetInfo called with ID0: {}, ID1: {} " , state . nce - > GetRegister ( wreg : : w1 ) , state . nce - > GetRegister ( xreg : : x3 ) ) ;
switch ( state . nce - > GetRegister ( wreg : : w1 ) ) {
2019-09-05 14:42:19 +02:00
case constant : : infoState : : AllowedCpuIdBitmask :
case constant : : infoState : : AllowedThreadPriorityMask :
case constant : : infoState : : IsCurrentProcessBeingDebugged :
case constant : : infoState : : TitleId :
case constant : : infoState : : PrivilegedProcessId :
2019-09-14 14:41:00 +02:00
state . nce - > SetRegister ( xreg : : x1 , 0 ) ;
break ;
case constant : : infoState : : AliasRegionBaseAddr :
state . nce - > SetRegister ( xreg : : x1 , constant : : map_addr ) ;
break ;
case constant : : infoState : : AliasRegionSize :
state . nce - > SetRegister ( xreg : : x1 , constant : : map_size ) ;
2019-09-05 14:42:19 +02:00
break ;
case constant : : infoState : : HeapRegionBaseAddr :
2019-09-14 14:41:00 +02:00
state . nce - > SetRegister ( xreg : : x1 , state . os - > this_process - > memory_region_map . at ( Memory : : Region : : heap ) - > address ) ;
2019-09-05 14:42:19 +02:00
break ;
case constant : : infoState : : HeapRegionSize :
2019-09-14 14:41:00 +02:00
state . nce - > SetRegister ( xreg : : x1 , state . os - > this_process - > memory_region_map . at ( Memory : : Region : : heap ) - > size ) ;
break ;
case constant : : infoState : : TotalMemoryAvailable :
state . nce - > SetRegister ( xreg : : x1 , constant : : total_phy_mem ) ;
break ;
case constant : : infoState : : TotalMemoryUsage :
state . nce - > SetRegister ( xreg : : x1 , state . os - > this_process - > memory_region_map . at ( Memory : : Region : : heap ) - > address + state . this_process - > main_thread_stack_sz + state . nce - > GetSharedSize ( ) ) ;
2019-09-05 14:42:19 +02:00
break ;
case constant : : infoState : : AddressSpaceBaseAddr :
2019-09-14 14:41:00 +02:00
state . nce - > SetRegister ( xreg : : x1 , constant : : base_addr ) ;
2019-09-05 14:42:19 +02:00
break ;
case constant : : infoState : : AddressSpaceSize :
2019-09-14 14:41:00 +02:00
state . nce - > SetRegister ( xreg : : x1 , constant : : base_size ) ;
break ;
case constant : : infoState : : StackRegionBaseAddr :
state . nce - > SetRegister ( xreg : : x1 , state . this_thread - > stack_top ) ;
break ;
case constant : : infoState : : StackRegionSize :
state . nce - > SetRegister ( xreg : : x1 , state . this_process - > main_thread_stack_sz ) ;
2019-09-05 14:42:19 +02:00
break ;
case constant : : infoState : : PersonalMmHeapSize :
2019-09-14 14:41:00 +02:00
state . nce - > SetRegister ( xreg : : x1 , constant : : total_phy_mem ) ;
2019-09-05 14:42:19 +02:00
break ;
case constant : : infoState : : PersonalMmHeapUsage :
2019-09-14 14:41:00 +02:00
state . nce - > SetRegister ( xreg : : x1 , state . os - > this_process - > memory_region_map . at ( Memory : : Region : : heap ) - > address + state . this_process - > main_thread_stack_sz ) ;
2019-09-05 14:42:19 +02:00
break ;
case constant : : infoState : : TotalMemoryAvailableWithoutMmHeap :
2019-09-14 14:41:00 +02:00
state . nce - > SetRegister ( xreg : : x1 , constant : : total_phy_mem ) ; // TODO: NPDM specifies SystemResourceSize, subtract that from this
2019-09-05 14:42:19 +02:00
break ;
case constant : : infoState : : TotalMemoryUsedWithoutMmHeap :
2019-09-14 14:41:00 +02:00
state . nce - > SetRegister ( xreg : : x1 , state . os - > this_process - > memory_region_map . at ( Memory : : Region : : heap ) - > address + state . this_process - > main_thread_stack_sz ) ; // TODO: Same as above
2019-09-05 14:42:19 +02:00
break ;
case constant : : infoState : : UserExceptionContextAddr :
2019-09-14 14:41:00 +02:00
state . nce - > SetRegister ( xreg : : x1 , state . this_process - > tls_pages [ 0 ] - > Get ( 0 ) ) ;
2019-09-05 14:42:19 +02:00
break ;
default :
2019-09-14 14:41:00 +02:00
state . logger - > Write ( Logger : : WARN , " Unimplemented svcGetInfo with ID0: {}, ID1: {} " , state . nce - > GetRegister ( wreg : : w1 ) , state . nce - > GetRegister ( xreg : : x3 ) ) ;
state . nce - > SetRegister ( wreg : : w0 , constant : : status : : unimpl ) ;
2019-09-05 14:42:19 +02:00
return ;
}
2019-09-14 14:41:00 +02:00
state . nce - > SetRegister ( wreg : : w0 , constant : : status : : success ) ;
2019-09-05 14:42:19 +02:00
}
void ExitProcess ( device_state & state ) {
state . os - > KillThread ( state . this_process - > main_thread ) ;
}
}