Example #1
0
static void swkbdMessageCallback(void* user, NS_APPID sender, void* msg, size_t msgsize)
{
	SwkbdExtra* extra = (SwkbdExtra*)user;
	SwkbdState* swkbd = (SwkbdState*)msg;

	if (sender != APPID_SOFTWARE_KEYBOARD || msgsize != sizeof(SwkbdState))
		return;

	u16* text16 = (u16*)(swkbdSharedMem + swkbd->text_offset);
	ssize_t units = utf16_to_utf8(NULL, text16, 0);
	if (units < 0) svcBreak(USERBREAK_PANIC); // Shouldn't happen.
	char* text8 = (char*)malloc(units+1);
	if (!text8) svcBreak(USERBREAK_PANIC); // Shouldn't happen.
	swkbdConvertToUTF8(text8, text16, units);

	const char* retmsg = NULL;
	swkbd->callback_result = extra->callback(extra->callback_user, &retmsg, text8, units);
	if (swkbd->callback_result > SWKBD_CALLBACK_OK)
		swkbdConvertToUTF16(swkbd->callback_msg, retmsg, SWKBD_MAX_CALLBACK_MSG_LEN);
	else
		swkbd->callback_msg[0] = 0;

	free(text8);
	APT_SendParameter(envGetAptAppId(), sender, APTCMD_MESSAGE, swkbd, sizeof(*swkbd), 0);
}
Example #2
0
static inline void initPXI(void)
{
    Result res;

    Handle handles[2] = {0};

    PXIReset();

    if(PXISyncInterrupt != 0) svcBreak(USERBREAK_PANIC); //0xE0A0183B
    assertSuccess(svcCreateEvent(&PXISyncInterrupt, RESET_ONESHOT));

    if(PXITransferMutex != 0) svcBreak(USERBREAK_PANIC); //0xE0A0183B
    assertSuccess(svcCreateMutex(&PXITransferMutex, false));

    assertSuccess(svcCreateEvent(&handles[0], RESET_ONESHOT)); //receive FIFO not empty
    assertSuccess(svcCreateEvent(&handles[1], RESET_ONESHOT)); //send FIFO empty
    assertSuccess(bindPXIInterrupts(&PXISyncInterrupt, &handles[0], &handles[1]));

    s32 handleIndex;
    do
    {
        while(!PXIIsSendFIFOFull()) PXISendWord(0);

        res = assertSuccess(svcWaitSynchronization(handles[0], 0LL));
        if(R_DESCRIPTION(res) == RD_TIMEOUT)
            assertSuccess(svcWaitSynchronizationN(&handleIndex, handles, 2, false, -1LL));
        else
            handleIndex = 0;
    } while(handleIndex != 0);



    unbindPXIInterrupts(NULL, &handles[0], &handles[1]);

    PXISendByte(1);
    while(PXIReceiveByte() < 1);

    while (!PXIIsReceiveFIFOEmpty())
        PXIReceiveWord();

    PXISendByte(2);
    while(PXIReceiveByte() < 2);

    svcCloseHandle(handles[0]);
    svcCloseHandle(handles[1]);
}
Example #3
0
int main(void)
{
    Handle handles[10] = {0}; //notification handle + service handles
    MyThread receiverThread = {0}, senderThread = {0}, PXISRV11HandlerThread = {0};

    for(u32 i = 0; i < 9; i++)
        assertSuccess(srvRegisterService(handles + 1 + i, serviceNames[i], 1));

    assertSuccess(MyThread_Create(&receiverThread, receiver, receiverStack, THREAD_STACK_SIZE, 0x2D, -2));
    assertSuccess(MyThread_Create(&senderThread, sender, senderStack, THREAD_STACK_SIZE, 0x2D, -2));
    assertSuccess(MyThread_Create(&PXISRV11HandlerThread, PXISRV11Handler, PXISRV11HandlerStack, THREAD_STACK_SIZE, 0x2D, -2));

    assertSuccess(srvEnableNotification(&handles[0]));

    while(!shouldTerminate)
    {
        s32 index = 0;
        assertSuccess(svcWaitSynchronizationN(&index, handles, 10, false, -1LL));

        if(index == 0)
        {
            u32 notificationId;
            assertSuccess(srvReceiveNotification(&notificationId));
            if(notificationId == 0x100) shouldTerminate = true;
        }

        else
        {
            Handle session = 0;
            SessionData *data = &sessionManager.sessionData[index - 1];
            assertSuccess(svcAcceptSession(&session, handles[index]));

            RecursiveLock_Lock(&sessionManager.senderLock);
            if(data->handle != 0)
                svcBreak(USERBREAK_PANIC);

            data->handle = session;
            assertSuccess(svcSignalEvent(sessionManager.sendAllBuffersToArm9Event));

            RecursiveLock_Unlock(&sessionManager.senderLock);
        }

    }

    u32 PXIMC_OnPXITerminate = 0x10000; //TODO: see if this is correct
    sessionManager.sessionData[0].state = STATE_SENT_TO_ARM9;
    sendPXICmdbuf(NULL, 0, &PXIMC_OnPXITerminate);

    assertSuccess(MyThread_Join(&receiverThread, -1LL));
    assertSuccess(MyThread_Join(&senderThread, -1LL));
    assertSuccess(MyThread_Join(&PXISRV11HandlerThread, -1LL));

    for(u32 i = 0; i < 10; i++)
        svcCloseHandle(handles[i]);

    return 0;
}
Example #4
0
static struct _reent* __ctru_get_reent()
{
	ThreadVars* tv = getThreadVars();
	if (tv->magic != THREADVARS_MAGIC)
	{
		svcBreak(USERBREAK_PANIC);
		for (;;);
	}
	return tv->reent;
}
Example #5
0
// this is called before main
void __appInit()
{
    assertSuccess(svcCreateEvent(&terminationRequestedEvent, RESET_STICKY));

    assertSuccess(svcCreateEvent(&sessionManager.sendAllBuffersToArm9Event, RESET_ONESHOT));
    assertSuccess(svcCreateSemaphore(&sessionManager.replySemaphore, 0, 9));
    assertSuccess(svcCreateEvent(&sessionManager.PXISRV11CommandReceivedEvent, RESET_ONESHOT));
    assertSuccess(svcCreateEvent(&sessionManager.PXISRV11ReplySentEvent, RESET_ONESHOT));    
    initPXI();

    for(Result res = 0xD88007FA; res == (Result)0xD88007FA; svcSleepThread(500 * 1000LL))
    {
        res = srvInit();
        if(R_FAILED(res) && res != (Result)0xD88007FA)
            svcBreak(USERBREAK_PANIC);
    }
}
Example #6
0
Result fsldrInit(void)
{
  Result ret = 0;

  if (AtomicPostIncrement(&fsldrRefCount)) return 0;

  ret = srvSysGetServiceHandle(&fsldrHandle, "fs:LDR");
  if (R_SUCCEEDED(ret))
  {
    fsldrPatchPermissions();
    ret = FSLDR_InitializeWithSdkVersion(fsldrHandle, SDK_VERSION);
    ret = FSLDR_SetPriority(0);
    if (R_FAILED(ret)) svcBreak(USERBREAK_ASSERT);
  }
  else
  {
    AtomicDecrement(&fsldrRefCount);
  }

  return ret;
}
Example #7
0
Result
srvSysExit()
{
    Result rc;
    RecursiveLock_Lock(&initLock);

    if (srvRefCount > 1) {
        srvRefCount--;
        RecursiveLock_Unlock(&initLock);
        return MAKERESULT(RL_INFO, RS_NOP, 25, RD_BUSY);
    }

    if (srvHandle != 0)
        svcCloseHandle(srvHandle);
    else
        svcBreak(USERBREAK_ASSERT);
    rc = (Result)srvHandle; // yeah, I think this is a benign bug
    srvHandle = 0;
    srvRefCount--;
    RecursiveLock_Unlock(&initLock);
    return rc;
}
Example #8
0
void __attribute__((weak)) __system_allocateHeaps(void) {
	u32 tmp=0;

	if (!__ctru_heap_size) {
		// Automatically allocate all remaining free memory, aligning to page size.
		__ctru_heap_size = osGetMemRegionFree(MEMREGION_APPLICATION) &~ 0xFFF;
		if (__ctru_heap_size <= __ctru_linear_heap_size)
			svcBreak(USERBREAK_PANIC);
		__ctru_heap_size -= __ctru_linear_heap_size;
	}

	// Allocate the application heap
	__ctru_heap = 0x08000000;
	svcControlMemory(&tmp, __ctru_heap, 0x0, __ctru_heap_size, MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE);

	// Allocate the linear heap
	svcControlMemory(&__ctru_linear_heap, 0x0, 0x0, __ctru_linear_heap_size, MEMOP_ALLOC_LINEAR, MEMPERM_READ | MEMPERM_WRITE);

	// Set up newlib heap
	fake_heap_start = (char*)__ctru_heap;
	fake_heap_end = fake_heap_start + __ctru_heap_size;

}
Example #9
0
void GDB_PreprocessDebugEvent(GDBContext *ctx, DebugEventInfo *info)
{
    switch(info->type)
    {
        case DBGEVENT_ATTACH_THREAD:
        {
            if(ctx->nbThreads == MAX_DEBUG_THREAD)
                svcBreak(USERBREAK_ASSERT);
            else
            {
                ctx->threadInfos[ctx->nbThreads].id = info->thread_id;
                ctx->threadInfos[ctx->nbThreads++].tls = info->attach_thread.thread_local_storage;
            }

            break;
        }

        case DBGEVENT_EXIT_THREAD:
        {
            u32 i;
            for(i = 0; i < ctx->nbThreads && ctx->threadInfos[i].id != info->thread_id; i++);
            if(i == ctx->nbThreads ||  ctx->threadInfos[i].id != info->thread_id)
                svcBreak(USERBREAK_ASSERT);
            else
            {
                for(u32 j = i; j < ctx->nbThreads - 1; j++)
                    memcpy(ctx->threadInfos + j, ctx->threadInfos + j + 1, sizeof(ThreadInfo));
                memset(ctx->threadInfos + --ctx->nbThreads, 0, sizeof(ThreadInfo));
            }

            break;
        }

        case DBGEVENT_EXIT_PROCESS:
        {
            ctx->processEnded = true;
            ctx->processExited = info->exit_process.reason == EXITPROCESS_EVENT_EXIT;

            break;
        }

        case DBGEVENT_OUTPUT_STRING:
        {
            if(info->output_string.string_addr >= 0xFFFFFFFE)
            {
                u32 sz = info->output_string.string_size, addr = info->output_string.string_addr, threadId = info->thread_id;
                memset(info, 0, sizeof(DebugEventInfo));
                info->type = (addr == 0xFFFFFFFF) ? DBGEVENT_SYSCALL_OUT : DBGEVENT_SYSCALL_IN;
                info->thread_id = threadId;
                info->flags = 1;
                info->syscall.syscall = sz;
            }

            break;
        }

        case DBGEVENT_EXCEPTION:
        {
            switch(info->exception.type)
            {
                case EXCEVENT_UNDEFINED_INSTRUCTION:
                {
                    // kernel bugfix for thumb mode
                    ThreadContext regs;
                    Result r = svcGetDebugThreadContext(&regs, ctx->debug, info->thread_id, THREADCONTEXT_CONTROL_CPU_SPRS);
                    if(R_SUCCEEDED(r) && (regs.cpu_registers.cpsr & 0x20) != 0)
                    {
                        regs.cpu_registers.pc += 2;
                        r = svcSetDebugThreadContext(ctx->debug, info->thread_id, &regs, THREADCONTEXT_CONTROL_CPU_SPRS);
                    }

                    break;
                }

                default:
                    break;
            }
        }
        default:
            break;
    }
}
Example #10
0
void patchCode(u64 progId, u16 progVer, u8 *code, u32 size)
{
    loadCFWInfo();

    if(((progId == 0x0004003000008F02LL || //USA Home Menu
         progId == 0x0004003000008202LL || //JPN Home Menu
         progId == 0x0004003000009802LL) //EUR Home Menu
        && progVer > 4) ||
       (progId == 0x000400300000A902LL //KOR Home Menu
        && progVer > 0) ||
        progId == 0x000400300000A102LL || //CHN Home Menu
        progId == 0x000400300000B102LL) //TWN Home Menu
    {
        static const u8 pattern[] = {
            0x0A, 0x0C, 0x00, 0x10
        },
                        patch[] = {
            0x01, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1
        };

        //Patch SMDH region checks
        if(!patchMemory(code, size,
                pattern,
                sizeof(pattern), -31,
                patch,
                sizeof(patch), 1
            )) goto error;
    }

    else if(progId == 0x0004013000003202LL) //FRIENDS
    {
        static const u8 pattern[] = {
            0x42, 0xE0, 0x1E, 0xFF
        };

        u8 mostRecentFpdVer = 8;

        u8 *off = memsearch(code, pattern, size, sizeof(pattern));

        if(off == NULL) goto error;

        //Allow online access to work with old friends modules
        if(off[0xA] < mostRecentFpdVer) off[0xA] = mostRecentFpdVer;
    }

    else if((progId == 0x0004001000021000LL || //USA MSET
             progId == 0x0004001000020000LL || //JPN MSET
             progId == 0x0004001000022000LL || //EUR MSET
             progId == 0x0004001000026000LL || //CHN MSET
             progId == 0x0004001000027000LL || //KOR MSET
             progId == 0x0004001000028000LL) //TWN MSET
            && CONFIG(PATCHVERSTRING)) 
    {
        static const u16 pattern[] = u"Ve";
        static u16 *patch;
        u32 patchSize = 0,
        currentNand = BOOTCFG_NAND;

        u16 customVerString[19];
        loadCustomVerString(customVerString, &patchSize, currentNand);

        if(patchSize != 0) patch = customVerString;
        else
        {
            patchSize = 8;
            u32 currentFirm = BOOTCFG_FIRM;

            static u16 *verStringsNands[] = { u" Sys",
                                              u" Emu",
                                              u"Emu2",
                                              u"Emu3",
                                              u"Emu4" },

                       *verStringsEmuSys[] = { u"EmuS",
                                               u"Em2S",
                                               u"Em3S",
                                               u"Em4S" },

                       *verStringsSysEmu[] = { u"SysE",
                                               u"SyE2",
                                               u"SyE3",
                                               u"SyE4" };

            patch = (currentFirm != 0) == (currentNand != 0) ? verStringsNands[currentNand] :
                                          (!currentNand ? verStringsSysEmu[currentFirm - 1] : verStringsEmuSys[currentNand - 1]);
        }

        //Patch Ver. string
        if(!patchMemory(code, size,
                pattern,
                sizeof(pattern) - 2, 0,
                patch,
                patchSize, 1
            )) goto error;
    }

    else if(progId == 0x0004013000008002LL) //NS
    {
        if(progVer > 4)
        {
            static const u8 pattern[] = {
                0x0C, 0x18, 0xE1, 0xD8
            },
                            patch[] = {
                0x0B, 0x18, 0x21, 0xC8
            };

            //Disable updates from foreign carts (makes carts region-free)
            u32 ret = patchMemory(code, size,
                          pattern,
                          sizeof(pattern), 0,
                          patch,
                          sizeof(patch), 2
                      );

            if(ret == 0 || (ret == 1 && progVer > 0xB)) goto error;
        }

        if(LOADERFLAG(ISN3DS))
        {
            u32 cpuSetting = MULTICONFIG(NEWCPU);

            if(cpuSetting != 0)
            {
                static const u8 pattern[] = {
                    0x0C, 0x00, 0x94, 0x15
                };

                u32 *off = (u32 *)memsearch(code, pattern, size, sizeof(pattern));

                if(off == NULL) goto error;

                //Patch N3DS CPU Clock and L2 cache setting
                *(off - 4) = *(off - 3);
                *(off - 3) = *(off - 1);
                memcpy(off - 1, off, 16);
                *(off + 3) = 0xE3800000 | cpuSetting;
            }
        }
    }

    else if(progId == 0x0004013000001702LL) //CFG
    {
        static const u8 pattern[] = {
            0x06, 0x46, 0x10, 0x48
        },
                        patch[] = {
            0x00, 0x26
        };

        //Disable SecureInfo signature check
        if(!patchMemory(code, size,
                pattern,
                sizeof(pattern), 0,
                patch,
                sizeof(patch), 1
            )) goto error;

        if(secureInfoExists())
        {
            static const u16 pattern[] = u"Sec",
                             patch[] = u"C";

            //Use SecureInfo_C
            if(patchMemory(code, size,
                   pattern,
                   sizeof(pattern) - 2, 22,
                   patch,
                   sizeof(patch) - 2, 2
               ) != 2) goto error;
        }
    }

    else if(progId == 0x0004013000003702LL && progVer > 0) //RO
    {
        static const u8 pattern[] = {
            0x20, 0xA0, 0xE1, 0x8B
        },
                        pattern2[] = {
            0xE1, 0x30, 0x40, 0x2D
        },
                        pattern3[] = {
            0x2D, 0xE9, 0x01, 0x70
        },
                        patch[] = {
            0x00, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1 //mov r0, #0; bx lr
        };

        //Disable CRR0 signature (RSA2048 with SHA256) check and CRO0/CRR0 SHA256 hash checks (section hashes, and hash table)
        if(!patchMemory(code, size,
                pattern,
                sizeof(pattern), -9,
                patch,
                sizeof(patch), 1
            ) ||
           !patchMemory(code, size,
                pattern2,
                sizeof(pattern2), 1,
                patch,
                sizeof(patch), 1
            ) ||
           !patchMemory(code, size,
                pattern3,
                sizeof(pattern3), -2,
                patch,
                sizeof(patch), 1
            )) goto error;
    }

    else if(progId == 0x0004003000008A02LL && MULTICONFIG(DEVOPTIONS) == 1) //ErrDisp
    {
        static const u8 pattern[] = { 
            0x00, 0xD0, 0xE5, 0xDB
        },
                        pattern2[] = {
            0x14, 0x00, 0xD0, 0xE5, 0x01
        },
                        patch[] = {
            0x00, 0x00, 0xA0, 0xE3
        };

        //Patch UNITINFO checks to make ErrDisp more verbose
        if(!patchMemory(code, size,
                pattern,
                sizeof(pattern), -1,
                patch,
                sizeof(patch), 1
            ) ||
           patchMemory(code, size,
               pattern2,
               sizeof(pattern2), 0,
               patch,
               sizeof(patch), 3
           ) != 3) goto error;
    }

    else if (progId == 0x0004013000003802LL) // ACT Module
    {
        antibanPatch(code, size);
    }

    if(CONFIG(PATCHGAMES) && (u32)((progId >> 0x20) & 0xFFFFFFEDULL) == 0x00040000)
    {
        u8 regionId = 0xFF,
           languageId;

        if(!loadTitleCodeSection(progId, code, size) ||
           !loadTitleLocaleConfig(progId, &regionId, &languageId)) goto error;

        if(regionId != 0xFF)
        {
            u32 CFGUHandleOffset;
            u8 *CFGU_GetConfigInfoBlk2_endPos = getCfgOffsets(code, size, &CFGUHandleOffset);

            if(CFGU_GetConfigInfoBlk2_endPos == NULL ||
               !patchCfgGetLanguage(code, size, languageId, CFGU_GetConfigInfoBlk2_endPos)) goto error;

            patchCfgGetRegion(code, size, regionId, CFGUHandleOffset);
        }

        if(!patchRomfsRedirection(progId, code, size)) goto error;
    }

    return;

error:
    svcBreak(USERBREAK_ASSERT);
    while(true);
}
Example #11
0
static void __panic(void)
{
	svcBreak(USERBREAK_PANIC);
	for (;;);
}