Merge pull request #297 from chaoskagami/master
Expose err:f global port
This commit is contained in:
commit
ea0a96c29b
@ -14,6 +14,7 @@ extern "C" {
|
||||
#include <3ds/ipc.h>
|
||||
#include <3ds/svc.h>
|
||||
#include <3ds/srv.h>
|
||||
#include <3ds/errf.h>
|
||||
#include <3ds/os.h>
|
||||
#include <3ds/synchronization.h>
|
||||
#include <3ds/thread.h>
|
||||
@ -106,4 +107,4 @@ extern "C" {
|
||||
* @example threads/event/source/main.c
|
||||
* @example time/rtc/source/main.c
|
||||
*/
|
||||
|
||||
|
||||
|
80
libctru/include/3ds/errf.h
Normal file
80
libctru/include/3ds/errf.h
Normal 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
52
libctru/source/errf.c
Normal 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];
|
||||
}
|
Loading…
Reference in New Issue
Block a user