129 lines
3.9 KiB
C++
129 lines
3.9 KiB
C++
/*
|
|
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
|
|
* Copyright (c) 2019 Atmosphere-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/>.
|
|
*/
|
|
|
|
/* See https://github.com/lulle2007200/emuMMC/blob/internal-emummc/source/ */
|
|
|
|
#include "oc_common.hpp"
|
|
|
|
#if defined(AMS_BUILD_FOR_AUDITING) || defined(AMS_BUILD_FOR_DEBUGGING)
|
|
#include "fatal_handler_bin.h"
|
|
#endif
|
|
|
|
namespace ams::ldr::hoc {
|
|
|
|
#define ATMOSPHERE_REBOOT_TO_FATAL_MAGIC 0x32454641
|
|
#define ATMOSPHERE_IRAM_PAYLOAD_BASE 0x40010000
|
|
#define ATMOSPHERE_FATAL_ERROR_ADDR 0x4003E000
|
|
|
|
_Alignas(4096) u8 working_buf[4096];
|
|
|
|
void SmcRebootToIramPayload() {
|
|
SecmonArgs args;
|
|
args.X[0] = 0xC3000401;
|
|
args.X[1] = 65001;
|
|
args.X[2] = 0;
|
|
args.X[3] = 2;
|
|
svcCallSecureMonitor(&args);
|
|
}
|
|
|
|
Result SmcCopyToIram(uintptr_t dest, const void *src, u32 size) {
|
|
SecmonArgs args;
|
|
args.X[0] = 0xF0000201;
|
|
args.X[1] = (u64)src;
|
|
args.X[2] = (u64)dest;
|
|
args.X[3] = size;
|
|
args.X[4] = 1;
|
|
svcCallSecureMonitor(&args);
|
|
Result rc = 0;
|
|
if (args.X[0] != 0) {
|
|
rc = (26u | ((u32)args.X[0] << 9u));
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
Result SmcCopyFromIram(void *dest, uintptr_t src, u32 size) {
|
|
SecmonArgs args;
|
|
args.X[0] = 0xF0000201;
|
|
args.X[1] = (u64)dest;
|
|
args.X[2] = (u64)src;
|
|
args.X[3] = size;
|
|
args.X[4] = 0;
|
|
svcCallSecureMonitor(&args);
|
|
Result rc = 0;
|
|
if (args.X[0] != 0) {
|
|
rc = (26u | ((u32)args.X[0] << 9u));
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
struct log_ctx_t {
|
|
u32 magic;
|
|
u32 sz;
|
|
u32 start;
|
|
u32 end;
|
|
char buf[];
|
|
};
|
|
|
|
#define IRAM_LOG_CTX_ADDR 0x4003C000
|
|
#define IRAM_LOG_MAX_SZ 4096
|
|
|
|
#if defined(AMS_BUILD_FOR_AUDITING) || defined(AMS_BUILD_FOR_DEBUGGING)
|
|
void Log(const char *data, ...) {
|
|
static const u32 max_log_sz = sizeof(working_buf) - sizeof(log_ctx_t);
|
|
static bool initDone = false;
|
|
log_ctx_t *log_ctx = (log_ctx_t*)working_buf;
|
|
|
|
SmcCopyFromIram(working_buf, IRAM_LOG_CTX_ADDR, sizeof(working_buf));
|
|
|
|
if (!initDone) {
|
|
initDone = true;
|
|
log_ctx->buf[0] = '\0';
|
|
log_ctx->magic = 0xaabbccdd;
|
|
log_ctx->start = 0;
|
|
log_ctx->end = 0;
|
|
}
|
|
|
|
va_list args;
|
|
va_start(args, data);
|
|
s32 res = vsnprintf(log_ctx->buf + log_ctx->end, max_log_sz - log_ctx->end, data, args);
|
|
va_end(args);
|
|
|
|
if (res < 0 || res >= (static_cast<s32>(max_log_sz - log_ctx->end))) {
|
|
SmcCopyToIram(IRAM_LOG_CTX_ADDR, working_buf, sizeof(working_buf));
|
|
return;
|
|
}
|
|
|
|
log_ctx->end += res;
|
|
SmcCopyToIram(IRAM_LOG_CTX_ADDR, working_buf, sizeof(working_buf));
|
|
}
|
|
#endif
|
|
|
|
#if defined(AMS_BUILD_FOR_AUDITING) || defined(AMS_BUILD_FOR_DEBUGGING)
|
|
void ViewLog() {
|
|
constexpr size_t PageSize = 4096;
|
|
for (size_t ofs = 0; ofs < fatal_handler_bin_size; ofs += PageSize) {
|
|
memcpy(&working_buf, fatal_handler_bin + ofs, std::min(fatal_handler_bin_size - ofs, PageSize));
|
|
SmcCopyToIram(ATMOSPHERE_IRAM_PAYLOAD_BASE + ofs, &working_buf, std::min(fatal_handler_bin_size - ofs, PageSize));
|
|
}
|
|
|
|
SmcRebootToIramPayload();
|
|
|
|
while(true){}
|
|
}
|
|
#endif
|
|
}
|