exo/meso/fusee: support dynamic control of log port/baud rate

This commit is contained in:
Michael Scire 2020-12-07 19:25:06 -08:00
parent 121c981bb4
commit 2de85c633a
17 changed files with 183 additions and 99 deletions

View file

@ -35,6 +35,14 @@
# mmc space, encrypted to prevent detection. This backup can be used # mmc space, encrypted to prevent detection. This backup can be used
# to prevent unrecoverable edits in emergencies. # to prevent unrecoverable edits in emergencies.
# Key: log_port, default: 0.
# Desc: Controls what uart port exosphere will set up for logging.
# NOTE: 0 = UART-A, 1 = UART-B, 2 = UART-C, 3 = UART-D
# Key: log_baud_rate, default: 115200
# Desc: Controls the baud rate exosphere will set up for logging.
# NOTE: 0 is treated as equivalent to 115200.
[exosphere] [exosphere]
debugmode=1 debugmode=1
debugmode_user=0 debugmode_user=0
@ -43,3 +51,5 @@ enable_user_pmu_access=0
blank_prodinfo_sysmmc=0 blank_prodinfo_sysmmc=0
blank_prodinfo_emummc=0 blank_prodinfo_emummc=0
allow_writing_to_cal_sysmmc=0 allow_writing_to_cal_sysmmc=0
log_port=0
log_baud_rate=115200

View file

@ -960,7 +960,7 @@ namespace ams::secmon {
} }
void SetupLogForBoot() { void SetupLogForBoot() {
log::Initialize(); log::Initialize(secmon::GetLogPort(), secmon::GetLogBaudRate());
log::SendText("OHAYO\n", 6); log::SendText("OHAYO\n", 6);
log::Flush(); log::Flush();
} }

View file

@ -282,6 +282,10 @@ namespace ams::secmon::smc {
return SmcResult::NotInitialized; return SmcResult::NotInitialized;
} }
break; break;
case ConfigItem::ExosphereLogConfiguration:
/* Get the log configuration. */
args.r[1] = (static_cast<u64>(static_cast<u8>(secmon::GetLogPort())) << 32) | static_cast<u64>(secmon::GetLogBaudRate());
break;
default: default:
return SmcResult::InvalidArgument; return SmcResult::InvalidArgument;
} }

View file

@ -40,15 +40,16 @@ namespace ams::secmon::smc {
Package2Hash = 17, Package2Hash = 17,
/* Extension config items for exosphere. */ /* Extension config items for exosphere. */
ExosphereApiVersion = 65000, ExosphereApiVersion = 65000,
ExosphereNeedsReboot = 65001, ExosphereNeedsReboot = 65001,
ExosphereNeedsShutdown = 65002, ExosphereNeedsShutdown = 65002,
ExosphereGitCommitHash = 65003, ExosphereGitCommitHash = 65003,
ExosphereHasRcmBugPatch = 65004, ExosphereHasRcmBugPatch = 65004,
ExosphereBlankProdInfo = 65005, ExosphereBlankProdInfo = 65005,
ExosphereAllowCalWrites = 65006, ExosphereAllowCalWrites = 65006,
ExosphereEmummcType = 65007, ExosphereEmummcType = 65007,
ExospherePayloadAddress = 65008, ExospherePayloadAddress = 65008,
ExosphereLogConfiguration = 65009,
}; };
SmcResult SmcGetConfigUser(SmcArguments &args); SmcResult SmcGetConfigUser(SmcArguments &args);

View file

