Skip to content

Commit

Permalink
use ams bpc sane reboot when available
Browse files Browse the repository at this point in the history
  • Loading branch information
HookedBehemoth committed Sep 25, 2021
1 parent 20f692d commit 20f0a07
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 51 deletions.
5 changes: 5 additions & 0 deletions applet/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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[]) {
Expand Down Expand Up @@ -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 */
Expand Down
41 changes: 41 additions & 0 deletions common/ams_bpc.c
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
*/
#include <switch.h>
#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 } },
);
}
31 changes: 31 additions & 0 deletions common/ams_bpc.h
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <switch.h>

#ifdef __cplusplus
extern "C" {
#endif

Result amsBpcInitialize();
void amsBpcExit();
Service *amsBpcGetServiceSession(void);

Result amsBpcSetRebootPayload(const void *src, size_t src_size);

#ifdef __cplusplus
}
#endif
89 changes: 45 additions & 44 deletions common/payload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
*/
#include "payload.hpp"

#include "ini.h"
#include "reboot_to_payload.h"
#include "ams_bpc.h"
#include "ini.h"

#include <cstdio>
#include <cstring>
Expand All @@ -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<HekateConfigList *>(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;
}
Expand Down Expand Up @@ -193,7 +210,8 @@ namespace Payload {
return res;
}

bool RebootToHekate() {
template<typename ConfigureFunction>
bool Reboot(ConfigureFunction func) {
/* Load payload. */
if (!LoadHekatePayload())
return false;
Expand All @@ -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<BootStorage *>(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<BootStorage *>(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) {
Expand All @@ -261,7 +262,7 @@ namespace Payload {
return false;

/* Reboot */
reboot_to_payload();
RebootToPayload();

return true;
}
Expand Down
10 changes: 5 additions & 5 deletions common/reboot_to_payload.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@
#include <string.h>
#include <switch.h>

#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};
Expand All @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions common/reboot_to_payload.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
2 changes: 2 additions & 0 deletions overlay/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,11 @@ class PancakeOverlay final : public tsl::Overlay {
virtual void initServices() override {
fsdevMountSdmc();
splInitialize();
spsmInitialize();
}

virtual void exitServices() override {
spsmExit();
splExit();
fsdevUnmountAll();
}
Expand Down

0 comments on commit 20f0a07

Please sign in to comment.