From 88294116b8061d44cf29aaa69aa2418a3502509b Mon Sep 17 00:00:00 2001 From: hexkyz Date: Tue, 9 Apr 2019 19:40:00 +0100 Subject: [PATCH 1/6] fusee-secondary: Fix arg names in raw_dev --- fusee/fusee-secondary/src/raw_dev.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fusee/fusee-secondary/src/raw_dev.h b/fusee/fusee-secondary/src/raw_dev.h index 5cc0ad55e..a1b9e03c5 100644 --- a/fusee/fusee-secondary/src/raw_dev.h +++ b/fusee/fusee-secondary/src/raw_dev.h @@ -24,7 +24,7 @@ #define RAWDEV_MAX_DEVICES 16 -int rawdev_mount_device(const char *name, const device_partition_t *device, bool mount_immediately); +int rawdev_mount_device(const char *name, const device_partition_t *devpart, bool initialize_immediately); int rawdev_register_device(const char *name); int rawdev_unregister_device(const char *name); From 1e5fcff2422e86d220b6fde126b693ba3e31f155 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 10 Apr 2019 23:30:19 -0700 Subject: [PATCH 2/6] exo: always enable usermode exception handlers --- exosphere/src/bootconfig.c | 2 +- exosphere/src/bootconfig.h | 10 +++++++++- exosphere/src/configitem.c | 9 +++++++-- exosphere/src/configitem.h | 2 +- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/exosphere/src/bootconfig.c b/exosphere/src/bootconfig.c index 392b16b88..599503e83 100644 --- a/exosphere/src/bootconfig.c +++ b/exosphere/src/bootconfig.c @@ -123,7 +123,7 @@ uint64_t bootconfig_get_memory_arrangement(void) { } } -uint64_t bootconfig_get_kernel_memory_configuration(void) { +uint64_t bootconfig_get_kernel_configuration(void) { if (bootconfig_is_debug_mode()) { uint64_t high_val = 0; if (fuse_get_dram_id() == 4) { diff --git a/exosphere/src/bootconfig.h b/exosphere/src/bootconfig.h index 319a8f9a1..beabc2045 100644 --- a/exosphere/src/bootconfig.h +++ b/exosphere/src/bootconfig.h @@ -21,6 +21,14 @@ #include #include "memory_map.h" +/* This is kind of ConfigItem, but it's stored in BootConfig, so... */ +typedef enum { + KERNELCONFIGFLAG_INITIALIZE_MEMORY_TO_PATTERN = (1 << 0), + KERNELCONFIGFLAG_ENABLE_USER_EXCEPTION_HANDLERS = (1 << 1), + KERNELCONFIGFLAG_ENABLE_USER_PMU_ACCESS = (1 << 2), + KERNELCONFIGFLAG_CALL_SMC_PANIC_ON_KERNEL_ERROR = (1 << 8), +} KernelConfigFlag; + /* This provides management for Switch BootConfig. */ #define LOADED_BOOTCONFIG (get_loaded_bootconfig()) @@ -78,7 +86,7 @@ bool bootconfig_take_extabt_serror_to_el3(void); uint64_t bootconfig_get_value_for_sysctr0(void); uint64_t bootconfig_get_memory_arrangement(void); -uint64_t bootconfig_get_kernel_memory_configuration(void); +uint64_t bootconfig_get_kernel_configuration(void); bool bootconfig_is_recovery_boot(void); uint64_t bootconfig_get_boot_reason(void); diff --git a/exosphere/src/configitem.c b/exosphere/src/configitem.c index dc0a07d23..2e3c537ae 100644 --- a/exosphere/src/configitem.c +++ b/exosphere/src/configitem.c @@ -206,8 +206,13 @@ uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue) *p_outvalue = (int)(bootconfig_is_debug_mode()); } break; - case CONFIGITEM_KERNELMEMORYCONFIGURATION: - *p_outvalue = bootconfig_get_kernel_memory_configuration(); + case CONFIGITEM_KERNELCONFIGURATION: + { + uint64_t config = bootconfig_get_kernel_configuration(); + /* Always enable usermode exception handlers. */ + config |= KERNELCONFIGFLAG_ENABLE_USER_EXCEPTION_HANDLERS; + *p_outvalue = config; + } break; case CONFIGITEM_BATTERYPROFILE: *p_outvalue = (int)g_battery_profile; diff --git a/exosphere/src/configitem.h b/exosphere/src/configitem.h index 46dbbd738..2f2ed5c3e 100644 --- a/exosphere/src/configitem.h +++ b/exosphere/src/configitem.h @@ -32,7 +32,7 @@ typedef enum { CONFIGITEM_BOOTREASON = 9, CONFIGITEM_MEMORYARRANGE = 10, CONFIGITEM_ISDEBUGMODE = 11, - CONFIGITEM_KERNELMEMORYCONFIGURATION = 12, + CONFIGITEM_KERNELCONFIGURATION = 12, CONFIGITEM_BATTERYPROFILE = 13, CONFIGITEM_ISQUESTUNIT = 14, CONFIGITEM_NEWHARDWARETYPE_5X = 15, From 67891954ec83035678cb8bd481ec6885d84941ea Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 11 Apr 2019 16:39:59 -0700 Subject: [PATCH 3/6] loader: fix support for 7.0.0+ games with NPDM flag bit 4 set. --- stratosphere/loader/source/ldr_npdm.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/stratosphere/loader/source/ldr_npdm.cpp b/stratosphere/loader/source/ldr_npdm.cpp index 603369f4a..912dc772f 100644 --- a/stratosphere/loader/source/ldr_npdm.cpp +++ b/stratosphere/loader/source/ldr_npdm.cpp @@ -117,8 +117,15 @@ Result NpdmUtils::LoadNpdmInternal(FILE *f_npdm, NpdmUtils::NpdmCache *cache) { return rc; } - if (info->header->mmu_flags > 0xF) { - return rc; + /* 7.0.0 added 0x10 as a valid bit to NPDM flags. */ + if (GetRuntimeFirmwareVersion() >= FirmwareVersion_700) { + if (info->header->mmu_flags > 0x1F) { + return rc; + } + } else { + if (info->header->mmu_flags > 0xF) { + return rc; + } } if (info->header->aci0_offset < sizeof(NpdmUtils::NpdmHeader) || info->header->aci0_size < sizeof(NpdmUtils::NpdmAci0) || info->header->aci0_offset + info->header->aci0_size > npdm_size) { From b03a778611d49449d62d0402661e277c0e2e9a0f Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 11 Apr 2019 16:52:07 -0700 Subject: [PATCH 4/6] Bump version to 0.8.7 --- common/include/atmosphere/version.h | 2 +- docs/changelog.md | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/common/include/atmosphere/version.h b/common/include/atmosphere/version.h index 99ab1f729..9323d4913 100644 --- a/common/include/atmosphere/version.h +++ b/common/include/atmosphere/version.h @@ -19,7 +19,7 @@ #define ATMOSPHERE_RELEASE_VERSION_MAJOR 0 #define ATMOSPHERE_RELEASE_VERSION_MINOR 8 -#define ATMOSPHERE_RELEASE_VERSION_MICRO 6 +#define ATMOSPHERE_RELEASE_VERSION_MICRO 7 #define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 7 #define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 0 diff --git a/docs/changelog.md b/docs/changelog.md index 4ec5e8554..2ada32830 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,4 +1,19 @@ # Changelog +## 0.8.7 ++ A few bugs were fixed that could cause fatal to fail to show an error under certain circumstances. ++ A bug was fixed that caused an error when launching certain games (e.g. Hellblade: Senua's Sacrifice). + + Loader had support added in ams-0.8.4 for a new (7.0.0+) flag bit in NPDMs during process creation, but forgot to allow this bit to be set when validating the NPDM. ++ dmnt's cheat virtual machine received new instructions. + + These allow for saving, restoring, or clearing registers to a secondary bank, effectively doubling the number of values that can be stored. ++ SHA256 code has been swapped from linux code to libnx's new hw-accelerated cryptography API. ++ Extensions were added to smcGetInfo: + + A ConfigItem was added to detect whether the current unit has the RCM bug patched. + + A ConfigItem was added to retrieve the current Atmosphère build hash. ++ Exosphère now tells the kernel to enable user-mode exception handlers, which should allow for better crash reporting/detection from Atmosphère's modules in the future.. ++ Opt-in support was added for redirecting game save files to directories on the SD card. + + Please note, this feature is **experimental**, and may cause problems. Please use at your own risk (and back up your saves before enabling it), as it still needs testing. + + This can be enabled by setting `atmosphere!fsmitm_redirect_saves_to_sd` to 1 in `system_settings.ini`. ++ General system stability improvements to enhance the user's experience. ## 0.8.6 + A number of bugs were fixed, including: + A case of inverted logic was fixed in fs.mitm which prevented the flags system from working correctly. From ac0797121163f0d80fa11bf6158a6620c3a709fc Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 12 Apr 2019 15:28:46 -0700 Subject: [PATCH 5/6] stratosphere: custom exception handlers (reboot to fusee) --- Makefile | 1 + fusee/fusee-primary/src/main.c | 6 +- fusee/fusee-primary/src/panic.c | 60 +++++++++++++++++++ fusee/fusee-primary/src/panic.h | 29 +++++++++ stratosphere/ams_mitm/ams_mitm.json | 1 + stratosphere/ams_mitm/source/amsmitm_main.cpp | 15 +++++ .../source/bpc_mitm/bpc_ams_service.cpp | 32 ++++++++++ .../source/bpc_mitm/bpc_ams_service.hpp | 34 +++++++++++ .../source/bpc_mitm/bpc_mitm_service.hpp | 2 +- .../ams_mitm/source/bpc_mitm/bpcmitm_main.cpp | 5 ++ .../bpc_mitm/bpcmitm_reboot_manager.cpp | 25 +++++++- .../bpc_mitm/bpcmitm_reboot_manager.hpp | 5 +- stratosphere/ams_mitm/source/utils.cpp | 5 ++ stratosphere/ams_mitm/source/utils.hpp | 3 + stratosphere/boot/source/boot_main.cpp | 11 ++++ stratosphere/creport/source/creport_main.cpp | 11 ++++ stratosphere/dmnt/source/dmnt_main.cpp | 11 ++++ stratosphere/eclct.stub/source/eclct_stub.cpp | 11 ++++ stratosphere/fatal/source/fatal_main.cpp | 11 ++++ stratosphere/libstratosphere | 2 +- stratosphere/loader/source/ldr_main.cpp | 14 ++++- stratosphere/pm/source/pm_main.cpp | 11 ++++ stratosphere/sm/source/sm_main.cpp | 13 +++- 23 files changed, 307 insertions(+), 11 deletions(-) create mode 100644 stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_service.cpp create mode 100644 stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_service.hpp diff --git a/Makefile b/Makefile index 1ebf1c635..e38f766b9 100644 --- a/Makefile +++ b/Makefile @@ -53,6 +53,7 @@ dist: all mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000036 mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000034 mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032 + mkdir -p atmosphere-$(AMSVER)/atmosphere/fatal_errors cp fusee/fusee-primary/fusee-primary.bin atmosphere-$(AMSVER)/atmosphere/reboot_payload.bin mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/010000000000000D cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin diff --git a/fusee/fusee-primary/src/main.c b/fusee/fusee-primary/src/main.c index 30d494246..3b4614bc8 100644 --- a/fusee/fusee-primary/src/main.c +++ b/fusee/fusee-primary/src/main.c @@ -90,9 +90,6 @@ static void setup_env(void) { /* Initialize hardware. */ nx_hwinit(); - /* Check for panics. */ - check_and_display_panic(); - /* Zero-fill the framebuffer and register it as printk provider. */ video_init(g_framebuffer); @@ -138,6 +135,9 @@ int main(void) { /* Initialize the display, console, etc. */ setup_env(); + + /* Check for panics. */ + check_and_display_panic(); /* Load the BCT0 configuration ini off of the SD. */ bct0 = load_config(); diff --git a/fusee/fusee-primary/src/panic.c b/fusee/fusee-primary/src/panic.c index cbd81bfb2..706955ced 100644 --- a/fusee/fusee-primary/src/panic.c +++ b/fusee/fusee-primary/src/panic.c @@ -14,15 +14,75 @@ * along with this program. If not, see . */ +#include #include "panic.h" #include "di.h" #include "pmc.h" #include "fuse.h" #include "utils.h" +#include "fs_utils.h" +#include "lib/log.h" static uint32_t g_panic_code = 0; +static const char *get_error_desc_str(uint32_t error_desc) { + switch (error_desc) { + case 0x100: + return "Instruction Abort"; + case 0x101: + return "Data Abort"; + case 0x102: + return "PC Misalignment"; + case 0x103: + return "SP Misalignment"; + case 0x104: + return "Trap"; + case 0x106: + return "SError"; + case 0x301: + return "Bad SVC"; + default: + return "Unknown"; + } +} + +static void _check_and_display_atmosphere_fatal_error(void) { + /* Check for valid magic. */ + if (ATMOSPHERE_FATAL_ERROR_CONTEXT->magic != ATMOSPHERE_REBOOT_TO_FATAL_MAGIC) { + return; + } + + { + /* Copy fatal error context to the stack. */ + atmosphere_fatal_error_ctx ctx = *(ATMOSPHERE_FATAL_ERROR_CONTEXT); + + /* Change magic to invalid, to prevent double-display of error/bootlooping. */ + ATMOSPHERE_FATAL_ERROR_CONTEXT->magic = 0xCCCCCCCC; + + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "A fatal error occurred when running Atmosph\xe8re.\n"); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "Title ID: %016llx\n", ctx.title_id); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "Error Desc: %s (0x%x)\n", get_error_desc_str(ctx.error_desc), ctx.error_desc); + + /* Save context to the SD card. */ + { + char filepath[0x40]; + snprintf(filepath, sizeof(filepath) - 1, "/atmosphere/fatal_errors/report_%016llx.bin", ctx.report_identifier); + filepath[sizeof(filepath)-1] = 0; + write_to_file(&ctx, sizeof(ctx), filepath); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX,"Report saved to %s\n", filepath); + } + + /* Display error. */ + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX,"\nPress POWER to reboot\n"); + } + + wait_for_button_and_reboot(); +} + void check_and_display_panic(void) { + /* Handle a panic sent via a stratosphere module. */ + _check_and_display_atmosphere_fatal_error(); + /* We also handle our own panics. */ /* In the case of our own panics, we assume that the display has already been initialized. */ bool has_panic = APBDEV_PMC_RST_STATUS_0 != 0 || g_panic_code != 0; diff --git a/fusee/fusee-primary/src/panic.h b/fusee/fusee-primary/src/panic.h index 848a3fd81..27d1f4982 100644 --- a/fusee/fusee-primary/src/panic.h +++ b/fusee/fusee-primary/src/panic.h @@ -28,6 +28,35 @@ #define PANIC_CODE_SAFEMODE 0x00000020 +/* Atmosphere reboot-to-fatal-error. */ +typedef struct { + uint32_t magic; + uint32_t error_desc; + uint64_t title_id; + union { + uint64_t gprs[32]; + struct { + uint64_t _gprs[29]; + uint64_t fp; + uint64_t lr; + uint64_t sp; + }; + }; + uint64_t pc; + uint64_t padding; + uint32_t pstate; + uint32_t afsr0; + uint32_t afsr1; + uint32_t esr; + uint64_t far; + uint64_t report_identifier; /* Normally just system tick. */ +} atmosphere_fatal_error_ctx; + +/* "AFE0" */ +#define ATMOSPHERE_REBOOT_TO_FATAL_MAGIC 0x30454641 + +#define ATMOSPHERE_FATAL_ERROR_CONTEXT ((volatile atmosphere_fatal_error_ctx *)(0x4003E000)) + void check_and_display_panic(void); __attribute__ ((noreturn)) void panic(uint32_t code); diff --git a/stratosphere/ams_mitm/ams_mitm.json b/stratosphere/ams_mitm/ams_mitm.json index e2efc65e9..431a1f5f0 100644 --- a/stratosphere/ams_mitm/ams_mitm.json +++ b/stratosphere/ams_mitm/ams_mitm.json @@ -71,6 +71,7 @@ "svcMapDeviceAddressSpaceAligned": "0x5a", "svcUnmapDeviceAddressSpace": "0x5c", "svcGetSystemInfo": "0x6f", + "svcManageNamedPort": "0x71", "svcCallSecureMonitor": "0x7F" } } diff --git a/stratosphere/ams_mitm/source/amsmitm_main.cpp b/stratosphere/ams_mitm/source/amsmitm_main.cpp index 99f342602..d244d3246 100644 --- a/stratosphere/ams_mitm/source/amsmitm_main.cpp +++ b/stratosphere/ams_mitm/source/amsmitm_main.cpp @@ -38,8 +38,23 @@ extern "C" { void __libnx_initheap(void); void __appInit(void); void __appExit(void); + + /* Exception handling. */ + alignas(16) u8 __nx_exception_stack[0x1000]; + u64 __nx_exception_stack_size = sizeof(__nx_exception_stack); + void __libnx_exception_handler(ThreadExceptionDump *ctx); + u64 __stratosphere_title_id = 0x010041544D530000ul; + void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx); } +void __libnx_exception_handler(ThreadExceptionDump *ctx) { + StratosphereCrashHandler(ctx); +} + +void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx) { + /* We're bpc-mitm (or ams_mitm, anyway), so manually reboot to fatal error. */ + Utils::RebootToFatalError(ctx); +} void __libnx_initheap(void) { void* addr = nx_inner_heap; diff --git a/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_service.cpp b/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_service.cpp new file mode 100644 index 000000000..77b9ed30c --- /dev/null +++ b/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_service.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018-2019 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 +#include +#include "bpc_ams_service.hpp" +#include "bpcmitm_reboot_manager.hpp" + +Result BpcAtmosphereService::RebootToFatalError(InBuffer ctx) { + if (ctx.buffer == nullptr || ctx.num_elements != 1) { + return ResultKernelConnectionClosed; + } + + /* Reboot to fusee with the input context. */ + BpcRebootManager::RebootForFatalError(ctx.buffer); + + return ResultSuccess; +} diff --git a/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_service.hpp b/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_service.hpp new file mode 100644 index 000000000..a9dbde26e --- /dev/null +++ b/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_service.hpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018-2019 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 + +#include "../utils.hpp" + +enum BpcAtmosphereCmd : u32 { + BpcAtmosphereCmd_RebootToFatalError = 65000, +}; + +class BpcAtmosphereService : public IServiceObject { + private: + Result RebootToFatalError(InBuffer ctx); + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MakeServiceCommandMeta(), + }; +}; diff --git a/stratosphere/ams_mitm/source/bpc_mitm/bpc_mitm_service.hpp b/stratosphere/ams_mitm/source/bpc_mitm/bpc_mitm_service.hpp index ab2e9c627..7b6589730 100644 --- a/stratosphere/ams_mitm/source/bpc_mitm/bpc_mitm_service.hpp +++ b/stratosphere/ams_mitm/source/bpc_mitm/bpc_mitm_service.hpp @@ -25,7 +25,7 @@ enum BpcCmd : u32 { BpcCmd_RebootSystem = 1, }; -class BpcMitmService : public IMitmServiceObject { +class BpcMitmService : public IMitmServiceObject { public: BpcMitmService(std::shared_ptr s, u64 pid) : IMitmServiceObject(s, pid) { /* ... */ diff --git a/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_main.cpp b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_main.cpp index 5138b0e8a..36c9c0af8 100644 --- a/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_main.cpp +++ b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_main.cpp @@ -25,6 +25,7 @@ #include "bpcmitm_main.hpp" #include "bpc_mitm_service.hpp" +#include "bpc_ams_service.hpp" #include "bpcmitm_reboot_manager.hpp" #include "../utils.hpp" @@ -46,6 +47,10 @@ void BpcMitmMain(void *arg) { } AddMitmServerToManager(server_manager, service_name, 13); + /* Extension: Allow for reboot-to-error. */ + /* Must be managed port in order for sm to be able to access. */ + server_manager->AddWaitable(new ManagedPortServer("bpc:ams", 1)); + /* Loop forever, servicing our services. */ server_manager->Process(); diff --git a/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.cpp b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.cpp index ef91ea801..4c6c71d66 100644 --- a/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.cpp +++ b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.cpp @@ -64,8 +64,8 @@ static void ClearIram() { memset(g_work_page, 0xFF, sizeof(g_work_page)); /* Overwrite all of IRAM with FFs. */ - for (size_t ofs = 0; ofs < IRAM_PAYLOAD_MAX_SIZE; ofs += sizeof(g_work_page)) { - CopyToIram(IRAM_PAYLOAD_BASE + ofs, g_work_page, sizeof(g_work_page)); + for (size_t ofs = 0; ofs < IRAM_SIZE; ofs += sizeof(g_work_page)) { + CopyToIram(IRAM_BASE + ofs, g_work_page, sizeof(g_work_page)); } } @@ -99,3 +99,24 @@ Result BpcRebootManager::PerformReboot() { return ResultSuccess; } } + +void BpcRebootManager::RebootForFatalError(AtmosphereFatalErrorContext *ctx) { + /* If we don't actually have a payload loaded, just go to RCM. */ + if (!g_payload_loaded) { + RebootToRcm(); + } + + /* Ensure clean IRAM state. */ + ClearIram(); + + + /* Copy in payload. */ + for (size_t ofs = 0; ofs < sizeof(g_reboot_payload); ofs += 0x1000) { + CopyToIram(IRAM_PAYLOAD_BASE + ofs, &g_reboot_payload[ofs], 0x1000); + } + + memcpy(g_work_page, ctx, sizeof(*ctx)); + CopyToIram(IRAM_PAYLOAD_BASE + IRAM_PAYLOAD_MAX_SIZE, g_work_page, sizeof(g_work_page)); + + RebootToIramPayload(); +} \ No newline at end of file diff --git a/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.hpp b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.hpp index a8feda168..4eecce70a 100644 --- a/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.hpp +++ b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.hpp @@ -18,7 +18,9 @@ #include #include -#define IRAM_PAYLOAD_MAX_SIZE 0x2F000 +#define IRAM_BASE 0x40000000ull +#define IRAM_SIZE 0x40000 +#define IRAM_PAYLOAD_MAX_SIZE 0x2E000 #define IRAM_PAYLOAD_BASE 0x40010000ull enum class BpcRebootType : u32 { @@ -31,4 +33,5 @@ class BpcRebootManager { public: static void Initialize(); static Result PerformReboot(); + static void RebootForFatalError(AtmosphereFatalErrorContext *ctx); }; \ No newline at end of file diff --git a/stratosphere/ams_mitm/source/utils.cpp b/stratosphere/ams_mitm/source/utils.cpp index 10d795d85..5d50fa178 100644 --- a/stratosphere/ams_mitm/source/utils.cpp +++ b/stratosphere/ams_mitm/source/utils.cpp @@ -25,6 +25,7 @@ #include "ini.h" #include "set_mitm/setsys_settings_items.hpp" +#include "bpc_mitm/bpcmitm_reboot_manager.hpp" static FsFileSystem g_sd_filesystem = {0}; static HosSignal g_sd_signal; @@ -652,3 +653,7 @@ Result Utils::GetSettingsItemBooleanValue(const char *name, const char *key, boo } return rc; } + +void Utils::RebootToFatalError(AtmosphereFatalErrorContext *ctx) { + BpcRebootManager::RebootForFatalError(ctx); +} diff --git a/stratosphere/ams_mitm/source/utils.hpp b/stratosphere/ams_mitm/source/utils.hpp index d44b9219f..04e1faadf 100644 --- a/stratosphere/ams_mitm/source/utils.hpp +++ b/stratosphere/ams_mitm/source/utils.hpp @@ -87,6 +87,9 @@ class Utils { static Result GetSettingsItemValue(const char *name, const char *key, void *out, size_t max_size, u64 *out_size); static Result GetSettingsItemBooleanValue(const char *name, const char *key, bool *out); + + /* Error occurred. */ + static void RebootToFatalError(AtmosphereFatalErrorContext *ctx); private: static void RefreshConfiguration(); }; \ No newline at end of file diff --git a/stratosphere/boot/source/boot_main.cpp b/stratosphere/boot/source/boot_main.cpp index 4bf7ffa83..862809d76 100644 --- a/stratosphere/boot/source/boot_main.cpp +++ b/stratosphere/boot/source/boot_main.cpp @@ -49,6 +49,17 @@ extern "C" { void __libnx_initheap(void); void __appInit(void); void __appExit(void); + + /* Exception handling. */ + alignas(16) u8 __nx_exception_stack[0x1000]; + u64 __nx_exception_stack_size = sizeof(__nx_exception_stack); + void __libnx_exception_handler(ThreadExceptionDump *ctx); + u64 __stratosphere_title_id = TitleId_Boot; + void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx); +} + +void __libnx_exception_handler(ThreadExceptionDump *ctx) { + StratosphereCrashHandler(ctx); } void __libnx_initheap(void) { diff --git a/stratosphere/creport/source/creport_main.cpp b/stratosphere/creport/source/creport_main.cpp index 610e47e84..662705fbc 100644 --- a/stratosphere/creport/source/creport_main.cpp +++ b/stratosphere/creport/source/creport_main.cpp @@ -38,6 +38,17 @@ extern "C" { void __libnx_initheap(void); void __appInit(void); void __appExit(void); + + /* Exception handling. */ + alignas(16) u8 __nx_exception_stack[0x1000]; + u64 __nx_exception_stack_size = sizeof(__nx_exception_stack); + void __libnx_exception_handler(ThreadExceptionDump *ctx); + u64 __stratosphere_title_id = TitleId_Creport; + void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx); +} + +void __libnx_exception_handler(ThreadExceptionDump *ctx) { + StratosphereCrashHandler(ctx); } diff --git a/stratosphere/dmnt/source/dmnt_main.cpp b/stratosphere/dmnt/source/dmnt_main.cpp index b027e9d89..77571d4ed 100644 --- a/stratosphere/dmnt/source/dmnt_main.cpp +++ b/stratosphere/dmnt/source/dmnt_main.cpp @@ -40,6 +40,17 @@ extern "C" { void __libnx_initheap(void); void __appInit(void); void __appExit(void); + + /* Exception handling. */ + alignas(16) u8 __nx_exception_stack[0x1000]; + u64 __nx_exception_stack_size = sizeof(__nx_exception_stack); + void __libnx_exception_handler(ThreadExceptionDump *ctx); + u64 __stratosphere_title_id = TitleId_Dmnt; + void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx); +} + +void __libnx_exception_handler(ThreadExceptionDump *ctx) { + StratosphereCrashHandler(ctx); } diff --git a/stratosphere/eclct.stub/source/eclct_stub.cpp b/stratosphere/eclct.stub/source/eclct_stub.cpp index 2dfbcc81e..fd6d73bbe 100644 --- a/stratosphere/eclct.stub/source/eclct_stub.cpp +++ b/stratosphere/eclct.stub/source/eclct_stub.cpp @@ -35,6 +35,17 @@ extern "C" { void __libnx_initheap(void); void __appInit(void); void __appExit(void); + + /* Exception handling. */ + alignas(16) u8 __nx_exception_stack[0x1000]; + u64 __nx_exception_stack_size = sizeof(__nx_exception_stack); + void __libnx_exception_handler(ThreadExceptionDump *ctx); + u64 __stratosphere_title_id = TitleId_Eclct; + void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx); +} + +void __libnx_exception_handler(ThreadExceptionDump *ctx) { + StratosphereCrashHandler(ctx); } diff --git a/stratosphere/fatal/source/fatal_main.cpp b/stratosphere/fatal/source/fatal_main.cpp index 554237c62..2f49576f7 100644 --- a/stratosphere/fatal/source/fatal_main.cpp +++ b/stratosphere/fatal/source/fatal_main.cpp @@ -45,6 +45,17 @@ extern "C" { void __libnx_initheap(void); void __appInit(void); void __appExit(void); + + /* Exception handling. */ + alignas(16) u8 __nx_exception_stack[0x1000]; + u64 __nx_exception_stack_size = sizeof(__nx_exception_stack); + void __libnx_exception_handler(ThreadExceptionDump *ctx); + u64 __stratosphere_title_id = TitleId_Fatal; + void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx); +} + +void __libnx_exception_handler(ThreadExceptionDump *ctx) { + StratosphereCrashHandler(ctx); } diff --git a/stratosphere/libstratosphere b/stratosphere/libstratosphere index 1f9e2d042..b9724cdca 160000 --- a/stratosphere/libstratosphere +++ b/stratosphere/libstratosphere @@ -1 +1 @@ -Subproject commit 1f9e2d042cb028cee1777b3d63a7cda06d2cffd0 +Subproject commit b9724cdcadd5ea5fbead8f1a9c9b7de11daf6b60 diff --git a/stratosphere/loader/source/ldr_main.cpp b/stratosphere/loader/source/ldr_main.cpp index 2a030552e..a278f6295 100644 --- a/stratosphere/loader/source/ldr_main.cpp +++ b/stratosphere/loader/source/ldr_main.cpp @@ -41,6 +41,16 @@ extern "C" { void __appInit(void); void __appExit(void); + /* Exception handling. */ + alignas(16) u8 __nx_exception_stack[0x1000]; + u64 __nx_exception_stack_size = sizeof(__nx_exception_stack); + void __libnx_exception_handler(ThreadExceptionDump *ctx); + u64 __stratosphere_title_id = TitleId_Loader; + void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx); +} + +void __libnx_exception_handler(ThreadExceptionDump *ctx) { + StratosphereCrashHandler(ctx); } @@ -103,9 +113,9 @@ struct LoaderServerOptions { int main(int argc, char **argv) { consoleDebugInit(debugDevice_SVC); - + auto server_manager = new WaitableManager(1); - + /* Add services to manager. */ server_manager->AddWaitable(new ServiceServer("ldr:pm", 1)); server_manager->AddWaitable(new ServiceServer("ldr:shel", 3)); diff --git a/stratosphere/pm/source/pm_main.cpp b/stratosphere/pm/source/pm_main.cpp index 4f1e34581..3aac9a359 100644 --- a/stratosphere/pm/source/pm_main.cpp +++ b/stratosphere/pm/source/pm_main.cpp @@ -42,6 +42,17 @@ extern "C" { void __libnx_initheap(void); void __appInit(void); void __appExit(void); + + /* Exception handling. */ + alignas(16) u8 __nx_exception_stack[0x1000]; + u64 __nx_exception_stack_size = sizeof(__nx_exception_stack); + void __libnx_exception_handler(ThreadExceptionDump *ctx); + u64 __stratosphere_title_id = TitleId_Pm; + void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx); +} + +void __libnx_exception_handler(ThreadExceptionDump *ctx) { + StratosphereCrashHandler(ctx); } diff --git a/stratosphere/sm/source/sm_main.cpp b/stratosphere/sm/source/sm_main.cpp index 981a6f777..be0d8815e 100644 --- a/stratosphere/sm/source/sm_main.cpp +++ b/stratosphere/sm/source/sm_main.cpp @@ -39,6 +39,17 @@ extern "C" { void __libnx_initheap(void); void __appInit(void); void __appExit(void); + + /* Exception handling. */ + alignas(16) u8 __nx_exception_stack[0x1000]; + u64 __nx_exception_stack_size = sizeof(__nx_exception_stack); + void __libnx_exception_handler(ThreadExceptionDump *ctx); + u64 __stratosphere_title_id = TitleId_Sm; + void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx); +} + +void __libnx_exception_handler(ThreadExceptionDump *ctx) { + StratosphereCrashHandler(ctx); } @@ -73,7 +84,7 @@ int main(int argc, char **argv) /* TODO: What's a good timeout value to use here? */ auto server_manager = new WaitableManager(1); - + /* Create sm:, (and thus allow things to register to it). */ server_manager->AddWaitable(new ManagedPortServer("sm:", 0x40)); From d0659377e86429739584c36ce9173ecd9f502f47 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 12 Apr 2019 23:04:12 -0700 Subject: [PATCH 6/6] creport: speed up code region detection (closes #491) --- stratosphere/creport/source/creport_code_info.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/creport/source/creport_code_info.cpp b/stratosphere/creport/source/creport_code_info.cpp index b0a858855..f59aaeaf1 100644 --- a/stratosphere/creport/source/creport_code_info.cpp +++ b/stratosphere/creport/source/creport_code_info.cpp @@ -136,7 +136,7 @@ bool CodeList::TryFindCodeRegion(Handle debug_handle, u64 guess, u64 *address) { return true; } - guess -= 4; + guess = mi.addr - 4; } return false; }