Merge pull request #19 from idunoe/master

Added new service APIs
This commit is contained in:
smea 2014-10-26 22:46:40 -07:00
commit 51850d5e6a
11 changed files with 716 additions and 7 deletions

View File

@ -0,0 +1,93 @@
#pragma once
/*
Requires access to "am:net" or "am:u" service
*/
Result amInit();
Result amExit();
/* AM_GetTitleCount()
About: Gets the number of titles for a given mediatype
mediatype mediatype to get titles from
count ptr to store title count
*/
Result AM_GetTitleCount(u8 mediatype, u32 *count);
/* AM_GetTitleList()
About: Writes a titleid list for a mediatype to a buffer
mediatype mediatype to get list from
count number of titleids to get
buffer buffer to write titleids to
*/
Result AM_GetTitleList(u8 mediatype, u32 count, void *buffer);
/* AM_GetDeviceId()
About: Gets a 32bit device id, it's used for some key slot inits
device_id ptr to where the device id is written to
*/
Result AM_GetDeviceId(u32 *deviceid);
/**** Title Install Methods ****/
/* AM_StartCiaInstall()
About: Inits CIA install process, the returned ciahandle is where the data for CIA should be written to
mediatype mediatype to install CIA to
ciahandle ptr to where the handle should be written to
*/
Result AM_StartCiaInstall(u8 mediatype, Handle *ciahandle);
/* AM_StartDlpChildCiaInstall()
About: Inits CIA install process, the returned ciahandle is where the data for CIA should be written to
Note: This is for installing DLP CIAs only, mediatype is hardcoded to be NAND
ciahandle ptr to where the handle should be written to
*/
Result AM_StartDlpChildCiaInstall(Handle *ciahandle);
/* AM_CancelCIAInstall()
About: Abort CIA install process
ciahandle ptr to cia Handle provided by AM
*/
Result AM_CancelCIAInstall(Handle *ciahandle);
/* AM_FinishCiaInstall()
About: Once all data is written to the cia handle, this command signals AM to proceed with CIA install.
Note: AM closes the cia handle provided here
mediatype same mediatype specified ciahandle was obtained
ciahandle ptr to cia Handle provided by AM
*/
Result AM_FinishCiaInstall(u8 mediatype, Handle *ciahandle);
/**** Title Delete Methods ****/
/* AM_DeleteTitle()
About: Deletes any title on NAND/SDMC
Note: AM closes the cia handle provided here
mediatype mediatype of title
titleid title id of title
*/
Result AM_DeleteTitle(u8 mediatype, u64 titleid);
/* AM_DeleteAppTitle()
About: Deletes any title on NAND/SDMC
Note: If the title has the system category bit set, this will fail
mediatype mediatype of title
titleid title id of title
*/
Result AM_DeleteAppTitle(u8 mediatype, u64 titleid);
/* AM_InstallFIRM()
About: Installs FIRM to NAND (firm0:/ & firm1:/) from a CXI
Note: The title must have the uniqueid: 0x00000, otherwise this will fail.
mediatype mediatype of title
titleid title id of title
*/
Result AM_InstallFIRM(u8 mediatype, u64 titleid);

View File

@ -0,0 +1,21 @@
#pragma once
/*
Requires access to "ns:s" service
*/
Result nsInit();
Result nsExit();
/* NS_LaunchTitle()
titleid TitleId of title to launch, if 0, gamecard assumed
launch_flags use if you know of any
procid ptr to where the process id of the launched title will be written to, leave a NULL, if you don't care
*/
Result NS_LaunchTitle(u64 titleid, u32 launch_flags, u32 *procid);
/* NS_RebootToTitle()
mediatype mediatype for title
titleid TitleId of title to launch
*/
Result NS_RebootToTitle(u8 mediatype, u64 titleid);

View File

