// Copyright 2017 plutoo #include "types.h" #include "result.h" #include "kernel/detect.h" #include "kernel/svc.h" #include "sf/service.h" #include "services/fatal.h" #include "services/sm.h" static void _fatalImpl(u32 cmd_id, Result err, FatalType type, FatalContext *ctx) { Result rc = 0; //Only [3.0.0+] supports FatalType_ErrorScreen, when specified on pre-3.0.0 use FatalType_ErrorReportAndErrorScreen instead. if (type == FatalType_ErrorScreen && !kernelAbove300()) type = FatalType_ErrorReportAndErrorScreen; if (detectDebugger()) { svcBreak(0x80000000, err, 0); } Handle session; rc = smInitialize(); if (R_SUCCEEDED(rc)) { rc = smGetServiceOriginal(&session, smEncodeName("fatal:u")); smExit(); } if (R_SUCCEEDED(rc)) { const struct { u32 result; u32 type; u64 pid_placeholder; } in = { err, type }; Service s; serviceCreate(&s, session); serviceDispatchIn(&s, cmd_id, in, .buffer_attrs = { ctx ? (SfBufferAttr_In | SfBufferAttr_HipcMapAlias) : 0U }, .buffers = { { ctx, sizeof(*ctx) } }, .in_send_pid = true, ); } switch (type) { case FatalType_ErrorReport: break; case FatalType_ErrorReportAndErrorScreen: case FatalType_ErrorScreen: default: svcExitProcess(); __builtin_unreachable(); } } void NORETURN fatalSimple(Result err) { /* By default, do not generate an error report. */ fatalWithType(err, FatalType_ErrorScreen); svcExitProcess(); __builtin_unreachable(); } void fatalWithType(Result err, FatalType type) { _fatalImpl(1, err, type, NULL); } void fatalWithContext(Result err, FatalType type, FatalContext *ctx) { _fatalImpl(2, err, type, ctx); }