From e2b17086d45601c6dfc74f8af2274dcae130f724 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Mon, 29 Jun 2020 23:19:33 -0700 Subject: [PATCH] fs: implement AccessLog, enable for File operations --- libraries/config/common.mk | 2 +- .../include/stratosphere/fs.hpp | 7 + .../include/stratosphere/fs/fs_access_log.hpp | 33 + .../include/stratosphere/fs/fs_context.hpp | 68 ++ .../include/stratosphere/fs/fs_priority.hpp | 44 ++ .../stratosphere/fs/fs_result_config.hpp | 24 + .../fs/impl/fs_access_log_impl.hpp | 153 ++++ .../fs/impl/fs_fs_inline_context_utils.hpp | 46 ++ .../fs/impl/fs_priority_utils.hpp | 68 ++ .../stratosphere/fs/impl/fs_result_utils.hpp | 77 +++ .../include/stratosphere/os.hpp | 3 +- .../os/os_sdk_thread_local_storage.hpp | 47 ++ .../os/os_sdk_thread_local_storage_api.hpp | 26 + .../os/os_thread_local_storage.hpp | 47 ++ .../stratosphere/os/os_thread_types.hpp | 6 + .../stratosphere/sf/sf_fs_inline_context.hpp | 12 +- .../source/fs/fs_access_log.cpp | 528 ++++++++++++++ .../libstratosphere/source/fs/fs_context.cpp | 74 ++ .../libstratosphere/source/fs/fs_priority.cpp | 160 +++++ .../source/fs/fs_result_utils.cpp | 69 ++ .../source/fs/fsa/fs_directory_accessor.hpp | 2 +- .../source/fs/fsa/fs_filesystem_accessor.hpp | 2 +- .../source/fs/fsa/fs_user_file.cpp | 24 +- .../source/ncm/ncm_content_meta_utils.cpp | 2 +- .../source/ncm/ncm_install_task_base.cpp | 2 +- .../source/os/impl/os_thread_manager.cpp | 3 + .../os/os_sdk_thread_local_storage_api.cpp | 26 + .../source/sf/cmif/sf_cmif_inline_context.cpp | 65 +- .../libvapours/include/vapours/defines.hpp | 3 + .../libvapours/include/vapours/includes.hpp | 1 + .../include/vapours/results/fs_results.hpp | 653 +++++++++--------- stratosphere/ams_mitm/source/amsmitm_main.cpp | 3 + stratosphere/fatal/source/fatal_main.cpp | 3 + stratosphere/loader/source/ldr_main.cpp | 3 + stratosphere/ncm/source/ncm_main.cpp | 3 + stratosphere/pgl/source/pgl_main.cpp | 3 + 36 files changed, 1930 insertions(+), 362 deletions(-) create mode 100644 libraries/libstratosphere/include/stratosphere/fs/fs_access_log.hpp create mode 100644 libraries/libstratosphere/include/stratosphere/fs/fs_context.hpp create mode 100644 libraries/libstratosphere/include/stratosphere/fs/fs_priority.hpp create mode 100644 libraries/libstratosphere/include/stratosphere/fs/fs_result_config.hpp create mode 100644 libraries/libstratosphere/include/stratosphere/fs/impl/fs_access_log_impl.hpp create mode 100644 libraries/libstratosphere/include/stratosphere/fs/impl/fs_fs_inline_context_utils.hpp create mode 100644 libraries/libstratosphere/include/stratosphere/fs/impl/fs_priority_utils.hpp create mode 100644 libraries/libstratosphere/include/stratosphere/fs/impl/fs_result_utils.hpp create mode 100644 libraries/libstratosphere/include/stratosphere/os/os_sdk_thread_local_storage.hpp create mode 100644 libraries/libstratosphere/include/stratosphere/os/os_sdk_thread_local_storage_api.hpp create mode 100644 libraries/libstratosphere/include/stratosphere/os/os_thread_local_storage.hpp create mode 100644 libraries/libstratosphere/source/fs/fs_access_log.cpp create mode 100644 libraries/libstratosphere/source/fs/fs_context.cpp create mode 100644 libraries/libstratosphere/source/fs/fs_priority.cpp create mode 100644 libraries/libstratosphere/source/fs/fs_result_utils.cpp create mode 100644 libraries/libstratosphere/source/os/os_sdk_thread_local_storage_api.cpp diff --git a/libraries/config/common.mk b/libraries/config/common.mk index 9e8a0af3c..8973da718 100644 --- a/libraries/config/common.mk +++ b/libraries/config/common.mk @@ -19,7 +19,7 @@ export ATMOSPHERE_DEFINES := -DATMOSPHERE export ATMOSPHERE_SETTINGS := -fPIE -g export ATMOSPHERE_CFLAGS := -Wall -ffunction-sections -fdata-sections -fno-strict-aliasing -fwrapv \ -fno-asynchronous-unwind-tables -fno-unwind-tables -fno-stack-protector \ - -Wno-format-truncation + -Wno-format-truncation -Wno-format-zero-length export ATMOSPHERE_CXXFLAGS := -fno-rtti -fno-exceptions -std=gnu++20 export ATMOSPHERE_ASFLAGS := diff --git a/libraries/libstratosphere/include/stratosphere/fs.hpp b/libraries/libstratosphere/include/stratosphere/fs.hpp index faa1f851a..176588fe7 100644 --- a/libraries/libstratosphere/include/stratosphere/fs.hpp +++ b/libraries/libstratosphere/include/stratosphere/fs.hpp @@ -16,7 +16,13 @@ #pragma once #include +#include +#include +#include #include +#include +#include +#include #include #include #include @@ -54,3 +60,4 @@ #include #include #include +#include diff --git a/libraries/libstratosphere/include/stratosphere/fs/fs_access_log.hpp b/libraries/libstratosphere/include/stratosphere/fs/fs_access_log.hpp new file mode 100644 index 000000000..5900d6de1 --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/fs/fs_access_log.hpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018-2020 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 + +namespace ams::fs { + + enum AccessLogMode : u32 { + AccessLogMode_None = 0, + AccessLogMode_Log = 1, + AccessLogMode_SdCard = 2, + }; + + Result GetGlobalAccessLogMode(u32 *out); + Result SetGlobalAccessLogMode(u32 mode); + + void SetLocalAccessLog(bool enabled); + void SetLocalSystemAccessLogForDebug(bool enabled); + +} diff --git a/libraries/libstratosphere/include/stratosphere/fs/fs_context.hpp b/libraries/libstratosphere/include/stratosphere/fs/fs_context.hpp new file mode 100644 index 000000000..9ce9dfc46 --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/fs/fs_context.hpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018-2020 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 + +namespace ams::fs { + + enum class AbortSpecifier { + Default, + Abort, + Return, + }; + + using ResultHandler = AbortSpecifier (*)(Result); + + class FsContext { + private: + ResultHandler handler; + public: + constexpr explicit FsContext(ResultHandler h) : handler(h) { /* ... */ } + + constexpr void SetHandler(ResultHandler h) { this->handler = h; } + + constexpr AbortSpecifier HandleResult(Result result) const { return this->handler(result); } + }; + + void SetDefaultFsContextResultHandler(const ResultHandler handler); + + const FsContext *GetCurrentThreadFsContext(); + void SetCurrentThreadFsContext(const FsContext *context); + + class ScopedFsContext { + private: + const FsContext * const prev_context; + public: + ALWAYS_INLINE ScopedFsContext(const FsContext &ctx) : prev_context(GetCurrentThreadFsContext()) { + SetCurrentThreadFsContext(std::addressof(ctx)); + } + + ALWAYS_INLINE ~ScopedFsContext() { + SetCurrentThreadFsContext(this->prev_context); + } + }; + + class ScopedAutoAbortDisabler { + private: + const FsContext * const prev_context; + public: + ScopedAutoAbortDisabler(); + ALWAYS_INLINE ~ScopedAutoAbortDisabler() { + SetCurrentThreadFsContext(this->prev_context); + } + }; + +} diff --git a/libraries/libstratosphere/include/stratosphere/fs/fs_priority.hpp b/libraries/libstratosphere/include/stratosphere/fs/fs_priority.hpp new file mode 100644 index 000000000..84e707dd2 --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/fs/fs_priority.hpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018-2020 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 + +namespace ams::fs { + + enum Priority { + Priority_Realtime = 0, + Priority_Normal = 1, + Priority_Low = 2, + }; + + enum PriorityRaw { + PriorityRaw_Realtime = 0, + PriorityRaw_Normal = 1, + PriorityRaw_Low = 2, + PriorityRaw_Background = 3, + }; + + Priority GetPriorityOnCurrentThread(); + Priority GetPriority(os::ThreadType *thread); + PriorityRaw GetPriorityRawOnCurrentThread(); + PriorityRaw GetPriorityRaw(os::ThreadType *thread); + + void SetPriorityOnCurrentThread(Priority prio); + void SetPriority(os::ThreadType *thread, Priority prio); + void SetPriorityRawOnCurrentThread(PriorityRaw prio); + void SetPriorityRaw(os::ThreadType *thread, PriorityRaw prio); + +} diff --git a/libraries/libstratosphere/include/stratosphere/fs/fs_result_config.hpp b/libraries/libstratosphere/include/stratosphere/fs/fs_result_config.hpp new file mode 100644 index 000000000..ab89bfc92 --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/fs/fs_result_config.hpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018-2020 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 + +namespace ams::fs { + + void SetEnabledAutoAbort(bool enabled); + void SetResultHandledByApplication(bool application); + +} diff --git a/libraries/libstratosphere/include/stratosphere/fs/impl/fs_access_log_impl.hpp b/libraries/libstratosphere/include/stratosphere/fs/impl/fs_access_log_impl.hpp new file mode 100644 index 000000000..9410043c5 --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/fs/impl/fs_access_log_impl.hpp @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2018-2020 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 +#include +#include +#include + +namespace ams::fs::impl { + + enum AccessLogTarget : u32 { + AccessLogTarget_None = (0 << 0), + AccessLogTarget_Application = (1 << 0), + AccessLogTarget_System = (1 << 1), + }; + + struct IdentifyAccessLogHandle { + void *handle; + public: + static constexpr IdentifyAccessLogHandle MakeHandle(void *h) { + return IdentifyAccessLogHandle{h}; + } + }; + + bool IsEnabledAccessLog(u32 target); + bool IsEnabledAccessLog(); + + bool IsEnabledHandleAccessLog(fs::FileHandle handle); + bool IsEnabledHandleAccessLog(fs::DirectoryHandle handle); + bool IsEnabledHandleAccessLog(fs::impl::IdentifyAccessLogHandle handle); + bool IsEnabledHandleAccessLog(const void *handle); + + bool IsEnabledFileSystemAccessorAccessLog(const char *mount_name); + void EnableFileSystemAccessorAccessLog(const char *mount_name); + + using AccessLogPrinterCallback = int (*)(char *buffer, size_t buffer_size); + void RegisterStartAccessLogPrinterCallback(AccessLogPrinterCallback callback); + + void OutputAccessLog(Result result, os::Tick start, os::Tick end, const char *name, fs::FileHandle handle, const char *fmt, ...) __attribute__((format (printf, 6, 7))); + void OutputAccessLog(Result result, os::Tick start, os::Tick end, const char *name, fs::DirectoryHandle handle, const char *fmt, ...) __attribute__((format (printf, 6, 7))); + void OutputAccessLog(Result result, os::Tick start, os::Tick end, const char *name, fs::impl::IdentifyAccessLogHandle handle, const char *fmt, ...) __attribute__((format (printf, 6, 7))); + void OutputAccessLog(Result result, os::Tick start, os::Tick end, const char *name, const void *handle, const char *fmt, ...) __attribute__((format (printf, 6, 7))); + void OutputAccessLog(Result result, fs::Priority priority, os::Tick start, os::Tick end, const char *name, const void *handle, const char *fmt, ...) __attribute__((format (printf, 7, 8))); + void OutputAccessLog(Result result, fs::PriorityRaw priority_raw, os::Tick start, os::Tick end, const char *name, const void *handle, const char *fmt, ...) __attribute__((format (printf, 7, 8))); + + void OutputAccessLogToOnlySdCard(const char *fmt, ...) __attribute__((format (printf, 1, 2))); + + void OutputAccessLogUnlessResultSuccess(Result result, os::Tick start, os::Tick end, const char *name, fs::FileHandle handle, const char *fmt, ...) __attribute__((format (printf, 6, 7))); + void OutputAccessLogUnlessResultSuccess(Result result, os::Tick start, os::Tick end, const char *name, fs::DirectoryHandle handle, const char *fmt, ...) __attribute__((format (printf, 6, 7))); + void OutputAccessLogUnlessResultSuccess(Result result, os::Tick start, os::Tick end, const char *name, const void *handle, const char *fmt, ...) __attribute__((format (printf, 6, 7))); + + class IdString { + private: + char buffer[0x20]; + private: + const char *ToValueString(int id); + public: + template + const char *ToString(T id); + }; + +} + +/* Access log components. */ +#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_SIZE ", size: %" PRId64 "" +#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_OFFSET_AND_SIZE ", offset: %" PRId64 ", size: %zu" +#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_THREAD_ID ", thread_id: %" PRIu64 "" + +/* Access log formats. */ +#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_NONE "" + +#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_WRITE_FILE_WITH_NO_OPTION AMS_FS_IMPL_ACCESS_LOG_FORMAT_OFFSET_AND_SIZE +#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_WRITE_FILE_WITH_FLUSH_OPTION AMS_FS_IMPL_ACCESS_LOG_FORMAT_WRITE_FILE_WITH_NO_OPTION ", write_option: Flush" +#define AMS_FS_IMPL_ACCESS_LOG_FORMAT_WRITE_FILE(__OPTION__) ((__OPTION__).HasFlushFlag() ? AMS_FS_IMPL_ACCESS_LOG_FORMAT_WRITE_FILE_WITH_FLUSH_OPTION : AMS_FS_IMPL_ACCESS_LOG_FORMAT_WRITE_FILE_WITH_NO_OPTION) + +/* Access log invocation lambdas. */ +#define AMS_FS_IMPL_ACCESS_LOG_IMPL(__EXPR__, __HANDLE__, __ENABLED__, __NAME__, ...) \ + [&](const char *name) { \ + if (!(__ENABLED__)) { \ + return (__EXPR__); \ + } else { \ + const ::ams::os::Tick start = ::ams::os::GetSystemTick(); \ + const auto result = (__EXPR__); \ + const ::ams::os::Tick end = ::ams::os::GetSystemTick(); \ + ::ams::fs::impl::OutputAccessLog(result, start, end, name, __HANDLE__, __VA_ARGS__); \ + return result; \ + } \ + }(__NAME__) + +#define AMS_FS_IMPL_ACCESS_LOG_WITH_PRIORITY_IMPL(__EXPR__, __PRIORITY__, __HANDLE__, __ENABLED__, __NAME__, ...) \ + [&](const char *name) { \ + if (!(__ENABLED__)) { \ + return (__EXPR__); \ + } else { \ + const ::ams::os::Tick start = ::ams::os::GetSystemTick(); \ + const auto result = (__EXPR__); \ + const ::ams::os::Tick end = ::ams::os::GetSystemTick(); \ + ::ams::fs::impl::OutputAccessLog(result, __PRIORITY__, start, end, name, __HANDLE__, __VA_ARGS__); \ + return result; \ + } \ + }(__NAME__) + +#define AMS_FS_IMPL_ACCESS_LOG_EXPLICIT_IMPL(__RESULT__, __START__, __END__, __HANDLE__, __ENABLED__, __NAME__, ...) \ + [&](const char *name) { \ + if (!(__ENABLED__)) { \ + return __RESULT__; \ + } else { \ + ::ams::fs::impl::OutputAccessLog(__RESULT__, __START__, __END__, name, __HANDLE__, __VA_ARGS__); \ + return __RESULT__; \ + } \ + }(__NAME__) + +#define AMS_FS_IMPL_ACCESS_LOG_UNLESS_R_SUCCEEDED_IMPL(__EXPR__, __ENABLED__, __NAME__, ...) \ + [&](const char *name) { \ + if (!(__ENABLED__)) { \ + return (__EXPR__); \ + } else { \ + const ::ams::os::Tick start = ::ams::os::GetSystemTick(); \ + const auto result = (__EXPR__); \ + const ::ams::os::Tick end = ::ams::os::GetSystemTick(); \ + ::ams::fs::impl::OutputAccessLogUnlessResultSuccess(result, start, end, name, nullptr, __VA_ARGS__); \ + return result; \ + } \ + }(__NAME__) + + +/* Access log api. */ +#define AMS_FS_IMPL_ACCESS_LOG(__EXPR__, __HANDLE__, ...) \ + AMS_FS_IMPL_ACCESS_LOG_IMPL((__EXPR__), __HANDLE__, ::ams::fs::impl::IsEnabledAccessLog() && ::ams::fs::impl::IsEnabledHandleAccessLog(__HANDLE__), AMS_CURRENT_FUNCTION_NAME, __VA_ARGS__) + +#define AMS_FS_IMPL_ACCESS_LOG_WITH_NAME(__EXPR__, __HANDLE__, __NAME__, ...) \ + AMS_FS_IMPL_ACCESS_LOG_IMPL((__EXPR__), __HANDLE__, ::ams::fs::impl::IsEnabledAccessLog() && ::ams::fs::impl::IsEnabledHandleAccessLog(__HANDLE__), __NAME__, __VA_ARGS__) + +#define AMS_FS_IMPL_ACCESS_LOG_EXPLICIT(__RESULT__, __START__, __END__, __HANDLE__, __NAME__, ...) \ + AMS_FS_IMPL_ACCESS_LOG_EXPLICIT_IMPL((__RESULT__), __START__, __END__, __HANDLE__, ::ams::fs::impl::IsEnabledAccessLog() && ::ams::fs::impl::IsEnabledHandleAccessLog(__HANDLE__), __NAME__, __VA_ARGS__) + +#define AMS_FS_IMPL_ACCESS_LOG_UNLESS_R_SUCCEEDED(__EXPR__, ...) \ + AMS_FS_IMPL_ACCESS_LOG_UNLESS_R_SUCCEEDED_IMPL((__EXPR__), ::ams::fs::impl::IsEnabledAccessLog(), AMS_CURRENT_FUNCTION_NAME, __VA_ARGS__) diff --git a/libraries/libstratosphere/include/stratosphere/fs/impl/fs_fs_inline_context_utils.hpp b/libraries/libstratosphere/include/stratosphere/fs/impl/fs_fs_inline_context_utils.hpp new file mode 100644 index 000000000..eae1f0d3f --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/fs/impl/fs_fs_inline_context_utils.hpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2018-2020 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 + +namespace ams::fs::impl { + + constexpr inline u8 TlsIoPriorityMask = 0x7; + constexpr inline u8 TlsIoRecursiveCallMask = 0x8; + + struct TlsIoValueForInheritance { + u8 _tls_value; + }; + + inline void SetCurrentRequestRecursive() { + os::ThreadType * const cur_thread = os::GetCurrentThread(); + sf::SetFsInlineContext(cur_thread, TlsIoRecursiveCallMask | sf::GetFsInlineContext(cur_thread)); + } + + inline bool IsCurrentRequestRecursive() { + return (sf::GetFsInlineContext(os::GetCurrentThread()) & TlsIoRecursiveCallMask) != 0; + } + + inline TlsIoValueForInheritance GetTlsIoValueForInheritance() { + return TlsIoValueForInheritance { sf::GetFsInlineContext(os::GetCurrentThread()) }; + } + + inline void SetTlsIoValueForInheritance(TlsIoValueForInheritance tls_io) { + sf::SetFsInlineContext(os::GetCurrentThread(), tls_io._tls_value); + } + +} diff --git a/libraries/libstratosphere/include/stratosphere/fs/impl/fs_priority_utils.hpp b/libraries/libstratosphere/include/stratosphere/fs/impl/fs_priority_utils.hpp new file mode 100644 index 000000000..84d15b5f6 --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/fs/impl/fs_priority_utils.hpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018-2020 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 + +namespace ams::fs::impl { + + enum TlsIoPriority : u8 { + TlsIoPriority_Normal = 0, + TlsIoPriority_Realtime = 1, + TlsIoPriority_Low = 2, + TlsIoPriority_Background = 3, + }; + + /* Ensure that TlsIo priority matches libnx priority. */ + static_assert(TlsIoPriority_Normal == static_cast(::FsPriority_Normal)); + static_assert(TlsIoPriority_Realtime == static_cast(::FsPriority_Realtime)); + static_assert(TlsIoPriority_Low == static_cast(::FsPriority_Low)); + static_assert(TlsIoPriority_Background == static_cast(::FsPriority_Background)); + + constexpr inline Result ConvertFsPriorityToTlsIoPriority(u8 *out, PriorityRaw priority) { + AMS_ASSERT(out != nullptr); + + switch (priority) { + case PriorityRaw_Normal: *out = TlsIoPriority_Normal; + case PriorityRaw_Realtime: *out = TlsIoPriority_Realtime; + case PriorityRaw_Low: *out = TlsIoPriority_Low; + case PriorityRaw_Background: *out = TlsIoPriority_Background; + default: return fs::ResultInvalidArgument(); + } + + return ResultSuccess(); + } + + constexpr inline Result ConvertTlsIoPriorityToFsPriority(PriorityRaw *out, u8 tls_io) { + AMS_ASSERT(out != nullptr); + + switch (static_cast(tls_io)) { + case TlsIoPriority_Normal: *out = PriorityRaw_Normal; + case TlsIoPriority_Realtime: *out = PriorityRaw_Realtime; + case TlsIoPriority_Low: *out = PriorityRaw_Low; + case TlsIoPriority_Background: *out = PriorityRaw_Background; + default: return fs::ResultInvalidArgument(); + } + + return ResultSuccess(); + } + + inline u8 GetTlsIoPriority(os::ThreadType *thread) { + return sf::GetFsInlineContext(thread) & TlsIoPriorityMask; + } + +} diff --git a/libraries/libstratosphere/include/stratosphere/fs/impl/fs_result_utils.hpp b/libraries/libstratosphere/include/stratosphere/fs/impl/fs_result_utils.hpp new file mode 100644 index 000000000..3313ef62f --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/fs/impl/fs_result_utils.hpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018-2020 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 + +namespace ams::fs::impl { + + bool IsAbortNeeded(Result result); + void LogErrorMessage(Result result, const char *function); + +} + +#define AMS_FS_R_CHECK_ABORT_IMPL(__RESULT__, __FORCE__) \ + ({ \ + if (::ams::fs::impl::IsAbortNeeded(__RESULT__) || (__FORCE__)) { \ + ::ams::fs::impl::LogErrorMessage(__RESULT__, AMS_CURRENT_FUNCTION_NAME); \ + R_ABORT_UNLESS(__RESULT__); \ + } \ + }) + +#define AMS_FS_R_TRY(__RESULT__) \ + ({ \ + const ::ams::Result __tmp_fs_result = (__RESULT__); \ + AMS_FS_R_CHECK_ABORT_IMPL(__tmp_fs_result, false); \ + R_TRY(__tmp_fs_result); \ + }) + +#define AMS_FS_R_ABORT_UNLESS(__RESULT__) \ + ({ \ + const ::ams::Result __tmp_fs_result = (__RESULT__); \ + AMS_FS_R_CHECK_ABORT_IMPL(__tmp_fs_result, true); \ + }) + +#define AMS_FS_R_THROW(__RESULT__) \ + ({ \ + const ::ams::Result __tmp_fs_result = (__RESULT__); \ + AMS_FS_R_CHECK_ABORT_IMPL(__tmp_fs_result, false); \ + return __tmp_fs_result; \ + }) + +#define AMS_FS_R_UNLESS(__EXPR__, __RESULT__) \ + ({ \ + if (!(__EXPR__)) { \ + AMS_FS_R_THROW((__RESULT__)); \ + } \ + }) + +#define AMS_FS_R_TRY_CATCH(__EXPR__) R_TRY_CATCH(__EXPR__) + +#define AMS_FS_R_CATCH(...) R_CATCH(__VA_ARGS__) + +#define AMS_FS_R_END_TRY_CATCH \ + else if (R_FAILED(R_CURRENT_RESULT)) { \ + AMS_FS_R_THROW(R_CURRENT_RESULT); \ + } \ + } \ + }) + +#define AMS_FS_R_END_TRY_CATCH_WITH_ABORT_UNLESS \ + else { \ + AMS_FS_R_ABORT_UNLESS(R_CURRENT_RESULT); \ + } \ + } \ + }) diff --git a/libraries/libstratosphere/include/stratosphere/os.hpp b/libraries/libstratosphere/include/stratosphere/os.hpp index 0e3c22d36..ea37812ac 100644 --- a/libraries/libstratosphere/include/stratosphere/os.hpp +++ b/libraries/libstratosphere/include/stratosphere/os.hpp @@ -35,7 +35,8 @@ #include #include #include -#include +#include +#include #include #include #include diff --git a/libraries/libstratosphere/include/stratosphere/os/os_sdk_thread_local_storage.hpp b/libraries/libstratosphere/include/stratosphere/os/os_sdk_thread_local_storage.hpp new file mode 100644 index 000000000..d55e312fd --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/os/os_sdk_thread_local_storage.hpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018-2020 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 + +namespace ams::os { + + class SdkThreadLocalStorage { + NON_COPYABLE(SdkThreadLocalStorage); + NON_MOVEABLE(SdkThreadLocalStorage); + private: + TlsSlot tls_slot; + public: + SdkThreadLocalStorage() { + R_ABORT_UNLESS(os::SdkAllocateTlsSlot(std::addressof(this->tls_slot), nullptr)); + } + + explicit SdkThreadLocalStorage(TlsDestructor destructor) { + R_ABORT_UNLESS(os::SdkAllocateTlsSlot(std::addressof(this->tls_slot), destructor)); + } + + ~SdkThreadLocalStorage() { + os::FreeTlsSlot(this->tls_slot); + } + + uintptr_t GetValue() const { return os::GetTlsValue(this->tls_slot); } + void SetValue(uintptr_t value) { return os::SetTlsValue(this->tls_slot, value); } + + TlsSlot GetTlsSlot() const { return this->tls_slot; } + }; + +} diff --git a/libraries/libstratosphere/include/stratosphere/os/os_sdk_thread_local_storage_api.hpp b/libraries/libstratosphere/include/stratosphere/os/os_sdk_thread_local_storage_api.hpp new file mode 100644 index 000000000..174142204 --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/os/os_sdk_thread_local_storage_api.hpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018-2020 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 + +namespace ams::os { + + Result SdkAllocateTlsSlot(TlsSlot *out, TlsDestructor destructor); + +} diff --git a/libraries/libstratosphere/include/stratosphere/os/os_thread_local_storage.hpp b/libraries/libstratosphere/include/stratosphere/os/os_thread_local_storage.hpp new file mode 100644 index 000000000..641974c68 --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/os/os_thread_local_storage.hpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018-2020 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 + +namespace ams::os { + + class ThreadLocalStorage { + NON_COPYABLE(ThreadLocalStorage); + NON_MOVEABLE(ThreadLocalStorage); + private: + TlsSlot tls_slot; + public: + ThreadLocalStorage() { + R_ABORT_UNLESS(os::AllocateTlsSlot(std::addressof(this->tls_slot), nullptr)); + } + + explicit ThreadLocalStorage(TlsDestructor destructor) { + R_ABORT_UNLESS(os::AllocateTlsSlot(std::addressof(this->tls_slot), destructor)); + } + + ~ThreadLocalStorage() { + os::FreeTlsSlot(this->tls_slot); + } + + uintptr_t GetValue() const { return os::GetTlsValue(this->tls_slot); } + void SetValue(uintptr_t value) { return os::SetTlsValue(this->tls_slot, value); } + + TlsSlot GetTlsSlot() const { return this->tls_slot; } + }; + +} diff --git a/libraries/libstratosphere/include/stratosphere/os/os_thread_types.hpp b/libraries/libstratosphere/include/stratosphere/os/os_thread_types.hpp index c687add16..08f1f6329 100644 --- a/libraries/libstratosphere/include/stratosphere/os/os_thread_types.hpp +++ b/libraries/libstratosphere/include/stratosphere/os/os_thread_types.hpp @@ -57,6 +57,12 @@ namespace ams::os { size_t stack_size; ThreadFunction function; void *argument; + + /* NOTE: Here, Nintendo stores the TLS array. This is handled by libnx in our case. */ + /* However, we need to access certain values in other threads' TLS (Nintendo uses a hardcoded layout for SDK tls members...) */ + /* These members are tls slot holders in sdk code, but just normal thread type members under our scheme. */ + uintptr_t atomic_sf_inline_context; + mutable impl::InternalCriticalSectionStorage cs_thread; mutable impl::InternalConditionVariableStorage cv_thread; diff --git a/libraries/libstratosphere/include/stratosphere/sf/sf_fs_inline_context.hpp b/libraries/libstratosphere/include/stratosphere/sf/sf_fs_inline_context.hpp index 376246dfc..11d0aac6d 100644 --- a/libraries/libstratosphere/include/stratosphere/sf/sf_fs_inline_context.hpp +++ b/libraries/libstratosphere/include/stratosphere/sf/sf_fs_inline_context.hpp @@ -17,9 +17,15 @@ #pragma once #include -namespace ams::sf { +namespace ams::os { - u8 GetFsInlineContext(); - u8 SetFsInlineContext(u8 ctx); + struct ThreadType; + +} + +namespace ams::sf { + + u8 GetFsInlineContext(os::ThreadType *thread); + u8 SetFsInlineContext(os::ThreadType *thread, u8 ctx); } diff --git a/libraries/libstratosphere/source/fs/fs_access_log.cpp b/libraries/libstratosphere/source/fs/fs_access_log.cpp new file mode 100644 index 000000000..9a0524a0a --- /dev/null +++ b/libraries/libstratosphere/source/fs/fs_access_log.cpp @@ -0,0 +1,528 @@ +/* + * Copyright (c) 2018-2020 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 "fsa/fs_user_mount_table.hpp" +#include "fsa/fs_directory_accessor.hpp" +#include "fsa/fs_file_accessor.hpp" +#include "fsa/fs_filesystem_accessor.hpp" + +#define AMS_FS_IMPL_ACCESS_LOG_AMS_API_VERSION "ams_version: " STRINGIZE(ATMOSPHERE_RELEASE_VERSION_MAJOR) "." STRINGIZE(ATMOSPHERE_RELEASE_VERSION_MINOR) "." STRINGIZE(ATMOSPHERE_RELEASE_VERSION_MICRO) + +/* TODO: Other boards? */ +#define AMS_FS_IMPL_ACCESS_LOG_SPEC "spec: NX" + +namespace ams::fs { + + /* Forward declare priority getter. */ + fs::PriorityRaw GetPriorityRawOnCurrentThreadInternal(); + + namespace { + + constinit u32 g_global_access_log_mode = fs::AccessLogMode_None; + constinit u32 g_local_access_log_target = fs::impl::AccessLogTarget_None; + + constinit std::atomic_bool g_access_log_initialized = false; + constinit os::SdkMutex g_access_log_initialization_mutex; + + void SetLocalAccessLogImpl(bool enabled) { + if (enabled) { + g_local_access_log_target |= fs::impl::AccessLogTarget_Application; + } else { + g_local_access_log_target &= ~fs::impl::AccessLogTarget_Application; + } + } + + } + + Result GetGlobalAccessLogMode(u32 *out) { + /* Use libnx bindings. */ + return ::fsGetGlobalAccessLogMode(out); + } + + Result SetGlobalAccessLogMode(u32 mode) { + /* Use libnx bindings. */ + return ::fsSetGlobalAccessLogMode(mode); + } + + void SetLocalAccessLog(bool enabled) { + SetLocalAccessLogImpl(enabled); + } + + void SetLocalApplicationAccessLog(bool enabled) { + SetLocalAccessLogImpl(enabled); + } + + void SetLocalSystemAccessLogForDebug(bool enabled) { + #if defined(AMS_BUILD_FOR_DEBUGGING) + if (enabled) { + g_local_access_log_target |= (fs::impl::AccessLogTarget_Application | fs::impl::AccessLogTarget_System); + } else { + g_local_access_log_target &= ~(fs::impl::AccessLogTarget_Application | fs::impl::AccessLogTarget_System); + } + #endif + } + +} + +namespace ams::fs::impl { + + const char *IdString::ToValueString(int id) { + const int len = std::snprintf(this->buffer, sizeof(this->buffer), "%d", id); + AMS_ASSERT(static_cast(len) < sizeof(this->buffer)); + return this->buffer; + } + + template<> const char *IdString::ToString(fs::Priority id) { + switch (id) { + case fs::Priority_Realtime: return "Realtime"; + case fs::Priority_Normal: return "Normal"; + case fs::Priority_Low: return "Low"; + default: return ToValueString(static_cast(id)); + } + } + + template<> const char *IdString::ToString(fs::PriorityRaw id) { + switch (id) { + case fs::PriorityRaw_Realtime: return "Realtime"; + case fs::PriorityRaw_Normal: return "Normal"; + case fs::PriorityRaw_Low: return "Low"; + case fs::PriorityRaw_Background: return "Realtime"; + default: return ToValueString(static_cast(id)); + } + } + + template<> const char *IdString::ToString(fs::ContentStorageId id) { + switch (id) { + case fs::ContentStorageId::User: return "User"; + case fs::ContentStorageId::System: return "System"; + case fs::ContentStorageId::SdCard: return "SdCard"; + default: return ToValueString(static_cast(id)); + } + } + + template<> const char *IdString::ToString(fs::SaveDataSpaceId id) { + switch (id) { + case fs::SaveDataSpaceId::System: return "System"; + case fs::SaveDataSpaceId::User: return "User"; + case fs::SaveDataSpaceId::SdSystem: return "SdSystem"; + case fs::SaveDataSpaceId::ProperSystem: return "ProperSystem"; + default: return ToValueString(static_cast(id)); + } + } + + template<> const char *IdString::ToString(fs::ContentType id) { + switch (id) { + case fs::ContentType_Meta: return "Meta"; + case fs::ContentType_Control: return "Control"; + case fs::ContentType_Manual: return "Manual"; + case fs::ContentType_Logo: return "Logo"; + case fs::ContentType_Data: return "Data"; + default: return ToValueString(static_cast(id)); + } + } + + template<> const char *IdString::ToString(fs::BisPartitionId id) { + switch (id) { + case fs::BisPartitionId::BootPartition1Root: return "BootPartition1Root"; + case fs::BisPartitionId::BootPartition2Root: return "BootPartition2Root"; + case fs::BisPartitionId::UserDataRoot: return "UserDataRoot"; + case fs::BisPartitionId::BootConfigAndPackage2Part1: return "BootConfigAndPackage2Part1"; + case fs::BisPartitionId::BootConfigAndPackage2Part2: return "BootConfigAndPackage2Part2"; + case fs::BisPartitionId::BootConfigAndPackage2Part3: return "BootConfigAndPackage2Part3"; + case fs::BisPartitionId::BootConfigAndPackage2Part4: return "BootConfigAndPackage2Part4"; + case fs::BisPartitionId::BootConfigAndPackage2Part5: return "BootConfigAndPackage2Part5"; + case fs::BisPartitionId::BootConfigAndPackage2Part6: return "BootConfigAndPackage2Part6"; + case fs::BisPartitionId::CalibrationBinary: return "CalibrationBinary"; + case fs::BisPartitionId::CalibrationFile: return "CalibrationFile"; + case fs::BisPartitionId::SafeMode: return "SafeMode"; + case fs::BisPartitionId::User: return "User"; + case fs::BisPartitionId::System: return "System"; + case fs::BisPartitionId::SystemProperEncryption: return "SystemProperEncryption"; + case fs::BisPartitionId::SystemProperPartition: return "SystemProperPartition"; + default: return ToValueString(static_cast(id)); + } + } + + namespace { + + class AccessLogPrinterCallbackManager { + private: + AccessLogPrinterCallback callback; + public: + constexpr AccessLogPrinterCallbackManager() : callback(nullptr) { /* ... */ } + + constexpr bool IsRegisteredCallback() const { return this->callback != nullptr; } + + constexpr void RegisterCallback(AccessLogPrinterCallback c) { + AMS_ASSERT(this->callback == nullptr); + this->callback = c; + } + + constexpr int InvokeCallback(char *buf, size_t size) const { + AMS_ASSERT(this->callback != nullptr); + return this->callback(buf, size); + } + }; + + constinit AccessLogPrinterCallbackManager g_access_log_manager_printer_callback_manager; + + ALWAYS_INLINE AccessLogPrinterCallbackManager &GetStartAccessLogPrinterCallbackManager() { + return g_access_log_manager_printer_callback_manager; + } + + const char *GetPriorityRawName() { + return fs::impl::IdString().ToString(fs::GetPriorityRawOnCurrentThreadInternal()); + } + + Result OutputAccessLogToSdCardImpl(const char *log, size_t size) { + /* Use libnx bindings. */ + return ::fsOutputAccessLogToSdCard(log, size); + } + + void OutputAccessLogToSdCard(const char *format, std::va_list vl) { + if ((g_global_access_log_mode & AccessLogMode_SdCard) != 0) { + /* Create a buffer to hold the log's input string. */ + int log_buffer_size = 1_KB; + auto log_buffer = fs::impl::MakeUnique(log_buffer_size); + while (true) { + if (log_buffer == nullptr) { + return; + } + + const auto size = std::vsnprintf(log_buffer.get(), log_buffer_size, format, vl); + if (size < log_buffer_size) { + break; + } + + log_buffer_size = size + 1; + log_buffer = fs::impl::MakeUnique(log_buffer_size); + } + + /* Output. */ + OutputAccessLogToSdCardImpl(log_buffer.get(), log_buffer_size - 1); + } + } + + void OutputAccessLogImpl(const char *log, size_t size) { + if ((g_global_access_log_mode & AccessLogMode_Log) != 0) { + /* TODO: Support logging. */ + } else if ((g_global_access_log_mode & AccessLogMode_SdCard) != 0) { + OutputAccessLogToSdCardImpl(log, size - 1); + } + } + + void OutputAccessLog(Result result, const char *priority, os::Tick start, os::Tick end, const char *name, const void *handle, const char *format, std::va_list vl) { + /* Create a buffer to hold the log's input string. */ + int str_buffer_size = 1_KB; + auto str_buffer = fs::impl::MakeUnique(str_buffer_size); + while (true) { + if (str_buffer == nullptr) { + return; + } + + const auto size = std::vsnprintf(str_buffer.get(), str_buffer_size, format, vl); + if (size < str_buffer_size) { + break; + } + + str_buffer_size = size + 1; + str_buffer = fs::impl::MakeUnique(str_buffer_size); + } + + /* Create a buffer to hold the log. */ + int log_buffer_size = 0; + decltype(str_buffer) log_buffer; + { + /* Declare format string. */ + constexpr const char FormatString[] = "FS_ACCESS { " + "start: %9" PRId64 ", " + "end: %9" PRId64 ", " + "result: 0x%08" PRIX32 ", " + "handle: 0x%p, " + "priority: %s, " + "function: \"%s\"" + "%s" + " }\n"; + + /* Convert the timing to ms. */ + const s64 start_ms = start.ToTimeSpan().GetMilliSeconds(); + const s64 end_ms = end.ToTimeSpan().GetMilliSeconds(); + + /* Print the log. */ + int try_size = std::max(str_buffer_size + sizeof(FormatString) + 0x100, 1_KB); + while (true) { + log_buffer = fs::impl::MakeUnique(try_size); + if (log_buffer == nullptr) { + return; + } + + log_buffer_size = 1 + std::snprintf(log_buffer.get(), try_size, FormatString, start_ms, end_ms, result.GetValue(), handle, priority, name, str_buffer.get()); + if (log_buffer_size <= try_size) { + break; + } + try_size = log_buffer_size; + } + } + + OutputAccessLogImpl(log_buffer.get(), log_buffer_size); + } + + void GetProgramIndexFortAccessLog(u32 *out_index, u32 *out_count) { + if (hos::GetVersion() >= hos::Version_7_0_0) { + /* Use libnx bindings if available. */ + R_ABORT_UNLESS(::fsGetProgramIndexForAccessLog(out_index, out_count)); + } else { + /* Use hardcoded defaults. */ + *out_index = 0; + *out_count = 0; + } + } + + void OutputAccessLogStart() { + /* Get the program index. */ + u32 program_index = 0, program_count = 0; + GetProgramIndexFortAccessLog(std::addressof(program_index), std::addressof(program_count)); + + /* Print the log buffer. */ + if (program_count < 2) { + constexpr const char StartLog[] = "FS_ACCESS: { " + AMS_FS_IMPL_ACCESS_LOG_AMS_API_VERSION ", " + AMS_FS_IMPL_ACCESS_LOG_SPEC + " }\n"; + + OutputAccessLogImpl(StartLog, sizeof(StartLog)); + } else { + constexpr const char StartLog[] = "FS_ACCESS: { " + AMS_FS_IMPL_ACCESS_LOG_AMS_API_VERSION ", " + AMS_FS_IMPL_ACCESS_LOG_SPEC ", " + "program_index: %d" + " }\n"; + + char log_buffer[0x80]; + const int len = 1 + std::snprintf(log_buffer, sizeof(log_buffer), StartLog, static_cast(program_index)); + if (static_cast(len) <= sizeof(log_buffer)) { + OutputAccessLogImpl(log_buffer, len); + } + } + } + + [[maybe_unused]] void OutputAccessLogStartForSystem() { + constexpr const char StartLog[] = "FS_ACCESS: { " + AMS_FS_IMPL_ACCESS_LOG_AMS_API_VERSION ", " + AMS_FS_IMPL_ACCESS_LOG_SPEC ", " + "for_system: true" + " }\n"; + OutputAccessLogImpl(StartLog, sizeof(StartLog)); + } + + void OutputAccessLogStartGeneratedByCallback() { + /* Get the manager. */ + const auto &manager = GetStartAccessLogPrinterCallbackManager(); + if (manager.IsRegisteredCallback()) { + /* Invoke the callback. */ + char log_buffer[0x80]; + const int len = 1 + manager.InvokeCallback(log_buffer, sizeof(log_buffer)); + + /* Print, if we fit. */ + if (static_cast(len) <= sizeof(log_buffer)) { + OutputAccessLogImpl(log_buffer, len); + } + } + } + + } + + bool IsEnabledAccessLog(u32 target) { + /* If we don't need to log to the target, return false. */ + if ((g_local_access_log_target & target) == 0) { + return false; + } + + /* Ensure we've initialized. */ + if (!g_access_log_initialized) { + std::scoped_lock lk(g_access_log_initialization_mutex); + if (!g_access_log_initialized) { + + #if defined (AMS_BUILD_FOR_DEBUGGING) + if ((g_local_access_log_target & fs::impl::AccessLogTarget_System) != 0) + { + g_global_access_log_mode = AccessLogMode_Log; + OutputAccessLogStartForSystem(); + OutputAccessLogStartGeneratedByCallback(); + } + else + #endif + { + AMS_FS_R_ABORT_UNLESS(GetGlobalAccessLogMode(std::addressof(g_global_access_log_mode))); + if (g_global_access_log_mode != AccessLogMode_None) { + OutputAccessLogStart(); + OutputAccessLogStartGeneratedByCallback(); + } + } + + g_access_log_initialized = true; + } + } + + return g_global_access_log_mode != AccessLogMode_None; + } + + bool IsEnabledAccessLog() { + return IsEnabledAccessLog(fs::impl::AccessLogTarget_Application | fs::impl::AccessLogTarget_System); + } + + void RegisterStartAccessLogPrinterCallback(AccessLogPrinterCallback callback) { + GetStartAccessLogPrinterCallbackManager().RegisterCallback(callback); + } + + void OutputAccessLog(Result result, fs::Priority priority, os::Tick start, os::Tick end, const char *name, const void *handle, const char *fmt, ...) { + std::va_list vl; + va_start(vl, fmt); + OutputAccessLog(result, fs::impl::IdString().ToString(priority), start, end, name, handle, fmt, vl); + va_end(vl); + } + + void OutputAccessLog(Result result, fs::PriorityRaw priority_raw, os::Tick start, os::Tick end, const char *name, const void *handle, const char *fmt, ...){ + std::va_list vl; + va_start(vl, fmt); + OutputAccessLog(result, fs::impl::IdString().ToString(priority_raw), start, end, name, handle, fmt, vl); + va_end(vl); + } + + void OutputAccessLog(Result result, os::Tick start, os::Tick end, const char *name, fs::FileHandle handle, const char *fmt, ...) { + std::va_list vl; + va_start(vl, fmt); + OutputAccessLog(result, GetPriorityRawName(), start, end, name, handle.handle, fmt, vl); + va_end(vl); + } + + void OutputAccessLog(Result result, os::Tick start, os::Tick end, const char *name, fs::DirectoryHandle handle, const char *fmt, ...) { + std::va_list vl; + va_start(vl, fmt); + OutputAccessLog(result, GetPriorityRawName(), start, end, name, handle.handle, fmt, vl); + va_end(vl); + } + + void OutputAccessLog(Result result, os::Tick start, os::Tick end, const char *name, fs::impl::IdentifyAccessLogHandle handle, const char *fmt, ...) { + std::va_list vl; + va_start(vl, fmt); + OutputAccessLog(result, GetPriorityRawName(), start, end, name, handle.handle, fmt, vl); + va_end(vl); + } + + void OutputAccessLog(Result result, os::Tick start, os::Tick end, const char *name, const void *handle, const char *fmt, ...) { + std::va_list vl; + va_start(vl, fmt); + OutputAccessLog(result, GetPriorityRawName(), start, end, name, handle, fmt, vl); + va_end(vl); + } + + void OutputAccessLogToOnlySdCard(const char *fmt, ...) { + std::va_list vl; + va_start(vl, fmt); + OutputAccessLogToSdCard(fmt, vl); + va_end(vl); + } + + void OutputAccessLogUnlessResultSuccess(Result result, os::Tick start, os::Tick end, const char *name, fs::FileHandle handle, const char *fmt, ...) { + if (R_FAILED(result)) { + std::va_list vl; + va_start(vl, fmt); + OutputAccessLog(result, GetPriorityRawName(), start, end, name, handle.handle, fmt, vl); + va_end(vl); + } + } + + void OutputAccessLogUnlessResultSuccess(Result result, os::Tick start, os::Tick end, const char *name, fs::DirectoryHandle handle, const char *fmt, ...) { + if (R_FAILED(result)) { + std::va_list vl; + va_start(vl, fmt); + OutputAccessLog(result, GetPriorityRawName(), start, end, name, handle.handle, fmt, vl); + va_end(vl); + } + } + + void OutputAccessLogUnlessResultSuccess(Result result, os::Tick start, os::Tick end, const char *name, const void *handle, const char *fmt, ...) { + if (R_FAILED(result)) { + std::va_list vl; + va_start(vl, fmt); + OutputAccessLog(result, GetPriorityRawName(), start, end, name, handle, fmt, vl); + va_end(vl); + } + } + + bool IsEnabledHandleAccessLog(fs::FileHandle handle) { + /* Get the file accessor. */ + impl::FileAccessor *accessor = reinterpret_cast(handle.handle); + if (accessor == nullptr) { + return true; + } + + /* Check the parent. */ + if (auto *parent = accessor->GetParent(); parent != nullptr) { + return parent->IsEnabledAccessLog(); + } else { + return false; + } + } + + bool IsEnabledHandleAccessLog(fs::DirectoryHandle handle) { + /* Get the file accessor. */ + impl::DirectoryAccessor *accessor = reinterpret_cast(handle.handle); + if (accessor == nullptr) { + return true; + } + + /* Check the parent. */ + if (auto *parent = accessor->GetParent(); parent != nullptr) { + return parent->IsEnabledAccessLog(); + } else { + return false; + } + } + + bool IsEnabledHandleAccessLog(fs::impl::IdentifyAccessLogHandle handle) { + return true; + } + + bool IsEnabledHandleAccessLog(const void *handle) { + if (handle == nullptr) { + return true; + } + + /* We should never receive non-null here. */ + AMS_ASSERT(handle == nullptr); + return false; + } + + bool IsEnabledFileSystemAccessorAccessLog(const char *mount_name) { + /* Get the accessor. */ + impl::FileSystemAccessor *accessor; + if (R_FAILED(impl::Find(std::addressof(accessor), mount_name))) { + return true; + } + + return accessor->IsEnabledAccessLog(); + } + + void EnableFileSystemAccessorAccessLog(const char *mount_name) { + /* Get the accessor. */ + impl::FileSystemAccessor *accessor; + AMS_FS_R_ABORT_UNLESS(impl::Find(std::addressof(accessor), mount_name)); + accessor->SetAccessLogEnabled(true); + } + +} diff --git a/libraries/libstratosphere/source/fs/fs_context.cpp b/libraries/libstratosphere/source/fs/fs_context.cpp new file mode 100644 index 000000000..7e00d708b --- /dev/null +++ b/libraries/libstratosphere/source/fs/fs_context.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018-2020 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 + +namespace ams::fs { + + namespace { + + constinit bool g_auto_abort_enabled = true; + + /* NOTE: This generates a global constructor. */ + os::SdkThreadLocalStorage g_context_tls; + + } + + void SetEnabledAutoAbort(bool enabled) { + g_auto_abort_enabled = enabled; + } + + AbortSpecifier DefaultResultHandler(Result result) { + if (g_auto_abort_enabled) { + return AbortSpecifier::Default; + } else { + return AbortSpecifier::Return; + } + } + + AbortSpecifier AlwaysReturnResultHandler(Result result) { + return AbortSpecifier::Return; + } + + constinit FsContext g_default_context(DefaultResultHandler); + constinit FsContext g_always_return_context(AlwaysReturnResultHandler); + + void SetDefaultFsContextResultHandler(const ResultHandler handler) { + if (handler == nullptr) { + g_default_context.SetHandler(DefaultResultHandler); + } else { + g_default_context.SetHandler(handler); + } + } + + const FsContext *GetCurrentThreadFsContext() { + const FsContext *context = reinterpret_cast(g_context_tls.GetValue()); + + if (context == nullptr) { + context = std::addressof(g_default_context); + } + + return context; + } + + void SetCurrentThreadFsContext(const FsContext *context) { + g_context_tls.SetValue(reinterpret_cast(context)); + } + + ScopedAutoAbortDisabler::ScopedAutoAbortDisabler() : prev_context(GetCurrentThreadFsContext()) { + SetCurrentThreadFsContext(std::addressof(g_always_return_context)); + } + +} diff --git a/libraries/libstratosphere/source/fs/fs_priority.cpp b/libraries/libstratosphere/source/fs/fs_priority.cpp new file mode 100644 index 000000000..3f3686262 --- /dev/null +++ b/libraries/libstratosphere/source/fs/fs_priority.cpp @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2018-2020 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 + +namespace ams::fs { + + namespace { + + constexpr bool IsValidPriority(fs::Priority priority) { + return priority == Priority_Low || priority == Priority_Normal || priority == Priority_Realtime; + } + + constexpr bool IsValidPriorityRaw(fs::PriorityRaw priority_raw) { + return priority_raw == PriorityRaw_Background || priority_raw == PriorityRaw_Low || priority_raw == PriorityRaw_Normal || priority_raw == PriorityRaw_Realtime; + } + + fs::PriorityRaw ConvertPriorityToPriorityRaw(fs::Priority priority) { + AMS_ASSERT(IsValidPriority(priority)); + + switch (priority) { + case Priority_Low: return PriorityRaw_Low; + case Priority_Normal: return PriorityRaw_Normal; + case Priority_Realtime: return PriorityRaw_Realtime; + AMS_UNREACHABLE_DEFAULT_CASE(); + } + } + + fs::Priority ConvertPriorityRawToPriority(fs::PriorityRaw priority_raw) { + AMS_ASSERT(IsValidPriorityRaw(priority_raw)); + + switch (priority_raw) { + case PriorityRaw_Background: return Priority_Low; + case PriorityRaw_Low: return Priority_Low; + case PriorityRaw_Normal: return Priority_Normal; + case PriorityRaw_Realtime: return Priority_Realtime; + AMS_UNREACHABLE_DEFAULT_CASE(); + } + } + + void UpdateTlsIoPriority(os::ThreadType *thread, u8 tls_io) { + sf::SetFsInlineContext(thread, (tls_io & impl::TlsIoPriorityMask) | (sf::GetFsInlineContext(thread) & ~impl::TlsIoPriorityMask)); + } + + Result GetPriorityRawImpl(fs::PriorityRaw *out, os::ThreadType *thread) { + /* Validate arguments. */ + R_UNLESS(thread != nullptr, fs::ResultNullptrArgument()); + + /* Get the raw priority. */ + PriorityRaw priority_raw; + R_TRY(impl::ConvertTlsIoPriorityToFsPriority(std::addressof(priority_raw), impl::GetTlsIoPriority(thread))); + + /* Set output. */ + *out = priority_raw; + return ResultSuccess(); + } + + Result GetPriorityImpl(fs::Priority *out, os::ThreadType *thread) { + /* Validate arguments. */ + R_UNLESS(thread != nullptr, fs::ResultNullptrArgument()); + + /* Get the raw priority. */ + PriorityRaw priority_raw; + R_TRY(impl::ConvertTlsIoPriorityToFsPriority(std::addressof(priority_raw), impl::GetTlsIoPriority(thread))); + + /* Set output. */ + *out = ConvertPriorityRawToPriority(priority_raw); + return ResultSuccess(); + } + + Result SetPriorityRawImpl(os::ThreadType *thread, fs::PriorityRaw priority_raw) { + /* Validate arguments. */ + R_UNLESS(thread != nullptr, fs::ResultNullptrArgument()); + R_UNLESS(IsValidPriorityRaw(priority_raw), fs::ResultInvalidArgument()); + + /* Convert to tls io. */ + u8 tls_io; + R_TRY(impl::ConvertFsPriorityToTlsIoPriority(std::addressof(tls_io), priority_raw)); + + /* Update the priority. */ + UpdateTlsIoPriority(thread, tls_io); + return ResultSuccess(); + } + + Result SetPriorityImpl(os::ThreadType *thread, fs::Priority priority) { + /* Validate arguments. */ + R_UNLESS(thread != nullptr, fs::ResultNullptrArgument()); + R_UNLESS(IsValidPriority(priority), fs::ResultInvalidArgument()); + + /* Convert to tls io. */ + u8 tls_io; + R_TRY(impl::ConvertFsPriorityToTlsIoPriority(std::addressof(tls_io), ConvertPriorityToPriorityRaw(priority))); + + /* Update the priority. */ + UpdateTlsIoPriority(thread, tls_io); + return ResultSuccess(); + } + + } + + Priority GetPriorityOnCurrentThread() { + fs::Priority priority; + AMS_FS_R_ABORT_UNLESS(AMS_FS_IMPL_ACCESS_LOG(GetPriorityImpl(std::addressof(priority), os::GetCurrentThread()), nullptr, AMS_FS_IMPL_ACCESS_LOG_FORMAT_NONE)); + return priority; + } + + Priority GetPriority(os::ThreadType *thread) { + fs::Priority priority; + AMS_FS_R_ABORT_UNLESS(AMS_FS_IMPL_ACCESS_LOG(GetPriorityImpl(std::addressof(priority), thread), nullptr, AMS_FS_IMPL_ACCESS_LOG_FORMAT_THREAD_ID, thread != nullptr ? os::GetThreadId(thread) : static_cast(0))); + return priority; + } + + PriorityRaw GetPriorityRawOnCurrentThread() { + fs::PriorityRaw priority_raw; + AMS_FS_R_ABORT_UNLESS(AMS_FS_IMPL_ACCESS_LOG(GetPriorityRawImpl(std::addressof(priority_raw), os::GetCurrentThread()), nullptr, AMS_FS_IMPL_ACCESS_LOG_FORMAT_NONE)); + return priority_raw; + } + + PriorityRaw GetPriorityRawOnCurrentThreadInternal() { + fs::PriorityRaw priority_raw; + AMS_FS_R_ABORT_UNLESS(GetPriorityRawImpl(std::addressof(priority_raw), os::GetCurrentThread())); + return priority_raw; + + } + + PriorityRaw GetPriorityRaw(os::ThreadType *thread) { + fs::PriorityRaw priority_raw; + AMS_FS_R_ABORT_UNLESS(AMS_FS_IMPL_ACCESS_LOG(GetPriorityRawImpl(std::addressof(priority_raw), thread), nullptr, AMS_FS_IMPL_ACCESS_LOG_FORMAT_THREAD_ID, thread != nullptr ? os::GetThreadId(thread) : static_cast(0))); + return priority_raw; + } + + void SetPriorityOnCurrentThread(Priority priority) { + AMS_FS_R_ABORT_UNLESS(AMS_FS_IMPL_ACCESS_LOG(SetPriorityImpl(os::GetCurrentThread(), priority), nullptr, AMS_FS_IMPL_ACCESS_LOG_FORMAT_NONE)); + } + + void SetPriority(os::ThreadType *thread, Priority priority) { + AMS_FS_R_ABORT_UNLESS(AMS_FS_IMPL_ACCESS_LOG(SetPriorityImpl(os::GetCurrentThread(), priority), nullptr, AMS_FS_IMPL_ACCESS_LOG_FORMAT_THREAD_ID, thread != nullptr ? os::GetThreadId(thread) : static_cast(0))); + } + + void SetPriorityRawOnCurrentThread(PriorityRaw priority_raw) { + AMS_FS_R_ABORT_UNLESS(AMS_FS_IMPL_ACCESS_LOG(SetPriorityRawImpl(os::GetCurrentThread(), priority_raw), nullptr, AMS_FS_IMPL_ACCESS_LOG_FORMAT_NONE)); + } + + void SetPriorityRaw(os::ThreadType *thread, PriorityRaw priority_raw) { + AMS_FS_R_ABORT_UNLESS(AMS_FS_IMPL_ACCESS_LOG(SetPriorityRawImpl(os::GetCurrentThread(), priority_raw), nullptr, AMS_FS_IMPL_ACCESS_LOG_FORMAT_THREAD_ID, thread != nullptr ? os::GetThreadId(thread) : static_cast(0))); + } + +} diff --git a/libraries/libstratosphere/source/fs/fs_result_utils.cpp b/libraries/libstratosphere/source/fs/fs_result_utils.cpp new file mode 100644 index 000000000..c6e1b4f70 --- /dev/null +++ b/libraries/libstratosphere/source/fs/fs_result_utils.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018-2020 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 + +namespace ams::fs { + + namespace { + + constinit bool g_handled_by_application = false; + + } + + void SetResultHandledByApplication(bool application) { + g_handled_by_application = application; + } + + namespace impl { + + bool IsAbortNeeded(Result result) { + /* If the result succeeded, we never need to abort. */ + if (R_SUCCEEDED(result)) { + return false; + } + + /* Get the abort specifier from current context. */ + switch (GetCurrentThreadFsContext()->HandleResult(result)) { + case AbortSpecifier::Default: + if (g_handled_by_application) { + return !fs::ResultHandledByAllProcess::Includes(result); + } else { + return !(fs::ResultHandledByAllProcess::Includes(result) || fs::ResultHandledBySystemProcess::Includes(result)); + } + case AbortSpecifier::Abort: + return true; + case AbortSpecifier::Return: + return false; + AMS_UNREACHABLE_DEFAULT_CASE(); + } + } + + void LogResultErrorMessage(Result result) { + /* TODO: log specific results */ + } + + void LogErrorMessage(Result result, const char *function) { + /* If the result succeeded, there's nothing to log. */ + if (R_SUCCEEDED(result)) { + return; + } + + /* TODO: Actually log stuff. */ + } + + } + +} diff --git a/libraries/libstratosphere/source/fs/fsa/fs_directory_accessor.hpp b/libraries/libstratosphere/source/fs/fsa/fs_directory_accessor.hpp index 77bc44af5..c47dc6699 100644 --- a/libraries/libstratosphere/source/fs/fsa/fs_directory_accessor.hpp +++ b/libraries/libstratosphere/source/fs/fsa/fs_directory_accessor.hpp @@ -32,7 +32,7 @@ namespace ams::fs::impl { Result Read(s64 *out_count, DirectoryEntry *out_entries, s64 max_entries); Result GetEntryCount(s64 *out); - FileSystemAccessor &GetParent() const { return this->parent; } + FileSystemAccessor *GetParent() const { return std::addressof(this->parent); } }; } diff --git a/libraries/libstratosphere/source/fs/fsa/fs_filesystem_accessor.hpp b/libraries/libstratosphere/source/fs/fsa/fs_filesystem_accessor.hpp index 5302af4a3..856059c16 100644 --- a/libraries/libstratosphere/source/fs/fsa/fs_filesystem_accessor.hpp +++ b/libraries/libstratosphere/source/fs/fsa/fs_filesystem_accessor.hpp @@ -71,7 +71,7 @@ namespace ams::fs::impl { void SetPathBasedFileDataCacheAttachable(bool en) { this->path_cache_attachable = en; } void SetMultiCommitSupported(bool en) { this->multi_commit_supported = en; } - bool IsAccessLogEnabled() const { return this->access_log_enabled; } + bool IsEnabledAccessLog() const { return this->access_log_enabled; } bool IsFileDataCacheAttachable() const { return this->data_cache_attachable; } bool IsPathBasedFileDataCacheAttachable() const { return this->path_cache_attachable; } diff --git a/libraries/libstratosphere/source/fs/fsa/fs_user_file.cpp b/libraries/libstratosphere/source/fs/fsa/fs_user_file.cpp index 7e2a816ca..b10a28f0b 100644 --- a/libraries/libstratosphere/source/fs/fsa/fs_user_file.cpp +++ b/libraries/libstratosphere/source/fs/fsa/fs_user_file.cpp @@ -29,8 +29,8 @@ namespace ams::fs { Result ReadFile(FileHandle handle, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) { size_t read_size; - R_TRY(ReadFile(std::addressof(read_size), handle, offset, buffer, size, option)); - R_UNLESS(read_size == size, fs::ResultOutOfRange()); + AMS_FS_R_TRY(ReadFile(std::addressof(read_size), handle, offset, buffer, size, option)); + AMS_FS_R_UNLESS(read_size == size, fs::ResultOutOfRange()); return ResultSuccess(); } @@ -39,7 +39,8 @@ namespace ams::fs { } Result ReadFile(size_t *out, FileHandle handle, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) { - return Get(handle)->Read(out, offset, buffer, size, option); + AMS_FS_R_TRY(Get(handle)->Read(out, offset, buffer, size, option)); + return ResultSuccess(); } Result ReadFile(size_t *out, FileHandle handle, s64 offset, void *buffer, size_t size) { @@ -47,19 +48,23 @@ namespace ams::fs { } Result GetFileSize(s64 *out, FileHandle handle) { - return Get(handle)->GetSize(out); + AMS_FS_R_TRY(Get(handle)->GetSize(out)); + return ResultSuccess(); } Result FlushFile(FileHandle handle) { - return Get(handle)->Flush(); + AMS_FS_R_TRY(AMS_FS_IMPL_ACCESS_LOG(Get(handle)->Flush(), handle, AMS_FS_IMPL_ACCESS_LOG_FORMAT_NONE)); + return ResultSuccess(); } Result WriteFile(FileHandle handle, s64 offset, const void *buffer, size_t size, const fs::WriteOption &option) { - return Get(handle)->Write(offset, buffer, size, option); + AMS_FS_R_TRY(AMS_FS_IMPL_ACCESS_LOG(Get(handle)->Write(offset, buffer, size, option), handle, AMS_FS_IMPL_ACCESS_LOG_FORMAT_WRITE_FILE(option), offset, size)); + return ResultSuccess(); } Result SetFileSize(FileHandle handle, s64 size) { - return Get(handle)->SetSize(size); + AMS_FS_R_TRY(AMS_FS_IMPL_ACCESS_LOG(Get(handle)->SetSize(size), handle, AMS_FS_IMPL_ACCESS_LOG_FORMAT_SIZE, size)); + return ResultSuccess(); } int GetFileOpenMode(FileHandle handle) { @@ -67,11 +72,12 @@ namespace ams::fs { } void CloseFile(FileHandle handle) { - delete Get(handle); + AMS_FS_IMPL_ACCESS_LOG((delete Get(handle), ResultSuccess()), handle, AMS_FS_IMPL_ACCESS_LOG_FORMAT_NONE); } Result QueryRange(QueryRangeInfo *out, FileHandle handle, s64 offset, s64 size) { - return Get(handle)->OperateRange(out, sizeof(*out), OperationId::QueryRange, offset, size, nullptr, 0); + AMS_FS_R_TRY(Get(handle)->OperateRange(out, sizeof(*out), OperationId::QueryRange, offset, size, nullptr, 0)); + return ResultSuccess(); } } diff --git a/libraries/libstratosphere/source/ncm/ncm_content_meta_utils.cpp b/libraries/libstratosphere/source/ncm/ncm_content_meta_utils.cpp index 05b6c78f1..7796720b1 100644 --- a/libraries/libstratosphere/source/ncm/ncm_content_meta_utils.cpp +++ b/libraries/libstratosphere/source/ncm/ncm_content_meta_utils.cpp @@ -86,7 +86,7 @@ namespace ams::ncm { Result ReadVariationContentMetaInfoList(s32 *out_count, std::unique_ptr *out_meta_infos, const Path &path, FirmwareVariationId firmware_variation_id) { AutoBuffer meta; { - /* TODO: fs::ScopedAutoAbortDisabler aad; */ + fs::ScopedAutoAbortDisabler aad; R_TRY(ReadContentMetaPath(std::addressof(meta), path.str)); } diff --git a/libraries/libstratosphere/source/ncm/ncm_install_task_base.cpp b/libraries/libstratosphere/source/ncm/ncm_install_task_base.cpp index 506e89fac..23d98cea5 100644 --- a/libraries/libstratosphere/source/ncm/ncm_install_task_base.cpp +++ b/libraries/libstratosphere/source/ncm/ncm_install_task_base.cpp @@ -1000,7 +1000,7 @@ namespace ams::ncm { Result InstallTaskBase::GetInstallContentMetaDataFromPath(AutoBuffer *out, const Path &path, const InstallContentInfo &content_info, std::optional source_version) { AutoBuffer meta; { - /* TODO: fs::ScopedAutoAbortDisabler aad; */ + fs::ScopedAutoAbortDisabler aad; R_TRY(ReadContentMetaPath(std::addressof(meta), path.str)); } diff --git a/libraries/libstratosphere/source/os/impl/os_thread_manager.cpp b/libraries/libstratosphere/source/os/impl/os_thread_manager.cpp index 8fee951ae..d58c4c321 100644 --- a/libraries/libstratosphere/source/os/impl/os_thread_manager.cpp +++ b/libraries/libstratosphere/source/os/impl/os_thread_manager.cpp @@ -41,6 +41,9 @@ namespace ams::os::impl { thread->name_buffer[0] = '\x00'; thread->name_pointer = thread->name_buffer; + /* Set internal tls variables. */ + thread->atomic_sf_inline_context = 0; + /* Mark initialized. */ thread->state = ThreadType::State_Initialized; } diff --git a/libraries/libstratosphere/source/os/os_sdk_thread_local_storage_api.cpp b/libraries/libstratosphere/source/os/os_sdk_thread_local_storage_api.cpp new file mode 100644 index 000000000..f7bb5d291 --- /dev/null +++ b/libraries/libstratosphere/source/os/os_sdk_thread_local_storage_api.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018-2020 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 + +namespace ams::os { + + /* TODO: Nintendo reserves half the TLS slots for SDK usage. */ + /* We don't have that ability...how should this work? */ + Result SdkAllocateTlsSlot(TlsSlot *out, TlsDestructor destructor) { + return os::AllocateTlsSlot(out, destructor); + } + +} diff --git a/libraries/libstratosphere/source/sf/cmif/sf_cmif_inline_context.cpp b/libraries/libstratosphere/source/sf/cmif/sf_cmif_inline_context.cpp index ecb3b98f3..ae86e967d 100644 --- a/libraries/libstratosphere/source/sf/cmif/sf_cmif_inline_context.cpp +++ b/libraries/libstratosphere/source/sf/cmif/sf_cmif_inline_context.cpp @@ -21,47 +21,74 @@ namespace ams::sf { namespace { - thread_local InlineContext g_inline_context; + ALWAYS_INLINE std::atomic *GetAtomicSfInlineContext(os::ThreadType *thread) { + static_assert(sizeof(thread->atomic_sf_inline_context) >= sizeof(std::atomic)); + return reinterpret_cast *>(std::addressof(thread->atomic_sf_inline_context)); + } - ALWAYS_INLINE void OnSetInlineContext() { + ALWAYS_INLINE std::atomic *GetAtomicSfInlineContext() { + return GetAtomicSfInlineContext(os::GetCurrentThread()); + } + + ALWAYS_INLINE void OnSetInlineContext(os::ThreadType *thread) { /* Ensure that libnx receives the priority value. */ - ::fsSetPriority(static_cast<::FsPriority>(::ams::sf::GetFsInlineContext())); + ::fsSetPriority(static_cast<::FsPriority>(::ams::sf::GetFsInlineContext(thread))); } } InlineContext GetInlineContext() { + /* Get current thread. */ + os::ThreadType * const cur_thread = os::GetCurrentThread(); + + /* Get the context. */ + uintptr_t thread_context = GetAtomicSfInlineContext()->load(); + + /* Copy it out. */ InlineContext ctx; - std::memcpy(std::addressof(ctx), std::addressof(::ams::sf::cmif::g_inline_context), sizeof(ctx)); + static_assert(sizeof(ctx) <= sizeof(thread_context)); + std::memcpy(std::addressof(ctx), std::addressof(thread_context), sizeof(ctx)); return ctx; } InlineContext SetInlineContext(InlineContext ctx) { - ON_SCOPE_EXIT { OnSetInlineContext(); }; - static_assert(sizeof(ctx) <= sizeof(g_inline_context)); + /* Get current thread. */ + os::ThreadType * const cur_thread = os::GetCurrentThread(); + ON_SCOPE_EXIT { OnSetInlineContext(cur_thread); }; + /* Create the new context. */ + static_assert(sizeof(ctx) <= sizeof(uintptr_t)); + uintptr_t new_context_value = 0; + std::memcpy(std::addressof(new_context_value), std::addressof(ctx), sizeof(ctx)); + + /* Get the old context. */ + uintptr_t old_context_value = GetAtomicSfInlineContext()->exchange(new_context_value); + + /* Convert and copy it out. */ InlineContext old_ctx; - std::memcpy(std::addressof(old_ctx), std::addressof(g_inline_context), sizeof(old_ctx)); - std::memcpy(std::addressof(g_inline_context), std::addressof(ctx), sizeof(ctx)); + std::memcpy(std::addressof(old_ctx), std::addressof(old_context_value), sizeof(old_ctx)); return old_ctx; } } - u8 GetFsInlineContext() { - u8 ctx; - std::memcpy(std::addressof(ctx), std::addressof(cmif::g_inline_context), sizeof(ctx)); - return ctx; + namespace { + + ALWAYS_INLINE std::atomic *GetAtomicFsInlineContext(os::ThreadType *thread) { + static_assert(sizeof(thread->atomic_sf_inline_context) >= sizeof(std::atomic)); + return reinterpret_cast *>(std::addressof(thread->atomic_sf_inline_context)); + } + } - u8 SetFsInlineContext(u8 ctx) { - ON_SCOPE_EXIT { cmif::OnSetInlineContext(); }; - static_assert(sizeof(ctx) <= sizeof(cmif::g_inline_context)); + u8 GetFsInlineContext(os::ThreadType *thread) { + return GetAtomicFsInlineContext(thread)->load(); + } - u8 old_ctx; - std::memcpy(std::addressof(old_ctx), std::addressof(cmif::g_inline_context), sizeof(old_ctx)); - std::memcpy(std::addressof(cmif::g_inline_context), std::addressof(ctx), sizeof(ctx)); - return old_ctx; + u8 SetFsInlineContext(os::ThreadType *thread, u8 ctx) { + ON_SCOPE_EXIT { cmif::OnSetInlineContext(thread); }; + + return GetAtomicFsInlineContext(thread)->exchange(ctx); } } diff --git a/libraries/libvapours/include/vapours/defines.hpp b/libraries/libvapours/include/vapours/defines.hpp index 61c733237..a4be456b7 100644 --- a/libraries/libvapours/include/vapours/defines.hpp +++ b/libraries/libvapours/include/vapours/defines.hpp @@ -40,6 +40,9 @@ #define BITSIZEOF(x) (sizeof(x) * CHAR_BIT) +#define STRINGIZE(x) STRINGIZE_IMPL(x) +#define STRINGIZE_IMPL(x) #x + #ifdef __COUNTER__ #define ANONYMOUS_VARIABLE(pref) CONCATENATE(pref, __COUNTER__) #else diff --git a/libraries/libvapours/include/vapours/includes.hpp b/libraries/libvapours/include/vapours/includes.hpp index 577e2c458..4a5494402 100644 --- a/libraries/libvapours/include/vapours/includes.hpp +++ b/libraries/libvapours/include/vapours/includes.hpp @@ -25,6 +25,7 @@ #include #include #include +#include /* C++ headers. */ #include diff --git a/libraries/libvapours/include/vapours/results/fs_results.hpp b/libraries/libvapours/include/vapours/results/fs_results.hpp index 88987e73b..5128fb631 100644 --- a/libraries/libvapours/include/vapours/results/fs_results.hpp +++ b/libraries/libvapours/include/vapours/results/fs_results.hpp @@ -21,386 +21,389 @@ namespace ams::fs { R_DEFINE_NAMESPACE_RESULT_MODULE(2); - R_DEFINE_ERROR_RESULT(PathNotFound, 1); - R_DEFINE_ERROR_RESULT(PathAlreadyExists, 2); + R_DEFINE_ERROR_RANGE(HandledByAllProcess, 0, 999); + R_DEFINE_ERROR_RESULT(PathNotFound, 1); + R_DEFINE_ERROR_RESULT(PathAlreadyExists, 2); - R_DEFINE_ERROR_RESULT(TargetLocked, 7); - R_DEFINE_ERROR_RESULT(DirectoryNotEmpty, 8); + R_DEFINE_ERROR_RESULT(TargetLocked, 7); + R_DEFINE_ERROR_RESULT(DirectoryNotEmpty, 8); - R_DEFINE_ERROR_RANGE (NotEnoughFreeSpace, 30, 45); - R_DEFINE_ERROR_RANGE(NotEnoughFreeSpaceBis, 34, 38); - R_DEFINE_ERROR_RESULT(NotEnoughFreeSpaceBisCalibration, 35); - R_DEFINE_ERROR_RESULT(NotEnoughFreeSpaceBisSafe, 36); - R_DEFINE_ERROR_RESULT(NotEnoughFreeSpaceBisUser, 37); - R_DEFINE_ERROR_RESULT(NotEnoughFreeSpaceBisSystem, 38); - R_DEFINE_ERROR_RESULT(NotEnoughFreeSpaceSdCard, 39); + R_DEFINE_ERROR_RANGE (NotEnoughFreeSpace, 30, 45); + R_DEFINE_ERROR_RANGE(NotEnoughFreeSpaceBis, 34, 38); + R_DEFINE_ERROR_RESULT(NotEnoughFreeSpaceBisCalibration, 35); + R_DEFINE_ERROR_RESULT(NotEnoughFreeSpaceBisSafe, 36); + R_DEFINE_ERROR_RESULT(NotEnoughFreeSpaceBisUser, 37); + R_DEFINE_ERROR_RESULT(NotEnoughFreeSpaceBisSystem, 38); + R_DEFINE_ERROR_RESULT(NotEnoughFreeSpaceSdCard, 39); - R_DEFINE_ERROR_RESULT(UnsupportedSdkVersion, 50); + R_DEFINE_ERROR_RESULT(UnsupportedSdkVersion, 50); - R_DEFINE_ERROR_RESULT(MountNameAlreadyExists, 60); + R_DEFINE_ERROR_RESULT(MountNameAlreadyExists, 60); - R_DEFINE_ERROR_RESULT(PartitionNotFound, 1001); - R_DEFINE_ERROR_RESULT(TargetNotFound, 1002); + R_DEFINE_ERROR_RANGE(HandledBySystemProcess, 1000, 2999); + R_DEFINE_ERROR_RESULT(PartitionNotFound, 1001); + R_DEFINE_ERROR_RESULT(TargetNotFound, 1002); - R_DEFINE_ERROR_RANGE(SdCardAccessFailed, 2000, 2499); - R_DEFINE_ERROR_RESULT(SdCardNotPresent, 2001); + R_DEFINE_ERROR_RANGE(SdCardAccessFailed, 2000, 2499); + R_DEFINE_ERROR_RESULT(SdCardNotPresent, 2001); - R_DEFINE_ERROR_RANGE(GameCardAccessFailed, 2500, 2999); + R_DEFINE_ERROR_RANGE(GameCardAccessFailed, 2500, 2999); - R_DEFINE_ERROR_RESULT(NotImplemented, 3001); - R_DEFINE_ERROR_RESULT(UnsupportedVersion, 3002); - R_DEFINE_ERROR_RESULT(OutOfRange, 3005); + R_DEFINE_ERROR_RESULT(NotImplemented, 3001); + R_DEFINE_ERROR_RESULT(UnsupportedVersion, 3002); + R_DEFINE_ERROR_RESULT(OutOfRange, 3005); - R_DEFINE_ERROR_RESULT(SystemPartitionNotReady, 3100); + R_DEFINE_ERROR_RESULT(SystemPartitionNotReady, 3100); - R_DEFINE_ERROR_RANGE(AllocationFailure, 3200, 3499); - R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemAccessorA, 3211); - R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemAccessorB, 3212); - R_DEFINE_ERROR_RESULT(AllocationFailureInApplicationA, 3213); - R_DEFINE_ERROR_RESULT(AllocationFailureInBisA, 3215); - R_DEFINE_ERROR_RESULT(AllocationFailureInBisB, 3216); - R_DEFINE_ERROR_RESULT(AllocationFailureInBisC, 3217); - R_DEFINE_ERROR_RESULT(AllocationFailureInCodeA, 3218); - R_DEFINE_ERROR_RESULT(AllocationFailureInContentA, 3219); - R_DEFINE_ERROR_RESULT(AllocationFailureInContentStorageA, 3220); - R_DEFINE_ERROR_RESULT(AllocationFailureInContentStorageB, 3221); - R_DEFINE_ERROR_RESULT(AllocationFailureInDataA, 3222); - R_DEFINE_ERROR_RESULT(AllocationFailureInDataB, 3223); - R_DEFINE_ERROR_RESULT(AllocationFailureInDeviceSaveDataA, 3224); - R_DEFINE_ERROR_RESULT(AllocationFailureInGameCardA, 3225); - R_DEFINE_ERROR_RESULT(AllocationFailureInGameCardB, 3226); - R_DEFINE_ERROR_RESULT(AllocationFailureInGameCardC, 3227); - R_DEFINE_ERROR_RESULT(AllocationFailureInGameCardD, 3228); - R_DEFINE_ERROR_RESULT(AllocationFailureInImageDirectoryA, 3232); - R_DEFINE_ERROR_RESULT(AllocationFailureInSdCardA, 3244); - R_DEFINE_ERROR_RESULT(AllocationFailureInSdCardB, 3245); - R_DEFINE_ERROR_RESULT(AllocationFailureInSystemSaveDataA, 3246); - R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemA, 3247); - R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemB, 3248); - R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemC, 3249); - R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemProxyCoreImplD, 3256); - R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemProxyCoreImplE, 3257); - R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemCreatorA, 3280); - R_DEFINE_ERROR_RESULT(AllocationFailureInRomFileSystemCreatorA, 3281); - R_DEFINE_ERROR_RESULT(AllocationFailureInStorageOnNcaCreatorA, 3288); - R_DEFINE_ERROR_RESULT(AllocationFailureInStorageOnNcaCreatorB, 3289); - R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemBuddyHeapA, 3294); - R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemBufferManagerA, 3295); - R_DEFINE_ERROR_RESULT(AllocationFailureInBlockCacheBufferedStorageA, 3296); - R_DEFINE_ERROR_RESULT(AllocationFailureInBlockCacheBufferedStorageB, 3297); - R_DEFINE_ERROR_RESULT(AllocationFailureInIntegrityVerificationStorageA, 3304); - R_DEFINE_ERROR_RESULT(AllocationFailureInIntegrityVerificationStorageB, 3305); - R_DEFINE_ERROR_RESULT(AllocationFailureInDirectorySaveDataFileSystem, 3321); - R_DEFINE_ERROR_RESULT(AllocationFailureInNcaFileSystemDriverI, 3341); - R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemA, 3347); - R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemB, 3348); - R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemC, 3349); - R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemMetaA, 3350); - R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemMetaB, 3351); - R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemD, 3352); - R_DEFINE_ERROR_RESULT(AllocationFailureInSubDirectoryFileSystem, 3355); - R_DEFINE_ERROR_RESULT(AllocationFailureInNcaReaderA, 3363); - R_DEFINE_ERROR_RESULT(AllocationFailureInRegisterA, 3365); - R_DEFINE_ERROR_RESULT(AllocationFailureInRegisterB, 3366); - R_DEFINE_ERROR_RESULT(AllocationFailureInPathNormalizer, 3367); - R_DEFINE_ERROR_RESULT(AllocationFailureInDbmRomKeyValueStorage, 3375); - R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemE, 3377); - R_DEFINE_ERROR_RESULT(AllocationFailureInReadOnlyFileSystemA, 3386); - R_DEFINE_ERROR_RESULT(AllocationFailureInAesCtrCounterExtendedStorageA, 3399); - R_DEFINE_ERROR_RESULT(AllocationFailureInAesCtrCounterExtendedStorageB, 3400); - R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemInterfaceAdapter, 3407); - R_DEFINE_ERROR_RESULT(AllocationFailureInBufferedStorageA, 3411); - R_DEFINE_ERROR_RESULT(AllocationFailureInIntegrityRomFsStorageA, 3412); - R_DEFINE_ERROR_RESULT(AllocationFailureInNew, 3420); - R_DEFINE_ERROR_RESULT(AllocationFailureInMakeUnique, 3422); - R_DEFINE_ERROR_RESULT(AllocationFailureInAllocateShared, 3423); - R_DEFINE_ERROR_RESULT(AllocationFailurePooledBufferNotEnoughSize, 3424); + R_DEFINE_ERROR_RANGE(AllocationFailure, 3200, 3499); + R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemAccessorA, 3211); + R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemAccessorB, 3212); + R_DEFINE_ERROR_RESULT(AllocationFailureInApplicationA, 3213); + R_DEFINE_ERROR_RESULT(AllocationFailureInBisA, 3215); + R_DEFINE_ERROR_RESULT(AllocationFailureInBisB, 3216); + R_DEFINE_ERROR_RESULT(AllocationFailureInBisC, 3217); + R_DEFINE_ERROR_RESULT(AllocationFailureInCodeA, 3218); + R_DEFINE_ERROR_RESULT(AllocationFailureInContentA, 3219); + R_DEFINE_ERROR_RESULT(AllocationFailureInContentStorageA, 3220); + R_DEFINE_ERROR_RESULT(AllocationFailureInContentStorageB, 3221); + R_DEFINE_ERROR_RESULT(AllocationFailureInDataA, 3222); + R_DEFINE_ERROR_RESULT(AllocationFailureInDataB, 3223); + R_DEFINE_ERROR_RESULT(AllocationFailureInDeviceSaveDataA, 3224); + R_DEFINE_ERROR_RESULT(AllocationFailureInGameCardA, 3225); + R_DEFINE_ERROR_RESULT(AllocationFailureInGameCardB, 3226); + R_DEFINE_ERROR_RESULT(AllocationFailureInGameCardC, 3227); + R_DEFINE_ERROR_RESULT(AllocationFailureInGameCardD, 3228); + R_DEFINE_ERROR_RESULT(AllocationFailureInImageDirectoryA, 3232); + R_DEFINE_ERROR_RESULT(AllocationFailureInSdCardA, 3244); + R_DEFINE_ERROR_RESULT(AllocationFailureInSdCardB, 3245); + R_DEFINE_ERROR_RESULT(AllocationFailureInSystemSaveDataA, 3246); + R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemA, 3247); + R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemB, 3248); + R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemC, 3249); + R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemProxyCoreImplD, 3256); + R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemProxyCoreImplE, 3257); + R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemCreatorA, 3280); + R_DEFINE_ERROR_RESULT(AllocationFailureInRomFileSystemCreatorA, 3281); + R_DEFINE_ERROR_RESULT(AllocationFailureInStorageOnNcaCreatorA, 3288); + R_DEFINE_ERROR_RESULT(AllocationFailureInStorageOnNcaCreatorB, 3289); + R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemBuddyHeapA, 3294); + R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemBufferManagerA, 3295); + R_DEFINE_ERROR_RESULT(AllocationFailureInBlockCacheBufferedStorageA, 3296); + R_DEFINE_ERROR_RESULT(AllocationFailureInBlockCacheBufferedStorageB, 3297); + R_DEFINE_ERROR_RESULT(AllocationFailureInIntegrityVerificationStorageA, 3304); + R_DEFINE_ERROR_RESULT(AllocationFailureInIntegrityVerificationStorageB, 3305); + R_DEFINE_ERROR_RESULT(AllocationFailureInDirectorySaveDataFileSystem, 3321); + R_DEFINE_ERROR_RESULT(AllocationFailureInNcaFileSystemDriverI, 3341); + R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemA, 3347); + R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemB, 3348); + R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemC, 3349); + R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemMetaA, 3350); + R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemMetaB, 3351); + R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemD, 3352); + R_DEFINE_ERROR_RESULT(AllocationFailureInSubDirectoryFileSystem, 3355); + R_DEFINE_ERROR_RESULT(AllocationFailureInNcaReaderA, 3363); + R_DEFINE_ERROR_RESULT(AllocationFailureInRegisterA, 3365); + R_DEFINE_ERROR_RESULT(AllocationFailureInRegisterB, 3366); + R_DEFINE_ERROR_RESULT(AllocationFailureInPathNormalizer, 3367); + R_DEFINE_ERROR_RESULT(AllocationFailureInDbmRomKeyValueStorage, 3375); + R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemE, 3377); + R_DEFINE_ERROR_RESULT(AllocationFailureInReadOnlyFileSystemA, 3386); + R_DEFINE_ERROR_RESULT(AllocationFailureInAesCtrCounterExtendedStorageA, 3399); + R_DEFINE_ERROR_RESULT(AllocationFailureInAesCtrCounterExtendedStorageB, 3400); + R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemInterfaceAdapter, 3407); + R_DEFINE_ERROR_RESULT(AllocationFailureInBufferedStorageA, 3411); + R_DEFINE_ERROR_RESULT(AllocationFailureInIntegrityRomFsStorageA, 3412); + R_DEFINE_ERROR_RESULT(AllocationFailureInNew, 3420); + R_DEFINE_ERROR_RESULT(AllocationFailureInMakeUnique, 3422); + R_DEFINE_ERROR_RESULT(AllocationFailureInAllocateShared, 3423); + R_DEFINE_ERROR_RESULT(AllocationFailurePooledBufferNotEnoughSize, 3424); - R_DEFINE_ERROR_RANGE(MmcAccessFailed, 3500, 3999); + R_DEFINE_ERROR_RANGE(Internal, 3000, 7999); + R_DEFINE_ERROR_RANGE(MmcAccessFailed, 3500, 3999); - R_DEFINE_ERROR_RANGE(DataCorrupted, 4000, 4999); - R_DEFINE_ERROR_RANGE(RomCorrupted, 4001, 4299); - R_DEFINE_ERROR_RESULT(UnsupportedRomVersion, 4002); + R_DEFINE_ERROR_RANGE(DataCorrupted, 4000, 4999); + R_DEFINE_ERROR_RANGE(RomCorrupted, 4001, 4299); + R_DEFINE_ERROR_RESULT(UnsupportedRomVersion, 4002); - R_DEFINE_ERROR_RANGE(AesCtrCounterExtendedStorageCorrupted, 4011, 4019); - R_DEFINE_ERROR_RESULT(InvalidAesCtrCounterExtendedEntryOffset, 4012); - R_DEFINE_ERROR_RESULT(InvalidAesCtrCounterExtendedTableSize, 4013); - R_DEFINE_ERROR_RESULT(InvalidAesCtrCounterExtendedGeneration, 4014); - R_DEFINE_ERROR_RESULT(InvalidAesCtrCounterExtendedOffset, 4015); + R_DEFINE_ERROR_RANGE(AesCtrCounterExtendedStorageCorrupted, 4011, 4019); + R_DEFINE_ERROR_RESULT(InvalidAesCtrCounterExtendedEntryOffset, 4012); + R_DEFINE_ERROR_RESULT(InvalidAesCtrCounterExtendedTableSize, 4013); + R_DEFINE_ERROR_RESULT(InvalidAesCtrCounterExtendedGeneration, 4014); + R_DEFINE_ERROR_RESULT(InvalidAesCtrCounterExtendedOffset, 4015); - R_DEFINE_ERROR_RANGE(IndirectStorageCorrupted, 4021, 4029); - R_DEFINE_ERROR_RESULT(InvalidIndirectEntryOffset, 4022); - R_DEFINE_ERROR_RESULT(InvalidIndirectEntryStorageIndex, 4023); - R_DEFINE_ERROR_RESULT(InvalidIndirectStorageSize, 4024); - R_DEFINE_ERROR_RESULT(InvalidIndirectVirtualOffset, 4025); - R_DEFINE_ERROR_RESULT(InvalidIndirectPhysicalOffset, 4026); - R_DEFINE_ERROR_RESULT(InvalidIndirectStorageIndex, 4027); + R_DEFINE_ERROR_RANGE(IndirectStorageCorrupted, 4021, 4029); + R_DEFINE_ERROR_RESULT(InvalidIndirectEntryOffset, 4022); + R_DEFINE_ERROR_RESULT(InvalidIndirectEntryStorageIndex, 4023); + R_DEFINE_ERROR_RESULT(InvalidIndirectStorageSize, 4024); + R_DEFINE_ERROR_RESULT(InvalidIndirectVirtualOffset, 4025); + R_DEFINE_ERROR_RESULT(InvalidIndirectPhysicalOffset, 4026); + R_DEFINE_ERROR_RESULT(InvalidIndirectStorageIndex, 4027); - R_DEFINE_ERROR_RANGE(BucketTreeCorrupted, 4031, 4039); - R_DEFINE_ERROR_RESULT(InvalidBucketTreeSignature, 4032); - R_DEFINE_ERROR_RESULT(InvalidBucketTreeEntryCount, 4033); - R_DEFINE_ERROR_RESULT(InvalidBucketTreeNodeEntryCount, 4034); - R_DEFINE_ERROR_RESULT(InvalidBucketTreeNodeOffset, 4035); - R_DEFINE_ERROR_RESULT(InvalidBucketTreeEntryOffset, 4036); - R_DEFINE_ERROR_RESULT(InvalidBucketTreeEntrySetOffset, 4037); - R_DEFINE_ERROR_RESULT(InvalidBucketTreeNodeIndex, 4038); - R_DEFINE_ERROR_RESULT(InvalidBucketTreeVirtualOffset, 4039); + R_DEFINE_ERROR_RANGE(BucketTreeCorrupted, 4031, 4039); + R_DEFINE_ERROR_RESULT(InvalidBucketTreeSignature, 4032); + R_DEFINE_ERROR_RESULT(InvalidBucketTreeEntryCount, 4033); + R_DEFINE_ERROR_RESULT(InvalidBucketTreeNodeEntryCount, 4034); + R_DEFINE_ERROR_RESULT(InvalidBucketTreeNodeOffset, 4035); + R_DEFINE_ERROR_RESULT(InvalidBucketTreeEntryOffset, 4036); + R_DEFINE_ERROR_RESULT(InvalidBucketTreeEntrySetOffset, 4037); + R_DEFINE_ERROR_RESULT(InvalidBucketTreeNodeIndex, 4038); + R_DEFINE_ERROR_RESULT(InvalidBucketTreeVirtualOffset, 4039); - R_DEFINE_ERROR_RANGE(RomNcaCorrupted, 4041, 4139); - R_DEFINE_ERROR_RANGE(RomNcaFileSystemCorrupted, 4051, 4069); - R_DEFINE_ERROR_RESULT(InvalidRomNcaFileSystemType, 4052); - R_DEFINE_ERROR_RESULT(InvalidRomAcidFileSize, 4053); - R_DEFINE_ERROR_RESULT(InvalidRomAcidSize, 4054); - R_DEFINE_ERROR_RESULT(InvalidRomAcid, 4055); - R_DEFINE_ERROR_RESULT(RomAcidVerificationFailed, 4056); - R_DEFINE_ERROR_RESULT(InvalidRomNcaSignature, 4057); - R_DEFINE_ERROR_RESULT(RomNcaHeaderSignature1VerificationFailed, 4058); - R_DEFINE_ERROR_RESULT(RomNcaHeaderSignature2VerificationFailed, 4059); - R_DEFINE_ERROR_RESULT(RomNcaFsHeaderHashVerificationFailed, 4060); - R_DEFINE_ERROR_RESULT(InvalidRomNcaKeyIndex, 4061); - R_DEFINE_ERROR_RESULT(InvalidRomNcaFsHeaderHashType, 4062); - R_DEFINE_ERROR_RESULT(InvalidRomNcaFsHeaderEncryptionType, 4063); + R_DEFINE_ERROR_RANGE(RomNcaCorrupted, 4041, 4139); + R_DEFINE_ERROR_RANGE(RomNcaFileSystemCorrupted, 4051, 4069); + R_DEFINE_ERROR_RESULT(InvalidRomNcaFileSystemType, 4052); + R_DEFINE_ERROR_RESULT(InvalidRomAcidFileSize, 4053); + R_DEFINE_ERROR_RESULT(InvalidRomAcidSize, 4054); + R_DEFINE_ERROR_RESULT(InvalidRomAcid, 4055); + R_DEFINE_ERROR_RESULT(RomAcidVerificationFailed, 4056); + R_DEFINE_ERROR_RESULT(InvalidRomNcaSignature, 4057); + R_DEFINE_ERROR_RESULT(RomNcaHeaderSignature1VerificationFailed, 4058); + R_DEFINE_ERROR_RESULT(RomNcaHeaderSignature2VerificationFailed, 4059); + R_DEFINE_ERROR_RESULT(RomNcaFsHeaderHashVerificationFailed, 4060); + R_DEFINE_ERROR_RESULT(InvalidRomNcaKeyIndex, 4061); + R_DEFINE_ERROR_RESULT(InvalidRomNcaFsHeaderHashType, 4062); + R_DEFINE_ERROR_RESULT(InvalidRomNcaFsHeaderEncryptionType, 4063); - R_DEFINE_ERROR_RANGE(RomNcaHierarchicalSha256StorageCorrupted, 4071, 4079); - R_DEFINE_ERROR_RESULT(InvalidRomHierarchicalSha256BlockSize, 4072); - R_DEFINE_ERROR_RESULT(InvalidRomHierarchicalSha256LayerCount, 4073); - R_DEFINE_ERROR_RESULT(RomHierarchicalSha256BaseStorageTooLarge, 4074); - R_DEFINE_ERROR_RESULT(RomHierarchicalSha256HashVerificationFailed, 4075); + R_DEFINE_ERROR_RANGE(RomNcaHierarchicalSha256StorageCorrupted, 4071, 4079); + R_DEFINE_ERROR_RESULT(InvalidRomHierarchicalSha256BlockSize, 4072); + R_DEFINE_ERROR_RESULT(InvalidRomHierarchicalSha256LayerCount, 4073); + R_DEFINE_ERROR_RESULT(RomHierarchicalSha256BaseStorageTooLarge, 4074); + R_DEFINE_ERROR_RESULT(RomHierarchicalSha256HashVerificationFailed, 4075); - R_DEFINE_ERROR_RANGE(RomIntegrityVerificationStorageCorrupted, 4141, 4179); - R_DEFINE_ERROR_RESULT(IncorrectRomIntegrityVerificationMagic, 4142); - R_DEFINE_ERROR_RESULT(InvalidRomZeroHash, 4143); - R_DEFINE_ERROR_RESULT(RomNonRealDataVerificationFailed, 4144); - R_DEFINE_ERROR_RESULT(InvalidRomHierarchicalIntegrityVerificationLayerCount, 4145); + R_DEFINE_ERROR_RANGE(RomIntegrityVerificationStorageCorrupted, 4141, 4179); + R_DEFINE_ERROR_RESULT(IncorrectRomIntegrityVerificationMagic, 4142); + R_DEFINE_ERROR_RESULT(InvalidRomZeroHash, 4143); + R_DEFINE_ERROR_RESULT(RomNonRealDataVerificationFailed, 4144); + R_DEFINE_ERROR_RESULT(InvalidRomHierarchicalIntegrityVerificationLayerCount, 4145); - R_DEFINE_ERROR_RANGE(RomRealDataVerificationFailed, 4151, 4159); - R_DEFINE_ERROR_RESULT(ClearedRomRealDataVerificationFailed, 4152); - R_DEFINE_ERROR_RESULT(UnclearedRomRealDataVerificationFailed, 4153); + R_DEFINE_ERROR_RANGE(RomRealDataVerificationFailed, 4151, 4159); + R_DEFINE_ERROR_RESULT(ClearedRomRealDataVerificationFailed, 4152); + R_DEFINE_ERROR_RESULT(UnclearedRomRealDataVerificationFailed, 4153); - R_DEFINE_ERROR_RANGE(RomPartitionFileSystemCorrupted, 4181, 4199); - R_DEFINE_ERROR_RESULT(InvalidRomSha256PartitionHashTarget, 4182); - R_DEFINE_ERROR_RESULT(RomSha256PartitionHashVerificationFailed, 4183); - R_DEFINE_ERROR_RESULT(RomPartitionSignatureVerificationFailed, 4184); - R_DEFINE_ERROR_RESULT(RomSha256PartitionSignatureVerificationFailed, 4185); - R_DEFINE_ERROR_RESULT(InvalidRomPartitionEntryOffset, 4186); - R_DEFINE_ERROR_RESULT(InvalidRomSha256PartitionMetaDataSize, 4187); + R_DEFINE_ERROR_RANGE(RomPartitionFileSystemCorrupted, 4181, 4199); + R_DEFINE_ERROR_RESULT(InvalidRomSha256PartitionHashTarget, 4182); + R_DEFINE_ERROR_RESULT(RomSha256PartitionHashVerificationFailed, 4183); + R_DEFINE_ERROR_RESULT(RomPartitionSignatureVerificationFailed, 4184); + R_DEFINE_ERROR_RESULT(RomSha256PartitionSignatureVerificationFailed, 4185); + R_DEFINE_ERROR_RESULT(InvalidRomPartitionEntryOffset, 4186); + R_DEFINE_ERROR_RESULT(InvalidRomSha256PartitionMetaDataSize, 4187); - R_DEFINE_ERROR_RANGE(RomBuiltInStorageCorrupted, 4201, 4219); - R_DEFINE_ERROR_RESULT(RomGptHeaderVerificationFailed, 4202); + R_DEFINE_ERROR_RANGE(RomBuiltInStorageCorrupted, 4201, 4219); + R_DEFINE_ERROR_RESULT(RomGptHeaderVerificationFailed, 4202); - R_DEFINE_ERROR_RANGE(RomHostFileSystemCorrupted, 4241, 4259); - R_DEFINE_ERROR_RESULT(RomHostEntryCorrupted, 4242); - R_DEFINE_ERROR_RESULT(RomHostFileDataCorrupted, 4243); - R_DEFINE_ERROR_RESULT(RomHostFileCorrupted, 4244); - R_DEFINE_ERROR_RESULT(InvalidRomHostHandle, 4245); + R_DEFINE_ERROR_RANGE(RomHostFileSystemCorrupted, 4241, 4259); + R_DEFINE_ERROR_RESULT(RomHostEntryCorrupted, 4242); + R_DEFINE_ERROR_RESULT(RomHostFileDataCorrupted, 4243); + R_DEFINE_ERROR_RESULT(RomHostFileCorrupted, 4244); + R_DEFINE_ERROR_RESULT(InvalidRomHostHandle, 4245); - R_DEFINE_ERROR_RANGE(RomDatabaseCorrupted, 4261, 4279); - R_DEFINE_ERROR_RESULT(InvalidRomAllocationTableBlock, 4262); - R_DEFINE_ERROR_RESULT(InvalidRomKeyValueListElementIndex, 4263); + R_DEFINE_ERROR_RANGE(RomDatabaseCorrupted, 4261, 4279); + R_DEFINE_ERROR_RESULT(InvalidRomAllocationTableBlock, 4262); + R_DEFINE_ERROR_RESULT(InvalidRomKeyValueListElementIndex, 4263); - R_DEFINE_ERROR_RANGE(SaveDataCorrupted, 4301, 4499); - R_DEFINE_ERROR_RANGE(NcaCorrupted, 4501, 4599); - R_DEFINE_ERROR_RESULT(NcaBaseStorageOutOfRangeA, 4508); - R_DEFINE_ERROR_RESULT(NcaBaseStorageOutOfRangeB, 4509); + R_DEFINE_ERROR_RANGE(SaveDataCorrupted, 4301, 4499); + R_DEFINE_ERROR_RANGE(NcaCorrupted, 4501, 4599); + R_DEFINE_ERROR_RESULT(NcaBaseStorageOutOfRangeA, 4508); + R_DEFINE_ERROR_RESULT(NcaBaseStorageOutOfRangeB, 4509); - R_DEFINE_ERROR_RANGE(NcaFileSystemCorrupted, 4511, 4529); - R_DEFINE_ERROR_RESULT(InvalidNcaFileSystemType, 4512); - R_DEFINE_ERROR_RESULT(InvalidAcidFileSize, 4513); - R_DEFINE_ERROR_RESULT(InvalidAcidSize, 4514); - R_DEFINE_ERROR_RESULT(InvalidAcid, 4515); - R_DEFINE_ERROR_RESULT(AcidVerificationFailed, 4516); - R_DEFINE_ERROR_RESULT(InvalidNcaSignature, 4517); - R_DEFINE_ERROR_RESULT(NcaHeaderSignature1VerificationFailed, 4518); - R_DEFINE_ERROR_RESULT(NcaHeaderSignature2VerificationFailed, 4519); - R_DEFINE_ERROR_RESULT(NcaFsHeaderHashVerificationFailed, 4520); - R_DEFINE_ERROR_RESULT(InvalidNcaKeyIndex, 4521); - R_DEFINE_ERROR_RESULT(InvalidNcaFsHeaderHashType, 4522); - R_DEFINE_ERROR_RESULT(InvalidNcaFsHeaderEncryptionType, 4523); - R_DEFINE_ERROR_RESULT(InvalidNcaPatchInfoIndirectSize, 4524); - R_DEFINE_ERROR_RESULT(InvalidNcaPatchInfoAesCtrExSize, 4525); - R_DEFINE_ERROR_RESULT(InvalidNcaPatchInfoAesCtrExOffset, 4526); - R_DEFINE_ERROR_RESULT(InvalidNcaId, 4527); - R_DEFINE_ERROR_RESULT(InvalidNcaHeader, 4528); - R_DEFINE_ERROR_RESULT(InvalidNcaFsHeader, 4529); + R_DEFINE_ERROR_RANGE(NcaFileSystemCorrupted, 4511, 4529); + R_DEFINE_ERROR_RESULT(InvalidNcaFileSystemType, 4512); + R_DEFINE_ERROR_RESULT(InvalidAcidFileSize, 4513); + R_DEFINE_ERROR_RESULT(InvalidAcidSize, 4514); + R_DEFINE_ERROR_RESULT(InvalidAcid, 4515); + R_DEFINE_ERROR_RESULT(AcidVerificationFailed, 4516); + R_DEFINE_ERROR_RESULT(InvalidNcaSignature, 4517); + R_DEFINE_ERROR_RESULT(NcaHeaderSignature1VerificationFailed, 4518); + R_DEFINE_ERROR_RESULT(NcaHeaderSignature2VerificationFailed, 4519); + R_DEFINE_ERROR_RESULT(NcaFsHeaderHashVerificationFailed, 4520); + R_DEFINE_ERROR_RESULT(InvalidNcaKeyIndex, 4521); + R_DEFINE_ERROR_RESULT(InvalidNcaFsHeaderHashType, 4522); + R_DEFINE_ERROR_RESULT(InvalidNcaFsHeaderEncryptionType, 4523); + R_DEFINE_ERROR_RESULT(InvalidNcaPatchInfoIndirectSize, 4524); + R_DEFINE_ERROR_RESULT(InvalidNcaPatchInfoAesCtrExSize, 4525); + R_DEFINE_ERROR_RESULT(InvalidNcaPatchInfoAesCtrExOffset, 4526); + R_DEFINE_ERROR_RESULT(InvalidNcaId, 4527); + R_DEFINE_ERROR_RESULT(InvalidNcaHeader, 4528); + R_DEFINE_ERROR_RESULT(InvalidNcaFsHeader, 4529); - R_DEFINE_ERROR_RANGE(NcaHierarchicalSha256StorageCorrupted, 4531, 4539); - R_DEFINE_ERROR_RESULT(InvalidHierarchicalSha256BlockSize, 4532); - R_DEFINE_ERROR_RESULT(InvalidHierarchicalSha256LayerCount, 4533); - R_DEFINE_ERROR_RESULT(HierarchicalSha256BaseStorageTooLarge, 4534); - R_DEFINE_ERROR_RESULT(HierarchicalSha256HashVerificationFailed, 4535); + R_DEFINE_ERROR_RANGE(NcaHierarchicalSha256StorageCorrupted, 4531, 4539); + R_DEFINE_ERROR_RESULT(InvalidHierarchicalSha256BlockSize, 4532); + R_DEFINE_ERROR_RESULT(InvalidHierarchicalSha256LayerCount, 4533); + R_DEFINE_ERROR_RESULT(HierarchicalSha256BaseStorageTooLarge, 4534); + R_DEFINE_ERROR_RESULT(HierarchicalSha256HashVerificationFailed, 4535); - /* TODO: Range? */ - R_DEFINE_ERROR_RESULT(InvalidNcaHeader1SignatureKeyGeneration, 4543); + /* TODO: Range? */ + R_DEFINE_ERROR_RESULT(InvalidNcaHeader1SignatureKeyGeneration, 4543); - R_DEFINE_ERROR_RANGE(IntegrityVerificationStorageCorrupted, 4601, 4639); - R_DEFINE_ERROR_RESULT(IncorrectIntegrityVerificationMagic, 4602); - R_DEFINE_ERROR_RESULT(InvalidZeroHash, 4603); - R_DEFINE_ERROR_RESULT(NonRealDataVerificationFailed, 4604); - R_DEFINE_ERROR_RESULT(InvalidHierarchicalIntegrityVerificationLayerCount, 4605); + R_DEFINE_ERROR_RANGE(IntegrityVerificationStorageCorrupted, 4601, 4639); + R_DEFINE_ERROR_RESULT(IncorrectIntegrityVerificationMagic, 4602); + R_DEFINE_ERROR_RESULT(InvalidZeroHash, 4603); + R_DEFINE_ERROR_RESULT(NonRealDataVerificationFailed, 4604); + R_DEFINE_ERROR_RESULT(InvalidHierarchicalIntegrityVerificationLayerCount, 4605); - R_DEFINE_ERROR_RANGE(RealDataVerificationFailed, 4611, 4619); - R_DEFINE_ERROR_RESULT(ClearedRealDataVerificationFailed, 4612); - R_DEFINE_ERROR_RESULT(UnclearedRealDataVerificationFailed, 4613); + R_DEFINE_ERROR_RANGE(RealDataVerificationFailed, 4611, 4619); + R_DEFINE_ERROR_RESULT(ClearedRealDataVerificationFailed, 4612); + R_DEFINE_ERROR_RESULT(UnclearedRealDataVerificationFailed, 4613); - R_DEFINE_ERROR_RANGE(PartitionFileSystemCorrupted, 4641, 4659); - R_DEFINE_ERROR_RESULT(InvalidSha256PartitionHashTarget, 4642); - R_DEFINE_ERROR_RESULT(Sha256PartitionHashVerificationFailed, 4643); - R_DEFINE_ERROR_RESULT(PartitionSignatureVerificationFailed, 4644); - R_DEFINE_ERROR_RESULT(Sha256PartitionSignatureVerificationFailed, 4645); - R_DEFINE_ERROR_RESULT(InvalidPartitionEntryOffset, 4646); - R_DEFINE_ERROR_RESULT(InvalidSha256PartitionMetaDataSize, 4647); + R_DEFINE_ERROR_RANGE(PartitionFileSystemCorrupted, 4641, 4659); + R_DEFINE_ERROR_RESULT(InvalidSha256PartitionHashTarget, 4642); + R_DEFINE_ERROR_RESULT(Sha256PartitionHashVerificationFailed, 4643); + R_DEFINE_ERROR_RESULT(PartitionSignatureVerificationFailed, 4644); + R_DEFINE_ERROR_RESULT(Sha256PartitionSignatureVerificationFailed, 4645); + R_DEFINE_ERROR_RESULT(InvalidPartitionEntryOffset, 4646); + R_DEFINE_ERROR_RESULT(InvalidSha256PartitionMetaDataSize, 4647); - R_DEFINE_ERROR_RANGE(BuiltInStorageCorrupted, 4661, 4679); - R_DEFINE_ERROR_RESULT(GptHeaderVerificationFailed, 4662); + R_DEFINE_ERROR_RANGE(BuiltInStorageCorrupted, 4661, 4679); + R_DEFINE_ERROR_RESULT(GptHeaderVerificationFailed, 4662); - R_DEFINE_ERROR_RANGE(FatFileSystemCorrupted, 4681, 4699); + R_DEFINE_ERROR_RANGE(FatFileSystemCorrupted, 4681, 4699); - R_DEFINE_ERROR_RANGE(HostFileSystemCorrupted, 4701, 4719); - R_DEFINE_ERROR_RESULT(HostEntryCorrupted, 4702); - R_DEFINE_ERROR_RESULT(HostFileDataCorrupted, 4703); - R_DEFINE_ERROR_RESULT(HostFileCorrupted, 4704); - R_DEFINE_ERROR_RESULT(InvalidHostHandle, 4705); + R_DEFINE_ERROR_RANGE(HostFileSystemCorrupted, 4701, 4719); + R_DEFINE_ERROR_RESULT(HostEntryCorrupted, 4702); + R_DEFINE_ERROR_RESULT(HostFileDataCorrupted, 4703); + R_DEFINE_ERROR_RESULT(HostFileCorrupted, 4704); + R_DEFINE_ERROR_RESULT(InvalidHostHandle, 4705); - R_DEFINE_ERROR_RANGE(DatabaseCorrupted, 4721, 4739); - R_DEFINE_ERROR_RESULT(InvalidAllocationTableBlock, 4722); - R_DEFINE_ERROR_RESULT(InvalidKeyValueListElementIndex, 4723); + R_DEFINE_ERROR_RANGE(DatabaseCorrupted, 4721, 4739); + R_DEFINE_ERROR_RESULT(InvalidAllocationTableBlock, 4722); + R_DEFINE_ERROR_RESULT(InvalidKeyValueListElementIndex, 4723); - R_DEFINE_ERROR_RANGE(AesXtsFileSystemCorrupted, 4741, 4759); - R_DEFINE_ERROR_RANGE(SaveDataTransferDataCorrupted, 4761, 4769); - R_DEFINE_ERROR_RANGE(SignedSystemPartitionDataCorrupted, 4771, 4779); + R_DEFINE_ERROR_RANGE(AesXtsFileSystemCorrupted, 4741, 4759); + R_DEFINE_ERROR_RANGE(SaveDataTransferDataCorrupted, 4761, 4769); + R_DEFINE_ERROR_RANGE(SignedSystemPartitionDataCorrupted, 4771, 4779); - R_DEFINE_ERROR_RESULT(GameCardLogoDataCorrupted, 4781); + R_DEFINE_ERROR_RESULT(GameCardLogoDataCorrupted, 4781); - R_DEFINE_ERROR_RANGE(Unexpected, 5000, 5999); - R_DEFINE_ERROR_RESULT(UnexpectedInAesCtrStorageA, 5315); - R_DEFINE_ERROR_RESULT(UnexpectedInAesXtsStorageA, 5316); - R_DEFINE_ERROR_RESULT(UnexpectedInFindFileSystemA, 5319); + R_DEFINE_ERROR_RANGE(Unexpected, 5000, 5999); + R_DEFINE_ERROR_RESULT(UnexpectedInAesCtrStorageA, 5315); + R_DEFINE_ERROR_RESULT(UnexpectedInAesXtsStorageA, 5316); + R_DEFINE_ERROR_RESULT(UnexpectedInFindFileSystemA, 5319); - R_DEFINE_ERROR_RANGE(PreconditionViolation, 6000, 6499); - R_DEFINE_ERROR_RANGE(InvalidArgument, 6001, 6199); - R_DEFINE_ERROR_RANGE(InvalidPath, 6002, 6029); - R_DEFINE_ERROR_RESULT(TooLongPath, 6003); - R_DEFINE_ERROR_RESULT(InvalidCharacter, 6004); - R_DEFINE_ERROR_RESULT(InvalidPathFormat, 6005); - R_DEFINE_ERROR_RESULT(DirectoryUnobtainable, 6006); - R_DEFINE_ERROR_RESULT(NotNormalized, 6007); + R_DEFINE_ERROR_RANGE(PreconditionViolation, 6000, 6499); + R_DEFINE_ERROR_RANGE(InvalidArgument, 6001, 6199); + R_DEFINE_ERROR_RANGE(InvalidPath, 6002, 6029); + R_DEFINE_ERROR_RESULT(TooLongPath, 6003); + R_DEFINE_ERROR_RESULT(InvalidCharacter, 6004); + R_DEFINE_ERROR_RESULT(InvalidPathFormat, 6005); + R_DEFINE_ERROR_RESULT(DirectoryUnobtainable, 6006); + R_DEFINE_ERROR_RESULT(NotNormalized, 6007); - R_DEFINE_ERROR_RANGE(InvalidPathForOperation, 6030, 6059); - R_DEFINE_ERROR_RESULT(DirectoryNotDeletable, 6031); - R_DEFINE_ERROR_RESULT(DirectoryNotRenamable, 6032); - R_DEFINE_ERROR_RESULT(IncompatiblePath, 6033); - R_DEFINE_ERROR_RESULT(RenameToOtherFileSystem, 6034); + R_DEFINE_ERROR_RANGE(InvalidPathForOperation, 6030, 6059); + R_DEFINE_ERROR_RESULT(DirectoryNotDeletable, 6031); + R_DEFINE_ERROR_RESULT(DirectoryNotRenamable, 6032); + R_DEFINE_ERROR_RESULT(IncompatiblePath, 6033); + R_DEFINE_ERROR_RESULT(RenameToOtherFileSystem, 6034); - R_DEFINE_ERROR_RESULT(InvalidOffset, 6061); - R_DEFINE_ERROR_RESULT(InvalidSize, 6062); - R_DEFINE_ERROR_RESULT(NullptrArgument, 6063); - R_DEFINE_ERROR_RESULT(InvalidAlignment, 6064); - R_DEFINE_ERROR_RESULT(InvalidMountName, 6065); + R_DEFINE_ERROR_RESULT(InvalidOffset, 6061); + R_DEFINE_ERROR_RESULT(InvalidSize, 6062); + R_DEFINE_ERROR_RESULT(NullptrArgument, 6063); + R_DEFINE_ERROR_RESULT(InvalidAlignment, 6064); + R_DEFINE_ERROR_RESULT(InvalidMountName, 6065); - R_DEFINE_ERROR_RESULT(ExtensionSizeTooLarge, 6066); - R_DEFINE_ERROR_RESULT(ExtensionSizeInvalid, 6067); + R_DEFINE_ERROR_RESULT(ExtensionSizeTooLarge, 6066); + R_DEFINE_ERROR_RESULT(ExtensionSizeInvalid, 6067); - R_DEFINE_ERROR_RESULT(InvalidOpenMode, 6072); + R_DEFINE_ERROR_RESULT(InvalidOpenMode, 6072); - R_DEFINE_ERROR_RANGE(InvalidEnumValue, 6080, 6099); - R_DEFINE_ERROR_RESULT(InvalidSaveDataState, 6081); - R_DEFINE_ERROR_RESULT(InvalidSaveDataSpaceId, 6082); + R_DEFINE_ERROR_RANGE(InvalidEnumValue, 6080, 6099); + R_DEFINE_ERROR_RESULT(InvalidSaveDataState, 6081); + R_DEFINE_ERROR_RESULT(InvalidSaveDataSpaceId, 6082); - R_DEFINE_ERROR_RANGE(InvalidOperationForOpenMode, 6200, 6299); - R_DEFINE_ERROR_RESULT(FileExtensionWithoutOpenModeAllowAppend, 6201); - R_DEFINE_ERROR_RESULT(ReadNotPermitted, 6202); - R_DEFINE_ERROR_RESULT(WriteNotPermitted, 6203); + R_DEFINE_ERROR_RANGE(InvalidOperationForOpenMode, 6200, 6299); + R_DEFINE_ERROR_RESULT(FileExtensionWithoutOpenModeAllowAppend, 6201); + R_DEFINE_ERROR_RESULT(ReadNotPermitted, 6202); + R_DEFINE_ERROR_RESULT(WriteNotPermitted, 6203); - R_DEFINE_ERROR_RANGE(UnsupportedOperation, 6300, 6399); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInSubStorageA, 6302); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInSubStorageB, 6303); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInMemoryStorageA, 6304); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInMemoryStorageB, 6305); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInFileStorageA, 6306); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInFileStorageB, 6307); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInSwitchStorageA, 6308); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInAesCtrCounterExtendedStorageA, 6310); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInAesCtrCounterExtendedStorageB, 6311); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInAesCtrCounterExtendedStorageC, 6312); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInAesCtrStorageExternalA, 6313); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInAesCtrStorageExternalB, 6314); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInAesCtrStorageA, 6315); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInHierarchicalIntegrityVerificationStorageA, 6316); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInHierarchicalIntegrityVerificationStorageB, 6317); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInIntegrityVerificationStorageA, 6318); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInIntegrityVerificationStorageB, 6319); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInIntegrityVerificationStorageC, 6320); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInBlockCacheBufferedStorageA, 6321); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInBlockCacheBufferedStorageB, 6322); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInBlockCacheBufferedStorageC, 6323); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInIndirectStorageA, 6324); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInIndirectStorageB, 6325); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInIndirectStorageC, 6326); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInZeroStorageA, 6327); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInZeroStorageB, 6328); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInHierarchicalSha256StorageA, 6329); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInReadOnlyBlockCacheStorageA, 6330); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInReadOnlyBlockCacheStorageB, 6331); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInIntegrityRomFsStorageA , 6332); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInFileServiceObjectAdapterA, 6362); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInRomFsFileSystemA, 6364); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInRomFsFileSystemB, 6365); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInRomFsFileSystemC, 6366); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInRomFsFileA, 6367); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInRomFsFileB, 6368); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInReadOnlyFileSystemTemplateA, 6369); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInReadOnlyFileSystemTemplateB, 6370); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInReadOnlyFileSystemTemplateC, 6371); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInReadOnlyFileA, 6372); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInReadOnlyFileB, 6373); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInPartitionFileSystemA, 6374); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInPartitionFileSystemB, 6375); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInPartitionFileA, 6376); - R_DEFINE_ERROR_RESULT(UnsupportedOperationInPartitionFileB, 6377); + R_DEFINE_ERROR_RANGE(UnsupportedOperation, 6300, 6399); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInSubStorageA, 6302); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInSubStorageB, 6303); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInMemoryStorageA, 6304); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInMemoryStorageB, 6305); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInFileStorageA, 6306); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInFileStorageB, 6307); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInSwitchStorageA, 6308); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInAesCtrCounterExtendedStorageA, 6310); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInAesCtrCounterExtendedStorageB, 6311); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInAesCtrCounterExtendedStorageC, 6312); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInAesCtrStorageExternalA, 6313); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInAesCtrStorageExternalB, 6314); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInAesCtrStorageA, 6315); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInHierarchicalIntegrityVerificationStorageA, 6316); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInHierarchicalIntegrityVerificationStorageB, 6317); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInIntegrityVerificationStorageA, 6318); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInIntegrityVerificationStorageB, 6319); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInIntegrityVerificationStorageC, 6320); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInBlockCacheBufferedStorageA, 6321); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInBlockCacheBufferedStorageB, 6322); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInBlockCacheBufferedStorageC, 6323); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInIndirectStorageA, 6324); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInIndirectStorageB, 6325); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInIndirectStorageC, 6326); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInZeroStorageA, 6327); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInZeroStorageB, 6328); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInHierarchicalSha256StorageA, 6329); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInReadOnlyBlockCacheStorageA, 6330); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInReadOnlyBlockCacheStorageB, 6331); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInIntegrityRomFsStorageA , 6332); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInFileServiceObjectAdapterA, 6362); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInRomFsFileSystemA, 6364); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInRomFsFileSystemB, 6365); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInRomFsFileSystemC, 6366); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInRomFsFileA, 6367); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInRomFsFileB, 6368); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInReadOnlyFileSystemTemplateA, 6369); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInReadOnlyFileSystemTemplateB, 6370); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInReadOnlyFileSystemTemplateC, 6371); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInReadOnlyFileA, 6372); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInReadOnlyFileB, 6373); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInPartitionFileSystemA, 6374); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInPartitionFileSystemB, 6375); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInPartitionFileA, 6376); + R_DEFINE_ERROR_RESULT(UnsupportedOperationInPartitionFileB, 6377); - R_DEFINE_ERROR_RANGE(PermissionDenied, 6400, 6449); + R_DEFINE_ERROR_RANGE(PermissionDenied, 6400, 6449); - R_DEFINE_ERROR_RESULT(NeedFlush, 6454); - R_DEFINE_ERROR_RESULT(FileNotClosed, 6455); - R_DEFINE_ERROR_RESULT(DirectoryNotClosed, 6456); - R_DEFINE_ERROR_RESULT(WriteModeFileNotClosed, 6457); - R_DEFINE_ERROR_RESULT(AllocatorAlreadyRegistered, 6458); - R_DEFINE_ERROR_RESULT(DefaultAllocatorUsed, 6459); - R_DEFINE_ERROR_RESULT(AllocatorAlignmentViolation, 6461); - R_DEFINE_ERROR_RESULT(UserNotExist, 6465); + R_DEFINE_ERROR_RESULT(NeedFlush, 6454); + R_DEFINE_ERROR_RESULT(FileNotClosed, 6455); + R_DEFINE_ERROR_RESULT(DirectoryNotClosed, 6456); + R_DEFINE_ERROR_RESULT(WriteModeFileNotClosed, 6457); + R_DEFINE_ERROR_RESULT(AllocatorAlreadyRegistered, 6458); + R_DEFINE_ERROR_RESULT(DefaultAllocatorUsed, 6459); + R_DEFINE_ERROR_RESULT(AllocatorAlignmentViolation, 6461); + R_DEFINE_ERROR_RESULT(UserNotExist, 6465); - R_DEFINE_ERROR_RANGE(NotFound, 6600, 6699); + R_DEFINE_ERROR_RANGE(NotFound, 6600, 6699); - R_DEFINE_ERROR_RANGE(OutOfResource, 6700, 6799); - R_DEFINE_ERROR_RESULT(BufferAllocationFailed, 6705); - R_DEFINE_ERROR_RESULT(MappingTableFull, 6706); - R_DEFINE_ERROR_RESULT(OpenCountLimit, 6709); + R_DEFINE_ERROR_RANGE(OutOfResource, 6700, 6799); + R_DEFINE_ERROR_RESULT(BufferAllocationFailed, 6705); + R_DEFINE_ERROR_RESULT(MappingTableFull, 6706); + R_DEFINE_ERROR_RESULT(OpenCountLimit, 6709); - R_DEFINE_ERROR_RANGE(MappingFailed, 6800, 6899); - R_DEFINE_ERROR_RESULT(MapFull, 6811); + R_DEFINE_ERROR_RANGE(MappingFailed, 6800, 6899); + R_DEFINE_ERROR_RESULT(MapFull, 6811); - R_DEFINE_ERROR_RANGE(BadState, 6900, 6999); - R_DEFINE_ERROR_RESULT(NotInitialized, 6902); - R_DEFINE_ERROR_RESULT(NotMounted, 6905); + R_DEFINE_ERROR_RANGE(BadState, 6900, 6999); + R_DEFINE_ERROR_RESULT(NotInitialized, 6902); + R_DEFINE_ERROR_RESULT(NotMounted, 6905); - R_DEFINE_ERROR_RANGE(DbmNotFound, 7901, 7904); - R_DEFINE_ERROR_RESULT(DbmKeyNotFound, 7902); - R_DEFINE_ERROR_RESULT(DbmFileNotFound, 7903); - R_DEFINE_ERROR_RESULT(DbmDirectoryNotFound, 7904); + R_DEFINE_ERROR_RANGE(DbmNotFound, 7901, 7904); + R_DEFINE_ERROR_RESULT(DbmKeyNotFound, 7902); + R_DEFINE_ERROR_RESULT(DbmFileNotFound, 7903); + R_DEFINE_ERROR_RESULT(DbmDirectoryNotFound, 7904); - R_DEFINE_ERROR_RESULT(DbmAlreadyExists, 7906); - R_DEFINE_ERROR_RESULT(DbmKeyFull, 7907); - R_DEFINE_ERROR_RESULT(DbmDirectoryEntryFull, 7908); - R_DEFINE_ERROR_RESULT(DbmFileEntryFull, 7909); + R_DEFINE_ERROR_RESULT(DbmAlreadyExists, 7906); + R_DEFINE_ERROR_RESULT(DbmKeyFull, 7907); + R_DEFINE_ERROR_RESULT(DbmDirectoryEntryFull, 7908); + R_DEFINE_ERROR_RESULT(DbmFileEntryFull, 7909); - R_DEFINE_ERROR_RANGE(DbmFindFinished, 7910, 7912); - R_DEFINE_ERROR_RESULT(DbmFindKeyFinished, 7911); - R_DEFINE_ERROR_RESULT(DbmIterationFinished, 7912); + R_DEFINE_ERROR_RANGE(DbmFindFinished, 7910, 7912); + R_DEFINE_ERROR_RESULT(DbmFindKeyFinished, 7911); + R_DEFINE_ERROR_RESULT(DbmIterationFinished, 7912); - R_DEFINE_ERROR_RESULT(DbmInvalidOperation, 7914); - R_DEFINE_ERROR_RESULT(DbmInvalidPathFormat, 7915); - R_DEFINE_ERROR_RESULT(DbmDirectoryNameTooLong, 7916); - R_DEFINE_ERROR_RESULT(DbmFileNameTooLong, 7917); + R_DEFINE_ERROR_RESULT(DbmInvalidOperation, 7914); + R_DEFINE_ERROR_RESULT(DbmInvalidPathFormat, 7915); + R_DEFINE_ERROR_RESULT(DbmDirectoryNameTooLong, 7916); + R_DEFINE_ERROR_RESULT(DbmFileNameTooLong, 7917); } diff --git a/stratosphere/ams_mitm/source/amsmitm_main.cpp b/stratosphere/ams_mitm/source/amsmitm_main.cpp index 537132531..7e9b57bc8 100644 --- a/stratosphere/ams_mitm/source/amsmitm_main.cpp +++ b/stratosphere/ams_mitm/source/amsmitm_main.cpp @@ -86,6 +86,9 @@ void __appInit(void) { spl::InitializeForFs(); }); + /* Disable auto-abort in fs operations. */ + fs::SetEnabledAutoAbort(false); + /* Initialize fssystem library. */ fssystem::InitializeForFileSystemProxy(); diff --git a/stratosphere/fatal/source/fatal_main.cpp b/stratosphere/fatal/source/fatal_main.cpp index f1708ba51..587c40f4a 100644 --- a/stratosphere/fatal/source/fatal_main.cpp +++ b/stratosphere/fatal/source/fatal_main.cpp @@ -142,6 +142,9 @@ namespace { int main(int argc, char **argv) { + /* Disable auto-abort in fs operations. */ + fs::SetEnabledAutoAbort(false); + /* Set thread name. */ os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(fatal, Main)); AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(fatal, Main)); diff --git a/stratosphere/loader/source/ldr_main.cpp b/stratosphere/loader/source/ldr_main.cpp index 5d0af575e..ace9cd4b2 100644 --- a/stratosphere/loader/source/ldr_main.cpp +++ b/stratosphere/loader/source/ldr_main.cpp @@ -115,6 +115,9 @@ namespace { int main(int argc, char **argv) { + /* Disable auto-abort in fs operations. */ + fs::SetEnabledAutoAbort(false); + /* Set thread name. */ os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(ldr, Main)); AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(ldr, Main)); diff --git a/stratosphere/ncm/source/ncm_main.cpp b/stratosphere/ncm/source/ncm_main.cpp index d9ed098ea..84cb3099a 100644 --- a/stratosphere/ncm/source/ncm_main.cpp +++ b/stratosphere/ncm/source/ncm_main.cpp @@ -262,6 +262,9 @@ namespace { int main(int argc, char **argv) { + /* Disable auto-abort in fs operations. */ + fs::SetEnabledAutoAbort(false); + /* Set thread name. */ os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(ncm, MainWaitThreads)); AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(ncm, MainWaitThreads)); diff --git a/stratosphere/pgl/source/pgl_main.cpp b/stratosphere/pgl/source/pgl_main.cpp index bd56bebc1..cc5d89650 100644 --- a/stratosphere/pgl/source/pgl_main.cpp +++ b/stratosphere/pgl/source/pgl_main.cpp @@ -145,6 +145,9 @@ void __appExit(void) { int main(int argc, char **argv) { + /* Disable auto-abort in fs operations. */ + fs::SetEnabledAutoAbort(false); + /* Set thread name. */ os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(pgl, Main)); AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(pgl, Main));