Line 1: |
Line 1: |
| Like most Tegra based devices, the Switch's GPU also includes a Falcon microprocessor. | | Like most Tegra based devices, the Switch's GPU also includes a Falcon microprocessor. |
| + | TSEC is a NVIDIA Falcon microprocessor with crypto extensions. |
| | | |
| = Driver = | | = Driver = |
− | A host driver for communicating with the Falcon is mapped to physical address 0x54500000 with a total size of 0x40000 bytes and exposes several registers. | + | A host driver for communicating with the TSEC/Falcon is mapped to physical address 0x54500000 with a total size of 0x40000 bytes and exposes several registers. |
| | | |
| == Registers == | | == Registers == |
Line 285: |
Line 286: |
| return; | | return; |
| | | |
− | = Firmware = | + | = TSEC Firmware = |
− | The actual code loaded into Falcon is assembled in NVIDIA's proprietary fuc5 ISA using crypto extensions. | + | The actual code loaded into TSEC is assembled in NVIDIA's proprietary fuc5 ISA using crypto extensions. |
| Stored inside the first bootloader, this firmware binary is split into 4 blobs: Stage0, Stage1, Stage2 and key data. | | Stored inside the first bootloader, this firmware binary is split into 4 blobs: Stage0, Stage1, Stage2 and key data. |
| + | |
| + | Firmware can be disassembled with http:x//envytools.readthedocs.io/en/latest/" envytools' https:x//github.com/envytools/envytools/tree/master/envydis envydis: |
| + | |
| + | <code>envydis -i tsec_fw.bin -m falcon -V fuc5 -F crypt</code> |
| + | |
| + | Note that the instruction set has variable length instructions, and the disassembler is not very good at detecting locations it should start disassembling from. One needs to disassemble multiple sub-regions and join them together. |
| | | |
| == Stage 0 == | | == Stage 0 == |
Line 613: |
Line 620: |
| == Key data == | | == Key data == |
| Small buffer stored after Stage 0's code and used across all stages. | | Small buffer stored after Stage 0's code and used across all stages. |
| + | |
| + | == Notes == |
| + | |
| + | https:x//wiki.0x04.net/wiki/Marcin_Ko%C5%9Bcielnicki mwk shared additional info learned from RE of falcon processors over the years, which hasn't made it into envytools documentation yet: |
| + | |
| + | === cxset === |
| + | |
| + | cxset instruction provides a way to change behavior of a variable amount of successively executed DMA-related instructions. |
| + | |
| + | for example: <code>000000de: f4 3c 02 cxset 0x2</code> |
| + | |
| + | can be read as: <code>dma_override(type=crypto_reg, count=2)</code> |
| + | |
| + | The argument to cxset specifies the type of behavior change in the top 3 bits, and the number of DMA-related instructions the effect lasts for in the lower 5 bits. |
| + | |
| + | ==== Override Types ==== |
| + | |
| + | Unlisted values are unknown, but probably do something. |
| + | |
| + | {| class=wikitable |
| + | ! Value || Effect |
| + | |- |
| + | | 0b000 || falcon data mem <-> falcon $cX register |
| + | |- |
| + | | 0b001 || external mem <-> crypto input/output stream |
| + | |} |
| + | |
| + | ==== DMA-Related Instructions ==== |
| + | |
| + | At least the following instructions may have changed behavior, and count against the cxset "count" argument: <code>xdwait</code>, <code>xdst</code>, <code>xdld</code>. |
| + | |
| + | For example, if override type=0b000, then the "length" argument to <code>xdst</code> is instead treated as the index of the target $cX register. |
| + | |
| + | === Register ACLs === |
| + | |
| + | Falcon tracks permission metadata about each crypto reg. Permissions include read/write ability per execution mode, as well as ability to use the reg for encrypt/decrypt, among other permissions. Permissions are propagated when registers are referenced by instructions (e.g. moving a value from read-protected $cX to $cY will result in $cY also being read-protected). |
| + | |
| + | === Authenticated Mode Entry/Exit === |
| + | |
| + | Entry to Authenticated Mode always sets $pc to the address supplied in $cauth (ie the base of the signature-checked region). This takes effect when trying to branch to any address within the range covered by $cauth. |
| + | |
| + | Exit from Authenticated Mode must poke a special register (this seems to be I[0x10300] = 0) before leaving authenticated code pages. Failure to do this would result in the Falcon core halting. |