/* * Copyright (c) 2019 m4xw * 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 . */ /* 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; R_DISCARD(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(max_log_sz - log_ctx->end))) { R_DISCARD(SmcCopyToIram(IRAM_LOG_CTX_ADDR, working_buf, sizeof(working_buf))); return; } log_ctx->end += res; R_DISCARD(SmcCopyToIram(IRAM_LOG_CTX_ADDR, working_buf, sizeof(working_buf))); } #endif #if defined(AMS_BUILD_FOR_AUDITING) || defined(AMS_BUILD_FOR_DEBUGGING) void ViewLog() { if (spl::GetSocType() == spl::SocType_Mariko) { return; } 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)); R_DISCARD(SmcCopyToIram(ATMOSPHERE_IRAM_PAYLOAD_BASE + ofs, &working_buf, std::min(fatal_handler_bin_size - ofs, PageSize))); } SmcRebootToIramPayload(); while(true){} } #endif }