@ -0,0 +1,51 @@
#pragma once
/*
Requires access to "pm:app" service
*/
Result pmInit();
Result pmExit();
/* PM_LaunchTitle()
About: Launches a title
mediatype mediatype of title
titleid TitleId of title to launch
launch_flags use if you know of any
*/
Result PM_LaunchTitle(u8 mediatype, u64 titleid);
/* PM_GetTitleExheaderFlags()
About: Writes to a buffer the launch flags (8 bytes) from a title exheader.
mediatype mediatype of title
titleid TitleId of title
out ptr to where the flags should be written to
*/
Result PM_GetTitleExheaderFlags(u8 mediatype, u64 titleid, u8* out);
/* PM_SetFIRMLaunchParams()
About: Sets the FIRM launch params from in
size size of FIRM launch params
in ptr to location of FIRM launch params
*/
Result PM_SetFIRMLaunchParams(u32 size, u8* in);
/* PM_GetFIRMLaunchParams()
About: Sets the FIRM launch params from in
size size of buffer to store FIRM launch params
out ptr to location to write FIRM launch params
*/
Result PM_GetFIRMLaunchParams(u32 size, u8* out);
/* PM_SetFIRMLaunchParams()
About: Same as PM_SetFIRMLaunchParams(), but also triggers a FIRM launch
firm_titleid_low TitleID low of firm title to launch
size size of FIRM launch params
in ptr to location of FIRM launch params
*/
Result PM_LaunchFIRMSetParams(u64 firm_titleid_low, u32 size, u8* in);

View File

@ -0,0 +1,76 @@
#pragma once
typedef enum
{
ps_CBC_ENC,
ps_CBC_DEC,
ps_CTR_ENC,
ps_CTR_DEC,
ps_CCM_ENC,
ps_CCM_DEC,
} ps_aes_algo;
typedef enum
{
ps_KEYSLOT_0D,
ps_KEYSLOT_2D,
ps_KEYSLOT_31,
ps_KEYSLOT_38,
ps_KEYSLOT_32,
ps_KEYSLOT_39,
ps_KEYSLOT_2E,
ps_KEYSLOT_INVALID,
ps_KEYSLOT_36
} ps_aes_keytypes;
/*
Requires access to "ps:ps" service
*/
Result psInit();
Result psExit();
/* PS_EncryptDecryptAes()
About: Is an interface for the AES Engine, you can only use predetermined keyslots though.
Note: Does not support AES CCM, see PS_EncryptSignDecryptVerifyAesCcm()
size size of data
in input buffer ptr
out output buffer ptr
aes_algo AES Algorithm to use, see ps_aes_algo
key_type see ps_aes_keytypes
iv ptr to the CTR/IV (This is updated before returning)
*/
Result PS_EncryptDecryptAes(u32 size, u8* in, u8* out, u32 aes_algo, u32 key_type, u8* iv);
/* PS_EncryptSignDecryptVerifyAesCcm()
About: Is an interface for the AES Engine (CCM Encrypt/Decrypt only), you can only use predetermined keyslots though.
Note: When encrypting, the output buffer size must include the MAC size, when decrypting, the input buffer size must include MAC size.
MAC: When decrypting, if the MAC is invalid, 0xC9010401 is returned. After encrypting the MAC is located at inputbufptr+(totalassocdata+totaldatasize)
in input buffer ptr
in_size size of input buffer
out output buffer ptr
out_size size of output buffer
data_len length of data to be crypted
mac_data_len length of data associated with MAC
mac_len length of MAC
aes_algo AES Algorithm to use, see ps_aes_algo
key_type see ps_aes_keytypes
nonce ptr to the nonce
*/
Result PS_EncryptSignDecryptVerifyAesCcm(u8* in, u32 in_size, u8* out, u32 out_size, u32 data_len, u32 mac_data_len, u32 mac_len, u32 aes_algo, u32 key_type, u8* nonce);
/* PS_GetLocalFriendCodeSeed()
About: Gets a 64bit console id, it's used for some key slot inits
seed ptr to where the seed is written to
*/
Result PS_GetLocalFriendCodeSeed(u64* seed);
/* PS_GetDeviceId()
About: Gets a 32bit device id, it's used for some key slot inits
device_id ptr to where the device id is written to
*/
Result PS_GetDeviceId(u32* device_id);

View File

@ -3,4 +3,8 @@
Result srvInit();
Result srvExit();
Result srvRegisterClient();
Result srvGetServiceHandle(Handle* out, char* name);
Result srvGetServiceHandle(Handle* out, const char* name);
Result srvPmInit();
Result srvRegisterProcess(u32 procid, u32 count, void *serviceaccesscontrol);
Result srvUnregisterProcess(u32 procid);

View File

