mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-28 20:40:24 +00:00
fatal: update for new-ipc
This commit is contained in:
parent
8d16d2152b
commit
799c158b86
9 changed files with 113 additions and 73 deletions
|
@ -65,40 +65,54 @@ namespace sts::fatal::srv {
|
|||
return false;
|
||||
}
|
||||
|
||||
/* HACK: We want to parse the command the fatal caller sent. */
|
||||
/* The easiest way to do this is to copy their TLS over ours, and parse ours. */
|
||||
std::memcpy(armGetTls(), thread_tls, sizeof(thread_tls));
|
||||
/* We want to parse the command the fatal caller sent. */
|
||||
{
|
||||
IpcParsedCommand r;
|
||||
if (R_FAILED(ipcParse(&r))) {
|
||||
return false;
|
||||
}
|
||||
const auto request = hipcParseRequest(thread_tls);
|
||||
|
||||
const struct {
|
||||
CmifInHeader header;
|
||||
u32 error_code;
|
||||
} *in_data = decltype(in_data)(request.data.data_words);
|
||||
static_assert(sizeof(*in_data) == 0x14, "InData!");
|
||||
|
||||
/* Fatal command takes in a PID, only one buffer max. */
|
||||
if (!r.HasPid || r.NumStatics || r.NumStaticsOut || r.NumHandles) {
|
||||
if ((request.meta.type != CmifCommandType_Request && request.meta.type != CmifCommandType_RequestWithContext) ||
|
||||
!request.meta.send_pid ||
|
||||
request.meta.num_send_statics ||
|
||||
request.meta.num_recv_statics ||
|
||||
request.meta.num_recv_buffers ||
|
||||
request.meta.num_exch_buffers ||
|
||||
request.meta.num_copy_handles ||
|
||||
request.meta.num_move_handles ||
|
||||
request.meta.num_data_words < ((sizeof(*in_data) + 0x10) / sizeof(u32)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
struct {
|
||||
u32 magic;
|
||||
u32 version;
|
||||
u64 cmd_id;
|
||||
u32 err_code;
|
||||
} *raw = (decltype(raw))(r.Raw);
|
||||
|
||||
if (raw->magic != SFCI_MAGIC) {
|
||||
if (in_data->header.magic != CMIF_IN_HEADER_MAGIC) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (raw->cmd_id > 2) {
|
||||
if (in_data->header.version > 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (raw->cmd_id != 2 && r.NumBuffers) {
|
||||
return false;
|
||||
switch (in_data->header.command_id) {
|
||||
case 0:
|
||||
case 1:
|
||||
if (request.meta.num_send_buffers != 0) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (request.meta.num_send_buffers != 1) {
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (raw->err_code != error_code) {
|
||||
if (in_data->error_code != error_code) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -154,10 +168,10 @@ namespace sts::fatal::srv {
|
|||
|
||||
}
|
||||
|
||||
void TryCollectDebugInformation(ThrowContext *ctx, u64 process_id) {
|
||||
void TryCollectDebugInformation(ThrowContext *ctx, os::ProcessId process_id) {
|
||||
/* Try to debug the process. This may fail, if we called into ourself. */
|
||||
os::ManagedHandle debug_handle;
|
||||
if (R_FAILED(svcDebugActiveProcess(debug_handle.GetPointer(), process_id))) {
|
||||
if (R_FAILED(svcDebugActiveProcess(debug_handle.GetPointer(), static_cast<u64>(process_id)))) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,6 @@
|
|||
|
||||
namespace sts::fatal::srv {
|
||||
|
||||
void TryCollectDebugInformation(ThrowContext *ctx, u64 process_id);
|
||||
void TryCollectDebugInformation(ThrowContext *ctx, os::ProcessId process_id);
|
||||
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include <cstdlib>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <malloc.h>
|
||||
|
||||
#include <switch.h>
|
||||
#include <atmosphere.h>
|
||||
|
@ -32,6 +31,7 @@ extern "C" {
|
|||
extern u32 __start__;
|
||||
|
||||
u32 __nx_applet_type = AppletType_None;
|
||||
u32 __nx_fs_num_sessions = 1;
|
||||
|
||||
#define INNER_HEAP_SIZE 0x2A0000
|
||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||
|
@ -69,8 +69,10 @@ void __libnx_initheap(void) {
|
|||
fake_heap_end = (char*)addr + size;
|
||||
}
|
||||
|
||||
using namespace sts;
|
||||
|
||||
void __appInit(void) {
|
||||
SetFirmwareVersionForLibnx();
|
||||
hos::SetVersionForLibnx();
|
||||
|
||||
DoWithSmSession([&]() {
|
||||
R_ASSERT(setInitialize());
|
||||
|
@ -79,7 +81,7 @@ void __appInit(void) {
|
|||
R_ASSERT(i2cInitialize());
|
||||
R_ASSERT(bpcInitialize());
|
||||
|
||||
if (GetRuntimeFirmwareVersion() >= FirmwareVersion_800) {
|
||||
if (hos::GetVersion() >= hos::Version_800) {
|
||||
R_ASSERT(clkrstInitialize());
|
||||
} else {
|
||||
R_ASSERT(pcvInitialize());
|
||||
|
@ -107,7 +109,7 @@ void __appExit(void) {
|
|||
spsmExit();
|
||||
psmExit();
|
||||
lblExit();
|
||||
if (GetRuntimeFirmwareVersion() >= FirmwareVersion_800) {
|
||||
if (hos::GetVersion() >= hos::Version_800) {
|
||||
clkrstExit();
|
||||
} else {
|
||||
pcvExit();
|
||||
|
@ -119,26 +121,55 @@ void __appExit(void) {
|
|||
setExit();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
using ServerOptions = sf::hipc::DefaultServerManagerOptions;
|
||||
|
||||
constexpr sm::ServiceName UserServiceName = sm::ServiceName::Encode("fatal:u");
|
||||
constexpr size_t UserMaxSessions = 4;
|
||||
|
||||
constexpr sm::ServiceName PrivateServiceName = sm::ServiceName::Encode("fatal:p");
|
||||
constexpr size_t PrivateMaxSessions = 4;
|
||||
|
||||
/* fatal:u, fatal:p. */
|
||||
/* TODO: Consider max sessions enforcement? */
|
||||
constexpr size_t NumServers = 2;
|
||||
constexpr size_t NumSessions = UserMaxSessions + PrivateMaxSessions;
|
||||
|
||||
sf::hipc::ServerManager<NumServers, ServerOptions, NumSessions> g_server_manager;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
/* Load shared font. */
|
||||
R_ASSERT(sts::fatal::srv::font::InitializeSharedFont());
|
||||
R_ASSERT(fatal::srv::font::InitializeSharedFont());
|
||||
|
||||
/* Check whether we should throw fatal due to repair process. */
|
||||
sts::fatal::srv::CheckRepairStatus();
|
||||
|
||||
/* Create waitable manager. */
|
||||
static auto s_server_manager = WaitableManager(1);
|
||||
fatal::srv::CheckRepairStatus();
|
||||
|
||||
/* Create services. */
|
||||
s_server_manager.AddWaitable(new ServiceServer<sts::fatal::srv::PrivateService>("fatal:p", 4));
|
||||
s_server_manager.AddWaitable(new ServiceServer<sts::fatal::srv::UserService>("fatal:u", 4));
|
||||
R_ASSERT((g_server_manager.RegisterServer<fatal::srv::PrivateService>(PrivateServiceName, PrivateMaxSessions)));
|
||||
R_ASSERT((g_server_manager.RegisterServer<fatal::srv::UserService>(UserServiceName, UserMaxSessions)));
|
||||
|
||||
/* Add dirty event holder. */
|
||||
/* TODO: s_server_manager.AddWaitable(sts::fatal::srv::GetFatalDirtyEvent()); */
|
||||
auto dirty_event_holder = sts::fatal::srv::GetFatalDirtyWaitableHolder();
|
||||
(void)dirty_event_holder;
|
||||
auto *dirty_event_holder = sts::fatal::srv::GetFatalDirtyWaitableHolder();
|
||||
g_server_manager.AddUserWaitableHolder(dirty_event_holder);
|
||||
|
||||
/* Loop forever, servicing our services. */
|
||||
s_server_manager.Process();
|
||||
/* Because fatal has a user wait holder, we need to specify how to process manually. */
|
||||
while (auto *signaled_holder = g_server_manager.WaitSignaled()) {
|
||||
if (signaled_holder == dirty_event_holder) {
|
||||
/* Dirty event holder was signaled. */
|
||||
fatal::srv::OnFatalDirtyEvent();
|
||||
g_server_manager.AddUserWaitableHolder(signaled_holder);
|
||||
} else {
|
||||
/* A server/session was signaled. Have the manager handle it. */
|
||||
R_ASSERT(g_server_manager.Process(signaled_holder));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace sts::fatal::srv {
|
|||
|
||||
bool IsInRepair() {
|
||||
/* Before firmware 3.0.0, this wasn't implemented. */
|
||||
if (GetRuntimeFirmwareVersion() < FirmwareVersion_300) {
|
||||
if (hos::GetVersion() < hos::Version_300) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,7 @@ namespace sts::fatal::srv {
|
|||
|
||||
bool NeedsRunTimeReviser() {
|
||||
/* Before firmware 5.0.0, this wasn't implemented. */
|
||||
if (GetRuntimeFirmwareVersion() < FirmwareVersion_300) {
|
||||
if (hos::GetVersion() < hos::Version_300) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -51,22 +51,22 @@ namespace sts::fatal::srv {
|
|||
return this->event_manager.GetEvent(out);
|
||||
}
|
||||
|
||||
Result ThrowFatal(u32 error_code, u64 process_id) {
|
||||
Result ThrowFatal(u32 error_code, os::ProcessId process_id) {
|
||||
return this->ThrowFatalWithCpuContext(error_code, process_id, FatalType_ErrorReportAndErrorScreen, {});
|
||||
}
|
||||
|
||||
Result ThrowFatalWithPolicy(u32 error_code, u64 process_id, FatalType policy) {
|
||||
Result ThrowFatalWithPolicy(u32 error_code, os::ProcessId process_id, FatalType policy) {
|
||||
return this->ThrowFatalWithCpuContext(error_code, process_id, policy, {});
|
||||
}
|
||||
|
||||
Result ThrowFatalWithCpuContext(u32 error_code, u64 process_id, FatalType policy, const CpuContext &cpu_ctx);
|
||||
Result ThrowFatalWithCpuContext(u32 error_code, os::ProcessId process_id, FatalType policy, const CpuContext &cpu_ctx);
|
||||
};
|
||||
|
||||
/* Context global. */
|
||||
ServiceContext g_context;
|
||||
|
||||
/* Throw implementation. */
|
||||
Result ServiceContext::ThrowFatalWithCpuContext(u32 error_code, u64 process_id, FatalType policy, const CpuContext &cpu_ctx) {
|
||||
Result ServiceContext::ThrowFatalWithCpuContext(u32 error_code, os::ProcessId process_id, FatalType policy, const CpuContext &cpu_ctx) {
|
||||
/* We don't support Error Report only fatals. */
|
||||
if (policy == FatalType_ErrorReport) {
|
||||
return ResultSuccess;
|
||||
|
@ -92,7 +92,7 @@ namespace sts::fatal::srv {
|
|||
|
||||
if (!this->context.is_creport) {
|
||||
/* On firmware version 2.0.0, use debugging SVCs to collect information. */
|
||||
if (GetRuntimeFirmwareVersion() >= FirmwareVersion_200) {
|
||||
if (hos::GetVersion() >= hos::Version_200) {
|
||||
fatal::srv::TryCollectDebugInformation(&this->context, process_id);
|
||||
}
|
||||
} else {
|
||||
|
@ -132,28 +132,22 @@ namespace sts::fatal::srv {
|
|||
}
|
||||
|
||||
Result ThrowFatalForSelf(Result error_code) {
|
||||
u64 process_id = 0;
|
||||
R_ASSERT(svcGetProcessId(&process_id, CUR_PROCESS_HANDLE));
|
||||
return g_context.ThrowFatalWithPolicy(static_cast<u32>(error_code), process_id, FatalType_ErrorScreen);
|
||||
return g_context.ThrowFatalWithPolicy(static_cast<u32>(error_code), os::GetCurrentProcessId(), FatalType_ErrorScreen);
|
||||
}
|
||||
|
||||
Result UserService::ThrowFatal(u32 error, PidDescriptor pid_desc) {
|
||||
return g_context.ThrowFatal(error, pid_desc.pid);
|
||||
Result UserService::ThrowFatal(u32 error, const sf::ClientProcessId &client_pid) {
|
||||
return g_context.ThrowFatal(error, client_pid.GetValue());
|
||||
}
|
||||
|
||||
Result UserService::ThrowFatalWithPolicy(u32 error, PidDescriptor pid_desc, FatalType policy) {
|
||||
return g_context.ThrowFatalWithPolicy(error, pid_desc.pid, policy);
|
||||
Result UserService::ThrowFatalWithPolicy(u32 error, const sf::ClientProcessId &client_pid, FatalType policy) {
|
||||
return g_context.ThrowFatalWithPolicy(error, client_pid.GetValue(), policy);
|
||||
}
|
||||
|
||||
Result UserService::ThrowFatalWithCpuContext(u32 error, PidDescriptor pid_desc, FatalType policy, InBuffer<u8> _ctx) {
|
||||
if (_ctx.num_elements < sizeof(CpuContext)) {
|
||||
return g_context.ThrowFatalWithPolicy(error, pid_desc.pid, policy);
|
||||
} else {
|
||||
return g_context.ThrowFatalWithCpuContext(error, pid_desc.pid, policy, *reinterpret_cast<const CpuContext *>(_ctx.buffer));
|
||||
}
|
||||
Result UserService::ThrowFatalWithCpuContext(u32 error, const sf::ClientProcessId &client_pid, FatalType policy, const CpuContext &cpu_ctx) {
|
||||
return g_context.ThrowFatalWithCpuContext(error, client_pid.GetValue(), policy, cpu_ctx);
|
||||
}
|
||||
|
||||
Result PrivateService::GetFatalEvent(Out<CopiedHandle> out_h) {
|
||||
Result PrivateService::GetFatalEvent(sf::OutCopyHandle out_h) {
|
||||
return g_context.GetEvent(out_h.GetHandlePointer());
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
namespace sts::fatal::srv {
|
||||
|
||||
class UserService final : public IServiceObject {
|
||||
class UserService final : public sf::IServiceObject {
|
||||
private:
|
||||
enum class CommandId {
|
||||
ThrowFatal = 0,
|
||||
|
@ -29,28 +29,28 @@ namespace sts::fatal::srv {
|
|||
};
|
||||
private:
|
||||
/* Actual commands. */
|
||||
Result ThrowFatal(u32 error, PidDescriptor pid_desc);
|
||||
Result ThrowFatalWithPolicy(u32 error, PidDescriptor pid_desc, FatalType policy);
|
||||
Result ThrowFatalWithCpuContext(u32 error, PidDescriptor pid_desc, FatalType policy, InBuffer<u8> _ctx);
|
||||
Result ThrowFatal(u32 error, const sf::ClientProcessId &client_pid);
|
||||
Result ThrowFatalWithPolicy(u32 error, const sf::ClientProcessId &client_pid, FatalType policy);
|
||||
Result ThrowFatalWithCpuContext(u32 error, const sf::ClientProcessId &client_pid, FatalType policy, const CpuContext &cpu_ctx);
|
||||
public:
|
||||
DEFINE_SERVICE_DISPATCH_TABLE {
|
||||
MAKE_SERVICE_COMMAND_META(UserService, ThrowFatal),
|
||||
MAKE_SERVICE_COMMAND_META(UserService, ThrowFatalWithPolicy),
|
||||
MAKE_SERVICE_COMMAND_META(UserService, ThrowFatalWithCpuContext),
|
||||
MAKE_SERVICE_COMMAND_META(ThrowFatal),
|
||||
MAKE_SERVICE_COMMAND_META(ThrowFatalWithPolicy),
|
||||
MAKE_SERVICE_COMMAND_META(ThrowFatalWithCpuContext),
|
||||
};
|
||||
};
|
||||
|
||||
class PrivateService final : public IServiceObject {
|
||||
class PrivateService final : public sf::IServiceObject {
|
||||
private:
|
||||
enum class CommandId {
|
||||
GetFatalEvent = 0,
|
||||
};
|
||||
private:
|
||||
/* Actual commands. */
|
||||
Result GetFatalEvent(Out<CopiedHandle> out_h);
|
||||
Result GetFatalEvent(sf::OutCopyHandle out_h);
|
||||
public:
|
||||
DEFINE_SERVICE_DISPATCH_TABLE {
|
||||
MAKE_SERVICE_COMMAND_META(PrivateService, GetFatalEvent),
|
||||
MAKE_SERVICE_COMMAND_META(GetFatalEvent),
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace sts::fatal::srv {
|
|||
|
||||
/* Task implementation. */
|
||||
Result AdjustClockTask::AdjustClockForModule(PcvModule module, u32 hz) {
|
||||
if (GetRuntimeFirmwareVersion() >= FirmwareVersion_800) {
|
||||
if (hos::GetVersion() >= hos::Version_800) {
|
||||
/* On 8.0.0+, convert to module id + use clkrst API. */
|
||||
PcvModuleId module_id;
|
||||
R_TRY(pcvGetModuleId(&module_id, module));
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
|
||||
#include <atmosphere/version.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include "fatal_task_screen.hpp"
|
||||
#include "fatal_config.hpp"
|
||||
|
@ -101,7 +102,7 @@ namespace sts::fatal::srv {
|
|||
ON_SCOPE_EXIT { viCloseDisplay(&temp_display); };
|
||||
|
||||
/* Turn on the screen. */
|
||||
if (GetRuntimeFirmwareVersion() >= FirmwareVersion_300) {
|
||||
if (hos::GetVersion() >= hos::Version_300) {
|
||||
R_TRY(viSetDisplayPowerState(&temp_display, ViPowerState_On));
|
||||
} else {
|
||||
/* Prior to 3.0.0, the ViPowerState enum was different (0 = Off, 1 = On). */
|
||||
|
@ -151,7 +152,7 @@ namespace sts::fatal::srv {
|
|||
R_TRY(viGetDisplayLogicalResolution(&this->display, &display_width, &display_height));
|
||||
|
||||
/* viSetDisplayMagnification was added in 3.0.0. */
|
||||
if (GetRuntimeFirmwareVersion() >= FirmwareVersion_300) {
|
||||
if (hos::GetVersion() >= hos::Version_300) {
|
||||
R_TRY(viSetDisplayMagnification(&this->display, 0, 0, display_width, display_height));
|
||||
}
|
||||
|
||||
|
@ -414,7 +415,6 @@ namespace sts::fatal::srv {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* Enqueue the buffer. */
|
||||
framebufferEnd(&fb);
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "../defines.hpp"
|
||||
#include "../results.hpp"
|
||||
#include "../ncm/ncm_types.hpp"
|
||||
#include "../sf/sf_buffer_tags.hpp"
|
||||
|
||||
namespace sts::fatal {
|
||||
|
||||
|
@ -293,7 +294,7 @@ namespace sts::fatal {
|
|||
|
||||
}
|
||||
|
||||
struct CpuContext {
|
||||
struct CpuContext : sf::LargeData, sf::PrefersMapAliasTransferMode {
|
||||
enum Architecture {
|
||||
Architecture_Aarch64 = 0,
|
||||
Architecture_Aarch32 = 1,
|
||||
|
|
Loading…
Reference in a new issue