This commit is contained in:
Tate Haga 2018-10-16 19:41:38 -04:00
commit 39e205973c
9 changed files with 402 additions and 236 deletions

View File

@ -63,6 +63,13 @@ typedef struct {
u32 Pad[2]; u32 Pad[2];
} DomainMessageHeader; } DomainMessageHeader;
/// IPC domain response header.
typedef struct {
u32 NumObjectIds;
u32 Pad[3];
} DomainResponseHeader;
typedef struct { typedef struct {
size_t NumSend; // A size_t NumSend; // A
size_t NumRecv; // B size_t NumRecv; // B
@ -363,12 +370,16 @@ typedef struct {
Handle Handles[IPC_MAX_OBJECTS]; ///< Handles. Handle Handles[IPC_MAX_OBJECTS]; ///< Handles.
bool WasHandleCopied[IPC_MAX_OBJECTS]; ///< true if the handle was moved, false if it was copied. bool WasHandleCopied[IPC_MAX_OBJECTS]; ///< true if the handle was moved, false if it was copied.
bool IsDomainMessage; ///< true if the the message is a Domain message. bool IsDomainRequest; ///< true if the the message is a Domain message.
DomainMessageType MessageType; ///< Type of the domain message. DomainMessageType InMessageType; ///< Type of the domain message.
u32 MessageLength; ///< Size of rawdata (for domain messages). u32 InMessageLength; ///< Size of rawdata (for domain messages).
u32 ThisObjectId; ///< Object ID to call the command on (for domain messages). u32 InThisObjectId; ///< Object ID to call the command on (for domain messages).
size_t NumObjectIds; ///< Number of object IDs (for domain messages). size_t InNumObjectIds; ///< Number of object IDs (for domain messages).
u32 ObjectIds[IPC_MAX_OBJECTS]; ///< Object IDs (for domain messages). u32 InObjectIds[IPC_MAX_OBJECTS]; ///< Object IDs (for domain messages).
bool IsDomainResponse; ///< true if the the message is a Domain response.
size_t OutNumObjectIds; ///< Number of object IDs (for domain responses).
u32 OutObjectIds[IPC_MAX_OBJECTS]; ///< Object IDs (for domain responses).
size_t NumBuffers; ///< Number of buffers in the response. size_t NumBuffers; ///< Number of buffers in the response.
void* Buffers[IPC_MAX_BUFFERS]; ///< Pointers to the buffers. void* Buffers[IPC_MAX_BUFFERS]; ///< Pointers to the buffers.
@ -399,7 +410,8 @@ static inline Result ipcParse(IpcParsedCommand* r) {
u32 ctrl1 = *buf++; u32 ctrl1 = *buf++;
size_t i; size_t i;
r->IsDomainMessage = false; r->IsDomainRequest = false;
r->IsDomainResponse = false;
r->CommandType = (IpcCommandType) (ctrl0 & 0xffff); r->CommandType = (IpcCommandType) (ctrl0 & 0xffff);
r->HasPid = false; r->HasPid = false;
@ -656,11 +668,11 @@ static inline void* ipcPrepareHeaderForDomain(IpcCommand* cmd, size_t sizeof_raw
} }
/** /**
* @brief Parse an IPC command response into an IPC parsed command structure (domain version). * @brief Parse an IPC command request into an IPC parsed command structure (domain version).
* @param IPC parsed command structure to fill in. * @param IPC parsed command structure to fill in.
* @return Result code. * @return Result code.
*/ */
static inline Result ipcParseForDomain(IpcParsedCommand* r) { static inline Result ipcParseDomainRequest(IpcParsedCommand* r) {
Result rc = ipcParse(r); Result rc = ipcParse(r);
DomainMessageHeader *hdr; DomainMessageHeader *hdr;
u32 *object_ids; u32 *object_ids;
@ -671,22 +683,51 @@ static inline Result ipcParseForDomain(IpcParsedCommand* r) {
object_ids = (u32*)(((uintptr_t) hdr) + sizeof(DomainMessageHeader) + hdr->Length); object_ids = (u32*)(((uintptr_t) hdr) + sizeof(DomainMessageHeader) + hdr->Length);
r->Raw = (void*)(((uintptr_t) r->Raw) + sizeof(DomainMessageHeader)); r->Raw = (void*)(((uintptr_t) r->Raw) + sizeof(DomainMessageHeader));
r->IsDomainMessage = true; r->IsDomainRequest = true;
r->MessageType = (DomainMessageType)(hdr->Type); r->InMessageType = (DomainMessageType)(hdr->Type);
switch (r->MessageType) { switch (r->InMessageType) {
case DomainMessageType_SendMessage: case DomainMessageType_SendMessage:
case DomainMessageType_Close: case DomainMessageType_Close:
break; break;
default: default:
return MAKERESULT(Module_Libnx, LibnxError_DomainMessageUnknownType); return MAKERESULT(Module_Libnx, LibnxError_DomainMessageUnknownType);
} }
r->ThisObjectId = hdr->ThisObjectId;
r->NumObjectIds = hdr->NumObjectIds > 8 ? 8 : hdr->NumObjectIds; r->InThisObjectId = hdr->ThisObjectId;
if ((uintptr_t)object_ids + sizeof(u32) * r->NumObjectIds - (uintptr_t)armGetTls() >= 0x100) { r->InNumObjectIds = hdr->NumObjectIds > 8 ? 8 : hdr->NumObjectIds;
if ((uintptr_t)object_ids + sizeof(u32) * r->InNumObjectIds - (uintptr_t)armGetTls() >= 0x100) {
return MAKERESULT(Module_Libnx, LibnxError_DomainMessageTooManyObjectIds); return MAKERESULT(Module_Libnx, LibnxError_DomainMessageTooManyObjectIds);
} }
for(size_t i = 0; i < r->NumObjectIds; i++) for(size_t i = 0; i < r->InNumObjectIds; i++)
r->ObjectIds[i] = object_ids[i]; r->InObjectIds[i] = object_ids[i];
return rc;
}
/**
* @brief Parse an IPC command response into an IPC parsed command structure (domain version).
* @param IPC parsed command structure to fill in.
* @return Result code.
*/
static inline Result ipcParseDomainResponse(IpcParsedCommand* r, size_t sizeof_raw) {
Result rc = ipcParse(r);
DomainResponseHeader *hdr;
u32 *object_ids;
if(R_FAILED(rc))
return rc;
hdr = (DomainResponseHeader*) r->Raw;
r->Raw = (void*)(((uintptr_t) r->Raw) + sizeof(DomainResponseHeader));
object_ids = (u32*)((((uintptr_t) r->Raw) + sizeof_raw + 3) & ~3);
r->IsDomainResponse = true;
r->OutNumObjectIds = hdr->NumObjectIds > 8 ? 8 : hdr->NumObjectIds;
if ((uintptr_t)object_ids + sizeof(u32) * r->OutNumObjectIds - (uintptr_t)armGetTls() >= 0x100) {
return MAKERESULT(Module_Libnx, LibnxError_DomainMessageTooManyObjectIds);
}
for(size_t i = 0; i < r->OutNumObjectIds; i++)
r->OutObjectIds[i] = object_ids[i];
return rc; return rc;
} }
@ -704,7 +745,7 @@ static inline Result ipcCloseObjectById(Handle session, u32 object_id) {
ipcInitialize(&c); ipcInitialize(&c);
hdr = (DomainMessageHeader*)ipcPrepareHeader(&c, sizeof(DomainMessageHeader)); hdr = (DomainMessageHeader*)ipcPrepareHeader(&c, sizeof(DomainMessageHeader));
hdr->Type = 2; hdr->Type = DomainMessageType_Close;
hdr->NumObjectIds = 0; hdr->NumObjectIds = 0;
hdr->Length = 0; hdr->Length = 0;
hdr->ThisObjectId = object_id; hdr->ThisObjectId = object_id;

View File

@ -13,14 +13,15 @@ typedef struct NvBuffer {
NvAddressSpace* addr_space; NvAddressSpace* addr_space;
NvKind kind; NvKind kind;
bool has_init; bool has_init;
bool is_cacheable; bool is_cpu_cacheable;
bool is_gpu_cacheable;
} NvBuffer; } NvBuffer;
Result nvBufferInit(void); Result nvBufferInit(void);
u32 nvBufferGetNvmapFd(void); u32 nvBufferGetNvmapFd(void);
void nvBufferExit(void); void nvBufferExit(void);
Result nvBufferCreate(NvBuffer* m, size_t size, u32 align, bool is_cacheable, NvKind kind, NvAddressSpace* as); Result nvBufferCreate(NvBuffer* m, size_t size, u32 align, bool is_cpu_cacheable, bool is_gpu_cacheable, NvKind kind, NvAddressSpace* as);
void nvBufferFree(NvBuffer* m); void nvBufferFree(NvBuffer* m);
void* nvBufferGetCpuAddr(NvBuffer* m); void* nvBufferGetCpuAddr(NvBuffer* m);

View File

@ -16,7 +16,7 @@ typedef enum {
ServiceType_Normal, ///< Normal service. ServiceType_Normal, ///< Normal service.
ServiceType_Domain, ///< Domain. ServiceType_Domain, ///< Domain.
ServiceType_DomainSubservice, ///< Domain subservice; ServiceType_DomainSubservice, ///< Domain subservice;
ServiceType_Override ///< Service overriden in the homebrew environment. ServiceType_Override, ///< Service overriden in the homebrew environment.
} ServiceType; } ServiceType;
/// Service object structure. /// Service object structure.
@ -113,15 +113,39 @@ static inline void serviceCreateDomainSubservice(Service* s, Service* parent, u3
s->object_id = object_id; s->object_id = object_id;
} }
/**
* @brief Creates a subservice object from a parent service.
* @param[out] s Service object.
* @param[in] parent Parent service, possibly a domain or domain subservice.
* @param[in] r Parsed IPC command containing handles/object IDs to create subservice from.
* @param[in] i The index of the handle/object ID to create subservice from.
*/
static inline void serviceCreateSubservice(Service* s, Service* parent, IpcParsedCommand* r, int i) {
if (r->IsDomainResponse) {
return serviceCreateDomainSubservice(s, parent, r->OutObjectIds[i]);
} else {
return serviceCreate(s, r->Handles[i]);
}
}
/** /**
* @brief Converts a regular service to a domain. * @brief Converts a regular service to a domain.
* @param[in] s Service object. * @param[in] s Service object.
* @return Result code. * @return Result code.
*/ */
static inline Result serviceConvertToDomain(Service* s) { static inline Result serviceConvertToDomain(Service* s) {
Result rc = ipcConvertSessionToDomain(s->handle, &s->object_id); Result rc = 0;
if(R_SUCCEEDED(rc)) if (serviceIsOverride(s)) {
rc = ipcCloneSession(s->handle, 1, &s->handle);
if (R_FAILED(rc)) {
return rc;
}
s->type = ServiceType_Normal;
}
rc = ipcConvertSessionToDomain(s->handle, &s->object_id);
if (R_SUCCEEDED(rc)) {
s->type = ServiceType_Domain; s->type = ServiceType_Domain;
}
return rc; return rc;
} }
@ -153,6 +177,37 @@ static inline void serviceClose(Service* s) {
s->type = ServiceType_Uninitialized; s->type = ServiceType_Uninitialized;
} }
/**
* @brief Prepares the header of an IPC command structure for a service.
* @param s Service to prepare message header for
* @param cmd IPC command structure.
* @param sizeof_raw Size in bytes of the raw data structure to embed inside the IPC request
* @return Pointer to the raw embedded data structure in the request, ready to be filled out.
*/
static inline void* serviceIpcPrepareHeader(Service* s, IpcCommand* cmd, size_t sizeof_raw) {
if (serviceIsDomain(s) || serviceIsDomainSubservice(s)) {
return ipcPrepareHeaderForDomain(cmd, sizeof_raw, serviceGetObjectId(s));
} else {
return ipcPrepareHeader(cmd, sizeof_raw);
}
}
/**
* @brief Parse an IPC command response into an IPC parsed command structure for a service.
* @param s Service to prepare message header for
* @param r IPC parsed command structure to fill in.
* @return Result code.
*/
static inline Result serviceIpcParse(Service* s, IpcParsedCommand* r, size_t sizeof_raw) {
if (serviceIsDomain(s) || serviceIsDomainSubservice(s)) {
return ipcParseDomainResponse(r, sizeof_raw);
} else {
return ipcParse(r);
}
}
/** /**
* @brief Initializes SM. * @brief Initializes SM.
* @return Result code. * @return Result code.

View File

@ -43,7 +43,7 @@ u32 nvBufferGetNvmapFd(void) {
} }
Result nvBufferCreate( Result nvBufferCreate(
NvBuffer* m, size_t size, u32 align, bool is_cacheable, NvKind kind, NvBuffer* m, size_t size, u32 align, bool is_cpu_cacheable, bool is_gpu_cacheable, NvKind kind,
NvAddressSpace* as) NvAddressSpace* as)
{ {
Result rc; Result rc;
@ -51,7 +51,8 @@ Result nvBufferCreate(
size = (size + align - 1) & ~(align - 1); size = (size + align - 1) & ~(align - 1);
m->has_init = true; m->has_init = true;
m->is_cacheable = is_cacheable; m->is_cpu_cacheable = is_cpu_cacheable;
m->is_gpu_cacheable = is_gpu_cacheable;
m->size = size; m->size = size;
m->fd = -1; m->fd = -1;
m->cpu_addr = memalign(align, size); m->cpu_addr = memalign(align, size);
@ -67,16 +68,16 @@ Result nvBufferCreate(
if (R_SUCCEEDED(rc)) if (R_SUCCEEDED(rc))
rc = nvioctlNvmap_Alloc(g_nvmap_fd, m->fd, rc = nvioctlNvmap_Alloc(g_nvmap_fd, m->fd,
0, is_cacheable ? 1 : 0, align, kind, m->cpu_addr); 0, is_cpu_cacheable ? 1 : 0, align, kind, m->cpu_addr);
if (R_SUCCEEDED(rc) && !is_cacheable) { if (R_SUCCEEDED(rc) && !is_cpu_cacheable) {
armDCacheFlush(m->cpu_addr, m->size); armDCacheFlush(m->cpu_addr, m->size);
svcSetMemoryAttribute(m->cpu_addr, m->size, 8, 8); svcSetMemoryAttribute(m->cpu_addr, m->size, 8, 8);
} }
if (R_SUCCEEDED(rc)) if (R_SUCCEEDED(rc))
rc = nvAddressSpaceMapBuffer(as, m->fd, rc = nvAddressSpaceMapBuffer(as, m->fd,
is_cacheable ? NvMapBufferFlags_IsCacheable : 0, NvKind_Pitch, &m->gpu_addr); is_gpu_cacheable ? NvMapBufferFlags_IsCacheable : 0, NvKind_Pitch, &m->gpu_addr);
if (R_FAILED(rc)) if (R_FAILED(rc))
nvBufferFree(m); nvBufferFree(m);
@ -105,7 +106,7 @@ void nvBufferFree(NvBuffer* m)
} }
if (m->cpu_addr) { if (m->cpu_addr) {
if (!m->is_cacheable) if (!m->is_cpu_cacheable)
svcSetMemoryAttribute(m->cpu_addr, m->size, 8, 0); svcSetMemoryAttribute(m->cpu_addr, m->size, 8, 0);
free(m->cpu_addr); free(m->cpu_addr);
@ -125,7 +126,7 @@ iova_t nvBufferGetGpuAddr(NvBuffer* m) {
Result nvBufferMapAsTexture(NvBuffer* m, NvKind kind) { Result nvBufferMapAsTexture(NvBuffer* m, NvKind kind) {
return nvAddressSpaceMapBuffer(m->addr_space, m->fd, return nvAddressSpaceMapBuffer(m->addr_space, m->fd,
m->is_cacheable ? NvMapBufferFlags_IsCacheable : 0, kind, &m->gpu_addr_texture); m->is_gpu_cacheable ? NvMapBufferFlags_IsCacheable : 0, kind, &m->gpu_addr_texture);
} }
iova_t nvBufferGetGpuAddrTexture(NvBuffer* m) { iova_t nvBufferGetGpuAddrTexture(NvBuffer* m) {

View File

@ -22,7 +22,7 @@ Result nvCmdListCreate(NvCmdList* c, NvGpu* parent, size_t max_cmds)
Result rc; Result rc;
rc = nvBufferCreate( rc = nvBufferCreate(
&c->buffer, max_cmds * 4, 0x1000, NvKind_Pitch, false, &c->buffer, max_cmds * 4, 0x1000, NvKind_Pitch, false, false,
&parent->addr_space); &parent->addr_space);
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {

View File

@ -25,7 +25,7 @@ Result nvZcullContextCreate(NvZcullContext* z, NvGpu* parent)
z->parent = parent; z->parent = parent;
rc = nvBufferCreate( rc = nvBufferCreate(
&z->ctx_buf, nvInfoGetZcullCtxSize(), 0x20000, NvKind_Pitch, true, &z->ctx_buf, nvInfoGetZcullCtxSize(), 0x20000, NvKind_Pitch, false, true,
&parent->addr_space); &parent->addr_space);
if (R_SUCCEEDED(rc)) if (R_SUCCEEDED(rc))

View File

@ -4,6 +4,7 @@
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
#include <malloc.h> #include <malloc.h>
#include <alloca.h>
#include <sys/iosupport.h> #include <sys/iosupport.h>
#include <sys/select.h> #include <sys/select.h>
@ -24,6 +25,8 @@
#include "services/nifm.h" #include "services/nifm.h"
#include "result.h" #include "result.h"
__attribute__((weak)) size_t __nx_pollfd_sb_max_fds = 64;
int _convert_errno(int bsdErrno); int _convert_errno(int bsdErrno);
__thread int h_errno; __thread int h_errno;
@ -261,7 +264,10 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struc
++numfds; ++numfds;
} }
pollinfo = (struct pollfd*)malloc(numfds * sizeof(struct pollfd)); if(numfds <= __nx_pollfd_sb_max_fds)
pollinfo = (struct pollfd *)alloca(numfds * sizeof(struct pollfd));
else
pollinfo = (struct pollfd *)malloc(numfds * sizeof(struct pollfd));
if(pollinfo == NULL) { if(pollinfo == NULL) {
errno = ENOMEM; errno = ENOMEM;
return -1; return -1;
@ -271,7 +277,11 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struc
if((readfds && FD_ISSET(i, readfds)) if((readfds && FD_ISSET(i, readfds))
|| (writefds && FD_ISSET(i, writefds)) || (writefds && FD_ISSET(i, writefds))
|| (exceptfds && FD_ISSET(i, exceptfds))) { || (exceptfds && FD_ISSET(i, exceptfds))) {
pollinfo[j].fd = i; pollinfo[j].fd = _socketGetFd(i);
if(pollinfo[j].fd == -1) {
rc = -1;
goto cleanup;
}
pollinfo[j].events = 0; pollinfo[j].events = 0;
pollinfo[j].revents = 0; pollinfo[j].revents = 0;
@ -285,14 +295,12 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struc
} }
if(timeout) if(timeout)
rc = poll(pollinfo, numfds, timeout->tv_sec*1000 + timeout->tv_usec/1000); rc = _socketParseBsdResult(NULL, bsdPoll(pollinfo, numfds, timeout->tv_sec*1000 + timeout->tv_usec/1000));
else else
rc = poll(pollinfo, numfds, -1); rc = _socketParseBsdResult(NULL, bsdPoll(pollinfo, numfds, -1));
if(rc < 0) { if(rc < 0)
free(pollinfo); goto cleanup;
return rc;
}
for(i = 0, j = 0, rc = 0; i < nfds; ++i) { for(i = 0, j = 0, rc = 0; i < nfds; ++i) {
found = 0; found = 0;
@ -328,8 +336,9 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struc
} }
} }
free(pollinfo); cleanup:
if(numfds > __nx_pollfd_sb_max_fds)
free(pollinfo);
return rc; return rc;
} }
@ -343,7 +352,10 @@ int poll(struct pollfd *fds, nfds_t nfds, int timeout) {
return -1; return -1;
} }
fds2 = (struct pollfd *)malloc(nfds * sizeof(struct pollfd)); if(nfds <= __nx_pollfd_sb_max_fds)
fds2 = (struct pollfd *)alloca(nfds * sizeof(struct pollfd));
else
fds2 = (struct pollfd *)malloc(nfds * sizeof(struct pollfd));
if(fds2 == NULL) { if(fds2 == NULL) {
errno = ENOMEM; errno = ENOMEM;
return -1; return -1;
@ -352,10 +364,14 @@ int poll(struct pollfd *fds, nfds_t nfds, int timeout) {
for(nfds_t i = 0; i < nfds; i++) { for(nfds_t i = 0; i < nfds; i++) {
fds2[i].events = fds[i].events; fds2[i].events = fds[i].events;
fds2[i].revents = fds[i].revents; fds2[i].revents = fds[i].revents;
fds2[i].fd = _socketGetFd(fds[i].fd); if(fds[i].fd < 0) {
if(fds2[i].fd == -1) { fds2[i].fd = -1;
ret = -1; } else {
break; fds2[i].fd = _socketGetFd(fds[i].fd);
if(fds2[i].fd == -1) {
ret = -1;
break;
}
} }
} }
@ -368,7 +384,8 @@ int poll(struct pollfd *fds, nfds_t nfds, int timeout) {
} }
} }
free(fds2); if(nfds > __nx_pollfd_sb_max_fds)
free(fds2);
return ret; return ret;
} }
@ -1617,4 +1634,4 @@ struct servent *getservbyport(int a, const char *s) { (void)a; (void)s; h_errno
struct servent *getservent(void) { h_errno = NO_RECOVERY; errno = ENOSYS; return NULL; } struct servent *getservent(void) { h_errno = NO_RECOVERY; errno = ENOSYS; return NULL; }
void sethostent(int a) { (void)a;} void sethostent(int a) { (void)a;}
void setnetent(int a) { (void)a;} void setnetent(int a) { (void)a;}
void setprotoent(int a) { (void)a; } void setprotoent(int a) { (void)a; }

File diff suppressed because it is too large Load Diff

View File

@ -21,6 +21,10 @@ Result fsldrInitialize(void) {
return 0; return 0;
Result rc = smGetService(&g_fsldrSrv, "fsp-ldr"); Result rc = smGetService(&g_fsldrSrv, "fsp-ldr");
if (R_SUCCEEDED(rc)) {
rc = serviceConvertToDomain(&g_fsldrSrv);
}
if (R_SUCCEEDED(rc) && kernelAbove400()) { if (R_SUCCEEDED(rc) && kernelAbove400()) {
rc = fsldrSetCurrentProcess(); rc = fsldrSetCurrentProcess();
@ -47,7 +51,7 @@ Result fsldrOpenCodeFileSystem(u64 tid, const char *path, FsFileSystem* out) {
u64 tid; u64 tid;
} *raw; } *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw)); raw = serviceIpcPrepareHeader(&g_fsldrSrv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC; raw->magic = SFCI_MAGIC;
raw->cmd_id = 0; raw->cmd_id = 0;
raw->tid = tid; raw->tid = tid;
@ -57,17 +61,18 @@ Result fsldrOpenCodeFileSystem(u64 tid, const char *path, FsFileSystem* out) {
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
IpcParsedCommand r; IpcParsedCommand r;
ipcParse(&r);
struct { struct {
u64 magic; u64 magic;
u64 result; u64 result;
} *resp = r.Raw; } *resp;
serviceIpcParse(&g_fsldrSrv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result; rc = resp->result;
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
serviceCreate(&out->s, r.Handles[0]); serviceCreateSubservice(&out->s, &g_fsldrSrv, &r, 0);
} }
} }
@ -84,7 +89,7 @@ Result fsldrIsArchivedProgram(u64 pid, bool *out) {
u64 pid; u64 pid;
} *raw; } *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw)); raw = serviceIpcPrepareHeader(&g_fsldrSrv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC; raw->magic = SFCI_MAGIC;
raw->cmd_id = 1; raw->cmd_id = 1;
raw->pid = pid; raw->pid = pid;
@ -93,13 +98,14 @@ Result fsldrIsArchivedProgram(u64 pid, bool *out) {
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
IpcParsedCommand r; IpcParsedCommand r;
ipcParse(&r);
struct { struct {
u64 magic; u64 magic;
u64 result; u64 result;
u8 is_archived; u8 is_archived;
} *resp = r.Raw; } *resp;
serviceIpcParse(&g_fsldrSrv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result; rc = resp->result;
@ -122,7 +128,7 @@ Result fsldrSetCurrentProcess(void) {
u64 unk; u64 unk;
} *raw; } *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw)); raw = serviceIpcPrepareHeader(&g_fsldrSrv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC; raw->magic = SFCI_MAGIC;
raw->cmd_id = 2; raw->cmd_id = 2;
@ -132,12 +138,13 @@ Result fsldrSetCurrentProcess(void) {
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
IpcParsedCommand r; IpcParsedCommand r;
ipcParse(&r);
struct { struct {
u64 magic; u64 magic;
u64 result; u64 result;
} *resp = r.Raw; } *resp;
serviceIpcParse(&g_fsldrSrv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result; rc = resp->result;
} }