From c333a84b6bef1eb5706358063eb6e9469503ce7f Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Sat, 21 Aug 2021 15:49:36 -0700 Subject: [PATCH] fusee-cpp: Implement mbist workaround --- fusee_cpp/program/Makefile | 2 +- fusee_cpp/program/lz4_compress.py | 2 +- fusee_cpp/program/program.ld | 61 ++- fusee_cpp/program/program.specs | 2 +- fusee_cpp/program/program_ovl.ld | 22 ++ fusee_cpp/program/source/fusee_main.cpp | 4 + .../program/source/fusee_registers_di.hpp | 354 ++++++++++++++++++ .../source/fusee_secure_initialize.cpp | 185 +++++++++ .../source/fusee_secure_initialize.hpp | 23 ++ .../libexosphere/include/exosphere/clkrst.hpp | 15 + .../libexosphere/include/exosphere/fuse.hpp | 2 + .../libexosphere/include/exosphere/tsec.hpp | 2 + .../libexosphere/source/clkrst/clkrst_api.cpp | 68 +++- .../libexosphere/source/fuse/fuse_api.cpp | 13 + .../libexosphere/source/tsec/tsec_api.cpp | 33 ++ .../libvapours/include/vapours/tegra.hpp | 1 + .../include/vapours/tegra/tegra_clkrst.hpp | 39 ++ .../include/vapours/tegra/tegra_i2s.hpp | 52 +++ .../include/vapours/tegra/tegra_pmc.hpp | 2 + 19 files changed, 847 insertions(+), 35 deletions(-) create mode 100644 fusee_cpp/program/program_ovl.ld create mode 100644 fusee_cpp/program/source/fusee_registers_di.hpp create mode 100644 fusee_cpp/program/source/fusee_secure_initialize.cpp create mode 100644 fusee_cpp/program/source/fusee_secure_initialize.hpp create mode 100644 libraries/libvapours/include/vapours/tegra/tegra_i2s.hpp diff --git a/fusee_cpp/program/Makefile b/fusee_cpp/program/Makefile index f87cead16..7eb6c1985 100644 --- a/fusee_cpp/program/Makefile +++ b/fusee_cpp/program/Makefile @@ -76,7 +76,7 @@ check_libexo_$(strip $1): clean-$(strip $1): @echo clean $(strip $1) ... - @rm -fr $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) $$(OUTPUT_BASE)$(strip $2).bin $$(OUTPUT_BASE)$(strip $2).elf + @rm -fr $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) $$(OUTPUT_BASE)$(strip $2).bin $$(OUTPUT_BASE)$(strip $2).lz4 $$(OUTPUT_BASE)$(strip $2).elf endef diff --git a/fusee_cpp/program/lz4_compress.py b/fusee_cpp/program/lz4_compress.py index 2bf17a64d..8283044f4 100644 --- a/fusee_cpp/program/lz4_compress.py +++ b/fusee_cpp/program/lz4_compress.py @@ -16,7 +16,7 @@ def main(argc, argv): with open(argv[1], 'rb') as f: data = f.read() with open(argv[2], 'wb') as f: - f.write(lz4_compress(data)) + f.write(lz4_compress(data[:0x2B000 + 0x11000])) return 0 if __name__ == '__main__': diff --git a/fusee_cpp/program/program.ld b/fusee_cpp/program/program.ld index 5a6ea3adf..53c7167a1 100644 --- a/fusee_cpp/program/program.ld +++ b/fusee_cpp/program/program.ld @@ -1,17 +1,10 @@ OUTPUT_ARCH(arm) ENTRY(_ZN3ams6nxboot5StartEv) -MEMORY -{ - NULL : ORIGIN = 0, LENGTH = 4K - main : ORIGIN = 0x40001000, LENGTH = 0x2B000 - ovl : ORIGIN = 0x4002C000, LENGTH = 0x14000 -} - - SECTIONS { /* =========== CODE section =========== */ + PROVIDE(__start__ = ORIGIN(main)); . = __start__; __main_start__ = . ; @@ -20,7 +13,7 @@ SECTIONS { KEEP (*(.crt0 .crt0.*)) . = ALIGN(8); - } >main + } >main AT>glob .text : { @@ -30,26 +23,26 @@ SECTIONS *(.text.hot .text.hot.*) *(.text .stub .text.* .gnu.linkonce.t.*) . = ALIGN(8); - } >main + } >main AT>glob .init : { KEEP( *(.init) ) . = ALIGN(8); - } >main + } >main AT>glob .plt : { *(.plt) *(.iplt) . = ALIGN(8); - } >main + } >main AT>glob .fini : { KEEP( *(.fini) ) . = ALIGN(8); - } >main + } >main AT>glob /* =========== RODATA section =========== */ @@ -60,30 +53,30 @@ SECTIONS { *(.rodata .rodata.* .gnu.linkonce.r.*) . = ALIGN(8); - } >main + } >main AT>glob - .eh_frame_hdr : { __eh_frame_hdr_start = .; *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) __eh_frame_hdr_end = .; } >main - .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } >main - .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } >main - .gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } >main + .eh_frame_hdr : { __eh_frame_hdr_start = .; *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) __eh_frame_hdr_end = .; } >main AT>glob + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } >main AT>glob + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } >main AT>glob + .gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } >main AT>glob - .hash : { *(.hash) } >main + .hash : { *(.hash) } >main AT>glob /* =========== DATA section =========== */ . = ALIGN(8); __data_start = . ; - .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } >main - .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } >main - .gnu_extab : ONLY_IF_RW { *(.gnu_extab*) } >main - .exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } >main + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } >main AT>glob + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } >main AT>glob + .gnu_extab : ONLY_IF_RW { *(.gnu_extab*) } >main AT>glob + .exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } >main AT>glob .preinit_array ALIGN(8) : { PROVIDE (__preinit_array_start = .); KEEP (*(.preinit_array)) PROVIDE (__preinit_array_end = .); - } >main + } >main AT>glob .init_array ALIGN(8) : { @@ -91,7 +84,7 @@ SECTIONS KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array)) PROVIDE (__init_array_end = .); - } >main + } >main AT>glob .fini_array ALIGN(8) : { @@ -99,7 +92,7 @@ SECTIONS KEEP (*(.fini_array)) KEEP (*(SORT(.fini_array.*))) PROVIDE (__fini_array_end = .); - } >main + } >main AT>glob .ctors ALIGN(8) : { @@ -107,7 +100,7 @@ SECTIONS KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) KEEP (*(SORT(.ctors.*))) KEEP (*(.ctors)) - } >main + } >main AT>glob .dtors ALIGN(8) : { @@ -115,7 +108,7 @@ SECTIONS KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) KEEP (*(SORT(.dtors.*))) KEEP (*(.dtors)) - } >main + } >main AT>glob __got_start__ = .; @@ -128,7 +121,7 @@ SECTIONS { *(.data .data.* .gnu.linkonce.d.*) SORT(CONSTRUCTORS) - } >main + } >main AT>glob __bss_start__ = .; .bss ALIGN(8) : @@ -137,11 +130,17 @@ SECTIONS *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON) . = ALIGN(16); - } >main - __bss_end__ = .; + } >main AT>glob + __bss_end__ = .; __main_end__ = ABSOLUTE(.) ; + .main.fill : { + FILL(0x00000000) + . = ORIGIN(main) + LENGTH(main) - 1; + BYTE(0x00); + } >main AT>glob + /* ================== ==== Metadata ==== ================== */ diff --git a/fusee_cpp/program/program.specs b/fusee_cpp/program/program.specs index 7d174b721..6940a62b1 100644 --- a/fusee_cpp/program/program.specs +++ b/fusee_cpp/program/program.specs @@ -1,4 +1,4 @@ %rename link old_link *link: -%(old_link) -T %:getenv(TOPDIR /program.ld) --gc-sections --nmagic \ No newline at end of file +%(old_link) -T %:getenv(TOPDIR /program_ovl.ld) -T %:getenv(TOPDIR /program.ld) --gc-sections --nmagic \ No newline at end of file diff --git a/fusee_cpp/program/program_ovl.ld b/fusee_cpp/program/program_ovl.ld new file mode 100644 index 000000000..acda8eb77 --- /dev/null +++ b/fusee_cpp/program/program_ovl.ld @@ -0,0 +1,22 @@ +MEMORY +{ + NULL : ORIGIN = 0, LENGTH = 4K + glob : ORIGIN = 0x40001000, LENGTH = 0x3F000 + main : ORIGIN = 0x40001000, LENGTH = 0x2B000 + ovl : ORIGIN = 0x4002C000, LENGTH = 0x14000 +} + +SECTIONS { + OVERLAY : NOCROSSREFS { + .ovl_sein { + fusee_secure_initialize.o(.text*); + fusee_secure_initialize.o(.rodata*); + fusee_secure_initialize.o(.data*); + fusee_secure_initialize.o(.bss*); + FILL(0x00000000) + . = ORIGIN(ovl) + LENGTH(ovl) - 1; + BYTE(0x00); + } + } >ovl AT>glob +} +INSERT AFTER .main.fill \ No newline at end of file diff --git a/fusee_cpp/program/source/fusee_main.cpp b/fusee_cpp/program/source/fusee_main.cpp index f57175850..8e7c6d595 100644 --- a/fusee_cpp/program/source/fusee_main.cpp +++ b/fusee_cpp/program/source/fusee_main.cpp @@ -14,10 +14,14 @@ * along with this program. If not, see . */ #include +#include "fusee_secure_initialize.hpp" namespace ams::nxboot { void Main() { + /* Perform secure hardware initialization. */ + SecureInitialize(); + /* TODO */ AMS_INFINITE_LOOP(); } diff --git a/fusee_cpp/program/source/fusee_registers_di.hpp b/fusee_cpp/program/source/fusee_registers_di.hpp new file mode 100644 index 000000000..92d834eff --- /dev/null +++ b/fusee_cpp/program/source/fusee_registers_di.hpp @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (C) 2018 CTCaer + * 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 License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include + +#define DC_CMD_GENERAL_INCR_SYNCPT 0x00 + +#define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x01 +#define SYNCPT_CNTRL_NO_STALL (1 << 8) +#define SYNCPT_CNTRL_SOFT_RESET (1 << 0) + +#define DC_CMD_CONT_SYNCPT_VSYNC 0x28 +#define SYNCPT_VSYNC_ENABLE (1 << 8) + +#define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031 + +#define DC_CMD_DISPLAY_COMMAND 0x32 +#define DISP_CTRL_MODE_STOP (0 << 5) +#define DISP_CTRL_MODE_C_DISPLAY (1 << 5) +#define DISP_CTRL_MODE_NC_DISPLAY (2 << 5) +#define DISP_CTRL_MODE_MASK (3 << 5) + +#define DC_CMD_DISPLAY_POWER_CONTROL 0x36 +#define PW0_ENABLE (1 << 0) +#define PW1_ENABLE (1 << 2) +#define PW2_ENABLE (1 << 4) +#define PW3_ENABLE (1 << 6) +#define PW4_ENABLE (1 << 8) +#define PM0_ENABLE (1 << 16) +#define PM1_ENABLE (1 << 18) + +#define DC_CMD_INT_STATUS 0x37 +#define DC_CMD_INT_MASK 0x38 +#define DC_CMD_INT_ENABLE 0x39 + +#define DC_CMD_STATE_ACCESS 0x40 +#define READ_MUX (1 << 0) +#define WRITE_MUX (1 << 2) + +#define DC_CMD_STATE_CONTROL 0x41 +#define GENERAL_ACT_REQ (1 << 0) +#define WIN_A_ACT_REQ (1 << 1) +#define WIN_B_ACT_REQ (1 << 2) +#define WIN_C_ACT_REQ (1 << 3) +#define CURSOR_ACT_REQ (1 << 7) +#define GENERAL_UPDATE (1 << 8) +#define WIN_A_UPDATE (1 << 9) +#define WIN_B_UPDATE (1 << 10) +#define WIN_C_UPDATE (1 << 11) +#define CURSOR_UPDATE (1 << 15) +#define NC_HOST_TRIG (1 << 24) + +#define DC_CMD_DISPLAY_WINDOW_HEADER 0x42 +#define WINDOW_A_SELECT (1 << 4) +#define WINDOW_B_SELECT (1 << 5) +#define WINDOW_C_SELECT (1 << 6) + +#define DC_CMD_REG_ACT_CONTROL 0x043 + +#define DC_COM_CRC_CONTROL 0x300 +#define DC_COM_PIN_OUTPUT_ENABLE(x) (0x302 + (x)) +#define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x)) + +#define DC_COM_DSC_TOP_CTL 0x33E + +#define DC_DISP_DISP_WIN_OPTIONS 0x402 +#define HDMI_ENABLE (1 << 30) +#define DSI_ENABLE (1 << 29) +#define SOR1_TIMING_CYA (1 << 27) +#define SOR1_ENABLE (1 << 26) +#define SOR_ENABLE (1 << 25) +#define CURSOR_ENABLE (1 << 16) + +#define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403 +#define DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER 0x404 +#define DC_DISP_DISP_TIMING_OPTIONS 0x405 +#define DC_DISP_REF_TO_SYNC 0x406 +#define DC_DISP_SYNC_WIDTH 0x407 +#define DC_DISP_BACK_PORCH 0x408 +#define DC_DISP_ACTIVE 0x409 +#define DC_DISP_FRONT_PORCH 0x40A + +#define DC_DISP_DISP_CLOCK_CONTROL 0x42E +#define PIXEL_CLK_DIVIDER_PCD1 (0 << 8) +#define PIXEL_CLK_DIVIDER_PCD1H (1 << 8) +#define PIXEL_CLK_DIVIDER_PCD2 (2 << 8) +#define PIXEL_CLK_DIVIDER_PCD3 (3 << 8) +#define PIXEL_CLK_DIVIDER_PCD4 (4 << 8) +#define PIXEL_CLK_DIVIDER_PCD6 (5 << 8) +#define PIXEL_CLK_DIVIDER_PCD8 (6 << 8) +#define PIXEL_CLK_DIVIDER_PCD9 (7 << 8) +#define PIXEL_CLK_DIVIDER_PCD12 (8 << 8) +#define PIXEL_CLK_DIVIDER_PCD16 (9 << 8) +#define PIXEL_CLK_DIVIDER_PCD18 (10 << 8) +#define PIXEL_CLK_DIVIDER_PCD24 (11 << 8) +#define PIXEL_CLK_DIVIDER_PCD13 (12 << 8) +#define SHIFT_CLK_DIVIDER(x) ((x) & 0xff) + +#define DC_DISP_DISP_INTERFACE_CONTROL 0x42F +#define DISP_DATA_FORMAT_DF1P1C (0 << 0) +#define DISP_DATA_FORMAT_DF1P2C24B (1 << 0) +#define DISP_DATA_FORMAT_DF1P2C18B (2 << 0) +#define DISP_DATA_FORMAT_DF1P2C16B (3 << 0) +#define DISP_DATA_FORMAT_DF2S (4 << 0) +#define DISP_DATA_FORMAT_DF3S (5 << 0) +#define DISP_DATA_FORMAT_DFSPI (6 << 0) +#define DISP_DATA_FORMAT_DF1P3C24B (7 << 0) +#define DISP_DATA_FORMAT_DF1P3C18B (8 << 0) +#define DISP_ALIGNMENT_MSB (0 << 8) +#define DISP_ALIGNMENT_LSB (1 << 8) +#define DISP_ORDER_RED_BLUE (0 << 9) +#define DISP_ORDER_BLUE_RED (1 << 9) + +#define DC_DISP_DISP_COLOR_CONTROL 0x430 +#define DITHER_CONTROL_MASK (3 << 8) +#define DITHER_CONTROL_DISABLE (0 << 8) +#define DITHER_CONTROL_ORDERED (2 << 8) +#define DITHER_CONTROL_ERRDIFF (3 << 8) +#define BASE_COLOR_SIZE_MASK (0xf << 0) +#define BASE_COLOR_SIZE_666 (0 << 0) +#define BASE_COLOR_SIZE_111 (1 << 0) +#define BASE_COLOR_SIZE_222 (2 << 0) +#define BASE_COLOR_SIZE_333 (3 << 0) +#define BASE_COLOR_SIZE_444 (4 << 0) +#define BASE_COLOR_SIZE_555 (5 << 0) +#define BASE_COLOR_SIZE_565 (6 << 0) +#define BASE_COLOR_SIZE_332 (7 << 0) +#define BASE_COLOR_SIZE_888 (8 << 0) + +#define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431 +#define SC1_H_QUALIFIER_NONE (1 << 16) +#define SC0_H_QUALIFIER_NONE (1 << 0) + +#define DC_DISP_DATA_ENABLE_OPTIONS 0x432 +#define DE_SELECT_ACTIVE_BLANK (0 << 0) +#define DE_SELECT_ACTIVE (1 << 0) +#define DE_SELECT_ACTIVE_IS (2 << 0) +#define DE_CONTROL_ONECLK (0 << 2) +#define DE_CONTROL_NORMAL (1 << 2) +#define DE_CONTROL_EARLY_EXT (2 << 2) +#define DE_CONTROL_EARLY (3 << 2) +#define DE_CONTROL_ACTIVE_BLANK (4 << 2) + +#define DC_DISP_DC_MCCIF_FIFOCTRL 0x480 +#define DC_DISP_SD_BL_PARAMETERS 0x4D7 +#define DC_DISP_SD_BL_CONTROL 0x4DC +#define DC_DISP_BLEND_BACKGROUND_COLOR 0x4E4 + +#define DC_WIN_CSC_YOF 0x611 +#define DC_WIN_CSC_KYRGB 0x612 +#define DC_WIN_CSC_KUR 0x613 +#define DC_WIN_CSC_KVR 0x614 +#define DC_WIN_CSC_KUG 0x615 +#define DC_WIN_CSC_KVG 0x616 +#define DC_WIN_CSC_KUB 0x617 +#define DC_WIN_CSC_KVB 0x618 +#define DC_WIN_AD_WIN_OPTIONS 0xB80 +#define DC_WIN_BD_WIN_OPTIONS 0xD80 +#define DC_WIN_CD_WIN_OPTIONS 0xF80 + +// The following registers are A/B/C shadows of the 0xB80/0xD80/0xF80 registers (see DISPLAY_WINDOW_HEADER). +#define DC_WIN_WIN_OPTIONS 0x700 +#define H_DIRECTION (1 << 0) +#define V_DIRECTION (1 << 2) +#define SCAN_COLUMN (1 << 4) +#define COLOR_EXPAND (1 << 6) +#define CSC_ENABLE (1 << 18) +#define WIN_ENABLE (1 << 30) + +#define DC_WIN_COLOR_DEPTH 0x703 +#define WIN_COLOR_DEPTH_P1 0x0 +#define WIN_COLOR_DEPTH_P2 0x1 +#define WIN_COLOR_DEPTH_P4 0x2 +#define WIN_COLOR_DEPTH_P8 0x3 +#define WIN_COLOR_DEPTH_B4G4R4A4 0x4 +#define WIN_COLOR_DEPTH_B5G5R5A 0x5 +#define WIN_COLOR_DEPTH_B5G6R5 0x6 +#define WIN_COLOR_DEPTH_AB5G5R5 0x7 +#define WIN_COLOR_DEPTH_B8G8R8A8 0xC +#define WIN_COLOR_DEPTH_R8G8B8A8 0xD +#define WIN_COLOR_DEPTH_B6x2G6x2R6x2A8 0xE +#define WIN_COLOR_DEPTH_R6x2G6x2B6x2A8 0xF +#define WIN_COLOR_DEPTH_YCbCr422 0x10 +#define WIN_COLOR_DEPTH_YUV422 0x11 +#define WIN_COLOR_DEPTH_YCbCr420P 0x12 +#define WIN_COLOR_DEPTH_YUV420P 0x13 +#define WIN_COLOR_DEPTH_YCbCr422P 0x14 +#define WIN_COLOR_DEPTH_YUV422P 0x15 +#define WIN_COLOR_DEPTH_YCbCr422R 0x16 +#define WIN_COLOR_DEPTH_YUV422R 0x17 +#define WIN_COLOR_DEPTH_YCbCr422RA 0x18 +#define WIN_COLOR_DEPTH_YUV422RA 0x19 + +#define DC_WIN_BUFFER_CONTROL 0x702 +#define DC_WIN_POSITION 0x704 + +#define DC_WIN_SIZE 0x705 +#define H_SIZE(x) (((x) & 0x1fff) << 0) +#define V_SIZE(x) (((x) & 0x1fff) << 16) + +#define DC_WIN_PRESCALED_SIZE 0x706 +#define H_PRESCALED_SIZE(x) (((x) & 0x7fff) << 0) +#define V_PRESCALED_SIZE(x) (((x) & 0x1fff) << 16) + +#define DC_WIN_H_INITIAL_DDA 0x707 +#define DC_WIN_V_INITIAL_DDA 0x708 + +#define DC_WIN_DDA_INC 0x709 +#define H_DDA_INC(x) (((x) & 0xffff) << 0) +#define V_DDA_INC(x) (((x) & 0xffff) << 16) + +#define DC_WIN_LINE_STRIDE 0x70A +#define LINE_STRIDE(x) (x) +#define UV_LINE_STRIDE(x) (((x) & 0xffff) << 16) +#define DC_WIN_DV_CONTROL 0x70E + +// The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER). +#define DC_WINBUF_START_ADDR 0x800 +#define DC_WINBUF_ADDR_H_OFFSET 0x806 +#define DC_WINBUF_ADDR_V_OFFSET 0x808 +#define DC_WINBUF_SURFACE_KIND 0x80B +#define PITCH (0 << 0) +#define TILED (1 << 0) +#define BLOCK (2 << 0) +#define BLOCK_HEIGHT(x) (((x) & 0x7) << 4) + +/*! Display serial interface registers. */ +#define _DSIREG(reg) ((reg) * 4) + +#define DSI_INCR_SYNCPT_CNTRL 0x1 + +#define DSI_RD_DATA 0x9 +#define DSI_WR_DATA 0xA + +#define DSI_POWER_CONTROL 0xB +#define DSI_POWER_CONTROL_ENABLE 1 + +#define DSI_INT_ENABLE 0xC +#define DSI_INT_STATUS 0xD +#define DSI_INT_MASK 0xE + +#define DSI_HOST_CONTROL 0xF +#define DSI_HOST_CONTROL_FIFO_RESET (1 << 21) +#define DSI_HOST_CONTROL_CRC_RESET (1 << 20) +#define DSI_HOST_CONTROL_TX_TRIG_SOL (0 << 12) +#define DSI_HOST_CONTROL_TX_TRIG_FIFO (1 << 12) +#define DSI_HOST_CONTROL_TX_TRIG_HOST (2 << 12) +#define DSI_HOST_CONTROL_RAW (1 << 6) +#define DSI_HOST_CONTROL_HS (1 << 5) +#define DSI_HOST_CONTROL_FIFO_SEL (1 << 4) +#define DSI_HOST_CONTROL_IMM_BTA (1 << 3) +#define DSI_HOST_CONTROL_PKT_BTA (1 << 2) +#define DSI_HOST_CONTROL_CS (1 << 1) +#define DSI_HOST_CONTROL_ECC (1 << 0) + +#define DSI_CONTROL 0x10 +#define DSI_CONTROL_HS_CLK_CTRL (1 << 20) +#define DSI_CONTROL_CHANNEL(c) (((c) & 0x3) << 16) +#define DSI_CONTROL_FORMAT(f) (((f) & 0x3) << 12) +#define DSI_CONTROL_TX_TRIG(x) (((x) & 0x3) << 8) +#define DSI_CONTROL_LANES(n) (((n) & 0x3) << 4) +#define DSI_CONTROL_DCS_ENABLE (1 << 3) +#define DSI_CONTROL_SOURCE(s) (((s) & 0x1) << 2) +#define DSI_CONTROL_VIDEO_ENABLE (1 << 1) +#define DSI_CONTROL_HOST_ENABLE (1 << 0) + +#define DSI_SOL_DELAY 0x11 +#define DSI_MAX_THRESHOLD 0x12 + +#define DSI_TRIGGER 0x13 +#define DSI_TRIGGER_HOST (1 << 1) +#define DSI_TRIGGER_VIDEO (1 << 0) + +#define DSI_TX_CRC 0x14 +#define DSI_STATUS 0x15 +#define DSI_INIT_SEQ_CONTROL 0x1A +#define DSI_INIT_SEQ_DATA_0 0x1B +#define DSI_INIT_SEQ_DATA_1 0x1C +#define DSI_INIT_SEQ_DATA_2 0x1D +#define DSI_INIT_SEQ_DATA_3 0x1E +#define DSI_PKT_SEQ_0_LO 0x23 +#define DSI_PKT_SEQ_0_HI 0x24 +#define DSI_PKT_SEQ_1_LO 0x25 +#define DSI_PKT_SEQ_1_HI 0x26 +#define DSI_PKT_SEQ_2_LO 0x27 +#define DSI_PKT_SEQ_2_HI 0x28 +#define DSI_PKT_SEQ_3_LO 0x29 +#define DSI_PKT_SEQ_3_HI 0x2A +#define DSI_PKT_SEQ_4_LO 0x2B +#define DSI_PKT_SEQ_4_HI 0x2C +#define DSI_PKT_SEQ_5_LO 0x2D +#define DSI_PKT_SEQ_5_HI 0x2E +#define DSI_DCS_CMDS 0x33 +#define DSI_PKT_LEN_0_1 0x34 +#define DSI_PKT_LEN_2_3 0x35 +#define DSI_PKT_LEN_4_5 0x36 +#define DSI_PKT_LEN_6_7 0x37 +#define DSI_PHY_TIMING_0 0x3C +#define DSI_PHY_TIMING_1 0x3D +#define DSI_PHY_TIMING_2 0x3E +#define DSI_BTA_TIMING 0x3F + +#define DSI_TIMEOUT_0 0x44 +#define DSI_TIMEOUT_LRX(x) (((x) & 0xffff) << 16) +#define DSI_TIMEOUT_HTX(x) (((x) & 0xffff) << 0) + +#define DSI_TIMEOUT_1 0x45 +#define DSI_TIMEOUT_PR(x) (((x) & 0xffff) << 16) +#define DSI_TIMEOUT_TA(x) (((x) & 0xffff) << 0) + +#define DSI_TO_TALLY 0x46 + +#define DSI_PAD_CONTROL_0 0x4B +#define DSI_PAD_CONTROL_VS1_PULLDN_CLK (1 << 24) +#define DSI_PAD_CONTROL_VS1_PULLDN(x) (((x) & 0xf) << 16) +#define DSI_PAD_CONTROL_VS1_PDIO_CLK (1 << 8) +#define DSI_PAD_CONTROL_VS1_PDIO(x) (((x) & 0xf) << 0) + +#define DSI_PAD_CONTROL_CD 0x4c +#define DSI_VIDEO_MODE_CONTROL 0x4E + +#define DSI_PAD_CONTROL_1 0x4F +#define DSI_PAD_CONTROL_2 0x50 + +#define DSI_PAD_CONTROL_3 0x51 +#define DSI_PAD_PREEMP_PD_CLK(x) (((x) & 0x3) << 12) +#define DSI_PAD_PREEMP_PU_CLK(x) (((x) & 0x3) << 8) +#define DSI_PAD_PREEMP_PD(x) (((x) & 0x3) << 4) +#define DSI_PAD_PREEMP_PU(x) (((x) & 0x3) << 0) + +#define DSI_PAD_CONTROL_4 0x52 +#define DSI_PAD_CONTROL_5_MARIKO 0x53 +#define DSI_PAD_CONTROL_6_MARIKO 0x54 +#define DSI_PAD_CONTROL_7_MARIKO 0x55 +#define DSI_INIT_SEQ_DATA_15 0x5F + +#define DSI_INIT_SEQ_DATA_15_MARIKO 0x62 + +#define NV_PVIC_THI_SLCG_OVERRIDE_LOW_A 0x8C diff --git a/fusee_cpp/program/source/fusee_secure_initialize.cpp b/fusee_cpp/program/source/fusee_secure_initialize.cpp new file mode 100644 index 000000000..24d12d372 --- /dev/null +++ b/fusee_cpp/program/source/fusee_secure_initialize.cpp @@ -0,0 +1,185 @@ +/* + * 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 License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "fusee_secure_initialize.hpp" +#include "fusee_registers_di.hpp" + +namespace ams::nxboot { + + namespace { + + constexpr inline const uintptr_t CLKRST = secmon::MemoryRegionPhysicalDeviceClkRst.GetAddress(); + constexpr inline const uintptr_t PMC = secmon::MemoryRegionPhysicalDevicePmc.GetAddress(); + constexpr inline const uintptr_t AHB = AHB_ARBC(0); + constexpr inline const uintptr_t I2S = I2S_REG(0); + constexpr inline const uintptr_t DISP1 = secmon::MemoryRegionPhysicalDeviceDisp1.GetAddress(); + constexpr inline const uintptr_t VIC = secmon::MemoryRegionPhysicalDeviceDsi.GetAddress() + 0x40000; + + void DoRcmWorkaround(const void *sbk, size_t sbk_size) { + /* Set the SBK inside the security engine. */ + se::SetAesKey(pkg1::AesKeySlot_SecureBoot, sbk, sbk_size); + + /* Lock the SBK/SSK as unreadable. */ + se::LockAesKeySlot(pkg1::AesKeySlot_SecureBoot, se::KeySlotLockFlags_KeyRead); + se::LockAesKeySlot(pkg1::AesKeySlot_SecureStorage, se::KeySlotLockFlags_KeyRead); + + /* Clear TZRAM. */ + std::memset(secmon::MemoryRegionPhysicalTzram.GetPointer(), 0, secmon::MemoryRegionPhysicalTzram.GetSize()); + + /* Clear APBDEV_PMC_CRYPTO_OP. */ + reg::Write(PMC + APBDEV_PMC_CRYPTO_OP, 0); + + /* Clear the boot reason. */ + reg::Write(PMC + APBDEV_PMC_SCRATCH200, 0); + reg::Write(PMC + APBDEV_PMC_CRYPTO_OP, 0); + + /* Clear OBS_OVERRIDE/APB2JTAG_OVERRIDE */ + reg::ReadWrite(AHB + AHB_AHB_SPARE_REG, AHB_REG_BITS_ENUM(AHB_SPARE_REG_OBS_OVERRIDE_EN, DISABLE), + AHB_REG_BITS_ENUM(AHB_SPARE_REG_APB2JTAG_OVERRIDE_EN, DISABLE)); + + /* Clear low bits of APBDEV_PMC_SCRATCH49 */ + reg::ClearBits(PMC + APBDEV_PMC_SCRATCH49, 0x3); + } + + void DoMbistWorkaround() { + /* Configure CLK_RST_CONTROLLER_CLK_SOURCE_SOR1. */ + reg::ReadWrite(CLKRST + CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, CLK_RST_REG_BITS_ENUM(CLK_SOURCE_SOR1_SOR1_CLK_SEL0, MUX), + CLK_RST_REG_BITS_ENUM(CLK_SOURCE_SOR1_SOR1_CLK_SEL1, SOR1_CLOCK_SWITCH)); + + /* Set CSI clock source as PLLD. */ + reg::ReadWrite(CLKRST + CLK_RST_CONTROLLER_PLLD_BASE, CLK_RST_REG_BITS_ENUM(PLLD_BASE_PLLD_ENABLE, ENABLE), + CLK_RST_REG_BITS_ENUM(PLLD_BASE_CSI_CLK_SRC, PLL_D)); + + /* Clear APE, VIC, HOST1X, DISP1 reset. */ + reg::Write(CLKRST + CLK_RST_CONTROLLER_RST_DEV_Y_CLR, CLK_RST_REG_BITS_ENUM(RST_DEV_Y_APE_RST, ENABLE)); + reg::Write(CLKRST + CLK_RST_CONTROLLER_RST_DEV_X_CLR, CLK_RST_REG_BITS_ENUM(RST_DEV_X_VIC_RST, ENABLE)); + reg::Write(CLKRST + CLK_RST_CONTROLLER_RST_DEV_L_CLR, CLK_RST_REG_BITS_ENUM(RST_DEV_L_DISP1_RST, ENABLE), CLK_RST_REG_BITS_ENUM(RST_DEV_L_HOST1X_RST, ENABLE)); + + /* Wait two microseconds for the devices to come out of reset. */ + util::WaitMicroSeconds(2); + + /* Set I2S_CTRL.MASTER and clear I2S_CG.SCLG_ENABLE for all I2S registers. */ + reg::ReadWrite(I2S + I2S0_I2S_CTRL, I2S_REG_BITS_ENUM(I2S_CTRL_MASTER, ENABLE)); + reg::ReadWrite(I2S + I2S0_I2S_CG, I2S_REG_BITS_ENUM(I2S_CG_SLCG_ENABLE, FALSE)); + reg::ReadWrite(I2S + I2S1_I2S_CTRL, I2S_REG_BITS_ENUM(I2S_CTRL_MASTER, ENABLE)); + reg::ReadWrite(I2S + I2S1_I2S_CG, I2S_REG_BITS_ENUM(I2S_CG_SLCG_ENABLE, FALSE)); + reg::ReadWrite(I2S + I2S2_I2S_CTRL, I2S_REG_BITS_ENUM(I2S_CTRL_MASTER, ENABLE)); + reg::ReadWrite(I2S + I2S2_I2S_CG, I2S_REG_BITS_ENUM(I2S_CG_SLCG_ENABLE, FALSE)); + reg::ReadWrite(I2S + I2S3_I2S_CTRL, I2S_REG_BITS_ENUM(I2S_CTRL_MASTER, ENABLE)); + reg::ReadWrite(I2S + I2S3_I2S_CG, I2S_REG_BITS_ENUM(I2S_CG_SLCG_ENABLE, FALSE)); + reg::ReadWrite(I2S + I2S4_I2S_CTRL, I2S_REG_BITS_ENUM(I2S_CTRL_MASTER, ENABLE)); + reg::ReadWrite(I2S + I2S4_I2S_CG, I2S_REG_BITS_ENUM(I2S_CG_SLCG_ENABLE, FALSE)); + + /* Set DC_COM_DSC_TOP_CTL.DSC_SLG_OVERRIDE */ + reg::SetBits(DISP1 + DC_COM_DSC_TOP_CTL * sizeof(u32), 0x4); + + /* Set NV_PVIC_THI_SLCG_OVERRIDE_LOW_A */ + reg::SetBits(VIC + NV_PVIC_THI_SLCG_OVERRIDE_LOW_A, 0xFFFFFFFF); + + /* Wait two microseconds for configuration to take. */ + util::WaitMicroSeconds(2); + + /* Set APE, VIC, HOST1X, DISP1 reset. */ + reg::Write(CLKRST + CLK_RST_CONTROLLER_RST_DEV_Y_SET, CLK_RST_REG_BITS_ENUM(RST_DEV_Y_APE_RST, ENABLE)); + reg::Write(CLKRST + CLK_RST_CONTROLLER_RST_DEV_L_SET, CLK_RST_REG_BITS_ENUM(RST_DEV_L_DISP1_RST, ENABLE), CLK_RST_REG_BITS_ENUM(RST_DEV_L_HOST1X_RST, ENABLE)); + reg::Write(CLKRST + CLK_RST_CONTROLLER_RST_DEV_X_SET, CLK_RST_REG_BITS_ENUM(RST_DEV_X_VIC_RST, ENABLE)); + + /* Set clock enable for a select few devices. */ + reg::Write(CLKRST + CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_REG_BITS_ENUM(CLK_ENB_H_CLK_ENB_FUSE, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_ENB_H_CLK_ENB_PMC, ENABLE)); + + reg::Write(CLKRST + CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_REG_BITS_ENUM(CLK_ENB_L_CLK_ENB_CACHE2, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_ENB_L_CLK_ENB_GPIO, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_ENB_L_CLK_ENB_TMR, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_ENB_L_CLK_ENB_RTC, ENABLE)); + + reg::Write(CLKRST + CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_REG_BITS_ENUM(CLK_ENB_U_CLK_ENB_CRAM2, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_ENB_U_CLK_ENB_IRAMD, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_ENB_U_CLK_ENB_IRAMC, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_ENB_U_CLK_ENB_IRAMB, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_ENB_U_CLK_ENB_IRAMA, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_ENB_U_CLK_ENB_CSITE, ENABLE)); + + reg::Write(CLKRST + CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_REG_BITS_ENUM(CLK_ENB_V_CLK_ENB_SE, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_ENB_V_CLK_ENB_SPDIF_DOUBLER, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_ENB_V_CLK_ENB_APB2APE, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_ENB_V_CLK_ENB_MSELECT, ENABLE)); + + reg::Write(CLKRST + CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_RST_REG_BITS_ENUM(CLK_ENB_W_CLK_ENB_MC1, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_ENB_W_CLK_ENB_ENTROPY, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_ENB_W_CLK_ENB_PCIERX5, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_ENB_W_CLK_ENB_PCIERX4, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_ENB_W_CLK_ENB_PCIERX3, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_ENB_W_CLK_ENB_PCIERX2, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_ENB_W_CLK_ENB_PCIERX1, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_ENB_W_CLK_ENB_PCIERX0, ENABLE)); + + reg::Write(CLKRST + CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_REG_BITS_ENUM(CLK_ENB_X_CLK_ENB_PLLG_REF, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_ENB_X_CLK_ENB_DBGAPB, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_ENB_X_CLK_ENB_GPU, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_ENB_X_CLK_ENB_MC_BBC, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_ENB_X_CLK_ENB_MC_CPU, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_ENB_X_CLK_ENB_MC_CBPA, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_ENB_X_CLK_ENB_MC_CAPA, ENABLE)); + + reg::Write(CLKRST + CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_REG_BITS_ENUM(CLK_ENB_Y_CLK_ENB_MC_CDPA, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_ENB_Y_CLK_ENB_MC_CCPA, ENABLE)); + + /* Clear all LVL2 clock gate overrides to zero. */ + reg::Write(CLKRST + CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA, 0); + reg::Write(CLKRST + CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRB, 0); + reg::Write(CLKRST + CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRC, 0); + reg::Write(CLKRST + CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD, 0); + reg::Write(CLKRST + CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRE, 0); + + /* Reset CSI clock source. */ + reg::ReadWrite(CLKRST + CLK_RST_CONTROLLER_PLLD_BASE, CLK_RST_REG_BITS_ENUM(PLLD_BASE_PLLD_BYPASS, DISABLE), + CLK_RST_REG_BITS_ENUM(PLLD_BASE_PLLD_ENABLE, DISABLE), + CLK_RST_REG_BITS_ENUM(PLLD_BASE_PLLD_REF_DIS, REF_ENABLE), + CLK_RST_REG_BITS_ENUM(PLLD_BASE_CSI_CLK_SRC, BRICK)); + + /* Configure CLK_RST_CONTROLLER_CLK_SOURCE_SOR1. */ + reg::ReadWrite(CLKRST + CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, CLK_RST_REG_BITS_ENUM(CLK_SOURCE_SOR1_SOR1_CLK_SEL0, MUX), + CLK_RST_REG_BITS_ENUM(CLK_SOURCE_SOR1_SOR1_CLK_SEL1, SAFE_CLOCK)); + + /* Configure VI, HOST1X, NVENC clock sources. */ + reg::ReadWrite(CLKRST + CLK_RST_CONTROLLER_CLK_SOURCE_VI, CLK_RST_REG_BITS_ENUM(CLK_SOURCE_VI_VI_CLK_SRC, PLLP_OUT0)); + reg::ReadWrite(CLKRST + CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, CLK_RST_REG_BITS_ENUM(CLK_SOURCE_HOST1X_HOST1X_CLK_SRC, PLLP_OUT0)); + reg::ReadWrite(CLKRST + CLK_RST_CONTROLLER_CLK_SOURCE_NVENC, CLK_RST_REG_BITS_ENUM(CLK_SOURCE_NVENC_NVENC_CLK_SRC, PLLP_OUT0)); + } + + } + + void SecureInitialize() { + /* Get SoC type. */ + const auto soc_type = fuse::GetSocType(); + + /* If Erista, perform bootrom logic (to compensate for RCM exploit) and MBIST workaround. */ + if (soc_type == fuse::SocType_Erista) { + /* Potentially perform bootrom compensation. */ + { + u32 sbk[4]; + if (fuse::GetSecureBootKey(sbk)) { + DoRcmWorkaround(sbk, sizeof(sbk)); + } + } + DoMbistWorkaround(); + } + + /* TODO */ + } + +} diff --git a/fusee_cpp/program/source/fusee_secure_initialize.hpp b/fusee_cpp/program/source/fusee_secure_initialize.hpp new file mode 100644 index 000000000..0c3563b87 --- /dev/null +++ b/fusee_cpp/program/source/fusee_secure_initialize.hpp @@ -0,0 +1,23 @@ +/* + * 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 License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#pragma once + +namespace ams::nxboot { + + void SecureInitialize(); + +} \ No newline at end of file diff --git a/libraries/libexosphere/include/exosphere/clkrst.hpp b/libraries/libexosphere/include/exosphere/clkrst.hpp index 2ee681490..2935eb2c1 100644 --- a/libraries/libexosphere/include/exosphere/clkrst.hpp +++ b/libraries/libexosphere/include/exosphere/clkrst.hpp @@ -29,6 +29,21 @@ namespace ams::clkrst { void EnableI2c1Clock(); void EnableI2c5Clock(); + + void EnableHost1xClock(); + void EnableTsecClock(); + void EnableSorSafeClock(); + void EnableSor0Clock(); + void EnableSor1Clock(); + void EnableKfuseClock(); + void DisableI2c1Clock(); + void DisableHost1xClock(); + void DisableTsecClock(); + void DisableSorSafeClock(); + void DisableSor0Clock(); + void DisableSor1Clock(); + void DisableKfuseClock(); + } \ No newline at end of file diff --git a/libraries/libexosphere/include/exosphere/fuse.hpp b/libraries/libexosphere/include/exosphere/fuse.hpp index 3c042db84..7e841ff36 100644 --- a/libraries/libexosphere/include/exosphere/fuse.hpp +++ b/libraries/libexosphere/include/exosphere/fuse.hpp @@ -100,6 +100,8 @@ namespace ams::fuse { DramId GetDramId(); + bool GetSecureBootKey(void *dst); + void GetEcid(br::BootEcid *out); HardwareType GetHardwareType(); HardwareState GetHardwareState(); diff --git a/libraries/libexosphere/include/exosphere/tsec.hpp b/libraries/libexosphere/include/exosphere/tsec.hpp index 454da2efe..0ae458f6f 100644 --- a/libraries/libexosphere/include/exosphere/tsec.hpp +++ b/libraries/libexosphere/include/exosphere/tsec.hpp @@ -18,6 +18,8 @@ namespace ams::tsec { + bool RunTsecFirmware(const void *fw, size_t fw_size); + void Lock(); } \ No newline at end of file diff --git a/libraries/libexosphere/source/clkrst/clkrst_api.cpp b/libraries/libexosphere/source/clkrst/clkrst_api.cpp index 8b3967804..b0f7f7820 100644 --- a/libraries/libexosphere/source/clkrst/clkrst_api.cpp +++ b/libraries/libexosphere/source/clkrst/clkrst_api.cpp @@ -62,11 +62,21 @@ namespace ams::clkrst { .reset_offset = CLK_RST_CONTROLLER_RST_DEVICES_##_REG_, \ .clk_enb_offset = CLK_RST_CONTROLLER_CLK_OUT_ENB_##_REG_, \ .clk_src_offset = CLK_RST_CONTROLLER_CLK_SOURCE_##_NAME_, \ - .index = CLK_RST_CONTROLLER_CLK_ENB_##_NAME_##_INDEX, \ + .index = CLK_RST_CONTROLLER_CLK_ENB_##_NAME_##_INDEX, \ .clk_src = CLK_RST_CONTROLLER_CLK_SOURCE_##_NAME_##_##_NAME_##_CLK_SRC_##_CLK_, \ .clk_div = _DIV_, \ } + #define DEFINE_CLOCK_PARAMETERS_WITHOUT_CLKDIV(_VARNAME_, _REG_, _NAME_) \ + constexpr inline const ClockParameters _VARNAME_ = { \ + .reset_offset = CLK_RST_CONTROLLER_RST_DEVICES_##_REG_, \ + .clk_enb_offset = CLK_RST_CONTROLLER_CLK_OUT_ENB_##_REG_, \ + .clk_src_offset = 0, \ + .index = CLK_RST_CONTROLLER_CLK_ENB_##_NAME_##_INDEX, \ + .clk_src = 0, \ + .clk_div = 0, \ + } + DEFINE_CLOCK_PARAMETERS(UartAClock, L, UARTA, PLLP_OUT0, 0); DEFINE_CLOCK_PARAMETERS(UartBClock, L, UARTB, PLLP_OUT0, 0); DEFINE_CLOCK_PARAMETERS(UartCClock, H, UARTC, PLLP_OUT0, 0); @@ -74,6 +84,14 @@ namespace ams::clkrst { DEFINE_CLOCK_PARAMETERS(I2c5Clock, H, I2C5, CLK_M, 0); DEFINE_CLOCK_PARAMETERS(ActmonClock, V, ACTMON, CLK_M, 0); + DEFINE_CLOCK_PARAMETERS(Host1xClock, L, HOST1X, PLLP_OUT0, 3); + DEFINE_CLOCK_PARAMETERS(TsecClock, U, TSEC, PLLP_OUT0, 2); + DEFINE_CLOCK_PARAMETERS(Sor1Clock, X, SOR1, PLLP_OUT0, 2); + + DEFINE_CLOCK_PARAMETERS_WITHOUT_CLKDIV(SorSafeClock, Y, SOR_SAFE); + DEFINE_CLOCK_PARAMETERS_WITHOUT_CLKDIV(Sor0Clock, X, SOR0); + DEFINE_CLOCK_PARAMETERS_WITHOUT_CLKDIV(KfuseClock, H, KFUSE); + } void SetRegisterAddress(uintptr_t address) { @@ -108,8 +126,56 @@ namespace ams::clkrst { EnableClock(I2c5Clock); } + void EnableHost1xClock() { + EnableClock(Host1xClock); + } + + void EnableTsecClock() { + EnableClock(TsecClock); + } + + void EnableSorSafeClock() { + EnableClock(SorSafeClock); + } + + void EnableSor0Clock() { + EnableClock(Sor0Clock); + } + + void EnableSor1Clock() { + EnableClock(Sor1Clock); + } + + void EnableKfuseClock() { + EnableClock(KfuseClock); + } + void DisableI2c1Clock() { DisableClock(I2c1Clock); } + void DisableHost1xClock() { + DisableClock(Host1xClock); + } + + void DisableTsecClock() { + DisableClock(TsecClock); + } + + void DisableSorSafeClock() { + DisableClock(SorSafeClock); + } + + void DisableSor0Clock() { + DisableClock(Sor0Clock); + } + + void DisableSor1Clock() { + DisableClock(Sor1Clock); + } + + void DisableKfuseClock() { + DisableClock(KfuseClock); + } + } diff --git a/libraries/libexosphere/source/fuse/fuse_api.cpp b/libraries/libexosphere/source/fuse/fuse_api.cpp index ba9157643..c7543c1d6 100644 --- a/libraries/libexosphere/source/fuse/fuse_api.cpp +++ b/libraries/libexosphere/source/fuse/fuse_api.cpp @@ -432,6 +432,19 @@ namespace ams::fuse { return reg::HasValue(GetChipRegistersCommon().FUSE_SECURITY_MODE, FUSE_REG_BITS_ENUM(SECURITY_MODE_SECURITY_MODE, ENABLED)); } + bool GetSecureBootKey(void *dst) { + /* Get the sbk from fuse data. */ + bool valid = false; + for (size_t i = 0; i < 4; ++i) { + const u32 key_word = GetChipRegistersCommon().FUSE_PRIVATE_KEY[i]; + + static_cast(dst)[i] = key_word; + valid |= key_word != 0xFFFFFFFF; + } + + return valid; + } + void ConfigureFuseBypass() { /* Make the fuse registers visible. */ clkrst::SetFuseVisibility(true); diff --git a/libraries/libexosphere/source/tsec/tsec_api.cpp b/libraries/libexosphere/source/tsec/tsec_api.cpp index b8994ebc4..a251b91f2 100644 --- a/libraries/libexosphere/source/tsec/tsec_api.cpp +++ b/libraries/libexosphere/source/tsec/tsec_api.cpp @@ -19,8 +19,41 @@ namespace ams::tsec { namespace { + enum TsecResult { + 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(); + /* Disable clocks once we're done. */ + ON_SCOPE_EXIT { + clkrst::DisableHost1xClock(); + clkrst::DisableTsecClock(); + clkrst::DisableSorSafeClock(); + clkrst::DisableSor0Clock(); + clkrst::DisableSor1Clock(); + clkrst::DisableKfuseClock(); + }; + + /* TODO */ + AMS_UNUSED(fw, fw_size); + return true; + } + + } + + bool RunTsecFirmware(const void *fw, size_t fw_size) { + /* TODO */ + AMS_UNUSED(fw, fw_size); + return RunFirmwareImpl(fw, fw_size); } void Lock() { diff --git a/libraries/libvapours/include/vapours/tegra.hpp b/libraries/libvapours/include/vapours/tegra.hpp index ac69ce1b2..e8887310f 100644 --- a/libraries/libvapours/include/vapours/tegra.hpp +++ b/libraries/libvapours/include/vapours/tegra.hpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include diff --git a/libraries/libvapours/include/vapours/tegra/tegra_clkrst.hpp b/libraries/libvapours/include/vapours/tegra/tegra_clkrst.hpp index 212000363..8287db38f 100644 --- a/libraries/libvapours/include/vapours/tegra/tegra_clkrst.hpp +++ b/libraries/libvapours/include/vapours/tegra/tegra_clkrst.hpp @@ -62,6 +62,11 @@ DEFINE_CLK_RST_REG(MISC_CLK_ENB_CFG_ALL_VISIBLE, 28, 1); DEFINE_CLK_RST_REG_BIT_ENUM(OSC_CTRL_XOE, 0, DISABLE, ENABLE); DEFINE_CLK_RST_REG(OSC_CTRL_XOFS, 4, 6); +DEFINE_CLK_RST_REG_BIT_ENUM(PLLD_BASE_CSI_CLK_SRC, 23, BRICK, PLL_D); +DEFINE_CLK_RST_REG_BIT_ENUM(PLLD_BASE_PLLD_REF_DIS, 29, REF_ENABLE, REF_DISABLE); +DEFINE_CLK_RST_REG_BIT_ENUM(PLLD_BASE_PLLD_ENABLE, 30, DISABLE, ENABLE); +DEFINE_CLK_RST_REG_BIT_ENUM(PLLD_BASE_PLLD_BYPASS, 31, DISABLE, ENABLE); + DEFINE_CLK_RST_REG_BIT_ENUM(PLLX_BASE_PLLX_ENABLE, 30, DISABLE, ENABLE); DEFINE_CLK_RST_REG(SUPER_CCLK_DIVIDER_SUPER_CDIV_DIVISOR, 0, 8); @@ -111,37 +116,48 @@ DEFINE_CLK_RST_REG_BIT_ENUM(PLLC4_BASE_PLLC4_ENABLE, 30, DISABLE, ENABLE); #define CLK_RST_CONTROLLER_CLK_SOURCE_I2C1 (0x124) #define CLK_RST_CONTROLLER_CLK_SOURCE_I2C5 (0x128) #define CLK_RST_CONTROLLER_CLK_SOURCE_DISP1 (0x138) +#define CLK_RST_CONTROLLER_CLK_SOURCE_VI (0x148) #define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC1 (0x150) #define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC2 (0x154) #define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC4 (0x164) #define CLK_RST_CONTROLLER_CLK_SOURCE_UARTA (0x178) #define CLK_RST_CONTROLLER_CLK_SOURCE_UARTB (0x17C) +#define CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X (0x180) #define CLK_RST_CONTROLLER_CLK_SOURCE_I2C2 (0x198) #define CLK_RST_CONTROLLER_CLK_SOURCE_UARTC (0x1A0) #define CLK_RST_CONTROLLER_CLK_SOURCE_I2C3 (0x1B8) #define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC3 (0x1BC) #define CLK_RST_CONTROLLER_CLK_SOURCE_CSITE (0x1D4) +#define CLK_RST_CONTROLLER_CLK_SOURCE_TSEC (0x1F4) #define CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT (0x3B4) #define CLK_RST_CONTROLLER_CLK_SOURCE_I2C4 (0x3C4) #define CLK_RST_CONTROLLER_CLK_SOURCE_ACTMON (0x3E8) +#define CLK_RST_CONTROLLER_CLK_SOURCE_SOR1 (0x410) #define CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP (0x620) #define CLK_RST_CONTROLLER_CLK_SOURCE_DVFS_REF (0x62C) #define CLK_RST_CONTROLLER_CLK_SOURCE_DVFS_SOC (0x630) #define CLK_RST_CONTROLLER_CLK_SOURCE_I2C6 (0x65C) #define CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIPI_CAL (0x66C) #define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM (0x694) +#define CLK_RST_CONTROLLER_CLK_SOURCE_NVENC (0x6A4) /* RST_DEV_*_SET */ #define CLK_RST_CONTROLLER_RST_DEV_L_SET (0x300) #define CLK_RST_CONTROLLER_RST_DEV_H_SET (0x308) #define CLK_RST_CONTROLLER_RST_DEV_U_SET (0x310) #define CLK_RST_CONTROLLER_RST_DEV_V_SET (0x430) +#define CLK_RST_CONTROLLER_RST_DEV_W_SET (0x438) +#define CLK_RST_CONTROLLER_RST_DEV_X_SET (0x290) +#define CLK_RST_CONTROLLER_RST_DEV_Y_SET (0x2A8) /* RST_DEV_*_CLR */ #define CLK_RST_CONTROLLER_RST_DEV_L_CLR (0x304) #define CLK_RST_CONTROLLER_RST_DEV_H_CLR (0x30C) #define CLK_RST_CONTROLLER_RST_DEV_U_CLR (0x314) #define CLK_RST_CONTROLLER_RST_DEV_V_CLR (0x434) +#define CLK_RST_CONTROLLER_RST_DEV_W_CLR (0x43C) +#define CLK_RST_CONTROLLER_RST_DEV_X_CLR (0x294) +#define CLK_RST_CONTROLLER_RST_DEV_Y_CLR (0x2AC) /* CLK_ENB_*_SET */ #define CLK_RST_CONTROLLER_CLK_ENB_L_SET (0x320) @@ -193,6 +209,13 @@ DEFINE_CLK_RST_REG_BIT_ENUM(PLLC4_BASE_PLLC4_ENABLE, 30, DISABLE, ENABLE); #define CLK_RST_CONTROLLER_CLK_ENB_ACTMON_INDEX (0x17) +#define CLK_RST_CONTROLLER_CLK_ENB_HOST1X_INDEX (0x1C) +#define CLK_RST_CONTROLLER_CLK_ENB_TSEC_INDEX (0x13) +#define CLK_RST_CONTROLLER_CLK_ENB_SOR0_INDEX (0x16) +#define CLK_RST_CONTROLLER_CLK_ENB_SOR1_INDEX (0x17) +#define CLK_RST_CONTROLLER_CLK_ENB_SOR_SAFE_INDEX (0x1E) +#define CLK_RST_CONTROLLER_CLK_ENB_KFUSE_INDEX (0x08) + /* RST_CPUG_CMPLX_* */ #define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_SET (0x450) #define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR (0x454) @@ -235,6 +258,19 @@ DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_UARTA_UARTA_CLK_SRC, 29, PLLP_OUT0, DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_UARTB_UARTB_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, RESERVED4, PLLC4_OUT1, CLK_M, PLLC4_OUT2); DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_UARTC_UARTC_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, RESERVED4, PLLC4_OUT1, CLK_M, PLLC4_OUT2); +DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_VI_VI_CLK_SRC, 29, RESERVED0, PLLC2_OUT0, PLLC_OUT, PLLC3_OUT0, PLLP_OUT0, CLK_M, PLLA1_OUT0, PLLC4_OUT0); + +DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_HOST1X_HOST1X_CLK_SRC, 29, PLLC4_OUT1, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT2, PLLP_OUT0, CLK_M, PLLA_OUT0, PLLC4_OUT0); + +DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_NVENC_NVENC_CLK_SRC, 29, RESERVED0, PLLC2_OUT0, PLLC_OUT0, PLLC3_OUT0, PLLP_OUT0, RESERVED5, PLLA1_OUT0, CLK_M); + +DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_TSEC_TSEC_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC3_OUT0, RESERVED4, PLLA1_OUT0, CLK_M, PLLC4_OUT0); + +DEFINE_CLK_RST_REG_BIT_ENUM(CLK_SOURCE_SOR1_SOR1_CLK_SEL0, 14, MUX, SOR1_BRICK_OUTPUT); +DEFINE_CLK_RST_REG_BIT_ENUM(CLK_SOURCE_SOR1_SOR1_CLK_SEL1, 15, SAFE_CLOCK, SOR1_CLOCK_SWITCH); + +DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_SOR1_SOR1_CLK_SRC, 29, PLLP_OUT0, RESERVED1, PLLD_OUT0, RESERVED3, RESERVED4, PLLD2_OUT0, CLK_M, RESERVED7); + DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_MSELECT_MSELECT_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT2, PLLC4_OUT1, CLK_S, CLK_M, PLLC4_OUT0); DEFINE_CLK_RST_REG(CLK_SOURCE_MSELECT_MSELECT_CLK_DIVISOR, 0, 8); @@ -302,6 +338,7 @@ DEFINE_CLK_RST_REG_BIT_ENUM(RST_CPUG_CMPLX_CLR_CLR_NONCPURESET, 29, DISABLE, ENA HANDLER(U, CRAM2, 2, 24) \ HANDLER(V, CPUG, 3, 0) \ HANDLER(V, MSELECT, 3, 3) \ + HANDLER(V, APB2APE, 3, 11) \ HANDLER(V, SPDIF_DOUBLER, 3, 22) \ HANDLER(V, ACTMON, 3, 23) \ HANDLER(V, TZRAM, 3, 30) \ @@ -322,10 +359,12 @@ DEFINE_CLK_RST_REG_BIT_ENUM(RST_CPUG_CMPLX_CLR_CLR_NONCPURESET, 29, DISABLE, ENA HANDLER(X, MC_BBC, 5, 10) \ HANDLER(X, EMC_DLL, 5, 14) \ HANDLER(X, UART_FST_MIPI_CAL, 5, 17) \ + HANDLER(X, VIC, 5, 18) \ HANDLER(X, GPU, 5, 24) \ HANDLER(X, DBGAPB, 5, 25) \ HANDLER(X, PLLG_REF, 5, 29) \ HANDLER(Y, LEGACY_TM, 6, 1) \ + HANDLER(Y, APE, 6, 6) \ HANDLER(Y, MC_CCPA, 6, 8) \ HANDLER(Y, MC_CDPA, 6, 9) \ HANDLER(Y, PLLP_OUT_CPU, 6, 31) diff --git a/libraries/libvapours/include/vapours/tegra/tegra_i2s.hpp b/libraries/libvapours/include/vapours/tegra/tegra_i2s.hpp new file mode 100644 index 000000000..c967d24b3 --- /dev/null +++ b/libraries/libvapours/include/vapours/tegra/tegra_i2s.hpp @@ -0,0 +1,52 @@ +/* + * 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 License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include +#include +#include +#include +#include +#include + +#define I2S_REG(x) (0x702d1000 + x) + + +#define I2S0_I2S_CG (0x088) +#define I2S0_I2S_CTRL (0x0A0) +#define I2S1_I2S_CG (0x188) +#define I2S1_I2S_CTRL (0x1A0) +#define I2S2_I2S_CG (0x288) +#define I2S2_I2S_CTRL (0x2A0) +#define I2S3_I2S_CG (0x388) +#define I2S3_I2S_CTRL (0x3A0) +#define I2S4_I2S_CG (0x488) +#define I2S4_I2S_CTRL (0x4A0) + +#define I2S_REG_BITS_MASK(NAME) REG_NAMED_BITS_MASK (I2S, NAME) +#define I2S_REG_BITS_VALUE(NAME, VALUE) REG_NAMED_BITS_VALUE (I2S, NAME, VALUE) +#define I2S_REG_BITS_ENUM(NAME, ENUM) REG_NAMED_BITS_ENUM (I2S, NAME, ENUM) +#define I2S_REG_BITS_ENUM_SEL(NAME, __COND__, TRUE_ENUM, FALSE_ENUM) REG_NAMED_BITS_ENUM_SEL(I2S, NAME, __COND__, TRUE_ENUM, FALSE_ENUM) + +#define DEFINE_I2S_REG(NAME, __OFFSET__, __WIDTH__) REG_DEFINE_NAMED_REG (I2S, NAME, __OFFSET__, __WIDTH__) +#define DEFINE_I2S_REG_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE) REG_DEFINE_NAMED_BIT_ENUM (I2S, NAME, __OFFSET__, ZERO, ONE) +#define DEFINE_I2S_REG_TWO_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE) REG_DEFINE_NAMED_TWO_BIT_ENUM (I2S, NAME, __OFFSET__, ZERO, ONE, TWO, THREE) +#define DEFINE_I2S_REG_THREE_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) REG_DEFINE_NAMED_THREE_BIT_ENUM(I2S, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN) +#define DEFINE_I2S_REG_FOUR_BIT_ENUM(NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) REG_DEFINE_NAMED_FOUR_BIT_ENUM (I2S, NAME, __OFFSET__, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN) + + +DEFINE_I2S_REG_BIT_ENUM(I2S_CG_SLCG_ENABLE, 0, FALSE, TRUE); + +DEFINE_I2S_REG_BIT_ENUM(I2S_CTRL_MASTER, 10, DISABLE, ENABLE); \ No newline at end of file diff --git a/libraries/libvapours/include/vapours/tegra/tegra_pmc.hpp b/libraries/libvapours/include/vapours/tegra/tegra_pmc.hpp index 17a35201b..561d44f13 100644 --- a/libraries/libvapours/include/vapours/tegra/tegra_pmc.hpp +++ b/libraries/libvapours/include/vapours/tegra/tegra_pmc.hpp @@ -58,6 +58,7 @@ #define APBDEV_PMC_AUTO_WAKE2_LVL_MASK (0x170) #define APBDEV_PMC_OSC_EDPD_OVER (0x1A4) #define APBDEV_PMC_CLK_OUT_CNTRL (0x1A8) +#define APBDEV_PMC_RST_STATUS (0x1B4) #define APBDEV_PMC_IO_DPD_REQ (0x1B8) #define APBDEV_PMC_IO_DPD_STATUS (0x1BC) #define APBDEV_PMC_IO_DPD2_REQ (0x1C0) @@ -65,6 +66,7 @@ #define APBDEV_PMC_SEL_DPD_TIM (0x1C8) #define APBDEV_PMC_SCRATCH45 (0x234) #define APBDEV_PMC_SCRATCH46 (0x238) +#define APBDEV_PMC_SCRATCH49 (0x244) #define APBDEV_PMC_TSC_MULT (0x2B4) #define APBDEV_PMC_STICKY_BITS (0x2C0) #define APBDEV_PMC_WEAK_BIAS (0x2C8)