mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-09 22:56:35 +00:00
exo/meso/fusee: support dynamic control of log port/baud rate
This commit is contained in:
parent
121c981bb4
commit
2de85c633a
17 changed files with 183 additions and 99 deletions
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ namespace ams::secmon::smc {
|
||||||
ExosphereAllowCalWrites = 65006,
|
ExosphereAllowCalWrites = 65006,
|
||||||
ExosphereEmummcType = 65007,
|
ExosphereEmummcType = 65007,
|
||||||
ExospherePayloadAddress = 65008,
|
ExospherePayloadAddress = 65008,
|
||||||
|
ExosphereLogConfiguration = 65009,
|
||||||
};
|
};
|
||||||
|
|
||||||
SmcResult SmcGetConfigUser(SmcArguments &args);
|
SmcResult SmcGetConfigUser(SmcArguments &args);
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)));
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 = {},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
case uart::Port_ReservedDebug:
|
||||||
/* Logging to the debug port. */
|
/* Logging to the debug port. */
|
||||||
/* Don't invert transactions. */
|
/* Don't invert transactions. */
|
||||||
return uart::Flag_None;
|
return uart::Flag_None;
|
||||||
} else if constexpr (UartLogPort == uart::Port_LeftJoyCon) {
|
case uart::Port_LeftJoyCon:
|
||||||
/* Logging to left joy-con (e.g. with Joyless). */
|
/* Logging to left joy-con (e.g. with Joyless). */
|
||||||
/* Invert transactions. */
|
/* Invert transactions. */
|
||||||
return uart::Flag_Inverted;
|
return uart::Flag_Inverted;
|
||||||
} else if constexpr (UartLogPort == uart::Port_RightJoyCon) {
|
case uart::Port_RightJoyCon:
|
||||||
/* Logging to right joy-con (e.g. with Joyless). */
|
/* Logging to right joy-con (e.g. with Joyless). */
|
||||||
/* Invert transactions. */
|
/* Invert transactions. */
|
||||||
return uart::Flag_Inverted;
|
return uart::Flag_Inverted;
|
||||||
} else {
|
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||||
__builtin_unreachable();
|
}
|
||||||
}
|
}
|
||||||
}();
|
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,7 @@ namespace ams::kern::board::nintendo::nx::smc {
|
||||||
ExosphereAllowCalWrites = 65006,
|
ExosphereAllowCalWrites = 65006,
|
||||||
ExosphereEmummcType = 65007,
|
ExosphereEmummcType = 65007,
|
||||||
ExospherePayloadAddress = 65008,
|
ExospherePayloadAddress = 65008,
|
||||||
|
ExosphereLogConfiguration = 65009,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class SmcResult {
|
enum class SmcResult {
|
||||||
|
|
|
@ -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,6 +88,7 @@ namespace ams::kern {
|
||||||
}
|
}
|
||||||
|
|
||||||
void KDebugLogImpl::Save() {
|
void KDebugLogImpl::Save() {
|
||||||
|
if constexpr (DoSaveAndRestore) {
|
||||||
/* Save LCR, IER, FCR. */
|
/* Save LCR, IER, FCR. */
|
||||||
g_saved_registers[0] = ReadUartRegister(UartRegister_LCR);
|
g_saved_registers[0] = ReadUartRegister(UartRegister_LCR);
|
||||||
g_saved_registers[1] = ReadUartRegister(UartRegister_IER);
|
g_saved_registers[1] = ReadUartRegister(UartRegister_IER);
|
||||||
|
@ -103,8 +106,10 @@ namespace ams::kern {
|
||||||
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() {
|
||||||
|
if constexpr (DoSaveAndRestore) {
|
||||||
/* 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);
|
||||||
|
@ -124,6 +129,7 @@ namespace ams::kern {
|
||||||
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)
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue