From f914edeebdf14bc01a62343a13a8c1058b81eff7 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Sat, 10 Nov 2018 12:38:24 -0800 Subject: [PATCH] fatal: Implement configuration based on settings --- stratosphere/fatal/source/fatal_config.cpp | 64 +++++++++++++++++++ stratosphere/fatal/source/fatal_config.hpp | 34 ++++++++++ stratosphere/fatal/source/fatal_main.cpp | 13 +++- .../fatal/source/fatal_task_power.cpp | 9 ++- .../fatal/source/fatal_task_screen.cpp | 1 + stratosphere/fatal/source/fatal_user.cpp | 12 +++- 6 files changed, 128 insertions(+), 5 deletions(-) create mode 100644 stratosphere/fatal/source/fatal_config.cpp create mode 100644 stratosphere/fatal/source/fatal_config.hpp diff --git a/stratosphere/fatal/source/fatal_config.cpp b/stratosphere/fatal/source/fatal_config.cpp new file mode 100644 index 000000000..5583e7a0b --- /dev/null +++ b/stratosphere/fatal/source/fatal_config.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include "fatal_types.hpp" +#include "fatal_config.hpp" + +static FatalConfig g_fatal_config; + +static IEvent *g_fatal_settings_event = nullptr; + +FatalConfig *GetFatalConfig() { + return &g_fatal_config; +} + +static void UpdateLanguageCode() { + setGetLanguageCode(&GetFatalConfig()->language_code); +} + +IEvent *GetFatalSettingsEvent() { + if (g_fatal_settings_event == nullptr) { + Event evt; + if (R_FAILED(setsysBindFatalDirtyFlagEvent(&evt))) { + std::abort(); + } + g_fatal_settings_event = LoadReadOnlySystemEvent(evt.revent, [](u64 timeout) { + u64 flags_0, flags_1; + if (R_SUCCEEDED(setsysGetFatalDirtyFlags(&flags_0, &flags_1)) && (flags_0 & 1)) { + UpdateLanguageCode(); + } + return 0; + }, true); + } + + return g_fatal_settings_event; +} + +void InitializeFatalConfig() { + FatalConfig *config = GetFatalConfig(); + + memset(config, 0, sizeof(*config)); + setsysGetSerialNumber(config->serial_number); + setsysGetFirmwareVersion(&config->firmware_version); + UpdateLanguageCode(); + + setsysGetSettingsItemValue("fatal", "transition_to_fatal", &config->transition_to_fatal, sizeof(config->transition_to_fatal)); + setsysGetSettingsItemValue("fatal", "show_extra_info", &config->show_extra_info, sizeof(config->show_extra_info)); + setsysGetSettingsItemValue("fatal", "quest_reboot_interval_second", &config->quest_reboot_interval_second, sizeof(config->quest_reboot_interval_second)); + + setsysGetFlag(SetSysFlag_Quest, &config->quest_flag); +} diff --git a/stratosphere/fatal/source/fatal_config.hpp b/stratosphere/fatal/source/fatal_config.hpp new file mode 100644 index 000000000..105534bfc --- /dev/null +++ b/stratosphere/fatal/source/fatal_config.hpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#include +#include + +struct FatalConfig { + char serial_number[0x18]; + SetSysFirmwareVersion firmware_version; + u64 language_code; + u64 quest_reboot_interval_second; + bool transition_to_fatal; + bool show_extra_info; + bool quest_flag; +}; + +IEvent *GetFatalSettingsEvent(); +FatalConfig *GetFatalConfig(); + +void InitializeFatalConfig(); \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_main.cpp b/stratosphere/fatal/source/fatal_main.cpp index 31cb4a798..62324f6f1 100644 --- a/stratosphere/fatal/source/fatal_main.cpp +++ b/stratosphere/fatal/source/fatal_main.cpp @@ -26,6 +26,7 @@ #include "fatal_types.hpp" #include "fatal_private.hpp" #include "fatal_user.hpp" +#include "fatal_config.hpp" extern "C" { extern u32 __start__; @@ -65,6 +66,11 @@ void __appInit(void) { std::abort(); } + rc = setInitialize(); + if (R_FAILED(rc)) { + std::abort(); + } + rc = setsysInitialize(); if (R_FAILED(rc)) { std::abort(); @@ -118,13 +124,15 @@ void __appExit(void) { i2cExit(); pminfoExit(); setsysExit(); + setExit(); smExit(); } int main(int argc, char **argv) { - /* TODO: Load settings from set:sys. */ - + /* Load settings from set:sys. */ + InitializeFatalConfig(); + /* TODO: Load shared font. */ /* TODO: Check whether we should throw fatal due to repair process... */ @@ -135,6 +143,7 @@ int main(int argc, char **argv) /* TODO: Create services. */ server_manager->AddWaitable(new ServiceServer("fatal:p", 4)); server_manager->AddWaitable(new ServiceServer("fatal:u", 4)); + server_manager->AddWaitable(GetFatalSettingsEvent()); /* Loop forever, servicing our services. */ server_manager->Process(); diff --git a/stratosphere/fatal/source/fatal_task_power.cpp b/stratosphere/fatal/source/fatal_task_power.cpp index 88e934f53..a804d6ff5 100644 --- a/stratosphere/fatal/source/fatal_task_power.cpp +++ b/stratosphere/fatal/source/fatal_task_power.cpp @@ -16,6 +16,7 @@ #include #include "fatal_task_power.hpp" +#include "fatal_config.hpp" bool PowerControlTask::TryShutdown() { /* Set a timeout of 30 seconds. */ @@ -91,12 +92,16 @@ void PowerButtonObserveTask::WaitForPowerButton() { /* Wait up to a second for error report generation to finish. */ eventWait(this->erpt_event, TimeoutHelper::NsToTick(1000000000UL)); - /* TODO: Force a reboot after some time if kiosk unit. */ + /* Force a reboot after some time if kiosk unit. */ + const FatalConfig *config = GetFatalConfig(); + TimeoutHelper reboot_helper(config->quest_reboot_interval_second * 1000000000UL); BpcSleepButtonState state; while (true) { + + Result rc = bpcGetSleepButtonState(&state); - if (R_SUCCEEDED(rc) && state == BpcSleepButtonState_Held) { + if ((R_SUCCEEDED(rc) && state == BpcSleepButtonState_Held) || (config->quest_flag && reboot_helper.TimedOut())) { bpcRebootSystem(); return; } diff --git a/stratosphere/fatal/source/fatal_task_screen.cpp b/stratosphere/fatal/source/fatal_task_screen.cpp index a28be3fa3..5dcf40b04 100644 --- a/stratosphere/fatal/source/fatal_task_screen.cpp +++ b/stratosphere/fatal/source/fatal_task_screen.cpp @@ -16,6 +16,7 @@ #include #include "fatal_task_screen.hpp" +#include "fatal_config.hpp" Result ShowFatalTask::ShowFatal() { Result rc = 0; diff --git a/stratosphere/fatal/source/fatal_user.cpp b/stratosphere/fatal/source/fatal_user.cpp index b21aefc29..f5405267c 100644 --- a/stratosphere/fatal/source/fatal_user.cpp +++ b/stratosphere/fatal/source/fatal_user.cpp @@ -18,6 +18,7 @@ #include "fatal_user.hpp" #include "fatal_event_manager.hpp" #include "fatal_task.hpp" +#include "fatal_config.hpp" static bool g_thrown = false; @@ -37,6 +38,9 @@ Result UserService::ThrowFatalImpl(u32 error, u64 pid, FatalType policy, FatalCp ctx.error_code = error; ctx.cpu_ctx = *cpu_ctx; + /* Get config. */ + const FatalConfig *config = GetFatalConfig(); + /* Get title id. On failure, it'll be zero. */ u64 title_id = 0; pminfoGetTitleId(&title_id, pid); @@ -63,7 +67,13 @@ Result UserService::ThrowFatalImpl(u32 error, u64 pid, FatalType policy, FatalCp } /* Run tasks. */ - RunFatalTasks(&ctx, title_id, policy == FatalType_ErrorReportAndErrorScreen, &erpt_event, &battery_event); + if (config->transition_to_fatal) { + RunFatalTasks(&ctx, title_id, policy == FatalType_ErrorReportAndErrorScreen, &erpt_event, &battery_event); + } else { + /* If flag is not set, don't show the fatal screen. */ + return 0; + } + } break; default: