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(); }