Expose err:f global port

This commit is contained in:
chaoskagami 2016-07-14 16:30:55 -04:00
parent da7ecc255b
commit cfdb8d1b58
3 changed files with 134 additions and 1 deletions

View File

@ -14,6 +14,7 @@ extern "C" {
#include <3ds/ipc.h> #include <3ds/ipc.h>
#include <3ds/svc.h> #include <3ds/svc.h>
#include <3ds/srv.h> #include <3ds/srv.h>
#include <3ds/errf.h>
#include <3ds/os.h> #include <3ds/os.h>
#include <3ds/synchronization.h> #include <3ds/synchronization.h>
#include <3ds/thread.h> #include <3ds/thread.h>
@ -106,4 +107,4 @@ extern "C" {
* @example threads/event/source/main.c * @example threads/event/source/main.c
* @example time/rtc/source/main.c * @example time/rtc/source/main.c
*/ */

View File

@ -0,0 +1,80 @@
/**
* @file errf.h
* @brief Error Display API
*/
#pragma once
#include <3ds/types.h>
/// Used for register dumps.
typedef struct {
u32 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, cpsr;
} ERRF_ExceptionContext;
/// Types of errors that can be thrown by err:f.
typedef enum {
ERRF_ERRTYPE_GENERIC = 0, ///< For generic errors. Shows miscellaneous info.
ERRF_ERRTYPE_EXCEPTION = 3, ///< For exceptions, or more specifically 'crashes'. union data should be exception_data.
ERRF_ERRTYPE_FAILURE = 4, ///< For general failure. Shows a message. union data should have a string set in failure_mesg
ERRF_ERRTYPE_LOGGED = 5 ///< Outputs logs to NAND in some cases.
} ERRF_ErrType;
/// Types of 'Exceptions' thrown for ERRF_ERRTYPE_EXCEPTION
typedef enum {
ERRF_EXCEPTION_PREFETCH_ABORT = 0, ///< Prefetch Abort
ERRF_EXCEPTION_DATA_ABORT = 1, ///< Data abort
ERRF_EXCEPTION_UNDEFINED = 2, ///< Undefined instruction
ERRF_EXCEPTION_VFP = 3 ///< VFP (floating point) exception.
} ERRF_ExceptionType;
typedef struct {
ERRF_ExceptionType type; ///< Type of the exception. One of the ERRF_EXCEPTION_* values.
u8 reserved[3];
u32 reg1; ///< If type is prefetch, this should be ifsr, and on data abort dfsr
u32 reg2; ///< If type is prefetch, this should be r15, and dfar on data abort
u32 fpexc;
u32 fpinst;
u32 fpint2;
} ERRF_ExceptionInfo;
typedef struct {
ERRF_ExceptionInfo excep; ///< Exception info struct
ERRF_ExceptionContext regs; ///< Register dump.
u8 pad[4];
} ERRF_ExceptionData;
typedef struct {
ERRF_ErrType type; ///< Type, one of the ERRF_ERRTYPE_* enum
u8 revHigh; ///< High revison ID
u16 revLow; ///< Low revision ID
u32 resCode; ///< Result code
u32 pcAddr; ///< PC address at exception
u32 procId; ///< Process ID.
u64 titleId; ///< Title ID.
u64 appTitleId; ///< Application Title ID.
union {
ERRF_ExceptionData exception_data; ///< Data for when type is ERRF_ERRTYPE_EXCEPTION
char failure_mesg[60]; ///< String for when type is ERRF_ERRTYPE_FAILURE
} data; ///< The different types of data for errors.
} ERRF_FatalErrInfo;
/// Initializes ERR:f.
Result errfInit(void);
/// Exits ERR:f.
void errfExit(void);
/**
* @brief Gets the current err:f API session handle.
* @return The current err:f API session handle.
*/
Handle *errfGetSessionHandle(void);
/**
* @brief Throws a system error and possibly results in ErrDisp triggering. After performing this,
* the system may panic and need to be rebooted. Extra information will be displayed on the
* top screen with a developer console or the proper patches in a CFW applied.
* @param error Error to throw.
*/
Result ERRF_Throw(ERRF_FatalErrInfo *error);

52
libctru/source/errf.c Normal file
View File

@ -0,0 +1,52 @@
#include <string.h>
#include <3ds/types.h>
#include <3ds/result.h>
#include <3ds/svc.h>
#include <3ds/synchronization.h>
#include <3ds/errf.h>
#include <3ds/ipc.h>
#include <3ds/env.h>
#include "internal.h"
static Handle errfHandle;
static int errfRefCount;
Result errfInit(void)
{
Result rc = 0;
if (AtomicPostIncrement(&errfRefCount)) return 0;
rc = svcConnectToPort(&errfHandle, "err:f");
if (R_FAILED(rc)) goto end;
end:
if (R_FAILED(rc)) errfExit();
return rc;
}
void errfExit(void)
{
if (AtomicDecrement(&errfRefCount))
return;
svcCloseHandle(errfHandle);
}
Handle* errfGetSessionHandle(void)
{
return &errfHandle;
}
Result ERRF_Throw(ERRF_FatalErrInfo *error)
{
uint32_t *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x10800;
memcpy(&cmdbuf[1], error, sizeof(ERRF_FatalErrInfo));
Result ret = 0;
if (R_FAILED(ret = svcSendSyncRequest(errfHandle)))
return ret;
return cmdbuf[1];
}