diff --git a/applet/main.cpp b/applet/main.cpp
index 55eadec2..7d4cd270 100644
--- a/applet/main.cpp
+++ b/applet/main.cpp
@@ -58,11 +58,13 @@ namespace {
}
extern "C" void userAppInit(void) {
+ spsmInitialize();
splInitialize();
}
extern "C" void userAppExit(void) {
splExit();
+ spsmExit();
}
int main(int const argc, char const *argv[]) {
@@ -126,6 +128,9 @@ int main(int const argc, char const *argv[]) {
PadState pad;
padInitializeAny(&pad);
+ /* Deinit sm to free up our only service slot */
+ smExit();
+
while (appletMainLoop()) {
{
/* Update padstate */
diff --git a/common/ams_bpc.c b/common/ams_bpc.c
new file mode 100644
index 00000000..cf4a27ee
--- /dev/null
+++ b/common/ams_bpc.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2018-2020 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#include
+#include "ams_bpc.h"
+
+static Service g_amsBpcSrv;
+
+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 amsBpcExit(void) {
+ serviceClose(&g_amsBpcSrv);
+}
+
+Service *amsBpcGetServiceSession(void) {
+ return &g_amsBpcSrv;
+}
+
+Result amsBpcSetRebootPayload(const void *src, size_t src_size) {
+ return serviceDispatch(&g_amsBpcSrv, 65001,
+ .buffer_attrs = { SfBufferAttr_In | SfBufferAttr_HipcMapAlias },
+ .buffers = { { src, src_size } },
+ );
+}
diff --git a/common/ams_bpc.h b/common/ams_bpc.h
new file mode 100644
index 00000000..cab9d2a5
--- /dev/null
+++ b/common/ams_bpc.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018-2020 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#pragma once
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+Result amsBpcInitialize();
+void amsBpcExit();
+Service *amsBpcGetServiceSession(void);
+
+Result amsBpcSetRebootPayload(const void *src, size_t src_size);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/common/payload.cpp b/common/payload.cpp
index 5025d231..6966d1c6 100644
--- a/common/payload.cpp
+++ b/common/payload.cpp
@@ -15,8 +15,9 @@
*/
#include "payload.hpp"
-#include "ini.h"
#include "reboot_to_payload.h"
+#include "ams_bpc.h"
+#include "ini.h"
#include
#include
@@ -27,10 +28,26 @@ namespace Payload {
namespace {
+ void RebootToPayload() {
+ /* Try reboot with safe ams bpc api. */
+ Result rc = amsBpcInitialize();
+ if (R_SUCCEEDED(rc)) {
+ rc = amsBpcSetRebootPayload(g_reboot_payload, IRAM_PAYLOAD_MAX_SIZE);
+ if (R_SUCCEEDED(rc)) {
+ spsmShutdown(true);
+ }
+ amsBpcExit();
+ }
+
+ /* Fallback to old smc reboot to payload. */
+ if (R_FAILED(rc))
+ smc_reboot_to_payload();
+ }
+
int HekateConfigHandler(void *user, char const *section, char const *name, char const *value) {
auto const list = reinterpret_cast(user);
- /* ignore pre-config and global config entries. */
+ /* Ignore pre-config and global config entries. */
if (section[0] == '\0' || std::strcmp(section, "config") == 0) {
return 1;
}
@@ -193,7 +210,8 @@ namespace Payload {
return res;
}
- bool RebootToHekate() {
+ template
+ bool Reboot(ConfigureFunction func) {
/* Load payload. */
if (!LoadHekatePayload())
return false;
@@ -204,55 +222,38 @@ namespace Payload {
/* Clear boot storage. */
std::memset(storage, 0, sizeof(BootStorage));
+ /* Configure boot storage */
+ func(storage);
+
/* Reboot */
- reboot_to_payload();
+ RebootToPayload();
return true;
}
- bool RebootToHekateConfig(HekateConfig const &config, bool const autoboot_list) {
- /* Load payload. */
- if (!LoadHekatePayload())
- return false;
-
- /* Get boot storage pointer. */
- auto const storage = reinterpret_cast(g_reboot_payload + BootStorageOffset);
-
- /* Clear boot storage. */
- std::memset(storage, 0, sizeof(BootStorage));
-
- /* Force autoboot and set boot id. */
- storage->boot_cfg = BootCfg_ForceAutoBoot;
- storage->autoboot = config.index;
- storage->autoboot_list = autoboot_list;
-
- /* Reboot */
- reboot_to_payload();
+ bool RebootToHekate() {
+ return Reboot([&] (BootStorage *storage) {
+ /* No-Op */
+ });
+ }
- return true;
+ bool RebootToHekateConfig(HekateConfig const &config, bool const autoboot_list) {
+ return Reboot([&] (BootStorage *storage) {
+ /* Force autoboot and set boot id. */
+ storage->boot_cfg = BootCfg_ForceAutoBoot;
+ storage->autoboot = config.index;
+ storage->autoboot_list = autoboot_list;
+ });
}
bool RebootToHekateUMS(UmsTarget const target) {
- /* Load payload. */
- if (!LoadHekatePayload())
- return false;
-
- /* Get boot storage pointer. */
- auto const storage = reinterpret_cast(g_reboot_payload + BootStorageOffset);
-
- /* Clear boot storage. */
- std::memset(storage, 0, sizeof(BootStorage));
-
- /* Force boot to menu, target UMS and select target. */
- storage->boot_cfg = BootCfg_ForceAutoBoot;
- storage->extra_cfg = ExtraCfg_NyxUms;
- storage->autoboot = 0;
- storage->ums = target;
-
- /* Reboot */
- reboot_to_payload();
-
- return true;
+ return Reboot([&] (BootStorage *storage) {
+ /* Force boot to menu, target UMS and select target. */
+ storage->boot_cfg = BootCfg_ForceAutoBoot;
+ storage->extra_cfg = ExtraCfg_NyxUms;
+ storage->autoboot = 0;
+ storage->ums = target;
+ });
}
bool RebootToPayload(PayloadConfig const &config) {
@@ -261,7 +262,7 @@ namespace Payload {
return false;
/* Reboot */
- reboot_to_payload();
+ RebootToPayload();
return true;
}
diff --git a/common/reboot_to_payload.c b/common/reboot_to_payload.c
index 8523f345..5988c638 100644
--- a/common/reboot_to_payload.c
+++ b/common/reboot_to_payload.c
@@ -18,14 +18,14 @@
#include
#include
-#define IRAM_PAYLOAD_MAX_SIZE 0x2F000
+#define IRAM_PAYLOAD_MAX_SIZE 0x24000
#define IRAM_PAYLOAD_BASE 0x40010000
alignas(0x1000) u8 g_reboot_payload[IRAM_PAYLOAD_MAX_SIZE];
static alignas(0x1000) u8 g_ff_page[0x1000];
static alignas(0x1000) u8 g_work_page[0x1000];
-void do_iram_dram_copy(void *buf, uintptr_t iram_addr, size_t size, int option) {
+static void do_iram_dram_copy(void *buf, uintptr_t iram_addr, size_t size, int option) {
memcpy(g_work_page, buf, size);
SecmonArgs args = {0};
@@ -39,18 +39,18 @@ void do_iram_dram_copy(void *buf, uintptr_t iram_addr, size_t size, int option)
memcpy(buf, g_work_page, size);
}
-void copy_to_iram(uintptr_t iram_addr, void *buf, size_t size) {
+static void copy_to_iram(uintptr_t iram_addr, void *buf, size_t size) {
do_iram_dram_copy(buf, iram_addr, size, 1);
}
-void clear_iram(void) {
+static void clear_iram(void) {
memset(g_ff_page, 0xFF, sizeof(g_ff_page));
for (size_t i = 0; i < IRAM_PAYLOAD_MAX_SIZE; i += sizeof(g_ff_page)) {
copy_to_iram(IRAM_PAYLOAD_BASE + i, g_ff_page, sizeof(g_ff_page));
}
}
-void reboot_to_payload(void) {
+void smc_reboot_to_payload(void) {
clear_iram();
for (size_t i = 0; i < IRAM_PAYLOAD_MAX_SIZE; i += 0x1000) {
diff --git a/common/reboot_to_payload.h b/common/reboot_to_payload.h
index da064626..0f437e3f 100644
--- a/common/reboot_to_payload.h
+++ b/common/reboot_to_payload.h
@@ -21,11 +21,11 @@
extern "C" {
#endif
-#define IRAM_PAYLOAD_MAX_SIZE 0x2F000
+#define IRAM_PAYLOAD_MAX_SIZE 0x24000
extern u8 g_reboot_payload[IRAM_PAYLOAD_MAX_SIZE];
-void reboot_to_payload(void);
+void smc_reboot_to_payload(void);
#ifdef __cplusplus
}
diff --git a/overlay/main.cpp b/overlay/main.cpp
index fa296f18..76f82b81 100644
--- a/overlay/main.cpp
+++ b/overlay/main.cpp
@@ -122,9 +122,11 @@ class PancakeOverlay final : public tsl::Overlay {
virtual void initServices() override {
fsdevMountSdmc();
splInitialize();
+ spsmInitialize();
}
virtual void exitServices() override {
+ spsmExit();
splExit();
fsdevUnmountAll();
}