@ -11,6 +11,13 @@
#define U64_MAX UINT64_MAX
typedef enum
{
mediatype_NAND,
mediatype_SDMC,
mediatype_GAMECARD,
} mediatypes_enum;
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;

View File

@ -0,0 +1,164 @@
#include <stdlib.h>
#include <3ds.h>
static Handle amHandle = 0;
Result amInit()
{
if(srvGetServiceHandle(&amHandle, "am:net") == 0)
return (Result)0;
else
return srvGetServiceHandle(&amHandle, "am:u");
}
Result amExit()
{
return svcCloseHandle(amHandle);
}
Result AM_GetTitleCount(u8 mediatype, u32 *count)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00010040;
cmdbuf[1] = mediatype;
if((ret = svcSendSyncRequest(amHandle))!=0) return ret;
*count = cmdbuf[2];
return (Result)cmdbuf[1];
}
Result AM_GetTitleList(u8 mediatype, u32 count, void *buffer)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00020082;
cmdbuf[1] = count;
cmdbuf[2] = mediatype;
cmdbuf[3] = ((count*8) << 4) | 12;
cmdbuf[4] = (u32)buffer;
if((ret = svcSendSyncRequest(amHandle))!=0) return ret;
return (Result)cmdbuf[1];
}
Result AM_GetDeviceId(u32 *deviceid)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x000A0000;
if((ret = svcSendSyncRequest(amHandle))!=0) return ret;
*deviceid = cmdbuf[3];
return (Result)cmdbuf[1];
}
Result AM_StartCiaInstall(u8 mediatype, Handle *ciahandle)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x04020040;
cmdbuf[1] = mediatype;
if((ret = svcSendSyncRequest(amHandle))!=0) return ret;
*ciahandle = cmdbuf[3];
return (Result)cmdbuf[1];
}
Result AM_StartDlpChildCiaInstall(Handle *ciahandle)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x04030000;
if((ret = svcSendSyncRequest(amHandle))!=0) return ret;
*ciahandle = cmdbuf[3];
return (Result)cmdbuf[1];
}
Result AM_CancelCIAInstall(Handle *ciahandle)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x04050002;
cmdbuf[1] = 0x10;
cmdbuf[2] = *ciahandle;
if((ret = svcSendSyncRequest(amHandle))!=0) return ret;
return (Result)cmdbuf[1];
}
Result AM_FinishCiaInstall(u8 mediatype, Handle *ciahandle)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x04040002;
cmdbuf[1] = 0x10;
cmdbuf[2] = *ciahandle;
if((ret = svcSendSyncRequest(amHandle))!=0) return ret;
return (Result)cmdbuf[1];
}
Result AM_DeleteTitle(u8 mediatype, u64 titleid)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x041000C0;
cmdbuf[1] = mediatype;
cmdbuf[2] = titleid & 0xffffffff;
cmdbuf[3] = (titleid >> 32) & 0xffffffff;
if((ret = svcSendSyncRequest(amHandle))!=0) return ret;
return (Result)cmdbuf[1];
}
Result AM_DeleteAppTitle(u8 mediatype, u64 titleid)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x000400C0;
cmdbuf[1] = mediatype;
cmdbuf[2] = titleid & 0xffffffff;
cmdbuf[3] = (titleid >> 32) & 0xffffffff;
if((ret = svcSendSyncRequest(amHandle))!=0) return ret;
return (Result)cmdbuf[1];
}
Result AM_InstallFIRM(u8 mediatype, u64 titleid)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x000400C0;
cmdbuf[1] = mediatype;
cmdbuf[2] = titleid & 0xffffffff;
cmdbuf[3] = (titleid >> 32) & 0xffffffff;
if((ret = svcSendSyncRequest(amHandle))!=0) return ret;
return (Result)cmdbuf[1];
}

View File

