libstrat: namespace remaining non-namespaced code. more new-ipc updates

This commit is contained in:
Michael Scire
2019-10-19 17:42:53 -07:00
committed by SciresM
parent ae2fa2fa60
commit 0b22af1206
68 changed files with 1257 additions and 2118 deletions

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#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 } },
);
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <switch/types.h>
#include <switch/kernel/event.h>
#include <switch/services/sm.h>
#ifdef __cplusplus
extern "C" {
#endif
Result amsBpcInitialize(void);
void amsBpcExit(void);
Service *amsBpcGetServiceSession(void);
Result amsBpcRebootToFatalError(void *ctx);
#ifdef __cplusplus
}
#endif

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#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<u64>(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<void *>(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<size_t>(mem_info.addr + mem_info.size - ams_ctx.sp));
ams_ctx.stack_dump_size = copy_size;
std::memcpy(ams_ctx.stack_dump, reinterpret_cast<void *>(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();
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#include <stratosphere/spl.hpp>
#include <stratosphere/spl/smc/spl_smc.hpp>
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<u32>((exosphere_cfg >> 0x20) & 0xFF),
.minor_version = static_cast<u32>((exosphere_cfg >> 0x18) & 0xFF),
.micro_version = static_cast<u32>((exosphere_cfg >> 0x10) & 0xFF),
.target_firmware = static_cast<TargetFirmware>((exosphere_cfg >> 0x08) & 0xFF),
.master_key_revision = static_cast<u32>((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;
}
}

View File

@@ -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<ams::TargetFirmware>(target_fw)) {
switch (ams::GetApiInfo().GetTargetFirmware()) {
case ams::TargetFirmware_100:
g_hos_version = hos::Version_100;
break;