@ -409,6 +409,7 @@ namespace ams::secmon::smc {
/* NOTE: Nintendo only does this on dev, but we will always do it. */ /* NOTE: Nintendo only does this on dev, but we will always do it. */
if (true /* !pkg1::IsProduction() */) { if (true /* !pkg1::IsProduction() */) {
log::SendText("OYASUMI\n", 8); log::SendText("OYASUMI\n", 8);
log::Flush();
} }
/* If we're on erista, configure the bootrom to allow our custom warmboot firmware. */ /* If we're on erista, configure the bootrom to allow our custom warmboot firmware. */

View file

@ -37,8 +37,12 @@
typedef struct { typedef struct {
uint32_t magic; uint32_t magic;
uint32_t target_firmware; uint32_t target_firmware;
uint32_t flags; uint32_t flags[2];
uint32_t reserved[5]; uint16_t lcd_vendor;
uint8_t reserved0;
uint8_t log_port;
uint32_t log_baud_rate;
uint32_t reserved1[2];
exo_emummc_config_t emummc_cfg; exo_emummc_config_t emummc_cfg;
} exosphere_config_t; } exosphere_config_t;
@ -54,6 +58,8 @@ _Static_assert(sizeof(exosphere_config_t) == 0x20 + sizeof(exo_emummc_config_t),
#define EXOSPHERE_BLANK_PRODINFO_SYSMMC_KEY "blank_prodinfo_sysmmc" #define EXOSPHERE_BLANK_PRODINFO_SYSMMC_KEY "blank_prodinfo_sysmmc"
#define EXOSPHERE_BLANK_PRODINFO_EMUMMC_KEY "blank_prodinfo_emummc" #define EXOSPHERE_BLANK_PRODINFO_EMUMMC_KEY "blank_prodinfo_emummc"
#define EXOSPHERE_ALLOW_WRITING_TO_CAL_SYSMMC_KEY "allow_writing_to_cal_sysmmc" #define EXOSPHERE_ALLOW_WRITING_TO_CAL_SYSMMC_KEY "allow_writing_to_cal_sysmmc"
#define EXOSPHERE_LOG_PORT_KEY "log_port"
#define EXOSPHERE_LOG_BAUD_RATE_KEY "log_baud_rate"
typedef struct { typedef struct {
int debugmode; int debugmode;
@ -63,6 +69,8 @@ typedef struct {
int blank_prodinfo_sysmmc; int blank_prodinfo_sysmmc;
int blank_prodinfo_emummc; int blank_prodinfo_emummc;
int allow_writing_to_cal_sysmmc; int allow_writing_to_cal_sysmmc;
int log_port;
int log_baud_rate;
} exosphere_parse_cfg_t; } exosphere_parse_cfg_t;
#endif #endif

View file

@ -196,6 +196,20 @@ static int exosphere_ini_handler(void *user, const char *section, const char *na
} else if (tmp == 0) { } else if (tmp == 0) {
parse_cfg->allow_writing_to_cal_sysmmc = 0; parse_cfg->allow_writing_to_cal_sysmmc = 0;
} }
} else if (strcmp(name, EXOSPHERE_LOG_PORT_KEY) == 0) {
sscanf(value, "%d", &tmp);
if (0 <= tmp && tmp < 4) {
parse_cfg->log_port = tmp;
} else {
parse_cfg->log_port = 0;
}
} else if (strcmp(name, EXOSPHERE_LOG_BAUD_RATE_KEY) == 0) {
sscanf(value, "%d", &tmp);
if (tmp > 0) {
parse_cfg->log_baud_rate = tmp;
} else {
parse_cfg->log_baud_rate = 115200;
}
} else { } else {
return 0; return 0;
} }
@ -478,6 +492,8 @@ static void nxboot_configure_exosphere(uint32_t target_firmware, unsigned int ke
.blank_prodinfo_sysmmc = 0, .blank_prodinfo_sysmmc = 0,
.blank_prodinfo_emummc = 0, .blank_prodinfo_emummc = 0,
.allow_writing_to_cal_sysmmc = 0, .allow_writing_to_cal_sysmmc = 0,
.log_port = 0,
.log_baud_rate = 115200,
}; };
/* If we have an ini to read, parse it. */ /* If we have an ini to read, parse it. */
@ -498,6 +514,9 @@ static void nxboot_configure_exosphere(uint32_t target_firmware, unsigned int ke
if (parse_cfg.blank_prodinfo_emummc && is_emummc) exo_cfg.flags |= EXOSPHERE_FLAG_BLANK_PRODINFO; if (parse_cfg.blank_prodinfo_emummc && is_emummc) exo_cfg.flags |= EXOSPHERE_FLAG_BLANK_PRODINFO;
if (parse_cfg.allow_writing_to_cal_sysmmc) exo_cfg.flags |= EXOSPHERE_FLAG_ALLOW_WRITING_TO_CAL_SYSMMC; if (parse_cfg.allow_writing_to_cal_sysmmc) exo_cfg.flags |= EXOSPHERE_FLAG_ALLOW_WRITING_TO_CAL_SYSMMC;
exo_cfg.log_port = parse_cfg.log_port;
exo_cfg.log_baud_rate = parse_cfg.log_baud_rate;
if ((exo_cfg.target_firmware < ATMOSPHERE_TARGET_FIRMWARE_MIN) || (exo_cfg.target_firmware > ATMOSPHERE_TARGET_FIRMWARE_MAX)) { if ((exo_cfg.target_firmware < ATMOSPHERE_TARGET_FIRMWARE_MIN) || (exo_cfg.target_firmware > ATMOSPHERE_TARGET_FIRMWARE_MAX)) {
fatal_error("[NXBOOT] Invalid Exosphere target firmware!\n"); fatal_error("[NXBOOT] Invalid Exosphere target firmware!\n");
} }

View file

@ -35,6 +35,7 @@ namespace ams::log {
#endif #endif
void Initialize(); void Initialize();
void Initialize(uart::Port port, u32 baud_rate);
void Finalize(); void Finalize();
void Printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); void Printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));

