mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 12:21:18 +00:00
exo: fixes, now tested working on mariko hardware
This commit is contained in:
parent
0a53c74aad
commit
b08ccd7341
8 changed files with 170 additions and 67 deletions
|
@ -48,7 +48,12 @@ namespace ams::secmon::boot {
|
|||
const auto pmc = MemoryRegionVirtualDevicePmc.GetAddress();
|
||||
|
||||
/* Set the physical address of the warmboot binary to scratch 1. */
|
||||
if (GetSocType() == fuse::SocType_Mariko) {
|
||||
reg::Write(pmc + APBDEV_PMC_SECURE_SCRATCH119, static_cast<u32>(MemoryRegionPhysicalDramSecureDataStoreWarmbootFirmware.GetAddress()));
|
||||
} else /* if (GetSocType() == fuse::SocType_Erista) */ {
|
||||
reg::Write(pmc + APBDEV_PMC_SCRATCH1, static_cast<u32>(MemoryRegionPhysicalDramSecureDataStoreWarmbootFirmware.GetAddress()));
|
||||
}
|
||||
|
||||
|
||||
/* Configure logging by setting bits 18-19 of scratch 20. */
|
||||
reg::ReadWrite(pmc + APBDEV_PMC_SCRATCH20, REG_BITS_VALUE(18, 2, 0));
|
||||
|
@ -66,6 +71,7 @@ namespace ams::secmon::boot {
|
|||
/* The warmboot key as a parameter. The latter is a better solution, but it would be nice to take */
|
||||
/* care of it here. Perhaps we should read the number of anti-downgrade fuses burnt, and translate that */
|
||||
/* to the warmboot key? To be decided during the process of implementing ams-on-mariko support. */
|
||||
reg::Write(pmc + APBDEV_PMC_SECURE_SCRATCH32, 0x129);
|
||||
}
|
||||
|
||||
constinit const u8 DeviceMasterKeySourceKekSource[se::AesBlockSize] = {
|
||||
|
@ -92,6 +98,10 @@ namespace ams::secmon::boot {
|
|||
0xF9, 0x37, 0xCF, 0x9A, 0xBD, 0x86, 0xBB, 0xA9, 0x9C, 0x9E, 0x03, 0xC4, 0xFC, 0xBC, 0x3B, 0xCE
|
||||
};
|
||||
|
||||
constinit const u8 MasterKeySource[se::AesBlockSize] = {
|
||||
0xD8, 0xA2, 0x41, 0x0A, 0xC6, 0xC5, 0x90, 0x01, 0xC6, 0x1D, 0x6A, 0x26, 0x7C, 0x51, 0x3F, 0x3C
|
||||
};
|
||||
|
||||
void DeriveMasterKekAndDeviceKeyMariko(bool is_prod) {
|
||||
/* Clear all keyslots other than KEK and SBK in SE1. */
|
||||
for (int i = 0; i < pkg1::AesKeySlot_Count; ++i) {
|
||||
|
@ -123,6 +133,14 @@ namespace ams::secmon::boot {
|
|||
}
|
||||
}
|
||||
|
||||
void DeriveMasterKey() {
|
||||
if (GetSocType() == fuse::SocType_Mariko) {
|
||||
se::SetEncryptedAesKey128(pkg1::AesKeySlot_Master, pkg1::AesKeySlot_MasterKek, MasterKeySource, se::AesBlockSize);
|
||||
} else /* if (GetSocType() == fuse::SocType_Erista) */ {
|
||||
/* Nothing to do here; erista bootloader will have derived master key already. */
|
||||
}
|
||||
}
|
||||
|
||||
void SetupRandomKey(int slot, se::KeySlotLockFlags flags) {
|
||||
/* Create an aligned buffer to hold the key. */
|
||||
constexpr size_t KeySize = se::AesBlockSize;
|
||||
|
@ -312,6 +330,9 @@ namespace ams::secmon::boot {
|
|||
/* Derive the master keys. */
|
||||
DeriveAllMasterKeys(is_prod, work_block);
|
||||
|
||||
/* Lock the master key as a kek. */
|
||||
se::LockAesKeySlot(pkg1::AesKeySlot_Master, se::KeySlotLockFlags_AllLockKek);
|
||||
|
||||
/* Derive the device master keys. */
|
||||
DeriveAllDeviceMasterKeys(is_prod, work_block);
|
||||
|
||||
|
@ -357,7 +378,10 @@ namespace ams::secmon::boot {
|
|||
/* Lock the device key as only usable as a kek. */
|
||||
se::LockAesKeySlot(pkg1::AesKeySlot_Device, se::KeySlotLockFlags_AllLockKek);
|
||||
|
||||
/* Derive all keys. */
|
||||
/* Derive the master key. */
|
||||
DeriveMasterKey();
|
||||
|
||||
/* Derive all other keys. */
|
||||
DeriveAllKeys(is_prod);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,10 +16,24 @@
|
|||
#include <exosphere.hpp>
|
||||
#include "secmon_error.hpp"
|
||||
|
||||
namespace {
|
||||
namespace ams {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr bool SaveSystemStateForDebug = false;
|
||||
constexpr bool LogSystemStateForDebug = false;
|
||||
|
||||
void LogU64(u64 value) {
|
||||
char buffer[2 * sizeof(value)];
|
||||
for (size_t i = 0; i < sizeof(value); ++i) {
|
||||
buffer[sizeof(buffer) - 1 - (2 * i) - 0] = "0123456789ABCDEF"[(value >> 0) & 0xF];
|
||||
buffer[sizeof(buffer) - 1 - (2 * i) - 1] = "0123456789ABCDEF"[(value >> 4) & 0xF];
|
||||
value >>= 8;
|
||||
}
|
||||
log::SendText(buffer, sizeof(buffer));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
namespace ams::diag {
|
||||
|
@ -98,6 +112,57 @@ namespace ams::secmon {
|
|||
util::WaitMicroSeconds(1000);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void LogSystemStateForDebugErrorReboot(u64 lr, u64 sp) {
|
||||
log::SendText("*** Error Reboot ***\n", 21);
|
||||
log::Flush();
|
||||
|
||||
u64 temp_reg;
|
||||
|
||||
__asm__ __volatile__("mrs %0, esr_el3" : "=r"(temp_reg) :: "memory");
|
||||
log::SendText("ESR_EL3: ", 9);
|
||||
LogU64(temp_reg);
|
||||
log::SendText("\n", 1);
|
||||
log::Flush();
|
||||
|
||||
__asm__ __volatile__("mrs %0, elr_el3" : "=r"(temp_reg) :: "memory");
|
||||
log::SendText("ELR_EL3: ", 9);
|
||||
LogU64(temp_reg);
|
||||
log::SendText("\n", 1);
|
||||
log::Flush();
|
||||
|
||||
__asm__ __volatile__("mrs %0, far_el3" : "=r"(temp_reg) :: "memory");
|
||||
log::SendText("FAR_EL3: ", 9);
|
||||
LogU64(temp_reg);
|
||||
log::SendText("\n", 1);
|
||||
log::Flush();
|
||||
|
||||
log::SendText("LR: ", 9);
|
||||
LogU64(lr);
|
||||
log::SendText("\n", 1);
|
||||
log::Flush();
|
||||
|
||||
log::SendText("SP: ", 9);
|
||||
LogU64(sp);
|
||||
log::SendText("\n", 1);
|
||||
log::Flush();
|
||||
|
||||
log::SendText("Stack:\n", 7);
|
||||
log::Flush();
|
||||
|
||||
char buf[2];
|
||||
for (int i = 0; i < 0x100; ++i) {
|
||||
const u8 byte = *(volatile u8 *)(sp + i);
|
||||
buf[0] = "0123456789ABCDEF"[(byte >> 4) & 0xF];
|
||||
buf[1] = "0123456789ABCDEF"[(byte >> 0) & 0xF];
|
||||
log::SendText(buf, 2);
|
||||
log::Flush();
|
||||
if (util::IsAligned(i + 1, 0x10)) {
|
||||
log::SendText("\n", 1);
|
||||
log::Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SetError(pkg1::ErrorInfo info) {
|
||||
|
@ -114,6 +179,14 @@ namespace ams::secmon {
|
|||
SaveSystemStateForDebugErrorReboot();
|
||||
}
|
||||
|
||||
if constexpr (LogSystemStateForDebug) {
|
||||
u64 lr, sp;
|
||||
__asm__ __volatile__("mov %0, lr" : "=r"(lr) :: "memory");
|
||||
__asm__ __volatile__("mov %0, sp" : "=r"(sp) :: "memory");
|
||||
|
||||
LogSystemStateForDebugErrorReboot(lr, sp);
|
||||
}
|
||||
|
||||
/* Lockout the security engine. */
|
||||
se::Lockout();
|
||||
|
||||
|
|
|
@ -51,27 +51,27 @@ namespace ams::secmon {
|
|||
|
||||
constinit bool g_is_cold_boot = true;
|
||||
|
||||
constinit const se::StickyBits ExpectedSeStickyBits = {
|
||||
constinit se::StickyBits ExpectedSeStickyBits = {
|
||||
.se_security = (1 << 0), /* SE_HARD_SETTING */
|
||||
.tzram_security = 0,
|
||||
.crypto_security_perkey = (1 << pkg1::AesKeySlot_UserEnd) - 1,
|
||||
.crypto_keytable_access = {
|
||||
(1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 0: User keyslot. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
|
||||
(1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 1: User keyslot. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
|
||||
(1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 2: User keyslot. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
|
||||
(1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 3: User keyslot. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
|
||||
(1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 4: User keyslot. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
|
||||
(1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 5: User keyslot. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
|
||||
(0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 6: Unused keyslot. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
|
||||
(0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 7: Unused keyslot. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
|
||||
(0 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 8: Temp keyslot. UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. KEYUSE, UIVREAD, OIVREAD, KEYREAD disabled. */
|
||||
(0 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 9: SmcTemp keyslot. UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. KEYUSE, UIVREAD, OIVREAD, KEYREAD disabled. */
|
||||
(0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 10: Wrap1 keyslot. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
|
||||
(0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 11: Wrap2 keyslot. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
|
||||
(0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 12: DMaster keyslot. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
|
||||
(0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 13: Master keyslot. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
|
||||
(0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 14: Unused keyslot. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
|
||||
(0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 13: Device keyslot. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
|
||||
(0 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 0: User keyslot. KEY. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
|
||||
(0 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 1: User keyslot. KEY. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
|
||||
(0 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 2: User keyslot. KEY. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
|
||||
(0 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 3: User keyslot. KEY. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
|
||||
(0 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 4: User keyslot. KEY. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
|
||||
(0 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 5: User keyslot. KEY. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
|
||||
(1 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 6: Unused keyslot. KEK. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
|
||||
(1 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 7: Unused keyslot. KEK. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
|
||||
(0 << 7) | (0 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 8: Temp keyslot. KEY. UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. KEYUSE, UIVREAD, OIVREAD, KEYREAD disabled. */
|
||||
(0 << 7) | (0 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 9: SmcTemp keyslot. KEY. UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. KEYUSE, UIVREAD, OIVREAD, KEYREAD disabled. */
|
||||
(1 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 10: Wrap1 keyslot. KEK. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
|
||||
(0 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 11: Wrap2 keyslot. KEY. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
|
||||
(1 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 12: DMaster keyslot. KEK. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
|
||||
(1 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 13: Master keyslot. KEK. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
|
||||
(1 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 14: Unused keyslot. KEK. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
|
||||
(1 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 13: Device keyslot. KEK. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
|
||||
},
|
||||
.rsa_security_perkey = 0,
|
||||
.rsa_keytable_access = {
|
||||
|
@ -139,6 +139,16 @@ namespace ams::secmon {
|
|||
}
|
||||
|
||||
void VerifySecurityEngineStickyBits() {
|
||||
/* On mariko, an extra sticky bit is set. */
|
||||
if (GetSocType() == fuse::SocType_Mariko) {
|
||||
ExpectedSeStickyBits.se_security |= (1 << 5);
|
||||
} else /* if (GetSocType() == fuse::SocType_Erista) */ {
|
||||
/* Erista does not support DST_KEYTABLE_ONLY, and so all keys will have the bit clear. */
|
||||
for (size_t i = 0; i < util::size(ExpectedSeStickyBits.crypto_keytable_access); ++i) {
|
||||
ExpectedSeStickyBits.crypto_keytable_access[i] &= ~(1 << 7);
|
||||
}
|
||||
}
|
||||
|
||||
if (!se::ValidateStickyBits(ExpectedSeStickyBits)) {
|
||||
SetError(pkg1::ErrorInfo_InvalidSecurityEngineStickyBits);
|
||||
AMS_ABORT("Invalid sticky bits");
|
||||
|
@ -938,13 +948,17 @@ namespace ams::secmon {
|
|||
return reg::Read(MC + MC_SECURITY_CFG3) == 0;
|
||||
}
|
||||
|
||||
void LogExitLp0() {
|
||||
/* NOTE: Nintendo only does this on dev, but we will always do it. */
|
||||
if (true /* !pkg1::IsProduction() */) {
|
||||
void SetupLogForBoot() {
|
||||
log::Initialize();
|
||||
log::SendText("OHAYO\n", 6);
|
||||
log::Flush();
|
||||
}
|
||||
|
||||
void LogExitLp0() {
|
||||
/* NOTE: Nintendo only does this on dev, but we will always do it. */
|
||||
if (true /* !pkg1::IsProduction() */) {
|
||||
SetupLogForBoot();
|
||||
}
|
||||
}
|
||||
|
||||
void SetupForLp0Exit() {
|
||||
|
@ -969,7 +983,7 @@ namespace ams::secmon {
|
|||
InitializeConfigurationContext();
|
||||
|
||||
/* Initialize uart for logging. */
|
||||
log::Initialize();
|
||||
SetupLogForBoot();
|
||||
|
||||
/* Initialize the security engine. */
|
||||
se::Initialize();
|
||||
|
@ -1017,12 +1031,16 @@ namespace ams::secmon {
|
|||
|
||||
/* Overwrite keys that we want to be random with random contents. */
|
||||
se::InitializeRandom();
|
||||
se::ConfigureAutomaticContextSave();
|
||||
se::SetRandomKey(pkg1::AesKeySlot_Temporary);
|
||||
se::GenerateSrk();
|
||||
se::SetRandomKey(pkg1::AesKeySlot_TzramSaveKek);
|
||||
|
||||
/* Initialize pmc secure scratch. */
|
||||
if (GetSocType() == fuse::SocType_Erista) {
|
||||
pmc::InitializeRandomScratch();
|
||||
}
|
||||
pmc::LockSecureRegister(pmc::SecureRegister_Srk);
|
||||
|
||||
/* Setup secure registers. */
|
||||
SetupSecureRegisters();
|
||||
|
|
|
@ -114,6 +114,7 @@
|
|||
#define APBDEV_PMC_SECURE_SCRATCH113 (0xB1C)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH114 (0xB20)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH115 (0xB24)
|
||||
#define APBDEV_PMC_SECURE_SCRATCH119 (0xB34)
|
||||
|
||||
|
||||
#define PMC_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (APBDEV_PMC, NAME)
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace ams::clkrst {
|
|||
reg::ReadWrite(g_register_address + param.clk_enb_offset, REG_BITS_VALUE(param.index, 1, 0));
|
||||
|
||||
/* Set the clock source. */
|
||||
if (param.clk_src != 0) {
|
||||
if (param.clk_src_offset != 0) {
|
||||
reg::Write(g_register_address + param.clk_src_offset, (param.clk_src << 29) | (param.clk_div << 0));
|
||||
}
|
||||
|
||||
|
@ -89,11 +89,11 @@ namespace ams::clkrst {
|
|||
}
|
||||
|
||||
void EnableUartBClock() {
|
||||
EnableClock(UartAClock);
|
||||
EnableClock(UartBClock);
|
||||
}
|
||||
|
||||
void EnableUartCClock() {
|
||||
EnableClock(UartAClock);
|
||||
EnableClock(UartCClock);
|
||||
}
|
||||
|
||||
void EnableActmonClock() {
|
||||
|
|
|
@ -48,12 +48,14 @@ namespace ams::log {
|
|||
clkrst::EnableUartAClock();
|
||||
} else if constexpr (UartLogPort == uart::Port_LeftJoyCon) {
|
||||
/* Logging to left joy-con (e.g. with Joyless). */
|
||||
pinmux::SetupUartB();
|
||||
clkrst::EnableUartBClock();
|
||||
} else if constexpr (UartLogPort == uart::Port_RightJoyCon) {
|
||||
/* Logging to right joy-con (e.g. with Joyless). */
|
||||
static_assert(uart::Port_LeftJoyCon == uart::Port_C);
|
||||
pinmux::SetupUartC();
|
||||
clkrst::EnableUartCClock();
|
||||
} else if constexpr (UartLogPort == uart::Port_RightJoyCon) {
|
||||
/* Logging to right joy-con (e.g. with Joyless). */
|
||||
static_assert(uart::Port_RightJoyCon == uart::Port_B);
|
||||
pinmux::SetupUartB();
|
||||
clkrst::EnableUartBClock();
|
||||
} else {
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
|
|
@ -104,7 +104,7 @@ namespace ams::pinmux {
|
|||
/* Get the registers. */
|
||||
const uintptr_t PINMUX = g_pinmux_address;
|
||||
|
||||
/* Configure Uart-B. */
|
||||
/* Configure Uart-C. */
|
||||
reg::Write(PINMUX + PINMUX_AUX_UART3_TX, PINMUX_REG_BITS_ENUM(AUX_UART3_PM, UARTC),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, NONE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
|
@ -114,13 +114,13 @@ namespace ams::pinmux {
|
|||
|
||||
reg::Write(PINMUX + PINMUX_AUX_UART3_RX, PINMUX_REG_BITS_ENUM(AUX_UART3_PM, UARTC),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, NONE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, TRISTATE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_LOCK, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_OD, DISABLE));
|
||||
|
||||
reg::Write(PINMUX + PINMUX_AUX_UART3_RTS, PINMUX_REG_BITS_ENUM(AUX_UART3_PM, UARTC),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, NONE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, PULL_DOWN),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_INPUT, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_LOCK, DISABLE),
|
||||
|
@ -128,13 +128,16 @@ namespace ams::pinmux {
|
|||
|
||||
reg::Write(PINMUX + PINMUX_AUX_UART3_CTS, PINMUX_REG_BITS_ENUM(AUX_UART3_PM, UARTC),
|
||||
PINMUX_REG_BITS_ENUM(AUX_PUPD, NONE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, PASSTHROUGH),
|
||||
PINMUX_REG_BITS_ENUM(AUX_TRISTATE, TRISTATE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_INPUT, ENABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_LOCK, DISABLE),
|
||||
PINMUX_REG_BITS_ENUM(AUX_E_OD, DISABLE));
|
||||
|
||||
/* Configure GPIO for Uart-C. */
|
||||
reg::ReadWrite(g_gpio_address + 0x00C, REG_BITS_VALUE(1, 4, 0));
|
||||
reg::ReadWrite(g_gpio_address + 0x118, REG_BITS_VALUE(0, 1, 1));
|
||||
reg::Read(g_gpio_address + 0x118);
|
||||
reg::ReadWrite(g_gpio_address + 0x00C, REG_BITS_VALUE(1, 1, 0));
|
||||
reg::Read(g_gpio_address + 0x00C);
|
||||
}
|
||||
|
||||
void SetupI2c1() {
|
||||
|
|
|
@ -33,11 +33,11 @@ namespace ams::uart {
|
|||
}
|
||||
|
||||
void WaitSymbols(int baud, u32 num) {
|
||||
util::WaitMicroSeconds(util::DivideUp(1'000'000, baud) * num);
|
||||
util::WaitMicroSeconds(util::DivideUp(num * 1'000'000, baud));
|
||||
}
|
||||
|
||||
void WaitCycles(int baud, u32 num) {
|
||||
util::WaitMicroSeconds(util::DivideUp(1'000'000, 16 * baud) * num);
|
||||
util::WaitMicroSeconds(util::DivideUp(num * 1'000'000, 16 * baud));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void WaitFifoNotFull(volatile UartRegisters *uart) {
|
||||
|
@ -60,26 +60,6 @@ namespace ams::uart {
|
|||
|
||||
constexpr inline u32 LockBit = (1 << 6);
|
||||
|
||||
void Lock(volatile UartRegisters *reg) {
|
||||
while (true) {
|
||||
if (reg->mie != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
reg->irda_csr = LockBit;
|
||||
|
||||
if (reg->mie == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
reg->irda_csr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Unlock(volatile UartRegisters *reg) {
|
||||
reg->irda_csr = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SetRegisterAddress(uintptr_t address) {
|
||||
|
@ -97,7 +77,13 @@ namespace ams::uart {
|
|||
constexpr u32 UartClock = 408000000;
|
||||
const u32 divisor = (UartClock + (baud_rate * 16) / 2) / (baud_rate * 16);
|
||||
|
||||
/* Disable DLAB and all interrupts. */
|
||||
/* Wait for idle state. */
|
||||
WaitIdle(uart, UART_VENDOR_STATE_TX_IDLE);
|
||||
|
||||
/* Wait 100 us. */
|
||||
util::WaitMicroSeconds(100);
|
||||
|
||||
/* Disable interrupts. */
|
||||
uart->lcr = uart->lcr & ~UART_LCR_DLAB;
|
||||
uart->ier = 0;
|
||||
uart->mcr = 0;
|
||||
|
@ -128,8 +114,8 @@ namespace ams::uart {
|
|||
/* Wait for idle state. */
|
||||
WaitIdle(uart, UART_VENDOR_STATE_TX_IDLE | UART_VENDOR_STATE_RX_IDLE);
|
||||
|
||||
/* Set scratch register to 0. */
|
||||
uart->spr = 0;
|
||||
/* Wait 100 us. */
|
||||
util::WaitMicroSeconds(100);
|
||||
}
|
||||
|
||||
void SendText(Port port, const void *data, size_t size) {
|
||||
|
@ -139,10 +125,6 @@ namespace ams::uart {
|
|||
/* Get pointer to data. */
|
||||
const u8 *p = static_cast<const u8 *>(data);
|
||||
|
||||
/* Lock the uart registers. */
|
||||
Lock(uart);
|
||||
ON_SCOPE_EXIT { Unlock(uart); };
|
||||
|
||||
/* Send each byte. */
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
WaitFifoNotFull(uart);
|
||||
|
|
Loading…
Reference in a new issue