diff --git a/stratosphere/boot/source/boot_check_clock.cpp b/stratosphere/boot/source/boot_check_clock.cpp
index 1aae210d2..4884e1548 100644
--- a/stratosphere/boot/source/boot_check_clock.cpp
+++ b/stratosphere/boot/source/boot_check_clock.cpp
@@ -36,7 +36,7 @@ namespace sts::boot {
/* Helpers. */
bool IsUsbClockValid() {
- uintptr_t car_regs = GetIoMapping(0x60006000ul, 0x1000);
+ uintptr_t car_regs = dd::GetIoMapping(0x60006000ul, 0x1000);
const u32 pllu = reg::Read(car_regs + 0xC0);
const u32 utmip = reg::Read(car_regs + 0x480);
diff --git a/stratosphere/boot/source/boot_display.cpp b/stratosphere/boot/source/boot_display.cpp
index b608a6c9b..02ff79aa9 100644
--- a/stratosphere/boot/source/boot_display.cpp
+++ b/stratosphere/boot/source/boot_display.cpp
@@ -79,12 +79,12 @@ namespace sts::boot {
/* Helper functions. */
void InitializeRegisterBaseAddresses() {
- g_disp1_regs = GetIoMapping(Disp1Base, Disp1Size);
- g_dsi_regs = GetIoMapping(DsiBase, DsiSize);
- g_clk_rst_regs = GetIoMapping(ClkRstBase, ClkRstSize);
- g_gpio_regs = GetIoMapping(GpioBase, GpioSize);
- g_apb_misc_regs = GetIoMapping(ApbMiscBase, ApbMiscSize);
- g_mipi_cal_regs = GetIoMapping(MipiCalBase, MipiCalSize);
+ g_disp1_regs = dd::GetIoMapping(Disp1Base, Disp1Size);
+ g_dsi_regs = dd::GetIoMapping(DsiBase, DsiSize);
+ g_clk_rst_regs = dd::GetIoMapping(ClkRstBase, ClkRstSize);
+ g_gpio_regs = dd::GetIoMapping(GpioBase, GpioSize);
+ g_apb_misc_regs = dd::GetIoMapping(ApbMiscBase, ApbMiscSize);
+ g_mipi_cal_regs = dd::GetIoMapping(MipiCalBase, MipiCalSize);
}
inline void DoRegisterWrites(uintptr_t base_address, const RegisterWrite *reg_writes, size_t num_writes) {
@@ -418,7 +418,7 @@ namespace sts::boot {
/* Nintendo waits 5 frames before continuing. */
{
- const uintptr_t host1x_vaddr = GetIoMapping(0x500030a4, 4);
+ const uintptr_t host1x_vaddr = dd::GetIoMapping(0x500030a4, 4);
const u32 start_val = reg::Read(host1x_vaddr);
while (reg::Read(host1x_vaddr) < start_val + 5) {
/* spinlock here. */
diff --git a/stratosphere/boot/source/boot_main.cpp b/stratosphere/boot/source/boot_main.cpp
index 23111d5df..696416b39 100644
--- a/stratosphere/boot/source/boot_main.cpp
+++ b/stratosphere/boot/source/boot_main.cpp
@@ -59,18 +59,23 @@ extern "C" {
alignas(16) u8 __nx_exception_stack[0x1000];
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
void __libnx_exception_handler(ThreadExceptionDump *ctx);
- void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx);
}
-sts::ncm::TitleId __stratosphere_title_id = sts::ncm::TitleId::Boot;
+namespace sts::ams {
+
+ ncm::TitleId StratosphereTitleId = ncm::TitleId::Boot;
+
+ void ExceptionHandler(FatalErrorContext *ctx) {
+ /* We're boot sysmodule, so manually reboot to fatal error. */
+ boot::RebootForFatalError(ctx);
+ }
+
+}
+
+using namespace sts;
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
- StratosphereCrashHandler(ctx);
-}
-
-void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx) {
- /* We're boot sysmodule, so manually reboot to fatal error. */
- boot::RebootForFatalError(ctx);
+ ams::CrashHandler(ctx);
}
void __libnx_initheap(void) {
@@ -89,13 +94,13 @@ void __appInit(void) {
hos::SetVersionForLibnx();
/* Initialize services we need (TODO: NCM) */
- DoWithSmSession([&]() {
+ sm::DoWithSession([&]() {
R_ASSERT(fsInitialize());
R_ASSERT(splInitialize());
R_ASSERT(pmshellInitialize());
});
- CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION);
+ ams::CheckApiVersion();
}
void __appExit(void) {
diff --git a/stratosphere/boot/source/boot_pmc_wrapper.cpp b/stratosphere/boot/source/boot_pmc_wrapper.cpp
index 2cdb2a467..59a269f89 100644
--- a/stratosphere/boot/source/boot_pmc_wrapper.cpp
+++ b/stratosphere/boot/source/boot_pmc_wrapper.cpp
@@ -13,7 +13,8 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-
+#include
+#include
#include "boot_pmc_wrapper.hpp"
namespace sts::boot {
@@ -31,29 +32,22 @@ namespace sts::boot {
return (phys_addr & 3) == 0 && PmcPhysStart <= phys_addr && phys_addr <= PmcPhysEnd;
}
- inline u32 SmcAtmosphereReadWriteRegister(u32 phys_addr, u32 value, u32 mask) {
- SecmonArgs args;
-
- args.X[0] = SmcFunctionId_AtmosphereReadWriteRegister;
- args.X[1] = phys_addr;
- args.X[2] = mask;
- args.X[3] = value;
- R_ASSERT(svcCallSecureMonitor(&args));
- STS_ASSERT(args.X[0] == 0);
-
- return static_cast(args.X[1]);
+ inline u32 ReadWriteRegisterImpl(uintptr_t phys_addr, u32 value, u32 mask) {
+ u32 out_value;
+ R_ASSERT(spl::smc::ConvertResult(spl::smc::AtmosphereReadWriteRegister(phys_addr, mask, value, &out_value)));
+ return out_value;
}
}
u32 ReadPmcRegister(u32 phys_addr) {
STS_ASSERT(IsValidPmcAddress(phys_addr));
- return SmcAtmosphereReadWriteRegister(phys_addr, 0, 0);
+ return ReadWriteRegisterImpl(phys_addr, 0, 0);
}
void WritePmcRegister(u32 phys_addr, u32 value, u32 mask) {
STS_ASSERT(IsValidPmcAddress(phys_addr));
- SmcAtmosphereReadWriteRegister(phys_addr, value, mask);
+ ReadWriteRegisterImpl(phys_addr, value, mask);
}
}
diff --git a/stratosphere/boot/source/boot_power_utils.cpp b/stratosphere/boot/source/boot_power_utils.cpp
index 0e34cf9a2..0253d2af6 100644
--- a/stratosphere/boot/source/boot_power_utils.cpp
+++ b/stratosphere/boot/source/boot_power_utils.cpp
@@ -37,22 +37,22 @@ namespace sts::boot {
/* Helpers. */
void ClearIram() {
/* Make page FFs. */
- memset(g_work_page, 0xFF, sizeof(g_work_page));
+ std::memset(g_work_page, 0xFF, sizeof(g_work_page));
/* Overwrite all of IRAM with FFs. */
for (size_t ofs = 0; ofs < IramSize; ofs += sizeof(g_work_page)) {
- CopyToIram(IramBase + ofs, g_work_page, sizeof(g_work_page));
+ ams::CopyToIram(IramBase + ofs, g_work_page, sizeof(g_work_page));
}
}
- void DoRebootToPayload(AtmosphereFatalErrorContext *ctx) {
+ void DoRebootToPayload(ams::FatalErrorContext *ctx) {
/* Ensure clean IRAM state. */
ClearIram();
/* Copy in payload. */
for (size_t ofs = 0; ofs < fusee_primary_bin_size; ofs += 0x1000) {
std::memcpy(g_work_page, &fusee_primary_bin[ofs], std::min(static_cast(fusee_primary_bin_size - ofs), size_t(0x1000)));
- CopyToIram(IramPayloadBase + ofs, g_work_page, 0x1000);
+ ams::CopyToIram(IramPayloadBase + ofs, g_work_page, 0x1000);
}
@@ -60,10 +60,10 @@ namespace sts::boot {
if (ctx != nullptr) {
std::memset(g_work_page, 0xCC, sizeof(g_work_page));
std::memcpy(g_work_page, ctx, sizeof(*ctx));
- CopyToIram(IramPayloadBase + IramPayloadMaxSize, g_work_page, sizeof(g_work_page));
+ ams::CopyToIram(IramPayloadBase + IramPayloadMaxSize, g_work_page, sizeof(g_work_page));
}
- RebootToIramPayload();
+ ams::ForceRebootToIramPayload();
}
}
@@ -72,7 +72,7 @@ namespace sts::boot {
DoRebootToPayload(nullptr);
}
- void RebootForFatalError(AtmosphereFatalErrorContext *ctx) {
+ void RebootForFatalError(ams::FatalErrorContext *ctx) {
DoRebootToPayload(ctx);
}
diff --git a/stratosphere/boot/source/boot_power_utils.hpp b/stratosphere/boot/source/boot_power_utils.hpp
index 3a5386b12..6efe66190 100644
--- a/stratosphere/boot/source/boot_power_utils.hpp
+++ b/stratosphere/boot/source/boot_power_utils.hpp
@@ -25,6 +25,6 @@ namespace sts::boot {
void ShutdownSystem();
/* Atmosphere power utilities. */
- void RebootForFatalError(AtmosphereFatalErrorContext *ctx);
+ void RebootForFatalError(ams::FatalErrorContext *ctx);
}
diff --git a/stratosphere/boot/source/gpio/gpio_utils.cpp b/stratosphere/boot/source/gpio/gpio_utils.cpp
index f0ff57750..32ad05adc 100644
--- a/stratosphere/boot/source/gpio/gpio_utils.cpp
+++ b/stratosphere/boot/source/gpio/gpio_utils.cpp
@@ -39,7 +39,7 @@ namespace sts::gpio {
uintptr_t GetBaseAddress() {
if (!g_initialized_gpio_vaddr) {
- g_gpio_vaddr = GetIoMapping(PhysicalBase, 0x1000);
+ g_gpio_vaddr = dd::GetIoMapping(PhysicalBase, 0x1000);
g_initialized_gpio_vaddr = true;
}
return g_gpio_vaddr;
diff --git a/stratosphere/boot/source/i2c/driver/impl/i2c_registers.hpp b/stratosphere/boot/source/i2c/driver/impl/i2c_registers.hpp
index 0d8c41a13..7cbd25e25 100644
--- a/stratosphere/boot/source/i2c/driver/impl/i2c_registers.hpp
+++ b/stratosphere/boot/source/i2c/driver/impl/i2c_registers.hpp
@@ -88,7 +88,7 @@ namespace sts::i2c::driver::impl {
12, 22, 3, 7, 15, 6
};
- const uintptr_t registers = GetIoMapping(0x60006000ul, 0x1000);
+ const uintptr_t registers = dd::GetIoMapping(0x60006000ul, 0x1000);
const size_t idx = ConvertToIndex(bus);
this->clk_src_reg = registers + s_clk_src_offsets[idx];
this->clk_en_reg = registers + s_clk_en_offsets[idx];
@@ -102,7 +102,7 @@ namespace sts::i2c::driver::impl {
0x0000, 0x0400, 0x0500, 0x0700, 0x1000, 0x1100
};
- const uintptr_t registers = GetIoMapping(0x7000c000ul, 0x2000) + s_offsets[ConvertToIndex(bus)];
+ const uintptr_t registers = dd::GetIoMapping(0x7000c000ul, 0x2000) + s_offsets[ConvertToIndex(bus)];
return reinterpret_cast(registers);
}
diff --git a/stratosphere/boot/source/pinmux/pinmux_utils.cpp b/stratosphere/boot/source/pinmux/pinmux_utils.cpp
index 2b2e17380..9000b520e 100644
--- a/stratosphere/boot/source/pinmux/pinmux_utils.cpp
+++ b/stratosphere/boot/source/pinmux/pinmux_utils.cpp
@@ -44,7 +44,7 @@ namespace sts::pinmux {
uintptr_t GetBaseAddress() {
if (!g_initialized_pinmux_vaddr) {
- g_pinmux_vaddr = GetIoMapping(ApbMiscPhysicalBase, 0x4000);
+ g_pinmux_vaddr = dd::GetIoMapping(ApbMiscPhysicalBase, 0x4000);
g_initialized_pinmux_vaddr = true;
}
return g_pinmux_vaddr;
diff --git a/stratosphere/boot2/source/boot2_main.cpp b/stratosphere/boot2/source/boot2_main.cpp
index 694659012..35fda6872 100644
--- a/stratosphere/boot2/source/boot2_main.cpp
+++ b/stratosphere/boot2/source/boot2_main.cpp
@@ -38,16 +38,20 @@ extern "C" {
alignas(16) u8 __nx_exception_stack[0x1000];
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
void __libnx_exception_handler(ThreadExceptionDump *ctx);
- void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx);
}
-sts::ncm::TitleId __stratosphere_title_id = sts::ncm::TitleId::Boot2;
+namespace sts::ams {
+
+ ncm::TitleId StratosphereTitleId = ncm::TitleId::Boot2;
+
+}
+
+using namespace sts;
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
- StratosphereCrashHandler(ctx);
+ ams::CrashHandler(ctx);
}
-
void __libnx_initheap(void) {
void* addr = nx_inner_heap;
size_t size = nx_inner_heap_size;
@@ -60,13 +64,11 @@ void __libnx_initheap(void) {
fake_heap_end = (char*)addr + size;
}
-using namespace sts;
-
void __appInit(void) {
hos::SetVersionForLibnx();
/* Initialize services we need. */
- DoWithSmSession([&]() {
+ sm::DoWithSession([&]() {
R_ASSERT(fsInitialize());
R_ASSERT(pmbmInitialize());
R_ASSERT(pminfoInitialize());
@@ -77,7 +79,7 @@ void __appInit(void) {
R_ASSERT(fsdevMountSdmc());
- CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION);
+ ams::CheckApiVersion();
}
void __appExit(void) {
diff --git a/stratosphere/creport/source/creport_main.cpp b/stratosphere/creport/source/creport_main.cpp
index 037fe520a..8de1a3c0e 100644
--- a/stratosphere/creport/source/creport_main.cpp
+++ b/stratosphere/creport/source/creport_main.cpp
@@ -44,16 +44,20 @@ extern "C" {
alignas(16) u8 __nx_exception_stack[0x1000];
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
void __libnx_exception_handler(ThreadExceptionDump *ctx);
- void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx);
}
-sts::ncm::TitleId __stratosphere_title_id = sts::ncm::TitleId::Creport;
+namespace sts::ams {
+
+ ncm::TitleId StratosphereTitleId = ncm::TitleId::Creport;
+
+}
+
+using namespace sts;
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
- StratosphereCrashHandler(ctx);
+ ams::CrashHandler(ctx);
}
-
void __libnx_initheap(void) {
void* addr = nx_inner_heap;
size_t size = nx_inner_heap_size;
@@ -66,12 +70,10 @@ void __libnx_initheap(void) {
fake_heap_end = (char*)addr + size;
}
-using namespace sts;
-
void __appInit(void) {
hos::SetVersionForLibnx();
- DoWithSmSession([&]() {
+ sm::DoWithSession([&]() {
R_ASSERT(fsInitialize());
});
diff --git a/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_api.cpp b/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_api.cpp
index 4db3129b7..56700d6f0 100644
--- a/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_api.cpp
+++ b/stratosphere/dmnt/source/cheat/impl/dmnt_cheat_api.cpp
@@ -157,7 +157,7 @@ namespace sts::dmnt::cheat::impl {
/* Note: This function *MUST* be called only with the cheat lock held. */
os::ProcessId pid;
bool has_cheat_process = this->cheat_process_debug_handle != INVALID_HANDLE;
- has_cheat_process &= R_SUCCEEDED(os::GetProcessId(&pid, this->cheat_process_debug_handle));
+ has_cheat_process &= R_SUCCEEDED(os::TryGetProcessId(&pid, this->cheat_process_debug_handle));
has_cheat_process &= R_SUCCEEDED(pm::dmnt::GetApplicationProcessId(&pid));
has_cheat_process &= (pid == this->cheat_process_metadata.process_id);
diff --git a/stratosphere/dmnt/source/dmnt_main.cpp b/stratosphere/dmnt/source/dmnt_main.cpp
index 4e643592d..1eec25cf0 100644
--- a/stratosphere/dmnt/source/dmnt_main.cpp
+++ b/stratosphere/dmnt/source/dmnt_main.cpp
@@ -43,8 +43,13 @@ extern "C" {
void __appExit(void);
}
-/* Exception handling. */
-sts::ncm::TitleId __stratosphere_title_id = sts::ncm::TitleId::Dmnt;
+namespace sts::ams {
+
+ ncm::TitleId StratosphereTitleId = ncm::TitleId::Dmnt;
+
+}
+
+using namespace sts;
void __libnx_initheap(void) {
void* addr = nx_inner_heap;
@@ -58,12 +63,10 @@ void __libnx_initheap(void) {
fake_heap_end = (char*)addr + size;
}
-using namespace sts;
-
void __appInit(void) {
hos::SetVersionForLibnx();
- DoWithSmSession([&]() {
+ sm::DoWithSession([&]() {
R_ASSERT(pmdmntInitialize());
R_ASSERT(pminfoInitialize());
R_ASSERT(ldrDmntInitialize());
@@ -81,7 +84,7 @@ void __appInit(void) {
R_ASSERT(fsdevMountSdmc());
- CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION);
+ ams::CheckApiVersion();
}
void __appExit(void) {
diff --git a/stratosphere/dmnt/source/dmnt_service_debug.cpp b/stratosphere/dmnt/source/dmnt_service_debug.cpp
index 656a1e72f..ad049af2c 100644
--- a/stratosphere/dmnt/source/dmnt_service_debug.cpp
+++ b/stratosphere/dmnt/source/dmnt_service_debug.cpp
@@ -36,7 +36,7 @@ namespace sts::dmnt {
Result DebugMonitorService::GetProcessId(sf::Out out_pid, Handle hnd) {
/* Nintendo discards the output of this command, but we will return it. */
- return svcGetProcessId(reinterpret_cast(out_pid.GetPointer()), hnd);
+ return os::TryGetProcessId(out_pid.GetPointer(), hnd);
}
Result DebugMonitorService::GetProcessHandle(sf::Out out_hnd, os::ProcessId pid) {
diff --git a/stratosphere/eclct.stub/source/eclct_stub.cpp b/stratosphere/eclct.stub/source/eclct_stub.cpp
index 62b73d454..53cc76625 100644
--- a/stratosphere/eclct.stub/source/eclct_stub.cpp
+++ b/stratosphere/eclct.stub/source/eclct_stub.cpp
@@ -28,7 +28,7 @@ extern "C" {
u32 __nx_applet_type = AppletType_None;
- #define INNER_HEAP_SIZE 0x8000
+ #define INNER_HEAP_SIZE 0x2000
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
char nx_inner_heap[INNER_HEAP_SIZE];
@@ -40,16 +40,20 @@ extern "C" {
alignas(16) u8 __nx_exception_stack[0x1000];
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
void __libnx_exception_handler(ThreadExceptionDump *ctx);
- void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx);
}
-sts::ncm::TitleId __stratosphere_title_id = sts::ncm::TitleId::Eclct;
+namespace sts::ams {
+
+ ncm::TitleId StratosphereTitleId = ncm::TitleId::Eclct;
+
+}
+
+using namespace sts;
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
- StratosphereCrashHandler(ctx);
+ ams::CrashHandler(ctx);
}
-
void __libnx_initheap(void) {
void* addr = nx_inner_heap;
size_t size = nx_inner_heap_size;
diff --git a/stratosphere/fatal/source/fatal_main.cpp b/stratosphere/fatal/source/fatal_main.cpp
index aa3d393c6..1fbb77572 100644
--- a/stratosphere/fatal/source/fatal_main.cpp
+++ b/stratosphere/fatal/source/fatal_main.cpp
@@ -49,13 +49,18 @@ extern "C" {
alignas(16) u8 __nx_exception_stack[0x1000];
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
void __libnx_exception_handler(ThreadExceptionDump *ctx);
- void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx);
}
-sts::ncm::TitleId __stratosphere_title_id = sts::ncm::TitleId::Fatal;
+namespace sts::ams {
+
+ ncm::TitleId StratosphereTitleId = ncm::TitleId::Fatal;
+
+}
+
+using namespace sts;
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
- StratosphereCrashHandler(ctx);
+ ams::CrashHandler(ctx);
}
void __libnx_initheap(void) {
@@ -70,12 +75,10 @@ void __libnx_initheap(void) {
fake_heap_end = (char*)addr + size;
}
-using namespace sts;
-
void __appInit(void) {
hos::SetVersionForLibnx();
- DoWithSmSession([&]() {
+ sm::DoWithSession([&]() {
R_ASSERT(setInitialize());
R_ASSERT(setsysInitialize());
R_ASSERT(pminfoInitialize());
@@ -98,7 +101,7 @@ void __appInit(void) {
R_ASSERT(fsdevMountSdmc());
- /* fatal cannot throw fatal, so don't do: CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION); */
+ /* fatal cannot throw fatal, so don't do: ams::CheckApiVersion(); */
}
void __appExit(void) {
diff --git a/stratosphere/fatal/source/fatal_task_error_report.cpp b/stratosphere/fatal/source/fatal_task_error_report.cpp
index 4c55d5f1e..3a0d9b27d 100644
--- a/stratosphere/fatal/source/fatal_task_error_report.cpp
+++ b/stratosphere/fatal/source/fatal_task_error_report.cpp
@@ -91,7 +91,7 @@ namespace sts::fatal::srv {
if (strlen(this->context->proc_name)) {
fprintf(f_report, "Process Name: %s\n", this->context->proc_name);
}
- fprintf(f_report, u8"Firmware: %s (Atmosphère %u.%u.%u-%s)\n", GetFatalConfig().GetFirmwareVersion().display_version, CURRENT_ATMOSPHERE_VERSION, GetAtmosphereGitRevision());
+ fprintf(f_report, u8"Firmware: %s (Atmosphère %u.%u.%u-%s)\n", GetFatalConfig().GetFirmwareVersion().display_version, ATMOSPHERE_RELEASE_VERSION, ams::GetGitRevision());
if (this->context->cpu_ctx.architecture == CpuContext::Architecture_Aarch32) {
fprintf(f_report, "General Purpose Registers:\n");
diff --git a/stratosphere/fatal/source/fatal_task_screen.cpp b/stratosphere/fatal/source/fatal_task_screen.cpp
index 9dc638057..ac72778f5 100644
--- a/stratosphere/fatal/source/fatal_task_screen.cpp
+++ b/stratosphere/fatal/source/fatal_task_screen.cpp
@@ -189,7 +189,7 @@ namespace sts::fatal::srv {
const FatalConfig &config = GetFatalConfig();
/* Prepare screen for drawing. */
- DoWithSmSession([&]() {
+ sm::DoWithSession([&]() {
R_ASSERT(PrepareScreenForDrawing());
});
@@ -222,7 +222,7 @@ namespace sts::fatal::srv {
font::AddSpacingLines(0.5f);
font::PrintFormatLine("Title: %016lX", static_cast(this->context->title_id));
font::AddSpacingLines(0.5f);
- font::PrintFormatLine(u8"Firmware: %s (Atmosphère %u.%u.%u-%s)", config.GetFirmwareVersion().display_version, CURRENT_ATMOSPHERE_VERSION, GetAtmosphereGitRevision());
+ font::PrintFormatLine(u8"Firmware: %s (Atmosphère %u.%u.%u-%s)", config.GetFirmwareVersion().display_version, ATMOSPHERE_RELEASE_VERSION, ams::GetGitRevision());
font::AddSpacingLines(1.5f);
if (this->context->error_code != ResultAtmosphereVersionMismatch) {
font::Print(config.GetErrorDescription());
diff --git a/stratosphere/libstratosphere/Makefile b/stratosphere/libstratosphere/Makefile
index 0fd81506a..581691221 100644
--- a/stratosphere/libstratosphere/Makefile
+++ b/stratosphere/libstratosphere/Makefile
@@ -16,7 +16,7 @@ include $(DEVKITPRO)/libnx/switch_rules
# INCLUDES is a list of directories containing header files
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
-SOURCES := source source/ams source/os source/os/impl source/sf source/sf/cmif source/sf/hipc source/spl source/spl/smc source/updater source/patcher source/map source/rnd source/util source/sm source/cfg source/pm source/hid source/ldr source/kvdb source/boot2
+SOURCES := source source/ams source/os source/os/impl source/dd source/sf source/sf/cmif source/sf/hipc source/dmnt source/spl source/spl/smc source/updater source/patcher source/map source/rnd source/util source/sm source/cfg source/pm source/hid source/ldr source/kvdb source/boot2
DATA := data
INCLUDES := include
diff --git a/stratosphere/libstratosphere/include/stratosphere.hpp b/stratosphere/libstratosphere/include/stratosphere.hpp
index b1a36f453..58e7ffe74 100644
--- a/stratosphere/libstratosphere/include/stratosphere.hpp
+++ b/stratosphere/libstratosphere/include/stratosphere.hpp
@@ -17,20 +17,13 @@
#pragma once
#include "stratosphere/defines.hpp"
-
-#include "stratosphere/utilities.hpp"
-#include "stratosphere/emummc_utilities.hpp"
-
-#include "stratosphere/version_check.hpp"
-
#include "stratosphere/results.hpp"
-#include "stratosphere/on_crash.hpp"
-
#include "stratosphere/util.hpp"
#include "stratosphere/svc.hpp"
#include "stratosphere/ams.hpp"
#include "stratosphere/os.hpp"
+#include "stratosphere/dd.hpp"
#include "stratosphere/cfg.hpp"
#include "stratosphere/fatal.hpp"
#include "stratosphere/hid.hpp"
diff --git a/stratosphere/libstratosphere/include/stratosphere/ams.hpp b/stratosphere/libstratosphere/include/stratosphere/ams.hpp
index 9af4ad13d..666633bdb 100644
--- a/stratosphere/libstratosphere/include/stratosphere/ams.hpp
+++ b/stratosphere/libstratosphere/include/stratosphere/ams.hpp
@@ -17,4 +17,7 @@
#pragma once
#include "ams/ams_types.hpp"
-#include "ams/ams_hos_version_api.hpp"
\ No newline at end of file
+#include "ams/ams_hos_version_api.hpp"
+#include "ams/ams_exosphere_api.hpp"
+#include "ams/ams_emummc_api.hpp"
+#include "ams/ams_environment.hpp"
diff --git a/stratosphere/libstratosphere/include/stratosphere/on_crash.hpp b/stratosphere/libstratosphere/include/stratosphere/ams/ams_emummc_api.hpp
similarity index 68%
rename from stratosphere/libstratosphere/include/stratosphere/on_crash.hpp
rename to stratosphere/libstratosphere/include/stratosphere/ams/ams_emummc_api.hpp
index 2f66f60ee..5a6661403 100644
--- a/stratosphere/libstratosphere/include/stratosphere/on_crash.hpp
+++ b/stratosphere/libstratosphere/include/stratosphere/ams/ams_emummc_api.hpp
@@ -15,13 +15,17 @@
*/
#pragma once
-#include
-#include
-#include "services/bpc_ams.h"
+#include "ams_types.hpp"
-static constexpr size_t AtmosphereFatalErrorNumGprs = 29;
+namespace sts::ams::emummc {
-static constexpr u32 AtmosphereFatalErrorMagic = 0x31454641; /* "AFE1" */
+ /* Get whether emummc is active. */
+ bool IsActive();
-/* Will be called by libstratosphere on crash. */
-void StratosphereCrashHandler(ThreadExceptionDump *ctx);
\ No newline at end of file
+ /* Get Nintendo redirection path. */
+ const char *GetNintendoDirPath();
+
+ /* Get Emummc folderpath, NULL if not file-based. */
+ const char *GetFilePath();
+
+}
diff --git a/stratosphere/libstratosphere/include/stratosphere/emummc_utilities.hpp b/stratosphere/libstratosphere/include/stratosphere/ams/ams_environment.hpp
similarity index 72%
rename from stratosphere/libstratosphere/include/stratosphere/emummc_utilities.hpp
rename to stratosphere/libstratosphere/include/stratosphere/ams/ams_environment.hpp
index d2b52e043..55265ee3d 100644
--- a/stratosphere/libstratosphere/include/stratosphere/emummc_utilities.hpp
+++ b/stratosphere/libstratosphere/include/stratosphere/ams/ams_environment.hpp
@@ -15,14 +15,11 @@
*/
#pragma once
-#include
-#include
+#include "ams_types.hpp"
-/* Get whether emummc is active. */
-bool IsEmummc();
+namespace sts::ams {
-/* Get Nintendo redirection path. */
-const char *GetEmummcNintendoDirPath();
+ /* Will be called by libstratosphere on crash. */
+ void CrashHandler(ThreadExceptionDump *ctx);
-/* Get Emummc folderpath, NULL if not file-based. */
-const char *GetEmummcFilePath();
+}
diff --git a/stratosphere/libstratosphere/include/stratosphere/ams/ams_exosphere_api.hpp b/stratosphere/libstratosphere/include/stratosphere/ams/ams_exosphere_api.hpp
new file mode 100644
index 000000000..7dbcbedf4
--- /dev/null
+++ b/stratosphere/libstratosphere/include/stratosphere/ams/ams_exosphere_api.hpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2018-2019 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#pragma once
+#include "ams_types.hpp"
+
+namespace sts::ams {
+
+ ApiInfo GetApiInfo();
+
+ void ForceRebootToRcm();
+ void ForceRebootToIramPayload();
+ void ForceShutdown();
+
+ bool IsRcmBugPatched();
+
+ void CopyToIram(uintptr_t iram_dst, const void *dram_src, size_t size);
+ void CopyFromIram(void *dram_dst, uintptr_t iram_src, size_t size);
+
+ /* Version checking utility. */
+#ifdef ATMOSPHERE_RELEASE_VERSION_MAJOR
+
+#define ATMOSPHERE_RELEASE_VERSION ATMOSPHERE_RELEASE_VERSION_MAJOR, ATMOSPHERE_RELEASE_VERSION_MINOR, ATMOSPHERE_RELEASE_VERSION_MICRO
+
+ inline void CheckApiVersion() {
+ const u32 runtime_version = GetApiInfo().GetVersion();
+ const u32 build_version = GetVersion(ATMOSPHERE_RELEASE_VERSION);
+
+ if (runtime_version < build_version) {
+ R_ASSERT(ResultAtmosphereVersionMismatch);
+ }
+ }
+
+#endif
+
+#ifdef ATMOSPHERE_GIT_BRANCH
+ NX_CONSTEXPR const char *GetGitBranch() {
+ return ATMOSPHERE_GIT_BRANCH;
+ }
+#endif
+
+#ifdef ATMOSPHERE_GIT_REV
+ NX_CONSTEXPR const char *GetGitRevision() {
+ return ATMOSPHERE_GIT_REV;
+ }
+#endif
+
+}
diff --git a/stratosphere/libstratosphere/include/stratosphere/ams/ams_types.hpp b/stratosphere/libstratosphere/include/stratosphere/ams/ams_types.hpp
index 9c0e2436b..15e29808b 100644
--- a/stratosphere/libstratosphere/include/stratosphere/ams/ams_types.hpp
+++ b/stratosphere/libstratosphere/include/stratosphere/ams/ams_types.hpp
@@ -17,6 +17,8 @@
#pragma once
#include
#include "../defines.hpp"
+#include "../results.hpp"
+#include "../sf/sf_buffer_tags.hpp"
/* Define firmware version in global namespace, for convenience. */
namespace sts {
@@ -59,4 +61,67 @@ namespace sts::ams {
TargetFirmware_900 = 11,
};
+ constexpr inline u32 GetVersion(u32 major, u32 minor, u32 micro) {
+ return (major << 16) | (minor << 8) | (micro);
+ }
+
+ struct ApiInfo {
+ u32 major_version;
+ u32 minor_version;
+ u32 micro_version;
+ TargetFirmware target_firmware;
+ u32 master_key_revision;
+
+ constexpr u32 GetVersion() const {
+ return ::sts::ams::GetVersion(this->major_version, this->minor_version, this->micro_version);
+ }
+
+ constexpr TargetFirmware GetTargetFirmware() const {
+ return this->target_firmware;
+ }
+
+ constexpr u32 GetMasterKeyRevision() const {
+ return this->master_key_revision;
+ }
+ };
+
+ struct FatalErrorContext : sf::LargeData, sf::PrefersMapAliasTransferMode {
+ static constexpr size_t MaxStackTrace = 0x20;
+ static constexpr size_t MaxStackDumpSize = 0x100;
+ static constexpr size_t NumGprs = 29;
+ static constexpr uintptr_t StdAbortMagicAddress = 0x8;
+ static constexpr u64 StdAbortMagicValue = 0xA55AF00DDEADCAFEul;
+ static constexpr u32 StdAbortErrorDesc = 0xFFE;
+ static constexpr u32 DataAbortErrorDesc = 0x101;
+ static constexpr u32 Magic = 0x31454641;
+
+ u32 magic;
+ u32 error_desc;
+ u64 title_id;
+ union {
+ u64 gprs[32];
+ struct {
+ u64 _gprs[29];
+ u64 fp;
+ u64 lr;
+ u64 sp;
+ };
+ };
+ u64 pc;
+ u64 module_base;
+ u32 pstate;
+ u32 afsr0;
+ u32 afsr1;
+ u32 esr;
+ u64 far;
+ u64 report_identifier; /* Normally just system tick. */
+ u64 stack_trace_size;
+ u64 stack_dump_size;
+ u64 stack_trace[MaxStackTrace];
+ u8 stack_dump[MaxStackDumpSize];
+ };
+
+ static_assert(sizeof(FatalErrorContext) == 0x350, "sizeof(FatalErrorContext)");
+ static_assert(std::is_pod::value, "FatalErrorContext");
+
}
diff --git a/stratosphere/libstratosphere/source/utilities.cpp b/stratosphere/libstratosphere/include/stratosphere/dd.hpp
similarity index 80%
rename from stratosphere/libstratosphere/source/utilities.cpp
rename to stratosphere/libstratosphere/include/stratosphere/dd.hpp
index af8d221d8..a4ba4aac0 100644
--- a/stratosphere/libstratosphere/source/utilities.cpp
+++ b/stratosphere/libstratosphere/include/stratosphere/dd.hpp
@@ -14,11 +14,7 @@
* along with this program. If not, see .
*/
+#pragma once
#include
-#include
-static sts::os::RecursiveMutex g_sm_session_lock;
-
-sts::os::RecursiveMutex &GetSmSessionMutex() {
- return g_sm_session_lock;
-}
+#include "dd/dd_io_mappings.hpp"
diff --git a/stratosphere/libstratosphere/include/stratosphere/dd/dd_io_mappings.hpp b/stratosphere/libstratosphere/include/stratosphere/dd/dd_io_mappings.hpp
new file mode 100644
index 000000000..a0ba2fd9a
--- /dev/null
+++ b/stratosphere/libstratosphere/include/stratosphere/dd/dd_io_mappings.hpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2018-2019 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#pragma once
+#include
+#include "../defines.hpp"
+
+namespace sts::dd {
+
+ uintptr_t QueryIoMapping(uintptr_t phys_addr, size_t size);
+
+ u32 ReadRegister(uintptr_t phys_addr);
+ void WriteRegister(uintptr_t phys_addr, u32 value);
+ u32 ReadWriteRegister(uintptr_t phys_addr, u32 value, u32 mask);
+
+ /* Convenience Helper. */
+
+ inline uintptr_t GetIoMapping(uintptr_t phys_addr, size_t size) {
+ const uintptr_t io_mapping = QueryIoMapping(phys_addr, size);
+ STS_ASSERT(io_mapping);
+ return io_mapping;
+ }
+}
diff --git a/stratosphere/libstratosphere/include/stratosphere/defines.hpp b/stratosphere/libstratosphere/include/stratosphere/defines.hpp
index 3cd70b67a..2f381820b 100644
--- a/stratosphere/libstratosphere/include/stratosphere/defines.hpp
+++ b/stratosphere/libstratosphere/include/stratosphere/defines.hpp
@@ -15,6 +15,7 @@
*/
#pragma once
+#include
#include
/* Any broadly useful language defines should go here. */
diff --git a/stratosphere/libstratosphere/include/stratosphere/os/os_common_types.hpp b/stratosphere/libstratosphere/include/stratosphere/os/os_common_types.hpp
index 8740faed1..9ed484058 100644
--- a/stratosphere/libstratosphere/include/stratosphere/os/os_common_types.hpp
+++ b/stratosphere/libstratosphere/include/stratosphere/os/os_common_types.hpp
@@ -46,14 +46,18 @@ namespace sts::os {
inline constexpr const ProcessId InvalidProcessId = ProcessId::Invalid;
- NX_INLINE Result GetProcessId(os::ProcessId *out, ::Handle process_handle) {
+ NX_INLINE Result TryGetProcessId(os::ProcessId *out, ::Handle process_handle) {
return svcGetProcessId(&out->value, process_handle);
}
+ NX_INLINE os::ProcessId GetProcessId(::Handle process_handle) {
+ os::ProcessId process_id;
+ R_ASSERT(TryGetProcessId(&process_id, process_handle));
+ return process_id;
+ }
+
NX_INLINE ProcessId GetCurrentProcessId() {
- os::ProcessId current_process_id;
- R_ASSERT(GetProcessId(¤t_process_id, CUR_PROCESS_HANDLE));
- return current_process_id;
+ return GetProcessId(CUR_PROCESS_HANDLE);
}
inline constexpr bool operator==(const ProcessId &lhs, const ProcessId &rhs) {
diff --git a/stratosphere/libstratosphere/include/stratosphere/services/bpc_ams.h b/stratosphere/libstratosphere/include/stratosphere/services/bpc_ams.h
deleted file mode 100644
index c8e11a73f..000000000
--- a/stratosphere/libstratosphere/include/stratosphere/services/bpc_ams.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2018-2019 Atmosphère-NX
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#pragma once
-#include
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define AMS_FATAL_ERROR_MAX_STACKTRACE 0x20
-#define AMS_FATAL_ERROR_MAX_STACKDUMP 0x100
-
-#define STD_ABORT_ADDR_MAGIC (0x8)
-#define STD_ABORT_VALUE_MAGIC (0xA55AF00DDEADCAFEul)
-#define DATA_ABORT_ERROR_DESC (0x101)
-#define STD_ABORT_ERROR_DESC (0xFFE)
-
-typedef struct {
- u32 magic;
- u32 error_desc;
- u64 title_id;
- union {
- u64 gprs[32];
- struct {
- u64 _gprs[29];
- u64 fp;
- u64 lr;
- u64 sp;
- };
- };
- u64 pc;
- u64 module_base;
- u32 pstate;
- u32 afsr0;
- u32 afsr1;
- u32 esr;
- u64 far;
- u64 report_identifier; /* Normally just system tick. */
- u64 stack_trace_size;
- u64 stack_dump_size;
- u64 stack_trace[AMS_FATAL_ERROR_MAX_STACKTRACE];
- u8 stack_dump[AMS_FATAL_ERROR_MAX_STACKDUMP];
-} AtmosphereFatalErrorContext;
-
-Result bpcAmsInitialize(void);
-void bpcAmsExit(void);
-
-Result bpcAmsRebootToFatalError(AtmosphereFatalErrorContext *ctx);
-
-#ifdef __cplusplus
-}
-#endif
\ No newline at end of file
diff --git a/stratosphere/libstratosphere/include/stratosphere/sm.hpp b/stratosphere/libstratosphere/include/stratosphere/sm.hpp
index a334419a1..5c6ac9f36 100644
--- a/stratosphere/libstratosphere/include/stratosphere/sm.hpp
+++ b/stratosphere/libstratosphere/include/stratosphere/sm.hpp
@@ -20,3 +20,4 @@
#include "sm/sm_types.hpp"
#include "sm/sm_api.hpp"
#include "sm/sm_mitm_api.hpp"
+#include "sm/sm_scoped_holder.hpp"
diff --git a/stratosphere/libstratosphere/include/stratosphere/sm/sm_api.hpp b/stratosphere/libstratosphere/include/stratosphere/sm/sm_api.hpp
index 80e12cb79..2fb4f9381 100644
--- a/stratosphere/libstratosphere/include/stratosphere/sm/sm_api.hpp
+++ b/stratosphere/libstratosphere/include/stratosphere/sm/sm_api.hpp
@@ -29,4 +29,17 @@ namespace sts::sm {
Result HasService(bool *out, ServiceName name);
Result WaitService(ServiceName name);
+ /* Scoped session access. */
+ namespace impl {
+
+ void DoWithSessionImpl(void (*Invoker)(void *), void *Function);
+
+ }
+
+ template
+ NX_CONSTEXPR void DoWithSession(F f) {
+ auto invoker = +[](void *func) { (*(F *)func)(); };
+ impl::DoWithSessionImpl(invoker, &f);
+ }
+
}
diff --git a/stratosphere/libstratosphere/include/stratosphere/sm/sm_scoped_holder.hpp b/stratosphere/libstratosphere/include/stratosphere/sm/sm_scoped_holder.hpp
new file mode 100644
index 000000000..a7ffb724e
--- /dev/null
+++ b/stratosphere/libstratosphere/include/stratosphere/sm/sm_scoped_holder.hpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2018-2019 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#pragma once
+
+#include "sm_api.hpp"
+
+namespace sts::sm {
+
+ /* Utility, for scoped access to libnx services. */
+ template
+ class ScopedServiceHolder {
+ NON_COPYABLE(ScopedServiceHolder);
+ private:
+ Result result;
+ bool has_initialized;
+ public:
+ ScopedServiceHolder(bool initialize = true) : result(ResultSuccess), has_initialized(false) {
+ if (initialize) {
+ this->Initialize();
+ }
+ }
+
+ ~ScopedServiceHolder() {
+ if (this->has_initialized) {
+ this->Finalize();
+ }
+ }
+
+ ScopedServiceHolder(ScopedServiceHolder&& rhs) {
+ this->result = rhs.result;
+ this->has_initialized = rhs.has_initialized;
+ rhs.result = ResultSuccess;
+ rhs.has_initialized = false;
+ }
+
+ ScopedServiceHolder& operator=(ScopedServiceHolder&& rhs) {
+ rhs.Swap(*this);
+ return *this;
+ }
+
+ void Swap(ScopedServiceHolder& rhs) {
+ std::swap(this->result, rhs.result);
+ std::swap(this->has_initialized, rhs.has_initialized);
+ }
+
+ explicit operator bool() const {
+ return this->has_initialized;
+ }
+
+ Result Initialize() {
+ STS_ASSERT(!this->has_initialized);
+
+ sm::DoWithSession([&]() {
+ this->result = Initializer();
+ });
+
+ this->has_initialized = R_SUCCEEDED(this->result);
+ return this->result;
+ }
+
+ void Finalize() {
+ STS_ASSERT(this->has_initialized);
+ Finalizer();
+ this->has_initialized = false;
+ }
+
+ Result GetResult() const {
+ return this->result;
+ }
+ };
+
+}
diff --git a/stratosphere/libstratosphere/include/stratosphere/sm/sm_types.hpp b/stratosphere/libstratosphere/include/stratosphere/sm/sm_types.hpp
index 812cc2f71..30d97b3b3 100644
--- a/stratosphere/libstratosphere/include/stratosphere/sm/sm_types.hpp
+++ b/stratosphere/libstratosphere/include/stratosphere/sm/sm_types.hpp
@@ -70,67 +70,4 @@ namespace sts::sm {
};
static_assert(sizeof(ServiceRecord) == 0x30, "ServiceRecord definition!");
- /* Utility, for scoped access to libnx services. */
- template
- class ScopedServiceHolder {
- NON_COPYABLE(ScopedServiceHolder);
- private:
- Result result;
- bool has_initialized;
- public:
- ScopedServiceHolder(bool initialize = true) : result(ResultSuccess), has_initialized(false) {
- if (initialize) {
- this->Initialize();
- }
- }
-
- ~ScopedServiceHolder() {
- if (this->has_initialized) {
- this->Finalize();
- }
- }
-
- ScopedServiceHolder(ScopedServiceHolder&& rhs) {
- this->result = rhs.result;
- this->has_initialized = rhs.has_initialized;
- rhs.result = ResultSuccess;
- rhs.has_initialized = false;
- }
-
- ScopedServiceHolder& operator=(ScopedServiceHolder&& rhs) {
- rhs.Swap(*this);
- return *this;
- }
-
- void Swap(ScopedServiceHolder& rhs) {
- std::swap(this->result, rhs.result);
- std::swap(this->has_initialized, rhs.has_initialized);
- }
-
- explicit operator bool() const {
- return this->has_initialized;
- }
-
- Result Initialize() {
- STS_ASSERT(!this->has_initialized);
-
- DoWithSmSession([&]() {
- this->result = Initializer();
- });
-
- this->has_initialized = R_SUCCEEDED(this->result);
- return this->result;
- }
-
- void Finalize() {
- STS_ASSERT(this->has_initialized);
- Finalizer();
- this->has_initialized = false;
- }
-
- Result GetResult() const {
- return this->result;
- }
- };
-
}
diff --git a/stratosphere/libstratosphere/include/stratosphere/spl/smc/spl_smc.hpp b/stratosphere/libstratosphere/include/stratosphere/spl/smc/spl_smc.hpp
index 46a011a38..fe39687bd 100644
--- a/stratosphere/libstratosphere/include/stratosphere/spl/smc/spl_smc.hpp
+++ b/stratosphere/libstratosphere/include/stratosphere/spl/smc/spl_smc.hpp
@@ -16,6 +16,7 @@
#pragma once
#include
+#include
#include "../spl_types.hpp"
@@ -54,4 +55,21 @@ namespace sts::spl::smc {
Result DecryptRsaPrivateKey(size_t *out_size, void *data, size_t size, const AccessKey &access_key, const KeySource &source, u32 option);
Result ImportSecureExpModKey(const void *data, size_t size, const AccessKey &access_key, const KeySource &source, u32 option);
+ /* Atmosphere functions. */
+ Result AtmosphereCopyToIram(uintptr_t iram_dst, const void *dram_src, size_t size);
+ Result AtmosphereCopyFromIram(void *dram_dst, uintptr_t iram_src, size_t size);
+ Result AtmosphereReadWriteRegister(uint64_t address, uint32_t mask, uint32_t value, uint32_t *out_value);
+ Result AtmosphereWriteAddress(void *dst, const void *src, size_t size);
+
+ /* Helpers. */
+ inline Result SetConfig(SplConfigItem which, const u64 value) {
+ return SetConfig(which, &value, 1);
+ }
+
+ template
+ inline Result AtmosphereWriteAddress(void *dst, const T value) {
+ static_assert(std::is_integral::value && sizeof(T) <= 8 && (sizeof(T) & (sizeof(T) - 1)) == 0, "AtmosphereWriteAddress requires integral type.");
+ return AtmosphereWriteAddress(dst, &value, sizeof(T));
+ }
+
}
diff --git a/stratosphere/libstratosphere/include/stratosphere/spl/spl_types.hpp b/stratosphere/libstratosphere/include/stratosphere/spl/spl_types.hpp
index 56ce8fdd4..664811e2c 100644
--- a/stratosphere/libstratosphere/include/stratosphere/spl/spl_types.hpp
+++ b/stratosphere/libstratosphere/include/stratosphere/spl/spl_types.hpp
@@ -46,6 +46,12 @@ namespace sts::spl {
ImportEsKey = 0xC300100C,
DecryptRsaPrivateKey = 0xC300100D,
ImportSecureExpModKey = 0xC300100E,
+
+ /* Atmosphere functions. */
+ AtmosphereIramCopy = 0xF0000201,
+ AtmosphereReadWriteRegister = 0xF0000002,
+ AtmosphereWriteAddress = 0xF0000003,
+ AtmosphereGetEmummcConfig = 0xF0000404,
};
enum class Result {
@@ -177,3 +183,10 @@ namespace sts::spl {
#pragma pack(pop)
}
+
+/* Extensions to libnx spl config item enum. */
+constexpr inline SplConfigItem SplConfigItem_ExosphereApiVersion = static_cast(65000);
+constexpr inline SplConfigItem SplConfigItem_ExosphereNeedsReboot = static_cast(65001);
+constexpr inline SplConfigItem SplConfigItem_ExosphereNeedsShutdown = static_cast(65002);
+constexpr inline SplConfigItem SplConfigItem_ExosphereGitCommitHash = static_cast(65003);
+constexpr inline SplConfigItem SplConfigItem_ExosphereHasRcmBugPatch = static_cast(65004);
diff --git a/stratosphere/libstratosphere/include/stratosphere/utilities.hpp b/stratosphere/libstratosphere/include/stratosphere/utilities.hpp
deleted file mode 100644
index 4de68dc18..000000000
--- a/stratosphere/libstratosphere/include/stratosphere/utilities.hpp
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 2018-2019 Atmosphère-NX
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#pragma once
-#include
-#include "defines.hpp"
-#include "results.hpp"
-#include "os.hpp"
-
-static inline uintptr_t GetIoMapping(const u64 io_addr, const u64 io_size) {
- u64 vaddr;
- const u64 aligned_addr = (io_addr & ~0xFFFul);
- const u64 aligned_size = io_size + (io_addr - aligned_addr);
- R_ASSERT(svcQueryIoMapping(&vaddr, aligned_addr, aligned_size));
- return static_cast(vaddr + (io_addr - aligned_addr));
-}
-
-static inline void RebootToRcm() {
- SecmonArgs args = {0};
- args.X[0] = 0xC3000401; /* smcSetConfig */
- args.X[1] = 65001; /* Exosphere reboot */
- args.X[3] = 1; /* Perform reboot to RCM. */
- svcCallSecureMonitor(&args);
-}
-
-static inline void RebootToIramPayload() {
- SecmonArgs args = {0};
- args.X[0] = 0xC3000401; /* smcSetConfig */
- args.X[1] = 65001; /* Exosphere reboot */
- args.X[3] = 2; /* Perform reboot to payload at 0x40010000 in IRAM. */
- svcCallSecureMonitor(&args);
-}
-
-static inline void PerformShutdownSmc() {
- SecmonArgs args = {0};
- args.X[0] = 0xC3000401; /* smcSetConfig */
- args.X[1] = 65002; /* Exosphere shutdown */
- args.X[3] = 1; /* Perform shutdown. */
- svcCallSecureMonitor(&args);
-}
-
-static inline void CopyToIram(uintptr_t iram_addr, void *src_addr, size_t size) {
- SecmonArgs args = {0};
- args.X[0] = 0xF0000201; /* smcAmsIramCopy */
- args.X[1] = (u64)src_addr; /* DRAM address */
- args.X[2] = (u64)iram_addr; /* IRAM address */
- args.X[3] = size; /* Amount to copy */
- args.X[4] = 1; /* 1 = Write */
- svcCallSecureMonitor(&args);
-}
-
-static inline void CopyFromIram(void *dst_addr, uintptr_t iram_addr, size_t size) {
- SecmonArgs args = {0};
- args.X[0] = 0xF0000201; /* smcAmsIramCopy */
- args.X[1] = (u64)dst_addr; /* DRAM address */
- args.X[2] = (u64)iram_addr; /* IRAM address */
- args.X[3] = size; /* Amount to copy */
- args.X[4] = 0; /* 0 = Read */
- svcCallSecureMonitor(&args);
-}
-
-static inline Result SmcGetConfig(SplConfigItem config_item, u64 *out_config) {
- SecmonArgs args = {0};
- args.X[0] = 0xC3000002; /* smcGetConfig */
- args.X[1] = (u64)config_item; /* config item */
-
- R_TRY(svcCallSecureMonitor(&args));
- if (args.X[0] != 0) {
- /* SPL result n = SMC result n */
- return MAKERESULT(26, args.X[0]);
- }
-
- if (out_config) {
- *out_config = args.X[1];
- }
- return ResultSuccess;
-}
-
-static inline Result GetRcmBugPatched(bool *out) {
- u64 tmp = 0;
- R_TRY(SmcGetConfig((SplConfigItem)65004, &tmp));
- *out = (tmp != 0);
- return ResultSuccess;
-}
-
-static inline bool IsRcmBugPatched() {
- bool rcm_bug_patched;
- R_ASSERT(GetRcmBugPatched(&rcm_bug_patched));
- return rcm_bug_patched;
-}
-
-static inline Result GetShouldBlankProdInfo(bool *out) {
- u64 tmp = 0;
- R_TRY(SmcGetConfig((SplConfigItem)65005, &tmp));
- *out = (tmp != 0);
- return ResultSuccess;
-}
-
-static inline bool ShouldBlankProdInfo() {
- bool should_blank_prodinfo;
- R_ASSERT(GetShouldBlankProdInfo(&should_blank_prodinfo));
- return should_blank_prodinfo;
-}
-
-sts::os::RecursiveMutex &GetSmSessionMutex();
-
-template
-static void DoWithSmSession(F f) {
- std::scoped_lock lk(GetSmSessionMutex());
- {
- R_ASSERT(smInitialize());
- f();
- smExit();
- }
-}
diff --git a/stratosphere/libstratosphere/include/stratosphere/version_check.hpp b/stratosphere/libstratosphere/include/stratosphere/version_check.hpp
deleted file mode 100644
index f9f3dea11..000000000
--- a/stratosphere/libstratosphere/include/stratosphere/version_check.hpp
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2018-2019 Atmosphère-NX
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#pragma once
-#include
-
-#include "results.hpp"
-
-static inline void GetAtmosphereApiVersion(u32 *major, u32 *minor, u32 *micro, u32 *target_fw, u32 *mkey_rev) {
- /* Check for exosphere API compatibility. */
- u64 exosphere_cfg;
- if (R_FAILED(SmcGetConfig((SplConfigItem)65000, &exosphere_cfg))) {
- fatalSimple(ResultAtmosphereExosphereNotPresent);
- }
-
- if (mkey_rev) {
- *mkey_rev = (u32)((exosphere_cfg >> 0x00) & 0xFF);
- }
-
- if (target_fw) {
- *target_fw = (u32)((exosphere_cfg >> 0x08) & 0xFF);
- }
-
- if (micro) {
- *micro = (u32)((exosphere_cfg >> 0x10) & 0xFF);
- }
-
- if (minor) {
- *minor = (u32)((exosphere_cfg >> 0x18) & 0xFF);
- }
-
- if (major) {
- *major = (u32)((exosphere_cfg >> 0x20) & 0xFF);
- }
-}
-
-static inline u32 MakeAtmosphereVersion(u32 major, u32 minor, u32 micro) {
- return (major << 16) | (minor << 8) | micro;
-}
-
-static inline void CheckAtmosphereVersion(u32 expected_major, u32 expected_minor, u32 expected_micro) {
- u32 major, minor, micro;
- GetAtmosphereApiVersion(&major, &minor, µ, nullptr, nullptr);
-
- if (MakeAtmosphereVersion(major, minor, micro) < MakeAtmosphereVersion(expected_major, expected_minor, expected_micro)) {
- fatalSimple(ResultAtmosphereVersionMismatch);
- }
-}
-
-#define CURRENT_ATMOSPHERE_VERSION ATMOSPHERE_RELEASE_VERSION_MAJOR, ATMOSPHERE_RELEASE_VERSION_MINOR, ATMOSPHERE_RELEASE_VERSION_MICRO
-
-#ifdef ATMOSPHERE_GIT_BRANCH
-static inline const char *GetAtmosphereGitBranch() {
- return ATMOSPHERE_GIT_BRANCH;
-}
-#endif
-
-#ifdef ATMOSPHERE_GIT_REV
-static inline const char *GetAtmosphereGitRevision() {
- return ATMOSPHERE_GIT_REV;
-}
-#endif
diff --git a/stratosphere/libstratosphere/source/ams/ams_bpc.c b/stratosphere/libstratosphere/source/ams/ams_bpc.c
new file mode 100644
index 000000000..84c1d4763
--- /dev/null
+++ b/stratosphere/libstratosphere/source/ams/ams_bpc.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2018-2019 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#define NX_SERVICE_ASSUME_NON_DOMAIN
+#include "../service_guard.h"
+#include "ams_bpc.h"
+
+static Service g_amsBpcSrv;
+
+NX_GENERATE_SERVICE_GUARD(amsBpc);
+
+Result _amsBpcInitialize(void) {
+ Handle h;
+ Result rc = svcConnectToNamedPort(&h, "bpc:ams"); /* TODO: ams:bpc */
+ if (R_SUCCEEDED(rc)) serviceCreate(&g_amsBpcSrv, h);
+ return rc;
+}
+
+void _amsBpcCleanup(void) {
+ serviceClose(&g_amsBpcSrv);
+}
+
+Service *amsBpcGetServiceSession(void) {
+ return &g_amsBpcSrv;
+}
+
+Result amsBpcRebootToFatalError(void *ctx) {
+ /* Note: this takes in an sts::ams::FatalErrorContext. */
+ /* static_assert(sizeof() == 0x350) is done at type definition. */
+ return serviceDispatch(&g_amsBpcSrv, 65000,
+ .buffer_attrs = { SfBufferAttr_Out | SfBufferAttr_HipcMapAlias | SfBufferAttr_FixedSize },
+ .buffers = { { ctx, 0x350 } },
+ );
+}
diff --git a/stratosphere/libstratosphere/source/ams/ams_bpc.h b/stratosphere/libstratosphere/source/ams/ams_bpc.h
new file mode 100644
index 000000000..91dfd1e41
--- /dev/null
+++ b/stratosphere/libstratosphere/source/ams/ams_bpc.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018-2019 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#pragma once
+#include
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+Result amsBpcInitialize(void);
+void amsBpcExit(void);
+Service *amsBpcGetServiceSession(void);
+
+Result amsBpcRebootToFatalError(void *ctx);
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/stratosphere/libstratosphere/source/ams/ams_environment.cpp b/stratosphere/libstratosphere/source/ams/ams_environment.cpp
new file mode 100644
index 000000000..77d3d8e64
--- /dev/null
+++ b/stratosphere/libstratosphere/source/ams/ams_environment.cpp
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2018-2019 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include "ams_bpc.h"
+
+namespace sts::ams {
+
+ namespace {
+
+ inline u64 GetPc() {
+ u64 pc;
+ __asm__ __volatile__ ("adr %[pc], ." : [pc]"=&r"(pc) :: );
+ return pc;
+ }
+
+ struct StackFrame {
+ u64 fp;
+ u64 lr;
+ };
+
+ }
+
+ extern ncm::TitleId StratosphereTitleId;
+
+ void WEAK ExceptionHandler(FatalErrorContext *ctx) {
+ R_ASSERT(amsBpcInitialize());
+ R_ASSERT(amsBpcRebootToFatalError(ctx));
+ while (1) { /* ... */ }
+ }
+
+ void CrashHandler(ThreadExceptionDump *ctx) {
+ FatalErrorContext ams_ctx;
+
+ /* Convert thread dump to atmosphere dump. */
+ {
+ ams_ctx.magic = FatalErrorContext::Magic;
+ ams_ctx.error_desc = ctx->error_desc;
+ ams_ctx.title_id = static_cast(StratosphereTitleId);
+ for (size_t i = 0; i < FatalErrorContext::NumGprs; i++) {
+ ams_ctx.gprs[i] = ctx->cpu_gprs[i].x;
+ }
+ if (ams_ctx.error_desc == FatalErrorContext::DataAbortErrorDesc &&
+ ams_ctx.gprs[27] == FatalErrorContext::StdAbortMagicAddress &&
+ ams_ctx.gprs[28] == FatalErrorContext::StdAbortMagicValue)
+ {
+ /* Detect std::abort(). */
+ ams_ctx.error_desc = FatalErrorContext::StdAbortErrorDesc;
+ }
+
+ ams_ctx.fp = ctx->fp.x;
+ ams_ctx.lr = ctx->lr.x;
+ ams_ctx.sp = ctx->sp.x;
+ ams_ctx.pc = ctx->pc.x;
+ ams_ctx.pstate = ctx->pstate;
+ ams_ctx.afsr0 = ctx->afsr0;
+ ams_ctx.afsr1 = ctx->afsr1;
+ ams_ctx.far = ctx->far.x;
+ ams_ctx.report_identifier = armGetSystemTick();
+ /* Grab module base. */
+ {
+ MemoryInfo mem_info;
+ u32 page_info;
+ if (R_SUCCEEDED(svcQueryMemory(&mem_info, &page_info, GetPc()))) {
+ ams_ctx.module_base = mem_info.addr;
+ } else {
+ ams_ctx.module_base = 0;
+ }
+ }
+ ams_ctx.stack_trace_size = 0;
+ u64 cur_fp = ams_ctx.fp;
+ for (size_t i = 0; i < FatalErrorContext::MaxStackTrace; i++) {
+ /* Validate current frame. */
+ if (cur_fp == 0 || (cur_fp & 0xF)) {
+ break;
+ }
+
+ /* Read a new frame. */
+ StackFrame cur_frame;
+ MemoryInfo mem_info;
+ u32 page_info;
+ if (R_SUCCEEDED(svcQueryMemory(&mem_info, &page_info, cur_fp)) && (mem_info.perm & Perm_R) == Perm_R) {
+ std::memcpy(&cur_frame, reinterpret_cast(cur_fp), sizeof(cur_frame));
+ } else {
+ break;
+ }
+
+ /* Advance to the next frame. */
+ ams_ctx.stack_trace[ams_ctx.stack_trace_size++] = cur_frame.lr;
+ cur_fp = cur_frame.fp;
+ }
+ /* Clear unused parts of stack trace. */
+ for (size_t i = ams_ctx.stack_trace_size; i < FatalErrorContext::MaxStackTrace; i++) {
+ ams_ctx.stack_trace[i] = 0;
+ }
+
+ /* Grab up to 0x100 of stack. */
+ {
+ MemoryInfo mem_info;
+ u32 page_info;
+ if (R_SUCCEEDED(svcQueryMemory(&mem_info, &page_info, ams_ctx.sp)) && (mem_info.perm & Perm_R) == Perm_R) {
+ size_t copy_size = std::min(FatalErrorContext::MaxStackDumpSize, static_cast(mem_info.addr + mem_info.size - ams_ctx.sp));
+ ams_ctx.stack_dump_size = copy_size;
+ std::memcpy(ams_ctx.stack_dump, reinterpret_cast(ams_ctx.sp), copy_size);
+ } else {
+ ams_ctx.stack_dump_size = 0;
+ }
+ }
+ }
+
+ /* Just call the user exception handler. */
+ ::sts::ams::ExceptionHandler(&ams_ctx);
+ }
+
+ inline __attribute((noreturn)) void AbortImpl() {
+ /* Just perform a data abort. */
+ register u64 addr __asm__("x27") = FatalErrorContext::StdAbortMagicAddress;
+ register u64 val __asm__("x28") = FatalErrorContext::StdAbortMagicValue;
+ while (true) {
+ __asm__ __volatile__ (
+ "str %[val], [%[addr]]"
+ :
+ : [val]"r"(val), [addr]"r"(addr)
+ );
+ }
+ }
+
+}
+
+extern "C" {
+
+ /* Redefine abort to trigger these handlers. */
+ void abort();
+
+}
+
+/* Custom abort handler, so that std::abort will trigger these. */
+void abort() {
+ sts::ams::AbortImpl();
+}
\ No newline at end of file
diff --git a/stratosphere/libstratosphere/source/ams/ams_exosphere_api.cpp b/stratosphere/libstratosphere/source/ams/ams_exosphere_api.cpp
new file mode 100644
index 000000000..39c8f60af
--- /dev/null
+++ b/stratosphere/libstratosphere/source/ams/ams_exosphere_api.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2018-2019 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+#include
+
+namespace sts::ams {
+
+ ApiInfo GetApiInfo() {
+ u64 exosphere_cfg;
+ if (spl::smc::GetConfig(&exosphere_cfg, 1, SplConfigItem_ExosphereApiVersion) != spl::smc::Result::Success) {
+ R_ASSERT(ResultAtmosphereExosphereNotPresent);
+ }
+
+ return ApiInfo{
+ .major_version = static_cast((exosphere_cfg >> 0x20) & 0xFF),
+ .minor_version = static_cast((exosphere_cfg >> 0x18) & 0xFF),
+ .micro_version = static_cast((exosphere_cfg >> 0x10) & 0xFF),
+ .target_firmware = static_cast((exosphere_cfg >> 0x08) & 0xFF),
+ .master_key_revision = static_cast((exosphere_cfg >> 0x00) & 0xFF),
+ };
+ }
+
+ void ForceRebootToRcm() {
+ R_ASSERT(spl::smc::ConvertResult(spl::smc::SetConfig(SplConfigItem_ExosphereNeedsReboot, 1)));
+ }
+
+ void ForceRebootToIramPayload() {
+ R_ASSERT(spl::smc::ConvertResult(spl::smc::SetConfig(SplConfigItem_ExosphereNeedsReboot, 2)));
+ }
+
+ void ForceShutdown() {
+ R_ASSERT(spl::smc::ConvertResult(spl::smc::SetConfig(SplConfigItem_ExosphereNeedsShutdown, 1)));
+ }
+
+ void CopyToIram(uintptr_t iram_dst, const void *dram_src, size_t size) {
+ spl::smc::AtmosphereCopyToIram(iram_dst, dram_src, size);
+ }
+
+ void CopyFromIram(void *dram_dst, uintptr_t iram_src, size_t size) {
+ spl::smc::AtmosphereCopyFromIram(dram_dst, iram_src, size);
+ }
+
+ namespace {
+
+ inline Result GetRcmBugPatched(bool *out) {
+ u64 tmp;
+ R_TRY(spl::smc::ConvertResult(spl::smc::GetConfig(&tmp, 1, SplConfigItem_ExosphereHasRcmBugPatch)));
+ *out = (tmp != 0);
+ return ResultSuccess;
+ }
+
+ }
+
+ bool IsRcmBugPatched() {
+ bool rcm_bug_patched;
+ R_ASSERT(GetRcmBugPatched(&rcm_bug_patched));
+ return rcm_bug_patched;
+ }
+
+}
diff --git a/stratosphere/libstratosphere/source/ams/ams_hos_version_api.cpp b/stratosphere/libstratosphere/source/ams/ams_hos_version_api.cpp
index 7a0404e0c..5f6ac7b35 100644
--- a/stratosphere/libstratosphere/source/ams/ams_hos_version_api.cpp
+++ b/stratosphere/libstratosphere/source/ams/ams_hos_version_api.cpp
@@ -35,19 +35,7 @@ namespace sts::hos {
return;
}
- /* TODO: spl::smc:: */
- u32 target_fw = 0;
- {
- SecmonArgs args = {0};
- args.X[0] = 0xC3000002; /* smcGetConfig */
- args.X[1] = 65000; /* ConfigItem_ExosphereVersion */
- R_ASSERT(svcCallSecureMonitor(&args));
- STS_ASSERT(args.X[0] == 0);
-
- target_fw = (args.X[1] >> 0x08) & 0xFF;
- }
-
- switch (static_cast(target_fw)) {
+ switch (ams::GetApiInfo().GetTargetFirmware()) {
case ams::TargetFirmware_100:
g_hos_version = hos::Version_100;
break;
diff --git a/stratosphere/libstratosphere/source/bpc_ams.c b/stratosphere/libstratosphere/source/bpc_ams.c
deleted file mode 100644
index 0728e0911..000000000
--- a/stratosphere/libstratosphere/source/bpc_ams.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2018-2019 Atmosphère-NX
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#include
-#include
-#include
-
-static Service g_bpcAmsSrv;
-static u64 g_bpcAmsAmsRefcnt;
-
-Result bpcAmsInitialize(void) {
- atomicIncrement64(&g_bpcAmsAmsRefcnt);
-
- if (serviceIsActive(&g_bpcAmsSrv)) {
- return 0;
- }
-
- Handle h;
- Result rc = svcConnectToNamedPort(&h, "bpc:ams");
- if (R_SUCCEEDED(rc)) {
- serviceCreate(&g_bpcAmsSrv, h);
- }
-
- return rc;
-}
-
-void bpcAmsExit(void) {
- if (atomicDecrement64(&g_bpcAmsAmsRefcnt) == 0)
- serviceClose(&g_bpcAmsSrv);
-}
-
-Result bpcAmsRebootToFatalError(AtmosphereFatalErrorContext *ctx) {
- IpcCommand c;
- ipcInitialize(&c);
- ipcAddSendBuffer(&c, ctx, sizeof(*ctx), BufferType_Normal);
-
- struct {
- u64 magic;
- u64 cmd_id;
- } *raw;
-
- raw = serviceIpcPrepareHeader(&g_bpcAmsSrv, &c, sizeof(*raw));
-
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65000;
-
- Result rc = serviceIpcDispatch(&g_bpcAmsSrv);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- } *resp;
-
- serviceIpcParse(&g_bpcAmsSrv, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
- }
-
- return rc;
-}
diff --git a/stratosphere/libstratosphere/source/dd/dd_io_mappings.cpp b/stratosphere/libstratosphere/source/dd/dd_io_mappings.cpp
new file mode 100644
index 000000000..5bb6b2ae6
--- /dev/null
+++ b/stratosphere/libstratosphere/source/dd/dd_io_mappings.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2018-2019 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#include
+
+namespace sts::dd {
+
+ uintptr_t QueryIoMapping(uintptr_t phys_addr, size_t size) {
+ u64 virtual_addr;
+ const u64 aligned_addr = util::AlignDown(phys_addr, 0x1000);
+ const size_t offset = phys_addr - aligned_addr;
+ const u64 aligned_size = size + offset;
+ R_TRY_CATCH(svcQueryIoMapping(&virtual_addr, aligned_addr, aligned_size)) {
+ /* Official software handles this by returning 0. */
+ R_CATCH(ResultKernelNotFound) { return 0; }
+ } R_END_TRY_CATCH_WITH_ASSERT;
+
+ return static_cast(virtual_addr + offset);
+ }
+
+ namespace {
+
+ inline u32 ReadWriteRegisterImpl(uintptr_t phys_addr, u32 value, u32 mask) {
+ u32 out_value;
+ R_ASSERT(svcReadWriteRegister(&out_value, phys_addr, mask, value));
+ return out_value;
+ }
+
+ }
+
+ u32 ReadRegister(uintptr_t phys_addr) {
+ return ReadWriteRegisterImpl(phys_addr, 0, 0);
+ }
+
+ void WriteRegister(uintptr_t phys_addr, u32 value) {
+ ReadWriteRegisterImpl(phys_addr, value, ~u32());
+ }
+
+ u32 ReadWriteRegister(uintptr_t phys_addr, u32 value, u32 mask) {
+ return ReadWriteRegisterImpl(phys_addr, value, mask);
+ }
+
+}
diff --git a/stratosphere/libstratosphere/source/dmnt/dmntcht.c b/stratosphere/libstratosphere/source/dmnt/dmntcht.c
new file mode 100644
index 000000000..86ed9be2f
--- /dev/null
+++ b/stratosphere/libstratosphere/source/dmnt/dmntcht.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2018-2019 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#define NX_SERVICE_ASSUME_NON_DOMAIN
+#include "../service_guard.h"
+#include "dmntcht.h"
+
+static Service g_dmntchtSrv;
+
+NX_GENERATE_SERVICE_GUARD(dmntcht);
+
+Result _dmntchtInitialize(void) {
+ return smGetService(&g_dmntchtSrv, "dmnt:cht");
+}
+
+void _dmntchtCleanup(void) {
+ serviceClose(&g_dmntchtSrv);
+}
+
+Service* dmntchtGetServiceSession(void) {
+ return &g_dmntchtSrv;
+}
+
+Result dmntchtHasCheatProcess(bool *out) {
+ u8 tmp;
+ Result rc = serviceDispatchOut(&g_dmntchtSrv, 65000, tmp);
+ if (R_SUCCEEDED(rc) && out) *out = tmp & 1;
+}
+
+Result dmntchtGetCheatProcessEvent(Event *event) {
+ Handle evt_handle;
+ Result rc = serviceDispatch(&g_dmntchtSrv, 65001,
+ .out_handle_attrs = { SfOutHandleAttr_HipcCopy },
+ .out_handles = &evt_handle,
+ );
+
+ if (R_SUCCEEDED(rc)) {
+ eventLoadRemote(&g_dmntchtSrv, evt_handle, true);
+ }
+
+ return rc;
+}
+
+Result dmntchtGetCheatProcessMetadata(DmntCheatProcessMetadata *out_metadata) {
+ return serviceDispatchOut(&g_dmntchtSrv, 65002, *out_metadata);
+}
+
+Result dmntchtForceOpenCheatProcess(void) {
+ return serviceDispatch(&g_dmntchtSrv, 65003);
+}
+
+static Result _dmntchtGetCount(u64 *out_count, u32 cmd_id) {
+ return serviceDispatchOut(&g_dmntchtSrv, cmd_id, *out_count);
+}
+
+static Result _dmntchtGetEntries(void *buffer, u64 buffer_size, u64 offset, u64 *out_count, u32 cmd_id) {
+ return serviceDispatchInOut(&g_dmntchtSrv, cmd_id, offset, *out_count,
+ .buffer_attrs = { SfBufferAttr_Out | SfBufferAttr_HipcMapAlias },
+ .buffers = { { buffer, buffer_size } },
+ );
+}
+
+static Result _dmntchtCmdInU32NoOut(u32 in, u32 cmd_id) {
+ return serviceDispatchIn(&g_dmntchtSrv, cmd_id, in);
+}
+
+Result dmntchtGetCheatProcessMappingCount(u64 *out_count) {
+ return _dmntchtGetCount(65100, out_count);
+}
+
+Result dmntchtGetCheatProcessMappings(MemoryInfo *buffer, u64 max_count, u64 offset, u64 *out_count) {
+ return _dmntchtGetEntries(65101, buffer, sizeof(*buffer) * max_count, offset, out_count);
+}
+
+Result dmntchtReadCheatProcessMemory(u64 address, void *buffer, size_t size) {
+ const struct {
+ u64 address;
+ u64 size;
+ } in = { address, size };
+ return serviceDispatchIn(&g_dmntchtSrv, 65102, in,
+ .buffer_attrs = { SfBufferAttr_Out | SfBufferAttr_HipcMapAlias },
+ .buffers = { { buffer, size } },
+ );
+}
+
+Result dmntchtWriteCheatProcessMemory(u64 address, const void *buffer, size_t size) {
+ const struct {
+ u64 address;
+ u64 size;
+ } in = { address, size };
+ return serviceDispatchIn(&g_dmntchtSrv, 65103, in,
+ .buffer_attrs = { SfBufferAttr_In | SfBufferAttr_HipcMapAlias },
+ .buffers = { { buffer, size } },
+ );
+}
+
+Result dmntchtQueryCheatProcessMemory(MemoryInfo *mem_info, u64 address){
+ return serviceDispatchInOut(&g_dmntchtSrv, 65104, address, *mem_info);
+}
+
+Result dmntchtGetCheatCount(u64 *out_count) {
+ return _dmntchtGetCount(65200, out_count);
+}
+
+Result dmntchtGetCheats(DmntCheatEntry *buffer, u64 max_count, u64 offset, u64 *out_count) {
+ return _dmntchtGetEntries(65201, buffer, sizeof(*buffer) * max_count, offset, out_count);
+}
+
+Result dmntchtGetCheatById(DmntCheatEntry *out, u32 cheat_id) {
+ return serviceDispatchIn(&g_dmntchtSrv, 65202, cheat_id,
+ .buffer_attrs = { SfBufferAttr_Out | SfBufferAttr_HipcMapAlias | SfBufferAttr_FixedSize },
+ .buffers = { { out, sizeof(*out) } },
+ );
+}
+
+Result dmntchtToggleCheat(u32 cheat_id) {
+ return _dmntchtCmdInU32NoOut(cheat_id, 65203);
+}
+
+Result dmntchtAddCheat(DmntCheatDefinition *cheat_def, bool enabled, u32 *out_cheat_id) {
+ const u8 in = enabled != 0;
+ return serviceDispatchInOut(&g_dmntchtSrv, 65204, in, *out_cheat_id,
+ .buffer_attrs = { SfBufferAttr_In | SfBufferAttr_HipcMapAlias | SfBufferAttr_FixedSize },
+ .buffers = { { cheat_def, sizeof(*cheat_def) } },
+ );
+}
+
+Result dmntchtRemoveCheat(u32 cheat_id) {
+ return _dmntchtCmdInU32NoOut(cheat_id, 65205);
+}
+
+Result dmntchtGetFrozenAddressCount(u64 *out_count) {
+ return _dmntchtGetCount(65300, out_count);
+}
+
+Result dmntchtGetFrozenAddresses(DmntFrozenAddressEntry *buffer, u64 max_count, u64 offset, u64 *out_count) {
+ return _dmntchtGetEntries(65301, buffer, sizeof(*buffer) * max_count, offset, out_count);
+}
+
+Result dmntchtGetFrozenAddress(DmntFrozenAddressEntry *out, u64 address) {
+ return serviceDispatchInOut(&g_dmntchtSrv, 65302, address, *out);
+}
+
+Result dmntchtEnableFrozenAddress(u64 address, u64 width, u64 *out_value) {
+ const struct {
+ u64 address;
+ u64 width;
+ } in = { address, width };
+ return serviceDispatchInOut(&g_dmntchtSrv, 65303, in, *out_value);
+}
+
+Result dmntchtDisableFrozenAddress(u64 address) {
+ return serviceDispatchIn(&g_dmntchtSrv, 65304, address);
+}
diff --git a/stratosphere/libstratosphere/include/stratosphere/services/dmntcht.h b/stratosphere/libstratosphere/source/dmnt/dmntcht.h
similarity index 96%
rename from stratosphere/libstratosphere/include/stratosphere/services/dmntcht.h
rename to stratosphere/libstratosphere/source/dmnt/dmntcht.h
index 6f8d5ddc2..c1dc6f71a 100644
--- a/stratosphere/libstratosphere/include/stratosphere/services/dmntcht.h
+++ b/stratosphere/libstratosphere/source/dmnt/dmntcht.h
@@ -15,7 +15,9 @@
*/
#pragma once
-#include
+#include
+#include
+#include
#ifdef __cplusplus
extern "C" {
@@ -86,7 +88,6 @@ Result dmntchtGetFrozenAddress(DmntFrozenAddressEntry *out, u64 address);
Result dmntchtEnableFrozenAddress(u64 address, u64 width, u64 *out_value);
Result dmntchtDisableFrozenAddress(u64 address);
-
#ifdef __cplusplus
}
-#endif
\ No newline at end of file
+#endif
diff --git a/stratosphere/libstratosphere/source/dmntcht.c b/stratosphere/libstratosphere/source/dmntcht.c
deleted file mode 100644
index eb6476f0d..000000000
--- a/stratosphere/libstratosphere/source/dmntcht.c
+++ /dev/null
@@ -1,650 +0,0 @@
-/*
- * Copyright (c) 2018-2019 Atmosphère-NX
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#include
-#include
-#include
-
-static Service g_dmntchtService;
-static u64 g_refCnt;
-
-static Result _dmntchtGetCount(u64 cmd_id, u64 *out_count);
-static Result _dmntchtGetEntries(u64 cmd_id, void *buffer, u64 buffer_size, u64 offset, u64 *out_count);
-
-Result dmntchtInitialize(void) {
- atomicIncrement64(&g_refCnt);
-
- if (serviceIsActive(&g_dmntchtService)) {
- return 0;
- }
-
- return smGetService(&g_dmntchtService, "dmnt:cht");
-}
-
-void dmntchtExit(void) {
- if (atomicIncrement64(&g_refCnt) == 0) {
- serviceClose(&g_dmntchtService);
- }
-}
-
-Service* dmntchtGetServiceSession(void) {
- return &g_dmntchtService;
-}
-
-Result dmntchtHasCheatProcess(bool *out) {
- IpcCommand c;
- ipcInitialize(&c);
-
- struct {
- u64 magic;
- u64 cmd_id;
- } *raw;
-
- raw = serviceIpcPrepareHeader(&g_dmntchtService, &c, sizeof(*raw));
-
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65000;
-
- Result rc = serviceIpcDispatch(&g_dmntchtService);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- bool out;
- } *resp;
-
- serviceIpcParse(&g_dmntchtService, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
- if (R_SUCCEEDED(rc)) {
- if (out) *out = resp->out;
- }
- }
-
- return rc;
-}
-
-Result dmntchtGetCheatProcessEvent(Event *event) {
- IpcCommand c;
- ipcInitialize(&c);
-
- struct {
- u64 magic;
- u64 cmd_id;
- } *raw;
-
- raw = serviceIpcPrepareHeader(&g_dmntchtService, &c, sizeof(*raw));
-
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65001;
-
- Result rc = serviceIpcDispatch(&g_dmntchtService);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- } *resp;
-
- serviceIpcParse(&g_dmntchtService, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
-
- if (R_SUCCEEDED(rc)) {
- eventLoadRemote(event, r.Handles[0], true);
- }
- }
-
- return rc;
-}
-
-Result dmntchtGetCheatProcessMetadata(DmntCheatProcessMetadata *out_metadata) {
- IpcCommand c;
- ipcInitialize(&c);
-
- struct {
- u64 magic;
- u64 cmd_id;
- } *raw;
-
- raw = serviceIpcPrepareHeader(&g_dmntchtService, &c, sizeof(*raw));
-
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65002;
-
- Result rc = serviceIpcDispatch(&g_dmntchtService);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- DmntCheatProcessMetadata metadata;
- } *resp;
-
- serviceIpcParse(&g_dmntchtService, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
- if (R_SUCCEEDED(rc)) {
- if (out_metadata) *out_metadata = resp->metadata;
- }
- }
-
- return rc;
-}
-
-Result dmntchtForceOpenCheatProcess(void) {
- IpcCommand c;
- ipcInitialize(&c);
-
- struct {
- u64 magic;
- u64 cmd_id;
- } *raw;
-
- raw = serviceIpcPrepareHeader(&g_dmntchtService, &c, sizeof(*raw));
-
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65003;
-
- Result rc = serviceIpcDispatch(&g_dmntchtService);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- } *resp;
-
- serviceIpcParse(&g_dmntchtService, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
- }
-
- return rc;
-}
-
-static Result _dmntchtGetCount(u64 cmd_id, u64 *out_count) {
- IpcCommand c;
- ipcInitialize(&c);
-
- struct {
- u64 magic;
- u64 cmd_id;
- } *raw;
-
- raw = serviceIpcPrepareHeader(&g_dmntchtService, &c, sizeof(*raw));
-
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = cmd_id;
-
- Result rc = serviceIpcDispatch(&g_dmntchtService);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- u64 count;
- } *resp;
-
- serviceIpcParse(&g_dmntchtService, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
- *out_count = resp->count;
- }
-
- return rc;
-}
-
-static Result _dmntchtGetEntries(u64 cmd_id, void *buffer, u64 buffer_size, u64 offset, u64 *out_count) {
- IpcCommand c;
- ipcInitialize(&c);
- ipcAddRecvBuffer(&c, buffer, buffer_size, 0);
-
- struct {
- u64 magic;
- u64 cmd_id;
- u64 offset;
- } *raw;
-
- raw = serviceIpcPrepareHeader(&g_dmntchtService, &c, sizeof(*raw));
-
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = cmd_id;
- raw->offset = offset;
-
- Result rc = serviceIpcDispatch(&g_dmntchtService);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- u64 count;
- } *resp;
-
- serviceIpcParse(&g_dmntchtService, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
- if (R_SUCCEEDED(rc)) {
- if (out_count) *out_count = resp->count;
- }
- }
-
- return rc;
-}
-
-Result dmntchtGetCheatProcessMappingCount(u64 *out_count) {
- return _dmntchtGetCount(65100, out_count);
-}
-
-Result dmntchtGetCheatProcessMappings(MemoryInfo *buffer, u64 max_count, u64 offset, u64 *out_count) {
- return _dmntchtGetEntries(65101, buffer, sizeof(*buffer) * max_count, offset, out_count);
-}
-
-Result dmntchtReadCheatProcessMemory(u64 address, void *buffer, size_t size) {
- IpcCommand c;
- ipcInitialize(&c);
- ipcAddRecvBuffer(&c, buffer, size, 0);
-
- struct {
- u64 magic;
- u64 cmd_id;
- u64 address;
- u64 size;
- } *raw;
-
- raw = serviceIpcPrepareHeader(&g_dmntchtService, &c, sizeof(*raw));
-
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65102;
- raw->address = address;
- raw->size = size;
-
- Result rc = serviceIpcDispatch(&g_dmntchtService);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- } *resp;
-
- serviceIpcParse(&g_dmntchtService, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
- }
-
- return rc;
-}
-
-Result dmntchtWriteCheatProcessMemory(u64 address, const void *buffer, size_t size) {
- IpcCommand c;
- ipcInitialize(&c);
- ipcAddSendBuffer(&c, buffer, size, 0);
-
- struct {
- u64 magic;
- u64 cmd_id;
- u64 address;
- u64 size;
- } *raw;
-
- raw = serviceIpcPrepareHeader(&g_dmntchtService, &c, sizeof(*raw));
-
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65103;
- raw->address = address;
- raw->size = size;
-
- Result rc = serviceIpcDispatch(&g_dmntchtService);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- } *resp;
-
- serviceIpcParse(&g_dmntchtService, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
- }
-
- return rc;
-}
-
-Result dmntchtQueryCheatProcessMemory(MemoryInfo *mem_info, u64 address){
- IpcCommand c;
- ipcInitialize(&c);
-
- struct {
- u64 magic;
- u64 cmd_id;
- u64 address;
- } *raw;
-
- raw = serviceIpcPrepareHeader(&g_dmntchtService, &c, sizeof(*raw));
-
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65104;
- raw->address = address;
-
- Result rc = serviceIpcDispatch(&g_dmntchtService);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- MemoryInfo mem_info;
- } *resp;
-
- serviceIpcParse(&g_dmntchtService, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
- if (R_SUCCEEDED(rc)) {
- if (mem_info) *mem_info = resp->mem_info;
- }
- }
-
- return rc;
-}
-
-Result dmntchtGetCheatCount(u64 *out_count) {
- return _dmntchtGetCount(65200, out_count);
-}
-
-Result dmntchtGetCheats(DmntCheatEntry *buffer, u64 max_count, u64 offset, u64 *out_count) {
- return _dmntchtGetEntries(65201, buffer, sizeof(*buffer) * max_count, offset, out_count);
-}
-
-Result dmntchtGetCheatById(DmntCheatEntry *buffer, u32 cheat_id) {
- IpcCommand c;
- ipcInitialize(&c);
- ipcAddRecvBuffer(&c, buffer, sizeof(*buffer), 0);
-
- struct {
- u64 magic;
- u64 cmd_id;
- u32 cheat_id;
- } *raw;
-
- raw = serviceIpcPrepareHeader(&g_dmntchtService, &c, sizeof(*raw));
-
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65202;
- raw->cheat_id = cheat_id;
-
- Result rc = serviceIpcDispatch(&g_dmntchtService);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- } *resp;
-
- serviceIpcParse(&g_dmntchtService, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
- }
-
- return rc;
-}
-
-Result dmntchtToggleCheat(u32 cheat_id) {
- IpcCommand c;
- ipcInitialize(&c);
-
- struct {
- u64 magic;
- u64 cmd_id;
- u32 cheat_id;
- } *raw;
-
- raw = serviceIpcPrepareHeader(&g_dmntchtService, &c, sizeof(*raw));
-
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65203;
- raw->cheat_id = cheat_id;
-
- Result rc = serviceIpcDispatch(&g_dmntchtService);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- } *resp;
-
- serviceIpcParse(&g_dmntchtService, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
- }
-
- return rc;
-}
-
-Result dmntchtAddCheat(DmntCheatDefinition *buffer, bool enabled, u32 *out_cheat_id) {
- IpcCommand c;
- ipcInitialize(&c);
- ipcAddSendBuffer(&c, buffer, sizeof(*buffer), 0);
-
- struct {
- u64 magic;
- u64 cmd_id;
- u8 enabled;
- } *raw;
-
- raw = serviceIpcPrepareHeader(&g_dmntchtService, &c, sizeof(*raw));
-
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65204;
- raw->enabled = enabled;
-
- Result rc = serviceIpcDispatch(&g_dmntchtService);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- u32 cheat_id;
- } *resp;
-
- serviceIpcParse(&g_dmntchtService, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
- if (R_SUCCEEDED(rc)) {
- if (out_cheat_id) *out_cheat_id = resp->cheat_id;
- }
- }
-
- return rc;
-}
-
-Result dmntchtRemoveCheat(u32 cheat_id) {
- IpcCommand c;
- ipcInitialize(&c);
-
- struct {
- u64 magic;
- u64 cmd_id;
- u32 cheat_id;
- } *raw;
-
- raw = serviceIpcPrepareHeader(&g_dmntchtService, &c, sizeof(*raw));
-
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65205;
- raw->cheat_id = cheat_id;
-
- Result rc = serviceIpcDispatch(&g_dmntchtService);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- } *resp;
-
- serviceIpcParse(&g_dmntchtService, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
- }
-
- return rc;
-}
-
-
-Result dmntchtGetFrozenAddressCount(u64 *out_count) {
- return _dmntchtGetCount(65300, out_count);
-}
-
-Result dmntchtGetFrozenAddresses(DmntFrozenAddressEntry *buffer, u64 max_count, u64 offset, u64 *out_count) {
- return _dmntchtGetEntries(65301, buffer, sizeof(*buffer) * max_count, offset, out_count);
-}
-
-Result dmntchtGetFrozenAddress(DmntFrozenAddressEntry *out, u64 address) {
- IpcCommand c;
- ipcInitialize(&c);
-
- struct {
- u64 magic;
- u64 cmd_id;
- u64 address;
- } *raw;
-
- raw = serviceIpcPrepareHeader(&g_dmntchtService, &c, sizeof(*raw));
-
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65302;
- raw->address = address;
-
- Result rc = serviceIpcDispatch(&g_dmntchtService);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- DmntFrozenAddressEntry entry;
- } *resp;
-
- serviceIpcParse(&g_dmntchtService, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
- if (R_SUCCEEDED(rc)) {
- if (out) *out = resp->entry;
- }
- }
-
- return rc;
-}
-
-Result dmntchtEnableFrozenAddress(u64 address, u64 width, u64 *out_value) {
- IpcCommand c;
- ipcInitialize(&c);
-
- struct {
- u64 magic;
- u64 cmd_id;
- u64 address;
- u64 width;
- } *raw;
-
- raw = serviceIpcPrepareHeader(&g_dmntchtService, &c, sizeof(*raw));
-
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65303;
- raw->address = address;
- raw->width = width;
-
- Result rc = serviceIpcDispatch(&g_dmntchtService);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- u64 value;
- } *resp;
-
- serviceIpcParse(&g_dmntchtService, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
- if (R_SUCCEEDED(rc)) {
- if (out_value) *out_value = resp->value;
- }
- }
-
- return rc;
-}
-
-Result dmntchtDisableFrozenAddress(u64 address) {
- IpcCommand c;
- ipcInitialize(&c);
-
- struct {
- u64 magic;
- u64 cmd_id;
- u64 address;
- } *raw;
-
- raw = serviceIpcPrepareHeader(&g_dmntchtService, &c, sizeof(*raw));
-
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65304;
- raw->address = address;
-
- Result rc = serviceIpcDispatch(&g_dmntchtService);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- u64 value;
- } *resp;
-
- serviceIpcParse(&g_dmntchtService, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
- }
-
- return rc;
-}
diff --git a/stratosphere/libstratosphere/source/emummc_utilities.cpp b/stratosphere/libstratosphere/source/emummc_utilities.cpp
deleted file mode 100644
index 59c4267cd..000000000
--- a/stratosphere/libstratosphere/source/emummc_utilities.cpp
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (c) 2018-2019 Atmosphère-NX
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#include
-#include
-
-/* EFS0 */
-static constexpr u32 EmummcStorageMagic = 0x30534645;
-static constexpr size_t EmummcMaxDirLength = 0x7F;
-
-struct EmummcBaseConfig {
- u32 magic;
- u32 type;
- u32 id;
- u32 fs_version;
-};
-
-struct EmummcPartitionConfig {
- u64 start_sector;
-};
-
-struct EmummcFileConfig {
- char path[EmummcMaxDirLength+1];
-};
-
-struct ExoEmummcConfig {
- EmummcBaseConfig base_cfg;
- union {
- EmummcPartitionConfig partition_cfg;
- EmummcFileConfig file_cfg;
- };
- char emu_dir_path[EmummcMaxDirLength+1];
-};
-
-enum EmummcType {
- EmummcType_Emmc = 0,
- EmummcType_Sd,
- EmummcType_SdFile,
-
- EmummcType_Max,
-};
-
-static bool g_IsEmummc = false;
-static bool g_HasCached = false;
-static Mutex g_Mutex;
-static ExoEmummcConfig g_exo_emummc_config;
-
-static void _CacheValues(void)
-{
- if (__atomic_load_n(&g_HasCached, __ATOMIC_SEQ_CST))
- return;
-
- mutexLock(&g_Mutex);
-
- if (g_HasCached) {
- mutexUnlock(&g_Mutex);
- return;
- }
-
- static struct {
- char file_path[EmummcMaxDirLength+1];
- char nintendo_path[EmummcMaxDirLength+1];
- } __attribute__((aligned(0x1000))) paths;
-
- {
- SecmonArgs args = {0};
- args.X[0] = 0xF0000404; /* smcAmsGetEmunandConfig */
- args.X[1] = 0; /* NAND */
- args.X[2] = reinterpret_cast(&paths); /* path output */
- R_ASSERT(svcCallSecureMonitor(&args));
- STS_ASSERT(args.X[0] == 0);
- std::memcpy(&g_exo_emummc_config, &args.X[1], sizeof(args) - sizeof(args.X[0]));
- }
-
- const EmummcType emummc_type = static_cast(g_exo_emummc_config.base_cfg.type);
-
-/* Ignore format warnings. */
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wformat-truncation"
- switch (emummc_type) {
- case EmummcType_SdFile:
- std::snprintf(g_exo_emummc_config.file_cfg.path, sizeof(g_exo_emummc_config.file_cfg.path), "/%s", paths.file_path);
- break;
- default:
- break;
- }
-
- std::snprintf(g_exo_emummc_config.emu_dir_path, sizeof(g_exo_emummc_config.emu_dir_path), "/%s", paths.nintendo_path);
-
- g_IsEmummc = g_exo_emummc_config.base_cfg.magic == EmummcStorageMagic && emummc_type != EmummcType_Emmc;
-
- /* Default Nintendo redirection path. */
- if (g_IsEmummc) {
- if (std::strcmp(g_exo_emummc_config.emu_dir_path, "/") == 0) {
- std::snprintf(g_exo_emummc_config.emu_dir_path, sizeof(g_exo_emummc_config.emu_dir_path), "/emummc/Nintendo_%04x", g_exo_emummc_config.base_cfg.id);
- }
- }
-#pragma GCC diagnostic pop
-
- __atomic_store_n(&g_HasCached, true, __ATOMIC_SEQ_CST);
-
- mutexUnlock(&g_Mutex);
-}
-
-
-/* Get whether emummc is active. */
-bool IsEmummc() {
- _CacheValues();
- return g_IsEmummc;
-}
-
-/* Get Nintendo redirection path. */
-const char *GetEmummcNintendoDirPath() {
- _CacheValues();
- if (!g_IsEmummc) {
- return nullptr;
- }
- return g_exo_emummc_config.emu_dir_path;
-}
-
-/* Get Emummc folderpath, NULL if not file-based. */
-const char *GetEmummcFilePath() {
- _CacheValues();
- if (!g_IsEmummc || g_exo_emummc_config.base_cfg.type != EmummcType_SdFile) {
- return nullptr;
- }
- return g_exo_emummc_config.file_cfg.path;
-}
diff --git a/stratosphere/libstratosphere/source/ldr/ldr_ams.c b/stratosphere/libstratosphere/source/ldr/ldr_ams.c
index 94c042e12..59ec13245 100644
--- a/stratosphere/libstratosphere/source/ldr/ldr_ams.c
+++ b/stratosphere/libstratosphere/source/ldr/ldr_ams.c
@@ -18,44 +18,9 @@
#include "ldr_ams.h"
static Result _ldrAtmosphereHasLaunchedTitle(Service *srv, bool *out, u64 tid) {
- IpcCommand c;
- ipcInitialize(&c);
-
- struct {
- u64 magic;
- u64 cmd_id;
- u64 title_id;
- } *raw;
-
- raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65000;
- raw->title_id = tid;
-
- Result rc = serviceIpcDispatch(srv);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- u8 has_launched_title;
- } *resp;
-
- serviceIpcParse(srv, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
-
- if (R_SUCCEEDED(rc)) {
- *out = resp->has_launched_title != 0;
- } else {
- rc = 0x666;
- }
- } else {
- rc = 0x555;
- }
-
+ u8 tmp;
+ Result rc = serviceDispatchInOut(srv, 65000, tid, tmp);
+ if (R_SUCCEEDED(rc) && out) *out = tmp & 1;
return rc;
}
diff --git a/stratosphere/libstratosphere/source/on_crash.cpp b/stratosphere/libstratosphere/source/on_crash.cpp
deleted file mode 100644
index 2621a51a4..000000000
--- a/stratosphere/libstratosphere/source/on_crash.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (c) 2018-2019 Atmosphère-NX
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#include
-#include
-#include
-
-WEAK sts::ncm::TitleId __stratosphere_title_id = sts::ncm::TitleId::Invalid;
-
-extern "C" {
- void WEAK __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx);
-
- /* Redefine abort, so that it triggers these handlers. */
- void abort();
-};
-
-static inline u64 GetPc() {
- u64 pc;
- __asm__ __volatile__ ("adr %[pc], ." : [pc]"=&r"(pc) :: );
- return pc;
-}
-
-struct StackFrame {
- u64 fp;
- u64 lr;
-};
-
-void StratosphereCrashHandler(ThreadExceptionDump *ctx) {
- AtmosphereFatalErrorContext ams_ctx;
- /* Convert thread dump to atmosphere dump. */
- {
- ams_ctx.magic = AtmosphereFatalErrorMagic;
- ams_ctx.error_desc = ctx->error_desc;
- ams_ctx.title_id = static_cast(__stratosphere_title_id);
- for (size_t i = 0; i < AtmosphereFatalErrorNumGprs; i++) {
- ams_ctx.gprs[i] = ctx->cpu_gprs[i].x;
- }
- if (ams_ctx.error_desc == DATA_ABORT_ERROR_DESC &&
- ams_ctx.gprs[2] == STD_ABORT_ADDR_MAGIC &&
- ams_ctx.gprs[3] == STD_ABORT_VALUE_MAGIC) {
- /* Detect std::abort(). */
- ams_ctx.error_desc = STD_ABORT_ERROR_DESC;
- }
-
- ams_ctx.fp = ctx->fp.x;
- ams_ctx.lr = ctx->lr.x;
- ams_ctx.sp = ctx->sp.x;
- ams_ctx.pc = ctx->pc.x;
- ams_ctx.pstate = ctx->pstate;
- ams_ctx.afsr0 = ctx->afsr0;
- ams_ctx.afsr1 = ctx->afsr1;
- ams_ctx.far = ctx->far.x;
- ams_ctx.report_identifier = armGetSystemTick();
- /* Grab module base. */
- {
- MemoryInfo mem_info;
- u32 page_info;
- if (R_SUCCEEDED(svcQueryMemory(&mem_info, &page_info, GetPc()))) {
- ams_ctx.module_base = mem_info.addr;
- } else {
- ams_ctx.module_base = 0;
- }
- }
- ams_ctx.stack_trace_size = 0;
- u64 cur_fp = ams_ctx.fp;
- for (size_t i = 0; i < AMS_FATAL_ERROR_MAX_STACKTRACE; i++) {
- /* Validate current frame. */
- if (cur_fp == 0 || (cur_fp & 0xF)) {
- break;
- }
-
- /* Read a new frame. */
- StackFrame cur_frame;
- MemoryInfo mem_info;
- u32 page_info;
- if (R_SUCCEEDED(svcQueryMemory(&mem_info, &page_info, cur_fp)) && (mem_info.perm & Perm_R) == Perm_R) {
- std::memcpy(&cur_frame, reinterpret_cast(cur_fp), sizeof(cur_frame));
- } else {
- break;
- }
-
- /* Advance to the next frame. */
- ams_ctx.stack_trace[ams_ctx.stack_trace_size++] = cur_frame.lr;
- cur_fp = cur_frame.fp;
- }
- /* Clear unused parts of stack trace. */
- for (size_t i = ams_ctx.stack_trace_size; i < AMS_FATAL_ERROR_MAX_STACKTRACE; i++) {
- ams_ctx.stack_trace[i] = 0;
- }
-
- /* Grab up to 0x100 of stack. */
- {
- MemoryInfo mem_info;
- u32 page_info;
- if (R_SUCCEEDED(svcQueryMemory(&mem_info, &page_info, ams_ctx.sp)) && (mem_info.perm & Perm_R) == Perm_R) {
- size_t copy_size = std::min(static_cast(AMS_FATAL_ERROR_MAX_STACKDUMP), static_cast(mem_info.addr + mem_info.size - ams_ctx.sp));
- ams_ctx.stack_dump_size = copy_size;
- std::memcpy(ams_ctx.stack_dump, reinterpret_cast(ams_ctx.sp), copy_size);
- } else {
- ams_ctx.stack_dump_size = 0;
- }
- }
- }
-
- /* Just call the user exception handler. */
- __libstratosphere_exception_handler(&ams_ctx);
-}
-
-/* Default exception handler behavior. */
-void WEAK __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx) {
- R_ASSERT(bpcAmsInitialize());
- R_ASSERT(bpcAmsRebootToFatalError(ctx));
- bpcAmsExit();
- while (1) { }
-}
-
-/* Custom abort handler, so that std::abort will trigger these. */
-void abort() {
- /* Just perform a data abort. */
- register u64 addr __asm__("x2") = STD_ABORT_ADDR_MAGIC;
- register u64 val __asm__("x3") = STD_ABORT_VALUE_MAGIC;
- while (true) {
- __asm__ __volatile__ (
- "str %[val], [%[addr]]"
- :
- : [val]"r"(val), [addr]"r"(addr)
- );
- }
-}
\ No newline at end of file
diff --git a/stratosphere/libstratosphere/source/pm/pm_ams.c b/stratosphere/libstratosphere/source/pm/pm_ams.c
index 2e1c19886..aeb6bf1cc 100644
--- a/stratosphere/libstratosphere/source/pm/pm_ams.c
+++ b/stratosphere/libstratosphere/source/pm/pm_ams.c
@@ -18,124 +18,35 @@
#include "pm_ams.h"
Result pminfoAtmosphereGetProcessId(u64 *out_pid, u64 tid) {
- IpcCommand c;
- ipcInitialize(&c);
- Service *srv = pminfoGetServiceSession();
-
- struct {
- u64 magic;
- u64 cmd_id;
- u64 title_id;
- } *raw;
-
- raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65000;
- raw->title_id = tid;
-
- Result rc = serviceIpcDispatch(srv);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- u64 pid;
- } *resp;
-
- serviceIpcParse(srv, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
-
- if (R_SUCCEEDED(rc)) {
- *out_pid = resp->pid;
- }
- }
-
- return rc;
+ return serviceDispatchInOut(pminfoGetServiceSession(), 65000, tid, *out_pid);
}
Result pminfoAtmosphereHasLaunchedTitle(bool *out, u64 tid) {
- IpcCommand c;
- ipcInitialize(&c);
- Service *srv = pminfoGetServiceSession();
-
- struct {
- u64 magic;
- u64 cmd_id;
- u64 title_id;
- } *raw;
-
- raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65001;
- raw->title_id = tid;
-
- Result rc = serviceIpcDispatch(srv);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- u8 has_launched_title;
- } *resp;
-
- serviceIpcParse(srv, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
-
- if (R_SUCCEEDED(rc)) {
- *out = resp->has_launched_title != 0;
- }
- }
-
+ u8 tmp;
+ Result rc = serviceDispatchInOut(pminfoGetServiceSession(), 65001, tid, tmp);
+ if (R_SUCCEEDED(rc) && out) *out = tmp & 1;
return rc;
}
-Result pmdmntAtmosphereGetProcessInfo(Handle* out, u64 *tid_out, u8 *sid_out, u64 pid) {
- IpcCommand c;
- ipcInitialize(&c);
- Service *s = pmdmntGetServiceSession();
-
+Result pmdmntAtmosphereGetProcessInfo(Handle* handle_out, u64 *tid_out, u8 *sid_out, u64 pid) {
struct {
- u64 magic;
- u64 cmd_id;
- u64 pid;
- } *raw;
+ u64 title_id;
+ u8 storage_id;
+ } out;
+ Handle tmp_handle;
- raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw));
-
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65000;
- raw->pid = pid;
-
- Result rc = serviceIpcDispatch(s);
+ Result rc = serviceDispatchInOut(pmdmntGetServiceSession(), 65000, pid, out,
+ .out_handle_attrs = { SfOutHandleAttr_HipcCopy },
+ .out_handles = &tmp_handle,
+ );
if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- u64 title_id;
- FsStorageId storage_id;
- } *resp;
-
- serviceIpcParse(s, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
-
- if (R_SUCCEEDED(rc)) {
- if (out) {
- *out = r.Handles[0];
- } else {
- svcCloseHandle(r.Handles[0]);
- }
- if (tid_out) *tid_out = resp->title_id;
- if (sid_out) *sid_out = resp->storage_id;
+ if (tid_out) *tid_out = out.title_id;
+ if (sid_out) *sid_out = out.storage_id;
+ if (handle_out) {
+ *handle_out = tmp_handle;
+ } else {
+ svcCloseHandle(tmp_handle);
}
}
@@ -143,44 +54,20 @@ Result pmdmntAtmosphereGetProcessInfo(Handle* out, u64 *tid_out, u8 *sid_out, u6
}
Result pmdmntAtmosphereGetCurrentLimitInfo(u64 *out_cur, u64 *out_lim, u32 group, u32 resource) {
- IpcCommand c;
- ipcInitialize(&c);
- Service *s = pmdmntGetServiceSession();
-
- struct {
- u64 magic;
- u64 cmd_id;
+ const struct {
u32 group;
u32 resource;
- } *raw;
+ } in = { group, resource };
+ struct {
+ u64 cur;
+ u64 lim;
+ } out;
- raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw));
-
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65001;
- raw->group = group;
- raw->resource = resource;
-
- Result rc = serviceIpcDispatch(s);
+ Result rc = serviceDispatchInOut(pmdmntGetServiceSession(), 65001, in, out);
if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- u64 cur_value;
- u64 lim_value;
- } *resp;
-
- serviceIpcParse(s, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
-
- if (R_SUCCEEDED(rc)) {
- if (out_cur) *out_cur = resp->cur_value;
- if (out_lim) *out_lim = resp->lim_value;
- }
+ if (out_cur) *out_cur = out.cur;
+ if (out_lim) *out_lim = out.lim;
}
return rc;
diff --git a/stratosphere/libstratosphere/source/service_guard.h b/stratosphere/libstratosphere/source/service_guard.h
new file mode 100644
index 000000000..588a0c995
--- /dev/null
+++ b/stratosphere/libstratosphere/source/service_guard.h
@@ -0,0 +1,64 @@
+#pragma once
+#include
+#include
+#include
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct ServiceGuard {
+ Mutex mutex;
+ u32 refCount;
+} ServiceGuard;
+
+NX_INLINE bool serviceGuardBeginInit(ServiceGuard* g)
+{
+ mutexLock(&g->mutex);
+ return (g->refCount++) == 0;
+}
+
+NX_INLINE Result serviceGuardEndInit(ServiceGuard* g, Result rc, void (*cleanupFunc)(void))
+{
+ if (R_FAILED(rc)) {
+ cleanupFunc();
+ --g->refCount;
+ }
+ mutexUnlock(&g->mutex);
+ return rc;
+}
+
+NX_INLINE void serviceGuardExit(ServiceGuard* g, void (*cleanupFunc)(void))
+{
+ mutexLock(&g->mutex);
+ if (g->refCount && (--g->refCount) == 0)
+ cleanupFunc();
+ mutexUnlock(&g->mutex);
+}
+
+#define NX_GENERATE_SERVICE_GUARD_PARAMS(name, _paramdecl, _parampass) \
+\
+static ServiceGuard g_##name##Guard; \
+NX_INLINE Result _##name##Initialize _paramdecl; \
+static void _##name##Cleanup(void); \
+\
+Result name##Initialize _paramdecl \
+{ \
+ Result rc = 0; \
+ if (serviceGuardBeginInit(&g_##name##Guard)) \
+ rc = _##name##Initialize _parampass; \
+ return serviceGuardEndInit(&g_##name##Guard, rc, _##name##Cleanup); \
+} \
+\
+void name##Exit(void) \
+{ \
+ serviceGuardExit(&g_##name##Guard, _##name##Cleanup); \
+}
+
+#define NX_GENERATE_SERVICE_GUARD(name) NX_GENERATE_SERVICE_GUARD_PARAMS(name, (void), ())
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/stratosphere/libstratosphere/source/sm/sm_ams.c b/stratosphere/libstratosphere/source/sm/sm_ams.c
index 628ff2fb8..b345e42a6 100644
--- a/stratosphere/libstratosphere/source/sm/sm_ams.c
+++ b/stratosphere/libstratosphere/source/sm/sm_ams.c
@@ -13,166 +13,42 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-
-#include
-#include
+#define NX_SERVICE_ASSUME_NON_DOMAIN
+#include "../service_guard.h"
#include "sm_ams.h"
-static Service g_smMitmSrv;
-static u64 g_mitmRefCnt;
+static Result _smAtmosphereCmdHas(bool *out, u64 service_name, u32 cmd_id) {
+ u8 tmp;
+ Result rc = serviceDispatchInOut(smGetServiceSession(), cmd_id, service_name, tmp);
+ if (R_SUCCEEDED(rc) && out) *out = tmp & 1;
+ return rc;
+}
+
+static Result _smAtmosphereCmdInServiceNameNoOut(u64 service_name, Service *srv, u32 cmd_id) {
+ return serviceDispatchIn(srv, cmd_id, service_name);
+}
Result smAtmosphereHasService(bool *out, const char *name) {
- IpcCommand c;
- ipcInitialize(&c);
- Service *srv = smGetServiceSession();
-
- struct {
- u64 magic;
- u64 cmd_id;
- u64 service_name;
- } *raw;
-
- raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65100;
- raw->service_name = smEncodeName(name);
-
- Result rc = serviceIpcDispatch(srv);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- u8 has_service;
- } *resp;
-
- serviceIpcParse(srv, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
-
- if (R_SUCCEEDED(rc)) {
- *out = resp->has_service != 0;
- }
- }
-
- return rc;
+ return _smAtmosphereCmdHas(out, smEncodeName(name), 65100);
}
Result smAtmosphereWaitService(const char *name) {
- IpcCommand c;
- ipcInitialize(&c);
- Service *srv = smGetServiceSession();
-
- struct {
- u64 magic;
- u64 cmd_id;
- u64 service_name;
- } *raw;
-
- raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65101;
- raw->service_name = smEncodeName(name);
-
- Result rc = serviceIpcDispatch(srv);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- } *resp;
-
- serviceIpcParse(srv, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
- }
-
- return rc;
+ return _smAtmosphereCmdInServiceNameNoOut(smEncodeName(name), smGetServiceSession(), 65101);
}
Result smAtmosphereHasMitm(bool *out, const char *name) {
- IpcCommand c;
- ipcInitialize(&c);
- Service *srv = smGetServiceSession();
-
- struct {
- u64 magic;
- u64 cmd_id;
- u64 service_name;
- } *raw;
-
- raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65004;
- raw->service_name = smEncodeName(name);
-
- Result rc = serviceIpcDispatch(srv);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- u8 has_mitm;
- } *resp;
-
- serviceIpcParse(srv, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
-
- if (R_SUCCEEDED(rc)) {
- *out = resp->has_mitm != 0;
- }
- }
-
- return rc;
+ return _smAtmosphereCmdHas(out, smEncodeName(name), 65004);
}
Result smAtmosphereWaitMitm(const char *name) {
- IpcCommand c;
- ipcInitialize(&c);
- Service *srv = smGetServiceSession();
-
- struct {
- u64 magic;
- u64 cmd_id;
- u64 service_name;
- } *raw;
-
- raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65005;
- raw->service_name = smEncodeName(name);
-
- Result rc = serviceIpcDispatch(srv);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- } *resp;
-
- serviceIpcParse(srv, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
- }
-
- return rc;
+ return _smAtmosphereCmdInServiceNameNoOut(smEncodeName(name), smGetServiceSession(), 65005);
}
-Result smAtmosphereMitmInitialize(void) {
- atomicIncrement64(&g_mitmRefCnt);
+static Service g_smAtmosphereMitmSrv;
- if (serviceIsActive(&g_smMitmSrv))
- return 0;
+NX_GENERATE_SERVICE_GUARD(smAtmosphereMitm);
+Result _smAtmosphereMitmInitialize(void) {
Handle sm_handle;
Result rc = svcConnectToNamedPort(&sm_handle, "sm:");
while (R_VALUE(rc) == KERNELRESULT(NotFound)) {
@@ -181,195 +57,64 @@ Result smAtmosphereMitmInitialize(void) {
}
if (R_SUCCEEDED(rc)) {
- serviceCreate(&g_smMitmSrv, sm_handle);
+ serviceCreate(&g_smAtmosphereMitmSrv, sm_handle);
}
if (R_SUCCEEDED(rc)) {
- IpcCommand c;
- ipcInitialize(&c);
- ipcSendPid(&c);
-
- struct {
- u64 magic;
- u64 cmd_id;
- u64 zero;
- u64 reserved[2];
- } *raw;
-
- raw = serviceIpcPrepareHeader(&g_smMitmSrv, &c, sizeof(*raw));
-
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 0;
- raw->zero = 0;
-
- rc = serviceIpcDispatch(&g_smMitmSrv);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
-
- struct {
- u64 magic;
- u64 result;
- } *resp;
- serviceIpcParse(&g_smMitmSrv, &r, sizeof(*resp));
-
- resp = r.Raw;
- rc = resp->result;
- }
+ const u64 pid_placeholder = 0;
+ rc = serviceDispatchIn(&g_smAtmosphereMitmSrv, 0, pid_placeholder, .in_send_pid = true);
}
- if (R_FAILED(rc))
- smAtmosphereMitmExit();
-
return rc;
}
-void smAtmosphereMitmExit(void) {
- if (atomicDecrement64(&g_mitmRefCnt) == 0) {
- serviceClose(&g_smMitmSrv);
- }
+void _smAtmosphereMitmCleanup(void) {
+ serviceClose(&g_smAtmosphereMitmSrv);
+}
+
+Service* smAtmosphereMitmGetServiceSession(void) {
+ return &g_smAtmosphereMitmSrv;
}
Result smAtmosphereMitmInstall(Handle *handle_out, Handle *query_out, const char *name) {
- IpcCommand c;
- ipcInitialize(&c);
- Service *srv = &g_smMitmSrv;
-
- struct {
- u64 magic;
- u64 cmd_id;
- u64 service_name;
- } *raw;
-
- raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65000;
- raw->service_name = smEncodeName(name);
-
- Result rc = serviceIpcDispatch(srv);
+ const u64 in = smEncodeName(name);
+ Handle tmp_handles[2];
+ Result rc = serviceDispatchIn(&g_smAtmosphereMitmSrv, 65000, in,
+ .out_handle_attrs = { SfOutHandleAttr_HipcMove, SfOutHandleAttr_HipcMove },
+ .out_handles = tmp_handles,
+ );
if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- } *resp;
-
- serviceIpcParse(srv, &r, sizeof(*resp));
- resp = r.Raw;
- rc = resp->result;
-
- if (R_SUCCEEDED(rc)) {
- *handle_out = r.Handles[0];
- *query_out = r.Handles[1];
- }
+ *handle_out = tmp_handles[0];
+ *query_out = tmp_handles[1];
}
return rc;
}
Result smAtmosphereMitmUninstall(const char *name) {
- IpcCommand c;
- ipcInitialize(&c);
- Service *srv = &g_smMitmSrv;
-
- struct {
- u64 magic;
- u64 cmd_id;
- u64 service_name;
- } *raw;
-
- raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65001;
- raw->service_name = smEncodeName(name);
-
- Result rc = serviceIpcDispatch(srv);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- } *resp;
-
- serviceIpcParse(srv, &r, sizeof(*resp));
- resp = r.Raw;
- rc = resp->result;
- }
-
- return rc;
+ return _smAtmosphereCmdInServiceNameNoOut(smEncodeName(name), &g_smAtmosphereMitmSrv, 65001);
}
Result smAtmosphereMitmDeclareFuture(const char *name) {
- IpcCommand c;
- ipcInitialize(&c);
- Service *srv = &g_smMitmSrv;
-
- struct {
- u64 magic;
- u64 cmd_id;
- u64 service_name;
- } *raw;
-
- raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65006;
- raw->service_name = smEncodeName(name);
-
- Result rc = serviceIpcDispatch(srv);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- } *resp;
-
- serviceIpcParse(srv, &r, sizeof(*resp));
- resp = r.Raw;
- rc = resp->result;
- }
-
- return rc;
+ return _smAtmosphereCmdInServiceNameNoOut(smEncodeName(name), &g_smAtmosphereMitmSrv, 65006);
}
Result smAtmosphereMitmAcknowledgeSession(Service *srv_out, u64 *pid_out, u64 *tid_out, const char *name) {
- IpcCommand c;
- ipcInitialize(&c);
- Service *srv = &g_smMitmSrv;
-
+ const u64 in = smEncodeName(name);
struct {
- u64 magic;
- u64 cmd_id;
- u64 service_name;
- } *raw;
+ u64 pid;
+ u64 tid;
+ } out;
- raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65003;
- raw->service_name = smEncodeName(name);
-
- Result rc = serviceIpcDispatch(srv);
+ Result rc = serviceDispatchInOut(&g_smAtmosphereMitmSrv, 65003, in, out,
+ .out_num_objects = 1,
+ .out_objects = srv_out,
+ );
if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- u64 pid;
- u64 tid;
- } *resp;
-
- serviceIpcParse(srv, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
- if (R_SUCCEEDED(rc)) {
- *pid_out = resp->pid;
- *tid_out = resp->tid;
- serviceCreate(srv_out, r.Handles[0]);
- }
+ if (pid_out) *pid_out = out.pid;
+ if (tid_out) *tid_out = out.tid;
}
return rc;
diff --git a/stratosphere/libstratosphere/source/sm/sm_ams.h b/stratosphere/libstratosphere/source/sm/sm_ams.h
index 67c9b8894..7ab27f64a 100644
--- a/stratosphere/libstratosphere/source/sm/sm_ams.h
+++ b/stratosphere/libstratosphere/source/sm/sm_ams.h
@@ -5,7 +5,9 @@
* @copyright libnx Authors
*/
#pragma once
-#include
+#include
+#include
+#include
#ifdef __cplusplus
extern "C" {
@@ -18,6 +20,7 @@ Result smAtmosphereWaitMitm(const char *name);
Result smAtmosphereMitmInitialize(void);
void smAtmosphereMitmExit(void);
+Service *smAtmosphereMitmGetServiceSession();
Result smAtmosphereMitmInstall(Handle *handle_out, Handle *query_out, const char *name);
Result smAtmosphereMitmUninstall(const char *name);
diff --git a/stratosphere/libstratosphere/source/sm/sm_api.cpp b/stratosphere/libstratosphere/source/sm/sm_api.cpp
index a6b2be97a..c12806e36 100644
--- a/stratosphere/libstratosphere/source/sm/sm_api.cpp
+++ b/stratosphere/libstratosphere/source/sm/sm_api.cpp
@@ -55,4 +55,15 @@ namespace sts::sm {
});
}
+ namespace impl {
+
+ void DoWithSessionImpl(void (*Invoker)(void *), void *Function) {
+ impl::DoWithUserSession([&]() {
+ Invoker(Function);
+ return ResultSuccess;
+ });
+ }
+
+ }
+
}
diff --git a/stratosphere/libstratosphere/source/sm/smm_ams.c b/stratosphere/libstratosphere/source/sm/smm_ams.c
index f5ea65172..e9a1995eb 100644
--- a/stratosphere/libstratosphere/source/sm/smm_ams.c
+++ b/stratosphere/libstratosphere/source/sm/smm_ams.c
@@ -13,117 +13,36 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-
-#include
#include "smm_ams.h"
Result smManagerAtmosphereEndInitialDefers(void) {
- IpcCommand c;
- ipcInitialize(&c);
- Service *srv = smManagerGetServiceSession();
-
- struct {
- u64 magic;
- u64 cmd_id;
- } *raw;
-
- raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65000;
-
-
- Result rc = serviceIpcDispatch(srv);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- } *resp;
-
- serviceIpcParse(srv, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
- }
-
- return rc;
-
+ return serviceDispatch(smManagerGetServiceSession(), 65000);
}
Result smManagerAtmosphereRegisterProcess(u64 pid, u64 tid, const void *acid_sac, size_t acid_sac_size, const void *aci_sac, size_t aci_sac_size) {
- IpcCommand c;
- ipcInitialize(&c);
- ipcAddSendBuffer(&c, acid_sac, acid_sac_size, BufferType_Normal);
- ipcAddSendBuffer(&c, aci_sac, aci_sac_size, BufferType_Normal);
- Service *srv = smManagerGetServiceSession();
-
- struct {
- u64 magic;
- u64 cmd_id;
+ const struct {
u64 pid;
u64 tid;
- } *raw;
-
- raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65002;
- raw->pid = pid;
- raw->tid = tid;
-
- Result rc = serviceIpcDispatch(srv);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- } *resp;
-
- serviceIpcParse(srv, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
- }
+ } in = { pid, tid };
+ return serviceDispatchIn(smManagerGetServiceSession(), 65002, in,
+ .buffer_attrs = {
+ SfBufferAttr_In | SfBufferAttr_HipcMapAlias,
+ SfBufferAttr_In | SfBufferAttr_HipcMapAlias,
+ },
+ .buffers = {
+ { acid_sac, acid_sac_size },
+ { aci_sac, aci_sac_size },
+ },
+ );
+}
+static Result _smManagerAtmosphereCmdHas(bool *out, u64 service_name, u32 cmd_id) {
+ u8 tmp;
+ Result rc = serviceDispatchInOut(smManagerGetServiceSession(), cmd_id, service_name, tmp);
+ if (R_SUCCEEDED(rc) && out) *out = tmp & 1;
return rc;
}
Result smManagerAtmosphereHasMitm(bool *out, const char* name) {
- IpcCommand c;
- ipcInitialize(&c);
- Service *srv = smManagerGetServiceSession();
-
- struct {
- u64 magic;
- u64 cmd_id;
- u64 service_name;
- } *raw;
-
- raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
- raw->magic = SFCI_MAGIC;
- raw->cmd_id = 65001;
- raw->service_name = smEncodeName(name);
-
- Result rc = serviceIpcDispatch(srv);
-
- if (R_SUCCEEDED(rc)) {
- IpcParsedCommand r;
- struct {
- u64 magic;
- u64 result;
- u8 has_mitm;
- } *resp;
-
- serviceIpcParse(srv, &r, sizeof(*resp));
- resp = r.Raw;
-
- rc = resp->result;
-
- if (R_SUCCEEDED(rc)) {
- *out = resp->has_mitm != 0;
- }
- }
-
- return rc;
+ return _smManagerAtmosphereCmdHas(out, smEncodeName(name), 65001);
}
diff --git a/stratosphere/libstratosphere/source/spl/smc/spl_smc.cpp b/stratosphere/libstratosphere/source/spl/smc/spl_smc.cpp
index 89e35067c..8b3c97339 100644
--- a/stratosphere/libstratosphere/source/spl/smc/spl_smc.cpp
+++ b/stratosphere/libstratosphere/source/spl/smc/spl_smc.cpp
@@ -309,4 +309,59 @@ namespace sts::spl::smc {
return static_cast(args.X[0]);
}
+ /* Atmosphere functions. */
+ namespace {
+
+ enum class IramCopyDirection {
+ FromIram = 0,
+ ToIram = 1,
+ };
+
+ inline Result AtmosphereIramCopy(uintptr_t dram_address, uintptr_t iram_address, size_t size, IramCopyDirection direction) {
+ SecmonArgs args;
+ args.X[0] = static_cast(FunctionId::AtmosphereIramCopy);
+ args.X[1] = dram_address;
+ args.X[2] = iram_address;
+ args.X[3] = size;
+ args.X[4] = static_cast(direction);
+ svcCallSecureMonitor(&args);
+
+ return static_cast(args.X[0]);
+ }
+
+ }
+
+ Result AtmosphereCopyToIram(uintptr_t iram_dst, const void *dram_src, size_t size) {
+ return AtmosphereIramCopy(reinterpret_cast(dram_src), iram_dst, size, IramCopyDirection::ToIram);
+ }
+
+ Result AtmosphereCopyFromIram(void *dram_dst, uintptr_t iram_src, size_t size) {
+ return AtmosphereIramCopy(reinterpret_cast(dram_dst), iram_src, size, IramCopyDirection::FromIram);
+ }
+
+ Result AtmosphereReadWriteRegister(uint64_t address, uint32_t mask, uint32_t value, uint32_t *out_value) {
+ SecmonArgs args;
+ args.X[0] = static_cast(FunctionId::AtmosphereReadWriteRegister);
+ args.X[1] = address;
+ args.X[2] = mask;
+ args.X[3] = value;
+ svcCallSecureMonitor(&args);
+
+ *out_value = static_cast(args.X[1]);
+ return static_cast(args.X[0]);
+ }
+
+ Result AtmosphereWriteAddress(void *dst, const void *src, size_t size) {
+ STS_ASSERT(size <= sizeof(u64));
+
+ SecmonArgs args;
+ args.X[0] = static_cast(FunctionId::AtmosphereWriteAddress);
+ args.X[1] = reinterpret_cast(dst);
+ __builtin_memcpy(&args.X[1], src, size);
+ args.X[3] = size;
+ svcCallSecureMonitor(&args);
+
+ return static_cast(args.X[0]);
+ }
+
}
diff --git a/stratosphere/libstratosphere/source/updater/updater_api.cpp b/stratosphere/libstratosphere/source/updater/updater_api.cpp
index f4f938520..ab619c107 100644
--- a/stratosphere/libstratosphere/source/updater/updater_api.cpp
+++ b/stratosphere/libstratosphere/source/updater/updater_api.cpp
@@ -346,7 +346,7 @@ namespace sts::updater {
}
/* Only preserve autorcm if on a unit with unpatched rcm bug. */
- if (HasAutoRcmPreserve(boot_image_update_type) && !IsRcmBugPatched()) {
+ if (HasAutoRcmPreserve(boot_image_update_type) && !ams::IsRcmBugPatched()) {
R_TRY(boot0_accessor.PreserveAutoRcm(bct, work, Boot0Partition::BctNormalSub));
R_TRY(boot0_accessor.Write(bct, BctSize, Boot0Partition::BctNormalSub));
R_TRY(boot0_accessor.PreserveAutoRcm(bct, work, Boot0Partition::BctNormalMain));
@@ -407,7 +407,7 @@ namespace sts::updater {
R_TRY(boot0_accessor.UpdateEks(bct, work));
}
/* Only preserve autorcm if on a unit with unpatched rcm bug. */
- if (HasAutoRcmPreserve(boot_image_update_type) && !IsRcmBugPatched()) {
+ if (HasAutoRcmPreserve(boot_image_update_type) && !ams::IsRcmBugPatched()) {
R_TRY(boot0_accessor.PreserveAutoRcm(bct, work, Boot0Partition::BctSafeSub));
R_TRY(boot0_accessor.Write(bct, BctSize, Boot0Partition::BctSafeSub));
R_TRY(boot0_accessor.PreserveAutoRcm(bct, work, Boot0Partition::BctSafeMain));
@@ -522,10 +522,8 @@ namespace sts::updater {
}
/* Get a session to ncm. */
- DoWithSmSession([&]() {
- R_ASSERT(ncmInitialize());
- });
- ON_SCOPE_EXIT { ncmExit(); };
+ sm::ScopedServiceHolder ncm_holder;
+ R_ASSERT(ncm_holder.GetResult());
/* Verify normal, verify safe as needed. */
if (verification_state.needs_verify_normal) {
diff --git a/stratosphere/loader/source/ldr_main.cpp b/stratosphere/loader/source/ldr_main.cpp
index 323866174..ebc612259 100644
--- a/stratosphere/loader/source/ldr_main.cpp
+++ b/stratosphere/loader/source/ldr_main.cpp
@@ -46,16 +46,20 @@ extern "C" {
alignas(16) u8 __nx_exception_stack[0x1000];
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
void __libnx_exception_handler(ThreadExceptionDump *ctx);
- void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx);
}
-sts::ncm::TitleId __stratosphere_title_id = sts::ncm::TitleId::Loader;
+namespace sts::ams {
+
+ ncm::TitleId StratosphereTitleId = ncm::TitleId::Loader;
+
+}
+
+using namespace sts;
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
- StratosphereCrashHandler(ctx);
+ ams::CrashHandler(ctx);
}
-
void __libnx_initheap(void) {
void* addr = nx_inner_heap;
size_t size = nx_inner_heap_size;
@@ -68,19 +72,17 @@ void __libnx_initheap(void) {
fake_heap_end = (char*)addr + size;
}
-using namespace sts;
-
void __appInit(void) {
hos::SetVersionForLibnx();
/* Initialize services we need. */
- DoWithSmSession([&]() {
+ sm::DoWithSession([&]() {
R_ASSERT(fsInitialize());
R_ASSERT(lrInitialize());
R_ASSERT(fsldrInitialize());
});
- CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION);
+ ams::CheckApiVersion();
}
void __appExit(void) {
diff --git a/stratosphere/loader/source/ldr_process_creation.cpp b/stratosphere/loader/source/ldr_process_creation.cpp
index 8eac3a8e2..d5edec87f 100644
--- a/stratosphere/loader/source/ldr_process_creation.cpp
+++ b/stratosphere/loader/source/ldr_process_creation.cpp
@@ -723,10 +723,9 @@ namespace sts::ldr {
R_TRY(LoadNsosIntoProcessMemory(&info, loc.title_id, nso_headers, has_nso, arg_info));
/* Register NSOs with ro manager. */
- os::ProcessId process_id = os::InvalidProcessId;
{
- /* Nintendo doesn't validate this result, but we will. */
- R_ASSERT(svcGetProcessId(&process_id.value, info.process_handle.Get()));
+ /* Nintendo doesn't validate this get, but we do. */
+ os::ProcessId process_id = os::GetProcessId(info.process_handle.Get());
/* Register new process. */
ldr::ro::RegisterProcess(pin_id, process_id, loc.title_id);
diff --git a/stratosphere/pm/Makefile b/stratosphere/pm/Makefile
index 57e73d8c8..09abb4c9a 100644
--- a/stratosphere/pm/Makefile
+++ b/stratosphere/pm/Makefile
@@ -41,7 +41,7 @@ ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE
CFLAGS := -g -Wall -O2 -ffunction-sections \
$(ARCH) $(DEFINES)
-CFLAGS += $(INCLUDE) -D__SWITCH__ -DSM_ENABLE_SMHAX
+CFLAGS += $(INCLUDE) -D__SWITCH__
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17
diff --git a/stratosphere/pm/source/impl/pm_process_manager.cpp b/stratosphere/pm/source/impl/pm_process_manager.cpp
index 3eebce2c7..039776f56 100644
--- a/stratosphere/pm/source/impl/pm_process_manager.cpp
+++ b/stratosphere/pm/source/impl/pm_process_manager.cpp
@@ -310,8 +310,7 @@ namespace sts::pm::impl {
});
/* Get the process id. */
- os::ProcessId process_id = os::InvalidProcessId;
- R_ASSERT(svcGetProcessId(&process_id.value, process_handle));
+ os::ProcessId process_id = os::GetProcessId(process_handle);
/* Make new process info. */
void *process_info_storage = g_process_info_allocator.AllocateProcessInfoStorage();
diff --git a/stratosphere/pm/source/pm_main.cpp b/stratosphere/pm/source/pm_main.cpp
index 93dbb0322..a7285c742 100644
--- a/stratosphere/pm/source/pm_main.cpp
+++ b/stratosphere/pm/source/pm_main.cpp
@@ -48,13 +48,18 @@ extern "C" {
alignas(16) u8 __nx_exception_stack[0x1000];
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
void __libnx_exception_handler(ThreadExceptionDump *ctx);
- void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx);
}
-sts::ncm::TitleId __stratosphere_title_id = sts::ncm::TitleId::Pm;
+namespace sts::ams {
+
+ ncm::TitleId StratosphereTitleId = ncm::TitleId::Pm;
+
+}
+
+using namespace sts;
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
- StratosphereCrashHandler(ctx);
+ ams::CrashHandler(ctx);
}
void __libnx_initheap(void) {
@@ -69,8 +74,6 @@ void __libnx_initheap(void) {
fake_heap_end = (char*)addr + size;
}
-using namespace sts;
-
namespace {
constexpr u32 PrivilegedFileAccessHeader[0x1C / sizeof(u32)] = {0x00000001, 0x00000000, 0x80000000, 0x0000001C, 0x00000000, 0x0000001C, 0x00000000};
@@ -83,10 +86,8 @@ namespace {
/* Check if we should return our title id. */
/* Doing this here works around a bug fixed in 6.0.0. */
/* Not doing so will cause svcDebugActiveProcess to deadlock on lower firmwares if called for it's own process. */
- os::ProcessId current_process_id = os::InvalidProcessId;
- R_ASSERT(svcGetProcessId(¤t_process_id.value, CUR_PROCESS_HANDLE));
- if (current_process_id == process_id) {
- return __stratosphere_title_id;
+ if (process_id == os::GetCurrentProcessId()) {
+ return ams::StratosphereTitleId;
}
/* Get a debug handle. */
@@ -97,8 +98,8 @@ namespace {
svc::DebugEventInfo d;
while (true) {
R_ASSERT(svcGetDebugEvent(reinterpret_cast(&d), debug_handle.Get()));
- if (d.type == sts::svc::DebugEventType::AttachProcess) {
- return sts::ncm::TitleId{d.info.attach_process.title_id};
+ if (d.type == svc::DebugEventType::AttachProcess) {
+ return ncm::TitleId{d.info.attach_process.title_id};
}
}
}
@@ -109,14 +110,14 @@ namespace {
void RegisterPrivilegedProcess(os::ProcessId process_id) {
fsprUnregisterProgram(static_cast(process_id));
fsprRegisterProgram(static_cast(process_id), static_cast(process_id), FsStorageId_NandSystem, PrivilegedFileAccessHeader, sizeof(PrivilegedFileAccessHeader), PrivilegedFileAccessControl, sizeof(PrivilegedFileAccessControl));
- sts::sm::manager::UnregisterProcess(process_id);
- sts::sm::manager::RegisterProcess(process_id, GetProcessTitleId(process_id), PrivilegedServiceAccessControl, sizeof(PrivilegedServiceAccessControl), PrivilegedServiceAccessControl, sizeof(PrivilegedServiceAccessControl));
+ sm::manager::UnregisterProcess(process_id);
+ sm::manager::RegisterProcess(process_id, GetProcessTitleId(process_id), PrivilegedServiceAccessControl, sizeof(PrivilegedServiceAccessControl), PrivilegedServiceAccessControl, sizeof(PrivilegedServiceAccessControl));
}
void RegisterPrivilegedProcesses() {
/* Get privileged process range. */
os::ProcessId min_priv_process_id = os::InvalidProcessId, max_priv_process_id = os::InvalidProcessId;
- sts::cfg::GetInitialProcessRange(&min_priv_process_id, &max_priv_process_id);
+ cfg::GetInitialProcessRange(&min_priv_process_id, &max_priv_process_id);
/* Get list of processes, register all privileged ones. */
u32 num_pids;
@@ -134,7 +135,7 @@ namespace {
void __appInit(void) {
hos::SetVersionForLibnx();
- DoWithSmSession([&]() {
+ sm::DoWithSession([&]() {
R_ASSERT(fsprInitialize());
R_ASSERT(smManagerInitialize());
@@ -143,14 +144,14 @@ void __appInit(void) {
RegisterPrivilegedProcesses();
/* Use AMS manager extension to tell SM that FS has been worked around. */
- R_ASSERT(sts::sm::manager::EndInitialDefers());
+ R_ASSERT(sm::manager::EndInitialDefers());
R_ASSERT(lrInitialize());
R_ASSERT(ldrPmInitialize());
R_ASSERT(splInitialize());
});
- CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION);
+ ams::CheckApiVersion();
}
void __appExit(void) {
@@ -191,7 +192,7 @@ namespace {
int main(int argc, char **argv)
{
/* Initialize process manager implementation. */
- R_ASSERT(sts::pm::impl::InitializeProcessManager());
+ R_ASSERT(pm::impl::InitializeProcessManager());
/* Create Services. */
/* NOTE: Extra sessions have been added to pm:bm and pm:info to facilitate access by the rest of stratosphere. */
diff --git a/stratosphere/ro/source/impl/ro_service_impl.cpp b/stratosphere/ro/source/impl/ro_service_impl.cpp
index cbcb080e3..3f3c478e2 100644
--- a/stratosphere/ro/source/impl/ro_service_impl.cpp
+++ b/stratosphere/ro/source/impl/ro_service_impl.cpp
@@ -93,8 +93,7 @@ namespace sts::ro::impl {
R_ASSERT(svcGetInfo(&title_id.value, InfoType_TitleId, process_h, 0));
} else {
/* 1.0.0-2.3.0: We're not inside loader, so ask pm. */
- os::ProcessId process_id = os::InvalidProcessId;
- R_ASSERT(svcGetProcessId(&process_id.value, process_h));
+ os::ProcessId process_id = os::GetProcessId(process_h);
R_ASSERT(pminfoGetTitleId(&title_id.value, process_id.value));
}
return title_id;
@@ -335,7 +334,7 @@ namespace sts::ro::impl {
os::ProcessId handle_pid = os::InvalidProcessId;
/* Validate handle is a valid process handle. */
- if (R_FAILED(svcGetProcessId(&handle_pid.value, process_handle))) {
+ if (R_FAILED(os::TryGetProcessId(&handle_pid, process_handle))) {
return ResultRoInvalidProcess;
}
diff --git a/stratosphere/ro/source/ro_main.cpp b/stratosphere/ro/source/ro_main.cpp
index f3f156814..4d33a7d4a 100644
--- a/stratosphere/ro/source/ro_main.cpp
+++ b/stratosphere/ro/source/ro_main.cpp
@@ -44,8 +44,13 @@ extern "C" {
void __appExit(void);
}
-/* Exception handling. */
-sts::ncm::TitleId __stratosphere_title_id = sts::ncm::TitleId::Ro;
+namespace sts::ams {
+
+ ncm::TitleId StratosphereTitleId = ncm::TitleId::Ro;
+
+}
+
+using namespace sts;
void __libnx_initheap(void) {
void* addr = nx_inner_heap;
@@ -59,12 +64,10 @@ void __libnx_initheap(void) {
fake_heap_end = (char*)addr + size;
}
-using namespace sts;
-
void __appInit(void) {
hos::SetVersionForLibnx();
- DoWithSmSession([&]() {
+ sm::DoWithSession([&]() {
R_ASSERT(setsysInitialize());
R_ASSERT(fsInitialize());
R_ASSERT(splInitialize());
@@ -75,7 +78,7 @@ void __appInit(void) {
R_ASSERT(fsdevMountSdmc());
- CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION);
+ ams::CheckApiVersion();
}
void __appExit(void) {
diff --git a/stratosphere/sm/source/sm_main.cpp b/stratosphere/sm/source/sm_main.cpp
index 08f33d020..239c0c6af 100644
--- a/stratosphere/sm/source/sm_main.cpp
+++ b/stratosphere/sm/source/sm_main.cpp
@@ -45,13 +45,18 @@ extern "C" {
alignas(16) u8 __nx_exception_stack[0x1000];
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
void __libnx_exception_handler(ThreadExceptionDump *ctx);
- void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx);
}
-sts::ncm::TitleId __stratosphere_title_id = sts::ncm::TitleId::Sm;
+namespace sts::ams {
+
+ ncm::TitleId StratosphereTitleId = ncm::TitleId::Sm;
+
+}
+
+using namespace sts;
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
- StratosphereCrashHandler(ctx);
+ ams::CrashHandler(ctx);
}
@@ -68,7 +73,7 @@ void __libnx_initheap(void) {
}
void __appInit(void) {
- sts::hos::SetVersionForLibnx();
+ hos::SetVersionForLibnx();
/* We must do no service setup here, because we are sm. */
}
@@ -77,8 +82,6 @@ void __appExit(void) {
/* Nothing to clean up, because we're sm. */
}
-using namespace sts;
-
namespace {
/* sm:m, sm:, sm:dmnt. */
diff --git a/stratosphere/spl/source/spl_main.cpp b/stratosphere/spl/source/spl_main.cpp
index d372891ff..b3ea6a7ec 100644
--- a/stratosphere/spl/source/spl_main.cpp
+++ b/stratosphere/spl/source/spl_main.cpp
@@ -19,6 +19,7 @@
#include
#include
+#include
#include
#include "spl_api_impl.hpp"
@@ -38,7 +39,7 @@ extern "C" {
u32 __nx_applet_type = AppletType_None;
- #define INNER_HEAP_SIZE 0x28000
+ #define INNER_HEAP_SIZE 0x4000
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
char nx_inner_heap[INNER_HEAP_SIZE];
@@ -50,16 +51,20 @@ extern "C" {
alignas(16) u8 __nx_exception_stack[0x1000];
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
void __libnx_exception_handler(ThreadExceptionDump *ctx);
- void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx);
}
-sts::ncm::TitleId __stratosphere_title_id = sts::ncm::TitleId::Spl;
+namespace sts::ams {
+
+ ncm::TitleId StratosphereTitleId = ncm::TitleId::Spl;
+
+}
+
+using namespace sts;
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
- StratosphereCrashHandler(ctx);
+ ams::CrashHandler(ctx);
}
-
void __libnx_initheap(void) {
void* addr = nx_inner_heap;
size_t size = nx_inner_heap_size;
@@ -72,12 +77,12 @@ void __libnx_initheap(void) {
fake_heap_end = (char*)addr + size;
}
-using namespace sts;
-
void __appInit(void) {
hos::SetVersionForLibnx();
/* SPL doesn't really access any services... */
+
+ ams::CheckApiVersion();
}
void __appExit(void) {
@@ -149,4 +154,4 @@ int main(int argc, char **argv)
g_server_manager.LoopProcess();
return 0;
-}
\ No newline at end of file
+}