View file

@ -116,6 +116,14 @@ namespace ams::secmon {
return GetSecmonConfiguration().GetLcdVendor(); return GetSecmonConfiguration().GetLcdVendor();
} }
ALWAYS_INLINE uart::Port GetLogPort() {
return GetSecmonConfiguration().GetLogPort();
}
ALWAYS_INLINE u32 GetLogBaudRate() {
return GetSecmonConfiguration().GetLogBaudRate();
}
ALWAYS_INLINE bool IsProduction() { ALWAYS_INLINE bool IsProduction() {
return GetSecmonConfiguration().IsProduction(); return GetSecmonConfiguration().IsProduction();
} }

View file

@ -16,6 +16,7 @@
#pragma once #pragma once
#include <vapours.hpp> #include <vapours.hpp>
#include <exosphere/fuse.hpp> #include <exosphere/fuse.hpp>
#include <exosphere/uart.hpp>
#include <exosphere/secmon/secmon_emummc_context.hpp> #include <exosphere/secmon/secmon_emummc_context.hpp>
namespace ams::secmon { namespace ams::secmon {
@ -39,8 +40,10 @@ namespace ams::secmon {
ams::TargetFirmware target_firmware; ams::TargetFirmware target_firmware;
u32 flags[2]; u32 flags[2];
u16 lcd_vendor; u16 lcd_vendor;
u16 reserved0; u8 reserved0;
u32 reserved1[3]; u8 log_port;
u32 log_baud_rate;
u32 reserved1[2];
EmummcConfiguration emummc_cfg; EmummcConfiguration emummc_cfg;
constexpr bool IsValid() const { return this->magic == Magic; } constexpr bool IsValid() const { return this->magic == Magic; }
@ -54,17 +57,20 @@ namespace ams::secmon {
u8 hardware_type; u8 hardware_type;
u8 soc_type; u8 soc_type;
u8 hardware_state; u8 hardware_state;
u8 pad_0B[1]; u8 log_port;
u32 flags[2]; u32 flags[2];
u16 lcd_vendor; u16 lcd_vendor;
u16 reserved0; u16 reserved0;
u32 reserved1[(0x80 - 0x18) / sizeof(u32)]; u32 log_baud_rate;
u32 reserved1[(0x80 - 0x1C) / sizeof(u32)];
constexpr void CopyFrom(const SecureMonitorStorageConfiguration &storage) { constexpr void CopyFrom(const SecureMonitorStorageConfiguration &storage) {
this->target_firmware = storage.target_firmware; this->target_firmware = storage.target_firmware;
this->flags[0] = storage.flags[0]; this->flags[0] = storage.flags[0];
this->flags[1] = storage.flags[1]; this->flags[1] = storage.flags[1];
this->lcd_vendor = storage.lcd_vendor; this->lcd_vendor = storage.lcd_vendor;
this->log_port = storage.log_port;
this->log_baud_rate = storage.log_baud_rate != 0 ? storage.log_baud_rate : 115200;
} }
void SetFuseInfo() { void SetFuseInfo() {
@ -78,9 +84,12 @@ namespace ams::secmon {
constexpr fuse::HardwareType GetHardwareType() const { return static_cast<fuse::HardwareType>(this->hardware_type); } constexpr fuse::HardwareType GetHardwareType() const { return static_cast<fuse::HardwareType>(this->hardware_type); }
constexpr fuse::SocType GetSocType() const { return static_cast<fuse::SocType>(this->soc_type); } constexpr fuse::SocType GetSocType() const { return static_cast<fuse::SocType>(this->soc_type); }
constexpr fuse::HardwareState GetHardwareState() const { return static_cast<fuse::HardwareState>(this->hardware_state); } constexpr fuse::HardwareState GetHardwareState() const { return static_cast<fuse::HardwareState>(this->hardware_state); }
constexpr uart::Port GetLogPort() const { return static_cast<uart::Port>(this->log_port); }
constexpr u16 GetLcdVendor() const { return this->lcd_vendor; } constexpr u16 GetLcdVendor() const { return this->lcd_vendor; }
constexpr u32 GetLogBaudRate() const { return this->log_baud_rate; }
constexpr bool IsProduction() const { return this->GetHardwareState() != fuse::HardwareState_Development; } constexpr bool IsProduction() const { return this->GetHardwareState() != fuse::HardwareState_Development; }
constexpr bool IsDevelopmentFunctionEnabledForKernel() const { return (this->flags[0] & SecureMonitorConfigurationFlag_IsDevelopmentFunctionEnabledForKernel) != 0; } constexpr bool IsDevelopmentFunctionEnabledForKernel() const { return (this->flags[0] & SecureMonitorConfigurationFlag_IsDevelopmentFunctionEnabledForKernel) != 0; }
@ -101,10 +110,11 @@ namespace ams::secmon {
.hardware_type = {}, .hardware_type = {},
.soc_type = {}, .soc_type = {},
.hardware_state = {}, .hardware_state = {},
.pad_0B = {}, .log_port = uart::Port_ReservedDebug,
.flags = { SecureMonitorConfigurationFlag_Default, SecureMonitorConfigurationFlag_None }, .flags = { SecureMonitorConfigurationFlag_Default, SecureMonitorConfigurationFlag_None },
.lcd_vendor = {}, .lcd_vendor = {},
.reserved0 = {}, .reserved0 = {},
.log_baud_rate = 115200,
.reserved1 = {}, .reserved1 = {},
}; };

View file

@ -19,58 +19,63 @@ namespace ams::log {
namespace { namespace {
constexpr inline uart::Port UartLogPort = uart::Port_ReservedDebug; constexpr inline uart::Port DefaultLogPort = uart::Port_ReservedDebug;
constexpr inline int UartBaudRate = 115200; constexpr inline int DefaultBaudRate = 115200;
constinit uart::Port g_log_port = DefaultLogPort;
constinit bool g_initialized_uart = false; constinit bool g_initialized_uart = false;
constexpr inline u32 UartPortFlags = [] { ALWAYS_INLINE u32 GetPortFlags(uart::Port port) {
if constexpr (UartLogPort == uart::Port_ReservedDebug) { switch (port) {
/* Logging to the debug port. */ case uart::Port_ReservedDebug:
/* Don't invert transactions. */ /* Logging to the debug port. */
return uart::Flag_None; /* Don't invert transactions. */
} else if constexpr (UartLogPort == uart::Port_LeftJoyCon) { return uart::Flag_None;
/* Logging to left joy-con (e.g. with Joyless). */ case uart::Port_LeftJoyCon:
/* Invert transactions. */ /* Logging to left joy-con (e.g. with Joyless). */
return uart::Flag_Inverted; /* Invert transactions. */
} else if constexpr (UartLogPort == uart::Port_RightJoyCon) { return uart::Flag_Inverted;
/* Logging to right joy-con (e.g. with Joyless). */ case uart::Port_RightJoyCon:
/* Invert transactions. */ /* Logging to right joy-con (e.g. with Joyless). */
return uart::Flag_Inverted; /* Invert transactions. */
} else { return uart::Flag_Inverted;
__builtin_unreachable(); AMS_UNREACHABLE_DEFAULT_CASE();
} }
}(); }
ALWAYS_INLINE void SetupUart() { ALWAYS_INLINE void SetupUartClock(uart::Port port) {
if constexpr (UartLogPort == uart::Port_ReservedDebug) { /* The debug port must always be set up, for compatibility with official hos. */
/* Logging to the debug port. */ pinmux::SetupUartA();
pinmux::SetupUartA(); clkrst::EnableUartAClock();
clkrst::EnableUartAClock();
} else if constexpr (UartLogPort == uart::Port_LeftJoyCon) { /* If logging to a joy-con port, configure appropriately. */
if (port == uart::Port_LeftJoyCon) {
/* Logging to left joy-con (e.g. with Joyless). */ /* Logging to left joy-con (e.g. with Joyless). */
static_assert(uart::Port_LeftJoyCon == uart::Port_C); static_assert(uart::Port_LeftJoyCon == uart::Port_C);
pinmux::SetupUartC(); pinmux::SetupUartC();
clkrst::EnableUartCClock(); clkrst::EnableUartCClock();
} else if constexpr (UartLogPort == uart::Port_RightJoyCon) { } else if (port == uart::Port_RightJoyCon) {
/* Logging to right joy-con (e.g. with Joyless). */ /* Logging to right joy-con (e.g. with Joyless). */
static_assert(uart::Port_RightJoyCon == uart::Port_B); static_assert(uart::Port_RightJoyCon == uart::Port_B);
pinmux::SetupUartB(); pinmux::SetupUartB();
clkrst::EnableUartBClock(); clkrst::EnableUartBClock();
} else {
__builtin_unreachable();
} }
} }
} }
void Initialize() { void Initialize() {
return Initialize(DefaultLogPort, DefaultBaudRate);
}
void Initialize(uart::Port port, u32 baud_rate) {
/* Initialize pinmux and clock for the target uart port. */ /* Initialize pinmux and clock for the target uart port. */
SetupUart(); SetupUartClock(port);
/* Initialize the target uart port. */ /* Initialize the target uart port. */
uart::Initialize(UartLogPort, UartBaudRate, UartPortFlags); uart::Initialize(port, baud_rate, GetPortFlags(port));
/* Note that we've initialized. */ /* Note that we've initialized. */
g_log_port = port;
g_initialized_uart = true; g_initialized_uart = true;
} }
@ -84,7 +89,7 @@ namespace ams::log {
const auto len = util::TVSNPrintf(log_buf, sizeof(log_buf), fmt, vl); const auto len = util::TVSNPrintf(log_buf, sizeof(log_buf), fmt, vl);
if (g_initialized_uart) { if (g_initialized_uart) {
uart::SendText(UartLogPort, log_buf, len); uart::SendText(g_log_port, log_buf, len);
} }
} }
@ -115,13 +120,13 @@ namespace ams::log {
void SendText(const void *text, size_t size) { void SendText(const void *text, size_t size) {
if (g_initialized_uart) { if (g_initialized_uart) {
uart::SendText(UartLogPort, text, size); uart::SendText(g_log_port, text, size);
} }
} }
void Flush() { void Flush() {
if (g_initialized_uart) { if (g_initialized_uart) {
uart::WaitFlush(UartLogPort); uart::WaitFlush(g_log_port);
} }
} }

View file

@ -30,6 +30,7 @@ namespace ams::kern::board::nintendo::nx {
static size_t GetApplicationPoolSize(); static size_t GetApplicationPoolSize();
static size_t GetAppletPoolSize(); static size_t GetAppletPoolSize();
static size_t GetMinimumNonSecureSystemPoolSize(); static size_t GetMinimumNonSecureSystemPoolSize();
static u8 GetDebugLogUartPort();
/* Randomness. */ /* Randomness. */
static void GenerateRandomBytes(void *dst, size_t size); static void GenerateRandomBytes(void *dst, size_t size);

View file

@ -40,7 +40,7 @@ namespace ams::kern {
#ifndef MESOSPHERE_DEBUG_LOG_SELECTED #ifndef MESOSPHERE_DEBUG_LOG_SELECTED
#ifdef ATMOSPHERE_BOARD_NINTENDO_NX #ifdef ATMOSPHERE_BOARD_NINTENDO_NX
#define MESOSPHERE_DEBUG_LOG_USE_UART_A #define MESOSPHERE_DEBUG_LOG_USE_UART
#else #else
#error "Unknown board for Default Debug Log Source" #error "Unknown board for Default Debug Log Source"
#endif #endif

View file

@ -409,6 +409,15 @@ namespace ams::kern::board::nintendo::nx {
return MinimumSize; return MinimumSize;
} }
u8 KSystemControl::Init::GetDebugLogUartPort() {
/* Get the log configuration. */
u64 value = 0;
smc::init::GetConfig(std::addressof(value), 1, smc::ConfigItem::ExosphereLogConfiguration);
/* Extract the port. */
return static_cast<u8>((value >> 32) & 0xFF);
}
void KSystemControl::Init::CpuOn(u64 core_id, uintptr_t entrypoint, uintptr_t arg) { void KSystemControl::Init::CpuOn(u64 core_id, uintptr_t entrypoint, uintptr_t arg) {
smc::init::CpuOn(core_id, entrypoint, arg); smc::init::CpuOn(core_id, entrypoint, arg);
} }

View file

@ -55,15 +55,16 @@ namespace ams::kern::board::nintendo::nx::smc {
Package2Hash = 17, Package2Hash = 17,
/* Extension config items for exosphere. */ /* Extension config items for exosphere. */
ExosphereApiVersion = 65000, ExosphereApiVersion = 65000,
ExosphereNeedsReboot = 65001, ExosphereNeedsReboot = 65001,
ExosphereNeedsShutdown = 65002, ExosphereNeedsShutdown = 65002,
ExosphereGitCommitHash = 65003, ExosphereGitCommitHash = 65003,
ExosphereHasRcmBugPatch = 65004, ExosphereHasRcmBugPatch = 65004,
ExosphereBlankProdInfo = 65005, ExosphereBlankProdInfo = 65005,
ExosphereAllowCalWrites = 65006, ExosphereAllowCalWrites = 65006,
ExosphereEmummcType = 65007, ExosphereEmummcType = 65007,
ExospherePayloadAddress = 65008, ExospherePayloadAddress = 65008,
ExosphereLogConfiguration = 65009,
}; };
enum class SmcResult { enum class SmcResult {

View file

@ -18,10 +18,12 @@
namespace ams::kern { namespace ams::kern {
#if defined(MESOSPHERE_DEBUG_LOG_USE_UART_A) || defined(MESOSPHERE_DEBUG_LOG_USE_UART_B) || defined(MESOSPHERE_DEBUG_LOG_USE_UART_C) || defined(MESOSPHERE_DEBUG_LOG_USE_UART_D) #if defined(MESOSPHERE_DEBUG_LOG_USE_UART)
namespace { namespace {
constexpr bool DoSaveAndRestore = false;
enum UartRegister { enum UartRegister {
UartRegister_THR = 0, UartRegister_THR = 0,
UartRegister_IER = 1, UartRegister_IER = 1,
@ -38,13 +40,13 @@ namespace ams::kern {
KVirtualAddress g_uart_address = 0; KVirtualAddress g_uart_address = 0;
constinit u32 g_saved_registers[5]; [[maybe_unused]] constinit u32 g_saved_registers[5];
NOINLINE u32 ReadUartRegister(UartRegister which) { ALWAYS_INLINE u32 ReadUartRegister(UartRegister which) {
return GetPointer<volatile u32>(g_uart_address)[which]; return GetPointer<volatile u32>(g_uart_address)[which];
} }
NOINLINE void WriteUartRegister(UartRegister which, u32 value) { ALWAYS_INLINE void WriteUartRegister(UartRegister which, u32 value) {
GetPointer<volatile u32>(g_uart_address)[which] = value; GetPointer<volatile u32>(g_uart_address)[which] = value;
} }
@ -86,43 +88,47 @@ namespace ams::kern {
} }
void KDebugLogImpl::Save() { void KDebugLogImpl::Save() {
/* Save LCR, IER, FCR. */ if constexpr (DoSaveAndRestore) {
g_saved_registers[0] = ReadUartRegister(UartRegister_LCR); /* Save LCR, IER, FCR. */
g_saved_registers[1] = ReadUartRegister(UartRegister_IER); g_saved_registers[0] = ReadUartRegister(UartRegister_LCR);
g_saved_registers[2] = ReadUartRegister(UartRegister_FCR); g_saved_registers[1] = ReadUartRegister(UartRegister_IER);
g_saved_registers[2] = ReadUartRegister(UartRegister_FCR);
/* Set Divisor Latch Access bit, to allow access to DLL/DLH */ /* Set Divisor Latch Access bit, to allow access to DLL/DLH */
WriteUartRegister(UartRegister_LCR, 0x80); WriteUartRegister(UartRegister_LCR, 0x80);
ReadUartRegister(UartRegister_LCR); ReadUartRegister(UartRegister_LCR);
/* Save DLL/DLH. */ /* Save DLL/DLH. */
g_saved_registers[3] = ReadUartRegister(UartRegister_DLL); g_saved_registers[3] = ReadUartRegister(UartRegister_DLL);
g_saved_registers[4] = ReadUartRegister(UartRegister_DLH); g_saved_registers[4] = ReadUartRegister(UartRegister_DLH);
/* Restore Divisor Latch Access bit. */ /* Restore Divisor Latch Access bit. */
WriteUartRegister(UartRegister_LCR, g_saved_registers[0]); WriteUartRegister(UartRegister_LCR, g_saved_registers[0]);
ReadUartRegister(UartRegister_LCR); ReadUartRegister(UartRegister_LCR);
}
} }
void KDebugLogImpl::Restore() { void KDebugLogImpl::Restore() {
/* Set Divisor Latch Access bit, to allow access to DLL/DLH */ if constexpr (DoSaveAndRestore) {
WriteUartRegister(UartRegister_LCR, 0x80); /* Set Divisor Latch Access bit, to allow access to DLL/DLH */
ReadUartRegister(UartRegister_LCR); WriteUartRegister(UartRegister_LCR, 0x80);
ReadUartRegister(UartRegister_LCR);
/* Restore DLL/DLH. */ /* Restore DLL/DLH. */
WriteUartRegister(UartRegister_DLL, g_saved_registers[3]); WriteUartRegister(UartRegister_DLL, g_saved_registers[3]);
WriteUartRegister(UartRegister_DLH, g_saved_registers[4]); WriteUartRegister(UartRegister_DLH, g_saved_registers[4]);
ReadUartRegister(UartRegister_DLH); ReadUartRegister(UartRegister_DLH);
/* Restore Divisor Latch Access bit. */ /* Restore Divisor Latch Access bit. */
WriteUartRegister(UartRegister_LCR, g_saved_registers[0]); WriteUartRegister(UartRegister_LCR, g_saved_registers[0]);
ReadUartRegister(UartRegister_LCR); ReadUartRegister(UartRegister_LCR);
/* Restore IER and FCR. */ /* Restore IER and FCR. */
WriteUartRegister(UartRegister_IER, g_saved_registers[1]); WriteUartRegister(UartRegister_IER, g_saved_registers[1]);
WriteUartRegister(UartRegister_FCR, g_saved_registers[2] | 2); WriteUartRegister(UartRegister_FCR, g_saved_registers[2] | 2);
WriteUartRegister(UartRegister_IRDA_CSR, 0x02); WriteUartRegister(UartRegister_IRDA_CSR, 0x02);
ReadUartRegister(UartRegister_FCR); ReadUartRegister(UartRegister_FCR);
}
} }
#elif defined(MESOSPHERE_DEBUG_LOG_USE_IRAM_RINGBUFFER) #elif defined(MESOSPHERE_DEBUG_LOG_USE_IRAM_RINGBUFFER)

View file

@ -26,14 +26,14 @@ namespace ams::kern {
constexpr size_t CarveoutSizeMax = 512_MB - CarveoutAlignment; constexpr size_t CarveoutSizeMax = 512_MB - CarveoutAlignment;
ALWAYS_INLINE bool SetupUartPhysicalMemoryRegion() { ALWAYS_INLINE bool SetupUartPhysicalMemoryRegion() {
#if defined(MESOSPHERE_DEBUG_LOG_USE_UART_A) #if defined(MESOSPHERE_DEBUG_LOG_USE_UART)
return KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x70006000, 0x40, KMemoryRegionType_Uart | KMemoryRegionAttr_ShouldKernelMap); switch (KSystemControl::Init::GetDebugLogUartPort()) {
#elif defined(MESOSPHERE_DEBUG_LOG_USE_UART_B) case 0: return KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x70006000, 0x40, KMemoryRegionType_Uart | KMemoryRegionAttr_ShouldKernelMap);
return KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x70006040, 0x40, KMemoryRegionType_Uart | KMemoryRegionAttr_ShouldKernelMap); case 1: return KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x70006040, 0x40, KMemoryRegionType_Uart | KMemoryRegionAttr_ShouldKernelMap);
#elif defined(MESOSPHERE_DEBUG_LOG_USE_UART_C) case 2: return KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x70006200, 0x100, KMemoryRegionType_Uart | KMemoryRegionAttr_ShouldKernelMap);
return KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x70006200, 0x100, KMemoryRegionType_Uart | KMemoryRegionAttr_ShouldKernelMap); case 3: return KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x70006300, 0x100, KMemoryRegionType_Uart | KMemoryRegionAttr_ShouldKernelMap);
#elif defined(MESOSPHERE_DEBUG_LOG_USE_UART_D) default: return false;
return KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x70006300, 0x100, KMemoryRegionType_Uart | KMemoryRegionAttr_ShouldKernelMap); }
#elif defined(MESOSPHERE_DEBUG_LOG_USE_IRAM_RINGBUFFER) #elif defined(MESOSPHERE_DEBUG_LOG_USE_IRAM_RINGBUFFER)
return true; return true;
#else #else