@ -0,0 +1,50 @@
#include <stdlib.h>
#include <3ds.h>
static Handle nsHandle;
Result nsInit()
{
return srvGetServiceHandle(&nsHandle, "ns:s");
}
Result nsExit()
{
return svcCloseHandle(nsHandle);
}
Result NS_LaunchTitle(u64 titleid, u32 launch_flags, u32 *procid)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x000200C0;
cmdbuf[1] = titleid & 0xffffffff;
cmdbuf[2] = (titleid >> 32) & 0xffffffff;
cmdbuf[3] = launch_flags;
if((ret = svcSendSyncRequest(nsHandle))!=0)return ret;
if(procid != NULL)
*procid = cmdbuf[2];
return (Result)cmdbuf[1];
}
Result NS_RebootToTitle(u8 mediatype, u64 titleid)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00100180;
cmdbuf[1] = 0x1;
cmdbuf[2] = titleid & 0xffffffff;
cmdbuf[3] = (titleid >> 32) & 0xffffffff;
cmdbuf[4] = mediatype;
cmdbuf[5] = 0x0; // reserved
cmdbuf[6] = 0x0;
if((ret = svcSendSyncRequest(nsHandle))!=0)return ret;
return (Result)cmdbuf[1];
}

View File

@ -0,0 +1,95 @@
#include <stdlib.h>
#include <3ds.h>
static Handle pmHandle;
Result pmInit()
{
return srvGetServiceHandle(&pmHandle, "pm:app");
}
Result pmExit()
{
return svcCloseHandle(pmHandle);
}
Result PM_LaunchTitle(u8 mediatype, u64 titleid, u32 launch_flags)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00010140;
cmdbuf[1] = titleid & 0xffffffff;
cmdbuf[2] = (titleid >> 32) & 0xffffffff;
cmdbuf[3] = mediatype;
cmdbuf[4] = 0x0;
cmdbuf[5] = launch_flags;
if((ret = svcSendSyncRequest(pmHandle))!=0)return ret;
return (Result)cmdbuf[1];
}
Result PM_GetTitleExheaderFlags(u8 mediatype, u64 titleid, u8* out)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00080100;
cmdbuf[1] = titleid & 0xffffffff;
cmdbuf[2] = (titleid >> 32) & 0xffffffff;
cmdbuf[3] = mediatype;
cmdbuf[4] = 0x0;
if((ret = svcSendSyncRequest(pmHandle))!=0)return ret;
memcpy(out, (u8*)(&cmdbuf[2]), 8);
return (Result)cmdbuf[1];
}
Result PM_SetFIRMLaunchParams(u32 size, u8* in)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00090042;
cmdbuf[1] = size;
cmdbuf[2] = (size << 0x4) | 0xa;
cmdbuf[3] = (u32)in;
if((ret = svcSendSyncRequest(pmHandle))!=0)return ret;
return (Result)cmdbuf[1];
}
Result PM_GetFIRMLaunchParams(u32 size, u8* out)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00070042;
cmdbuf[1] = size;
cmdbuf[2] = (size << 0x4) | 0xc;
cmdbuf[3] = (u32)out;
if((ret = svcSendSyncRequest(pmHandle))!=0)return ret;
return (Result)cmdbuf[1];
}
Result PM_LaunchFIRMSetParams(u32 firm_titleid_low, u32 size, u8* in)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00020082;
cmdbuf[1] = firm_titleid_low;
cmdbuf[2] = size;
cmdbuf[3] = (size << 0x4) | 0xa;
cmdbuf[4] = (u32)in;
if((ret = svcSendSyncRequest(pmHandle))!=0)return ret;
return (Result)cmdbuf[1];
}

View File

