mirror of
https://github.com/switchbrew/libnx.git
synced 2025-07-05 19:02:14 +02:00
Merge branch 'master' of https://github.com/switchbrew/libnx
This commit is contained in:
commit
39e205973c
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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.
|
||||||
|
@ -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) {
|
||||||
|
@ -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)) {
|
||||||
|
@ -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))
|
||||||
|
@ -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,6 +264,9 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struc
|
|||||||
++numfds;
|
++numfds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(numfds <= __nx_pollfd_sb_max_fds)
|
||||||
|
pollinfo = (struct pollfd *)alloca(numfds * sizeof(struct pollfd));
|
||||||
|
else
|
||||||
pollinfo = (struct pollfd *)malloc(numfds * sizeof(struct pollfd));
|
pollinfo = (struct pollfd *)malloc(numfds * sizeof(struct pollfd));
|
||||||
if(pollinfo == NULL) {
|
if(pollinfo == NULL) {
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
@ -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
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if(numfds > __nx_pollfd_sb_max_fds)
|
||||||
free(pollinfo);
|
free(pollinfo);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,6 +352,9 @@ int poll(struct pollfd *fds, nfds_t nfds, int timeout) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(nfds <= __nx_pollfd_sb_max_fds)
|
||||||
|
fds2 = (struct pollfd *)alloca(nfds * sizeof(struct pollfd));
|
||||||
|
else
|
||||||
fds2 = (struct pollfd *)malloc(nfds * sizeof(struct pollfd));
|
fds2 = (struct pollfd *)malloc(nfds * sizeof(struct pollfd));
|
||||||
if(fds2 == NULL) {
|
if(fds2 == NULL) {
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
@ -352,12 +364,16 @@ 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;
|
||||||
|
if(fds[i].fd < 0) {
|
||||||
|
fds2[i].fd = -1;
|
||||||
|
} else {
|
||||||
fds2[i].fd = _socketGetFd(fds[i].fd);
|
fds2[i].fd = _socketGetFd(fds[i].fd);
|
||||||
if(fds2[i].fd == -1) {
|
if(fds2[i].fd == -1) {
|
||||||
ret = -1;
|
ret = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(ret != -1)
|
if(ret != -1)
|
||||||
ret = _socketParseBsdResult(NULL, bsdPoll(fds2, nfds, timeout));
|
ret = _socketParseBsdResult(NULL, bsdPoll(fds2, nfds, timeout));
|
||||||
@ -368,6 +384,7 @@ int poll(struct pollfd *fds, nfds_t nfds, int timeout) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(nfds > __nx_pollfd_sb_max_fds)
|
||||||
free(fds2);
|
free(fds2);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -22,6 +22,10 @@ Result fsldrInitialize(void) {
|
|||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user