fatal: refactor into sts namespace

This commit is contained in:
Michael Scire
2019-07-18 19:09:35 -07:00
committed by SciresM
parent 442ebff829
commit 39d041466d
38 changed files with 2176 additions and 1926 deletions

View File

@@ -14,378 +14,434 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <switch.h>
#include <atmosphere/version.h>
#include "fatal_task_screen.hpp"
#include "fatal_config.hpp"
#include "fatal_font.hpp"
#include "ams_logo.hpp"
static constexpr u32 FatalScreenWidth = 1280;
static constexpr u32 FatalScreenHeight = 720;
static constexpr u32 FatalScreenBpp = 2;
namespace sts::fatal::srv {
static constexpr u32 FatalScreenWidthAlignedBytes = (FatalScreenWidth * FatalScreenBpp + 63) & ~63;
static constexpr u32 FatalScreenWidthAligned = FatalScreenWidthAlignedBytes / FatalScreenBpp;
/* Include Atmosphere logo into its own anonymous namespace. */
u32 GetPixelOffset(uint32_t x, uint32_t y)
{
u32 tmp_pos;
namespace {
tmp_pos = ((y & 127) / 16) + (x/32*8) + ((y/16/8)*(((FatalScreenWidthAligned/2)/16*8)));
tmp_pos *= 16*16 * 4;
#include "fatal_ams_logo.inc"
tmp_pos += ((y%16)/8)*512 + ((x%32)/16)*256 + ((y%8)/2)*64 + ((x%16)/8)*32 + (y%2)*16 + (x%8)*2;//This line is a modified version of code from the Tegra X1 datasheet.
}
return tmp_pos / 2;
}
namespace {
/* Screen definitions. */
constexpr u32 FatalScreenWidth = 1280;
constexpr u32 FatalScreenHeight = 720;
constexpr u32 FatalScreenBpp = 2;
constexpr u32 FatalLayerZ = 100;
constexpr u32 FatalScreenWidthAlignedBytes = (FatalScreenWidth * FatalScreenBpp + 63) & ~63;
constexpr u32 FatalScreenWidthAligned = FatalScreenWidthAlignedBytes / FatalScreenBpp;
/* Pixel calculation helper. */
constexpr u32 GetPixelOffset(u32 x, u32 y) {
u32 tmp_pos = ((y & 127) / 16) + (x/32*8) + ((y/16/8)*(((FatalScreenWidthAligned/2)/16*8)));
tmp_pos *= 16*16 * 4;
tmp_pos += ((y%16)/8)*512 + ((x%32)/16)*256 + ((y%8)/2)*64 + ((x%16)/8)*32 + (y%2)*16 + (x%8)*2;//This line is a modified version of code from the Tegra X1 datasheet.
return tmp_pos / 2;
}
/* Task definitions. */
class ShowFatalTask : public ITask {
private:
ViDisplay display;
ViLayer layer;
NWindow win;
Framebuffer fb;
private:
Result SetupDisplayInternal();
Result SetupDisplayExternal();
Result PrepareScreenForDrawing();
Result ShowFatal();
public:
virtual Result Run() override;
virtual const char *GetName() const override {
return "ShowFatal";
}
virtual size_t GetStackSize() const override {
return 0x8000;
}
};
class BacklightControlTask : public ITask {
private:
void TurnOnBacklight();
public:
virtual Result Run() override;
virtual const char *GetName() const override {
return "BacklightControlTask";
}
};
/* Task globals. */
ShowFatalTask g_show_fatal_task;
BacklightControlTask g_backlight_control_task;
/* Task implementations. */
Result ShowFatalTask::SetupDisplayInternal() {
ViDisplay temp_display;
/* Try to open the display. */
R_TRY_CATCH(viOpenDisplay("Internal", &temp_display)) {
R_CATCH(ResultViNotFound) {
return ResultSuccess;
}
} R_END_TRY_CATCH;
/* Guarantee we close the display. */
ON_SCOPE_EXIT { viCloseDisplay(&temp_display); };
/* Turn on the screen. */
R_TRY(viSetDisplayPowerState(&temp_display, ViPowerState_On));
/* Set alpha to 1.0f. */
R_TRY(viSetDisplayAlpha(&temp_display, 1.0f));
Result ShowFatalTask::SetupDisplayInternal() {
ViDisplay display;
/* Try to open the display. */
R_TRY_CATCH(viOpenDisplay("Internal", &display)) {
R_CATCH(ResultViNotFound) {
return ResultSuccess;
}
} R_END_TRY_CATCH;
/* Guarantee we close the display. */
ON_SCOPE_EXIT { viCloseDisplay(&display); };
Result ShowFatalTask::SetupDisplayExternal() {
ViDisplay temp_display;
/* Try to open the display. */
R_TRY_CATCH(viOpenDisplay("External", &temp_display)) {
R_CATCH(ResultViNotFound) {
return ResultSuccess;
}
} R_END_TRY_CATCH;
/* Turn on the screen. */
R_TRY(viSetDisplayPowerState(&display, ViPowerState_On));
/* Guarantee we close the display. */
ON_SCOPE_EXIT { viCloseDisplay(&temp_display); };
/* Set alpha to 1.0f. */
R_TRY(viSetDisplayAlpha(&display, 1.0f));
/* Set alpha to 1.0f. */
R_TRY(viSetDisplayAlpha(&temp_display, 1.0f));
return ResultSuccess;
}
Result ShowFatalTask::SetupDisplayExternal() {
ViDisplay display;
/* Try to open the display. */
R_TRY_CATCH(viOpenDisplay("External", &display)) {
R_CATCH(ResultViNotFound) {
return ResultSuccess;
}
} R_END_TRY_CATCH;
/* Guarantee we close the display. */
ON_SCOPE_EXIT { viCloseDisplay(&display); };
Result ShowFatalTask::PrepareScreenForDrawing() {
/* Connect to vi. */
R_TRY(viInitialize(ViServiceType_Manager));
/* Set alpha to 1.0f. */
R_TRY(viSetDisplayAlpha(&display, 1.0f));
/* Close other content. */
viSetContentVisibility(false);
return ResultSuccess;
}
/* Setup the two displays. */
R_TRY(SetupDisplayInternal());
R_TRY(SetupDisplayExternal());
Result ShowFatalTask::PrepareScreenForDrawing() {
/* Connect to vi. */
R_TRY(viInitialize(ViServiceType_Manager));
/* Open the default display. */
R_TRY(viOpenDefaultDisplay(&this->display));
/* Close other content. */
viSetContentVisibility(false);
/* Reset the display magnification to its default value. */
u32 display_width, display_height;
R_TRY(viGetDisplayLogicalResolution(&this->display, &display_width, &display_height));
/* Setup the two displays. */
R_TRY(SetupDisplayInternal());
R_TRY(SetupDisplayExternal());
/* viSetDisplayMagnification was added in 3.0.0. */
if (GetRuntimeFirmwareVersion() >= FirmwareVersion_300) {
R_TRY(viSetDisplayMagnification(&this->display, 0, 0, display_width, display_height));
}
/* Open the default display. */
R_TRY(viOpenDefaultDisplay(&this->display));
/* Create layer to draw to. */
R_TRY(viCreateLayer(&this->display, &this->layer));
/* Reset the display magnification to its default value. */
u32 display_width, display_height;
R_TRY(viGetDisplayLogicalResolution(&this->display, &display_width, &display_height));
/* Setup the layer. */
{
/* Display a layer of 1280 x 720 at 1.5x magnification */
/* NOTE: N uses 2 (770x400) RGBA4444 buffers (tiled buffer + linear). */
/* We use a single 1280x720 tiled RGB565 buffer. */
constexpr u32 raw_width = FatalScreenWidth;
constexpr u32 raw_height = FatalScreenHeight;
constexpr u32 layer_width = ((raw_width) * 3) / 2;
constexpr u32 layer_height = ((raw_height) * 3) / 2;
/* viSetDisplayMagnification was added in 3.0.0. */
if (GetRuntimeFirmwareVersion() >= FirmwareVersion_300) {
R_TRY(viSetDisplayMagnification(&this->display, 0, 0, display_width, display_height));
}
const float layer_x = static_cast<float>((display_width - layer_width) / 2);
const float layer_y = static_cast<float>((display_height - layer_height) / 2);
/* Create layer to draw to. */
R_TRY(viCreateLayer(&this->display, &this->layer));
R_TRY(viSetLayerSize(&this->layer, layer_width, layer_height));
/* Setup the layer. */
{
/* Display a layer of 1280 x 720 at 1.5x magnification */
/* NOTE: N uses 2 (770x400) RGBA4444 buffers (tiled buffer + linear). */
/* We use a single 1280x720 tiled RGB565 buffer. */
constexpr u32 raw_width = FatalScreenWidth;
constexpr u32 raw_height = FatalScreenHeight;
constexpr u32 layer_width = ((raw_width) * 3) / 2;
constexpr u32 layer_height = ((raw_height) * 3) / 2;
/* Set the layer's Z at display maximum, to be above everything else .*/
R_TRY(viSetLayerZ(&this->layer, FatalLayerZ));
const float layer_x = static_cast<float>((display_width - layer_width) / 2);
const float layer_y = static_cast<float>((display_height - layer_height) / 2);
u64 layer_z;
/* Center the layer in the screen. */
R_TRY(viSetLayerPosition(&this->layer, layer_x, layer_y));
R_TRY(viSetLayerSize(&this->layer, layer_width, layer_height));
/* Create framebuffer. */
R_TRY(nwindowCreateFromLayer(&this->win, &this->layer));
R_TRY(framebufferCreate(&this->fb, &this->win, raw_width, raw_height, PIXEL_FORMAT_RGB_565, 1));
}
/* Set the layer's Z at display maximum, to be above everything else .*/
/* NOTE: Fatal hardcodes 100 here. */
if (R_SUCCEEDED(viGetDisplayMaximumZ(&this->display, &layer_z))) {
R_TRY(viSetLayerZ(&this->layer, layer_z));
return ResultSuccess;
}
/* Center the layer in the screen. */
R_TRY(viSetLayerPosition(&this->layer, layer_x, layer_y));
Result ShowFatalTask::ShowFatal() {
const FatalConfig &config = GetFatalConfig();
/* Create framebuffer. */
R_TRY(nwindowCreateFromLayer(&this->win, &this->layer));
R_TRY(framebufferCreate(&this->fb, &this->win, raw_width, raw_height, PIXEL_FORMAT_RGB_565, 1));
}
/* Prepare screen for drawing. */
DoWithSmSession([&]() {
R_ASSERT(PrepareScreenForDrawing());
});
return ResultSuccess;
}
/* Dequeue a buffer. */
u16 *tiled_buf = reinterpret_cast<u16 *>(framebufferBegin(&this->fb, NULL));
if (tiled_buf == nullptr) {
return ResultFatalNullGraphicsBuffer;
}
Result ShowFatalTask::ShowFatal() {
const FatalConfig *config = GetFatalConfig();
/* Let the font manager know about our framebuffer. */
font::ConfigureFontFramebuffer(tiled_buf, GetPixelOffset);
font::SetFontColor(0xFFFF);
/* Prepare screen for drawing. */
DoWithSmSession([&]() {
if (R_FAILED(PrepareScreenForDrawing())) {
std::abort();
}
});
/* Draw a background. */
for (size_t i = 0; i < this->fb.fb_size / sizeof(*tiled_buf); i++) {
tiled_buf[i] = 0x39C9;
}
/* Dequeue a buffer. */
u16 *tiled_buf = reinterpret_cast<u16 *>(framebufferBegin(&this->fb, NULL));
if (tiled_buf == nullptr) {
return ResultFatalNullGraphicsBuffer;
}
/* Draw the atmosphere logo in the bottom right corner. */
for (size_t y = 0; y < AtmosphereLogoHeight; y++) {
for (size_t x = 0; x < AtmosphereLogoWidth; x++) {
tiled_buf[GetPixelOffset(FatalScreenWidth - AtmosphereLogoWidth - 32 + x, 32 + y)] = AtmosphereLogoData[y * AtmosphereLogoWidth + x];
}
}
/* Let the font manager know about our framebuffer. */
FontManager::ConfigureFontFramebuffer(tiled_buf, GetPixelOffset);
FontManager::SetFontColor(0xFFFF);
/* Draw a background. */
for (size_t i = 0; i < this->fb.fb_size / sizeof(*tiled_buf); i++) {
tiled_buf[i] = 0x39C9;
}
/* Draw the atmosphere logo in the bottom right corner. */
for (size_t y = 0; y < AMS_LOGO_HEIGHT; y++) {
for (size_t x = 0; x < AMS_LOGO_WIDTH; x++) {
tiled_buf[GetPixelOffset(FatalScreenWidth - AMS_LOGO_WIDTH - 32 + x, 32 + y)] = AMS_LOGO_BIN[y * AMS_LOGO_WIDTH + x];
}
}
/* TODO: Actually draw meaningful shit here. */
FontManager::SetPosition(32, 64);
FontManager::SetFontSize(16.0f);
FontManager::PrintFormat(config->error_msg, R_MODULE(this->ctx->error_code), R_DESCRIPTION(this->ctx->error_code), this->ctx->error_code);
FontManager::AddSpacingLines(0.5f);
FontManager::PrintFormatLine("Title: %016lX", this->title_id);
FontManager::AddSpacingLines(0.5f);
FontManager::PrintFormatLine(u8"Firmware: %s (Atmosphère %u.%u.%u-%s)", GetFatalConfig()->firmware_version.display_version, CURRENT_ATMOSPHERE_VERSION, GetAtmosphereGitRevision());
FontManager::AddSpacingLines(1.5f);
if (this->ctx->error_code != ResultAtmosphereVersionMismatch) {
FontManager::Print(config->error_desc);
} else {
/* Print a special message for atmosphere version mismatch. */
FontManager::Print(u8"Atmosphère version mismatch detected.\n\n"
u8"Please press the POWER Button to restart the console normally, or a VOL button\n"
u8"to reboot to a payload (or RCM, if none is present). If you are unable to\n"
u8"restart the console, hold the POWER Button for 12 seconds to turn the console off.\n\n"
u8"Please ensure that all Atmosphère components are updated.\n"
u8"github.com/Atmosphere-NX/Atmosphere/releases\n");
}
/* Add a line. */
for (size_t x = 32; x < FatalScreenWidth - 32; x++) {
tiled_buf[GetPixelOffset(x, FontManager::GetY())] = 0xFFFF;
}
FontManager::AddSpacingLines(1.5f);
u32 backtrace_y = FontManager::GetY();
u32 backtrace_x = 0;
/* Print GPRs. */
FontManager::SetFontSize(14.0f);
FontManager::Print("General Purpose Registers ");
{
FontManager::SetPosition(FontManager::GetX() + 2, FontManager::GetY());
u32 x = FontManager::GetX();
FontManager::Print("PC: ");
FontManager::SetPosition(x + 47, FontManager::GetY());
}
if (this->ctx->cpu_ctx.is_aarch32) {
FontManager::PrintMonospaceU32(this->ctx->cpu_ctx.aarch32_ctx.pc);
} else {
FontManager::PrintMonospaceU64(this->ctx->cpu_ctx.aarch64_ctx.pc);
}
FontManager::PrintLine("");
FontManager::SetPosition(32, FontManager::GetY());
FontManager::AddSpacingLines(0.5f);
if (this->ctx->cpu_ctx.is_aarch32) {
for (size_t i = 0; i < (NumAarch32Gprs / 2); i++) {
u32 x = FontManager::GetX();
FontManager::PrintFormat("%s:", Aarch32GprNames[i]);
FontManager::SetPosition(x + 47, FontManager::GetY());
if (this->ctx->has_gprs[i]) {
FontManager::PrintMonospaceU32(this->ctx->cpu_ctx.aarch32_ctx.r[i]);
/* TODO: Actually draw meaningful shit here. */
font::SetPosition(32, 64);
font::SetFontSize(16.0f);
font::PrintFormat(config.GetErrorMessage(), R_MODULE(this->context->error_code), R_DESCRIPTION(this->context->error_code), this->context->error_code);
font::AddSpacingLines(0.5f);
font::PrintFormatLine("Title: %016lX", static_cast<u64>(this->context->title_id));
font::AddSpacingLines(0.5f);
font::PrintFormatLine(u8"Firmware: %s (Atmosphère %u.%u.%u-%s)", config.GetFirmwareVersion().display_version, CURRENT_ATMOSPHERE_VERSION, GetAtmosphereGitRevision());
font::AddSpacingLines(1.5f);
if (this->context->error_code != ResultAtmosphereVersionMismatch) {
font::Print(config.GetErrorDescription());
} else {
FontManager::PrintMonospaceBlank(8);
/* Print a special message for atmosphere version mismatch. */
font::Print(u8"Atmosphère version mismatch detected.\n\n"
u8"Please press the POWER Button to restart the console normally, or a VOL button\n"
u8"to reboot to a payload (or RCM, if none is present). If you are unable to\n"
u8"restart the console, hold the POWER Button for 12 seconds to turn the console off.\n\n"
u8"Please ensure that all Atmosphère components are updated.\n"
u8"github.com/Atmosphere-NX/Atmosphere/releases\n");
}
FontManager::Print(" ");
x = FontManager::GetX();
FontManager::PrintFormat("%s:", Aarch32GprNames[i + (NumAarch32Gprs / 2)]);
FontManager::SetPosition(x + 47, FontManager::GetY());
if (this->ctx->has_gprs[i + (NumAarch32Gprs / 2)]) {
FontManager::PrintMonospaceU32(this->ctx->cpu_ctx.aarch32_ctx.r[i + (NumAarch32Gprs / 2)]);
/* Add a line. */
for (size_t x = 32; x < FatalScreenWidth - 32; x++) {
tiled_buf[GetPixelOffset(x, font::GetY())] = 0xFFFF;
}
font::AddSpacingLines(1.5f);
u32 backtrace_y = font::GetY();
u32 backtrace_x = 0;
/* Note architecutre. */
const bool is_aarch32 = this->context->cpu_ctx.architecture == CpuContext::Architecture_Aarch32;
/* Print GPRs. */
font::SetFontSize(14.0f);
font::Print("General Purpose Registers ");
{
font::SetPosition(font::GetX() + 2, font::GetY());
u32 x = font::GetX();
font::Print("PC: ");
font::SetPosition(x + 47, font::GetY());
}
if (is_aarch32) {
font::PrintMonospaceU32(this->context->cpu_ctx.aarch32_ctx.pc);
} else {
FontManager::PrintMonospaceBlank(8);
font::PrintMonospaceU64(this->context->cpu_ctx.aarch64_ctx.pc);
}
font::PrintLine("");
font::SetPosition(32, font::GetY());
font::AddSpacingLines(0.5f);
if (is_aarch32) {
for (size_t i = 0; i < (aarch32::RegisterName_GeneralPurposeCount / 2); i++) {
u32 x = font::GetX();
font::PrintFormat("%s:", aarch32::CpuContext::RegisterNameStrings[i]);
font::SetPosition(x + 47, font::GetY());
if (this->context->cpu_ctx.aarch32_ctx.HasRegisterValue(static_cast<aarch32::RegisterName>(i))) {
font::PrintMonospaceU32(this->context->cpu_ctx.aarch32_ctx.r[i]);
} else {
font::PrintMonospaceBlank(8);
}
font::Print(" ");
x = font::GetX();
font::PrintFormat("%s:", aarch32::CpuContext::RegisterNameStrings[i + (aarch32::RegisterName_GeneralPurposeCount / 2)]);
font::SetPosition(x + 47, font::GetY());
if (this->context->cpu_ctx.aarch32_ctx.HasRegisterValue(static_cast<aarch32::RegisterName>(i + (aarch32::RegisterName_GeneralPurposeCount / 2)))) {
font::PrintMonospaceU32(this->context->cpu_ctx.aarch32_ctx.r[i + (aarch32::RegisterName_GeneralPurposeCount / 2)]);
} else {
font::PrintMonospaceBlank(8);
}
if (i == (aarch32::RegisterName_GeneralPurposeCount / 2) - 1) {
font::Print(" ");
backtrace_x = font::GetX();
}
font::PrintLine("");
font::SetPosition(32, font::GetY());
}
} else {
for (size_t i = 0; i < aarch64::RegisterName_GeneralPurposeCount / 2; i++) {
u32 x = font::GetX();
font::PrintFormat("%s:", aarch64::CpuContext::RegisterNameStrings[i]);
font::SetPosition(x + 47, font::GetY());
if (this->context->cpu_ctx.aarch64_ctx.HasRegisterValue(static_cast<aarch64::RegisterName>(i))) {
font::PrintMonospaceU64(this->context->cpu_ctx.aarch64_ctx.x[i]);
} else {
font::PrintMonospaceBlank(16);
}
font::Print(" ");
x = font::GetX();
font::PrintFormat("%s:", aarch64::CpuContext::RegisterNameStrings[i + (aarch64::RegisterName_GeneralPurposeCount / 2)]);
font::SetPosition(x + 47, font::GetY());
if (this->context->cpu_ctx.aarch64_ctx.HasRegisterValue(static_cast<aarch64::RegisterName>(i + (aarch64::RegisterName_GeneralPurposeCount / 2)))) {
font::PrintMonospaceU64(this->context->cpu_ctx.aarch64_ctx.x[i + (aarch64::RegisterName_GeneralPurposeCount / 2)]);
} else {
font::PrintMonospaceBlank(16);
}
if (i == (aarch64::RegisterName_GeneralPurposeCount / 2) - 1) {
font::Print(" ");
backtrace_x = font::GetX();
}
font::PrintLine("");
font::SetPosition(32, font::GetY());
}
}
if (i == (NumAarch32Gprs / 2) - 1) {
FontManager::Print(" ");
backtrace_x = FontManager::GetX();
/* Print Backtrace. */
u32 bt_size;
if (is_aarch32) {
bt_size = this->context->cpu_ctx.aarch32_ctx.stack_trace_size;
} else {
bt_size = this->context->cpu_ctx.aarch64_ctx.stack_trace_size;
}
FontManager::PrintLine("");
FontManager::SetPosition(32, FontManager::GetY());
font::SetPosition(backtrace_x, backtrace_y);
if (bt_size == 0) {
if (is_aarch32) {
font::Print("Start Address: ");
font::PrintMonospaceU32(this->context->cpu_ctx.aarch32_ctx.base_address);
font::PrintLine("");
} else {
font::Print("Start Address: ");
font::PrintMonospaceU64(this->context->cpu_ctx.aarch64_ctx.base_address);
font::PrintLine("");
}
} else {
if (is_aarch32) {
font::Print("Backtrace - Start Address: ");
font::PrintMonospaceU32(this->context->cpu_ctx.aarch32_ctx.base_address);
font::PrintLine("");
font::AddSpacingLines(0.5f);
for (u32 i = 0; i < aarch32::CpuContext::MaxStackTraceDepth / 2; i++) {
u32 bt_cur = 0, bt_next = 0;
if (i < this->context->cpu_ctx.aarch32_ctx.stack_trace_size) {
bt_cur = this->context->cpu_ctx.aarch32_ctx.stack_trace[i];
}
if (i + aarch32::CpuContext::MaxStackTraceDepth / 2 < this->context->cpu_ctx.aarch32_ctx.stack_trace_size) {
bt_next = this->context->cpu_ctx.aarch32_ctx.stack_trace[i + aarch32::CpuContext::MaxStackTraceDepth / 2];
}
if (i < this->context->cpu_ctx.aarch32_ctx.stack_trace_size) {
u32 x = font::GetX();
font::PrintFormat("BT[%02d]: ", i);
font::SetPosition(x + 72, font::GetY());
font::PrintMonospaceU32(bt_cur);
font::Print(" ");
}
if (i + aarch32::CpuContext::MaxStackTraceDepth / 2 < this->context->cpu_ctx.aarch32_ctx.stack_trace_size) {
u32 x = font::GetX();
font::PrintFormat("BT[%02d]: ", i + aarch32::CpuContext::MaxStackTraceDepth / 2);
font::SetPosition(x + 72, font::GetY());
font::PrintMonospaceU32(bt_next);
}
font::PrintLine("");
font::SetPosition(backtrace_x, font::GetY());
}
} else {
font::Print("Backtrace - Start Address: ");
font::PrintMonospaceU64(this->context->cpu_ctx.aarch64_ctx.base_address);
font::PrintLine("");
font::AddSpacingLines(0.5f);
for (u32 i = 0; i < aarch64::CpuContext::MaxStackTraceDepth / 2; i++) {
u64 bt_cur = 0, bt_next = 0;
if (i < this->context->cpu_ctx.aarch64_ctx.stack_trace_size) {
bt_cur = this->context->cpu_ctx.aarch64_ctx.stack_trace[i];
}
if (i + aarch64::CpuContext::MaxStackTraceDepth / 2 < this->context->cpu_ctx.aarch64_ctx.stack_trace_size) {
bt_next = this->context->cpu_ctx.aarch64_ctx.stack_trace[i + aarch64::CpuContext::MaxStackTraceDepth / 2];
}
if (i < this->context->cpu_ctx.aarch64_ctx.stack_trace_size) {
u32 x = font::GetX();
font::PrintFormat("BT[%02d]: ", i);
font::SetPosition(x + 72, font::GetY());
font::PrintMonospaceU64(bt_cur);
font::Print(" ");
}
if (i + aarch64::CpuContext::MaxStackTraceDepth / 2 < this->context->cpu_ctx.aarch64_ctx.stack_trace_size) {
u32 x = font::GetX();
font::PrintFormat("BT[%02d]: ", i + aarch64::CpuContext::MaxStackTraceDepth / 2);
font::SetPosition(x + 72, font::GetY());
font::PrintMonospaceU64(bt_next);
}
font::PrintLine("");
font::SetPosition(backtrace_x, font::GetY());
}
}
}
/* Enqueue the buffer. */
framebufferEnd(&fb);
return ResultSuccess;
}
} else {
for (size_t i = 0; i < NumAarch64Gprs / 2; i++) {
u32 x = FontManager::GetX();
FontManager::PrintFormat("%s:", Aarch64GprNames[i]);
FontManager::SetPosition(x + 47, FontManager::GetY());
if (this->ctx->has_gprs[i]) {
FontManager::PrintMonospaceU64(this->ctx->cpu_ctx.aarch64_ctx.x[i]);
} else {
FontManager::PrintMonospaceBlank(16);
}
FontManager::Print(" ");
x = FontManager::GetX();
FontManager::PrintFormat("%s:", Aarch64GprNames[i + (NumAarch64Gprs / 2)]);
FontManager::SetPosition(x + 47, FontManager::GetY());
if (this->ctx->has_gprs[i + (NumAarch64Gprs / 2)]) {
FontManager::PrintMonospaceU64(this->ctx->cpu_ctx.aarch64_ctx.x[i + (NumAarch64Gprs / 2)]);
} else {
FontManager::PrintMonospaceBlank(16);
}
if (i == (NumAarch64Gprs / 2) - 1) {
FontManager::Print(" ");
backtrace_x = FontManager::GetX();
}
Result ShowFatalTask::Run() {
/* Don't show the fatal error screen until we've verified the battery is okay. */
eventWait(const_cast<Event *>(&this->context->battery_event), U64_MAX);
FontManager::PrintLine("");
FontManager::SetPosition(32, FontManager::GetY());
return ShowFatal();
}
void BacklightControlTask::TurnOnBacklight() {
lblSwitchBacklightOn(0);
}
Result BacklightControlTask::Run() {
TurnOnBacklight();
return ResultSuccess;
}
}
/* Print Backtrace. */
u32 bt_size;
if (this->ctx->cpu_ctx.is_aarch32) {
bt_size = this->ctx->cpu_ctx.aarch32_ctx.stack_trace_size;
} else {
bt_size = this->ctx->cpu_ctx.aarch64_ctx.stack_trace_size;
ITask *GetShowFatalTask(const ThrowContext *ctx) {
g_show_fatal_task.Initialize(ctx);
return &g_show_fatal_task;
}
FontManager::SetPosition(backtrace_x, backtrace_y);
if (bt_size == 0) {
if (this->ctx->cpu_ctx.is_aarch32) {
FontManager::Print("Start Address: ");
FontManager::PrintMonospaceU32(this->ctx->cpu_ctx.aarch32_ctx.start_address);
FontManager::PrintLine("");
} else {
FontManager::Print("Start Address: ");
FontManager::PrintMonospaceU64(this->ctx->cpu_ctx.aarch64_ctx.start_address);
FontManager::PrintLine("");
}
} else {
if (this->ctx->cpu_ctx.is_aarch32) {
FontManager::Print("Backtrace - Start Address: ");
FontManager::PrintMonospaceU32(this->ctx->cpu_ctx.aarch32_ctx.start_address);
FontManager::PrintLine("");
FontManager::AddSpacingLines(0.5f);
for (u32 i = 0; i < Aarch32CpuContext::MaxStackTraceDepth / 2; i++) {
u32 bt_cur = 0, bt_next = 0;
if (i < this->ctx->cpu_ctx.aarch32_ctx.stack_trace_size) {
bt_cur = this->ctx->cpu_ctx.aarch32_ctx.stack_trace[i];
}
if (i + Aarch32CpuContext::MaxStackTraceDepth / 2 < this->ctx->cpu_ctx.aarch32_ctx.stack_trace_size) {
bt_next = this->ctx->cpu_ctx.aarch32_ctx.stack_trace[i + Aarch32CpuContext::MaxStackTraceDepth / 2];
}
if (i < this->ctx->cpu_ctx.aarch32_ctx.stack_trace_size) {
u32 x = FontManager::GetX();
FontManager::PrintFormat("BT[%02d]: ", i);
FontManager::SetPosition(x + 72, FontManager::GetY());
FontManager::PrintMonospaceU32(bt_cur);
FontManager::Print(" ");
}
if (i + Aarch32CpuContext::MaxStackTraceDepth / 2 < this->ctx->cpu_ctx.aarch32_ctx.stack_trace_size) {
u32 x = FontManager::GetX();
FontManager::PrintFormat("BT[%02d]: ", i + Aarch32CpuContext::MaxStackTraceDepth / 2);
FontManager::SetPosition(x + 72, FontManager::GetY());
FontManager::PrintMonospaceU32(bt_next);
}
FontManager::PrintLine("");
FontManager::SetPosition(backtrace_x, FontManager::GetY());
}
} else {
FontManager::Print("Backtrace - Start Address: ");
FontManager::PrintMonospaceU64(this->ctx->cpu_ctx.aarch64_ctx.start_address);
FontManager::PrintLine("");
FontManager::AddSpacingLines(0.5f);
for (u32 i = 0; i < Aarch64CpuContext::MaxStackTraceDepth / 2; i++) {
u64 bt_cur = 0, bt_next = 0;
if (i < this->ctx->cpu_ctx.aarch64_ctx.stack_trace_size) {
bt_cur = this->ctx->cpu_ctx.aarch64_ctx.stack_trace[i];
}
if (i + Aarch64CpuContext::MaxStackTraceDepth / 2 < this->ctx->cpu_ctx.aarch64_ctx.stack_trace_size) {
bt_next = this->ctx->cpu_ctx.aarch64_ctx.stack_trace[i + Aarch64CpuContext::MaxStackTraceDepth / 2];
}
if (i < this->ctx->cpu_ctx.aarch64_ctx.stack_trace_size) {
u32 x = FontManager::GetX();
FontManager::PrintFormat("BT[%02d]: ", i);
FontManager::SetPosition(x + 72, FontManager::GetY());
FontManager::PrintMonospaceU64(bt_cur);
FontManager::Print(" ");
}
if (i + Aarch64CpuContext::MaxStackTraceDepth / 2 < this->ctx->cpu_ctx.aarch64_ctx.stack_trace_size) {
u32 x = FontManager::GetX();
FontManager::PrintFormat("BT[%02d]: ", i + Aarch64CpuContext::MaxStackTraceDepth / 2);
FontManager::SetPosition(x + 72, FontManager::GetY());
FontManager::PrintMonospaceU64(bt_next);
}
FontManager::PrintLine("");
FontManager::SetPosition(backtrace_x, FontManager::GetY());
}
}
ITask *GetBacklightControlTask(const ThrowContext *ctx) {
g_backlight_control_task.Initialize(ctx);
return &g_backlight_control_task;
}
/* Enqueue the buffer. */
framebufferEnd(&fb);
return ResultSuccess;
}
Result ShowFatalTask::Run() {
/* Don't show the fatal error screen until we've verified the battery is okay. */
eventWait(this->battery_event, U64_MAX);
return ShowFatal();
}
void BacklightControlTask::TurnOnBacklight() {
lblSwitchBacklightOn(0);
}
Result BacklightControlTask::Run() {
TurnOnBacklight();
return ResultSuccess;
}