@ -0,0 +1,100 @@
#include <stdlib.h>
#include <3ds.h>
static Handle psHandle;
Result psInit()
{
return srvGetServiceHandle(&psHandle, "ps:ps");
}
Result psExit()
{
return svcCloseHandle(psHandle);
}
Result PS_EncryptDecryptAes(u32 size, u8* in, u8* out, u32 aes_algo, u32 key_type, u8* iv)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
u32 *_iv = (u32*)iv;
cmdbuf[0] = 0x000401C4;
cmdbuf[1] = size;
cmdbuf[2] = _iv[0];
cmdbuf[3] = _iv[1];
cmdbuf[4] = _iv[2];
cmdbuf[5] = _iv[3];
cmdbuf[6] = aes_algo;
cmdbuf[7] = key_type;
cmdbuf[8] = (size << 0x8) | 0x4;
cmdbuf[9] = (u32)in;
cmdbuf[10] = (size << 0x8) | 0x14;
cmdbuf[11] = (u32)out;
if((ret = svcSendSyncRequest(psHandle))!=0)return ret;
_iv[0] = cmdbuf[2];
_iv[1] = cmdbuf[3];
_iv[2] = cmdbuf[4];
_iv[3] = cmdbuf[5];
return (Result)cmdbuf[1];
}
Result PS_EncryptSignDecryptVerifyAesCcm(u8* in, u32 in_size, u8* out, u32 out_size, u32 data_len, u32 mac_data_len, u32 mac_len, u32 aes_algo, u32 key_type, u8* nonce)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
u32 *_nonce = (u32*)nonce;
cmdbuf[0] = 0x00050284;
cmdbuf[1] = in_size;
cmdbuf[2] = out_size;
cmdbuf[3] = mac_data_len;
cmdbuf[4] = data_len;
cmdbuf[5] = mac_len;
cmdbuf[6] = _nonce[0];
cmdbuf[7] = _nonce[1];
cmdbuf[8] = _nonce[2];
cmdbuf[9] = aes_algo;
cmdbuf[10] = key_type;
cmdbuf[8] = (in_size << 0x8) | 0x4;
cmdbuf[9] = (u32)in;
cmdbuf[10] = (out_size << 0x8) | 0x14;
cmdbuf[11] = (u32)out;
if((ret = svcSendSyncRequest(psHandle))!=0)return ret;
return (Result)cmdbuf[1];
}
Result PS_GetLocalFriendCodeSeed(u64* seed)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x000A0000;
if((ret = svcSendSyncRequest(psHandle))!=0)return ret;
*seed = (u64)cmdbuf[2] | (u64)cmdbuf[3] << 32;
return (Result)cmdbuf[1];
}
Result PS_GetDeviceId(u32* device_id)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x000B0000;
if((ret = svcSendSyncRequest(psHandle))!=0)return ret;
*device_id = cmdbuf[2];
return (Result)cmdbuf[1];
}

View File

@ -31,7 +31,6 @@ extern service_list_t* __service_ptr;
static Handle g_srv_handle = 0;
static int __name_cmp(const char* a, const char* b) {
u32 i;
@ -45,7 +44,7 @@ static int __name_cmp(const char* a, const char* b) {
return 0;
}
Handle __get_handle_from_list(char* name) {
Handle __get_handle_from_list(const char* name) {
if((u32)__service_ptr == 0)
return 0;
@ -83,18 +82,22 @@ Result srvExit()
Result srvRegisterClient()
{
Result rc = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x10002;
cmdbuf[1] = 0x20;
Result rc;
if((rc = svcSendSyncRequest(g_srv_handle)))return rc;
return cmdbuf[1];
}
Result srvGetServiceHandle(Handle* out, char* name)
Result srvGetServiceHandle(Handle* out, const char* name)
{
Result rc = 0;
/* Look in service-list given to us by loader. If we find find a match,
we return it. */
Handle h = __get_handle_from_list(name);
@ -110,9 +113,54 @@ Result srvGetServiceHandle(Handle* out, char* name)
cmdbuf[3] = strlen(name);
cmdbuf[4] = 0x0;
Result rc;
if((rc = svcSendSyncRequest(g_srv_handle)))return rc;
*out = cmdbuf[3];
return cmdbuf[1];
}
// Old srv:pm interface, will only work on systems where srv:pm was a port (<7.X)
Result srvPmInit()
{
Result rc = 0;
if((rc = svcConnectToPort(&g_srv_handle, "srv:pm")))return rc;
if((rc = srvRegisterClient())) {
svcCloseHandle(g_srv_handle);
g_srv_handle = 0;
}
return rc;
}
Result srvRegisterProcess(u32 procid, u32 count, void *serviceaccesscontrol)
{
Result rc = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x04030082; // <7.x
cmdbuf[1] = procid;
cmdbuf[2] = count;
cmdbuf[3] = (count << 16) | 2;
cmdbuf[4] = (u32)serviceaccesscontrol;
if((rc = svcSendSyncRequest(g_srv_handle))) return rc;
return cmdbuf[1];
}
Result srvUnregisterProcess(u32 procid)
{
Result rc = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x04040040; // <7.x
cmdbuf[1] = procid;
if((rc = svcSendSyncRequest(g_srv_handle))) return rc;
return cmdbuf[1];
}