From 51cf28339bd52cdfa297ae50e176ebceeb294325 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 27 Aug 2021 23:20:46 -0700 Subject: [PATCH] fusee_cpp: implement tsec_keygen firmware execution --- fusee_cpp/program/program.ld | 4 + fusee_cpp/program/program_ovl.ld | 4 +- .../program/source/fusee_setup_horizon.cpp | 29 +++- fusee_cpp/program/source/mtc/fusee_mtc.cpp | 26 +-- fusee_cpp/program/source/mtc/fusee_mtc.hpp | 2 - .../program/source/mtc/fusee_mtc_erista.cpp | 11 +- .../program/source/mtc/fusee_mtc_mariko.cpp | 8 +- libraries/libexosphere/arm.mk | 2 +- .../source/kfuse/kfuse_registers.hpp | 32 ++++ .../libexosphere/source/tsec/tsec_api.cpp | 156 +++++++++++++++--- .../source/tsec/tsec_registers.hpp | 49 ++++++ 11 files changed, 270 insertions(+), 53 deletions(-) create mode 100644 libraries/libexosphere/source/kfuse/kfuse_registers.hpp create mode 100644 libraries/libexosphere/source/tsec/tsec_registers.hpp diff --git a/fusee_cpp/program/program.ld b/fusee_cpp/program/program.ld index 6d97ae2e7..9f6d514b0 100644 --- a/fusee_cpp/program/program.ld +++ b/fusee_cpp/program/program.ld @@ -19,6 +19,10 @@ SECTIONS .text : { + KEEP(*(.text._ZN3ams4util15GetMicroSecondsEv)) + KEEP(*(.text._ZN3ams4util16WaitMicroSecondsEi)) + KEEP(*(.text._ZN3ams6nxboot14ShowFatalErrorEPKcz)) + _*.o(SORT(.text*)) *(.text.unlikely .text.*_unlikely .text.unlikely.*) *(.text.exit .text.exit.*) *(.text.startup .text.startup.*) diff --git a/fusee_cpp/program/program_ovl.ld b/fusee_cpp/program/program_ovl.ld index 9dfe1ce09..0f73539c8 100644 --- a/fusee_cpp/program/program_ovl.ld +++ b/fusee_cpp/program/program_ovl.ld @@ -23,7 +23,7 @@ SECTIONS { BYTE(0x00); } .ovl_mtc_erista { - KEEP(*(.text._ZN3ams6nxboot22DoMemoryTrainingEristaEv)) + KEEP(*(.text._ZN3ams6nxboot22DoMemoryTrainingEristaEi)) fusee_mtc_erista.o(.text*); fusee_mtc_erista.o(.rodata*); fusee_mtc_erista.o(.data*); @@ -33,7 +33,7 @@ SECTIONS { BYTE(0x00); } .ovl_mtc_mariko { - KEEP(*(.text._ZN3ams6nxboot22DoMemoryTrainingMarikoEv)) + KEEP(*(.text._ZN3ams6nxboot22DoMemoryTrainingMarikoEi)) fusee_mtc_mariko.o(.text*); fusee_mtc_mariko.o(.rodata*); fusee_mtc_mariko.o(.data*); diff --git a/fusee_cpp/program/source/fusee_setup_horizon.cpp b/fusee_cpp/program/source/fusee_setup_horizon.cpp index c34a983a9..5437e5723 100644 --- a/fusee_cpp/program/source/fusee_setup_horizon.cpp +++ b/fusee_cpp/program/source/fusee_setup_horizon.cpp @@ -14,13 +14,40 @@ * along with this program. If not, see . */ #include +#include "fusee_secondary_archive.hpp" #include "fusee_setup_horizon.hpp" #include "fusee_fatal.hpp" namespace ams::nxboot { + namespace { + + void DeriveAllKeys(const fuse::SocType soc_type) { + /* If on erista, run the TSEC keygen firmware. */ + if (soc_type == fuse::SocType_Erista) { + clkrst::SetBpmpClockRate(clkrst::BpmpClockRate_408MHz); + + if (!tsec::RunTsecFirmware(GetSecondaryArchive().tsec_keygen, sizeof(GetSecondaryArchive().tsec_keygen))) { + ShowFatalError("Failed to run tsec_keygen firmware!\n"); + } + + clkrst::SetBpmpClockRate(clkrst::BpmpClockRate_576MHz); + } + + ShowFatalError("DeriveAllKeys not fully implemented\n"); + } + + } + void SetupAndStartHorizon() { - /* TODO */ + /* Get soc/hardware type. */ + const auto soc_type = fuse::GetSocType(); + const auto hw_type = fuse::GetHardwareType(); + + /* Derive all keys. */ + DeriveAllKeys(soc_type); + + AMS_UNUSED(hw_type); ShowFatalError("SetupAndStartHorizon not fully implemented\n"); } diff --git a/fusee_cpp/program/source/mtc/fusee_mtc.cpp b/fusee_cpp/program/source/mtc/fusee_mtc.cpp index bbd7b148f..8d8596546 100644 --- a/fusee_cpp/program/source/mtc/fusee_mtc.cpp +++ b/fusee_cpp/program/source/mtc/fusee_mtc.cpp @@ -17,8 +17,8 @@ namespace ams::nxboot { - void DoMemoryTrainingErista(); - void DoMemoryTrainingMariko(); + void DoMemoryTrainingErista(int index); + void DoMemoryTrainingMariko(int index); namespace { @@ -56,21 +56,23 @@ namespace ams::nxboot { /* DramId_MarikoAulaSamsung1y8gbX */ 0x0D, }; + int GetMemoryTrainingTableIndex() { + if (const auto dram_id = fuse::GetDramId(); dram_id < util::size(MemoryTrainingTableIndices) && MemoryTrainingTableIndices[dram_id] != MemoryTrainingTableIndex_Invalid) { + return static_cast(MemoryTrainingTableIndices[dram_id]); + } else { + return -1; + } + } + } void DoMemoryTraining() { - if (fuse::GetSocType() == fuse::SocType_Erista) { - DoMemoryTrainingErista(); - } else { - DoMemoryTrainingMariko(); - } - } + const auto index = GetMemoryTrainingTableIndex(); - int GetMemoryTrainingTableIndex() { - if (const auto dram_id = fuse::GetDramId(); dram_id < util::size(MemoryTrainingTableIndices) && MemoryTrainingTableIndices[dram_id] != MemoryTrainingTableIndex_Invalid) { - return static_cast(MemoryTrainingTableIndices[dram_id]); + if (fuse::GetSocType() == fuse::SocType_Erista) { + DoMemoryTrainingErista(index); } else { - return -1; + DoMemoryTrainingMariko(index); } } diff --git a/fusee_cpp/program/source/mtc/fusee_mtc.hpp b/fusee_cpp/program/source/mtc/fusee_mtc.hpp index 4440cc330..2fc9e120c 100644 --- a/fusee_cpp/program/source/mtc/fusee_mtc.hpp +++ b/fusee_cpp/program/source/mtc/fusee_mtc.hpp @@ -20,6 +20,4 @@ namespace ams::nxboot { void DoMemoryTraining(); - int GetMemoryTrainingTableIndex(); - } diff --git a/fusee_cpp/program/source/mtc/fusee_mtc_erista.cpp b/fusee_cpp/program/source/mtc/fusee_mtc_erista.cpp index 2259db502..d723854b9 100644 --- a/fusee_cpp/program/source/mtc/fusee_mtc_erista.cpp +++ b/fusee_cpp/program/source/mtc/fusee_mtc_erista.cpp @@ -72,8 +72,7 @@ namespace ams::nxboot { using EmcDvfsTimingTable = erista::EmcDvfsTimingTable; - EmcDvfsTimingTable *GetEmcDvfsTimingTables() { - const auto index = GetMemoryTrainingTableIndex(); + EmcDvfsTimingTable *GetEmcDvfsTimingTables(int index) { switch (index) { case 0: case 3: @@ -2830,11 +2829,11 @@ namespace ams::nxboot { } - void DoMemoryTrainingErista() { + void DoMemoryTrainingErista(int index) { /* Get timing tables. */ - auto *timing_tables = GetEmcDvfsTimingTables(); - auto *src_timing = timing_tables + 0; - auto *dst_timing = timing_tables + 1; + auto *timing_tables = GetEmcDvfsTimingTables(index); + auto *src_timing = timing_tables + 0; + auto *dst_timing = timing_tables + 1; /* Check timing tables. */ if (src_timing->rate_khz != 204000 || dst_timing->rate_khz != 1600000) { diff --git a/fusee_cpp/program/source/mtc/fusee_mtc_mariko.cpp b/fusee_cpp/program/source/mtc/fusee_mtc_mariko.cpp index e38bc1b31..8ce16623c 100644 --- a/fusee_cpp/program/source/mtc/fusee_mtc_mariko.cpp +++ b/fusee_cpp/program/source/mtc/fusee_mtc_mariko.cpp @@ -27,9 +27,7 @@ namespace ams::nxboot { using EmcDvfsTimingTable = mariko::EmcDvfsTimingTable; - EmcDvfsTimingTable *GetEmcDvfsTimingTables() { - const auto index = GetMemoryTrainingTableIndex(); - + EmcDvfsTimingTable *GetEmcDvfsTimingTables(int index) { /* Get the compressed table. */ u8 *cmp_table; size_t cmp_table_size; @@ -65,9 +63,9 @@ namespace ams::nxboot { } - void DoMemoryTrainingMariko() { + void DoMemoryTrainingMariko(int index) { /* Get timing tables. */ - auto *timing_tables = GetEmcDvfsTimingTables(); + auto *timing_tables = GetEmcDvfsTimingTables(index); auto *src_timing_tables = timing_tables + 0; auto *dst_timing_tables = timing_tables + 1; diff --git a/libraries/libexosphere/arm.mk b/libraries/libexosphere/arm.mk index 6a42c37c6..0414f3dea 100644 --- a/libraries/libexosphere/arm.mk +++ b/libraries/libexosphere/arm.mk @@ -149,7 +149,7 @@ $(OFILES) : $(GCH_FILES) $(OFILES_SRC) : $(HFILES_BIN) libc.o: CFLAGS += -fno-builtin -fno-lto -libgcc_division.arch.arm.o: CFLAGS += -fno-builtin -fno-lto +util_api.o: CXXFLAGS += -fno-lto #--------------------------------------------------------------------------------- %_bin.h %.bin.o : %.bin diff --git a/libraries/libexosphere/source/kfuse/kfuse_registers.hpp b/libraries/libexosphere/source/kfuse/kfuse_registers.hpp new file mode 100644 index 000000000..4e6f1c6f3 --- /dev/null +++ b/libraries/libexosphere/source/kfuse/kfuse_registers.hpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public LicenKFUSE, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be uKFUSEful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOKFUSE. KFUSEe the GNU General Public LicenKFUSE for + * more details. + * + * You should have received a copy of the GNU General Public LicenKFUSE + * along with this program. If not, KFUSEe . + */ +#include + +#define KFUSE_STATE (0x080) + +#define KFUSE_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (KFUSE, NAME) +#define KFUSE_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (KFUSE, NAME, VALUE) +#define KFUSE_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (KFUSE, NAME, ENUM) +#define KFUSE_REG_BITS_ENUM_KFUSEL(NAME, __COND__, TRUE_ENUM, FALKFUSE_ENUM) REG_NAMED_BITS_ENUM_KFUSEL(KFUSE, NAME, __COND__, TRUE_ENUM, FALKFUSE_ENUM) + +#define DEFINE_KFUSE_REG(NAME, __OFFKFUSET__, __WIDTH__) REG_DEFINE_NAMED_REG (KFUSE, NAME, __OFFKFUSET__, __WIDTH__) +#define DEFINE_KFUSE_REG_BIT_ENUM(NAME, __OFFKFUSET__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (KFUSE, NAME, __OFFKFUSET__, ZERO, ONE) +#define DEFINE_KFUSE_REG_TWO_BIT_ENUM(NAME, __OFFKFUSET__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (KFUSE, NAME, __OFFKFUSET__, ZERO, ONE, TWO, THREE) +#define DEFINE_KFUSE_REG_THREE_BIT_ENUM(NAME, __OFFKFUSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, KFUSEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(KFUSE, NAME, __OFFKFUSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, KFUSEVEN) +#define DEFINE_KFUSE_REG_FOUR_BIT_ENUM(NAME, __OFFKFUSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, KFUSEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (KFUSE, NAME, __OFFKFUSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, KFUSEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) + +DEFINE_KFUSE_REG_BIT_ENUM(STATE_DONE, 16, NOT_DONE, DONE); +DEFINE_KFUSE_REG_BIT_ENUM(STATE_CRCPASS, 17, FAIL, PASS); diff --git a/libraries/libexosphere/source/tsec/tsec_api.cpp b/libraries/libexosphere/source/tsec/tsec_api.cpp index a251b91f2..56f6a7087 100644 --- a/libraries/libexosphere/source/tsec/tsec_api.cpp +++ b/libraries/libexosphere/source/tsec/tsec_api.cpp @@ -14,46 +14,154 @@ * along with this program. If not, see . */ #include +#include "tsec_registers.hpp" +#include "../kfuse/kfuse_registers.hpp" namespace ams::tsec { namespace { - enum TsecResult { + constexpr inline const uintptr_t KFUSE = 0x7000FC00; + constexpr inline const uintptr_t TSEC = 0x54500000; + + enum TsecResult : u32 { TsecResult_Success = 0xB0B0B0B0, TsecResult_Failure = 0xD0D0D0D0, }; - bool RunFirmwareImpl(const void *fw, size_t fw_size) { - /* Enable relevant clocks. */ - clkrst::EnableHost1xClock(); - clkrst::EnableTsecClock(); - clkrst::EnableSorSafeClock(); - clkrst::EnableSor0Clock(); - clkrst::EnableSor1Clock(); - clkrst::EnableKfuseClock(); + enum TsecMemory { + TsecMemory_Imem, + TsecMemory_Dmem, + }; - /* Disable clocks once we're done. */ - ON_SCOPE_EXIT { - clkrst::DisableHost1xClock(); - clkrst::DisableTsecClock(); - clkrst::DisableSorSafeClock(); - clkrst::DisableSor0Clock(); - clkrst::DisableSor1Clock(); - clkrst::DisableKfuseClock(); - }; + bool WaitForKfuseReady() { + constexpr auto KfuseTimeout = 10 * 1000; /* 10 ms. */ - /* TODO */ - AMS_UNUSED(fw, fw_size); - return true; + const u32 end_time = util::GetMicroSeconds() + KfuseTimeout; + + /* Wait for STATE_DONE. */ + while (!reg::HasValue(KFUSE + KFUSE_STATE, KFUSE_REG_BITS_ENUM(STATE_DONE, DONE))) { + if (util::GetMicroSeconds() >= end_time) { + return false; + } + } + + /* Check for STATE_CRCPASS. */ + return reg::HasValue(KFUSE + KFUSE_STATE, KFUSE_REG_BITS_ENUM(STATE_CRCPASS, PASS)); + } + + void WaitForDmaIdle() { + constexpr auto DmaTimeout = 10 * 1000 * 1000; /* 10 Seconds. */ + + u32 cur_time = util::GetMicroSeconds(); + const u32 end_time = cur_time + DmaTimeout; + + while (cur_time <= end_time) { + if (reg::HasValue(TSEC + TSEC_FALCON_DMATRFCMD, TSEC_REG_BITS_ENUM(FALCON_DMATRFCMD_BUSY, IDLE))) { + return; + } + + cur_time = util::GetMicroSeconds(); + } + + AMS_ABORT("tsec dma timeout"); + } + + void WaitForTsecIdle() { + constexpr auto TsecTimeout = 2 * 1000 * 1000; /* 2 Seconds. */ + + u32 cur_time = util::GetMicroSeconds(); + const u32 end_time = cur_time + TsecTimeout; + + while (cur_time <= end_time) { + if (reg::HasValue(TSEC + TSEC_FALCON_CPUCTL, TSEC_REG_BITS_ENUM(FALCON_CPUCTL_HALTED, TRUE))) { + return; + } + + cur_time = util::GetMicroSeconds(); + } + + AMS_ABORT("tsec timeout"); + } + + void DoDma256(TsecMemory memory, u32 dst_offset, u32 src_offset) { + reg::Write(TSEC + TSEC_FALCON_DMATRFMOFFS, TSEC_REG_BITS_VALUE(FALCON_DMATRFMOFFS_OFFSET, dst_offset)); + reg::Write(TSEC + TSEC_FALCON_DMATRFFBOFFS, src_offset); + + if (memory == TsecMemory_Imem) { + reg::Write(TSEC + TSEC_FALCON_DMATRFCMD, TSEC_REG_BITS_ENUM(FALCON_DMATRFCMD_TO, IMEM), + TSEC_REG_BITS_ENUM(FALCON_DMATRFCMD_SIZE, 4B)); + } else { + reg::Write(TSEC + TSEC_FALCON_DMATRFCMD, TSEC_REG_BITS_ENUM(FALCON_DMATRFCMD_TO, DMEM), + TSEC_REG_BITS_ENUM(FALCON_DMATRFCMD_SIZE, 256B)); + } + + WaitForDmaIdle(); } } bool RunTsecFirmware(const void *fw, size_t fw_size) { - /* TODO */ - AMS_UNUSED(fw, fw_size); - return RunFirmwareImpl(fw, fw_size); + /* Enable relevant clocks. */ + clkrst::EnableHost1xClock(); + clkrst::EnableTsecClock(); + clkrst::EnableSorSafeClock(); + clkrst::EnableSor0Clock(); + clkrst::EnableSor1Clock(); + clkrst::EnableKfuseClock(); + + /* Disable clocks once we're done. */ + ON_SCOPE_EXIT { + clkrst::DisableHost1xClock(); + clkrst::DisableTsecClock(); + clkrst::DisableSorSafeClock(); + clkrst::DisableSor0Clock(); + clkrst::DisableSor1Clock(); + clkrst::DisableKfuseClock(); + }; + + /* Wait for kfuse to be ready. */ + if (!WaitForKfuseReady()) { + return false; + } + + /* Configure falcon. */ + reg::Write(TSEC + TSEC_FALCON_DMACTL, 0); + reg::Write(TSEC + TSEC_FALCON_IRQMSET, 0xFFF2); + reg::Write(TSEC + TSEC_FALCON_IRQDEST, 0xFFF0); + reg::Write(TSEC + TSEC_FALCON_ITFEN, 0x3); + + /* Wait for TSEC dma to be idle. */ + WaitForDmaIdle(); + + /* Set the base address for transfers. */ + reg::Write(TSEC + TSEC_FALCON_DMATRFBASE, reinterpret_cast(fw) >> 8); + + /* Transfer all data to TSEC imem. */ + for (size_t i = 0; i < fw_size; i += 0x100) { + DoDma256(TsecMemory_Imem, i, i); + } + + /* Write the magic value to host1x syncpoint 160. */ + reg::Write(0x50003300, 0x34C2E1DA); + + /* Execute the firmware. */ + reg::Write(TSEC + TSEC_FALCON_MAILBOX0, 0); + reg::Write(TSEC + TSEC_FALCON_MAILBOX1, 0); + reg::Write(TSEC + TSEC_FALCON_BOOTVEC, 0); + reg::Write(TSEC + TSEC_FALCON_CPUCTL, TSEC_REG_BITS_ENUM(FALCON_CPUCTL_STARTCPU, TRUE)); + + /* Wait for TSEC dma to be idle. */ + WaitForDmaIdle(); + + /* Wait for TSEC to complete. */ + WaitForTsecIdle(); + + /* Clear magic value from host1x syncpoint 160. */ + reg::Write(0x50003300, 0); + + /* Return whether the tsec firmware succeeded. */ + return reg::Read(TSEC + TSEC_FALCON_MAILBOX1) == TsecResult_Success; } void Lock() { diff --git a/libraries/libexosphere/source/tsec/tsec_registers.hpp b/libraries/libexosphere/source/tsec/tsec_registers.hpp new file mode 100644 index 000000000..fb8e758aa --- /dev/null +++ b/libraries/libexosphere/source/tsec/tsec_registers.hpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public LicenTSEC, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be uTSECful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOTSEC. TSECe the GNU General Public LicenTSEC for + * more details. + * + * You should have received a copy of the GNU General Public LicenTSEC + * along with this program. If not, TSECe . + */ +#include + +#define TSEC_FALCON_IRQMSET (0x1010) +#define TSEC_FALCON_IRQDEST (0x101C) +#define TSEC_FALCON_MAILBOX0 (0x1040) +#define TSEC_FALCON_MAILBOX1 (0x1044) +#define TSEC_FALCON_ITFEN (0x1048) +#define TSEC_FALCON_CPUCTL (0x1100) +#define TSEC_FALCON_BOOTVEC (0x1104) +#define TSEC_FALCON_DMACTL (0x110C) +#define TSEC_FALCON_DMATRFBASE (0x1110) +#define TSEC_FALCON_DMATRFMOFFS (0x1114) +#define TSEC_FALCON_DMATRFCMD (0x1118) +#define TSEC_FALCON_DMATRFFBOFFS (0x111C) + +#define TSEC_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (TSEC, NAME) +#define TSEC_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (TSEC, NAME, VALUE) +#define TSEC_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (TSEC, NAME, ENUM) +#define TSEC_REG_BITS_ENUM_TSECL(NAME, __COND__, TRUE_ENUM, FALTSEC_ENUM) REG_NAMED_BITS_ENUM_TSECL(TSEC, NAME, __COND__, TRUE_ENUM, FALTSEC_ENUM) + +#define DEFINE_TSEC_REG(NAME, __OFFTSECT__, __WIDTH__) REG_DEFINE_NAMED_REG (TSEC, NAME, __OFFTSECT__, __WIDTH__) +#define DEFINE_TSEC_REG_BIT_ENUM(NAME, __OFFTSECT__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (TSEC, NAME, __OFFTSECT__, ZERO, ONE) +#define DEFINE_TSEC_REG_TWO_BIT_ENUM(NAME, __OFFTSECT__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (TSEC, NAME, __OFFTSECT__, ZERO, ONE, TWO, THREE) +#define DEFINE_TSEC_REG_THREE_BIT_ENUM(NAME, __OFFTSECT__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, TSECVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(TSEC, NAME, __OFFTSECT__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, TSECVEN) +#define DEFINE_TSEC_REG_FOUR_BIT_ENUM(NAME, __OFFTSECT__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, TSECVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (TSEC, NAME, __OFFTSECT__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, TSECVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) + +DEFINE_TSEC_REG_BIT_ENUM(FALCON_CPUCTL_STARTCPU, 1, FALSE, TRUE); +DEFINE_TSEC_REG_BIT_ENUM(FALCON_CPUCTL_HALTED, 4, FALSE, TRUE); + +DEFINE_TSEC_REG(FALCON_DMATRFMOFFS_OFFSET, 0, 16); + +DEFINE_TSEC_REG_BIT_ENUM(FALCON_DMATRFCMD_BUSY, 1, BUSY, IDLE); +DEFINE_TSEC_REG_BIT_ENUM(FALCON_DMATRFCMD_TO, 4, DMEM, IMEM); +DEFINE_TSEC_REG_THREE_BIT_ENUM(FALCON_DMATRFCMD_SIZE, 8, 4B, 8B, 16B, 32B, 64B, 128B, 256B, RSVD7); \ No newline at end of file